Index: lib/Format/UnwrappedLineParser.cpp =================================================================== --- lib/Format/UnwrappedLineParser.cpp +++ lib/Format/UnwrappedLineParser.cpp @@ -703,6 +703,13 @@ // but only aims to correctly handle certain well known cases. It *must not* // return true in speculative cases. void UnwrappedLineParser::readTokenWithJavaScriptASI() { + bool PreviousIsAnnotation = false; + if (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::next(Line->Tokens.rend(), 2)->Tok; + PreviousIsAnnotation = PrePrevious->is(tok::at); + } FormatToken *Previous = FormatTok; readToken(); FormatToken *Next = FormatTok; @@ -714,7 +721,8 @@ if (IsOnSameLine) return; - bool PreviousMustBeValue = mustBeJSIdentOrValue(Keywords, Previous); + bool PreviousMustBeValue = + !PreviousIsAnnotation && mustBeJSIdentOrValue(Keywords, Previous); if (Next->is(tok::exclaim) && PreviousMustBeValue) addUnwrappedLine(); bool NextMustBeValue = mustBeJSIdentOrValue(Keywords, Next); Index: unittests/Format/FormatTestJS.cpp =================================================================== --- unittests/Format/FormatTestJS.cpp +++ unittests/Format/FormatTestJS.cpp @@ -686,6 +686,8 @@ verifyFormat("x instanceof String", "x\n" "instanceof\n" "String"); + verifyFormat("function f(@Foo bar) {}", "function f(@Foo\n" + " bar) {}"); } TEST_F(FormatTestJS, ClosureStyleCasts) {