diff options
-rw-r--r-- | clang/lib/Format/TokenAnnotator.cpp | 21 | ||||
-rw-r--r-- | clang/unittests/Format/FormatTestJS.cpp | 20 |
2 files changed, 27 insertions, 14 deletions
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index c3ed348ad39..bfa31febd78 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2367,13 +2367,20 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, Left.isOneOf(Keywords.kw_function, Keywords.kw_yield, Keywords.kw_extends, Keywords.kw_implements)) return true; - // JS methods can use some keywords as names (e.g. `delete()`). - if (Right.is(tok::l_paren) && Line.MustBeDeclaration && - Left.Tok.getIdentifierInfo()) - return false; - if (Right.is(tok::l_paren) && - Left.isOneOf(tok::kw_throw, Keywords.kw_await, Keywords.kw_typeof, tok::kw_void)) - return true; + if (Right.is(tok::l_paren)) { + // JS methods can use some keywords as names (e.g. `delete()`). + if (Line.MustBeDeclaration && Left.Tok.getIdentifierInfo()) + return false; + // Valid JS method names can include keywords, e.g. `foo.delete()` or + // `bar.instanceof()`. Recognize call positions by preceding period. + if (Left.Previous && Left.Previous->is(tok::period) && + Left.Tok.getIdentifierInfo()) + return false; + // Additional unary JavaScript operators that need a space after. + if (Left.isOneOf(tok::kw_throw, Keywords.kw_await, Keywords.kw_typeof, + tok::kw_void)) + return true; + } if ((Left.isOneOf(Keywords.kw_let, Keywords.kw_var, Keywords.kw_in, tok::kw_const) || // "of" is only a keyword if it appears after another identifier diff --git a/clang/unittests/Format/FormatTestJS.cpp b/clang/unittests/Format/FormatTestJS.cpp index fb035066d68..57dc7c1119d 100644 --- a/clang/unittests/Format/FormatTestJS.cpp +++ b/clang/unittests/Format/FormatTestJS.cpp @@ -271,14 +271,21 @@ TEST_F(FormatTestJS, ReservedWords) { verifyFormat("x.case = 1;"); verifyFormat("x.interface = 1;"); verifyFormat("x.for = 1;"); - verifyFormat("x.of() = 1;"); + verifyFormat("x.of();"); verifyFormat("of(null);"); verifyFormat("import {of} from 'x';"); - verifyFormat("x.in() = 1;"); - verifyFormat("x.let() = 1;"); - verifyFormat("x.var() = 1;"); - verifyFormat("x.for() = 1;"); - verifyFormat("x.as() = 1;"); + verifyFormat("x.in();"); + verifyFormat("x.let();"); + verifyFormat("x.var();"); + verifyFormat("x.for();"); + verifyFormat("x.as();"); + verifyFormat("x.instanceof();"); + verifyFormat("x.switch();"); + verifyFormat("x.case();"); + verifyFormat("x.delete();"); + verifyFormat("x.throw();"); + verifyFormat("x.throws();"); + verifyFormat("x.if();"); verifyFormat("x = {\n" " a: 12,\n" " interface: 1,\n" @@ -1228,7 +1235,6 @@ TEST_F(FormatTestJS, TryCatch) { // But, of course, "catch" is a perfectly fine function name in JavaScript. verifyFormat("someObject.catch();"); verifyFormat("someObject.new();"); - verifyFormat("someObject.delete();"); } TEST_F(FormatTestJS, StringLiteralConcatenation) { |