[clangd] Handle more than two conflicting semantic tokens in resolveConflict()
authorNathan Ridge <zeratul976@hotmail.com>
Wed, 16 Mar 2022 08:01:43 +0000 (04:01 -0400)
committerNathan Ridge <zeratul976@hotmail.com>
Wed, 16 Mar 2022 16:53:04 +0000 (12:53 -0400)
Fixes https://github.com/clangd/clangd/issues/1057

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

clang-tools-extra/clangd/SemanticHighlighting.cpp
clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp

index 492763c..862cfc8 100644 (file)
@@ -313,21 +313,26 @@ unsigned evaluateHighlightPriority(const HighlightingToken &Tok) {
 //
 // In particular, heuristically resolved dependent names get their heuristic
 // kind, plus the dependent modifier.
+llvm::Optional<HighlightingToken> resolveConflict(const HighlightingToken &A,
+                                                  const HighlightingToken &B) {
+  unsigned Priority1 = evaluateHighlightPriority(A);
+  unsigned Priority2 = evaluateHighlightPriority(B);
+  if (Priority1 == Priority2 && A.Kind != B.Kind)
+    return llvm::None;
+  auto Result = Priority1 > Priority2 ? A : B;
+  Result.Modifiers = A.Modifiers | B.Modifiers;
+  return Result;
+}
 llvm::Optional<HighlightingToken>
 resolveConflict(ArrayRef<HighlightingToken> Tokens) {
   if (Tokens.size() == 1)
     return Tokens[0];
 
-  if (Tokens.size() != 2)
-    return llvm::None;
-
-  unsigned Priority1 = evaluateHighlightPriority(Tokens[0]);
-  unsigned Priority2 = evaluateHighlightPriority(Tokens[1]);
-  if (Priority1 == Priority2 && Tokens[0].Kind != Tokens[1].Kind)
-    return llvm::None;
-  auto Result = Priority1 > Priority2 ? Tokens[0] : Tokens[1];
-  Result.Modifiers = Tokens[0].Modifiers | Tokens[1].Modifiers;
-  return Result;
+  assert(Tokens.size() >= 2);
+  Optional<HighlightingToken> Winner = resolveConflict(Tokens[0], Tokens[1]);
+  for (size_t I = 2; Winner && I < Tokens.size(); ++I)
+    Winner = resolveConflict(*Winner, Tokens[I]);
+  return Winner;
 }
 
 /// Consumes source locations and maps them to text ranges for highlightings.
index a4e901d..210bc77 100644 (file)
@@ -615,7 +615,14 @@ sizeof...($TemplateParameter[[Elements]]);
         void $Method_decl[[bar1]]() {
           $Class[[Foo]]<$TemplateParameter[[U]]>().$Field_dependentName[[Waldo]];
         }
+
+        void $Method_decl[[Overload]]();
+        void $Method_decl_readonly[[Overload]]() const;
       };
+      template <typename $TemplateParameter_decl[[T]]>
+      void $Function_decl[[baz]]($Class[[Foo]]<$TemplateParameter[[T]]> $Parameter_decl[[o]]) {
+        $Parameter[[o]].$Method_readonly_dependentName[[Overload]]();
+      }
     )cpp",
       // Concepts
       R"cpp(