[clangd] Added semantic highlighting support for primitives.

Summary:
Adds a new HighlightingKind "Primitive". Adds a special case for TypeLocs that have an underlying TypePtr that is are builtin types, adding them as primitives.
The primary reason for this change is because otherwise typedefs that typedef primitives `typedef int A` would not get highlighted (so in the example `A` would not get any highlightings.)

Reviewers: hokein, ilya-biryukov

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

Tags: #clang

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

llvm-svn: 368291
This commit is contained in:
Johan Vikstrom 2019-08-08 13:10:30 +00:00
parent e1e749d86a
commit d73d994746
5 changed files with 51 additions and 37 deletions

View File

@ -138,9 +138,13 @@ public:
private:
void addTypeLoc(SourceLocation Loc, const TypeLoc &TL) {
if (const Type *TP = TL.getTypePtr())
if (const Type *TP = TL.getTypePtr()) {
if (const TagDecl *TD = TP->getAsTagDecl())
addToken(Loc, TD);
if (TP->isBuiltinType())
// Builtins must be special cased as they do not have a TagDecl.
addToken(Loc, HighlightingKind::Primitive);
}
}
void addToken(SourceLocation Loc, const NamedDecl *D) {
@ -386,6 +390,8 @@ llvm::StringRef toTextMateScope(HighlightingKind Kind) {
return "entity.name.namespace.cpp";
case HighlightingKind::TemplateParameter:
return "entity.name.type.template.cpp";
case HighlightingKind::Primitive:
return "storage.type.primitive.cpp";
case HighlightingKind::NumKinds:
llvm_unreachable("must not pass NumKinds to the function");
}

View File

@ -33,6 +33,7 @@ enum class HighlightingKind {
EnumConstant,
Namespace,
TemplateParameter,
Primitive,
NumKinds,
};

View File

@ -30,6 +30,9 @@
# CHECK-NEXT: ],
# CHECK-NEXT: [
# CHECK-NEXT: "entity.name.type.template.cpp"
# CHECK-NEXT: ],
# CHECK-NEXT: [
# CHECK-NEXT: "storage.type.primitive.cpp"
# CHECK-NEXT: ]
# CHECK-NEXT: ]
# CHECK-NEXT: },
@ -40,7 +43,7 @@
# CHECK-NEXT: "lines": [
# CHECK-NEXT: {
# CHECK-NEXT: "line": 0,
# CHECK-NEXT: "tokens": "AAAABAABAAA="
# CHECK-NEXT: "tokens": "AAAAAAADAAkAAAAEAAEAAA=="
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "textDocument": {
@ -55,11 +58,11 @@
# CHECK-NEXT: "lines": [
# CHECK-NEXT: {
# CHECK-NEXT: "line": 0,
# CHECK-NEXT: "tokens": "AAAABAABAAA="
# CHECK-NEXT: "tokens": "AAAAAAADAAkAAAAEAAEAAA=="
# CHECK-NEXT: }
# CHECK-NEXT: {
# CHECK-NEXT: "line": 1,
# CHECK-NEXT: "tokens": "AAAABAABAAA="
# CHECK-NEXT: "tokens": "AAAAAAADAAkAAAAEAAEAAA=="
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "textDocument": {
@ -74,7 +77,7 @@
# CHECK-NEXT: "lines": [
# CHECK-NEXT: {
# CHECK-NEXT: "line": 1,
# CHECK-NEXT: "tokens": "AAAABAABAAA="
# CHECK-NEXT: "tokens": "AAAAAAADAAkAAAAEAAEAAA=="
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "textDocument": {

View File

@ -39,7 +39,8 @@ std::vector<HighlightingToken> getExpectedTokens(Annotations &Test) {
{HighlightingKind::EnumConstant, "EnumConstant"},
{HighlightingKind::Field, "Field"},
{HighlightingKind::Method, "Method"},
{HighlightingKind::TemplateParameter, "TemplateParameter"}};
{HighlightingKind::TemplateParameter, "TemplateParameter"},
{HighlightingKind::Primitive, "Primitive"}};
std::vector<HighlightingToken> ExpectedTokens;
for (const auto &KindString : KindToString) {
std::vector<HighlightingToken> Toks = makeHighlightingTokens(
@ -93,26 +94,26 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
const char *TestCases[] = {
R"cpp(
struct $Class[[AS]] {
double $Field[[SomeMember]];
$Primitive[[double]] $Field[[SomeMember]];
};
struct {
} $Variable[[S]];
void $Function[[foo]](int $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
$Primitive[[void]] $Function[[foo]]($Primitive[[int]] $Variable[[A]], $Class[[AS]] $Variable[[As]]) {
auto $Variable[[VeryLongVariableName]] = 12312;
$Class[[AS]] $Variable[[AA]];
auto $Variable[[L]] = $Variable[[AA]].$Field[[SomeMember]] + $Variable[[A]];
auto $Variable[[FN]] = [ $Variable[[AA]]](int $Variable[[A]]) -> void {};
auto $Variable[[FN]] = [ $Variable[[AA]]]($Primitive[[int]] $Variable[[A]]) -> $Primitive[[void]] {};
$Variable[[FN]](12312);
}
)cpp",
R"cpp(
void $Function[[foo]](int);
void $Function[[Gah]]();
void $Function[[foo]]() {
$Primitive[[void]] $Function[[foo]]($Primitive[[int]]);
$Primitive[[void]] $Function[[Gah]]();
$Primitive[[void]] $Function[[foo]]() {
auto $Variable[[Bou]] = $Function[[Gah]];
}
struct $Class[[A]] {
void $Method[[abc]]();
$Primitive[[void]] $Method[[abc]]();
};
)cpp",
R"cpp(
@ -126,17 +127,17 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
struct $Class[[C]] : $Namespace[[abc]]::$Class[[A]]<$TemplateParameter[[T]]> {
typename $TemplateParameter[[T]]::A* $Field[[D]];
};
$Namespace[[abc]]::$Class[[A]]<int> $Variable[[AA]];
typedef $Namespace[[abc]]::$Class[[A]]<int> $Class[[AAA]];
$Namespace[[abc]]::$Class[[A]]<$Primitive[[int]]> $Variable[[AA]];
typedef $Namespace[[abc]]::$Class[[A]]<$Primitive[[int]]> $Class[[AAA]];
struct $Class[[B]] {
$Class[[B]]();
~$Class[[B]]();
void operator<<($Class[[B]]);
$Primitive[[void]] operator<<($Class[[B]]);
$Class[[AAA]] $Field[[AA]];
};
$Class[[B]]::$Class[[B]]() {}
$Class[[B]]::~$Class[[B]]() {}
void $Function[[f]] () {
$Primitive[[void]] $Function[[f]] () {
$Class[[B]] $Variable[[BB]] = $Class[[B]]();
$Variable[[BB]].~$Class[[B]]();
$Class[[B]]();
@ -154,7 +155,7 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
$Enum[[E]] $Field[[EEE]];
$Enum[[EE]] $Field[[EEEE]];
};
int $Variable[[I]] = $EnumConstant[[Hi]];
$Primitive[[int]] $Variable[[I]] = $EnumConstant[[Hi]];
$Enum[[E]] $Variable[[L]] = $Enum[[E]]::$EnumConstant[[B]];
)cpp",
R"cpp(
@ -182,13 +183,13 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
)cpp",
R"cpp(
struct $Class[[D]] {
double $Field[[C]];
$Primitive[[double]] $Field[[C]];
};
struct $Class[[A]] {
double $Field[[B]];
$Primitive[[double]] $Field[[B]];
$Class[[D]] $Field[[E]];
static double $Variable[[S]];
void $Method[[foo]]() {
static $Primitive[[double]] $Variable[[S]];
$Primitive[[void]] $Method[[foo]]() {
$Field[[B]] = 123;
this->$Field[[B]] = 156;
this->$Method[[foo]]();
@ -196,7 +197,7 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
$Variable[[S]] = 90.1;
}
};
void $Function[[foo]]() {
$Primitive[[void]] $Function[[foo]]() {
$Class[[A]] $Variable[[AA]];
$Variable[[AA]].$Field[[B]] += 2;
$Variable[[AA]].$Method[[foo]]();
@ -206,14 +207,15 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
)cpp",
R"cpp(
struct $Class[[AA]] {
int $Field[[A]];
$Primitive[[int]] $Field[[A]];
}
int $Variable[[B]];
$Primitive[[int]] $Variable[[B]];
$Class[[AA]] $Variable[[A]]{$Variable[[B]]};
)cpp",
R"cpp(
namespace $Namespace[[a]] {
struct $Class[[A]] {};
typedef $Primitive[[char]] $Primitive[[C]];
}
typedef $Namespace[[a]]::$Class[[A]] $Class[[B]];
using $Class[[BB]] = $Namespace[[a]]::$Class[[A]];
@ -223,9 +225,11 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
using $Enum[[CD]] = $Enum[[CC]];
$Enum[[CC]] $Function[[f]]($Class[[B]]);
$Enum[[CD]] $Function[[f]]($Class[[BB]]);
typedef $Namespace[[a]]::$Primitive[[C]] $Primitive[[PC]];
typedef $Primitive[[float]] $Primitive[[F]];
)cpp",
R"cpp(
template<typename $TemplateParameter[[T]], typename = void>
template<typename $TemplateParameter[[T]], typename = $Primitive[[void]]>
class $Class[[A]] {
$TemplateParameter[[T]] $Field[[AA]];
$TemplateParameter[[T]] $Method[[foo]]();
@ -237,7 +241,7 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
template<class $TemplateParameter[[TT]], class $TemplateParameter[[GG]]>
class $Class[[BB]] {};
template<class $TemplateParameter[[T]]>
class $Class[[BB]]<$TemplateParameter[[T]], int> {};
class $Class[[BB]]<$TemplateParameter[[T]], $Primitive[[int]]> {};
template<class $TemplateParameter[[T]]>
class $Class[[BB]]<$TemplateParameter[[T]], $TemplateParameter[[T]]*> {};
@ -248,13 +252,13 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
class $Class[[Foo]] {};
template<typename $TemplateParameter[[T]]>
void $Function[[foo]]($TemplateParameter[[T]] ...);
$Primitive[[void]] $Function[[foo]]($TemplateParameter[[T]] ...);
)cpp",
R"cpp(
template <class $TemplateParameter[[T]]>
struct $Class[[Tmpl]] {$TemplateParameter[[T]] $Field[[x]] = 0;};
extern template struct $Class[[Tmpl]]<float>;
template struct $Class[[Tmpl]]<double>;
extern template struct $Class[[Tmpl]]<$Primitive[[float]]>;
template struct $Class[[Tmpl]]<$Primitive[[double]]>;
)cpp",
// This test is to guard against highlightings disappearing when using
// conversion operators as their behaviour in the clang AST differ from
@ -263,14 +267,14 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
class $Class[[Foo]] {};
struct $Class[[Bar]] {
explicit operator $Class[[Foo]]*() const;
explicit operator int() const;
explicit operator $Primitive[[int]]() const;
operator $Class[[Foo]]();
};
void $Function[[f]]() {
$Primitive[[void]] $Function[[f]]() {
$Class[[Bar]] $Variable[[B]];
$Class[[Foo]] $Variable[[F]] = $Variable[[B]];
$Class[[Foo]] *$Variable[[FP]] = ($Class[[Foo]]*)$Variable[[B]];
int $Variable[[I]] = (int)$Variable[[B]];
$Primitive[[int]] $Variable[[I]] = ($Primitive[[int]])$Variable[[B]];
}
)cpp"};
for (const auto &TestCase : TestCases) {

View File

@ -488,7 +488,7 @@ TEST(TweaksTest, AnnotateHighlightings) {
checkAvailable(ID, "^vo^id^ ^f(^) {^}^"); // available everywhere.
checkAvailable(ID, "[[int a; int b;]]");
const char *Input = "void ^f() {}";
const char *Output = "void /* entity.name.function.cpp */f() {}";
const char *Output = "/* storage.type.primitive.cpp */void /* entity.name.function.cpp */f() {}";
checkTransform(ID, Input, Output);
checkTransform(ID,
@ -497,8 +497,8 @@ TEST(TweaksTest, AnnotateHighlightings) {
void f2();]]
)cpp",
R"cpp(
void /* entity.name.function.cpp */f1();
void /* entity.name.function.cpp */f2();
/* storage.type.primitive.cpp */void /* entity.name.function.cpp */f1();
/* storage.type.primitive.cpp */void /* entity.name.function.cpp */f2();
)cpp");
checkTransform(ID,
@ -509,7 +509,7 @@ void f2() {^};
R"cpp(
void f1();
void /* entity.name.function.cpp */f2() {};
/* storage.type.primitive.cpp */void /* entity.name.function.cpp */f2() {};
)cpp");
}