]> granicus.if.org Git - clang/commitdiff
clang-format: [JS] space between pseudo keywords and template literals.
authorMartin Probst <martin@probst.io>
Tue, 4 Jul 2017 15:30:21 +0000 (15:30 +0000)
committerMartin Probst <martin@probst.io>
Tue, 4 Jul 2017 15:30:21 +0000 (15:30 +0000)
Summary:
Before:
  yield`foo`;

After:
  yield `foo`;

This reinstates commit 71d3b5cd91 / r307023 and fixes the logic by
introducing an explicit table of JavaScript pseudo keywords.

Reviewers: djasper

Subscribers: klimek

Differential Revision: https://reviews.llvm.org/D34953

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@307087 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Format/FormatToken.h
lib/Format/TokenAnnotator.cpp
unittests/Format/FormatTestJS.cpp

index ce107e2d82a20aeaf64a0ef29d985e0b92b90424..4ea81baf59d69065b389edc1085d46af92eba8b6 100644 (file)
@@ -21,6 +21,7 @@
 #include "clang/Format/Format.h"
 #include "clang/Lex/Lexer.h"
 #include <memory>
+#include <unordered_set>
 
 namespace clang {
 namespace format {
@@ -645,6 +646,13 @@ struct AdditionalKeywords {
     kw_var = &IdentTable.get("var");
     kw_yield = &IdentTable.get("yield");
 
+    JsExtraKeywords = std::unordered_set<IdentifierInfo *>(
+        {kw_as, kw_async, kw_await, kw_declare, kw_finally, kw_from,
+         kw_function, kw_get, kw_import, kw_is, kw_let, kw_module, kw_set,
+         kw_type, kw_var, kw_yield,
+         // Keywords from the Java section.
+         kw_abstract, kw_extends, kw_implements, kw_instanceof, kw_interface});
+
     kw_abstract = &IdentTable.get("abstract");
     kw_assert = &IdentTable.get("assert");
     kw_extends = &IdentTable.get("extends");
@@ -733,6 +741,18 @@ struct AdditionalKeywords {
   IdentifierInfo *kw_qsignals;
   IdentifierInfo *kw_slots;
   IdentifierInfo *kw_qslots;
+
+  /// \brief Returns \c true if \p Tok is a true JavaScript identifier, returns
+  /// \c false if it is a keyword or a pseudo keyword.
+  bool IsJavaScriptIdentifier(const FormatToken &Tok) const {
+    return Tok.is(tok::identifier) &&
+           JsExtraKeywords.find(Tok.Tok.getIdentifierInfo()) ==
+               JsExtraKeywords.end();
+  }
+
+private:
+  /// \brief The JavaScript keywords beyond the C++ keyword set.
+  std::unordered_set<IdentifierInfo *> JsExtraKeywords;
 };
 
 } // namespace format
index a7250cf16950cee66ac975d7b15ffed81aac5a69..821c33a3384f0f942f3a77dfdb1a89d79159a8da 100644 (file)
@@ -2319,7 +2319,11 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
     if ((Left.is(TT_TemplateString) && Left.TokenText.endswith("${")) ||
         (Right.is(TT_TemplateString) && Right.TokenText.startswith("}")))
       return false;
-    if (Left.is(tok::identifier) && Right.is(TT_TemplateString))
+    // In tagged template literals ("html`bar baz`"), there is no space between
+    // the tag identifier and the template string. getIdentifierInfo makes sure
+    // that the identifier is not a pseudo keyword like `yield`, either.
+    if (Left.is(tok::identifier) && Keywords.IsJavaScriptIdentifier(Left) &&
+        Right.is(TT_TemplateString))
       return false;
     if (Right.is(tok::star) &&
         Left.isOneOf(Keywords.kw_function, Keywords.kw_yield))
index e84f470687ec60a10c80b9a908d60d4784884ec6..8c6068171364fb0e333cd734c78e186e74c85e88 100644 (file)
@@ -1622,6 +1622,7 @@ TEST_F(FormatTestJS, NestedTemplateStrings) {
 
 TEST_F(FormatTestJS, TaggedTemplateStrings) {
   verifyFormat("var x = html`<ul>`;");
+  verifyFormat("yield `hello`;");
 }
 
 TEST_F(FormatTestJS, CastSyntax) {