nridge created this revision.
nridge added reviewers: hokein, jvikstrom.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

It's useful to be able to distinguish local variables from namespace
scope variables.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D66723

Files:
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/SemanticHighlighting.h
  clang-tools-extra/clangd/test/semantic-highlighting.test
  clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp

Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -41,7 +41,8 @@
       {HighlightingKind::Field, "Field"},
       {HighlightingKind::Method, "Method"},
       {HighlightingKind::TemplateParameter, "TemplateParameter"},
-      {HighlightingKind::Primitive, "Primitive"}};
+      {HighlightingKind::Primitive, "Primitive"},
+      {HighlightingKind::LocalVariable, "LocalVariable"}};
   std::vector<HighlightingToken> ExpectedTokens;
   for (const auto &KindString : KindToString) {
     std::vector<HighlightingToken> Toks = makeHighlightingTokens(
@@ -99,31 +100,31 @@
 
 TEST(SemanticHighlighting, GetsCorrectTokens) {
   const char *TestCases[] = {
-    R"cpp(
+      R"cpp(
       struct $Class[[AS]] {
         $Primitive[[double]] $Field[[SomeMember]];
       };
       struct {
       } $Variable[[S]];
       $Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Parameter[[A]], $Class[[AS]] $Parameter[[As]]) {
-        $Primitive[[auto]] $Variable[[VeryLongVariableName]] = 12312;
-        $Class[[AS]]     $Variable[[AA]];
-        $Primitive[[auto]] $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Parameter[[A]];
-        auto $Variable[[FN]] = [ $Variable[[AA]]]($Primitive[[int]] $Parameter[[A]]) -> $Primitive[[void]] {};
-        $Variable[[FN]](12312);
+        $Primitive[[auto]] $LocalVariable[[VeryLongVariableName]] = 12312;
+        $Class[[AS]]     $LocalVariable[[AA]];
+        $Primitive[[auto]] $LocalVariable[[L]] = $LocalVariable[[AA]].$Field[[SomeMember]] + $Parameter[[A]];
+        auto $LocalVariable[[FN]] = [ $LocalVariable[[AA]]]($Primitive[[int]] $Parameter[[A]]) -> $Primitive[[void]] {};
+        $LocalVariable[[FN]](12312);
       }
     )cpp",
-    R"cpp(
+      R"cpp(
       $Primitive[[void]] $Function[[foo]]($Primitive[[int]]);
       $Primitive[[void]] $Function[[Gah]]();
       $Primitive[[void]] $Function[[foo]]() {
-        auto $Variable[[Bou]] = $Function[[Gah]];
+        auto $LocalVariable[[Bou]] = $Function[[Gah]];
       }
       struct $Class[[A]] {
         $Primitive[[void]] $Method[[abc]]();
       };
     )cpp",
-    R"cpp(
+      R"cpp(
       namespace $Namespace[[abc]] {
         template<typename $TemplateParameter[[T]]>
         struct $Class[[A]] {
@@ -145,12 +146,12 @@
       $Class[[B]]::$Class[[B]]() {}
       $Class[[B]]::~$Class[[B]]() {}
       $Primitive[[void]] $Function[[f]] () {
-        $Class[[B]] $Variable[[BB]] = $Class[[B]]();
-        $Variable[[BB]].~$Class[[B]]();
+        $Class[[B]] $LocalVariable[[BB]] = $Class[[B]]();
+        $LocalVariable[[BB]].~$Class[[B]]();
         $Class[[B]]();
       }
     )cpp",
-    R"cpp(
+      R"cpp(
       enum class $Enum[[E]] {
         $EnumConstant[[A]],
         $EnumConstant[[B]],
@@ -165,7 +166,7 @@
       $Primitive[[int]] $Variable[[I]] = $EnumConstant[[Hi]];
       $Enum[[E]] $Variable[[L]] = $Enum[[E]]::$EnumConstant[[B]];
     )cpp",
-    R"cpp(
+      R"cpp(
       namespace $Namespace[[abc]] {
         namespace {}
         namespace $Namespace[[bcd]] {
@@ -188,7 +189,7 @@
       ::$Namespace[[vwz]]::$Class[[A]] $Variable[[B]];
       ::$Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable[[BB]];
     )cpp",
-    R"cpp(
+      R"cpp(
       struct $Class[[D]] {
         $Primitive[[double]] $Field[[C]];
       };
@@ -205,21 +206,21 @@
         }
       };
       $Primitive[[void]] $Function[[foo]]() {
-        $Class[[A]] $Variable[[AA]];
-        $Variable[[AA]].$Field[[B]] += 2;
-        $Variable[[AA]].$Method[[foo]]();
-        $Variable[[AA]].$Field[[E]].$Field[[C]];
+        $Class[[A]] $LocalVariable[[AA]];
+        $LocalVariable[[AA]].$Field[[B]] += 2;
+        $LocalVariable[[AA]].$Method[[foo]]();
+        $LocalVariable[[AA]].$Field[[E]].$Field[[C]];
         $Class[[A]]::$Variable[[S]] = 90;
       }
     )cpp",
