Author: mprobst Date: Tue Mar 19 05:28:41 2019 New Revision: 356449 URL: http://llvm.org/viewvc/llvm-project?rev=356449&view=rev Log: [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!). Modified: cfe/trunk/lib/Format/FormatToken.h cfe/trunk/lib/Format/FormatTokenLexer.cpp cfe/trunk/lib/Format/FormatTokenLexer.h cfe/trunk/unittests/Format/FormatTestJS.cpp Modified: cfe/trunk/lib/Format/FormatToken.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatToken.h?rev=356449&r1=356448&r2=356449&view=diff ============================================================================== --- cfe/trunk/lib/Format/FormatToken.h (original) +++ cfe/trunk/lib/Format/FormatToken.h Tue Mar 19 05:28:41 2019 @@ -60,6 +60,7 @@ namespace format { TYPE(JsExponentiationEqual) \ TYPE(JsFatArrow) \ TYPE(JsNonNullAssertion) \ + TYPE(JsPrivateIdentifier) \ TYPE(JsTypeColon) \ TYPE(JsTypeOperator) \ TYPE(JsTypeOptionalQuestion) \ Modified: cfe/trunk/lib/Format/FormatTokenLexer.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatTokenLexer.cpp?rev=356449&r1=356448&r2=356449&view=diff ============================================================================== --- cfe/trunk/lib/Format/FormatTokenLexer.cpp (original) +++ cfe/trunk/lib/Format/FormatTokenLexer.cpp Tue Mar 19 05:28:41 2019 @@ -95,6 +95,8 @@ void FormatTokenLexer::tryMergePreviousT Tokens.back()->Tok.setKind(tok::starequal); return; } + if (tryMergeJSPrivateIdentifier()) + return; } if (Style.Language == FormatStyle::LK_Java) { @@ -120,6 +122,25 @@ bool FormatTokenLexer::tryMergeNSStringL Tokens.erase(Tokens.end() - 1); 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. Modified: cfe/trunk/lib/Format/FormatTokenLexer.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/FormatTokenLexer.h?rev=356449&r1=356448&r2=356449&view=diff ============================================================================== --- cfe/trunk/lib/Format/FormatTokenLexer.h (original) +++ cfe/trunk/lib/Format/FormatTokenLexer.h Tue Mar 19 05:28:41 2019 @@ -48,6 +48,7 @@ private: bool tryMergeLessLess(); bool tryMergeNSStringLiteral(); + bool tryMergeJSPrivateIdentifier(); bool tryMergeTokens(ArrayRef<tok::TokenKind> Kinds, TokenType NewType); Modified: cfe/trunk/unittests/Format/FormatTestJS.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTestJS.cpp?rev=356449&r1=356448&r2=356449&view=diff ============================================================================== --- cfe/trunk/unittests/Format/FormatTestJS.cpp (original) +++ cfe/trunk/unittests/Format/FormatTestJS.cpp Tue Mar 19 05:28:41 2019 @@ -2334,5 +2334,27 @@ TEST_F(FormatTestJS, ConditionalTypes) { " never) extends((k: infer I) => void) ? I : never;"); } -} // end namespace tooling +TEST_F(FormatTestJS, SupportPrivateFieldsAndMethods) { + verifyFormat("class Example {\n" + " pub = 1;\n" + " #priv = 2;\n" + " static pub2 = 'foo';\n" + " static #priv2 = 'bar';\n" + " method() {\n" + " this.#priv = 5;\n" + " }\n" + " static staticMethod() {\n" + " switch (this.#priv) {\n" + " case '1':\n" + " #priv = 3;\n" + " break;\n" + " }\n" + " }\n" + " #privateMethod() {\n" + " this.#privateMethod(); // infinite loop\n" + " }\n" + " static #staticPrivateMethod() {}\n"); +} + +} // namespace format } // end namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits