Skip to content

Commit e3702f6

Browse files
authored
[clang-format] TableGen multi line string support. (#78032)
Support the handling of TableGen's multiline string (code) literal. That has the form, [{ this is the string possibly with multi line... }]
1 parent 2db9244 commit e3702f6

File tree

5 files changed

+64
-0
lines changed

5 files changed

+64
-0
lines changed

clang/lib/Format/ContinuationIndenter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,9 @@ unsigned ContinuationIndenter::moveStateToNextToken(LineState &State,
15911591
State.StartOfStringLiteral = State.Column + 1;
15921592
if (Current.is(TT_CSharpStringLiteral) && State.StartOfStringLiteral == 0) {
15931593
State.StartOfStringLiteral = State.Column + 1;
1594+
} else if (Current.is(TT_TableGenMultiLineString) &&
1595+
State.StartOfStringLiteral == 0) {
1596+
State.StartOfStringLiteral = State.Column + 1;
15941597
} else if (Current.isStringLiteral() && State.StartOfStringLiteral == 0) {
15951598
State.StartOfStringLiteral = State.Column;
15961599
} else if (!Current.isOneOf(tok::comment, tok::identifier, tok::hash) &&

clang/lib/Format/FormatToken.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ namespace format {
148148
TYPE(StructLBrace) \
149149
TYPE(StructRBrace) \
150150
TYPE(StructuredBindingLSquare) \
151+
TYPE(TableGenMultiLineString) \
151152
TYPE(TemplateCloser) \
152153
TYPE(TemplateOpener) \
153154
TYPE(TemplateString) \

clang/lib/Format/FormatTokenLexer.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ ArrayRef<FormatToken *> FormatTokenLexer::lex() {
9393
// string literals are correctly identified.
9494
handleCSharpVerbatimAndInterpolatedStrings();
9595
}
96+
if (Style.isTableGen())
97+
handleTableGenMultilineString();
9698
if (Tokens.back()->NewlinesBefore > 0 || Tokens.back()->IsMultiline)
9799
FirstInLineIndex = Tokens.size() - 1;
98100
} while (Tokens.back()->isNot(tok::eof));
@@ -272,6 +274,14 @@ void FormatTokenLexer::tryMergePreviousTokens() {
272274
return;
273275
}
274276
}
277+
// TableGen's Multi line string starts with [{
278+
if (Style.isTableGen() && tryMergeTokens({tok::l_square, tok::l_brace},
279+
TT_TableGenMultiLineString)) {
280+
// Set again with finalizing. This must never be annotated as other types.
281+
Tokens.back()->setFinalizedType(TT_TableGenMultiLineString);
282+
Tokens.back()->Tok.setKind(tok::string_literal);
283+
return;
284+
}
275285
}
276286

277287
bool FormatTokenLexer::tryMergeNSStringLiteral() {
@@ -763,6 +773,37 @@ void FormatTokenLexer::handleCSharpVerbatimAndInterpolatedStrings() {
763773
resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(Offset + 1)));
764774
}
765775

776+
void FormatTokenLexer::handleTableGenMultilineString() {
777+
FormatToken *MultiLineString = Tokens.back();
778+
if (MultiLineString->isNot(TT_TableGenMultiLineString))
779+
return;
780+
781+
auto OpenOffset = Lex->getCurrentBufferOffset() - 2 /* "[{" */;
782+
// "}]" is the end of multi line string.
783+
auto CloseOffset = Lex->getBuffer().find("}]", OpenOffset);
784+
if (CloseOffset == StringRef::npos)
785+
return;
786+
auto Text = Lex->getBuffer().substr(OpenOffset, CloseOffset + 2);
787+
MultiLineString->TokenText = Text;
788+
resetLexer(SourceMgr.getFileOffset(
789+
Lex->getSourceLocation(Lex->getBufferLocation() - 2 + Text.size())));
790+
auto FirstLineText = Text;
791+
auto FirstBreak = Text.find('\n');
792+
// Set ColumnWidth and LastLineColumnWidth when it has multiple lines.
793+
if (FirstBreak != StringRef::npos) {
794+
MultiLineString->IsMultiline = true;
795+
FirstLineText = Text.substr(0, FirstBreak + 1);
796+
// LastLineColumnWidth holds the width of the last line.
797+
auto LastBreak = Text.rfind('\n');
798+
MultiLineString->LastLineColumnWidth = encoding::columnWidthWithTabs(
799+
Text.substr(LastBreak + 1), MultiLineString->OriginalColumn,
800+
Style.TabWidth, Encoding);
801+
}
802+
// ColumnWidth holds only the width of the first line.
803+
MultiLineString->ColumnWidth = encoding::columnWidthWithTabs(
804+
FirstLineText, MultiLineString->OriginalColumn, Style.TabWidth, Encoding);
805+
}
806+
766807
void FormatTokenLexer::handleTemplateStrings() {
767808
FormatToken *BacktickToken = Tokens.back();
768809

clang/lib/Format/FormatTokenLexer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ class FormatTokenLexer {
9595

9696
void handleCSharpVerbatimAndInterpolatedStrings();
9797

98+
// Handles TableGen multiline strings. It has the form [{ ... }].
99+
void handleTableGenMultilineString();
100+
98101
void tryParsePythonComment();
99102

100103
bool tryMerge_TMacro();

clang/unittests/Format/TokenAnnotatorTest.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2193,6 +2193,22 @@ TEST_F(TokenAnnotatorTest, UnderstandTableGenTokens) {
21932193
ASSERT_TRUE(Keywords.isTableGenDefinition(*Tokens[0]));
21942194
ASSERT_TRUE(Tokens[0]->is(Keywords.kw_def));
21952195
ASSERT_TRUE(Tokens[1]->is(TT_StartOfName));
2196+
2197+
// Code, the multiline string token.
2198+
Tokens = Annotate("[{ code is multiline string }]");
2199+
ASSERT_EQ(Tokens.size(), 2u) << Tokens;
2200+
EXPECT_TOKEN(Tokens[0], tok::string_literal, TT_TableGenMultiLineString);
2201+
EXPECT_FALSE(Tokens[0]->IsMultiline);
2202+
// Case with multiple lines.
2203+
Tokens = Annotate("[{ It can break\n"
2204+
" across lines and the line breaks\n"
2205+
" are retained in \n"
2206+
" the string. }]");
2207+
ASSERT_EQ(Tokens.size(), 2u) << Tokens;
2208+
EXPECT_TOKEN(Tokens[0], tok::string_literal, TT_TableGenMultiLineString);
2209+
EXPECT_EQ(Tokens[0]->ColumnWidth, sizeof("[{ It can break\n") - 1);
2210+
EXPECT_TRUE(Tokens[0]->IsMultiline);
2211+
EXPECT_EQ(Tokens[0]->LastLineColumnWidth, sizeof(" the string. }]") - 1);
21962212
}
21972213

21982214
TEST_F(TokenAnnotatorTest, UnderstandConstructors) {

0 commit comments

Comments
 (0)