dgoldman created this revision. dgoldman added reviewers: sammccall, kadircet. Herald added subscribers: usaxena95, jfb, arphaman. dgoldman requested review of this revision. Herald added subscribers: cfe-commits, MaskRay, ilya-biryukov. Herald added a project: clang-tools-extra.
This allows us to differentiate symbols from the system (e.g. system includes or sysroot) differently than symbols defined in the user's project, which can be used by editors to display them differently. This is currently based on `FileCharacteristic`, but we can consider alternatives such as `Sysroot` and file paths in the future. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D101554 Files: clang-tools-extra/clangd/SemanticHighlighting.cpp clang-tools-extra/clangd/SemanticHighlighting.h clang-tools-extra/clangd/test/initialize-params.test clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
Index: clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp +++ clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp @@ -69,13 +69,16 @@ std::vector<std::pair</*FileName*/ llvm::StringRef, /*FileContent*/ llvm::StringRef>> AdditionalFiles = {}, - uint32_t ModifierMask = -1) { + uint32_t ModifierMask = -1, + std::vector<std::string> 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) { Index: clang-tools-extra/clangd/test/initialize-params.test =================================================================== --- clang-tools-extra/clangd/test/initialize-params.test +++ 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", Index: clang-tools-extra/clangd/SemanticHighlighting.h =================================================================== --- clang-tools-extra/clangd/SemanticHighlighting.h +++ clang-tools-extra/clangd/SemanticHighlighting.h @@ -72,8 +72,9 @@ ClassScope, FileScope, GlobalScope, + DefaultLibrary, - LastModifier = GlobalScope + LastModifier = DefaultLibrary }; static_assert(static_cast<unsigned>(HighlightingModifier::LastModifier) < 32, "Increase width of modifiers bitfield!"); Index: clang-tools-extra/clangd/SemanticHighlighting.cpp =================================================================== --- clang-tools-extra/clangd/SemanticHighlighting.cpp +++ 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<HighlightingModifier> scopeModifier(const NamedDecl *D) { +llvm::Optional<HighlightingModifier> +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<RecordDecl>(D)) @@ -447,15 +461,18 @@ return HighlightingModifier::GlobalScope; } -llvm::Optional<HighlightingModifier> scopeModifier(const Type *T) { +llvm::Optional<HighlightingModifier> +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<TemplateTypeParmType>(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<ObjCObjectType>(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<SourceLocation> &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<SourceLocation> 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<SourceLocation> 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"); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits