clang-tools  7.0.0
SymbolCollector.cpp
Go to the documentation of this file.
1 //===--- SymbolCollector.cpp -------------------------------------*- C++-*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "SymbolCollector.h"
11 #include "../AST.h"
12 #include "../CodeComplete.h"
13 #include "../CodeCompletionStrings.h"
14 #include "../Logger.h"
15 #include "../SourceCode.h"
16 #include "../URI.h"
17 #include "CanonicalIncludes.h"
18 #include "clang/AST/DeclCXX.h"
19 #include "clang/AST/DeclTemplate.h"
20 #include "clang/ASTMatchers/ASTMatchFinder.h"
21 #include "clang/Basic/SourceManager.h"
22 #include "clang/Index/IndexSymbol.h"
23 #include "clang/Index/USRGeneration.h"
24 #include "llvm/Support/FileSystem.h"
25 #include "llvm/Support/MemoryBuffer.h"
26 #include "llvm/Support/Path.h"
27 
28 namespace clang {
29 namespace clangd {
30 
31 namespace {
32 /// If \p ND is a template specialization, returns the described template.
33 /// Otherwise, returns \p ND.
34 const NamedDecl &getTemplateOrThis(const NamedDecl &ND) {
35  if (auto T = ND.getDescribedTemplate())
36  return *T;
37  return ND;
38 }
39 
40 // Returns a URI of \p Path. Firstly, this makes the \p Path absolute using the
41 // current working directory of the given SourceManager if the Path is not an
42 // absolute path. If failed, this resolves relative paths against \p FallbackDir
43 // to get an absolute path. Then, this tries creating an URI for the absolute
44 // path with schemes specified in \p Opts. This returns an URI with the first
45 // working scheme, if there is any; otherwise, this returns None.
46 //
47 // The Path can be a path relative to the build directory, or retrieved from
48 // the SourceManager.
49 llvm::Optional<std::string> toURI(const SourceManager &SM, StringRef Path,
50  const SymbolCollector::Options &Opts) {
51  llvm::SmallString<128> AbsolutePath(Path);
52  if (std::error_code EC =
53  SM.getFileManager().getVirtualFileSystem()->makeAbsolute(
54  AbsolutePath))
55  log("Warning: could not make absolute file: {0}", EC.message());
56  if (llvm::sys::path::is_absolute(AbsolutePath)) {
57  // Handle the symbolic link path case where the current working directory
58  // (getCurrentWorkingDirectory) is a symlink./ We always want to the real
59  // file path (instead of the symlink path) for the C++ symbols.
60  //
61  // Consider the following example:
62  //
63  // src dir: /project/src/foo.h
64  // current working directory (symlink): /tmp/build -> /project/src/
65  //
66  // The file path of Symbol is "/project/src/foo.h" instead of
67  // "/tmp/build/foo.h"
68  if (const DirectoryEntry *Dir = SM.getFileManager().getDirectory(
69  llvm::sys::path::parent_path(AbsolutePath.str()))) {
70  StringRef DirName = SM.getFileManager().getCanonicalName(Dir);
71  SmallString<128> AbsoluteFilename;
72  llvm::sys::path::append(AbsoluteFilename, DirName,
73  llvm::sys::path::filename(AbsolutePath.str()));
74  AbsolutePath = AbsoluteFilename;
75  }
76  } else if (!Opts.FallbackDir.empty()) {
77  llvm::sys::fs::make_absolute(Opts.FallbackDir, AbsolutePath);
78  }
79 
80  llvm::sys::path::remove_dots(AbsolutePath, /*remove_dot_dot=*/true);
81 
82  std::string ErrMsg;
83  for (const auto &Scheme : Opts.URISchemes) {
84  auto U = URI::create(AbsolutePath, Scheme);
85  if (U)
86  return U->toString();
87  ErrMsg += llvm::toString(U.takeError()) + "\n";
88  }
89  log("Failed to create an URI for file {0}: {1}", AbsolutePath, ErrMsg);
90  return llvm::None;
91 }
92 
93 // All proto generated headers should start with this line.
94 static const char *PROTO_HEADER_COMMENT =
95  "// Generated by the protocol buffer compiler. DO NOT EDIT!";
96 
97 // Checks whether the decl is a private symbol in a header generated by
98 // protobuf compiler.
99 // To identify whether a proto header is actually generated by proto compiler,
100 // we check whether it starts with PROTO_HEADER_COMMENT.
101 // FIXME: make filtering extensible when there are more use cases for symbol
102 // filters.
103 bool isPrivateProtoDecl(const NamedDecl &ND) {
104  const auto &SM = ND.getASTContext().getSourceManager();
105  auto Loc = findNameLoc(&ND);
106  auto FileName = SM.getFilename(Loc);
107  if (!FileName.endswith(".proto.h") && !FileName.endswith(".pb.h"))
108  return false;
109  auto FID = SM.getFileID(Loc);
110  // Double check that this is an actual protobuf header.
111  if (!SM.getBufferData(FID).startswith(PROTO_HEADER_COMMENT))
112  return false;
113 
114  // ND without identifier can be operators.
115  if (ND.getIdentifier() == nullptr)
116  return false;
117  auto Name = ND.getIdentifier()->getName();
118  if (!Name.contains('_'))
119  return false;
120  // Nested proto entities (e.g. Message::Nested) have top-level decls
121  // that shouldn't be used (Message_Nested). Ignore them completely.
122  // The nested entities are dangling type aliases, we may want to reconsider
123  // including them in the future.
124  // For enum constants, SOME_ENUM_CONSTANT is not private and should be
125  // indexed. Outer_INNER is private. This heuristic relies on naming style, it
126  // will include OUTER_INNER and exclude some_enum_constant.
127  // FIXME: the heuristic relies on naming style (i.e. no underscore in
128  // user-defined names) and can be improved.
129  return (ND.getKind() != Decl::EnumConstant) ||
130  std::any_of(Name.begin(), Name.end(), islower);
131 }
132 
133 // We only collect #include paths for symbols that are suitable for global code
134 // completion, except for namespaces since #include path for a namespace is hard
135 // to define.
136 bool shouldCollectIncludePath(index::SymbolKind Kind) {
137  using SK = index::SymbolKind;
138  switch (Kind) {
139  case SK::Macro:
140  case SK::Enum:
141  case SK::Struct:
142  case SK::Class:
143  case SK::Union:
144  case SK::TypeAlias:
145  case SK::Using:
146  case SK::Function:
147  case SK::Variable:
148  case SK::EnumConstant:
149  return true;
150  default:
151  return false;
152  }
153 }
154 
155 /// Gets a canonical include (URI of the header or <header> or "header") for
156 /// header of \p Loc.
157 /// Returns None if fails to get include header for \p Loc.
158 llvm::Optional<std::string>
159 getIncludeHeader(llvm::StringRef QName, const SourceManager &SM,
160  SourceLocation Loc, const SymbolCollector::Options &Opts) {
161  std::vector<std::string> Headers;
162  // Collect the #include stack.
163  while (true) {
164  if (!Loc.isValid())
165  break;
166  auto FilePath = SM.getFilename(Loc);
167  if (FilePath.empty())
168  break;
169  Headers.push_back(FilePath);
170  if (SM.isInMainFile(Loc))
171  break;
172  Loc = SM.getIncludeLoc(SM.getFileID(Loc));
173  }
174  if (Headers.empty())
175  return llvm::None;
176  llvm::StringRef Header = Headers[0];
177  if (Opts.Includes) {
178  Header = Opts.Includes->mapHeader(Headers, QName);
179  if (Header.startswith("<") || Header.startswith("\""))
180  return Header.str();
181  }
182  return toURI(SM, Header, Opts);
183 }
184 
185 // Return the symbol location of the token at \p Loc.
186 llvm::Optional<SymbolLocation>
187 getTokenLocation(SourceLocation TokLoc, const SourceManager &SM,
188  const SymbolCollector::Options &Opts,
189  const clang::LangOptions &LangOpts,
190  std::string &FileURIStorage) {
191  auto U = toURI(SM, SM.getFilename(TokLoc), Opts);
192  if (!U)
193  return llvm::None;
194  FileURIStorage = std::move(*U);
195  SymbolLocation Result;
196  Result.FileURI = FileURIStorage;
197  auto TokenLength = clang::Lexer::MeasureTokenLength(TokLoc, SM, LangOpts);
198 
199  auto CreatePosition = [&SM](SourceLocation Loc) {
200  auto LSPLoc = sourceLocToPosition(SM, Loc);
201  SymbolLocation::Position Pos;
202  Pos.Line = LSPLoc.line;
203  Pos.Column = LSPLoc.character;
204  return Pos;
205  };
206 
207  Result.Start = CreatePosition(TokLoc);
208  auto EndLoc = TokLoc.getLocWithOffset(TokenLength);
209  Result.End = CreatePosition(EndLoc);
210 
211  return std::move(Result);
212 }
213 
214 // Checks whether \p ND is a definition of a TagDecl (class/struct/enum/union)
215 // in a header file, in which case clangd would prefer to use ND as a canonical
216 // declaration.
217 // FIXME: handle symbol types that are not TagDecl (e.g. functions), if using
218 // the first seen declaration as canonical declaration is not a good enough
219 // heuristic.
220 bool isPreferredDeclaration(const NamedDecl &ND, index::SymbolRoleSet Roles) {
221  using namespace clang::ast_matchers;
222  return (Roles & static_cast<unsigned>(index::SymbolRole::Definition)) &&
223  llvm::isa<TagDecl>(&ND) &&
224  match(decl(isExpansionInMainFile()), ND, ND.getASTContext()).empty();
225 }
226 
227 } // namespace
228 
229 SymbolCollector::SymbolCollector(Options Opts) : Opts(std::move(Opts)) {}
230 
231 void SymbolCollector::initialize(ASTContext &Ctx) {
232  ASTCtx = &Ctx;
233  CompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();
234  CompletionTUInfo =
235  llvm::make_unique<CodeCompletionTUInfo>(CompletionAllocator);
236 }
237 
238 bool SymbolCollector::shouldCollectSymbol(const NamedDecl &ND,
239  ASTContext &ASTCtx,
240  const Options &Opts) {
241  using namespace clang::ast_matchers;
242  if (ND.isImplicit())
243  return false;
244  // Skip anonymous declarations, e.g (anonymous enum/class/struct).
245  if (ND.getDeclName().isEmpty())
246  return false;
247 
248  // FIXME: figure out a way to handle internal linkage symbols (e.g. static
249  // variables, function) defined in the .cc files. Also we skip the symbols
250  // in anonymous namespace as the qualifier names of these symbols are like
251  // `foo::<anonymous>::bar`, which need a special handling.
252  // In real world projects, we have a relatively large set of header files
253  // that define static variables (like "static const int A = 1;"), we still
254  // want to collect these symbols, although they cause potential ODR
255  // violations.
256  if (ND.isInAnonymousNamespace())
257  return false;
258 
259  // We want most things but not "local" symbols such as symbols inside
260  // FunctionDecl, BlockDecl, ObjCMethodDecl and OMPDeclareReductionDecl.
261  // FIXME: Need a matcher for ExportDecl in order to include symbols declared
262  // within an export.
263  auto InNonLocalContext = hasDeclContext(anyOf(
264  translationUnitDecl(), namespaceDecl(), linkageSpecDecl(), recordDecl(),
265  enumDecl(), objcProtocolDecl(), objcInterfaceDecl(), objcCategoryDecl(),
266  objcCategoryImplDecl(), objcImplementationDecl()));
267  // Don't index template specializations and expansions in main files.
268  auto IsSpecialization =
269  anyOf(functionDecl(isExplicitTemplateSpecialization()),
270  cxxRecordDecl(isExplicitTemplateSpecialization()),
271  varDecl(isExplicitTemplateSpecialization()));
272  if (match(decl(allOf(unless(isExpansionInMainFile()), InNonLocalContext,
273  unless(IsSpecialization))),
274  ND, ASTCtx)
275  .empty())
276  return false;
277 
278  // Avoid indexing internal symbols in protobuf generated headers.
279  if (isPrivateProtoDecl(ND))
280  return false;
281  return true;
282 }
283 
284 // Always return true to continue indexing.
286  const Decl *D, index::SymbolRoleSet Roles,
287  ArrayRef<index::SymbolRelation> Relations, SourceLocation Loc,
288  index::IndexDataConsumer::ASTNodeInfo ASTNode) {
289  assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
290  assert(CompletionAllocator && CompletionTUInfo);
291  assert(ASTNode.OrigD);
292  // If OrigD is an declaration associated with a friend declaration and it's
293  // not a definition, skip it. Note that OrigD is the occurrence that the
294  // collector is currently visiting.
295  if ((ASTNode.OrigD->getFriendObjectKind() !=
296  Decl::FriendObjectKind::FOK_None) &&
297  !(Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
298  return true;
299  // A declaration created for a friend declaration should not be used as the
300  // canonical declaration in the index. Use OrigD instead, unless we've already
301  // picked a replacement for D
302  if (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None)
303  D = CanonicalDecls.try_emplace(D, ASTNode.OrigD).first->second;
304  const NamedDecl *ND = llvm::dyn_cast<NamedDecl>(D);
305  if (!ND)
306  return true;
307 
308  // Mark D as referenced if this is a reference coming from the main file.
309  // D may not be an interesting symbol, but it's cheaper to check at the end.
310  auto &SM = ASTCtx->getSourceManager();
311  if (Opts.CountReferences &&
312  (Roles & static_cast<unsigned>(index::SymbolRole::Reference)) &&
313  SM.getFileID(SM.getSpellingLoc(Loc)) == SM.getMainFileID())
314  ReferencedDecls.insert(ND);
315 
316  // Don't continue indexing if this is a mere reference.
317  if (!(Roles & static_cast<unsigned>(index::SymbolRole::Declaration) ||
318  Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
319  return true;
320  if (!shouldCollectSymbol(*ND, *ASTCtx, Opts))
321  return true;
322 
323  llvm::SmallString<128> USR;
324  if (index::generateUSRForDecl(ND, USR))
325  return true;
326  SymbolID ID(USR);
327 
328  const NamedDecl &OriginalDecl = *cast<NamedDecl>(ASTNode.OrigD);
329  const Symbol *BasicSymbol = Symbols.find(ID);
330  if (!BasicSymbol) // Regardless of role, ND is the canonical declaration.
331  BasicSymbol = addDeclaration(*ND, std::move(ID));
332  else if (isPreferredDeclaration(OriginalDecl, Roles))
333  // If OriginalDecl is preferred, replace the existing canonical
334  // declaration (e.g. a class forward declaration). There should be at most
335  // one duplicate as we expect to see only one preferred declaration per
336  // TU, because in practice they are definitions.
337  BasicSymbol = addDeclaration(OriginalDecl, std::move(ID));
338 
339  if (Roles & static_cast<unsigned>(index::SymbolRole::Definition))
340  addDefinition(OriginalDecl, *BasicSymbol);
341  return true;
342 }
343 
344 bool SymbolCollector::handleMacroOccurence(const IdentifierInfo *Name,
345  const MacroInfo *MI,
346  index::SymbolRoleSet Roles,
347  SourceLocation Loc) {
348  if (!Opts.CollectMacro)
349  return true;
350  assert(PP.get());
351 
352  const auto &SM = PP->getSourceManager();
353  if (SM.isInMainFile(SM.getExpansionLoc(MI->getDefinitionLoc())))
354  return true;
355  // Header guards are not interesting in index. Builtin macros don't have
356  // useful locations and are not needed for code completions.
357  if (MI->isUsedForHeaderGuard() || MI->isBuiltinMacro())
358  return true;
359 
360  // Mark the macro as referenced if this is a reference coming from the main
361  // file. The macro may not be an interesting symbol, but it's cheaper to check
362  // at the end.
363  if (Opts.CountReferences &&
364  (Roles & static_cast<unsigned>(index::SymbolRole::Reference)) &&
365  SM.getFileID(SM.getSpellingLoc(Loc)) == SM.getMainFileID())
366  ReferencedMacros.insert(Name);
367  // Don't continue indexing if this is a mere reference.
368  // FIXME: remove macro with ID if it is undefined.
369  if (!(Roles & static_cast<unsigned>(index::SymbolRole::Declaration) ||
370  Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
371  return true;
372 
373  llvm::SmallString<128> USR;
374  if (index::generateUSRForMacro(Name->getName(), MI->getDefinitionLoc(), SM,
375  USR))
376  return true;
377  SymbolID ID(USR);
378 
379  // Only collect one instance in case there are multiple.
380  if (Symbols.find(ID) != nullptr)
381  return true;
382 
383  Symbol S;
384  S.ID = std::move(ID);
385  S.Name = Name->getName();
387  S.SymInfo = index::getSymbolInfoForMacro(*MI);
388  std::string FileURI;
389  if (auto DeclLoc = getTokenLocation(MI->getDefinitionLoc(), SM, Opts,
390  PP->getLangOpts(), FileURI))
391  S.CanonicalDeclaration = *DeclLoc;
392 
393  CodeCompletionResult SymbolCompletion(Name);
394  const auto *CCS = SymbolCompletion.CreateCodeCompletionStringForMacro(
395  *PP, *CompletionAllocator, *CompletionTUInfo);
396  std::string Signature;
397  std::string SnippetSuffix;
398  getSignature(*CCS, &Signature, &SnippetSuffix);
399 
400  std::string Include;
401  if (Opts.CollectIncludePath && shouldCollectIncludePath(S.SymInfo.Kind)) {
402  if (auto Header =
403  getIncludeHeader(Name->getName(), SM,
404  SM.getExpansionLoc(MI->getDefinitionLoc()), Opts))
405  Include = std::move(*Header);
406  }
407  S.Signature = Signature;
409  Symbol::Details Detail;
410  Detail.IncludeHeader = Include;
411  S.Detail = &Detail;
412  Symbols.insert(S);
413  return true;
414 }
415 
417  // At the end of the TU, add 1 to the refcount of all referenced symbols.
418  auto IncRef = [this](const SymbolID &ID) {
419  if (const auto *S = Symbols.find(ID)) {
420  Symbol Inc = *S;
421  ++Inc.References;
422  Symbols.insert(Inc);
423  }
424  };
425  for (const NamedDecl *ND : ReferencedDecls) {
426  llvm::SmallString<128> USR;
427  if (!index::generateUSRForDecl(ND, USR))
428  IncRef(SymbolID(USR));
429  }
430  if (Opts.CollectMacro) {
431  assert(PP);
432  for (const IdentifierInfo *II : ReferencedMacros) {
433  llvm::SmallString<128> USR;
434  if (const auto *MI = PP->getMacroDefinition(II).getMacroInfo())
435  if (!index::generateUSRForMacro(II->getName(), MI->getDefinitionLoc(),
436  PP->getSourceManager(), USR))
437  IncRef(SymbolID(USR));
438  }
439  }
440  ReferencedDecls.clear();
441  ReferencedMacros.clear();
442 }
443 
444 const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND,
445  SymbolID ID) {
446  auto &Ctx = ND.getASTContext();
447  auto &SM = Ctx.getSourceManager();
448 
449  Symbol S;
450  S.ID = std::move(ID);
451  std::string QName = printQualifiedName(ND);
452  std::tie(S.Scope, S.Name) = splitQualifiedName(QName);
453  // FIXME: this returns foo:bar: for objective-C methods, we prefer only foo:
454  // for consistency with CodeCompletionString and a clean name/signature split.
455 
457  S.SymInfo = index::getSymbolInfo(&ND);
458  std::string FileURI;
459  if (auto DeclLoc = getTokenLocation(findNameLoc(&ND), SM, Opts,
460  ASTCtx->getLangOpts(), FileURI))
461  S.CanonicalDeclaration = *DeclLoc;
462 
463  // Add completion info.
464  // FIXME: we may want to choose a different redecl, or combine from several.
465  assert(ASTCtx && PP.get() && "ASTContext and Preprocessor must be set.");
466  // We use the primary template, as clang does during code completion.
467  CodeCompletionResult SymbolCompletion(&getTemplateOrThis(ND), 0);
468  const auto *CCS = SymbolCompletion.CreateCodeCompletionString(
469  *ASTCtx, *PP, CodeCompletionContext::CCC_Name, *CompletionAllocator,
470  *CompletionTUInfo,
471  /*IncludeBriefComments*/ false);
472  std::string Signature;
473  std::string SnippetSuffix;
474  getSignature(*CCS, &Signature, &SnippetSuffix);
475  std::string Documentation =
476  formatDocumentation(*CCS, getDocComment(Ctx, SymbolCompletion,
477  /*CommentsFromHeaders=*/true));
478  std::string ReturnType = getReturnType(*CCS);
479 
480  std::string Include;
481  if (Opts.CollectIncludePath && shouldCollectIncludePath(S.SymInfo.Kind)) {
482  // Use the expansion location to get the #include header since this is
483  // where the symbol is exposed.
484  if (auto Header = getIncludeHeader(
485  QName, SM, SM.getExpansionLoc(ND.getLocation()), Opts))
486  Include = std::move(*Header);
487  }
488  S.Signature = Signature;
490  Symbol::Details Detail;
491  Detail.Documentation = Documentation;
492  Detail.ReturnType = ReturnType;
493  Detail.IncludeHeader = Include;
494  S.Detail = &Detail;
495 
496  S.Origin = Opts.Origin;
497  Symbols.insert(S);
498  return Symbols.find(S.ID);
499 }
500 
501 void SymbolCollector::addDefinition(const NamedDecl &ND,
502  const Symbol &DeclSym) {
503  if (DeclSym.Definition)
504  return;
505  // If we saw some forward declaration, we end up copying the symbol.
506  // This is not ideal, but avoids duplicating the "is this a definition" check
507  // in clang::index. We should only see one definition.
508  Symbol S = DeclSym;
509  std::string FileURI;
510  if (auto DefLoc = getTokenLocation(findNameLoc(&ND),
511  ND.getASTContext().getSourceManager(),
512  Opts, ASTCtx->getLangOpts(), FileURI))
513  S.Definition = *DefLoc;
514  Symbols.insert(S);
515 }
516 
517 } // namespace clangd
518 } // namespace clang
SourceLocation Loc
&#39;#&#39; location in the include directive
llvm::StringRef Name
bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *MI, index::SymbolRoleSet Roles, SourceLocation Loc) override
llvm::StringRef Documentation
Documentation including comment for the symbol declaration.
Definition: Index.h:208
static const char * Scheme
Definition: URI.cpp:33
Optional symbol details that are not required to be set.
Definition: Index.h:206
std::string printQualifiedName(const NamedDecl &ND)
Returns the qualified name of ND.
Definition: AST.cpp:41
bool IsIndexedForCodeCompletion
Whether or not this symbol is meant to be used for the code completion.
Definition: Index.h:190
llvm::StringRef IncludeHeader
This can be either a URI of the header to be #include&#39;d for this symbol, or a literal header quoted w...
Definition: Index.h:219
clang::find_all_symbols::SymbolInfo::SymbolKind SymbolKind
Definition: SymbolInfo.cpp:22
SourceLocation findNameLoc(const clang::Decl *D)
Find the identifier source location of the given D.
Definition: AST.cpp:20
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
def make_absolute(f, directory)
llvm::StringRef Scope
Definition: Index.h:172
std::string getDocComment(const ASTContext &Ctx, const CodeCompletionResult &Result, bool CommentsFromHeaders)
Gets a minimally formatted documentation comment of Result, with comment markers stripped.
Documents should not be synced at all.
void initialize(ASTContext &Ctx) override
llvm::StringRef ReturnType
Type when this symbol is used in an expression.
Definition: Index.h:211
unsigned References
Definition: Index.h:187
index::SymbolInfo SymInfo
Definition: Index.h:168
std::string getReturnType(const CodeCompletionString &CCS)
Gets detail to be used as the detail field in an LSP completion item.
BindArgumentKind Kind
SymbolLocation Definition
Definition: Index.h:175
bool handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles, ArrayRef< index::SymbolRelation > Relations, SourceLocation Loc, index::IndexDataConsumer::ASTNodeInfo ASTNode) override
bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx)
llvm::StringRef Signature
A brief description of the symbol that can be appended in the completion candidate list...
Definition: Index.h:195
void log(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:62
std::string Path
A typedef to represent a file path.
Definition: Path.h:21
SymbolLocation CanonicalDeclaration
Definition: Index.h:184
PathRef FileName
std::string formatDocumentation(const CodeCompletionString &CCS, llvm::StringRef DocComment)
Assembles formatted documentation for a completion result.
std::string ReturnType
std::string SnippetSuffix
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
Definition: SourceCode.cpp:130
Position Pos
int line
Line position in a document (zero-based).
Definition: Protocol.h:91
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
Definition: URI.cpp:174
void getSignature(const CodeCompletionString &CCS, std::string *Signature, std::string *Snippet, std::string *RequiredQualifiers)
Formats the signature for an item, as a display string and snippet.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
llvm::StringRef Name
Definition: Index.h:170
const Details * Detail
Definition: Index.h:223
std::pair< llvm::StringRef, llvm::StringRef > splitQualifiedName(llvm::StringRef QName)
From "a::b::c", return {"a::b::", "c"}.
Definition: SourceCode.cpp:166
static bool shouldCollectSymbol(const NamedDecl &ND, ASTContext &ASTCtx, const Options &Opts)
Returns true is ND should be collected.
llvm::StringRef CompletionSnippetSuffix
What to insert when completing this symbol, after the symbol name.
Definition: Index.h:199
tooling::ExecutionContext * Ctx
std::string Signature
SymbolOrigin Origin
Where this symbol came from. Usually an index provides a constant value.
Definition: Index.h:192
std::array< uint8_t, 20 > SymbolID