Skip to content

Commit 00e794b

Browse files
authored
[clang-format] Properly indent lines inside Verilog case structure (#65861)
When a statement following a case label had to be broken into multiple lines, the continuation parts were not indented correctly. Old: ```Verilog case (data) 16'd0: result = // break here 10'b0111111111; endcase ``` New: ```Verilog case (data) 16'd0: result = // break here 10'b0111111111; endcase ``` Verilog case labels and the following statements are on the same unwrapped line due to the difficulty of identifying them. So there was a rule in `getNewLineColumn` to add a level of indentation to the part following the case label. However, in case the line had to be broken again, the code at the end of the function would see that the line was already broken with the continuation part indented, so it would not indent it more. Now `State.FirstIndent` is changed as well for the part following the case label, so the logic for determining when to add a continuation indentation works.
1 parent bce6c53 commit 00e794b

File tree

2 files changed

+63
-6
lines changed

2 files changed

+63
-6
lines changed

clang/lib/Format/ContinuationIndenter.cpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,12 +1204,13 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
12041204
CurrentState.Indent + Style.ContinuationIndentWidth);
12051205
}
12061206

1207-
// After a goto label. Usually labels are on separate lines. However
1208-
// for Verilog the labels may be only recognized by the annotator and
1209-
// thus are on the same line as the current token.
1210-
if ((Style.isVerilog() && Keywords.isVerilogEndOfLabel(Previous)) ||
1211-
(Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths &&
1212-
State.Line->First->is(tok::kw_enum))) {
1207+
// Indentation of the statement following a Verilog case label is taken care
1208+
// of in moveStateToNextToken.
1209+
if (Style.isVerilog() && Keywords.isVerilogEndOfLabel(Previous))
1210+
return State.FirstIndent;
1211+
1212+
if (Style.BreakBeforeBraces == FormatStyle::BS_Whitesmiths &&
1213+
State.Line->First->is(tok::kw_enum)) {
12131214
return (Style.IndentWidth * State.Line->First->IndentLevel) +
12141215
Style.IndentWidth;
12151216
}
@@ -1599,6 +1600,15 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
15991600

16001601
State.Column += Current.ColumnWidth;
16011602
State.NextToken = State.NextToken->Next;
1603+
// Verilog case labels are on the same unwrapped lines as the statements that
1604+
// follow. TokenAnnotator identifies them and sets MustBreakBefore.
1605+
// Indentation is taken care of here. A case label can only have 1 statement
1606+
// in Verilog, so we don't have to worry about lines that follow.
1607+
if (Style.isVerilog() && State.NextToken &&
1608+
State.NextToken->MustBreakBefore &&
1609+
Keywords.isVerilogEndOfLabel(Current)) {
1610+
State.FirstIndent += Style.IndentWidth;
1611+
}
16021612

16031613
unsigned Penalty =
16041614
handleEndOfLine(Current, State, DryRun, AllowBreak, Newline);

clang/unittests/Format/FormatTestVerilog.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,53 @@ TEST_F(FormatTestVerilog, Case) {
312312
verifyFormat("default:\n"
313313
" x = '{x: x, default: 9};\n",
314314
Style);
315+
// When the line following the case label needs to be broken, the continuation
316+
// should be indented correctly.
317+
verifyFormat("case (data)\n"
318+
" 16'd0:\n"
319+
" result = //\n"
320+
" 10'b0111111111;\n"
321+
"endcase");
322+
verifyFormat("case (data)\n"
323+
" 16'd0, //\n"
324+
" 16'd1:\n"
325+
" result = //\n"
326+
" 10'b0111111111;\n"
327+
"endcase");
328+
verifyFormat("case (data)\n"
329+
" 16'd0:\n"
330+
" result = (10'b0111111111 + //\n"
331+
" 10'b0111111111 + //\n"
332+
" 10'b0111111111);\n"
333+
"endcase");
334+
verifyFormat("case (data)\n"
335+
" 16'd0:\n"
336+
" result = //\n"
337+
" (10'b0111111111 + //\n"
338+
" 10'b0111111111 + //\n"
339+
" 10'b0111111111);\n"
340+
"endcase");
341+
verifyFormat("case (data)\n"
342+
" 16'd0:\n"
343+
" result = //\n"
344+
" longfunction( //\n"
345+
" arg);\n"
346+
"endcase");
347+
Style = getDefaultStyle();
348+
Style.ContinuationIndentWidth = 1;
349+
verifyFormat("case (data)\n"
350+
" 16'd0:\n"
351+
" result = //\n"
352+
" 10'b0111111111;\n"
353+
"endcase",
354+
Style);
355+
verifyFormat("case (data)\n"
356+
" 16'd0:\n"
357+
" result = //\n"
358+
" longfunction( //\n"
359+
" arg);\n"
360+
"endcase",
361+
Style);
315362
}
316363

317364
TEST_F(FormatTestVerilog, Coverage) {

0 commit comments

Comments
 (0)