[clangd] Added highlighting for variable references (declrefs)

Summary: Added highlighting for variable references using VisitDeclRefExpr.

Reviewers: hokein, sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

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

llvm-svn: 365205
This commit is contained in:
Johan Vikstrom 2019-07-05 13:06:03 +00:00
parent ee08036df8
commit 8ca1c65ced
2 changed files with 60 additions and 25 deletions

View File

@ -34,26 +34,46 @@ public:
return Tokens; return Tokens;
} }
bool VisitVarDecl(VarDecl *Var) { bool VisitNamedDecl(NamedDecl *ND) {
addToken(Var, HighlightingKind::Variable); // FIXME: (De)Constructors/operator need to be highlighted some other way.
if (ND->getDeclName().getNameKind() != DeclarationName::Identifier)
return true;
if (ND->getDeclName().isEmpty())
// Don't add symbols that don't have any length.
return true;
addToken(ND->getLocation(), ND);
return true; return true;
} }
bool VisitFunctionDecl(FunctionDecl *Func) {
addToken(Func, HighlightingKind::Function); bool VisitDeclRefExpr(DeclRefExpr *Ref) {
if (Ref->getNameInfo().getName().getNameKind() !=
DeclarationName::Identifier)
// Only want to highlight identifiers.
return true;
addToken(Ref->getLocation(), Ref->getDecl());
return true; return true;
} }
private: private:
void addToken(const NamedDecl *D, HighlightingKind Kind) { void addToken(SourceLocation Loc, const Decl *D) {
if (D->getLocation().isMacroID()) if (isa<VarDecl>(D)) {
addToken(Loc, HighlightingKind::Variable);
return;
}
if (isa<FunctionDecl>(D)) {
addToken(Loc, HighlightingKind::Function);
return;
}
}
void addToken(SourceLocation Loc, HighlightingKind Kind) {
if (Loc.isMacroID())
// FIXME: skip tokens inside macros for now. // FIXME: skip tokens inside macros for now.
return; return;
if (D->getDeclName().isEmpty()) auto R = getTokenRange(SM, Ctx.getLangOpts(), Loc);
// Don't add symbols that don't have any length.
return;
auto R = getTokenRange(SM, Ctx.getLangOpts(), D->getLocation());
if (!R) { if (!R) {
// R should always have a value, if it doesn't something is very wrong. // R should always have a value, if it doesn't something is very wrong.
elog("Tried to add semantic token with an invalid range"); elog("Tried to add semantic token with an invalid range");

View File

@ -48,20 +48,35 @@ void checkHighlightings(llvm::StringRef Code) {
TEST(SemanticHighlighting, GetsCorrectTokens) { TEST(SemanticHighlighting, GetsCorrectTokens) {
const char *TestCases[] = { const char *TestCases[] = {
R"cpp( R"cpp(
struct A { struct AS {
double SomeMember; double SomeMember;
}; };
struct { struct {
} $Variable[[HStruct]]; } $Variable[[S]];
void $Function[[foo]](int $Variable[[a]]) { void $Function[[foo]](int $Variable[[A]]) {
auto $Variable[[VeryLongVariableName]] = 12312; auto $Variable[[VeryLongVariableName]] = 12312;
A $Variable[[aa]]; AS $Variable[[AA]];
} auto $Variable[[L]] = $Variable[[AA]].SomeMember + $Variable[[A]];
)cpp", auto $Variable[[FN]] = [ $Variable[[AA]]](int $Variable[[A]]) -> void {};
R"cpp( $Variable[[FN]](12312);
void $Function[[foo]](int); }
)cpp"}; )cpp",
R"cpp(
void $Function[[foo]](int);
void $Function[[Gah]]();
void $Function[[foo]]() {
auto $Variable[[Bou]] = $Function[[Gah]];
}
)cpp",
R"cpp(
struct A {
A();
~A();
void $Function[[abc]]();
void operator<<(int);
};
)cpp"};
for (const auto &TestCase : TestCases) { for (const auto &TestCase : TestCases) {
checkHighlightings(TestCase); checkHighlightings(TestCase);
} }