From 5d33839e5b7cf04662d25e07a0bf6b8269f18de9 Mon Sep 17 00:00:00 2001 From: Martin Probst Date: Mon, 14 Aug 2017 16:08:16 +0000 Subject: [PATCH] clang-format: [JS] do not insert whitespace in call positions. Summary: In JavaScript, may keywords can be used in method names and thus call sites: foo.delete(); foo.instanceof(); clang-format would previously insert whitespace after the `instanceof`. This change generically skips inserting whitespace between a keyword and a parenthesis if preceded by a dot, i.e. in a callsite. Reviewers: djasper Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D36142 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@310851 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/TokenAnnotator.cpp | 21 ++++++++++++++------- unittests/Format/FormatTestJS.cpp | 20 +++++++++++++------- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index c3ed348ad3..bfa31febd7 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/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/unittests/Format/FormatTestJS.cpp b/unittests/Format/FormatTestJS.cpp index fb035066d6..57dc7c1119 100644 --- a/unittests/Format/FormatTestJS.cpp +++ b/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) { -- 2.50.0