forked from OSchip/llvm-project
[clangd] Added highlightings for namespace specifiers.
Summary: Added highlightings for namespace specifiers. Reviewers: hokein, sammccall, ilya-biryukov Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64492 llvm-svn: 365745
This commit is contained in:
parent
962524070a
commit
b6a74e33c3
|
@ -11,8 +11,6 @@
|
||||||
#include "Protocol.h"
|
#include "Protocol.h"
|
||||||
#include "SourceCode.h"
|
#include "SourceCode.h"
|
||||||
#include "clang/AST/ASTContext.h"
|
#include "clang/AST/ASTContext.h"
|
||||||
#include "clang/AST/Decl.h"
|
|
||||||
#include "clang/AST/DeclarationName.h"
|
|
||||||
#include "clang/AST/RecursiveASTVisitor.h"
|
#include "clang/AST/RecursiveASTVisitor.h"
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
@ -36,7 +34,21 @@ public:
|
||||||
return Tokens;
|
return Tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VisitNamespaceAliasDecl(NamespaceAliasDecl *NAD) {
|
||||||
|
// The target namespace of an alias can not be found in any other way.
|
||||||
|
addToken(NAD->getTargetNameLoc(), HighlightingKind::Namespace);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool VisitNamedDecl(NamedDecl *ND) {
|
bool VisitNamedDecl(NamedDecl *ND) {
|
||||||
|
// UsingDirectiveDecl's namespaces do not show up anywhere else in the
|
||||||
|
// Visit/Traverse mehods. But they should also be highlighted as a
|
||||||
|
// namespace.
|
||||||
|
if (const auto *UD = dyn_cast<UsingDirectiveDecl>(ND)) {
|
||||||
|
addToken(UD->getIdentLocation(), HighlightingKind::Namespace);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Constructors' TypeLoc has a TypePtr that is a FunctionProtoType. It has
|
// Constructors' TypeLoc has a TypePtr that is a FunctionProtoType. It has
|
||||||
// no tag decl and therefore constructors must be gotten as NamedDecls
|
// no tag decl and therefore constructors must be gotten as NamedDecls
|
||||||
// instead.
|
// instead.
|
||||||
|
@ -65,17 +77,28 @@ public:
|
||||||
|
|
||||||
bool VisitTypeLoc(TypeLoc &TL) {
|
bool VisitTypeLoc(TypeLoc &TL) {
|
||||||
// This check is for not getting two entries when there are anonymous
|
// This check is for not getting two entries when there are anonymous
|
||||||
// structs. It also makes us not highlight namespace qualifiers. For
|
// structs. It also makes us not highlight certain namespace qualifiers
|
||||||
// elaborated types the actual type is highlighted as an inner TypeLoc.
|
// twice. For elaborated types the actual type is highlighted as an inner
|
||||||
|
// TypeLoc.
|
||||||
if (TL.getTypeLocClass() == TypeLoc::TypeLocClass::Elaborated)
|
if (TL.getTypeLocClass() == TypeLoc::TypeLocClass::Elaborated)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (const Type *TP = TL.getTypePtr())
|
if (const Type *TP = TL.getTypePtr())
|
||||||
if (const TagDecl *TD = TP->getAsTagDecl())
|
if (const TagDecl *TD = TP->getAsTagDecl())
|
||||||
addToken(TL.getBeginLoc(), TD);
|
addToken(TL.getBeginLoc(), TD);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNSLoc) {
|
||||||
|
if (NestedNameSpecifier *NNS = NNSLoc.getNestedNameSpecifier())
|
||||||
|
if (NNS->getKind() == NestedNameSpecifier::Namespace ||
|
||||||
|
NNS->getKind() == NestedNameSpecifier::NamespaceAlias)
|
||||||
|
addToken(NNSLoc.getLocalBeginLoc(), HighlightingKind::Namespace);
|
||||||
|
|
||||||
|
return RecursiveASTVisitor<
|
||||||
|
HighlightingTokenCollector>::TraverseNestedNameSpecifierLoc(NNSLoc);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addToken(SourceLocation Loc, const NamedDecl *D) {
|
void addToken(SourceLocation Loc, const NamedDecl *D) {
|
||||||
if (D->getDeclName().isIdentifier() && D->getName().empty())
|
if (D->getDeclName().isIdentifier() && D->getName().empty())
|
||||||
|
@ -104,6 +127,14 @@ private:
|
||||||
addToken(Loc, HighlightingKind::Function);
|
addToken(Loc, HighlightingKind::Function);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (isa<NamespaceDecl>(D)) {
|
||||||
|
addToken(Loc, HighlightingKind::Namespace);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isa<NamespaceAliasDecl>(D)) {
|
||||||
|
addToken(Loc, HighlightingKind::Namespace);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addToken(SourceLocation Loc, HighlightingKind Kind) {
|
void addToken(SourceLocation Loc, HighlightingKind Kind) {
|
||||||
|
@ -218,6 +249,8 @@ llvm::StringRef toTextMateScope(HighlightingKind Kind) {
|
||||||
return "entity.name.type.class.cpp";
|
return "entity.name.type.class.cpp";
|
||||||
case HighlightingKind::Enum:
|
case HighlightingKind::Enum:
|
||||||
return "entity.name.type.enum.cpp";
|
return "entity.name.type.enum.cpp";
|
||||||
|
case HighlightingKind::Namespace:
|
||||||
|
return "entity.name.namespace.cpp";
|
||||||
case HighlightingKind::NumKinds:
|
case HighlightingKind::NumKinds:
|
||||||
llvm_unreachable("must not pass NumKinds to the function");
|
llvm_unreachable("must not pass NumKinds to the function");
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ enum class HighlightingKind {
|
||||||
Function,
|
Function,
|
||||||
Class,
|
Class,
|
||||||
Enum,
|
Enum,
|
||||||
|
Namespace,
|
||||||
|
|
||||||
NumKinds,
|
NumKinds,
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,12 +9,15 @@
|
||||||
# CHECK-NEXT: ],
|
# CHECK-NEXT: ],
|
||||||
# CHECK-NEXT: [
|
# CHECK-NEXT: [
|
||||||
# CHECK-NEXT: "entity.name.function.cpp"
|
# CHECK-NEXT: "entity.name.function.cpp"
|
||||||
# CHECK-NEXT: ]
|
# CHECK-NEXT: ],
|
||||||
# CHECK-NEXT: [
|
# CHECK-NEXT: [
|
||||||
# CHECK-NEXT: "entity.name.type.class.cpp"
|
# CHECK-NEXT: "entity.name.type.class.cpp"
|
||||||
# CHECK-NEXT: ],
|
# CHECK-NEXT: ],
|
||||||
# CHECK-NEXT: [
|
# CHECK-NEXT: [
|
||||||
# CHECK-NEXT: "entity.name.type.enum.cpp"
|
# CHECK-NEXT: "entity.name.type.enum.cpp"
|
||||||
|
# CHECK-NEXT: ],
|
||||||
|
# CHECK-NEXT: [
|
||||||
|
# CHECK-NEXT: "entity.name.namespace.cpp"
|
||||||
# CHECK-NEXT: ]
|
# CHECK-NEXT: ]
|
||||||
# CHECK-NEXT: ]
|
# CHECK-NEXT: ]
|
||||||
# CHECK-NEXT: },
|
# CHECK-NEXT: },
|
||||||
|
|
|
@ -36,7 +36,8 @@ void checkHighlightings(llvm::StringRef Code) {
|
||||||
{HighlightingKind::Variable, "Variable"},
|
{HighlightingKind::Variable, "Variable"},
|
||||||
{HighlightingKind::Function, "Function"},
|
{HighlightingKind::Function, "Function"},
|
||||||
{HighlightingKind::Class, "Class"},
|
{HighlightingKind::Class, "Class"},
|
||||||
{HighlightingKind::Enum, "Enum"}};
|
{HighlightingKind::Enum, "Enum"},
|
||||||
|
{HighlightingKind::Namespace, "Namespace"}};
|
||||||
std::vector<HighlightingToken> ExpectedTokens;
|
std::vector<HighlightingToken> ExpectedTokens;
|
||||||
for (const auto &KindString : KindToString) {
|
for (const auto &KindString : KindToString) {
|
||||||
std::vector<HighlightingToken> Toks = makeHighlightingTokens(
|
std::vector<HighlightingToken> Toks = makeHighlightingTokens(
|
||||||
|
@ -75,18 +76,18 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
|
||||||
};
|
};
|
||||||
)cpp",
|
)cpp",
|
||||||
R"cpp(
|
R"cpp(
|
||||||
namespace abc {
|
namespace $Namespace[[abc]] {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct $Class[[A]] {
|
struct $Class[[A]] {
|
||||||
T t;
|
T t;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct $Class[[C]] : abc::A<T> {
|
struct $Class[[C]] : $Namespace[[abc]]::A<T> {
|
||||||
typename T::A* D;
|
typename T::A* D;
|
||||||
};
|
};
|
||||||
abc::$Class[[A]]<int> $Variable[[AA]];
|
$Namespace[[abc]]::$Class[[A]]<int> $Variable[[AA]];
|
||||||
typedef abc::$Class[[A]]<int> AAA;
|
typedef $Namespace[[abc]]::$Class[[A]]<int> AAA;
|
||||||
struct $Class[[B]] {
|
struct $Class[[B]] {
|
||||||
$Class[[B]]();
|
$Class[[B]]();
|
||||||
~$Class[[B]]();
|
~$Class[[B]]();
|
||||||
|
@ -108,6 +109,29 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
|
||||||
$Enum[[E]] EEE;
|
$Enum[[E]] EEE;
|
||||||
$Enum[[EE]] EEEE;
|
$Enum[[EE]] EEEE;
|
||||||
};
|
};
|
||||||
|
)cpp",
|
||||||
|
R"cpp(
|
||||||
|
namespace $Namespace[[abc]] {
|
||||||
|
namespace {}
|
||||||
|
namespace $Namespace[[bcd]] {
|
||||||
|
struct $Class[[A]] {};
|
||||||
|
namespace $Namespace[[cde]] {
|
||||||
|
struct $Class[[A]] {
|
||||||
|
enum class $Enum[[B]] {
|
||||||
|
Hi,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using namespace $Namespace[[abc]]::$Namespace[[bcd]];
|
||||||
|
namespace $Namespace[[vwz]] =
|
||||||
|
$Namespace[[abc]]::$Namespace[[bcd]]::$Namespace[[cde]];
|
||||||
|
$Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable[[AA]];
|
||||||
|
$Namespace[[vwz]]::$Class[[A]]::$Enum[[B]] $Variable[[AAA]] =
|
||||||
|
$Namespace[[vwz]]::$Class[[A]]::$Enum[[B]]::Hi;
|
||||||
|
::$Namespace[[vwz]]::$Class[[A]] $Variable[[B]];
|
||||||
|
::$Namespace[[abc]]::$Namespace[[bcd]]::$Class[[A]] $Variable[[BB]];
|
||||||
)cpp"};
|
)cpp"};
|
||||||
for (const auto &TestCase : TestCases) {
|
for (const auto &TestCase : TestCases) {
|
||||||
checkHighlightings(TestCase);
|
checkHighlightings(TestCase);
|
||||||
|
|
Loading…
Reference in New Issue