Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.h =================================================================== --- clang-tools-extra/trunk/clangd/SemanticHighlighting.h +++ clang-tools-extra/trunk/clangd/SemanticHighlighting.h @@ -28,6 +28,7 @@ Function, Class, Enum, + Namespace, NumKinds, }; Index: clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp =================================================================== --- clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp +++ clang-tools-extra/trunk/clangd/SemanticHighlighting.cpp @@ -11,8 +11,6 @@ #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 { @@ -36,7 +34,21 @@ 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) { + // 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(ND)) { + addToken(UD->getIdentLocation(), HighlightingKind::Namespace); + return true; + } + // Constructors' TypeLoc has a TypePtr that is a FunctionProtoType. It has // no tag decl and therefore constructors must be gotten as NamedDecls // instead. @@ -65,17 +77,28 @@ 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. + // structs. It also makes us not highlight certain namespace qualifiers + // twice. 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); + addToken(TL.getBeginLoc(), TD); 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: void addToken(SourceLocation Loc, const NamedDecl *D) { if (D->getDeclName().isIdentifier() && D->getName().empty()) @@ -104,6 +127,14 @@ addToken(Loc, HighlightingKind::Function); return; } + if (isa(D)) { + addToken(Loc, HighlightingKind::Namespace); + return; + } + if (isa(D)) { + addToken(Loc, HighlightingKind::Namespace); + return; + } } void addToken(SourceLocation Loc, HighlightingKind Kind) { @@ -218,6 +249,8 @@ return "entity.name.type.class.cpp"; case HighlightingKind::Enum: return "entity.name.type.enum.cpp"; + case HighlightingKind::Namespace: + return "entity.name.namespace.cpp"; case HighlightingKind::NumKinds: llvm_unreachable("must not pass NumKinds to the function"); } Index: clang-tools-extra/trunk/clangd/test/semantic-highlighting.test =================================================================== --- clang-tools-extra/trunk/clangd/test/semantic-highlighting.test +++ clang-tools-extra/trunk/clangd/test/semantic-highlighting.test @@ -9,12 +9,15 @@ # CHECK-NEXT: ], # CHECK-NEXT: [ # CHECK-NEXT: "entity.name.function.cpp" -# CHECK-NEXT: ] +# 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: "entity.name.namespace.cpp" # CHECK-NEXT: ] # CHECK-NEXT: ] # CHECK-NEXT: }, Index: clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp =================================================================== --- clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp +++ clang-tools-extra/trunk/clangd/unittests/SemanticHighlightingTests.cpp @@ -36,7 +36,8 @@ {HighlightingKind::Variable, "Variable"}, {HighlightingKind::Function, "Function"}, {HighlightingKind::Class, "Class"}, - {HighlightingKind::Enum, "Enum"}}; + {HighlightingKind::Enum, "Enum"}, + {HighlightingKind::Namespace, "Namespace"}}; std::vector ExpectedTokens; for (const auto &KindString : KindToString) { std::vector Toks = makeHighlightingTokens( @@ -75,18 +76,18 @@ }; )cpp", R"cpp( - namespace abc { + namespace $Namespace[[abc]] { template struct $Class[[A]] { T t; }; } template - struct $Class[[C]] : abc::A { + struct $Class[[C]] : $Namespace[[abc]]::A { typename T::A* D; }; - abc::$Class[[A]] $Variable[[AA]]; - typedef abc::$Class[[A]] AAA; + $Namespace[[abc]]::$Class[[A]] $Variable[[AA]]; + typedef $Namespace[[abc]]::$Class[[A]] AAA; struct $Class[[B]] { $Class[[B]](); ~$Class[[B]](); @@ -108,6 +109,29 @@ $Enum[[E]] EEE; $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"}; for (const auto &TestCase : TestCases) { checkHighlightings(TestCase);