Skip to content

Keep a preprocessor directive in an expression body off the arrow line and out of the semicolon [patch] - #162

Merged
matt-edmondson merged 5 commits into
mainfrom
claude/issue-158-directive-in-expression-body
Nov 4, 2026
Merged

matt-edmondson merged 5 commits into
mainfrom
claude/issue-158-directive-in-expression-body

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #158

What changed

TemplateRendering.WriteExpressionBody, which PropertyTemplate.ExpressionBodyFactory and AccessorKind.Expression share, now handles preprocessor directives:

  • A directive that opens the expression is no longer written on the declaration line. The line ends at => and the directive starts the next line, which avoids CS1040.
  • A directive after the last line of code moves the semicolon. The last line of code may sit in one branch of an #if, so terminating it would leave the other branches unterminated. When any directive follows that line, the ; goes on a line of its own after the last directive, where every branch reaches it. This avoids #endif; (CS1025) and leaves no branch without a terminator.
  • When code follows the last directive, that code is terminated as before. Comment-only lines are still skipped, as An expression body whose last line ends in a // comment gets its semicolon inside the comment: public int P => x // note; does not compile (CS1002) #144 introduced.

The repro now renders:

int P =>
#if DEBUG
1
#else
2
#endif
;

The issue's example form, with the ; inside each branch, was one option it offered. A trailing ; after the directives is correct whether the branches are complete expressions or fragments of one, such as 1 #if DEBUG + 2 #endif. Terminating inside each branch would break that second case.

Tests


Generated by Claude Code

…e and out of the semicolon [patch]

WriteExpressionBody wrote the first content line straight after " => ",
even a directive (CS1040), and appended the semicolon to the last line
with code, which could be #endif (CS1025). A body that opens with a
directive now starts on the line after the arrow, and when a directive
follows the last line of code the semicolon goes on its own line after
it, so every #if branch reaches it. Covers PropertyTemplate
ExpressionBodyFactory and AccessorKind.Expression.

Fixes #158

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW3C2EQ5hMiLw63t4Aa
SonarCloud S3776 flagged the method's cognitive complexity (19 > 15)
after the directive handling. The choice of which line takes the
semicolon moves to FindTerminatedLine, and the code/directive checks
become private helpers; behaviour is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW3C2EQ5hMiLw63t4Aa
Keeps both sides' TemplateRendering helpers; HasCode (from #161) now
reuses IsCode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW3C2EQ5hMiLw63t4Aa

Copy link
Copy Markdown
Contributor Author

I merged main into this branch to resolve the conflict with #161, which also added helpers to TemplateRendering.cs. Both sides' helpers are kept, and HasCode now reuses IsCode.

This PR's CI will show 6 failures that aren't caused by this PR. They are the six ScopesTests.PragmaScopeRejectsWarningsThatSpanLinesBeforeWriting data rows, and they fail on main too, at 08f896f.

Every other test passes on the merged branch: 285 of 291.


Generated by Claude Code

…ill refused

PragmaScope.JoinWarnings trimmed every entry (#167), which stripped the
terminator PragmaScopeRejectsWarningsThatSpanLinesBeforeWriting (#155)
relies on, so main failed that test on every platform.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW5jpiuVuBRXSgitSY1
@sonarqubecloud

sonarqubecloud Bot commented Nov 4, 2026

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit e23c31e into main Nov 4, 2026
15 checks passed
@matt-edmondson
matt-edmondson deleted the claude/issue-158-directive-in-expression-body branch November 4, 2026 03:26
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.

An expression body containing #if/#else/#endif renders int P => #if DEBUG and #endif;, which doesn't compile

2 participants