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 @@ -67,6 +67,7 @@ Static, Abstract, DependentName, + DefaultLibrary, FunctionScope, ClassScope, 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 @@ -246,6 +246,29 @@ return false; } +/// Returns true if `Decl` 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 isDefaultLibrary(const Decl *D) { + SourceLocation Loc = D->getLocation(); + if (!Loc.isValid()) + return false; + return D->getASTContext().getSourceManager().isInSystemHeader(Loc); +} + +bool isDefaultLibrary(const Type *T) { + if (!T) + return false; + const Type *Underlying = T->getPointeeOrArrayElementType(); + if (Underlying->isBuiltinType()) + return true; + if (auto *TD = dyn_cast(Underlying)) + return isDefaultLibrary(TD->getDecl()); + if (auto *TD = Underlying->getAsTagDecl()) + return isDefaultLibrary(TD); + return false; +} + // For a macro usage `DUMP(foo)`, we want: // - DUMP --> "macro" // - foo --> "variable". @@ -473,6 +496,8 @@ .addModifier(HighlightingModifier::Deduced); if (auto Mod = scopeModifier(L.getTypePtr())) Tok.addModifier(*Mod); + if (isDefaultLibrary(L.getTypePtr())) + Tok.addModifier(HighlightingModifier::DefaultLibrary); } return true; } @@ -485,8 +510,11 @@ H.getResolver())) { auto &Tok = H.addToken(D->getTypeSpecStartLoc(), *K) .addModifier(HighlightingModifier::Deduced); - if (auto Mod = scopeModifier(AT->getDeducedType().getTypePtrOrNull())) + const Type *Deduced = AT->getDeducedType().getTypePtrOrNull(); + if (auto Mod = scopeModifier(Deduced)) Tok.addModifier(*Mod); + if (isDefaultLibrary(Deduced)) + Tok.addModifier(HighlightingModifier::DefaultLibrary); } return true; } @@ -494,7 +522,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) { @@ -504,20 +532,27 @@ 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(), + isDefaultLibrary(OMD)); return true; } bool VisitObjCMessageExpr(ObjCMessageExpr *OME) { llvm::SmallVector Locs; OME->getSelectorLocs(Locs); - highlightObjCSelector(Locs, /*Decl=*/false, OME->isClassMessage()); + bool DefaultLibrary = false; + if (ObjCMethodDecl *OMD = OME->getMethodDecl()) + DefaultLibrary = isDefaultLibrary(OMD); + highlightObjCSelector(Locs, /*Decl=*/false, OME->isClassMessage(), + DefaultLibrary); return true; } @@ -643,6 +678,8 @@ Tok.addModifier(HighlightingModifier::Abstract); if (isDependent(Decl)) Tok.addModifier(HighlightingModifier::DependentName); + if (isDefaultLibrary(Decl)) + Tok.addModifier(HighlightingModifier::DefaultLibrary); if (Decl->isDeprecated()) Tok.addModifier(HighlightingModifier::Deprecated); // Do not treat an UnresolvedUsingValueDecl as a declaration. @@ -827,6 +864,8 @@ return "abstract"; case HighlightingModifier::DependentName: return "dependentName"; // nonstandard + case HighlightingModifier::DefaultLibrary: + return "defaultLibrary"; case HighlightingModifier::FunctionScope: return "functionScope"; // nonstandard case HighlightingModifier::ClassScope: 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 @@ -89,6 +89,7 @@ # CHECK-NEXT: "static", # CHECK-NEXT: "abstract", # CHECK-NEXT: "dependentName", +# CHECK-NEXT: "defaultLibrary", # CHECK-NEXT: "functionScope", # CHECK-NEXT: "classScope", # CHECK-NEXT: "fileScope", diff --git a/clang-tools-extra/clangd/test/semantic-tokens.test b/clang-tools-extra/clangd/test/semantic-tokens.test --- a/clang-tools-extra/clangd/test/semantic-tokens.test +++ b/clang-tools-extra/clangd/test/semantic-tokens.test @@ -23,7 +23,7 @@ # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 1025 +# CHECK-NEXT: 2049 # CHECK-NEXT: ], # CHECK-NEXT: "resultId": "1" # CHECK-NEXT: } @@ -49,7 +49,7 @@ # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 1025 +# CHECK-NEXT: 2049 # CHECK-NEXT: ], # Inserted at position 1 # CHECK-NEXT: "deleteCount": 0, @@ -72,12 +72,12 @@ # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 1025, +# CHECK-NEXT: 2049, # CHECK-NEXT: 1, # CHECK-NEXT: 4, # CHECK-NEXT: 1, # CHECK-NEXT: 0, -# CHECK-NEXT: 1025 +# CHECK-NEXT: 2049 # CHECK-NEXT: ], # CHECK-NEXT: "resultId": "3" # CHECK-NEXT: } 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( @@ -746,6 +749,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) {