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);
|
llvm::raw_string_ostream OS(HI.Definition);
|
||||||
A->printPretty(OS, AST.getASTContext().getPrintingPolicy());
|
A->printPretty(OS, AST.getASTContext().getPrintingPolicy());
|
||||||
}
|
}
|
||||||
// FIXME: attributes have documentation, can we get at that?
|
HI.Documentation = Attr::getDocumentation(A->getKind()).str();
|
||||||
return HI;
|
return HI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "TestIndex.h"
|
#include "TestIndex.h"
|
||||||
#include "TestTU.h"
|
#include "TestTU.h"
|
||||||
#include "index/MemIndex.h"
|
#include "index/MemIndex.h"
|
||||||
|
#include "clang/AST/Attr.h"
|
||||||
#include "clang/Basic/Specifiers.h"
|
#include "clang/Basic/Specifiers.h"
|
||||||
#include "clang/Index/IndexSymbol.h"
|
#include "clang/Index/IndexSymbol.h"
|
||||||
#include "llvm/ADT/None.h"
|
#include "llvm/ADT/None.h"
|
||||||
|
@ -2384,7 +2385,7 @@ TEST(Hover, All) {
|
||||||
HI.Name = "nonnull";
|
HI.Name = "nonnull";
|
||||||
HI.Kind = index::SymbolKind::Unknown; // FIXME: no suitable value
|
HI.Kind = index::SymbolKind::Unknown; // FIXME: no suitable value
|
||||||
HI.Definition = "__attribute__((nonnull))";
|
HI.Definition = "__attribute__((nonnull))";
|
||||||
HI.Documentation = ""; // FIXME
|
HI.Documentation = Attr::getDocumentation(attr::NonNull).str();
|
||||||
}},
|
}},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -109,6 +109,8 @@ public:
|
||||||
|
|
||||||
// Pretty print this attribute.
|
// Pretty print this attribute.
|
||||||
void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
|
void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const;
|
||||||
|
|
||||||
|
static StringRef getDocumentation(attr::Kind);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TypeAttr : public Attr {
|
class TypeAttr : public Attr {
|
||||||
|
|
|
@ -13,6 +13,11 @@ clang_tablegen(Opcodes.inc
|
||||||
SOURCE Interp/Opcodes.td
|
SOURCE Interp/Opcodes.td
|
||||||
TARGET Opcodes)
|
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
|
add_clang_library(clangAST
|
||||||
APValue.cpp
|
APValue.cpp
|
||||||
ASTConcept.cpp
|
ASTConcept.cpp
|
||||||
|
@ -24,6 +29,7 @@ add_clang_library(clangAST
|
||||||
ASTImporterLookupTable.cpp
|
ASTImporterLookupTable.cpp
|
||||||
ASTStructuralEquivalence.cpp
|
ASTStructuralEquivalence.cpp
|
||||||
ASTTypeTraits.cpp
|
ASTTypeTraits.cpp
|
||||||
|
AttrDocTable.cpp
|
||||||
AttrImpl.cpp
|
AttrImpl.cpp
|
||||||
Comment.cpp
|
Comment.cpp
|
||||||
CommentBriefParser.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
|
ASTTraverserTest.cpp
|
||||||
ASTTypeTraitsTest.cpp
|
ASTTypeTraitsTest.cpp
|
||||||
ASTVectorTest.cpp
|
ASTVectorTest.cpp
|
||||||
|
AttrTest.cpp
|
||||||
CommentLexer.cpp
|
CommentLexer.cpp
|
||||||
CommentParser.cpp
|
CommentParser.cpp
|
||||||
CommentTextTest.cpp
|
CommentTextTest.cpp
|
||||||
|
|
|
@ -4210,6 +4210,42 @@ void EmitClangAttrSubjectMatchRulesParserStringSwitches(RecordKeeper &Records,
|
||||||
getPragmaAttributeSupport(Records).generateParsingHelpers(OS);
|
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 {
|
enum class SpellingKind {
|
||||||
GNU,
|
GNU,
|
||||||
CXX11,
|
CXX11,
|
||||||
|
|
|
@ -30,6 +30,7 @@ enum ActionType {
|
||||||
GenClangAttrSubjectMatchRulesParserStringSwitches,
|
GenClangAttrSubjectMatchRulesParserStringSwitches,
|
||||||
GenClangAttrImpl,
|
GenClangAttrImpl,
|
||||||
GenClangAttrList,
|
GenClangAttrList,
|
||||||
|
GenClangAttrDocTable,
|
||||||
GenClangAttrSubjectMatchRuleList,
|
GenClangAttrSubjectMatchRuleList,
|
||||||
GenClangAttrPCHRead,
|
GenClangAttrPCHRead,
|
||||||
GenClangAttrPCHWrite,
|
GenClangAttrPCHWrite,
|
||||||
|
@ -115,6 +116,8 @@ cl::opt<ActionType> Action(
|
||||||
"Generate clang attribute implementations"),
|
"Generate clang attribute implementations"),
|
||||||
clEnumValN(GenClangAttrList, "gen-clang-attr-list",
|
clEnumValN(GenClangAttrList, "gen-clang-attr-list",
|
||||||
"Generate a clang attribute list"),
|
"Generate a clang attribute list"),
|
||||||
|
clEnumValN(GenClangAttrDocTable, "gen-clang-attr-doc-table",
|
||||||
|
"Generate a table of attribute documentation"),
|
||||||
clEnumValN(GenClangAttrSubjectMatchRuleList,
|
clEnumValN(GenClangAttrSubjectMatchRuleList,
|
||||||
"gen-clang-attr-subject-match-rule-list",
|
"gen-clang-attr-subject-match-rule-list",
|
||||||
"Generate a clang attribute 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:
|
case GenClangAttrList:
|
||||||
EmitClangAttrList(Records, OS);
|
EmitClangAttrList(Records, OS);
|
||||||
break;
|
break;
|
||||||
|
case GenClangAttrDocTable:
|
||||||
|
EmitClangAttrDocTable(Records, OS);
|
||||||
|
break;
|
||||||
case GenClangAttrSubjectMatchRuleList:
|
case GenClangAttrSubjectMatchRuleList:
|
||||||
EmitClangAttrSubjectMatchRuleList(Records, OS);
|
EmitClangAttrSubjectMatchRuleList(Records, OS);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -61,6 +61,7 @@ void EmitClangAttrTextNodeDump(llvm::RecordKeeper &Records,
|
||||||
llvm::raw_ostream &OS);
|
llvm::raw_ostream &OS);
|
||||||
void EmitClangAttrNodeTraverse(llvm::RecordKeeper &Records,
|
void EmitClangAttrNodeTraverse(llvm::RecordKeeper &Records,
|
||||||
llvm::raw_ostream &OS);
|
llvm::raw_ostream &OS);
|
||||||
|
void EmitClangAttrDocTable(llvm::RecordKeeper &Records, llvm::raw_ostream &OS);
|
||||||
|
|
||||||
void EmitClangDiagsDefs(llvm::RecordKeeper &Records, llvm::raw_ostream &OS,
|
void EmitClangDiagsDefs(llvm::RecordKeeper &Records, llvm::raw_ostream &OS,
|
||||||
const std::string &Component);
|
const std::string &Component);
|
||||||
|
|
Loading…
Reference in New Issue