[c-sharp] fix Semgrep pattern parsing for top-level expressions, declarations, and ellipsis positions - #584
Draft
brandonspark wants to merge 1 commit into
Draft
[c-sharp] fix Semgrep pattern parsing for top-level expressions, declarations, and ellipsis positions#584brandonspark wants to merge 1 commit into
brandonspark wants to merge 1 commit into
Conversation
…arations, and ellipsis positions
Extend `lang/semgrep-grammars/src/semgrep-c-sharp/grammar.js` so several
modern C# pattern shapes that previously errored at parse time are now
admitted by the grammar:
- Top-level bare expression alternative on `compilation_unit`: covers
patterns without a trailing `;` like `$X is null`, `$X with { ... }`,
`$X is { $P: $V }`, `from $X in $Y where $C select $E`.
- Top-level bare `property_declaration` alternative: covers patterns
like `public $T $P { get; init; }` that were mis-parsed as a
`local_declaration_statement` followed by a stray block.
- `expression_statement` extended with the C# 7/8/9+ expression shapes
that upstream's `_expression_statement_expression` rejects, so
`$X is $T $Y;`, `$"hello {$X}";`, `($X) => $E;`, `$X?.$Y;`,
`typeof($T);`, `$X[..$Y];`, `$X..$Y;`, and `init $X => $Y;` all parse.
- `switch_expression_arm` accepts `$.ellipsis` so
`$X switch { $P => $E, ... }` parses.
- `type_parameter` accepts `$.ellipsis` so `class $C<...> { }` parses.
The new top-level alternatives are gated with strongly negative
`prec.dynamic` so that ordinary C# code still resolves through the
existing `previous` (i.e. `global_statement` /
`_namespace_member_declaration`) path. Targeted `conflicts` entries
disambiguate where the new alternatives unavoidably overlap with the
upstream rules.
Closes LANG-478, LANG-484. Partially addresses LANG-494 (the augmentation
parts: switch-arm `...` and `<...>` type-parameter ellipsis). The
`I$I` metavariable+identifier concatenation case from LANG-494 is
deferred — it requires scanner-level work (token immediacy /
`token.immediate`) and is labeled `fix:scanner-or-entrypoint` upstream.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
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.
Summary
Augments
lang/semgrep-grammars/src/semgrep-c-sharp/grammar.jsso severalmodern C# pattern shapes that previously errored at parse time are now
admitted by the grammar.
Changes
_expressionalternative oncompilation_unitsopatterns without a trailing
;parse:$X is null,$X with { ... },$X is { $P: $V },from $X in $Y where $C select $E.property_declarationalternative sopublic $T $P { get; init; }parses (instead of being mis-tokenizedas
local_declaration_statement+ stray block).expression_statementextended to accept C# 7/8/9+ expressionshapes that the upstream
_expression_statement_expressionrejects:is_pattern_expression,interpolated_string_expression,lambda_expression,conditional_access_expression,type_of_expression,element_access_expression, andrange_expression.switch_expression_armaccepts$.ellipsisso$X switch { $P => $E, ... }parses.type_parameteraccepts$.ellipsissoclass $C<...> { }parses.The new top-level alternatives are gated with strongly negative
prec.dynamicso ordinary C# code still resolves through the existingpreviouspath. Targetedconflictsentries disambiguate the smallnumber of unavoidable overlaps.
Tickets
switch-arm
...and<...>type-parameter ellipsis are fixed here.The
I$Imetavariable+identifier concatenation case from LANG-494is deferred — it is labeled
fix:scanner-or-entrypointupstream andrequires scanner-level work (
token.immediatefor zero-widthadjacency, or pattern-preprocessing in semgrep-core).
Test plan
make build && make testpasses (188 corpus tests, 15 new).tree-sitter parsespot-checked on every pattern listed in thethree Linear tickets.
semgrep-c-sharpSHA bump insemgrep/semgrep-c-sharp.