Skip to content

Commit 37e31e6

Browse files
[clangd] Improve semantic highlighting in dependent contexts (fixes #154)
Reviewers: hokein Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D67901 llvm-svn: 374799
1 parent 76f9869 commit 37e31e6

File tree

4 files changed

+119
-5
lines changed

4 files changed

+119
-5
lines changed

clang-tools-extra/clangd/SemanticHighlighting.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ bool canHighlightName(DeclarationName Name) {
3737

3838
llvm::Optional<HighlightingKind> kindForType(const Type *TP);
3939
llvm::Optional<HighlightingKind> kindForDecl(const NamedDecl *D) {
40+
if (auto *TD = dyn_cast<TemplateDecl>(D)) {
41+
if (auto *Templated = TD->getTemplatedDecl())
42+
D = Templated;
43+
}
4044
if (auto *TD = dyn_cast<TypedefNameDecl>(D)) {
4145
// We try to highlight typedefs as their underlying type.
4246
if (auto K = kindForType(TD->getUnderlyingType().getTypePtrOrNull()))
@@ -95,6 +99,20 @@ llvm::Optional<HighlightingKind> kindForType(const Type *TP) {
9599
return kindForDecl(TD);
96100
return llvm::None;
97101
}
102+
// Given a set of candidate declarations for an unresolved name,
103+
// if the declarations all have the same highlighting kind, return
104+
// that highlighting kind, otherwise return None.
105+
llvm::Optional<HighlightingKind>
106+
kindForCandidateDecls(llvm::iterator_range<UnresolvedSetIterator> Decls) {
107+
llvm::Optional<HighlightingKind> Result;
108+
for (NamedDecl *Decl : Decls) {
109+
auto Kind = kindForDecl(Decl);
110+
if (!Kind || (Result && Kind != Result))
111+
return llvm::None;
112+
Result = Kind;
113+
}
114+
return Result;
115+
}
98116

99117
// Collects all semantic tokens in an ASTContext.
100118
class HighlightingTokenCollector
@@ -152,6 +170,26 @@ class HighlightingTokenCollector
152170
return true;
153171
}
154172

173+
bool VisitOverloadExpr(OverloadExpr *E) {
174+
if (canHighlightName(E->getName()))
175+
addToken(E->getNameLoc(),
176+
kindForCandidateDecls(E->decls())
177+
.getValueOr(HighlightingKind::DependentName));
178+
return true;
179+
}
180+
181+
bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
182+
if (canHighlightName(E->getDeclName()))
183+
addToken(E->getLocation(), HighlightingKind::DependentName);
184+
return true;
185+
}
186+
187+
bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
188+
if (canHighlightName(E->getMember()))
189+
addToken(E->getMemberLoc(), HighlightingKind::DependentName);
190+
return true;
191+
}
192+
155193
bool VisitNamedDecl(NamedDecl *ND) {
156194
if (canHighlightName(ND->getDeclName()))
157195
addToken(ND->getLocation(), ND);
@@ -187,6 +225,11 @@ class HighlightingTokenCollector
187225
return true;
188226
}
189227

228+
bool WalkUpFromDependentNameTypeLoc(DependentNameTypeLoc L) {
229+
addToken(L.getNameLoc(), HighlightingKind::DependentType);
230+
return true;
231+
}
232+
190233
bool VisitTypeLoc(TypeLoc TL) {
191234
if (auto K = kindForType(TL.getTypePtr()))
192235
addToken(TL.getBeginLoc(), *K);
@@ -339,6 +382,10 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, HighlightingKind K) {
339382
return OS << "EnumConstant";
340383
case HighlightingKind::Typedef:
341384
return OS << "Typedef";
385+
case HighlightingKind::DependentType:
386+
return OS << "DependentType";
387+
case HighlightingKind::DependentName:
388+
return OS << "DependentName";
342389
case HighlightingKind::Namespace:
343390
return OS << "Namespace";
344391
case HighlightingKind::TemplateParameter:
@@ -468,6 +515,10 @@ llvm::StringRef toTextMateScope(HighlightingKind Kind) {
468515
return "variable.other.enummember.cpp";
469516
case HighlightingKind::Typedef:
470517
return "entity.name.type.typedef.cpp";
518+
case HighlightingKind::DependentType:
519+
return "entity.name.type.dependent.cpp";
520+
case HighlightingKind::DependentName:
521+
return "entity.name.other.dependent.cpp";
471522
case HighlightingKind::Namespace:
472523
return "entity.name.namespace.cpp";
473524
case HighlightingKind::TemplateParameter:

clang-tools-extra/clangd/SemanticHighlighting.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ enum class HighlightingKind {
3737
Enum,
3838
EnumConstant,
3939
Typedef,
40+
DependentType,
41+
DependentName,
4042
Namespace,
4143
TemplateParameter,
4244
Primitive,

clang-tools-extra/clangd/test/semantic-highlighting.test

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@
4141
# CHECK-NEXT: "entity.name.type.typedef.cpp"
4242
# CHECK-NEXT: ],
4343
# CHECK-NEXT: [
44+
# CHECK-NEXT: "entity.name.type.dependent.cpp"
45+
# CHECK-NEXT: ],
46+
# CHECK-NEXT: [
47+
# CHECK-NEXT: "entity.name.other.dependent.cpp"
48+
# CHECK-NEXT: ],
49+
# CHECK-NEXT: [
4450
# CHECK-NEXT: "entity.name.namespace.cpp"
4551
# CHECK-NEXT: ],
4652
# CHECK-NEXT: [
@@ -61,7 +67,7 @@
6167
# CHECK-NEXT: "lines": [
6268
# CHECK-NEXT: {
6369
# CHECK-NEXT: "line": 0,
64-
# CHECK-NEXT: "tokens": "AAAAAAADAA4AAAAEAAEAAA=="
70+
# CHECK-NEXT: "tokens": "AAAAAAADABAAAAAEAAEAAA=="
6571
# CHECK-NEXT: }
6672
# CHECK-NEXT: ],
6773
# CHECK-NEXT: "textDocument": {
@@ -76,11 +82,11 @@
7682
# CHECK-NEXT: "lines": [
7783
# CHECK-NEXT: {
7884
# CHECK-NEXT: "line": 0,
79-
# CHECK-NEXT: "tokens": "AAAAAAADAA4AAAAEAAEAAA=="
85+
# CHECK-NEXT: "tokens": "AAAAAAADABAAAAAEAAEAAA=="
8086
# CHECK-NEXT: }
8187
# CHECK-NEXT: {
8288
# CHECK-NEXT: "line": 1,
83-
# CHECK-NEXT: "tokens": "AAAAAAADAA4AAAAEAAEAAA=="
89+
# CHECK-NEXT: "tokens": "AAAAAAADABAAAAAEAAEAAA=="
8490
# CHECK-NEXT: }
8591
# CHECK-NEXT: ],
8692
# CHECK-NEXT: "textDocument": {
@@ -95,7 +101,7 @@
95101
# CHECK-NEXT: "lines": [
96102
# CHECK-NEXT: {
97103
# CHECK-NEXT: "line": 1,
98-
# CHECK-NEXT: "tokens": "AAAAAAADAA4AAAAEAAEAAA=="
104+
# CHECK-NEXT: "tokens": "AAAAAAADABAAAAAEAAEAAA=="
99105
# CHECK-NEXT: }
100106
# CHECK-NEXT: ],
101107
# CHECK-NEXT: "textDocument": {

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

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ std::vector<HighlightingToken> getExpectedTokens(Annotations &Test) {
5151
{HighlightingKind::StaticField, "StaticField"},
5252
{HighlightingKind::Method, "Method"},
5353
{HighlightingKind::StaticMethod, "StaticMethod"},
54+
{HighlightingKind::Typedef, "Typedef"},
55+
{HighlightingKind::DependentType, "DependentType"},
56+
{HighlightingKind::DependentName, "DependentName"},
5457
{HighlightingKind::TemplateParameter, "TemplateParameter"},
5558
{HighlightingKind::Primitive, "Primitive"},
5659
{HighlightingKind::Macro, "Macro"}};
@@ -181,7 +184,7 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
181184
}
182185
template<typename $TemplateParameter[[T]]>
183186
struct $Class[[C]] : $Namespace[[abc]]::$Class[[A]]<$TemplateParameter[[T]]> {
184-
typename $TemplateParameter[[T]]::A* $Field[[D]];
187+
typename $TemplateParameter[[T]]::$DependentType[[A]]* $Field[[D]];
185188
};
186189
$Namespace[[abc]]::$Class[[A]]<$Primitive[[int]]> $Variable[[AA]];
187190
typedef $Namespace[[abc]]::$Class[[A]]<$Primitive[[int]]> $Class[[AAA]];
@@ -529,6 +532,58 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
529532
$Typedef[[Pointer]], $Typedef[[LVReference]], $Typedef[[RVReference]],
530533
$Typedef[[Array]], $Typedef[[MemberPointer]]);
531534
};
535+
)cpp",
536+
R"cpp(
537+
template <class $TemplateParameter[[T]]>
538+
$Primitive[[void]] $Function[[phase1]]($TemplateParameter[[T]]);
539+
template <class $TemplateParameter[[T]]>
540+
$Primitive[[void]] $Function[[foo]]($TemplateParameter[[T]] $Parameter[[P]]) {
541+
$Function[[phase1]]($Parameter[[P]]);
542+
$DependentName[[phase2]]($Parameter[[P]]);
543+
}
544+
)cpp",
545+
R"cpp(
546+
class $Class[[A]] {
547+
template <class $TemplateParameter[[T]]>
548+
$Primitive[[void]] $Method[[bar]]($TemplateParameter[[T]]);
549+
};
550+
551+
template <class $TemplateParameter[[U]]>
552+
$Primitive[[void]] $Function[[foo]]($TemplateParameter[[U]] $Parameter[[P]]) {
553+
$Class[[A]]().$Method[[bar]]($Parameter[[P]]);
554+
}
555+
)cpp",
556+
R"cpp(
557+
struct $Class[[A]] {
558+
template <class $TemplateParameter[[T]]>
559+
static $Primitive[[void]] $StaticMethod[[foo]]($TemplateParameter[[T]]);
560+
};
561+
562+
template <class $TemplateParameter[[T]]>
563+
struct $Class[[B]] {
564+
$Primitive[[void]] $Method[[bar]]() {
565+
$Class[[A]]::$StaticMethod[[foo]]($TemplateParameter[[T]]());
566+
}
567+
};
568+
)cpp",
569+
R"cpp(
570+
template <class $TemplateParameter[[T]]>
571+
$Primitive[[void]] $Function[[foo]](typename $TemplateParameter[[T]]::$DependentType[[Type]]
572+
= $TemplateParameter[[T]]::$DependentName[[val]]);
573+
)cpp",
574+
R"cpp(
575+
template <class $TemplateParameter[[T]]>
576+
$Primitive[[void]] $Function[[foo]]($TemplateParameter[[T]] $Parameter[[P]]) {
577+
$Parameter[[P]].$DependentName[[Field]];
578+
}
579+
)cpp",
580+
R"cpp(
581+
template <class $TemplateParameter[[T]]>
582+
class $Class[[A]] {
583+
$Primitive[[int]] $Method[[foo]]() {
584+
return $TemplateParameter[[T]]::$DependentName[[Field]];
585+
}
586+
};
532587
)cpp"};
533588
for (const auto &TestCase : TestCases) {
534589
checkHighlightings(TestCase);

0 commit comments

Comments
 (0)