Skip to content

fix(csharp) support digit separators in binary literals and numeric type suffixes#4447

Merged
joshgoebel merged 2 commits into
highlightjs:mainfrom
sarathfrancis90:fix-csharp-number-literals
Jul 22, 2026
Merged

fix(csharp) support digit separators in binary literals and numeric type suffixes#4447
joshgoebel merged 2 commits into
highlightjs:mainfrom
sarathfrancis90:fix-csharp-number-literals

Conversation

@sarathfrancis90

Copy link
Copy Markdown
Contributor

Resolves #4258 — the digit-separator work in #4280 covered decimal and hex literals, but a few C# number forms are still highlighted wrong.

Changes

The number mode had kept some C/C++ habits: ' as the digit separator, _ allowed only in the decimal/hex variant, and the u/U/l/L suffixes recognised only after a plain decimal literal. In practice that means:

int bin = 0b1010_1010;      // stops highlighting at the first _
ulong hex = 0xFF_FFUL;      // UL falls out of the literal
ulong dec = 1_000_000UL;    // same
decimal price = 19.99m;     // m/M and d/D suffixes aren't matched at all
int _count = 0;             // the leading _ renders as a number

The last one is the one I noticed first — [\d_]+ can start with an underscore, so _count (the usual private-field convention) gets a stray highlighted _, and point._1 highlights ._1.

I rewrote the three variants to follow the lexical grammar in the spec (integer literals, real literals): separators sit between digits and may also follow the 0x/0b prefix, integer literals take U/L in either order, and real literals take F/D/M.

Tested with a new markup fixture covering the forms above plus the two identifier cases; npm run build && npm test is green (1579 passing), as are npm run lint and npm run lint-languages. The existing csharp/floats fixture is unchanged.

Checklist

  • Added markup tests, or they don't apply here because...
  • Updated the changelog at CHANGES.md

@github-actions

Copy link
Copy Markdown

Build Size Report

Changes to minified artifacts in /build, after gzip compression.

4 files changed

Total change +26 B

View Changes
file base pr diff
es/core.min.js 8.24 KB 8.24 KB +1 B
es/highlight.min.js 8.24 KB 8.24 KB +1 B
es/languages/csharp.min.js 1.7 KB 1.72 KB +12 B
languages/csharp.min.js 1.71 KB 1.73 KB +12 B

double ratio = 3.14d;
decimal big = 1.5e10M;
int _count = 0;
int index = point._1;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is a false positive lets add a comment making that explicit.

@joshgoebel joshgoebel left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One request. Looks great.

@sarathfrancis90

Copy link
Copy Markdown
Contributor Author

Yes — both of those highlighted as numbers before the fix, since the old [\d_]+ alternative matched without requiring a leading digit, so _count and the ._1 member both came out as NUMBER. Added a line above them saying so.

@github-actions

Copy link
Copy Markdown

Build Size Report

Changes to minified artifacts in /build, after gzip compression.

5 files changed

Total change +30 B

View Changes
file base pr diff
es/core.min.js 8.24 KB 8.24 KB +2 B
es/highlight.min.js 8.24 KB 8.24 KB +2 B
es/languages/csharp.min.js 1.7 KB 1.72 KB +12 B
highlight.min.js 8.28 KB 8.28 KB +2 B
languages/csharp.min.js 1.71 KB 1.73 KB +12 B

…ype suffixes

The C# number mode still carried a few C/C++ habits: it used ' as the
digit separator, only allowed _ in decimal and hex literals, and only
recognised the u/U/l/L/f/F suffixes on plain decimal literals.

So 0b1010_1010 highlighted only up to the first _, 0xFFu and 1_000UL
dropped their suffix, and the decimal/double suffixes m/M and d/D were
missing entirely, which leaves 19.99m half-highlighted.

Allowing [\d_]+ to start with an underscore also made _count (the usual
private-field convention) render its leading _ as a number.

Rewrote the three variants against the lexical grammar: separators sit
between digits and may follow the 0x/0b prefix, integer literals take
the U/L suffixes in either order, and real literals take F/D/M as well.
@sarathfrancis90
sarathfrancis90 force-pushed the fix-csharp-number-literals branch from 7e26a03 to 4c9852b Compare July 22, 2026 02:24
@github-actions

Copy link
Copy Markdown

Build Size Report

Changes to minified artifacts in /build, after gzip compression.

4 files changed

Total change +22 B

View Changes
file base pr diff
es/core.min.js 8.24 KB 8.24 KB -1 B
es/highlight.min.js 8.24 KB 8.24 KB -1 B
es/languages/csharp.min.js 1.7 KB 1.72 KB +12 B
languages/csharp.min.js 1.71 KB 1.73 KB +12 B

@joshgoebel
joshgoebel merged commit 29dc139 into highlightjs:main Jul 22, 2026
19 checks passed
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.

(C#) Support digit separators

2 participants