forked from OSchip/llvm-project
[AST][clangd] Expose documentation of Attrs on hover.
This adds a method to Attr to get at the documentation programmatically. Differential Revision: https://reviews.llvm.org/D107703
This commit is contained in:
parent
2f1ee56f3c
commit
18f9e25ce1
|
@ -731,7 +731,7 @@ llvm::Optional<HoverInfo> getHoverContents(const Attr *A, ParsedAST &AST) {
|
|||
llvm::raw_string_ostream OS(HI.Definition);
|
||||
A->printPretty(OS, AST.getASTContext().getPrintingPolicy());
|
||||
}
|
||||
// FIXME: attributes have documentation, can we get at that?
|
||||
HI.Documentation = Attr::getDocumentation(A->getKind()).str();
|
||||
return HI;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "TestIndex.h"
|
||||
#include "TestTU.h"
|
||||
#include "index/MemIndex.h"
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "clang/Index/IndexSymbol.h"
|
||||
#include "llvm/ADT/None.h"
|
||||
|
@ -2384,7 +2385,7 @@ TEST(Hover, All) {
|
|||
HI.Name = "nonnull";
|
||||
HI.Kind = index::SymbolKind::Unknown; // FIXME: no suitable value
|
||||
HI.Definition = "__attribute__((nonnull))";
|
||||
HI.Documentation = ""; // FIXME
|
||||
HI.Documentation = Attr::getDocumentation(attr::NonNull).str();
|
||||
}},
|
||||
};
|
||||
|
||||
|
|
|
@ -109,6 +109,8 @@ public:
|
|||
|
||||
// Pretty print this attribute.
|
||||
void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
|
||||
|
||||
static StringRef getDocumentation(attr::Kind);
|
||||
};
|
||||
|
||||
class TypeAttr : public Attr {
|
||||
|
|
|
@ -13,6 +13,11 @@ clang_tablegen(Opcodes.inc
|
|||
SOURCE Interp/Opcodes.td
|
||||
TARGET Opcodes)
|
||||
|
||||
clang_tablegen(AttrDocTable.cpp -gen-clang-attr-doc-table
|
||||
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../include/
|
||||
SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/../../include/clang/Basic/Attr.td
|
||||
TARGET ClangAttrDocTable)
|
||||
|
||||
add_clang_library(clangAST
|
||||
APValue.cpp
|
||||
ASTConcept.cpp
|
||||
|
@ -24,6 +29,7 @@ add_clang_library(clangAST
|
|||
ASTImporterLookupTable.cpp
|
||||
ASTStructuralEquivalence.cpp
|
||||
ASTTypeTraits.cpp
|
||||
AttrDocTable.cpp
|
||||
AttrImpl.cpp
|
||||
Comment.cpp
|
||||
CommentBriefParser.cpp
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
//===- unittests/AST/AttrTests.cpp --- Attribute tests --------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/Basic/AttrKinds.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(Attr, Doc) {
|
||||
EXPECT_THAT(Attr::getDocumentation(attr::Used).str(),
|
||||
testing::HasSubstr("The compiler must emit the definition even "
|
||||
"if it appears to be unused"));
|
||||
}
|
||||
|
||||
} // namespace
|
|
@ -15,6 +15,7 @@ add_clang_unittest(ASTTests
|
|||
ASTTraverserTest.cpp
|
||||
ASTTypeTraitsTest.cpp
|
||||
ASTVectorTest.cpp
|
||||
AttrTest.cpp
|
||||
CommentLexer.cpp
|
||||
CommentParser.cpp
|
||||
CommentTextTest.cpp
|
||||
|
|
|
@ -4210,6 +4210,42 @@ void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records,
|
|||
getPragmaAttributeSupport(Records).generateParsingHelpers(OS);
|
||||
}
|
||||
|
||||
void EmitClangAttrDocTable(RecordKeeper &Records, raw_ostream &OS) {
|
||||
emitSourceFileHeader("Clang attribute documentation", OS);
|
||||
|
||||
OS << R"cpp(
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
)cpp";
|
||||
std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr");
|
||||
for (const auto *A : Attrs) {
|
||||
if (!A->getValueAsBit("ASTNode"))
|
||||
continue;
|
||||
std::vector<Record *> Docs = A->getValueAsListOfDefs("Documentation");
|
||||
for (const auto *D : Docs) {
|
||||
OS << "\nstatic const char AttrDoc_" << A->getName() << "[] = "
|
||||
<< "R\"reST("
|
||||
<< D->getValueAsOptionalString("Content").getValueOr("").trim()
|
||||
<< ")reST\";\n";
|
||||
// Only look at the first documentation if there are several.
|
||||
// (Currently there's only one such attr, revisit if this becomes common).
|
||||
break;
|
||||
}
|
||||
}
|
||||
OS << R"cpp(
|
||||
static const llvm::StringRef AttrDoc[] = {
|
||||
#define ATTR(NAME) AttrDoc_##NAME,
|
||||
#include "clang/Basic/AttrList.inc"
|
||||
};
|
||||
|
||||
llvm::StringRef clang::Attr::getDocumentation(clang::attr::Kind K) {
|
||||
if(K < llvm::array_lengthof(AttrDoc))
|
||||
return AttrDoc[K];
|
||||
return "";
|
||||
}
|
||||
)cpp";
|
||||
}
|
||||
|
||||
enum class SpellingKind {
|
||||
GNU,
|
||||
CXX11,
|
||||
|
|
|
@ -30,6 +30,7 @@ enum ActionType {
|
|||
GenClangAttrSubjectMatchRulesParserStringSwitches,
|
||||
GenClangAttrImpl,
|
||||
GenClangAttrList,
|
||||
GenClangAttrDocTable,
|
||||
GenClangAttrSubjectMatchRuleList,
|
||||
GenClangAttrPCHRead,
|
||||
GenClangAttrPCHWrite,
|
||||
|
@ -115,6 +116,8 @@ cl::opt<ActionType> Action(
|
|||
"Generate clang attribute implementations"),
|
||||
clEnumValN(GenClangAttrList, "gen-clang-attr-list",
|
||||
"Generate a clang attribute list"),
|
||||
clEnumValN(GenClangAttrDocTable, "gen-clang-attr-doc-table",
|
||||
"Generate a table of attribute documentation"),
|
||||
clEnumValN(GenClangAttrSubjectMatchRuleList,
|
||||
"gen-clang-attr-subject-match-rule-list",
|
||||
"Generate a clang attribute subject match rule list"),
|
||||
|
@ -280,6 +283,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
|
|||
case GenClangAttrList:
|
||||
EmitClangAttrList(Records, OS);
|
||||
break;
|
||||
case GenClangAttrDocTable:
|
||||
EmitClangAttrDocTable(Records, OS);
|
||||
break;
|
||||
case GenClangAttrSubjectMatchRuleList:
|
||||
EmitClangAttrSubjectMatchRuleList(Records, OS);
|
||||
break;
|
||||
|
|
|
@ -61,6 +61,7 @@ void EmitClangAttrTextNodeDump(llvm::RecordKeeper &Records,
|
|||
llvm::raw_ostream &OS);
|
||||
void EmitClangAttrNodeTraverse(llvm::RecordKeeper &Records,
|
||||
llvm::raw_ostream &OS);
|
||||
void EmitClangAttrDocTable(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
|
||||
|
||||
void EmitClangDiagsDefs(llvm::RecordKeeper &Records, llvm::raw_ostream &OS,
|
||||
const std::string &Component);
|
||||
|
|
Loading…
Reference in New Issue