-    R"cpp(
+      R"cpp(
       struct $Class[[AA]] {
         $Primitive[[int]] $Field[[A]];
       }
       $Primitive[[int]] $Variable[[B]];
       $Class[[AA]] $Variable[[A]]{$Variable[[B]]};
     )cpp",
-    R"cpp(
+      R"cpp(
       namespace $Namespace[[a]] {
         struct $Class[[A]] {};
         typedef $Primitive[[char]] $Primitive[[C]];
@@ -235,7 +236,7 @@
       typedef $Namespace[[a]]::$Primitive[[C]] $Primitive[[PC]];
       typedef $Primitive[[float]] $Primitive[[F]];
     )cpp",
-    R"cpp(
+      R"cpp(
       template<typename $TemplateParameter[[T]], typename = $Primitive[[void]]>
       class $Class[[A]] {
         $TemplateParameter[[T]] $Field[[AA]];
@@ -261,16 +262,16 @@
       template<typename $TemplateParameter[[T]]>
       $Primitive[[void]] $Function[[foo]]($TemplateParameter[[T]] ...);
     )cpp",
-    R"cpp(
+      R"cpp(
       template <class $TemplateParameter[[T]]>
       struct $Class[[Tmpl]] {$TemplateParameter[[T]] $Field[[x]] = 0;};
       extern template struct $Class[[Tmpl]]<$Primitive[[float]]>;
       template struct $Class[[Tmpl]]<$Primitive[[double]]>;
     )cpp",
-    // This test is to guard against highlightings disappearing when using
-    // conversion operators as their behaviour in the clang AST differ from
-    // other CXXMethodDecls.
-    R"cpp(
+      // This test is to guard against highlightings disappearing when using
+      // conversion operators as their behaviour in the clang AST differ from
+      // other CXXMethodDecls.
+      R"cpp(
       class $Class[[Foo]] {};
       struct $Class[[Bar]] {
         explicit operator $Class[[Foo]]*() const;
@@ -278,13 +279,13 @@
         operator $Class[[Foo]]();
       };
       $Primitive[[void]] $Function[[f]]() {
-        $Class[[Bar]] $Variable[[B]];
-        $Class[[Foo]] $Variable[[F]] = $Variable[[B]];
-        $Class[[Foo]] *$Variable[[FP]] = ($Class[[Foo]]*)$Variable[[B]];
-        $Primitive[[int]] $Variable[[I]] = ($Primitive[[int]])$Variable[[B]];
+        $Class[[Bar]] $LocalVariable[[B]];
+        $Class[[Foo]] $LocalVariable[[F]] = $LocalVariable[[B]];
+        $Class[[Foo]] *$LocalVariable[[FP]] = ($Class[[Foo]]*)$LocalVariable[[B]];
+        $Primitive[[int]] $LocalVariable[[I]] = ($Primitive[[int]])$LocalVariable[[B]];
       }
     )cpp"
-    R"cpp(
+      R"cpp(
       struct $Class[[B]] {};
       struct $Class[[A]] {
         $Class[[B]] $Field[[BB]];
@@ -293,7 +294,7 @@
 
       $Class[[A]] &$Class[[A]]::operator=($Class[[A]] &&$Parameter[[O]]) = default;
     )cpp",
-    R"cpp(
+      R"cpp(
       enum $Enum[[En]] {
         $EnumConstant[[EC]],
       };
@@ -311,7 +312,7 @@
         $Class[[Bar2]]() : $Class[[Bar]]($Class[[Foo]](), $EnumConstant[[EC]]) {}
       };
     )cpp",
-    R"cpp(
+      R"cpp(
       enum $Enum[[E]] {
         $EnumConstant[[E]],
       };
@@ -325,7 +326,7 @@
       $Primitive[[decltype]]($Variable[[Form]]) $Variable[[F]] = 10;
       auto $Variable[[Fun]] = []()->$Primitive[[void]]{};
     )cpp",
-    R"cpp(
+      R"cpp(
       class $Class[[G]] {};
       template<$Class[[G]] *$TemplateParameter[[U]]>
       class $Class[[GP]] {};
@@ -340,19 +341,19 @@
       template<$Primitive[[unsigned]] $TemplateParameter[[U]] = 2>
       class $Class[[Foo]] {
         $Primitive[[void]] $Method[[f]]() {
-          for($Primitive[[int]] $Variable[[I]] = 0;
-            $Variable[[I]] < $TemplateParameter[[U]];) {}
+          for($Primitive[[int]] $LocalVariable[[I]] = 0;
+            $LocalVariable[[I]] < $TemplateParameter[[U]];) {}
         }
       };
 
       $Class[[G]] $Variable[[L]];
       $Primitive[[void]] $Function[[f]]() {
-        $Class[[Foo]]<123> $Variable[[F]];
-        $Class[[GP]]<&$Variable[[L]]> $Variable[[LL]];
-        $Class[[GR]]<$Variable[[L]]> $Variable[[LLL]];
+        $Class[[Foo]]<123> $LocalVariable[[F]];
+        $Class[[GP]]<&$Variable[[L]]> $LocalVariable[[LL]];
+        $Class[[GR]]<$Variable[[L]]> $LocalVariable[[LLL]];
       }
     )cpp",
-    R"cpp(
+      R"cpp(
       template<typename $TemplateParameter[[T]], 
         $Primitive[[void]] (T::*$TemplateParameter[[method]])($Primitive[[int]])>
       struct $Class[[G]] {
@@ -372,14 +373,14 @@
       };
 
       $Primitive[[void]] $Function[[foo]]() {
-        $Class[[F]] $Variable[[FF]];
-        $Class[[G]]<$Class[[F]], &$Class[[F]]::$Method[[f]]> $Variable[[GG]];
-        $Variable[[GG]].$Method[[foo]](&$Variable[[FF]]);
-        $Class[[A]]<$Function[[foo]]> $Variable[[AA]];
+        $Class[[F]] $LocalVariable[[FF]];
+        $Class[[G]]<$Class[[F]], &$Class[[F]]::$Method[[f]]> $LocalVariable[[GG]];
+        $LocalVariable[[GG]].$Method[[foo]](&$LocalVariable[[FF]]);
+        $Class[[A]]<$Function[[foo]]> $LocalVariable[[AA]];
     )cpp",
-    // Tokens that share a source range but have conflicting Kinds are not
-    // highlighted.
-    R"cpp(
+      // Tokens that share a source range but have conflicting Kinds are not
+      // highlighted.
+      R"cpp(
       #define DEF_MULTIPLE(X) namespace X { class X { int X; }; }
       #define DEF_CLASS(T) class T {};
       DEF_MULTIPLE(XYZ);
@@ -395,17 +396,17 @@
       #define SOME_NAME_SET variable2 = 123
       #define INC_VAR(X) X += 2
       $Primitive[[void]] $Function[[foo]]() {
-        DEF_VAR($Variable[[X]],  123);
-        DEF_VAR_REV(908, $Variable[[XY]]);
-        $Primitive[[int]] CPY( $Variable[[XX]] );
-        DEF_VAR_TYPE($Class[[A]], $Variable[[AA]]);
+        DEF_VAR($LocalVariable[[X]],  123);
+        DEF_VAR_REV(908, $LocalVariable[[XY]]);
+        $Primitive[[int]] CPY( $LocalVariable[[XX]] );
+        DEF_VAR_TYPE($Class[[A]], $LocalVariable[[AA]]);
         $Primitive[[double]] SOME_NAME;
         $Primitive[[int]] SOME_NAME_SET;
-        $Variable[[variable]] = 20.1;
+        $LocalVariable[[variable]] = 20.1;
         MACRO_CONCAT(var, 2, $Primitive[[float]]);
-        DEF_VAR_T($Class[[A]], CPY(CPY($Variable[[Nested]])),
+        DEF_VAR_T($Class[[A]], CPY(CPY($LocalVariable[[Nested]])),
               CPY($Class[[A]]()));
-        INC_VAR($Variable[[variable]]);
+        INC_VAR($LocalVariable[[variable]]);
       }
       $Primitive[[void]] SOME_NAME();
       DEF_VAR($Variable[[XYZ]], 567);
@@ -417,7 +418,7 @@
         CALL_FN($Function[[foo]]);
       }
     )cpp",
