summaryrefslogtreecommitdiffstats
path: root/lib/Format
diff options
context:
space:
mode:
authorMartin Probst <martin@probst.io>2019-03-19 12:28:41 +0000
committerMartin Probst <martin@probst.io>2019-03-19 12:28:41 +0000
commit6e5c5ff2d98f297fcfbb107f00010b792c4a8b14 (patch)
tree1eeeeb9dd8b6fae467b0067b85b4952db6740cc2 /lib/Format
parente40a5a512cae6848aa78ddf8194f1ef1fa0798e2 (diff)
[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!). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@356449 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Format')
-rw-r--r--lib/Format/FormatToken.h1
-rw-r--r--lib/Format/FormatTokenLexer.cpp21
-rw-r--r--lib/Format/FormatTokenLexer.h1
3 files changed, 23 insertions, 0 deletions
diff --git a/lib/Format/FormatToken.h b/lib/Format/FormatToken.h
index 2989c760b6..a5daf8aed4 100644
--- a/lib/Format/FormatToken.h
+++ b/lib/Format/FormatToken.h
@@ -60,6 +60,7 @@ namespace format {
TYPE(JsExponentiationEqual) \
TYPE(JsFatArrow) \
TYPE(JsNonNullAssertion) \
+ TYPE(JsPrivateIdentifier) \
TYPE(JsTypeColon) \
TYPE(JsTypeOperator) \
TYPE(JsTypeOptionalQuestion) \
diff --git a/lib/Format/FormatTokenLexer.cpp b/lib/Format/FormatTokenLexer.cpp
index 2f1b08a8b0..da755e36c1 100644
--- a/lib/Format/FormatTokenLexer.cpp
+++ b/lib/Format/FormatTokenLexer.cpp
@@ -95,6 +95,8 @@ void FormatTokenLexer::tryMergePreviousTokens() {
Tokens.back()->Tok.setKind(tok::starequal);
return;
}
+ if (tryMergeJSPrivateIdentifier())
+ return;
}
if (Style.Language == FormatStyle::LK_Java) {
@@ -121,6 +123,25 @@ bool FormatTokenLexer::tryMergeNSStringLiteral() {
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/lib/Format/FormatTokenLexer.h b/lib/Format/FormatTokenLexer.h
index 61a4c041d1..a964626146 100644
--- a/lib/Format/FormatTokenLexer.h
+++ b/lib/Format/FormatTokenLexer.h
@@ -48,6 +48,7 @@ private:
bool tryMergeLessLess();
bool tryMergeNSStringLiteral();
+ bool tryMergeJSPrivateIdentifier();
bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType);