Skip to main content

changing-public-api

Add, change or remove public API in the libphonenumber-csharp or libphonenumber-csharp.extensions packages. Use when introducing a public type or member, changing a signature, deciding which of the two packages new API belongs in, or when a build fails on package validation (PKV/CP diagnostics), TFM parity, trim/AOT analysis, or a missing netstandard2.0 fallback.

설치로 이동

소스 정보

저장소
twcclegg/libphonenumber-csharp
최근 소스 활동
2026년 9월 17일 01:20
감지된 SKILL.md 언어
영어
스타
920
포크
157

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
changing-public-api
description
Add, change or remove public API in the libphonenumber-csharp or libphonenumber-csharp.extensions packages. Use when introducing a public type or member, changing a signature, deciding which of the two packages new API belongs in, or when a build fails on package validation (PKV/CP diagnostics), TFM parity, trim/AOT analysis, or a missing netstandard2.0 fallback.
# Changing the public surface Both packable projects have `EnablePackageValidation` on, so the build itself is the gate: an API that is inconsistent across target frameworks, or a breaking change against the published baseline, fails the build rather than shipping. ## First: is a new member authorised? **Adding a public member to `csharp/PhoneNumbers/` needs explicit sign-off from the user, as its own decision.** Package validation only catches breaks against the published baseline — never additions, so nothing automated will object. "It matches an existing pattern" is not permission — `IMetadataLoader`/`SetMetadataLoader` and `PrewarmRegionsAsync` were added on exactly that reasoning and both were regretted. Ask, every time. `PhoneNumbers.Extensions` is exempt and exists to grow. This is the same rule `AGENTS.md` states; keep the two copies identical. A task like "fix this perf issue" does not authorise a new public member as a side effect. If the answer is no, an `internal` member or a helper in `PhoneNumbers.Extensions` usually serves. ## Which package? - **`csharp/PhoneNumbers/`** (`libphonenumber-csharp`) — anything with a counterpart in the Java library. Keep the Java name and shape; see the `porting-upstream-changes` skill. - **`csharp/PhoneNumbers.Extensions/`** (`libphonenumber-csharp.extensions`) — C#-idiomatic helpers with *no* Java counterpart: the `TryParse`-style `PhoneNumber` static class, the `System.Text.Json` converter and source-generated context, `PhoneNumberAttribute`, `PhoneNumberTypeConverter`. Putting these in the core package makes every future upstream sync a diff to reconcile, so new non-ported conveniences belong here. ## The constraints Both projects target `netstandard2.0;net8.0;net10.0`. - **TFM parity is mandatory.** A member that exists on `net10.0` but not `netstandard2.0` fails package validation. If the implementation needs a modern BCL API, ship the same signature on every target with a fallback implementation — for `PhoneNumberUtil` that means the modern half in `PhoneNumberUtil.net.cs` and the netstandard2.0 half in `PhoneNumberUtil.netstandard.cs`. - **Trim and AOT.** `IsAotCompatible` is set on the modern TFMs and warnings are errors, so no reflection or dynamic code may be reachable from anything public. The JSON support in Extensions goes through a source-generated `JsonSerializerContext` for this reason. - **Nullable reference types** are enabled on every target but `netstandard2.0`. Annotate regardless — an unannotated new API is inconsistent with everything around it. - **Breaking changes.** Each pack is compared against `PackageValidationBaselineVersion` in the csproj (a real nuget.org release — restore downloads it). If a break is genuinely intended, that is a maintainer decision about the next version — raise it rather than suppressing the diagnostic or bumping the baseline to hide it. Moving the baseline forward *after* a release ships is a separate, routine chore: bump both csprojs together to the released version. - **Extensions is analysed more strictly** — `AnalysisMode=AllEnabledByDefault` there versus the default rule set in the core library, so code that builds in `PhoneNumbers/` may not in `PhoneNumbers.Extensions/`. - **XML docs.** `CS1591` (missing doc comment) is suppressed repo-wide, so nothing forces you to document a new member. Document it anyway; it is the only reference consumers get. ## Verify ```bash dotnet build csharp --no-restore # catches TFM parity, trim/AOT, validation dotnet test csharp/PhoneNumbers.slnx -p:TargetFrameworks=net10.0 dotnet pack -c Release csharp/PhoneNumbers # publish_nuget.yml adds -p:VersionPrefix=<tag minus "v"> dotnet pack -c Release csharp/PhoneNumbers.Extensions ``` `dotnet build` matters more than `dotnet test` here: the tests only run on `net8.0`/`net10.0`, so a netstandard2.0 gap is invisible to them and shows up only in the build. ## Test the new API Public entry points get hostile input from real callers. Beyond the normal ported tests, add the new surface to `csharp/PhoneNumbers.Test/TestPublicApiRobustness.cs` (curated hostile strings) and, where an invariant is worth asserting, `TestPhoneNumberProperties.cs` (FsCheck). Both run against the real shipped metadata, and that pair has already caught an unbounded `stackalloc` and a `KeyNotFoundException` that the well-formed-input suite missed. The `writing-tests` skill has the detail.
GitHub에서 보기