-    R"cpp(
+      R"cpp(
       #define fail(expr) expr
       #define assert(COND) if (!(COND)) { fail("assertion failed" #COND); }
       $Primitive[[int]] $Variable[[x]];
Index: clang-tools-extra/clangd/test/semantic-highlighting.test
===================================================================
--- clang-tools-extra/clangd/test/semantic-highlighting.test
+++ clang-tools-extra/clangd/test/semantic-highlighting.test
@@ -36,6 +36,9 @@
 # CHECK-NEXT:          ],
 # CHECK-NEXT:          [
 # CHECK-NEXT:            "storage.type.primitive.cpp"
+# CHECK-NEXT:          ],
+# CHECK-NEXT:          [
+# CHECK-NEXT:            "variable.other.local.cpp"
 # CHECK-NEXT:          ]
 # CHECK-NEXT:        ]
 # CHECK-NEXT:      },
Index: clang-tools-extra/clangd/SemanticHighlighting.h
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.h
+++ clang-tools-extra/clangd/SemanticHighlighting.h
@@ -35,6 +35,7 @@
   Namespace,
   TemplateParameter,
   Primitive,
+  LocalVariable,
 
   NumKinds,
 };
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -225,7 +225,11 @@
       addToken(Loc, HighlightingKind::Parameter);
       return;
     }
-    if (isa<VarDecl>(D)) {
+    if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
+      if (VD->isLocalVarDecl()) {
+        addToken(Loc, HighlightingKind::LocalVariable);
+        return;
+      }
       addToken(Loc, HighlightingKind::Variable);
       return;
     }
@@ -256,7 +260,7 @@
   }
 
   void addToken(SourceLocation Loc, HighlightingKind Kind) {
-    if(Loc.isMacroID()) {
+    if (Loc.isMacroID()) {
       // Only intereseted in highlighting arguments in macros (DEF_X(arg)).
       if (!SM.isMacroArgExpansion(Loc))
         return;
@@ -266,8 +270,8 @@
     // Non top level decls that are included from a header are not filtered by
     // topLevelDecls. (example: method declarations being included from another
     // file for a class from another file)
-    // There are also cases with macros where the spelling loc will not be in the
-    // main file and the highlighting would be incorrect.
+    // There are also cases with macros where the spelling loc will not be in
+    // the main file and the highlighting would be incorrect.
     if (!isInsideMainFile(Loc, SM))
       return;
 
@@ -340,8 +344,10 @@
 std::vector<LineHighlightings>
 diffHighlightings(ArrayRef<HighlightingToken> New,
                   ArrayRef<HighlightingToken> Old, int NewMaxLine) {
-  assert(std::is_sorted(New.begin(), New.end()) && "New must be a sorted vector");
-  assert(std::is_sorted(Old.begin(), Old.end()) && "Old must be a sorted vector");
+  assert(std::is_sorted(New.begin(), New.end()) &&
+         "New must be a sorted vector");
+  assert(std::is_sorted(Old.begin(), Old.end()) &&
+         "Old must be a sorted vector");
 
   // FIXME: There's an edge case when tokens span multiple lines. If the first
   // token on the line started on a line above the current one and the rest of
@@ -365,9 +371,9 @@
   auto OldEnd = Old.end();
   auto NextLineNumber = [&]() {
     int NextNew = NewLine.end() != NewEnd ? NewLine.end()->R.start.line
-                                             : std::numeric_limits<int>::max();
+                                          : std::numeric_limits<int>::max();
     int NextOld = OldLine.end() != OldEnd ? OldLine.end()->R.start.line
-                                             : std::numeric_limits<int>::max();
+                                          : std::numeric_limits<int>::max();
     return std::min(NextNew, NextOld);
   };
 
@@ -452,6 +458,8 @@
     return "entity.name.type.template.cpp";
   case HighlightingKind::Primitive:
     return "storage.type.primitive.cpp";
+  case HighlightingKind::LocalVariable:
+    return "variable.other.local.cpp";
   case HighlightingKind::NumKinds:
     llvm_unreachable("must not pass NumKinds to the function");
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to