[clang-format] [JS] handle private members.
Addresses PR40999 https://bugs.llvm.org/show_bug.cgi?id=40999
Private fields and methods in JavaScript would get incorrectly indented
(it sees them as preprocessor directives and hence left aligns them)
In this revision `#identifier` tokens `tok::hash->tok::identifier` are
merged into a single new token `tok::identifier` with the `#` contained
inside the TokenText.
Before:
```
class Example {
pub = 1;
static pub2 = "foo";
static #priv2 = "bar";
method() { this.#priv = 5; }
static staticMethod() {
switch (this.#priv) {
case '1':
break;
}
}
this.#privateMethod(); // infinite loop
}
static #staticPrivateMethod() {}
}
```
After this fix the code will be correctly indented
```
class Example {
pub = 1;
#priv = 2;
static pub2 = "foo";
static #priv2 = "bar";
method() { this.#priv = 5; }
static staticMethod() {
switch (this.#priv) {
case '1':
#priv = 3;
break;
}
}
#privateMethod() {
this.#privateMethod(); // infinite loop
}
static #staticPrivateMethod() {}
}
```
NOTE: There might be some JavaScript code out there which uses the C
processor to preprocess .js files
http://www.nongnu.org/espresso/js-cpp.html. It's not clear how this
revision or even private fields and methods would interact.
Patch originally by MyDeveloperDays (thanks!).
llvm-svn: 356449
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 2989c76..a5daf8a 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -60,6 +60,7 @@
TYPE(JsExponentiationEqual) \
TYPE(JsFatArrow) \
TYPE(JsNonNullAssertion) \
+ TYPE(JsPrivateIdentifier) \
TYPE(JsTypeColon) \
TYPE(JsTypeOperator) \
TYPE(JsTypeOptionalQuestion) \
diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp
index 2f1b08a..da755e3 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -95,6 +95,8 @@
Tokens.back()->Tok.setKind(tok::starequal);
return;
}
+ if (tryMergeJSPrivateIdentifier())
+ return;
}
if (Style.Language == FormatStyle::LK_Java) {
@@ -121,6 +123,25 @@
return true;
}
+bool FormatTokenLexer::tryMergeJSPrivateIdentifier() {
+ // Merges #idenfier into a single identifier with the text #identifier
+ // but the token tok::identifier.
+ if (Tokens.size() < 2)
+ return false;
+ auto &Hash = *(Tokens.end() - 2);
+ auto &Identifier = *(Tokens.end() - 1);
+ if (!Hash->is(tok::hash) || !Identifier->is(tok::identifier))
+ return false;
+ Hash->Tok.setKind(tok::identifier);
+ Hash->TokenText =
+ StringRef(Hash->TokenText.begin(),
+ Identifier->TokenText.end() - Hash->TokenText.begin());
+ Hash->ColumnWidth += Identifier->ColumnWidth;
+ Hash->Type = TT_JsPrivateIdentifier;
+ Tokens.erase(Tokens.end() - 1);
+ return true;
+}
+
bool FormatTokenLexer::tryMergeLessLess() {
// Merge X,less,less,Y into X,lessless,Y unless X or Y is less.
if (Tokens.size() < 3)
diff --git a/clang/lib/Format/FormatTokenLexer.h b/clang/lib/Format/FormatTokenLexer.h
index 61a4c04..a964626 100644
--- a/clang/lib/Format/FormatTokenLexer.h
+++ b/clang/lib/Format/FormatTokenLexer.h
@@ -48,6 +48,7 @@
bool tryMergeLessLess();
bool tryMergeNSStringLiteral();
+ bool tryMergeJSPrivateIdentifier();
bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType);