diff --git a/clang-tools-extra/clangd/Hover.h b/clang-tools-extra/clangd/Hover.h --- a/clang-tools-extra/clangd/Hover.h +++ b/clang-tools-extra/clangd/Hover.h @@ -59,6 +59,8 @@ /// Source code containing the definition of the symbol. std::string Definition; + /// Access specifier. Applies to members of class/structs or unions. + AccessSpecifier AccessSpecifier = AccessSpecifier::AS_none; /// Pretty-printed variable type. /// Set only for variables. llvm::Optional Type; diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -468,6 +468,7 @@ HoverInfo HI; const ASTContext &Ctx = D->getASTContext(); + HI.AccessSpecifier = D->getAccess(); HI.NamespaceScope = getNamespaceScope(D); if (!HI.NamespaceScope->empty()) HI.NamespaceScope->append("::"); @@ -676,6 +677,20 @@ } } +StringRef getAccessString(AccessSpecifier AS) { + switch (AS) { + case AccessSpecifier::AS_public: + return "public"; + case AccessSpecifier::AS_protected: + return "protected"; + case AccessSpecifier::AS_private: + return "private"; + case AccessSpecifier::AS_none: + return {}; + } + llvm_unreachable("Unknown AccessSpecifier"); +} + } // namespace llvm::Optional getHover(ParsedAST &AST, Position Pos, @@ -774,6 +789,8 @@ // level 1 and 2 headers in a huge font, see // https://github.com/microsoft/vscode/issues/88417 for details. markup::Paragraph &Header = Output.addHeading(3); + if (AccessSpecifier != AccessSpecifier::AS_none) + Header.appendText(getAccessString(AccessSpecifier)).appendSpace(); if (Kind != index::SymbolKind::Unknown) Header.appendText(index::getSymbolKindString(Kind)).appendSpace(); assert(!Name.empty() && "hover triggered on a nameless symbol"); diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -12,6 +12,7 @@ #include "TestIndex.h" #include "TestTU.h" #include "index/MemIndex.h" +#include "clang/Basic/Specifiers.h" #include "clang/Index/IndexSymbol.h" #include "llvm/ADT/None.h" #include "llvm/ADT/StringRef.h" @@ -1964,7 +1965,51 @@ // In test::Bar def)", }, - }; + { + [](HoverInfo &HI) { + HI.Kind = index::SymbolKind::Field; + HI.AccessSpecifier = AccessSpecifier::AS_public; + HI.Name = "foo"; + HI.LocalScope = "test::Bar::"; + HI.Definition = "def"; + }, + R"(public field foo + +// In test::Bar +def)", + }, + { + [](HoverInfo &HI) { + HI.Definition = "int method()"; + HI.AccessSpecifier = AccessSpecifier::AS_protected; + HI.Kind = index::SymbolKind::InstanceMethod; + HI.NamespaceScope = ""; + HI.LocalScope = "cls::"; + HI.Name = "method"; + HI.Parameters.emplace(); + HI.ReturnType = "int"; + HI.Type = "int ()"; + }, + R"(protected instance-method method + +→ int + +// In cls +int method())", + }, + { + [](HoverInfo &HI) { + HI.Kind = index::SymbolKind::Union; + HI.AccessSpecifier = AccessSpecifier::AS_private; + HI.Name = "foo"; + HI.NamespaceScope = "ns1::"; + HI.Definition = "union foo {}"; + }, + R"(private union foo + +// In namespace ns1 +union foo {})", + }}; for (const auto &C : Cases) { HoverInfo HI;