Skip to content

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

Open
matt-edmondson wants to merge 2 commits into
mainfrom
claude/issue-158-directive-in-expression-body
Open

matt-edmondson wants to merge 2 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
@sonarqubecloud

sonarqubecloud Bot commented Nov 2, 2026

Copy link
Copy Markdown

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