diff --git a/clang-tools-extra/clang-doc/Generators.h b/clang-tools-extra/clang-doc/Generators.h --- a/clang-tools-extra/clang-doc/Generators.h +++ b/clang-tools-extra/clang-doc/Generators.h @@ -42,8 +42,6 @@ llvm::Expected> findGeneratorByName(llvm::StringRef Format); -std::string getAccess(AccessSpecifier AS); - std::string getTagType(TagTypeKind AS); } // namespace doc diff --git a/clang-tools-extra/clang-doc/Generators.cpp b/clang-tools-extra/clang-doc/Generators.cpp --- a/clang-tools-extra/clang-doc/Generators.cpp +++ b/clang-tools-extra/clang-doc/Generators.cpp @@ -27,20 +27,6 @@ // Enum conversion -std::string getAccess(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"); -} - std::string getTagType(TagTypeKind AS) { switch (AS) { case TagTypeKind::TTK_Class: diff --git a/clang-tools-extra/clang-doc/HTMLGenerator.cpp b/clang-tools-extra/clang-doc/HTMLGenerator.cpp --- a/clang-tools-extra/clang-doc/HTMLGenerator.cpp +++ b/clang-tools-extra/clang-doc/HTMLGenerator.cpp @@ -402,7 +402,7 @@ Out.emplace_back(std::make_unique(HTMLTag::TAG_UL)); auto &ULBody = Out.back(); for (const auto &M : Members) { - std::string Access = getAccess(M.Access); + std::string Access = std::string(getAccess(M.Access)); if (Access != "") Access = Access + " "; auto LIBody = std::make_unique(HTMLTag::TAG_LI); @@ -679,7 +679,7 @@ Out.emplace_back(std::make_unique(HTMLTag::TAG_P)); auto &FunctionHeader = Out.back(); - std::string Access = getAccess(I.Access); + std::string Access = std::string(getAccess(I.Access)); if (Access != "") FunctionHeader->Children.emplace_back( std::make_unique(Access + " ")); diff --git a/clang-tools-extra/clang-doc/MDGenerator.cpp b/clang-tools-extra/clang-doc/MDGenerator.cpp --- a/clang-tools-extra/clang-doc/MDGenerator.cpp +++ b/clang-tools-extra/clang-doc/MDGenerator.cpp @@ -157,7 +157,7 @@ First = false; } writeHeader(I.Name, 3, OS); - std::string Access = getAccess(I.Access); + std::string Access = std::string(getAccess(I.Access)); if (Access != "") writeLine(genItalic(Access + " " + I.ReturnType.Type.Name + " " + I.Name + "(" + Stream.str() + ")"), @@ -250,7 +250,7 @@ if (!I.Members.empty()) { writeHeader("Members", 2, OS); for (const auto &Member : I.Members) { - std::string Access = getAccess(Member.Access); + std::string Access = std::string(getAccess(Member.Access)); if (Access != "") writeLine(Access + " " + Member.Type.Name + " " + Member.Name, OS); else 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,8 +59,9 @@ /// 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; + /// Access specifier for declarations inside class/struct/unions, empty for + /// others. + std::string AccessSpecifier; /// 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,7 +468,7 @@ HoverInfo HI; const ASTContext &Ctx = D->getASTContext(); - HI.AccessSpecifier = D->getAccess(); + HI.AccessSpecifier = std::string(getAccess(D->getAccess())); HI.NamespaceScope = getNamespaceScope(D); if (!HI.NamespaceScope->empty()) HI.NamespaceScope->append("::"); @@ -677,20 +677,6 @@ } } -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, @@ -789,8 +775,6 @@ // 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"); @@ -852,9 +836,12 @@ ScopeComment = "// In namespace " + llvm::StringRef(*NamespaceScope).rtrim(':').str() + '\n'; } + std::string DefinitionWithAccess = !AccessSpecifier.empty() + ? AccessSpecifier + ": " + Definition + : Definition; // Note that we don't print anything for global namespace, to not annoy // non-c++ projects or projects that are not making use of namespaces. - Output.addCodeBlock(ScopeComment + Definition); + Output.addCodeBlock(ScopeComment + DefinitionWithAccess); } return Output; } 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 @@ -80,6 +80,7 @@ HI.Type = "char"; HI.Offset = 0; HI.Size = 1; + HI.AccessSpecifier = "public"; }}, // Local to class method. {R"cpp( @@ -116,6 +117,7 @@ HI.Type = "char"; HI.Offset = 0; HI.Size = 1; + HI.AccessSpecifier = "public"; }}, // Struct definition shows size. {R"cpp( @@ -345,6 +347,7 @@ HI.Kind = index::SymbolKind::Constructor; HI.Definition = "X()"; HI.Parameters.emplace(); + HI.AccessSpecifier = "public"; }}, {"class X { [[^~]]X(); };", // FIXME: Should be [[~X]]() [](HoverInfo &HI) { @@ -354,6 +357,7 @@ HI.Kind = index::SymbolKind::Destructor; HI.Definition = "~X()"; HI.Parameters.emplace(); + HI.AccessSpecifier = "private"; }}, {"class X { [[op^erator]] int(); };", [](HoverInfo &HI) { @@ -363,6 +367,7 @@ HI.Kind = index::SymbolKind::ConversionFunction; HI.Definition = "operator int()"; HI.Parameters.emplace(); + HI.AccessSpecifier = "private"; }}, {"class X { operator [[^X]](); };", [](HoverInfo &HI) { @@ -495,6 +500,7 @@ HI.NamespaceScope = ""; HI.LocalScope = "Add<1, 2>::"; HI.Value = "3"; + HI.AccessSpecifier = "public"; }}, {R"cpp( constexpr int answer() { return 40 + 2; } @@ -607,6 +613,7 @@ HI.Definition = "typename T = int"; HI.LocalScope = "foo::"; HI.Type = "typename"; + HI.AccessSpecifier = "public"; }}, {// TemplateTemplate Type Parameter R"cpp( @@ -619,6 +626,7 @@ HI.Definition = "template class T"; HI.LocalScope = "foo::"; HI.Type = "template class"; + HI.AccessSpecifier = "public"; }}, {// NonType Template Parameter R"cpp( @@ -631,6 +639,7 @@ HI.Definition = "int T = 5"; HI.LocalScope = "foo::"; HI.Type = "int"; + HI.AccessSpecifier = "public"; }}, {// Getter @@ -647,6 +656,7 @@ HI.Type = "float ()"; HI.ReturnType = "float"; HI.Parameters.emplace(); + HI.AccessSpecifier = "public"; }}, {// Setter R"cpp( @@ -665,6 +675,7 @@ HI.Parameters->emplace_back(); HI.Parameters->back().Type = "float"; HI.Parameters->back().Name = "v"; + HI.AccessSpecifier = "public"; }}, {// Setter (builder) R"cpp( @@ -683,6 +694,7 @@ HI.Parameters->emplace_back(); HI.Parameters->back().Type = "float"; HI.Parameters->back().Name = "v"; + HI.AccessSpecifier = "public"; }}, }; for (const auto &Case : Cases) { @@ -716,6 +728,7 @@ EXPECT_EQ(H->Value, Expected.Value); EXPECT_EQ(H->Size, Expected.Size); EXPECT_EQ(H->Offset, Expected.Offset); + EXPECT_EQ(H->AccessSpecifier, Expected.AccessSpecifier); } } @@ -1968,20 +1981,20 @@ { [](HoverInfo &HI) { HI.Kind = index::SymbolKind::Field; - HI.AccessSpecifier = AccessSpecifier::AS_public; + HI.AccessSpecifier = "public"; HI.Name = "foo"; HI.LocalScope = "test::Bar::"; HI.Definition = "def"; }, - R"(public field foo + R"(field foo // In test::Bar -def)", +public: def)", }, { [](HoverInfo &HI) { HI.Definition = "int method()"; - HI.AccessSpecifier = AccessSpecifier::AS_protected; + HI.AccessSpecifier = "protected"; HI.Kind = index::SymbolKind::InstanceMethod; HI.NamespaceScope = ""; HI.LocalScope = "cls::"; @@ -1990,25 +2003,25 @@ HI.ReturnType = "int"; HI.Type = "int ()"; }, - R"(protected instance-method method + R"(instance-method method → int // In cls -int method())", +protected: int method())", }, { [](HoverInfo &HI) { HI.Kind = index::SymbolKind::Union; - HI.AccessSpecifier = AccessSpecifier::AS_private; + HI.AccessSpecifier = "private"; HI.Name = "foo"; HI.NamespaceScope = "ns1::"; HI.Definition = "union foo {}"; }, - R"(private union foo + R"(union foo // In namespace ns1 -union foo {})", +private: union foo {})", }}; for (const auto &C : Cases) { diff --git a/clang/include/clang/Basic/Specifiers.h b/clang/include/clang/Basic/Specifiers.h --- a/clang/include/clang/Basic/Specifiers.h +++ b/clang/include/clang/Basic/Specifiers.h @@ -365,6 +365,20 @@ }; llvm::StringRef getParameterABISpelling(ParameterABI kind); + + inline llvm::StringRef getAccess(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"); + } } // end namespace clang #endif // LLVM_CLANG_BASIC_SPECIFIERS_H