Skip to content

Commit 4b6e5a2

Browse files
owencatstellar
authored andcommitted
[clang-format] Handle Java text blocks (llvm#141334)
Fix llvm#61954 (cherry picked from commit b7f5950)
1 parent 0e1ef69 commit 4b6e5a2

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed

clang/lib/Format/FormatTokenLexer.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,36 @@ bool FormatTokenLexer::canPrecedeRegexLiteral(FormatToken *Prev) {
636636
return true;
637637
}
638638

639+
void FormatTokenLexer::tryParseJavaTextBlock() {
640+
if (FormatTok->TokenText != "\"\"")
641+
return;
642+
643+
const auto *S = Lex->getBufferLocation();
644+
const auto *End = Lex->getBuffer().end();
645+
646+
if (S == End || *S != '\"')
647+
return;
648+
649+
++S; // Skip the `"""` that begins a text block.
650+
651+
// Find the `"""` that ends the text block.
652+
for (int Count = 0; Count < 3 && S < End; ++S) {
653+
switch (*S) {
654+
case '\\':
655+
Count = -1;
656+
break;
657+
case '\"':
658+
++Count;
659+
break;
660+
default:
661+
Count = 0;
662+
}
663+
}
664+
665+
// Ignore the possibly invalid text block.
666+
resetLexer(SourceMgr.getFileOffset(Lex->getSourceLocation(S)));
667+
}
668+
639669
// Tries to parse a JavaScript Regex literal starting at the current token,
640670
// if that begins with a slash and is in a location where JavaScript allows
641671
// regex literals. Changes the current token to a regex literal and updates
@@ -1326,6 +1356,9 @@ FormatToken *FormatTokenLexer::getNextToken() {
13261356
FormatTok->TokenText = FormatTok->TokenText.substr(0, 1);
13271357
++Column;
13281358
StateStack.push(LexerState::TOKEN_STASHED);
1359+
} else if (Style.Language == FormatStyle::LK_Java &&
1360+
FormatTok->is(tok::string_literal)) {
1361+
tryParseJavaTextBlock();
13291362
}
13301363

13311364
if (Style.isVerilog() && Tokens.size() > 0 &&

clang/lib/Format/FormatTokenLexer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ class FormatTokenLexer {
7171

7272
bool canPrecedeRegexLiteral(FormatToken *Prev);
7373

74+
void tryParseJavaTextBlock();
75+
7476
// Tries to parse a JavaScript Regex literal starting at the current token,
7577
// if that begins with a slash and is in a location where JavaScript allows
7678
// regex literals. Changes the current token to a regex literal and updates

clang/unittests/Format/FormatTestJava.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,63 @@ TEST_F(FormatTestJava, AlignCaseArrows) {
789789
Style);
790790
}
791791

792+
TEST_F(FormatTestJava, TextBlock) {
793+
verifyNoChange("String myStr = \"\"\"\n"
794+
"hello\n"
795+
"there\n"
796+
"\"\"\";");
797+
798+
verifyNoChange("String tb = \"\"\"\n"
799+
" the new\"\"\";");
800+
801+
verifyNoChange("System.out.println(\"\"\"\n"
802+
" This is the first line\n"
803+
" This is the second line\n"
804+
" \"\"\");");
805+
806+
verifyNoChange("void writeHTML() {\n"
807+
" String html = \"\"\" \n"
808+
" <html>\n"
809+
" <p>Hello World.</p>\n"
810+
" </html>\n"
811+
"\"\"\";\n"
812+
" writeOutput(html);\n"
813+
"}");
814+
815+
verifyNoChange("String colors = \"\"\"\t\n"
816+
" red\n"
817+
" green\n"
818+
" blue\"\"\".indent(4);");
819+
820+
verifyNoChange("String code = \"\"\"\n"
821+
" String source = \\\"\"\"\n"
822+
" String message = \"Hello, World!\";\n"
823+
" System.out.println(message);\n"
824+
" \\\"\"\";\n"
825+
" \"\"\";");
826+
827+
verifyNoChange(
828+
"class Outer {\n"
829+
" void printPoetry() {\n"
830+
" String lilacs = \"\"\"\n"
831+
"Passing the apple-tree blows of white and pink in the orchards\n"
832+
"\"\"\";\n"
833+
" System.out.println(lilacs);\n"
834+
" }\n"
835+
"}");
836+
837+
verifyNoChange("String name = \"\"\"\r\n"
838+
" red\n"
839+
" green\n"
840+
" blue\\\n"
841+
" \"\"\";");
842+
843+
verifyFormat("String name = \"\"\"Pat Q. Smith\"\"\";");
844+
845+
verifyNoChange("String name = \"\"\"\n"
846+
" Pat Q. Smith");
847+
}
848+
792849
} // namespace
793850
} // namespace test
794851
} // namespace format

0 commit comments

Comments
 (0)