Skip to content

Commit 9eae0c4

Browse files
krasimirggllvmbot
authored andcommitted
[clang-format] js handle anonymous classes (llvm#106242)
Addresses a regression in JavaScript when formatting anonymous classes. --------- Co-authored-by: Owen Pan <[email protected]> (cherry picked from commit 77d63cf)
1 parent 5f744ee commit 9eae0c4

File tree

3 files changed

+20
-2
lines changed

3 files changed

+20
-2
lines changed

clang/lib/Format/UnwrappedLineParser.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -3978,6 +3978,9 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
39783978
auto IsNonMacroIdentifier = [](const FormatToken *Tok) {
39793979
return Tok->is(tok::identifier) && Tok->TokenText != Tok->TokenText.upper();
39803980
};
3981+
// JavaScript/TypeScript supports anonymous classes like:
3982+
// a = class extends foo { }
3983+
bool JSPastExtendsOrImplements = false;
39813984
// The actual identifier can be a nested name specifier, and in macros
39823985
// it is often token-pasted.
39833986
// An [[attribute]] can be before the identifier.
@@ -3988,6 +3991,7 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
39883991
FormatTok->isOneOf(tok::period, tok::comma))) {
39893992
if (Style.isJavaScript() &&
39903993
FormatTok->isOneOf(Keywords.kw_extends, Keywords.kw_implements)) {
3994+
JSPastExtendsOrImplements = true;
39913995
// JavaScript/TypeScript supports inline object types in
39923996
// extends/implements positions:
39933997
// class Foo implements {bar: number} { }
@@ -4013,8 +4017,8 @@ void UnwrappedLineParser::parseRecord(bool ParseAsExpr) {
40134017
case tok::coloncolon:
40144018
break;
40154019
default:
4016-
if (!ClassName && Previous->is(tok::identifier) &&
4017-
Previous->isNot(TT_AttributeMacro)) {
4020+
if (!JSPastExtendsOrImplements && !ClassName &&
4021+
Previous->is(tok::identifier) && Previous->isNot(TT_AttributeMacro)) {
40184022
ClassName = Previous;
40194023
}
40204024
}

clang/unittests/Format/FormatTestJS.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,14 @@ TEST_F(FormatTestJS, GoogScopes) {
579579
"});");
580580
}
581581

582+
TEST_F(FormatTestJS, GoogAnonymousClass) {
583+
verifyFormat("a = class extends goog.structs.a {\n"
584+
" a() {\n"
585+
" return 0;\n"
586+
" }\n"
587+
"};");
588+
}
589+
582590
TEST_F(FormatTestJS, IIFEs) {
583591
// Internal calling parens; no semi.
584592
verifyFormat("(function() {\n"

clang/unittests/Format/TokenAnnotatorTest.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -3189,6 +3189,12 @@ TEST_F(TokenAnnotatorTest, BraceKind) {
31893189
EXPECT_BRACE_KIND(Tokens[8], BK_BracedInit);
31903190
EXPECT_BRACE_KIND(Tokens[11], BK_BracedInit);
31913191
EXPECT_BRACE_KIND(Tokens[13], BK_Block);
3192+
3193+
Tokens = annotate("a = class extends goog.a {};",
3194+
getGoogleStyle(FormatStyle::LK_JavaScript));
3195+
ASSERT_EQ(Tokens.size(), 11u) << Tokens;
3196+
EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_ClassLBrace);
3197+
EXPECT_BRACE_KIND(Tokens[7], BK_Block);
31923198
}
31933199

31943200
TEST_F(TokenAnnotatorTest, UnderstandsElaboratedTypeSpecifier) {

0 commit comments

Comments
 (0)