summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Vikstrom <jvikstrom@google.com>2019-07-10 08:41:25 +0000
committerJohan Vikstrom <jvikstrom@google.com>2019-07-10 08:41:25 +0000
commiteff868fdef2b674b4f14f2c403413c349381040e (patch)
tree16b509b83b09d012826ce886c627214d14731269
parent4e09ef030e0e073689e08b948b3135938a949fc4 (diff)
downloadbcm5719-llvm-eff868fdef2b674b4f14f2c403413c349381040e.tar.gz
bcm5719-llvm-eff868fdef2b674b4f14f2c403413c349381040e.zip
[clangd] Added highlighting for class and enum types.
Summary: Added highlighting for non-builtin types using VisitTypeLoc. Ignoring namespace qualifiers as for now. Reviewers: hokein, sammccall, ilya-biryukov Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64257 llvm-svn: 365602
-rw-r--r--clang-tools-extra/clangd/SemanticHighlighting.cpp52
-rw-r--r--clang-tools-extra/clangd/SemanticHighlighting.h2
-rw-r--r--clang-tools-extra/clangd/test/semantic-highlighting.test6
-rw-r--r--clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp54
4 files changed, 98 insertions, 16 deletions
diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp
index 3171feb306a..773dfc04108 100644
--- a/clang-tools-extra/clangd/SemanticHighlighting.cpp
+++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp
@@ -11,6 +11,8 @@
#include "Protocol.h"
#include "SourceCode.h"
#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclarationName.h"
#include "clang/AST/RecursiveASTVisitor.h"
namespace clang {
@@ -35,13 +37,18 @@ public:
}
bool VisitNamedDecl(NamedDecl *ND) {
- // FIXME: (De)Constructors/operator need to be highlighted some other way.
- if (ND->getDeclName().getNameKind() != DeclarationName::Identifier)
+ // Constructors' TypeLoc has a TypePtr that is a FunctionProtoType. It has
+ // no tag decl and therefore constructors must be gotten as NamedDecls
+ // instead.
+ if (ND->getDeclName().getNameKind() ==
+ DeclarationName::CXXConstructorName) {
+ addToken(ND->getLocation(), ND);
return true;
+ }
- if (ND->getDeclName().isEmpty())
- // Don't add symbols that don't have any length.
+ if (ND->getDeclName().getNameKind() != DeclarationName::Identifier)
return true;
+
addToken(ND->getLocation(), ND);
return true;
}
@@ -56,8 +63,39 @@ public:
return true;
}
+ bool VisitTypeLoc(TypeLoc &TL) {
+ // This check is for not getting two entries when there are anonymous
+ // structs. It also makes us not highlight namespace qualifiers. For
+ // elaborated types the actual type is highlighted as an inner TypeLoc.
+ if (TL.getTypeLocClass() == TypeLoc::TypeLocClass::Elaborated)
+ return true;
+
+ if (const Type *TP = TL.getTypePtr())
+ if (const TagDecl *TD = TP->getAsTagDecl())
+ addToken(TL.getBeginLoc(), TD);
+ return true;
+ }
+
private:
- void addToken(SourceLocation Loc, const Decl *D) {
+ void addToken(SourceLocation Loc, const NamedDecl *D) {
+ if (D->getDeclName().isIdentifier() && D->getName().empty())
+ // Don't add symbols that don't have any length.
+ return;
+ // We highlight class decls, constructor decls and destructor decls as
+ // `Class` type. The destructor decls are handled in `VisitTypeLoc` (we will
+ // visit a TypeLoc where the underlying Type is a CXXRecordDecl).
+ if (isa<RecordDecl>(D)) {
+ addToken(Loc, HighlightingKind::Class);
+ return;
+ }
+ if (isa<CXXConstructorDecl>(D)) {
+ addToken(Loc, HighlightingKind::Class);
+ return;
+ }
+ if (isa<EnumDecl>(D)) {
+ addToken(Loc, HighlightingKind::Enum);
+ return;
+ }
if (isa<VarDecl>(D)) {
addToken(Loc, HighlightingKind::Variable);
return;
@@ -176,6 +214,10 @@ llvm::StringRef toTextMateScope(HighlightingKind Kind) {
return "entity.name.function.cpp";
case HighlightingKind::Variable:
return "variable.cpp";
+ case HighlightingKind::Class:
+ return "entity.name.type.class.cpp";
+ case HighlightingKind::Enum:
+ return "entity.name.type.enum.cpp";
case HighlightingKind::NumKinds:
llvm_unreachable("must not pass NumKinds to the function");
}
diff --git a/clang-tools-extra/clangd/SemanticHighlighting.h b/clang-tools-extra/clangd/SemanticHighlighting.h
index 385db8d2268..8ba5de22f50 100644
--- a/clang-tools-extra/clangd/SemanticHighlighting.h
+++ b/clang-tools-extra/clangd/SemanticHighlighting.h
@@ -26,6 +26,8 @@ namespace clangd {
enum class HighlightingKind {
Variable = 0,
Function,
+ Class,
+ Enum,
NumKinds,
};
diff --git a/clang-tools-extra/clangd/test/semantic-highlighting.test b/clang-tools-extra/clangd/test/semantic-highlighting.test
index e556e6f30f5..59553c4bfa8 100644
--- a/clang-tools-extra/clangd/test/semantic-highlighting.test
+++ b/clang-tools-extra/clangd/test/semantic-highlighting.test
@@ -10,6 +10,12 @@
# CHECK-NEXT: [
# CHECK-NEXT: "entity.name.function.cpp"
# CHECK-NEXT: ]
+# CHECK-NEXT: [
+# CHECK-NEXT: "entity.name.type.class.cpp"
+# CHECK-NEXT: ],
+# CHECK-NEXT: [
+# CHECK-NEXT: "entity.name.type.enum.cpp"
+# CHECK-NEXT: ]
# CHECK-NEXT: ]
# CHECK-NEXT: },
---
diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
index 599a3430da9..a1d16ab6eb6 100644
--- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -34,11 +34,13 @@ void checkHighlightings(llvm::StringRef Code) {
auto AST = TestTU::withCode(Test.code()).build();
static const std::map<HighlightingKind, std::string> KindToString{
{HighlightingKind::Variable, "Variable"},
- {HighlightingKind::Function, "Function"}};
+ {HighlightingKind::Function, "Function"},
+ {HighlightingKind::Class, "Class"},
+ {HighlightingKind::Enum, "Enum"}};
std::vector<HighlightingToken> ExpectedTokens;
for (const auto &KindString : KindToString) {
- std::vector<HighlightingToken> Toks =
- makeHighlightingTokens(Test.ranges(KindString.second), KindString.first);
+ std::vector<HighlightingToken> Toks = makeHighlightingTokens(
+ Test.ranges(KindString.second), KindString.first);
ExpectedTokens.insert(ExpectedTokens.end(), Toks.begin(), Toks.end());
}
@@ -49,14 +51,14 @@ void checkHighlightings(llvm::StringRef Code) {
TEST(SemanticHighlighting, GetsCorrectTokens) {
const char *TestCases[] = {
R"cpp(
- struct AS {
+ struct $Class[[AS]] {
double SomeMember;
};
struct {
} $Variable[[S]];
- void $Function[[foo]](int $Variable[[A]]) {
+ void $Function[[foo]](int $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
auto $Variable[[VeryLongVariableName]] = 12312;
- AS $Variable[[AA]];
+ $Class[[AS]] $Variable[[AA]];
auto $Variable[[L]] = $Variable[[AA]].SomeMember + $Variable[[A]];
auto $Variable[[FN]] = [ $Variable[[AA]]](int $Variable[[A]]) -> void {};
$Variable[[FN]](12312);
@@ -68,13 +70,43 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
void $Function[[foo]]() {
auto $Variable[[Bou]] = $Function[[Gah]];
}
+ struct $Class[[A]] {
+ void $Function[[abc]]();
+ };
)cpp",
R"cpp(
- struct A {
- A();
- ~A();
- void $Function[[abc]]();
- void operator<<(int);
+ namespace abc {
+ template<typename T>
+ struct $Class[[A]] {
+ T t;
+ };
+ }
+ template<typename T>
+ struct $Class[[C]] : abc::A<T> {
+ typename T::A* D;
+ };
+ abc::$Class[[A]]<int> $Variable[[AA]];
+ typedef abc::$Class[[A]]<int> AAA;
+ struct $Class[[B]] {
+ $Class[[B]]();
+ ~$Class[[B]]();
+ void operator<<($Class[[B]]);
+ $Class[[AAA]] AA;
+ };
+ $Class[[B]]::$Class[[B]]() {}
+ $Class[[B]]::~$Class[[B]]() {}
+ void $Function[[f]] () {
+ $Class[[B]] $Variable[[BB]] = $Class[[B]]();
+ $Variable[[BB]].~$Class[[B]]();
+ $Class[[B]]();
+ }
+ )cpp",
+ R"cpp(
+ enum class $Enum[[E]] {};
+ enum $Enum[[EE]] {};
+ struct $Class[[A]] {
+ $Enum[[E]] EEE;
+ $Enum[[EE]] EEEE;
};
)cpp"};
for (const auto &TestCase : TestCases) {
OpenPOWER on IntegriCloud