fix: stop the obsolete leading-zero setter calling an obsolete method - #460
Merged
Conversation
Resolves the cs/call-to-obsolete-method CodeQL alerts. The query excludes a call whose *enclosing callable* is itself marked [Obsolete], but attributes on a property do not reach its accessors, so the back-compat shim below was flagged even though it is deprecated code calling deprecated code. PhoneNumber.Builder.ItalianLeadingZero's setter now writes through SetNumberOfLeadingZeros(value ? 1 : 0) instead of SetItalianLeadingZero(value). SetItalianLeadingZero's entire body is that same write plus `return this` (discarded here), and its own [Obsolete] message names SetNumberOfLeadingZeros as the replacement, so this is the documented migration and the observable behaviour is unchanged. The property, its [Obsolete] marker and the public signature all stay exactly as they were; line 170 was SetItalianLeadingZero's only caller. The three MetadataManager.SetMetadataLoader calls in TestMedataManager are deliberately left alone. That member's [Obsolete] message names no replacement - it is slated to become internal rather than to be superseded - so there is nothing to migrate to, and the two tests exist specifically to cover that entry point. They keep their narrowly scoped CS0618 pragma; the comment above it now records why the CodeQL alerts on those lines should be dismissed rather than "fixed" by rewriting the tests away from the API under test.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #460 +/- ##
==========================================
+ Coverage 87.51% 87.59% +0.07%
==========================================
Files 43 43
Lines 3886 3885 -1
Branches 991 991
==========================================
+ Hits 3401 3403 +2
+ Misses 280 278 -2
+ Partials 205 204 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
The existing coverage near this code (TestNonEqualWithItalianLeadingZeroSetToTrue) calls SetNumberOfLeadingZeros directly, so nothing in the suite actually invokes the obsolete ItalianLeadingZero property setter this PR just changed to stop calling SetItalianLeadingZero. Add a test that goes through the property itself.
twcclegg
force-pushed
the
fix/codeql-obsolete-api-calls
branch
from
September 5, 2026 19:38
a14a0d9 to
5f28309
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The four
cs/call-to-obsolete-methodalerts. One is a real deprecated-calls-deprecated chain and is fixed; three are tests that deliberately cover a deprecated API and should be dismissed rather than rewritten.What actually triggers this query
Reading the query itself (
csharp/ql/src/API Abuse/CallToObsoleteMethod.ql) rather than guessing at it decided every call site:Three consequences:
#pragma warning disable CS0618does nothing here. All four sites were already inside a pragma with an explanatory comment. CodeQL reads the AST, not pragmas — which is why these alerts persist despite a 0-warning build.MethodCallcounts. Constructor calls and property accesses are invisible to it, which is why the repo's other CS0618-suppressed obsolete usages (new EmbeddedResourceMetadataLoader(), thePhoneRegexctor,MessageBeingBuilt.ItalianLeadingZero) are not flagged. Exactly four obsolete method calls exist; exactly four alerts.[Obsolete]on a property does not reach its accessors — which is precisely whyPhonenumber.cs:170was flagged. It is deprecated code calling deprecated code, butgetEnclosingCallable()returns the setter accessor, whose own attribute set is empty.Fixed:
Phonenumber.cs:170SetItalianLeadingZero's own[Obsolete]namesSetNumberOfLeadingZerosas the replacement, and its entire body isMessageBeingBuilt.NumberOfLeadingZeros = value ? 1 : 0; return this;. The setter discarded that return value, so calling the replacement directly is byte-identical. Line 170 was the method's only caller in the repo. The property, its[Obsolete]marker and the public signature are unchanged.Added
TestItalianLeadingZeroSetterWritesNumberOfLeadingZeros, which goes through theItalianLeadingZeroproperty setter itself rather thanSetNumberOfLeadingZerosdirectly. Nothing in the existing suite exercised that exact line —TestNonEqualWithItalianLeadingZeroSetToTrue, the test whose name suggests it does, callsSetNumberOfLeadingZerosdirectly on both sides — so the fixed line previously shipped with no regression coverage of its own.Recommend dismissing: the three
TestMedataManager.cssites (68, 81, 88)MetadataManager.SetMetadataLoader's[Obsolete]message is "Not intended for external use and will become internal in a future release." It names no replacement — the member is slated to become internal, not superseded — so there is nothing to migrate to, andSetMetadataLoader_RoutesLookupsThroughCustomLoader/SetMetadataLoader_RejectsNullexist precisely to cover that entry point. The comment above the pragma now says so explicitly.Two ways to make the alerts disappear were considered and rejected:
[Obsolete]to satisfy the query's exclusion — analyzer-gaming, and it wouldn't even work: line 88's call sits inside a lambda (Assert.Throws<...>(() => ...)), sogetEnclosingCallable()returns the lambda, which can carry no attribute.internalalias for the tests to call — adds API surface and destroys the coverage the tests exist for.Suggested dismissal reason: won't fix — test deliberately covers a deprecated API that has no replacement.
Verification
dotnet build csharp/PhoneNumbers.slnx -p:TargetFrameworks=net10.0— 0 warnings, 0 errors.dotnet test csharp/PhoneNumbers.slnx -p:TargetFrameworks=net10.0— 491 passed, 0 failed, 0 skipped.No
[Obsolete]markers removed, no public API changes.Note for reviewers: the new test was added in a sandbox with no .NET SDK and no network access to install one, so it could not be built/run locally to confirm it compiles and passes — checked by hand against the existing test file's own conventions (same
#pragma warning disable CS0618pattern used elsewhere in this repo). CI on this PR is the actual gate for that one commit.