diff --git a/clang-tools-extra/clangd/SemanticHighlighting.h b/clang-tools-extra/clangd/SemanticHighlighting.h --- a/clang-tools-extra/clangd/SemanticHighlighting.h +++ b/clang-tools-extra/clangd/SemanticHighlighting.h @@ -72,8 +72,9 @@ ClassScope, FileScope, GlobalScope, + DefaultLibrary, - LastModifier = GlobalScope + LastModifier = DefaultLibrary }; static_assert(static_cast(HighlightingModifier::LastModifier) < 32, "Increase width of modifiers bitfield!"); diff --git a/clang-tools-extra/clangd/SemanticHighlighting.cpp b/clang-tools-extra/clangd/SemanticHighlighting.cpp --- a/clang-tools-extra/clangd/SemanticHighlighting.cpp +++ b/clang-tools-extra/clangd/SemanticHighlighting.cpp @@ -407,6 +407,15 @@ return WithInactiveLines; } + /// Returns true if `Loc` is considered to be from a default/system library. + /// This currently checks the systemness of the file by include type, although + /// different heuristics may be used in the future (e.g. sysroot paths). + bool InDefaultLibrary(SourceLocation Loc) const { + if (!Loc.isValid()) + return false; + return SourceMgr.isInSystemHeader(Loc); + } + const HeuristicResolver *getResolver() const { return Resolver; } private: @@ -419,7 +428,12 @@ HighlightingToken InvalidHighlightingToken; }; -llvm::Optional scopeModifier(const NamedDecl *D) { +llvm::Optional +scopeModifier(const NamedDecl *D, const HighlightingsBuilder &HB) { + if (!D) + return llvm::None; + if (HB.InDefaultLibrary(D->getLocation())) + return HighlightingModifier::DefaultLibrary; const DeclContext *DC = D->getDeclContext(); // Injected "Foo" within the class "Foo" has file scope, not class scope. if (auto *R = dyn_cast_or_null(D)) @@ -447,15 +461,18 @@ return HighlightingModifier::GlobalScope; } -llvm::Optional scopeModifier(const Type *T) { +llvm::Optional +scopeModifier(const Type *T, const HighlightingsBuilder &HB) { if (!T) return llvm::None; if (T->isBuiltinType()) - return HighlightingModifier::GlobalScope; + return HighlightingModifier::DefaultLibrary; if (auto *TD = dyn_cast(T)) - return scopeModifier(TD->getDecl()); + return scopeModifier(TD->getDecl(), HB); if (auto *TD = T->getAsTagDecl()) - return scopeModifier(TD); + return scopeModifier(TD, HB); + if (auto *OT = dyn_cast(T)) + return scopeModifier(OT->getInterface(), HB); return llvm::None; } @@ -466,11 +483,17 @@ public: CollectExtraHighlightings(HighlightingsBuilder &H) : H(H) {} + bool IsFromDefaultLibrary(const NamedDecl *D) { + if (!D) + return false; + return H.InDefaultLibrary(D->getLocation()); + } + bool VisitDecltypeTypeLoc(DecltypeTypeLoc L) { if (auto K = kindForType(L.getTypePtr(), H.getResolver())) { auto &Tok = H.addToken(L.getBeginLoc(), *K) .addModifier(HighlightingModifier::Deduced); - if (auto Mod = scopeModifier(L.getTypePtr())) + if (auto Mod = scopeModifier(L.getTypePtr(), H)) Tok.addModifier(*Mod); } return true; @@ -484,7 +507,7 @@ H.getResolver())) { auto &Tok = H.addToken(D->getTypeSpecStartLoc(), *K) .addModifier(HighlightingModifier::Deduced); - if (auto Mod = scopeModifier(AT->getDeducedType().getTypePtrOrNull())) + if (auto Mod = scopeModifier(AT->getDeducedType().getTypePtrOrNull(), H)) Tok.addModifier(*Mod); } return true; @@ -493,7 +516,7 @@ // We handle objective-C selectors specially, because one reference can // cover several non-contiguous tokens. void highlightObjCSelector(const ArrayRef &Locs, bool Decl, - bool Class) { + bool Class, bool DefaultLibrary) { HighlightingKind Kind = Class ? HighlightingKind::StaticMethod : HighlightingKind::Method; for (SourceLocation Part : Locs) { @@ -503,20 +526,24 @@ Tok.addModifier(HighlightingModifier::Declaration); if (Class) Tok.addModifier(HighlightingModifier::Static); + if (DefaultLibrary) + Tok.addModifier(HighlightingModifier::DefaultLibrary); } } bool VisitObjCMethodDecl(ObjCMethodDecl *OMD) { llvm::SmallVector Locs; OMD->getSelectorLocs(Locs); - highlightObjCSelector(Locs, /*Decl=*/true, OMD->isClassMethod()); + highlightObjCSelector(Locs, /*Decl=*/true, OMD->isClassMethod(), + IsFromDefaultLibrary(OMD)); return true; } bool VisitObjCMessageExpr(ObjCMessageExpr *OME) { llvm::SmallVector Locs; OME->getSelectorLocs(Locs); - highlightObjCSelector(Locs, /*Decl=*/false, OME->isClassMessage()); + highlightObjCSelector(Locs, /*Decl=*/false, OME->isClassMessage(), + IsFromDefaultLibrary(OME->getMethodDecl())); return true; } @@ -632,7 +659,7 @@ if (auto *Templated = TD->getTemplatedDecl()) Decl = Templated; } - if (auto Mod = scopeModifier(Decl)) + if (auto Mod = scopeModifier(Decl, Builder)) Tok.addModifier(*Mod); if (isConst(Decl)) Tok.addModifier(HighlightingModifier::Readonly); @@ -834,6 +861,8 @@ return "fileScope"; // nonstandard case HighlightingModifier::GlobalScope: return "globalScope"; // nonstandard + case HighlightingModifier::DefaultLibrary: + return "defaultLibrary"; } llvm_unreachable("unhandled HighlightingModifier"); } diff --git a/clang-tools-extra/clangd/test/initialize-params.test b/clang-tools-extra/clangd/test/initialize-params.test --- a/clang-tools-extra/clangd/test/initialize-params.test +++ b/clang-tools-extra/clangd/test/initialize-params.test @@ -93,7 +93,8 @@ # CHECK-NEXT: "functionScope", # CHECK-NEXT: "classScope", # CHECK-NEXT: "fileScope", -# CHECK-NEXT: "globalScope" +# CHECK-NEXT: "globalScope", +# CHECK-NEXT: "defaultLibrary" # CHECK-NEXT: ], # CHECK-NEXT: "tokenTypes": [ # CHECK-NEXT: "variable", diff --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp --- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -69,13 +69,16 @@ std::vector> AdditionalFiles = {}, - uint32_t ModifierMask = -1) { + uint32_t ModifierMask = -1, + std::vector AdditionalArgs = {}) { Annotations Test(Code); TestTU TU; TU.Code = std::string(Test.code()); TU.ExtraArgs.push_back("-std=c++20"); TU.ExtraArgs.push_back("-xobjective-c++"); + TU.ExtraArgs.insert(std::end(TU.ExtraArgs), std::begin(AdditionalArgs), + std::end(AdditionalArgs)); for (auto File : AdditionalFiles) TU.AdditionalFiles.insert({File.first, std::string(File.second)}); @@ -102,9 +105,9 @@ struct { } $Variable_decl[[S]]; void $Function_decl[[foo]](int $Parameter_decl[[A]], $Class[[AS]] $Parameter_decl[[As]]) { - $Primitive_deduced[[auto]] $LocalVariable_decl[[VeryLongVariableName]] = 12312; + $Primitive_deduced_defaultLibrary[[auto]] $LocalVariable_decl[[VeryLongVariableName]] = 12312; $Class[[AS]] $LocalVariable_decl[[AA]]; - $Primitive_deduced[[auto]] $LocalVariable_decl[[L]] = $LocalVariable[[AA]].$Field[[SomeMember]] + $Parameter[[A]]; + $Primitive_deduced_defaultLibrary[[auto]] $LocalVariable_decl[[L]] = $LocalVariable[[AA]].$Field[[SomeMember]] + $Parameter[[A]]; auto $LocalVariable_decl[[FN]] = [ $LocalVariable[[AA]]](int $Parameter_decl[[A]]) -> void {}; $LocalVariable[[FN]](12312); } @@ -320,8 +323,8 @@ $Class_deduced[[decltype]](auto) $Variable_decl[[AF2]] = $Class[[Foo]](); $Class_deduced[[auto]] *$Variable_decl[[AFP]] = &$Variable[[AF]]; $Enum_deduced[[auto]] &$Variable_decl[[AER]] = $Variable[[AE]]; - $Primitive_deduced[[auto]] $Variable_decl[[Form]] = 10.2 + 2 * 4; - $Primitive_deduced[[decltype]]($Variable[[Form]]) $Variable_decl[[F]] = 10; + $Primitive_deduced_defaultLibrary[[auto]] $Variable_decl[[Form]] = 10.2 + 2 * 4; + $Primitive_deduced_defaultLibrary[[decltype]]($Variable[[Form]]) $Variable_decl[[F]] = 10; auto $Variable_decl[[Fun]] = []()->void{}; )cpp", R"cpp( @@ -731,6 +734,24 @@ #define DEFINE_Y DEFINE(Y) )cpp"}}, ~ScopeModifierMask); + + checkHighlightings(R"cpp( + #include "SYSObject.h" + @interface $Class_defaultLibrary[[SYSObject]] ($Namespace_decl[[UserCategory]]) + @property(nonatomic, readonly) int $Field_decl_readonly[[user_property]]; + @end + int $Function_decl[[somethingUsingSystemSymbols]]() { + $Class_defaultLibrary[[SYSObject]] *$LocalVariable_decl[[obj]] = [$Class_defaultLibrary[[SYSObject]] $StaticMethod_static_defaultLibrary[[new]]]; + return $LocalVariable[[obj]].$Field_defaultLibrary[[value]] + $LocalVariable[[obj]].$Field_readonly[[user_property]]; + } + )cpp", + {{"SystemSDK/SYSObject.h", R"cpp( + @interface SYSObject + @property(nonatomic, assign) int value; + + (instancetype)new; + @end + )cpp"}}, + ~ScopeModifierMask, {"-isystemSystemSDK/"}); } TEST(SemanticHighlighting, ScopeModifiers) {