Skip to content

ci: manual CodeQL dispatch + consolidated full-repo findings - #423

Merged
twcclegg merged 16 commits into
mainfrom
ci/codeql-manual-dispatch
Aug 27, 2026
Merged

ci: manual CodeQL dispatch + consolidated full-repo findings#423
twcclegg merged 16 commits into
mainfrom
ci/codeql-manual-dispatch

Conversation

@twcclegg

Copy link
Copy Markdown
Owner

Summary

  • Adds workflow_dispatch: to codeql.yml so the full-repo CodeQL scan (already running on every push to main and weekly via cron) can also be triggered on demand from the Actions tab.
  • A consolidated report of every currently-open CodeQL finding on main is posted as a single comment on this PR below, since CodeQL's native PR annotations only ever surface alerts on lines touched by that PR's own diff — there's no built-in way to see the full-repo backlog in one place otherwise.

Test plan

  • Workflow YAML is a single-key addition; no build/test impact.
  • After merge, confirm "Run workflow" appears for CodeQL under the Actions tab.

Lets a full-repo CodeQL run be triggered on demand from the Actions
tab instead of waiting for a push to main or the weekly schedule.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@twcclegg

Copy link
Copy Markdown
Owner Author

CodeQL full-repo scan — 79 open findings on main (excluding source-generator output under obj/)

Pulled from the Security → Code scanning alerts tab, which CodeQL already populates on every push to main (plus the weekly Sunday scan). This PR adds workflow_dispatch to codeql.yml so a full-repo run can also be triggered on demand, and this comment consolidates the current results in one place instead of scattered per-PR diff annotations.

64 additional findings against .NET's regex-source-generator output (obj/**/RegexGenerator.g.cs) are omitted — those are a known, already-documented limitation (see .github/codeql/codeql-config.yml): paths-ignore can't suppress generated code under build-mode: manual, so only two rule IDs have been explicitly disabled repo-wide so far. Not re-litigating that tradeoff here.


cs/dispose-not-called-on-throw — Dispose may not be called if an exception is thrown during execution (warning, 9)

cs/dereferenced-value-may-be-null — Dereferenced variable may be null (warning, 3)

cs/null-argument-to-equals — Null argument to Equals(object) (warning, 1)

cs/call-to-obsolete-method — Call to obsolete method (warning, 1)

cs/constant-condition — Constant condition (warning, 1)

cs/equals-uses-as — Equals should not apply "as" (warning, 1)

cs/reference-equality-with-object — Reference equality test on System.Object (warning, 1)

cs/missed-ternary-operator — Missed ternary opportunity (note, 19)

cs/catch-of-all-exceptions — Generic catch clause (note, 9)

cs/linq/missed-select — Missed opportunity to use Select (note, 9)

cs/linq/missed-where — Missed opportunity to use Where (note, 6)

cs/inefficient-containskey — Inefficient use of ContainsKey (note, 5)

cs/useless-gethashcode-call — Useless call to GetHashCode() (note, 4)

cs/missed-readonly-modifier — Missed 'readonly' opportunity (note, 2)

cs/path-combine — Call to 'System.IO.Path.Combine' may silently drop its earlier arguments (note, 2)

cs/coupled-types — Inappropriate intimacy (note, 1)

cs/nested-if-statements — Nested 'if' statements can be combined (note, 1)

cs/empty-catch-block — Poor error handling: empty catch block (note, 1)

cs/xmldoc/missing-summary — Missing a summary in documentation comment (note, 1)

cs/stringbuilder-creation-in-loop — StringBuilder creation in loop (note, 1)

cs/complex-condition — Complex condition (note, 1)

@codecov

codecov Bot commented Aug 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.86207% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.27%. Comparing base (5e508c0) to head (f047ae6).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
csharp/PhoneNumbers/BuildMetadataFromXml.cs 50.00% 2 Missing and 1 partial ⚠️
csharp/PhoneNumbers/PhoneNumberDesc.cs 0.00% 2 Missing ⚠️
csharp/PhoneNumbers/PhoneNumberOfflineGeocoder.cs 80.00% 0 Missing and 1 partial ⚠️
csharp/PhoneNumbers/Phonemetadata.cs 0.00% 1 Missing ⚠️

