mprobst created this revision. Herald added a subscriber: klimek. 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. https://reviews.llvm.org/D40410 Files: lib/Format/UnwrappedLineParser.cpp unittests/Format/FormatTestJS.cpp Index: unittests/Format/FormatTestJS.cpp =================================================================== --- unittests/Format/FormatTestJS.cpp +++ unittests/Format/FormatTestJS.cpp @@ -1192,6 +1192,8 @@ "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" @@ -1557,7 +1559,7 @@ "}"); } -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}"); Index: lib/Format/UnwrappedLineParser.cpp =================================================================== --- lib/Format/UnwrappedLineParser.cpp +++ lib/Format/UnwrappedLineParser.cpp @@ -18,6 +18,8 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> + #define DEBUG_TYPE "format-parser" namespace clang { @@ -891,11 +893,14 @@ 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)
Index: unittests/Format/FormatTestJS.cpp =================================================================== --- unittests/Format/FormatTestJS.cpp +++ unittests/Format/FormatTestJS.cpp @@ -1192,6 +1192,8 @@ "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" @@ -1557,7 +1559,7 @@ "}"); } -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}"); Index: lib/Format/UnwrappedLineParser.cpp =================================================================== --- lib/Format/UnwrappedLineParser.cpp +++ lib/Format/UnwrappedLineParser.cpp @@ -18,6 +18,8 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include <algorithm> + #define DEBUG_TYPE "format-parser" namespace clang { @@ -891,11 +893,14 @@ 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)
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits