diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -646,6 +646,15 @@ /*IsDecl=*/false, {E->getNamedConcept()}}); } + + void + VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) { + Refs.push_back( + ReferenceLoc{E->getQualifierLoc(), E->getMemberNameInfo().getLoc(), + /*IsDecl=*/false, + explicitReferenceTargets(DynTypedNode::create(*E), {})}); + } + void VisitDeclRefExpr(const DeclRefExpr *E) { Refs.push_back(ReferenceLoc{E->getQualifierLoc(), E->getNameInfo().getLoc(), @@ -653,6 +662,12 @@ {E->getFoundDecl()}}); } + void VisitDependentScopeDeclRefExpr(const DependentScopeDeclRefExpr *E) { + Refs.push_back(ReferenceLoc{ + E->getQualifierLoc(), E->getNameInfo().getLoc(), /*IsDecl=*/false, + explicitReferenceTargets(DynTypedNode::create(*E), {})}); + } + void VisitMemberExpr(const MemberExpr *E) { // Skip destructor calls to avoid duplication: TypeLoc within will be // visited separately. diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -143,6 +143,27 @@ return getHighlightableSpellingToken(SM.getImmediateSpellingLoc(L), SM); } +enum class TokenQuality { Resolved, Heuristic }; + +TokenQuality evaluateTokenQuality(HighlightingKind Kind) { + return Kind == HighlightingKind::DependentType || + Kind == HighlightingKind::DependentName + ? TokenQuality::Heuristic + : TokenQuality::Resolved; +} + +llvm::Optional +resolveConflict(ArrayRef Tokens) { + if (Tokens.size() != 2) + return llvm::None; + + TokenQuality Quality1 = evaluateTokenQuality(Tokens[0].Kind); + TokenQuality Quality2 = evaluateTokenQuality(Tokens[1].Kind); + if (Quality1 == Quality2) + return llvm::None; + return Quality1 == TokenQuality::Resolved ? Tokens[0] : Tokens[1]; +} + /// Consumes source locations and maps them to text ranges for highlightings. class HighlightingsBuilder { public: @@ -187,6 +208,8 @@ // should be in the highlightings. if (Conflicting.size() == 1) NonConflicting.push_back(TokRef.front()); + else if (auto Resolved = resolveConflict(Conflicting)) + NonConflicting.push_back(*Resolved); // TokRef[Conflicting.size()] is the next token with a different range (or // the end of the Tokens). TokRef = TokRef.drop_front(Conflicting.size()); diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -829,11 +829,11 @@ "0: targets = {x}, decl\n" "1: targets = {vector}\n" "2: targets = {x}\n"}, - // Handle UnresolvedLookupExpr. - // FIXME - // This case fails when expensive checks are enabled. - // Seems like the order of ns1::func and ns2::func isn't defined. - #ifndef EXPENSIVE_CHECKS +// Handle UnresolvedLookupExpr. +// FIXME +// This case fails when expensive checks are enabled. +// Seems like the order of ns1::func and ns2::func isn't defined. +#ifndef EXPENSIVE_CHECKS {R"cpp( namespace ns1 { void func(char*); } namespace ns2 { void func(int*); } @@ -847,7 +847,7 @@ )cpp", "0: targets = {ns1::func, ns2::func}\n" "1: targets = {t}\n"}, - #endif +#endif // Handle UnresolvedMemberExpr. {R"cpp( struct X { @@ -1134,7 +1134,7 @@ namespace foo { template requires $1^Drawable<$2^T> void $3^bar($4^T $5^t) { - $6^t.draw(); + $6^t.$7^draw(); } } )cpp", @@ -1144,7 +1144,8 @@ "3: targets = {foo::bar}, decl\n" "4: targets = {T}\n" "5: targets = {t}, decl\n" - "6: targets = {t}\n"}, + "6: targets = {t}\n" + "7: targets = {}\n"}, // Objective-C: properties { R"cpp( diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -654,6 +654,20 @@ static const int $StaticField[[Value]] = $TemplateParameter[[T]] ::$DependentType[[Resolver]]::$DependentName[[Value]]; }; + )cpp", + // Dependent name with heuristic target + R"cpp( + template + struct $Class[[Foo]] { + int $Field[[Waldo]]; + void $Method[[bar]]() { + $Class[[Foo]]().$Field[[Waldo]]; + } + template + void $Method[[bar1]]() { + $Class[[Foo]]<$TemplateParameter[[U]]>().$Field[[Waldo]]; + } + }; )cpp", // Concepts R"cpp(