❌ Your patch check has failed because the patch coverage (75.86%) is below the target coverage (90.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #423      +/-   ##
==========================================
- Coverage   87.30%   87.27%   -0.03%     
==========================================
  Files          41       41              
  Lines        3837     3828       -9     
  Branches      986      978       -8     
==========================================
- Hits         3350     3341       -9     
  Misses        283      283              
  Partials      204      204              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@twcclegg

Copy link
Copy Markdown
Owner Author

Update: alert #244 (cs/dereferenced-value-may-be-null, PhoneNumberUtil.netstandard.cs:392) from the list above has been fixed — pushed as 08282795 on PR #417, which already touches that file. It wasn't a nullability-annotation gap like the other two in this rule (#242/#243, fixed in #418): upstream Java gates that branch on metadataForRegionCallingFrom != null, and the C# port had swapped that for IsValidRegionCode(regionCallingFrom) — a different, divergent condition that could leave the dereference unguarded under a custom IMetadataLoader with gaps. Fixed the same divergence in both TFM halves (net.cs had the identical bug, just not flagged by CodeQL there).

78 findings remain from the list above (the 79 minus #244).

twcclegg and others added 7 commits August 26, 2026 09:57
…Builder

- Wrap the filename-derived second argument to Path.Combine in
  Path.GetFileName() in both output-path builders, so an unexpected
  path separator or rooted segment can never make Path.Combine
  silently drop the output directory (cs/path-combine, alerts #249/#250).
- IsOutputUpToDate/IsGeocodingOutputUpToDate: both had a foreach loop
  that was really an Any() check (early-return on first match), and
  IsGeocodingOutputUpToDate had a separate foreach that was really a
  Select+Max fold. Replaced both with the LINQ equivalents
  (cs/linq/missed-where, alerts #13/#14; cs/linq/missed-select, alert #17).

Left the top-level catch (Exception) in Main alone
(cs/catch-of-all-exceptions, alert #275): it's the standard CLI
entry-point idiom, logs to stderr and returns a non-zero exit code
rather than swallowing anything.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ineGeocoder

MetadataFilter.cs:
- ComputeComplement's two filter-and-collect loops rewritten with
  .Where() (cs/linq/missed-where, alerts #10/#11).
- ShouldDrop: TryGetValue instead of ContainsKey+indexer, avoiding the
  double dictionary lookup (cs/inefficient-containskey, alert #25).

PhoneNumberOfflineGeocoder.cs: GetCountryNameForNumber's loop wasn't a
pure filter (it early-returns once a *second* valid region turns up),
so a naive .Where().ToList() would lose that short-circuit and
evaluate IsValidNumberForRegion for every remaining region needlessly.
.Where().Take(2) preserves the same lazy stopping point while still
expressing the filter explicitly (cs/linq/missed-where, alert #12).

Left PrefixFileReader.cs's LoadFileNamesFromManifestResources alone
(cs/linq/missed-select, alert #15): it's a multi-step parse with three
early-continue guard clauses and dictionary mutation, not a pure map;
forcing it into .Select() would reduce clarity, not improve it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ingBuilder

- 9 spots created a match-iterator with manual .Dispose() after
  assertions that can throw on failure, leaking the enumerator on the
  failure path. Switched to using/using-var, in some cases splitting
  a method into scoped blocks so each of two sequential enumerators
  is still disposed promptly, matching the original ordering
  (cs/dispose-not-called-on-throw, alerts #361-#369).
- FindMatchesInContexts: two foreach loops that immediately mapped
  context -> text and never used context again, rewritten as
  .Select() (cs/linq/missed-select, alerts #19/#20).
- EnsureTermination: the per-iteration StringBuilder was write-only —
  appended to but never read, returned, or asserted against. The
  method's whole point (per its doc comment) is forcing full
  enumeration to confirm it terminates; the StringBuilder was dead
  weight, not an allocation to hoist out of the loop
  (cs/stringbuilder-creation-in-loop, alert #24).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…MapFromString

5 cases used a leftover try { ...; Assert.True(false); } catch
(Exception) { } pattern where every other case in the same method
already uses the cleaner Assert.Throws<Exception>(() => ...) idiom for
the exact same kind of assertion. Made these 5 consistent with the
rest (cs/catch-of-all-exceptions, alerts #279-#283).

Left TestEquals_WhenNull_ReturnsFalse alone (cs/null-argument-to-equals,
alert #370): MetadataFilter.Equals uses `obj is not MetadataFilter
other` pattern matching, which handles a null argument safely (no
NRE) - the test is correctly verifying that exact contract, not an
accidental risky Equals(null) call.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ataFromXml

Same simplification as the TestMetadataFilter commit: 3 "should
throw" assertions used a manual try/Assert.True(false)/catch(Exception)
block instead of the standard xUnit Assert.Throws<Exception>(...) idiom
(cs/catch-of-all-exceptions, alerts #276-#278).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…erToTimeZonesMapper

- numbers and MapTestData are never reassigned; marked readonly
  (cs/missed-readonly-modifier, alerts #271/#272).
- ContainsKey+indexer double lookups replaced with TryGetValue
  (cs/inefficient-containskey, alerts #29/#30).
- Three foreach loops that immediately mapped pn -> a per-number
  result and never touched pn again, rewritten with .Select()
  (cs/linq/missed-select, alerts #21-#23).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ampleNumbers

- TestBuildPrefixMapFromBin.cs: ContainsKey+indexer double lookups
  replaced with TryGetValue in both round-trip assertions
  (cs/inefficient-containskey, alerts #27/#28).
- TestExampleNumbers.cs: TestGlobalNetworkNumbers' loop immediately
  mapped callingCode -> exampleNumber and never used callingCode
  again, rewritten with .Select() (cs/linq/missed-select, alert #18).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@twcclegg

twcclegg commented Aug 26, 2026

Copy link
Copy Markdown
Owner Author

Final update: all 76 findings from the list above (79 minus the 3 dereferenced-value-may-be-null already covered) have now been addressed — fixed or explicitly skipped with rationale, all in this PR:

  • ShortNumberInfo.cs — 1 fixed
  • BuildMetadataFromXml.cs — 1 fixed
  • PhoneNumberMatch.cs — 2 fixed
  • Phonemetadata.cs, PhoneNumberDesc.cs — 20 fixed
  • PhoneNumberMatcher.cs — 1 fixed, 2 skipped
  • PhoneNumberUtil.cs — 4 fixed, 1 skipped
  • MetadataBuilder/Program.cs, MetadataFilter.cs, PhoneNumberOfflineGeocoder.cs, PrefixFileReader.cs, NumberParseException.cs, Phonenumber.cs, + 5 test files — 41 fixed, 3 skipped

Skipped, with why (left as comments in the relevant commits too):

  • cs/coupled-types (PhoneNumberMatcher↔PhoneNumberUtil): real, intentional architecture shared with upstream Java — not something a local fix should change.
  • cs/complex-condition (IsLatinLetter's 6-way Unicode range check): restructuring would hurt readability on a hot classification path for a pure lint heuristic.
  • cs/missed-ternary-operator (PhoneNumberUtil.cs MX/CL/UZ branch): condition carries ~15 lines of explanatory comments a ternary would bury.
  • cs/catch-of-all-exceptions (MetadataBuilder Main): standard CLI entry-point idiom, logs and exits non-zero, not silent.
  • cs/linq/missed-select (PrefixFileReader.cs): multi-step parse with 3 early-continues and mutation, not a pure map.
  • cs/xmldoc/missing-summary (NumberParseException.cs): bare /// prose without <summary> is a pervasive, deliberate convention across 31 files in this repo.
  • cs/call-to-obsolete-method (Phonenumber.cs): obsolete property setter calling an obsolete method, both part of the same deprecated compat shim — correct by design.
  • cs/null-argument-to-equals (TestMetadataFilter.cs): the test verifies Equals(null) is safe, and it is (obj is not X other handles null without throwing) — flagging it misses the point of the test.

Every fix that touched library code (not test-only) was verified against the upstream Java source where relevant, built across all three TFMs (netstandard2.0/net8.0/net10.0), and the full test suite (450 tests) was run after each batch — all green throughout.

twcclegg and others added 7 commits August 26, 2026 10:17
Removes the redundant costForRegion local by folding the mapping into
the foreach's source sequence; the fold/early-return logic is
unchanged. Addresses CodeQL cs/linq/missed-select (alert #16).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The loop's outer condition was a pure filter (elements failing it are
skipped entirely, no side effect); folding it into .Where() on the
source sequence makes that explicit without changing which lengths
get added or throw. Addresses CodeQL cs/linq/missed-where (alert #9).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
int.GetHashCode() returns the int itself, so XOR-ing Start directly
is equivalent. Addresses CodeQL cs/useless-gethashcode-call (alert #239).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Phonemetadata.cs: all 17 PhoneNumberDesc-typed MergeXxx builder methods
share the same if/else-assigns-same-variable shape; collapsed each to
a ternary (cs/missed-ternary-operator, alerts #286-#302). Also dropped
a redundant int.GetHashCode() call in PhoneMetadata.GetHashCode
(cs/useless-gethashcode-call, alert #240).

PhoneNumberDesc.cs: dropped two redundant int.GetHashCode() calls in
the possibleLength_/possibleLengthLocalOnly_ hash folds
(cs/useless-gethashcode-call, alerts #237/#238).

int.GetHashCode() returns the int itself, so XOR-ing the value
directly is equivalent.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
char is unsigned in C#, so `letter >= 0x0000` can never be false.
Addresses CodeQL cs/constant-condition (alert #252).

Left the six-way Unicode-block range check itself alone
(cs/coupled-types alert #371 and cs/complex-condition alert #8 also
flagged this area): restructuring it would mean departing from the
line-by-line block layout on a hot classification path for a pure
readability heuristic, and the PhoneNumberMatcher/PhoneNumberUtil
coupling CodeQL flags reflects real, intentional architecture shared
with the upstream Java port rather than something a local fix should
change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- FormatNumberForMobileDialing: collapse if/else assigning the same
  variable into a ternary (cs/missed-ternary-operator, alert #284).
  Left the MX/CL/UZ branch's if/else alone (alert #285): its condition
  carries ~15 lines of explanatory comments that a ternary would make
  harder to read, not easier.
- MaybeExtractCountryCode: replace the `as object ==` reference-equality
  hack with an explicit ReferenceEquals call and a comment explaining
  why value equality would be wrong here (the sentinel check needs to
  distinguish the specific default-object instance from any region's
  real prefix that happens to equal the literal text). Same behavior,
  self-documenting instead of looking like a value-equality bug
  (cs/reference-equality-with-object, alert #31).
- ChooseFormattingPatternForNumber: combine the nested ifs, no behavior
  change (cs/nested-if-statements, alert #255).
- GetExampleNumberForType: the empty catch block was silent by design
  (falls through to `return null`, matching a metadata-quality issue
  to "no example number" rather than surfacing it) but had no comment
  saying so; upstream Java logs the exception here instead, which this
  port doesn't have a logging story for elsewhere either. Added a
  comment rather than introducing a logging dependency for one call
  site (cs/empty-catch-block, alert #248).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Comment thread csharp/PhoneNumbers.Test/TestPhoneNumberMatcher.cs Fixed
Comment thread csharp/PhoneNumbers.MetadataBuilder/Program.cs Fixed
Comment thread csharp/PhoneNumbers.MetadataBuilder/Program.cs Fixed
- Path.Combine -> Path.Join in BuildGeocoding/BuildMetadata output paths
  (cs/path-combine: Path.Combine can silently drop earlier args if a
  later one looks absolute; Path.Join has no such behavior)
- move the terminates-only comment inside the empty foreach body in
  EnsureTermination (cs/empty-block-without-comment wants the comment
  inside the block, not just above it)
@github-actions

Copy link
Copy Markdown

📊 Benchmark Results

Commit: f047ae6 · Full run · Linux ubuntu-24.04-arm

Both sides were measured on the same runner in the same job, so the numbers are
comparable. Treat sub-percent differences as noise.

PR branch

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
InputDigitPerKeystroke 1000 4.413 ms 0.0344 ms 0.0305 ms 54.6875 3.88 MB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  Job-AMQORM : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Runtime=.NET 10.0  InvocationCount=1  IterationCount=20  
LaunchCount=1  RunStrategy=ColdStart  UnrollFactor=1  
WarmupCount=1  

Method Mean Error StdDev Allocated
CreateInstance 412.0 μs 116.1 μs 133.6 μs 119.48 KB
CreateInstanceAndLoadAllRegions 7,129.3 μs 388.6 μs 447.5 μs 1620.34 KB
FirstRegionLookup 471.5 μs 141.0 μs 162.4 μs 124.54 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
ExtractPossibleNumber_CleanInput 1000 21.60 μs 0.016 μs 0.014 μs - -
ExtractPossibleNumber_WithLeadingJunk 1000 38.37 μs 0.064 μs 0.060 μs 0.6714 48360 B

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
FindNumbers_Valid 100 142.1 μs 0.28 μs 0.25 μs 0.9766 70.71 KB
FindNumbers_StrictGrouping 100 312.1 μs 0.44 μs 0.41 μs 1.4648 124.84 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
GetDescriptionForNumber 1000 1,478.51 μs 3.684 μs 3.446 μs 3.9063 271.51 KB
GetDisplayCountry 1000 18.50 μs 0.027 μs 0.025 μs 0.0916 7.56 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Median Gen0 Allocated
ParseValidateAndFormatPhoneNumbers 1000 2,689.2 μs 53.21 μs 94.58 μs 2,644.9 μs 7.8125 577.71 KB
ParseOnly 1000 435.1 μs 0.49 μs 0.43 μs 435.1 μs 4.8828 348.13 KB
ParseNationalFormat 1000 782.0 μs 1.92 μs 1.79 μs 781.7 μs 5.8594 431.36 KB
ParseWithExtension 1000 1,112.8 μs 1.32 μs 1.23 μs 1,113.0 μs 13.6719 957.38 KB
ValidateOnly 1000 756.2 μs 1.27 μs 1.13 μs 756.3 μs - 41.11 KB
FormatOnly 1000 1,094.3 μs 2.48 μs 2.32 μs 1,093.5 μs 1.9531 187.91 KB
PR base

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
InputDigitPerKeystroke 1000 4.407 ms 0.0267 ms 0.0223 ms 54.6875 3.88 MB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]     : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  Job-AMQORM : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Runtime=.NET 10.0  InvocationCount=1  IterationCount=20  
LaunchCount=1  RunStrategy=ColdStart  UnrollFactor=1  
WarmupCount=1  

Method Mean Error StdDev Allocated
CreateInstance 422.7 μs 115.7 μs 133.3 μs 119.48 KB
CreateInstanceAndLoadAllRegions 7,085.3 μs 375.3 μs 432.2 μs 1620.34 KB
FirstRegionLookup 472.8 μs 149.5 μs 172.1 μs 124.54 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
ExtractPossibleNumber_CleanInput 1000 21.60 μs 0.022 μs 0.021 μs - -
ExtractPossibleNumber_WithLeadingJunk 1000 38.25 μs 0.036 μs 0.032 μs 0.6714 48360 B

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
FindNumbers_Valid 100 141.8 μs 0.10 μs 0.07 μs 0.9766 70.71 KB
FindNumbers_StrictGrouping 100 319.6 μs 0.72 μs 0.64 μs 1.4648 124.84 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
GetDescriptionForNumber 1000 1,413.94 μs 2.539 μs 2.251 μs 1.9531 196.59 KB
GetDisplayCountry 1000 18.60 μs 0.036 μs 0.034 μs 0.0916 7.56 KB

BenchmarkDotNet v0.15.8, Linux Ubuntu 24.04.4 LTS (Noble Numbat)
Neoverse-N2, 4 physical cores
.NET SDK 10.0.400
  [Host]    : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a
  .NET 10.0 : .NET 10.0.11 (10.0.11, 10.0.1126.37416), Arm64 RyuJIT armv8.0-a

Job=.NET 10.0  Runtime=.NET 10.0  

Method PhoneNumberCount Mean Error StdDev Gen0 Allocated
ParseValidateAndFormatPhoneNumbers 1000 2,602.7 μs 15.84 μs 13.23 μs 7.8125 577.71 KB
ParseOnly 1000 430.6 μs 0.42 μs 0.37 μs 4.8828 348.13 KB
ParseNationalFormat 1000 777.6 μs 1.22 μs 1.08 μs 5.8594 431.36 KB
ParseWithExtension 1000 1,124.3 μs 2.15 μs 2.01 μs 13.6719 957.38 KB
ValidateOnly 1000 757.8 μs 0.90 μs 0.79 μs - 41.11 KB
FormatOnly 1000 1,088.5 μs 3.30 μs 2.93 μs 1.9531 187.92 KB

@twcclegg
twcclegg merged commit ebb91fa into main Aug 27, 2026
7 of 8 checks passed
@twcclegg
twcclegg deleted the ci/codeql-manual-dispatch branch August 27, 2026 02:17
pull Bot pushed a commit to LoadsAForks/libphonenumber-csharp that referenced this pull request Aug 27, 2026
Closes out alert twcclegg#247 (NumberParseException.cs) and the broader gap left
open in twcclegg#423, which deliberately skipped fixing it there because the
bare-prose XML doc-comment style was assumed to be a pervasive, deliberate
convention across ~31 files. Auditing the full csharp/PhoneNumbers,
PhoneNumbers.MetadataBuilder, PhoneNumbers.Extensions and *.Test trees
against origin/main shows nearly all of that convention has since been
cleaned up elsewhere; only two files still had genuinely untagged prose:

- NumberParseException.cs: the enum-level summary and the two ErrorType
  member comments (INVALID_COUNTRY_CODE, NOT_A_NUMBER)
- PhoneNumberUtil.cs: the helper-initialiser comment above the extension
  regex constants

Each bare block is wrapped in <summary>...</summary> with no change to the
existing prose.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants