Deferred ideas for this rule, moved out of .claude/rules/diagnostics/fc0007-statement-blocks-separated-by-blank-line.md so the rule doc describes current state only. None of these is scheduled; names and defaults may change when an item is picked up.
Planned settings — none of these are implemented yet, and none has a scheduled milestone. Names, defaults, and value sets may change when a roadmap item is picked up. Track work here.
CaseBranchMode (planned, not implemented)
A future StatementBlockSpacing.CaseBranchMode setting to control blank-line separation between the individual branches of a case statement, orthogonal to ControlFlowBefore / ControlFlowAfter (which govern the whole case block relative to its siblings).
Scope:
- Between
case Value: label branches (single-statement form).
- Between
case Value: begin ... end; block branches.
- Between the last branch and the
else clause, and between else and end;.
Proposed values (final naming to be decided when implemented):
| Value |
Behavior |
Off |
Do not enforce blank lines between branches (current behavior). |
BlocksOnly |
Require a blank line after each begin ... end; block branch, but not between label-only branches. |
All |
Require a blank line after every branch, regardless of whether the branch uses a block. |
Design questions to answer before implementation:
- Where is the diagnostic located? On the following branch's
case-value token, or on the missing-blank position?
- Does it apply to one-line branches (
"A": DoA();) or does OneLinerMode gate it?
- Is the
else clause treated as just another branch, or is it a separate axis?
- Should adjacent label-only branches (
"A":\n"B":\n DoAOrB();) be exempt because they share a statement?
Implementation notes: CaseStatementSyntax.CaseLines (SyntaxList<CaseLineSyntax>) exposes each branch; caseLine.Statement is BlockSyntax distinguishes block-form from single-statement form. Estimated effort ~2.5 h including tests, schema, docs.
GuardClauseMode (planned, not implemented)
A future StatementBlockSpacing.GuardClauseMode setting to define dedicated spacing for the widely-used guard clause early-exit pattern (if X then exit; / if X then Error(...); at the top of a method). Currently the direct branch is not analyzed as an independent scope-leaver; the containing if follows ControlFlowBefore / ControlFlowAfter and is excluded as a one-liner unless OneLinerMode = All.
Proposed values (final naming to be decided when implemented):
| Value |
Behavior |
Off |
No dedicated guard-clause handling; the containing if follows the regular control-flow settings (current behavior). |
AllowStacked |
Consecutive guard clauses at the top of a method may be stacked without blank lines between them, but a blank line is required before the first non-guard statement below the guard block. |
Isolated |
Every guard clause requires a blank line before AND after it, regardless of stacking. |
Design questions to answer before implementation:
- What counts as a guard clause? Reuse the
IsGuardClause heuristic already in CognitiveComplexity.cs (LC0090) so definitions do not drift.
- Is the "at the top of a method" positional requirement strict, or does any early-
exit inside a loop also qualify?
- Interaction with
ScopeLeavingMode = Off: should GuardClauseMode still activate? Recommended answer: no — if the user disabled scope-leaver spacing globally, the guard exception is moot.
LoopControlBeforeMode (planned, not implemented)
A future StatementBlockSpacing.LoopControlBeforeMode setting for blank-line enforcement before loop-control statements — currently the analyzer only handles exit and built-in Error(...), but break, continue, and Skip (the report/xmlport equivalents) share the same "control-flow-leaving" semantics and benefit from the same visual separation.
Proposed values (final naming to be decided when implemented):
| Value |
Behavior |
Off |
Do not enforce (current behavior). |
RequireBlank |
Require a blank line before break, continue, and Skip when they follow another statement in the same block. |
Design questions to answer before implementation:
- Does this share the
Off short-circuit with ScopeLeavingMode, or is it fully independent? Recommendation: fully independent — teams may want blank before break but not before exit.
- Is
Skip (report/xmlport-only) covered under the same axis or its own? Recommendation: same axis for simplicity; add a separate mode only if user feedback demands it.
- Reuse the existing sibling-lookup + blank-line helpers (
GetSiblingStatements, HasBlankLineBetween) — no new infrastructure needed.
TreatCommentOnlyLinesAsSeparator (planned, not implemented)
A future StatementBlockSpacing.TreatCommentOnlyLinesAsSeparator boolean to decide whether comment-only lines between two statements satisfy the "blank line" requirement. Today only true empty lines count; a //---- section divider on its own line does not.
Proposed default: false (current behavior — only empty lines count). Setting to true opts in to the more lenient interpretation, where any non-empty line consisting solely of leading whitespace + a comment token counts as a separator.
Design questions to answer before implementation:
- Which comment kinds count? Line comments (
//), block comments (/* */), XML-doc comments (///)? Recommendation: all three, because visual effect is the same.
- Is a multi-line block comment on a single line (
/* foo */) a separator? Recommendation: yes.
- What about comments on a statement line (trailing comment)? Recommendation: no — the statement line still counts as "a statement line", the comment is trivia on it.
Implementation notes: the current check walks SourceText.Lines strictly between the two token positions and returns true iff any is whitespace-only. To support this setting, additionally count lines whose sole non-whitespace content is a comment token as blank-equivalent. Estimated effort ~1 h including tests.
SkipDirectiveBoundaries (planned, not implemented)
A future StatementBlockSpacing.SkipDirectiveBoundaries boolean to suppress FC0007 diagnostics across compiler-directive boundaries (#region / #endregion, #pragma, etc.). Directives visually break the code but do not represent statements. Enforcing blank lines around them can conflict with team conventions that already collapse spacing at region boundaries.
Proposed default: false (current behavior — directive-only lines are non-blank, so spacing rules fire across them). Setting to true opts in to treating the boundary as a natural separator.
Design questions to answer before implementation:
- Which directives count?
#region / #endregion clearly; #pragma is less obviously a "visual break". Recommendation: #region / #endregion only, with a follow-up if #pragma demand emerges.
- Does the setting suppress "before" checks, "after" checks, or both? Recommendation: both — a region boundary breaks the block conceptually in both directions.
- Interaction with
TreatCommentOnlyLinesAsSeparator: independent — one is about comments, the other about directives.
Implementation notes: requires walking leading/trailing trivia of the surrounding tokens for RegionDirectiveTrivia / EndRegionDirectiveTrivia. Estimated effort ~2.5 h including tests.
Deferred ideas for this rule, moved out of
.claude/rules/diagnostics/fc0007-statement-blocks-separated-by-blank-line.mdso the rule doc describes current state only. None of these is scheduled; names and defaults may change when an item is picked up.Planned settings — none of these are implemented yet, and none has a scheduled milestone. Names, defaults, and value sets may change when a roadmap item is picked up. Track work here.
CaseBranchMode(planned, not implemented)A future
StatementBlockSpacing.CaseBranchModesetting to control blank-line separation between the individual branches of acasestatement, orthogonal toControlFlowBefore/ControlFlowAfter(which govern the wholecaseblock relative to its siblings).Scope:
case Value:label branches (single-statement form).case Value: begin ... end;block branches.elseclause, and betweenelseandend;.Proposed values (final naming to be decided when implemented):
OffBlocksOnlybegin ... end;block branch, but not between label-only branches.AllDesign questions to answer before implementation:
case-value token, or on the missing-blank position?"A": DoA();) or doesOneLinerModegate it?elseclause treated as just another branch, or is it a separate axis?"A":\n"B":\n DoAOrB();) be exempt because they share a statement?Implementation notes:
CaseStatementSyntax.CaseLines(SyntaxList<CaseLineSyntax>) exposes each branch;caseLine.Statement is BlockSyntaxdistinguishes block-form from single-statement form. Estimated effort ~2.5 h including tests, schema, docs.GuardClauseMode(planned, not implemented)A future
StatementBlockSpacing.GuardClauseModesetting to define dedicated spacing for the widely-used guard clause early-exit pattern (if X then exit;/if X then Error(...);at the top of a method). Currently the direct branch is not analyzed as an independent scope-leaver; the containingiffollowsControlFlowBefore/ControlFlowAfterand is excluded as a one-liner unlessOneLinerMode = All.Proposed values (final naming to be decided when implemented):
Offiffollows the regular control-flow settings (current behavior).AllowStackedIsolatedDesign questions to answer before implementation:
IsGuardClauseheuristic already in CognitiveComplexity.cs (LC0090) so definitions do not drift.exitinside a loop also qualify?ScopeLeavingMode = Off: shouldGuardClauseModestill activate? Recommended answer: no — if the user disabled scope-leaver spacing globally, the guard exception is moot.LoopControlBeforeMode(planned, not implemented)A future
StatementBlockSpacing.LoopControlBeforeModesetting for blank-line enforcement before loop-control statements — currently the analyzer only handlesexitand built-inError(...), butbreak,continue, andSkip(the report/xmlport equivalents) share the same "control-flow-leaving" semantics and benefit from the same visual separation.Proposed values (final naming to be decided when implemented):
OffRequireBlankbreak,continue, andSkipwhen they follow another statement in the same block.Design questions to answer before implementation:
Offshort-circuit withScopeLeavingMode, or is it fully independent? Recommendation: fully independent — teams may want blank beforebreakbut not beforeexit.Skip(report/xmlport-only) covered under the same axis or its own? Recommendation: same axis for simplicity; add a separate mode only if user feedback demands it.GetSiblingStatements,HasBlankLineBetween) — no new infrastructure needed.TreatCommentOnlyLinesAsSeparator(planned, not implemented)A future
StatementBlockSpacing.TreatCommentOnlyLinesAsSeparatorboolean to decide whether comment-only lines between two statements satisfy the "blank line" requirement. Today only true empty lines count; a//---- section divideron its own line does not.Proposed default:
false(current behavior — only empty lines count). Setting totrueopts in to the more lenient interpretation, where any non-empty line consisting solely of leading whitespace + a comment token counts as a separator.Design questions to answer before implementation:
//), block comments (/* */), XML-doc comments (///)? Recommendation: all three, because visual effect is the same./* foo */) a separator? Recommendation: yes.Implementation notes: the current check walks
SourceText.Linesstrictly between the two token positions and returns true iff any is whitespace-only. To support this setting, additionally count lines whose sole non-whitespace content is a comment token as blank-equivalent. Estimated effort ~1 h including tests.SkipDirectiveBoundaries(planned, not implemented)A future
StatementBlockSpacing.SkipDirectiveBoundariesboolean to suppress FC0007 diagnostics across compiler-directive boundaries (#region/#endregion,#pragma, etc.). Directives visually break the code but do not represent statements. Enforcing blank lines around them can conflict with team conventions that already collapse spacing at region boundaries.Proposed default:
false(current behavior — directive-only lines are non-blank, so spacing rules fire across them). Setting totrueopts in to treating the boundary as a natural separator.Design questions to answer before implementation:
#region/#endregionclearly;#pragmais less obviously a "visual break". Recommendation:#region/#endregiononly, with a follow-up if#pragmademand emerges.TreatCommentOnlyLinesAsSeparator: independent — one is about comments, the other about directives.Implementation notes: requires walking leading/trailing trivia of the surrounding tokens for
RegionDirectiveTrivia/EndRegionDirectiveTrivia. Estimated effort ~2.5 h including tests.