From: Martin Probst Date: Sat, 25 Nov 2017 09:19:42 +0000 (+0000) Subject: clang-format: [JS] disable ASI on decorators. X-Git-Tag: llvmorg-6.0.0-rc1~2704 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7e0f25b28d56ee2c568c7bcdc3fcc90182800eab;p=platform%2Fupstream%2Fllvm.git clang-format: [JS] disable ASI on decorators. Summary: Automatic Semicolon Insertion in clang-format tries to guess if a line wrap should insert an implicit semicolong. The previous heuristic would not trigger ASI if a token was immediately preceded by an `@` sign: function foo(@Bar // <-- does not trigger due to preceding @ baz) {} However decorators can have arbitrary parameters: function foo(@Bar(param, param, param) // <-- precending @ missed baz) {} While it would be possible to precisely find the matching `@`, just conversatively disabling ASI for the entire line is simpler, while also not regressing ASI substatially. Reviewers: djasper Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D40410 llvm-svn: 318973 --- diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 55518d6..6dd922e 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -18,6 +18,8 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include + #define DEBUG_TYPE "format-parser" namespace clang { @@ -891,11 +893,14 @@ void UnwrappedLineParser::readTokenWithJavaScriptASI() { bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous); bool PreviousStartsTemplateExpr = Previous->is(TT_TemplateString) && Previous->TokenText.endswith("${"); - if (PreviousMustBeValue && Line && Line->Tokens.size() > 1) { - // If the token before the previous one is an '@', the previous token is an - // annotation and can precede another identifier/value. - const FormatToken *PrePrevious = std::prev(Line->Tokens.end(), 2)->Tok; - if (PrePrevious->is(tok::at)) + if (PreviousMustBeValue || Previous->is(tok::r_paren)) { + // If the line contains an '@' sign, the previous token might be an + // annotation, which can precede another identifier/value. + bool HasAt = std::find_if(Line->Tokens.begin(), Line->Tokens.end(), + [](UnwrappedLineNode &LineNode) { + return LineNode.Tok->is(tok::at); + }) != Line->Tokens.end(); + if (HasAt) return; } if (Next->is(tok::exclaim) && PreviousMustBeValue) diff --git a/clang/unittests/Format/FormatTestJS.cpp b/clang/unittests/Format/FormatTestJS.cpp index a107599..97ec843 100644 --- a/clang/unittests/Format/FormatTestJS.cpp +++ b/clang/unittests/Format/FormatTestJS.cpp @@ -1197,6 +1197,8 @@ TEST_F(FormatTestJS, AutomaticSemicolonInsertionHeuristic) { "String"); verifyFormat("function f(@Foo bar) {}", "function f(@Foo\n" " bar) {}"); + verifyFormat("function f(@Foo(Param) bar) {}", "function f(@Foo(Param)\n" + " bar) {}"); verifyFormat("a = true\n" "return 1", "a = true\n" @@ -1564,7 +1566,7 @@ TEST_F(FormatTestJS, EnumDeclarations) { "}"); } -TEST_F(FormatTestJS, MetadataAnnotations) { +TEST_F(FormatTestJS, Decorators) { verifyFormat("@A\nclass C {\n}"); verifyFormat("@A({arg: 'value'})\nclass C {\n}"); verifyFormat("@A\n@B\nclass C {\n}");