Preserve the L suffix on converted long literals - #175
Merged
Conversation
LongLiteralExpressionVisitor stripped the trailing L/l from a Java long literal and emitted the remaining text verbatim, so the generated C# lost the suffix that makes it a long. That produced code which does not compile. C# types a bare numeric literal as int, so `long a = 0xFFFFFFFFFFFFFFFFL` became `long a = 0xFFFFFFFFFFFFFFFF` -- a ulong that will not implicitly convert to long (CS0266). Re-append the suffix when building the literal token, and strip the incoming L/l as a suffix rather than via a blanket Replace over the whole string. A hex literal above long.MaxValue stays invalid in C# even with the suffix, since the literal is typed by its magnitude. For that case emit the wrapped decimal value, which is the number Java means: 0xFFFFFFFFFFFFFFFFL -> -1L. The existing long-literal tests only asserted the parsed numeric Value, which is why this went unnoticed; the new cases assert the emitted token text. LongLiterals.java covers it end to end through the compile-and-run harness. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Problem
LongLiteralExpressionVisitorstripped the trailingL/lfrom a Java long literal and emitted the remaining text verbatim, so the generated C# lost the suffix that makes it a long.That produced code which does not compile. C# types a bare numeric literal as
int, so:converted to:
Fix
Lsuffix when building the literal token.L/las a suffix rather than via a blanketReplaceover the whole string, which was scanning every character of a value we echo back into the generated source.long.MaxValuestays invalid in C# even with the suffix, because the literal is typed by its magnitude. For that case emit the wrapped decimal value, which is the number Java means:0xFFFFFFFFFFFFFFFFL→-1L.Why it went unnoticed
The existing long-literal tests asserted only the parsed numeric
Value, never the emitted token text — so a literal with a correct value but uncompilable text passed. The new cases assertText.Testing
VisitLiteralExpression_Long_PreservesSuffixInTexttheory covering hex, binary, octal, underscore separators, lowercasel, and both overflow boundaries.VisitLiteralExpression_Longcases for the two's-complement and above-int.MaxValuevalues.Resources/LongLiterals.javawired intoFullIntegrationTests, which compiles the generated C# and asserts its runtime output matches Java's.Full suite: 378 passed, 0 failed (was 363).
Note on #128
The binary-literal crash originally reported in #128 (
0b10,0b100) no longer reproduces on master — it was fixed sometime after the 3.0.0 build in that report. Investigating it surfaced this adjacent defect in the long-literal path, which this PR fixes. Worth confirming whether #128 should now be closed.🤖 Generated with Claude Code