Skip to content

Commit f88180b

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

File tree

3 files changed

+20
-2
lines changed

3 files changed

+20
-2
lines changed

clang/lib/Format/UnwrappedLineParser.cpp

Lines changed: 6 additions & 2 deletions
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

Lines changed: 8 additions & 0 deletions
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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3200,6 +3200,12 @@ TEST_F(TokenAnnotatorTest, BraceKind) {
32003200
EXPECT_BRACE_KIND(Tokens[8], BK_BracedInit);
32013201
EXPECT_BRACE_KIND(Tokens[11], BK_BracedInit);
32023202
EXPECT_BRACE_KIND(Tokens[13], BK_Block);
3203+
3204+
Tokens = annotate("a = class extends goog.a {};",
3205+
getGoogleStyle(FormatStyle::LK_JavaScript));
3206+
ASSERT_EQ(Tokens.size(), 11u) << Tokens;
3207+
EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_ClassLBrace);
3208+
EXPECT_BRACE_KIND(Tokens[7], BK_Block);
32033209
}
32043210

32053211
TEST_F(TokenAnnotatorTest, UnderstandsElaboratedTypeSpecifier) {

0 commit comments

Comments
 (0)