tom-anders created this revision.
Herald added subscribers: usaxena95, kadircet, arphaman.
tom-anders requested review of this revision.
Herald added subscribers: cfe-commits, ilya-biryukov.
Herald added a project: clang-tools-extra.

See https://github.com/clangd/clangd/issues/839


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D108320

Files:
  clang-tools-extra/clangd/SemanticHighlighting.cpp
  clang-tools-extra/clangd/SemanticHighlighting.h
  clang-tools-extra/clangd/test/initialize-params.test
  clang-tools-extra/clangd/test/semantic-tokens.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
@@ -729,6 +729,28 @@
           }
         };
       )cpp",
+      // Modifier for variables passed as non-const references
+      R"cpp(
+        void $Function_decl[[fun]](int $Parameter_decl[[value]], const int& $Parameter_decl_readonly[[constRef]], 
+                                   int& $Parameter_decl[[ref]], int* $Parameter_decl[[ptr]], 
+                                   int $Parameter_decl[[defaultParameter]] = 3);
+        struct $Class_decl[[S]] {
+          $Class_decl[[S]](int $Parameter_decl[[value]], const int& $Parameter_decl_readonly[[constRef]], 
+                                        int& $Parameter_decl[[ref]], int* $Parameter_decl[[ptr]], 
+                                        int $Parameter_decl[[defaultParameter]] = 3);
+          int $Field_decl[[field]];
+        };
+        void $Function_decl[[bar]]() {
+          int $LocalVariable_decl[[foo]];
+          $Function[[fun]]($LocalVariable[[foo]], $LocalVariable[[foo]], 
+                           $LocalVariable_passedByNonConstRef[[foo]], &$LocalVariable[[foo]]);
+
+          $Class[[S]] $LocalVariable_decl[[s]]($LocalVariable[[foo]], $LocalVariable[[foo]], 
+                                               $LocalVariable_passedByNonConstRef[[foo]], &$LocalVariable[[foo]]);
+          $Function[[fun]]($LocalVariable[[s]].$Field[[field]], $LocalVariable[[s]].$Field[[field]], 
+                           $LocalVariable[[s]].$Field_passedByNonConstRef[[field]], &$LocalVariable[[s]].$Field[[field]]);
+        }
+      )cpp",
   };
   for (const auto &TestCase : TestCases)
     // Mask off scope modifiers to keep the tests manageable.
Index: clang-tools-extra/clangd/test/semantic-tokens.test
===================================================================
--- clang-tools-extra/clangd/test/semantic-tokens.test
+++ clang-tools-extra/clangd/test/semantic-tokens.test
@@ -23,7 +23,7 @@
 # CHECK-NEXT:      4,
 # CHECK-NEXT:      1,
 # CHECK-NEXT:      0,
-# CHECK-NEXT:      4097
+# CHECK-NEXT:      8193
 # CHECK-NEXT:    ],
 # CHECK-NEXT:    "resultId": "1"
 # CHECK-NEXT:  }
@@ -49,7 +49,7 @@
 # CHECK-NEXT:          4,
 # CHECK-NEXT:          1,
 # CHECK-NEXT:          0,
-# CHECK-NEXT:          4097
+# CHECK-NEXT:          8193
 # CHECK-NEXT:        ],
 #                    Inserted at position 1
 # CHECK-NEXT:        "deleteCount": 0,
@@ -72,12 +72,12 @@
 # CHECK-NEXT:      4,
 # CHECK-NEXT:      1,
 # CHECK-NEXT:      0,
-# CHECK-NEXT:      4097,
+# CHECK-NEXT:      8193,
 # CHECK-NEXT:      1,
 # CHECK-NEXT:      4,
 # CHECK-NEXT:      1,
 # CHECK-NEXT:      0,
-# CHECK-NEXT:      4097
+# CHECK-NEXT:      8193
 # CHECK-NEXT:    ],
 # CHECK-NEXT:    "resultId": "3"
 # CHECK-NEXT:  }
Index: clang-tools-extra/clangd/test/initialize-params.test
===================================================================
--- clang-tools-extra/clangd/test/initialize-params.test
+++ clang-tools-extra/clangd/test/initialize-params.test
@@ -91,6 +91,7 @@
 # CHECK-NEXT:            "virtual",
 # CHECK-NEXT:            "dependentName",
 # CHECK-NEXT:            "defaultLibrary",
+# CHECK-NEXT:            "passedByNonConstRef",
 # CHECK-NEXT:            "functionScope",
 # CHECK-NEXT:            "classScope",
 # CHECK-NEXT:            "fileScope",
Index: clang-tools-extra/clangd/SemanticHighlighting.h
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.h
+++ clang-tools-extra/clangd/SemanticHighlighting.h
@@ -70,6 +70,8 @@
   DependentName,
   DefaultLibrary,
 
+  PassedByNonConstRef,
+
   FunctionScope,
   ClassScope,
   FileScope,
Index: clang-tools-extra/clangd/SemanticHighlighting.cpp
===================================================================
--- clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -290,10 +290,12 @@
 }
 
 unsigned evaluateHighlightPriority(const HighlightingToken &Tok) {
-  enum HighlightPriority { Dependent = 0, Resolved = 1 };
+  enum HighlightPriority { Dependent = 0, ResolvedButUnknown = 1, Resolved = 2 };
+
   return (Tok.Modifiers & (1 << uint32_t(HighlightingModifier::DependentName)))
              ? Dependent
-             : Resolved;
+             : (Tok.Kind == HighlightingKind::Unknown ? ResolvedButUnknown
+                                                      : Resolved);
 }
 
 // Sometimes we get multiple tokens at the same location:
@@ -309,6 +311,8 @@
 //
 // - token kinds that come with "dependent-name" modifiers are less reliable
 //   (these tend to be vague, like Type or Unknown)
+// - Resolved tokens (i.e. without the "dependent-name" modifier) with kind
+//   "Unknown" are less reliable than resolved tokens with other kinds
 // - if we have multiple equally reliable kinds, drop token rather than guess
 // - take the union of modifiers from all tokens
 //
@@ -494,7 +498,65 @@
 class CollectExtraHighlightings
     : public RecursiveASTVisitor<CollectExtraHighlightings> {
 public:
-  CollectExtraHighlightings(HighlightingsBuilder &H) : H(H) {}
+  CollectExtraHighlightings(HighlightingsBuilder &H) : H(H) {
+  }
+
+  bool VisitCXXConstructExpr(CXXConstructExpr *E) {
+    highlightPassedByNonConstReference(
+        E->getConstructor(), [&](size_t I) -> Expr * {
+          return I < E->getNumArgs() ? E->getArg(I) : nullptr;
+        });
+
+    return true;
+  }
+
+  bool VisitCallExpr(CallExpr *E) {
+    // Highlighting parameters passed by non-const reference does not really
+    // make sence for these
+    if (isa<CXXOperatorCallExpr>(E) || isa<UserDefinedLiteral>(E))
+      return true;
+
+    highlightPassedByNonConstReference(
+        dyn_cast_or_null<FunctionDecl>(E->getCalleeDecl()),
+        [&](size_t I) -> Expr * {
+          return I < E->getNumArgs() ? E->getArg(I) : nullptr;
+        });
+
+    return true;
+  }
+
+  void highlightPassedByNonConstReference(
+      const FunctionDecl *FD,
+      llvm::function_ref<Expr *(size_t)> GetArgExprAtIndex) {
+    if (!FD)
+      return;
+
+    // Iterate over the declarations of the function parameters.
+    // If any of them are non-const reference paramters, add it as a
+    // highlighting modifier to the corresponding expression
+    for (size_t I = 0; I < FD->getNumParams(); ++I) {
+      if (const auto *Param = FD->getParamDecl(I)) {
+        auto T = Param->getType();
+
+        // Is this parameter passed by non-const reference?
+        if (T->isLValueReferenceType() && !isConst(T)) {
+          if (auto *Arg = GetArgExprAtIndex(I)) {
+            llvm::Optional<SourceLocation> Location;
+
+            if (isa<DeclRefExpr>(Arg)) {
+              Location = Arg->getBeginLoc();
+            } else if (auto *M = dyn_cast<MemberExpr>(Arg)) {
+              Location = M->getMemberLoc();
+            }
+
+            if (Location)
+              H.addToken(*Location, HighlightingKind::Unknown)
+                  .addModifier(HighlightingModifier::PassedByNonConstRef);
+          }
+        }
+      }
+    }
+  }
 
   bool VisitDecltypeTypeLoc(DecltypeTypeLoc L) {
     if (auto K = kindForType(L.getTypePtr(), H.getResolver())) {
@@ -912,6 +974,8 @@
     return "dependentName"; // nonstandard
   case HighlightingModifier::DefaultLibrary:
     return "defaultLibrary";
+  case HighlightingModifier::PassedByNonConstRef:
+    return "passedByNonConstRef"; // nonstandard
   case HighlightingModifier::FunctionScope:
     return "functionScope"; // nonstandard
   case HighlightingModifier::ClassScope:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to