22#include "clang/Tooling/CompilationDatabase.h"
23#include "llvm/ADT/StringRef.h"
24#include "llvm/Support/Allocator.h"
25#include "llvm/Support/StringSaver.h"
26#include "llvm/Support/YAMLTraits.h"
27#include "llvm/Support/raw_ostream.h"
32struct YIncludeHeaderWithReferences;
37LLVM_YAML_IS_SEQUENCE_VECTOR(YIncludeHeaderWithReferences)
41 std::pair<clang::clangd::SymbolID, std::vector<clang::clangd::Ref>>;
44 std::optional<clang::clangd::Symbol> Symbol;
45 std::optional<RefBundle> Refs;
46 std::optional<clang::clangd::Relation> Relation;
47 std::optional<clang::clangd::IncludeGraphNode> Source;
48 std::optional<clang::tooling::CompileCommand> Cmd;
58struct YIncludeHeaderWithReferences {
59 llvm::StringRef IncludeHeader;
63 YIncludeHeaderWithReferences() =
default;
65 YIncludeHeaderWithReferences(
66 llvm::StringRef IncludeHeader, uint32_t References,
68 : IncludeHeader(IncludeHeader), References(References),
69 SupportedDirectives(SupportedDirectives) {}
73struct CompileCommandYAML : clang::tooling::CompileCommand {};
81using clang::clangd::IncludeGraphNode;
82using clang::clangd::Ref;
84using clang::clangd::Relation;
86using clang::clangd::Symbol;
87using clang::clangd::SymbolID;
88using clang::clangd::SymbolLocation;
89using clang::index::SymbolInfo;
90using clang::index::SymbolKind;
91using clang::index::SymbolLanguage;
92using clang::tooling::CompileCommand;
105 I.setError(llvm::toString(ID.takeError()));
117 Flag =
static_cast<uint8_t
>(F);
127template <>
struct MappingTraits<YPosition> {
128 static void mapping(IO &IO, YPosition &Value) {
129 IO.mapRequired(
"Line", Value.Line);
130 IO.mapRequired(
"Column", Value.Column);
156 assert(IO.getContext() &&
157 "Expecting an UniqueStringSaver to allocate data");
158 return static_cast<llvm::UniqueStringSaver *
>(IO.getContext())
168 MappingNormalization<NormalizedFileURI, const char *> NFile(IO,
170 IO.mapRequired(
"FileURI", NFile->URI);
171 MappingNormalization<NormalizedPosition, SymbolLocation::Position> NStart(
173 IO.mapRequired(
"Start", NStart->P);
174 MappingNormalization<NormalizedPosition, SymbolLocation::Position> NEnd(
176 IO.mapRequired(
"End", NEnd->P);
183 IO.mapRequired(
"Kind", SymInfo.Kind);
184 IO.mapRequired(
"Lang", SymInfo.Lang);
188template <>
struct ScalarBitSetTraits<
clang::clangd::Symbol::IncludeDirective> {
195template <>
struct MappingTraits<YIncludeHeaderWithReferences> {
196 static void mapping(IO &IO, YIncludeHeaderWithReferences &Inc) {
197 IO.mapRequired(
"Header", Inc.IncludeHeader);
198 IO.mapRequired(
"References", Inc.References);
199 IO.mapOptional(
"Directives", Inc.SupportedDirectives,
208 IO &,
const llvm::SmallVector<IncludeHeader, 1> &IncludeHeaders) {
209 for (
auto &I : IncludeHeaders) {
210 Headers.emplace_back(I.IncludeHeader, I.References,
211 I.supportedDirectives());
216 llvm::SmallVector<IncludeHeader, 1> Result;
218 Result.emplace_back(H.IncludeHeader, H.References, H.SupportedDirectives);
221 llvm::SmallVector<YIncludeHeaderWithReferences, 1>
Headers;
224template <>
struct MappingTraits<
Symbol> {
226 MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(IO, Sym.
ID);
227 MappingNormalization<NormalizedSymbolFlag, Symbol::SymbolFlag> NSymbolFlag(
229 MappingNormalization<
231 llvm::SmallVector<Symbol::IncludeHeaderWithReferences, 1>>
233 IO.mapRequired(
"ID", NSymbolID->HexString);
234 IO.mapRequired(
"Name", Sym.
Name);
235 IO.mapRequired(
"Scope", Sym.
Scope);
236 IO.mapRequired(
"SymInfo", Sym.
SymInfo);
240 IO.mapOptional(
"References", Sym.
References, 0u);
241 IO.mapOptional(
"Flags", NSymbolFlag->Flag);
242 IO.mapOptional(
"Signature", Sym.
Signature);
243 IO.mapOptional(
"TemplateSpecializationArgs",
248 IO.mapOptional(
"Type", Sym.
Type);
249 IO.mapOptional(
"Tags", Sym.
Tags);
250 IO.mapOptional(
"IncludeHeaders", NIncludeHeaders->Headers);
254template <>
struct ScalarEnumerationTraits<SymbolLanguage> {
256 IO.enumCase(Value,
"C", SymbolLanguage::C);
257 IO.enumCase(Value,
"Cpp", SymbolLanguage::CXX);
258 IO.enumCase(Value,
"ObjC", SymbolLanguage::ObjC);
259 IO.enumCase(Value,
"Swift", SymbolLanguage::Swift);
265#define DEFINE_ENUM_FINAL(name) \
266 case SymbolKind::name: \
267 IO.enumCase(Value, #name, SymbolKind::name)
268#define DEFINE_ENUM(name) \
269 DEFINE_ENUM_FINAL(name); \
309#undef DEFINE_ENUM_FINAL
313template <>
struct MappingTraits<RefBundle> {
314 static void mapping(IO &IO, RefBundle &Refs) {
315 MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(IO,
317 IO.mapRequired(
"ID", NSymbolID->HexString);
318 IO.mapRequired(
"References", Refs.second);
331template <>
struct MappingTraits<
Ref> {
333 MappingNormalization<NormalizedRefKind, RefKind> NKind(IO, R.
Kind);
334 IO.mapRequired(
"Kind", NKind->Kind);
335 IO.mapRequired(
"Location", R.
Location);
336 IO.mapOptional(
"Container", R.
Container);
343 Kind =
static_cast<uint8_t
>(R);
353 MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(IO, ID);
354 IO.mapRequired(
"ID", NSymbolID->HexString);
360 MappingNormalization<NormalizedSymbolRole, RelationKind> NRole(
363 IO.mapRequired(
"Predicate", NRole->Kind);
371 Flag =
static_cast<uint8_t
>(O);
389 if (
HexString.size() == Digest.size() * 2 &&
390 llvm::all_of(
HexString, llvm::isHexDigit)) {
391 memcpy(Digest.data(), llvm::fromHex(
HexString).data(), Digest.size());
393 I.setError(std::string(
"Bad hex file digest: ") +
HexString);
403 IO.mapRequired(
"URI", Node.
URI);
404 MappingNormalization<NormalizedSourceFlag, IncludeGraphNode::SourceFlag>
405 NSourceFlag(IO, Node.
Flags);
406 IO.mapRequired(
"Flags", NSourceFlag->Flag);
407 MappingNormalization<NormalizedFileDigest, FileDigest> NDigest(IO,
409 IO.mapRequired(
"Digest", NDigest->HexString);
414template <>
struct MappingTraits<CompileCommandYAML> {
415 static void mapping(IO &IO, CompileCommandYAML &Cmd) {
416 IO.mapRequired(
"Directory", Cmd.Directory);
417 IO.mapRequired(
"CommandLine", Cmd.CommandLine);
421template <>
struct MappingTraits<VariantEntry> {
422 static void mapping(IO &IO, VariantEntry &Variant) {
423 if (IO.mapTag(
"!Symbol", Variant.Symbol.has_value())) {
424 if (!IO.outputting())
425 Variant.Symbol.emplace();
426 MappingTraits<Symbol>::mapping(IO, *Variant.Symbol);
427 }
else if (IO.mapTag(
"!Refs", Variant.Refs.has_value())) {
428 if (!IO.outputting())
429 Variant.Refs.emplace();
430 MappingTraits<RefBundle>::mapping(IO, *Variant.Refs);
431 }
else if (IO.mapTag(
"!Relations", Variant.Relation.has_value())) {
432 if (!IO.outputting())
433 Variant.Relation.emplace();
434 MappingTraits<Relation>::mapping(IO, *Variant.Relation);
435 }
else if (IO.mapTag(
"!Source", Variant.Source.has_value())) {
436 if (!IO.outputting())
437 Variant.Source.emplace();
438 MappingTraits<IncludeGraphNode>::mapping(IO, *Variant.Source);
439 }
else if (IO.mapTag(
"!Cmd", Variant.Cmd.has_value())) {
440 if (!IO.outputting())
441 Variant.Cmd.emplace();
442 MappingTraits<CompileCommandYAML>::mapping(
443 IO,
static_cast<CompileCommandYAML &
>(*Variant.Cmd));
455 llvm::yaml::Output Yout(OS);
456 for (
const auto &Sym : *O.
Symbols) {
462 for (
auto &Sym : *O.
Refs) {
474 for (
const auto &Source : *O.
Sources) {
476 Entry.Source = Source.getValue();
487llvm::Expected<IndexFileIn>
readYAML(llvm::StringRef Data,
492 llvm::BumpPtrAllocator
494 llvm::UniqueStringSaver Strings(Arena);
495 llvm::yaml::Input Yin(Data, &Strings);
497 std::optional<tooling::CompileCommand> Cmd;
498 while (Yin.setCurrentDocument()) {
499 llvm::yaml::EmptyContext Ctx;
500 VariantEntry Variant;
501 yamlize(Yin, Variant,
true, Ctx);
503 return llvm::errorCodeToError(Yin.error());
505 if (Variant.Symbol) {
506 Variant.Symbol->Origin = Origin;
507 Symbols.insert(*Variant.Symbol);
510 for (
const auto &
Ref : Variant.Refs->second)
511 Refs.insert(Variant.Refs->first,
Ref);
512 if (Variant.Relation)
513 Relations.insert(*Variant.Relation);
514 if (Variant.Source) {
515 auto &IGN = *Variant.Source;
516 auto Entry = Sources.try_emplace(IGN.URI).first;
517 Entry->getValue() = std::move(IGN);
520 for (
auto &Include :
Entry->getValue().DirectIncludes)
521 Include = Sources.try_emplace(Include).first->getKey();
530 Result.
Refs.emplace(std::move(Refs).build());
531 Result.
Relations.emplace(std::move(Relations).build());
533 Result.
Sources = std::move(Sources);
534 Result.
Cmd = std::move(Cmd);
535 return std::move(Result);
541 llvm::raw_string_ostream OS(Buf);
542 llvm::yaml::Output Yout(OS);
550 RefBundle Refs = {Data.first, Data.second};
553 llvm::raw_string_ostream OS(Buf);
554 llvm::yaml::Output Yout(OS);
563 llvm::raw_string_ostream OS(Buf);
564 llvm::yaml::Output Yout(OS);
574 llvm::raw_string_ostream OS(Buf);
575 llvm::yaml::Output Yout(OS);
clang::find_all_symbols::SymbolInfo SymbolInfo
clang::find_all_symbols::SymbolInfo::SymbolKind SymbolKind
#define DEFINE_ENUM(name)
#define DEFINE_ENUM_FINAL(name)
RefSlab::Builder is a mutable container that can 'freeze' to RefSlab.
RelationSlab::Builder is a mutable container that can 'freeze' to RelationSlab.
SymbolSlab::Builder is a mutable container that can 'freeze' to SymbolSlab.
static llvm::Expected< SymbolID > fromStr(llvm::StringRef)
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
llvm::Expected< IndexFileIn > readYAML(llvm::StringRef, SymbolOrigin Origin)
llvm::StringMap< IncludeGraphNode > IncludeGraph
std::string toYAML(const Symbol &)
RefKind
Describes the kind of a cross-reference.
void writeYAML(const IndexFileOut &, llvm::raw_ostream &)
std::array< uint8_t, 8 > FileDigest
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Some operations such as code completion produce a set of candidates.
std::vector< llvm::StringRef > DirectIncludes
std::optional< RelationSlab > Relations
std::optional< SymbolSlab > Symbols
std::optional< RefSlab > Refs
std::optional< tooling::CompileCommand > Cmd
std::optional< IncludeGraph > Sources
const IncludeGraph * Sources
const RelationSlab * Relations
const tooling::CompileCommand * Cmd
const SymbolSlab * Symbols
Represents a symbol occurrence in the source file.
SymbolID Container
The ID of the symbol whose definition contains this reference.
SymbolLocation Location
The source location where the symbol is named.
Represents a relation between two symbols.
void setColumn(uint32_t Column)
void setLine(uint32_t Line)
Ensure we have enough bits to represent all SymbolTag values.
@ Include
#include "header.h"
@ Import
#import "header.h"
SymbolLocation Definition
The location of the symbol's definition, if one was found.
llvm::StringRef Type
Raw representation of the OpaqueType of the symbol, used for scoring purposes.
llvm::StringRef Documentation
Documentation including comment for the symbol declaration.
SymbolTags Tags
Symbol tags for LSP protocol (Deprecated, Static, Virtual, Abstract, Final, ReadOnly,...
index::SymbolInfo SymInfo
The symbol information, like symbol kind.
llvm::SmallVector< IncludeHeaderWithReferences, 1 > IncludeHeaders
One Symbol can potentially be included via different headers.
llvm::StringRef Name
The unqualified name of the symbol, e.g. "bar" (for ns::bar).
llvm::StringRef Scope
The containing namespace. e.g. "" (global), "ns::" (top-level namespace).
llvm::StringRef Signature
A brief description of the symbol that can be appended in the completion candidate list.
unsigned References
The number of translation units that reference this symbol from their main file.
llvm::StringRef ReturnType
Type when this symbol is used in an expression.
llvm::StringRef TemplateSpecializationArgs
Argument list in human-readable format, will be displayed to help disambiguate between different spec...
SymbolLocation CanonicalDeclaration
The location of the preferred declaration of the symbol.
llvm::StringRef CompletionSnippetSuffix
What to insert when completing this symbol, after the symbol name.
SymbolID ID
The ID of the symbol.
static void mapping(IO &IO, CompileCommandYAML &Cmd)
static void mapping(IO &IO, IncludeGraphNode &Node)
static void mapping(IO &IO, RefBundle &Refs)
static void mapping(IO &IO, Ref &R)
static void mapping(IO &IO, Relation &Relation)
static void mapping(IO &IO, SymbolID &ID)
static void mapping(IO &IO, SymbolInfo &SymInfo)
static void mapping(IO &IO, SymbolLocation &Value)
static void mapping(IO &IO, Symbol &Sym)
static void mapping(IO &IO, VariantEntry &Variant)
static void mapping(IO &IO, YPosition &Value)
NormalizedFileDigest(IO &, const FileDigest &Digest)
NormalizedFileDigest(IO &)
FileDigest denormalize(IO &I)
NormalizedFileURI(IO &, const char *FileURI)
const char * denormalize(IO &IO)
NormalizedPosition(IO &, const Position &Pos)
Position denormalize(IO &)
clang::clangd::SymbolLocation::Position Position
NormalizedRefKind(IO &, RefKind O)
RefKind denormalize(IO &)
IncludeGraphNode::SourceFlag denormalize(IO &)
NormalizedSourceFlag(IO &)
NormalizedSourceFlag(IO &, IncludeGraphNode::SourceFlag O)
NormalizedSymbolFlag(IO &, Symbol::SymbolFlag F)
Symbol::SymbolFlag denormalize(IO &)
NormalizedSymbolFlag(IO &)
SymbolID denormalize(IO &I)
NormalizedSymbolID(IO &, const SymbolID &ID)
NormalizedSymbolRole(IO &IO, RelationKind R)
RelationKind denormalize(IO &IO)
NormalizedSymbolRole(IO &)
static void bitset(IO &IO, clang::clangd::Symbol::IncludeDirective &Value)
static void enumeration(IO &IO, SymbolKind &Value)
static void enumeration(IO &IO, SymbolLanguage &Value)