clang-tools  15.0.0git
SymbolCollector.cpp
Go to the documentation of this file.
1 //===--- SymbolCollector.cpp -------------------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "SymbolCollector.h"
10 #include "AST.h"
11 #include "CodeComplete.h"
12 #include "CodeCompletionStrings.h"
13 #include "ExpectedTypes.h"
14 #include "SourceCode.h"
15 #include "URI.h"
17 #include "index/Relation.h"
18 #include "index/SymbolID.h"
19 #include "index/SymbolLocation.h"
20 #include "clang/AST/Decl.h"
21 #include "clang/AST/DeclBase.h"
22 #include "clang/AST/DeclObjC.h"
23 #include "clang/AST/DeclTemplate.h"
24 #include "clang/AST/DeclarationName.h"
25 #include "clang/Basic/LangOptions.h"
26 #include "clang/Basic/SourceLocation.h"
27 #include "clang/Basic/SourceManager.h"
28 #include "clang/Index/IndexSymbol.h"
29 #include "clang/Lex/Preprocessor.h"
30 #include "clang/Lex/Token.h"
31 #include "llvm/ADT/ArrayRef.h"
32 #include "llvm/Support/Casting.h"
33 #include "llvm/Support/FileSystem.h"
34 #include "llvm/Support/Path.h"
35 
36 namespace clang {
37 namespace clangd {
38 namespace {
39 
40 /// If \p ND is a template specialization, returns the described template.
41 /// Otherwise, returns \p ND.
42 const NamedDecl &getTemplateOrThis(const NamedDecl &ND) {
43  if (auto *T = ND.getDescribedTemplate())
44  return *T;
45  return ND;
46 }
47 
48 // Checks whether the decl is a private symbol in a header generated by
49 // protobuf compiler.
50 // FIXME: make filtering extensible when there are more use cases for symbol
51 // filters.
52 bool isPrivateProtoDecl(const NamedDecl &ND) {
53  const auto &SM = ND.getASTContext().getSourceManager();
54  if (!isProtoFile(nameLocation(ND, SM), SM))
55  return false;
56 
57  // ND without identifier can be operators.
58  if (ND.getIdentifier() == nullptr)
59  return false;
60  auto Name = ND.getIdentifier()->getName();
61  if (!Name.contains('_'))
62  return false;
63  // Nested proto entities (e.g. Message::Nested) have top-level decls
64  // that shouldn't be used (Message_Nested). Ignore them completely.
65  // The nested entities are dangling type aliases, we may want to reconsider
66  // including them in the future.
67  // For enum constants, SOME_ENUM_CONSTANT is not private and should be
68  // indexed. Outer_INNER is private. This heuristic relies on naming style, it
69  // will include OUTER_INNER and exclude some_enum_constant.
70  // FIXME: the heuristic relies on naming style (i.e. no underscore in
71  // user-defined names) and can be improved.
72  return (ND.getKind() != Decl::EnumConstant) || llvm::any_of(Name, islower);
73 }
74 
75 // We only collect #include paths for symbols that are suitable for global code
76 // completion, except for namespaces since #include path for a namespace is hard
77 // to define.
78 bool shouldCollectIncludePath(index::SymbolKind Kind) {
79  using SK = index::SymbolKind;
80  switch (Kind) {
81  case SK::Macro:
82  case SK::Enum:
83  case SK::Struct:
84  case SK::Class:
85  case SK::Union:
86  case SK::TypeAlias:
87  case SK::Using:
88  case SK::Function:
89  case SK::Variable:
90  case SK::EnumConstant:
91  case SK::Concept:
92  return true;
93  default:
94  return false;
95  }
96 }
97 
98 // Return the symbol range of the token at \p TokLoc.
99 std::pair<SymbolLocation::Position, SymbolLocation::Position>
100 getTokenRange(SourceLocation TokLoc, const SourceManager &SM,
101  const LangOptions &LangOpts) {
102  auto CreatePosition = [&SM](SourceLocation Loc) {
103  auto LSPLoc = sourceLocToPosition(SM, Loc);
104  SymbolLocation::Position Pos;
105  Pos.setLine(LSPLoc.line);
106  Pos.setColumn(LSPLoc.character);
107  return Pos;
108  };
109 
110  auto TokenLength = clang::Lexer::MeasureTokenLength(TokLoc, SM, LangOpts);
111  return {CreatePosition(TokLoc),
112  CreatePosition(TokLoc.getLocWithOffset(TokenLength))};
113 }
114 
115 // Checks whether \p ND is a good candidate to be the *canonical* declaration of
116 // its symbol (e.g. a go-to-declaration target). This overrides the default of
117 // using Clang's canonical declaration, which is the first in the TU.
118 //
119 // Example: preferring a class declaration over its forward declaration.
120 bool isPreferredDeclaration(const NamedDecl &ND, index::SymbolRoleSet Roles) {
121  const auto &SM = ND.getASTContext().getSourceManager();
122  if (isa<TagDecl>(ND))
123  return (Roles & static_cast<unsigned>(index::SymbolRole::Definition)) &&
124  !isInsideMainFile(ND.getLocation(), SM);
125  if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(&ND))
126  return ID->isThisDeclarationADefinition();
127  if (const auto *PD = dyn_cast<ObjCProtocolDecl>(&ND))
128  return PD->isThisDeclarationADefinition();
129  return false;
130 }
131 
132 RefKind toRefKind(index::SymbolRoleSet Roles, bool Spelled = false) {
133  RefKind Result = RefKind::Unknown;
134  if (Roles & static_cast<unsigned>(index::SymbolRole::Declaration))
135  Result |= RefKind::Declaration;
136  if (Roles & static_cast<unsigned>(index::SymbolRole::Definition))
137  Result |= RefKind::Definition;
138  if (Roles & static_cast<unsigned>(index::SymbolRole::Reference))
139  Result |= RefKind::Reference;
140  if (Spelled)
141  Result |= RefKind::Spelled;
142  return Result;
143 }
144 
145 llvm::Optional<RelationKind> indexableRelation(const index::SymbolRelation &R) {
146  if (R.Roles & static_cast<unsigned>(index::SymbolRole::RelationBaseOf))
147  return RelationKind::BaseOf;
148  if (R.Roles & static_cast<unsigned>(index::SymbolRole::RelationOverrideOf))
150  return None;
151 }
152 
153 // Given a ref contained in enclosing decl `Enclosing`, return
154 // the decl that should be used as that ref's Ref::Container. This is
155 // usually `Enclosing` itself, but in cases where `Enclosing` is not
156 // indexed, we walk further up because Ref::Container should always be
157 // an indexed symbol.
158 // Note: we don't use DeclContext as the container as in some cases
159 // it's useful to use a Decl which is not a DeclContext. For example,
160 // for a ref occurring in the initializer of a namespace-scope variable,
161 // it's useful to use that variable as the container, as otherwise the
162 // next enclosing DeclContext would be a NamespaceDecl or TranslationUnitDecl,
163 // which are both not indexed and less granular than we'd like for use cases
164 // like call hierarchy.
165 const Decl *getRefContainer(const Decl *Enclosing,
166  const SymbolCollector::Options &Opts) {
167  while (Enclosing) {
168  const auto *ND = dyn_cast<NamedDecl>(Enclosing);
169  if (ND && SymbolCollector::shouldCollectSymbol(*ND, ND->getASTContext(),
170  Opts, true)) {
171  break;
172  }
173  Enclosing = dyn_cast_or_null<Decl>(Enclosing->getDeclContext());
174  }
175  return Enclosing;
176 }
177 
178 // Check if there is an exact spelling of \p ND at \p Loc.
179 bool isSpelled(SourceLocation Loc, const NamedDecl &ND) {
180  auto Name = ND.getDeclName();
181  const auto NameKind = Name.getNameKind();
182  if (NameKind != DeclarationName::Identifier &&
183  NameKind != DeclarationName::CXXConstructorName)
184  return false;
185  const auto &AST = ND.getASTContext();
186  const auto &SM = AST.getSourceManager();
187  const auto &LO = AST.getLangOpts();
188  clang::Token Tok;
189  if (clang::Lexer::getRawToken(Loc, Tok, SM, LO))
190  return false;
191  auto StrName = Name.getAsString();
192  return clang::Lexer::getSpelling(Tok, SM, LO) == StrName;
193 }
194 } // namespace
195 
196 // Encapsulates decisions about how to record header paths in the index,
197 // including filename normalization, URI conversion etc.
198 // Expensive checks are cached internally.
200  struct FrameworkUmbrellaSpelling {
201  // Spelling for the public umbrella header, e.g. <Foundation/Foundation.h>
202  llvm::Optional<std::string> PublicHeader;
203  // Spelling for the private umbrella header, e.g.
204  // <Foundation/Foundation_Private.h>
205  llvm::Optional<std::string> PrivateHeader;
206  };
207  // Weird double-indirect access to PP, which might not be ready yet when
208  // HeaderFiles is created but will be by the time it's used.
209  // (IndexDataConsumer::setPreprocessor can happen before or after initialize)
210  Preprocessor *&PP;
211  const SourceManager &SM;
212  const CanonicalIncludes *Includes;
213  llvm::StringRef FallbackDir;
214  llvm::DenseMap<const FileEntry *, const std::string *> CacheFEToURI;
215  llvm::StringMap<std::string> CachePathToURI;
216  llvm::DenseMap<FileID, llvm::StringRef> CacheFIDToInclude;
217  llvm::StringMap<std::string> CachePathToFrameworkSpelling;
218  llvm::StringMap<FrameworkUmbrellaSpelling>
219  CacheFrameworkToUmbrellaHeaderSpelling;
220 
221 public:
222  HeaderFileURICache(Preprocessor *&PP, const SourceManager &SM,
223  const SymbolCollector::Options &Opts)
224  : PP(PP), SM(SM), Includes(Opts.Includes), FallbackDir(Opts.FallbackDir) {
225  }
226 
227  // Returns a canonical URI for the file \p FE.
228  // We attempt to make the path absolute first.
229  const std::string &toURI(const FileEntry *FE) {
230  auto R = CacheFEToURI.try_emplace(FE);
231  if (R.second) {
232  auto CanonPath = getCanonicalPath(FE, SM);
233  R.first->second = &toURIInternal(CanonPath ? *CanonPath : FE->getName());
234  }
235  return *R.first->second;
236  }
237 
238  // Returns a canonical URI for \p Path.
239  // If the file is in the FileManager, use that to canonicalize the path.
240  // We attempt to make the path absolute in any case.
241  const std::string &toURI(llvm::StringRef Path) {
242  if (auto File = SM.getFileManager().getFile(Path))
243  return toURI(*File);
244  return toURIInternal(Path);
245  }
246 
247  // Gets a canonical include (URI of the header or <header> or "header") for
248  // header of \p FID (which should usually be the *expansion* file).
249  // This does not account for any per-symbol overrides!
250  // Returns "" if includes should not be inserted for this file.
251  llvm::StringRef getIncludeHeader(FileID FID) {
252  auto R = CacheFIDToInclude.try_emplace(FID);
253  if (R.second)
254  R.first->second = getIncludeHeaderUncached(FID);
255  return R.first->second;
256  }
257 
258 private:
259  // This takes care of making paths absolute and path->URI caching, but no
260  // FileManager-based canonicalization.
261  const std::string &toURIInternal(llvm::StringRef Path) {
262  auto R = CachePathToURI.try_emplace(Path);
263  if (R.second) {
264  llvm::SmallString<256> AbsPath = Path;
265  if (!llvm::sys::path::is_absolute(AbsPath) && !FallbackDir.empty())
266  llvm::sys::fs::make_absolute(FallbackDir, AbsPath);
267  assert(llvm::sys::path::is_absolute(AbsPath) &&
268  "If the VFS can't make paths absolute, a FallbackDir must be "
269  "provided");
270  llvm::sys::path::remove_dots(AbsPath, /*remove_dot_dot=*/true);
271  R.first->second = URI::create(AbsPath).toString();
272  }
273  return R.first->second;
274  }
275 
276  struct FrameworkHeaderPath {
277  // Path to the framework directory containing the Headers/PrivateHeaders
278  // directories e.g. /Frameworks/Foundation.framework/
279  llvm::StringRef HeadersParentDir;
280  // Subpath relative to the Headers or PrivateHeaders dir, e.g. NSObject.h
281  // Note: This is NOT relative to the `HeadersParentDir`.
282  llvm::StringRef HeaderSubpath;
283  // Whether this header is under the PrivateHeaders dir
284  bool IsPrivateHeader;
285  };
286 
287  llvm::Optional<FrameworkHeaderPath>
288  splitFrameworkHeaderPath(llvm::StringRef Path) {
289  using namespace llvm::sys;
290  path::reverse_iterator I = path::rbegin(Path);
291  path::reverse_iterator Prev = I;
292  path::reverse_iterator E = path::rend(Path);
293  while (I != E) {
294  if (*I == "Headers") {
295  FrameworkHeaderPath HeaderPath;
296  HeaderPath.HeadersParentDir = Path.substr(0, I - E);
297  HeaderPath.HeaderSubpath = Path.substr(Prev - E);
298  HeaderPath.IsPrivateHeader = false;
299  return HeaderPath;
300  }
301  if (*I == "PrivateHeaders") {
302  FrameworkHeaderPath HeaderPath;
303  HeaderPath.HeadersParentDir = Path.substr(0, I - E);
304  HeaderPath.HeaderSubpath = Path.substr(Prev - E);
305  HeaderPath.IsPrivateHeader = true;
306  return HeaderPath;
307  }
308  Prev = I;
309  ++I;
310  }
311  // Unexpected, must not be a framework header.
312  return llvm::None;
313  }
314 
315  // Frameworks typically have an umbrella header of the same name, e.g.
316  // <Foundation/Foundation.h> instead of <Foundation/NSObject.h> or
317  // <Foundation/Foundation_Private.h> instead of
318  // <Foundation/NSObject_Private.h> which should be used instead of directly
319  // importing the header.
320  llvm::Optional<std::string> getFrameworkUmbrellaSpelling(
321  llvm::StringRef Framework, SrcMgr::CharacteristicKind HeadersDirKind,
322  HeaderSearch &HS, FrameworkHeaderPath &HeaderPath) {
323  auto Res = CacheFrameworkToUmbrellaHeaderSpelling.try_emplace(Framework);
324  auto *CachedSpelling = &Res.first->second;
325  if (!Res.second) {
326  return HeaderPath.IsPrivateHeader ? CachedSpelling->PrivateHeader
327  : CachedSpelling->PublicHeader;
328  }
329  bool IsSystem = isSystem(HeadersDirKind);
330  SmallString<256> UmbrellaPath(HeaderPath.HeadersParentDir);
331  llvm::sys::path::append(UmbrellaPath, "Headers", Framework + ".h");
332 
333  llvm::vfs::Status Status;
334  auto StatErr = HS.getFileMgr().getNoncachedStatValue(UmbrellaPath, Status);
335  if (!StatErr) {
336  if (IsSystem)
337  CachedSpelling->PublicHeader = llvm::formatv("<{0}/{0}.h>", Framework);
338  else
339  CachedSpelling->PublicHeader =
340  llvm::formatv("\"{0}/{0}.h\"", Framework);
341  }
342 
343  UmbrellaPath = HeaderPath.HeadersParentDir;
344  llvm::sys::path::append(UmbrellaPath, "PrivateHeaders",
345  Framework + "_Private.h");
346 
347  StatErr = HS.getFileMgr().getNoncachedStatValue(UmbrellaPath, Status);
348  if (!StatErr) {
349  if (IsSystem)
350  CachedSpelling->PrivateHeader =
351  llvm::formatv("<{0}/{0}_Private.h>", Framework);
352  else
353  CachedSpelling->PrivateHeader =
354  llvm::formatv("\"{0}/{0}_Private.h\"", Framework);
355  }
356  return HeaderPath.IsPrivateHeader ? CachedSpelling->PrivateHeader
357  : CachedSpelling->PublicHeader;
358  }
359 
360  // Compute the framework include spelling for `FE` which is in a framework
361  // named `Framework`, e.g. `NSObject.h` in framework `Foundation` would
362  // give <Foundation/Foundation.h> if the umbrella header exists, otherwise
363  // <Foundation/NSObject.h>.
364  llvm::Optional<llvm::StringRef> getFrameworkHeaderIncludeSpelling(
365  const FileEntry *FE, llvm::StringRef Framework, HeaderSearch &HS) {
366  auto Res = CachePathToFrameworkSpelling.try_emplace(FE->getName());
367  auto *CachedHeaderSpelling = &Res.first->second;
368  if (!Res.second)
369  return llvm::StringRef(*CachedHeaderSpelling);
370 
371  auto HeaderPath = splitFrameworkHeaderPath(FE->getName());
372  if (!HeaderPath) {
373  // Unexpected: must not be a proper framework header, don't cache the
374  // failure.
375  CachePathToFrameworkSpelling.erase(Res.first);
376  return llvm::None;
377  }
378  auto DirKind = HS.getFileDirFlavor(FE);
379  if (auto UmbrellaSpelling =
380  getFrameworkUmbrellaSpelling(Framework, DirKind, HS, *HeaderPath)) {
381  *CachedHeaderSpelling = *UmbrellaSpelling;
382  return llvm::StringRef(*CachedHeaderSpelling);
383  }
384 
385  if (isSystem(DirKind))
386  *CachedHeaderSpelling =
387  llvm::formatv("<{0}/{1}>", Framework, HeaderPath->HeaderSubpath)
388  .str();
389  else
390  *CachedHeaderSpelling =
391  llvm::formatv("\"{0}/{1}\"", Framework, HeaderPath->HeaderSubpath)
392  .str();
393  return llvm::StringRef(*CachedHeaderSpelling);
394  }
395 
396  llvm::StringRef getIncludeHeaderUncached(FileID FID) {
397  const FileEntry *FE = SM.getFileEntryForID(FID);
398  if (!FE || FE->getName().empty())
399  return "";
400  llvm::StringRef Filename = FE->getName();
401  // If a file is mapped by canonical headers, use that mapping, regardless
402  // of whether it's an otherwise-good header (header guards etc).
403  if (Includes) {
404  llvm::StringRef Canonical =
405  Includes->mapHeader(*SM.getFileEntryRefForID(FID));
406  if (!Canonical.empty()) {
407  // If we had a mapping, always use it.
408  if (Canonical.startswith("<") || Canonical.startswith("\""))
409  return Canonical;
410  return toURI(Canonical);
411  }
412  }
413  // Framework headers are spelled as <FrameworkName/Foo.h>, not
414  // "path/FrameworkName.framework/Headers/Foo.h".
415  auto &HS = PP->getHeaderSearchInfo();
416  if (const auto *HFI = HS.getExistingFileInfo(FE, /*WantExternal*/ false))
417  if (!HFI->Framework.empty())
418  if (auto Spelling =
419  getFrameworkHeaderIncludeSpelling(FE, HFI->Framework, HS))
420  return *Spelling;
421 
422  if (!isSelfContainedHeader(FE, FID, PP->getSourceManager(),
423  PP->getHeaderSearchInfo())) {
424  // A .inc or .def file is often included into a real header to define
425  // symbols (e.g. LLVM tablegen files).
426  if (Filename.endswith(".inc") || Filename.endswith(".def"))
427  // Don't use cache reentrantly due to iterator invalidation.
428  return getIncludeHeaderUncached(SM.getFileID(SM.getIncludeLoc(FID)));
429  // Conservatively refuse to insert #includes to files without guards.
430  return "";
431  }
432  // Standard case: just insert the file itself.
433  return toURI(FE);
434  }
435 };
436 
437 // Return the symbol location of the token at \p TokLoc.
438 llvm::Optional<SymbolLocation>
439 SymbolCollector::getTokenLocation(SourceLocation TokLoc) {
440  const auto &SM = ASTCtx->getSourceManager();
441  auto *FE = SM.getFileEntryForID(SM.getFileID(TokLoc));
442  if (!FE)
443  return None;
444 
445  SymbolLocation Result;
446  Result.FileURI = HeaderFileURIs->toURI(FE).c_str();
447  auto Range = getTokenRange(TokLoc, SM, ASTCtx->getLangOpts());
448  Result.Start = Range.first;
449  Result.End = Range.second;
450 
451  return Result;
452 }
453 
454 SymbolCollector::SymbolCollector(Options Opts) : Opts(std::move(Opts)) {}
456 
457 void SymbolCollector::initialize(ASTContext &Ctx) {
458  ASTCtx = &Ctx;
459  HeaderFileURIs = std::make_unique<HeaderFileURICache>(
460  this->PP, ASTCtx->getSourceManager(), Opts);
461  CompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();
462  CompletionTUInfo =
463  std::make_unique<CodeCompletionTUInfo>(CompletionAllocator);
464 }
465 
466 bool SymbolCollector::shouldCollectSymbol(const NamedDecl &ND,
467  const ASTContext &ASTCtx,
468  const Options &Opts,
469  bool IsMainFileOnly) {
470  // Skip anonymous declarations, e.g (anonymous enum/class/struct).
471  if (ND.getDeclName().isEmpty())
472  return false;
473 
474  // Skip main-file symbols if we are not collecting them.
475  if (IsMainFileOnly && !Opts.CollectMainFileSymbols)
476  return false;
477 
478  // Skip symbols in anonymous namespaces in header files.
479  if (!IsMainFileOnly && ND.isInAnonymousNamespace())
480  return false;
481 
482  // For function local symbols, index only classes and its member functions.
483  if (index::isFunctionLocalSymbol(&ND))
484  return isa<RecordDecl>(ND) ||
485  (ND.isCXXInstanceMember() && ND.isFunctionOrFunctionTemplate());
486 
487  // We want most things but not "local" symbols such as symbols inside
488  // FunctionDecl, BlockDecl, ObjCMethodDecl and OMPDeclareReductionDecl.
489  // FIXME: Need a matcher for ExportDecl in order to include symbols declared
490  // within an export.
491  const auto *DeclCtx = ND.getDeclContext();
492  switch (DeclCtx->getDeclKind()) {
493  case Decl::TranslationUnit:
494  case Decl::Namespace:
495  case Decl::LinkageSpec:
496  case Decl::Enum:
497  case Decl::ObjCProtocol:
498  case Decl::ObjCInterface:
499  case Decl::ObjCCategory:
500  case Decl::ObjCCategoryImpl:
501  case Decl::ObjCImplementation:
502  break;
503  default:
504  // Record has a few derivations (e.g. CXXRecord, Class specialization), it's
505  // easier to cast.
506  if (!isa<RecordDecl>(DeclCtx))
507  return false;
508  }
509 
510  // Avoid indexing internal symbols in protobuf generated headers.
511  if (isPrivateProtoDecl(ND))
512  return false;
513  if (!Opts.CollectReserved &&
514  (hasReservedName(ND) || hasReservedScope(*ND.getDeclContext())))
515  return false;
516 
517  return true;
518 }
519 
520 // Always return true to continue indexing.
522  const Decl *D, index::SymbolRoleSet Roles,
523  llvm::ArrayRef<index::SymbolRelation> Relations, SourceLocation Loc,
524  index::IndexDataConsumer::ASTNodeInfo ASTNode) {
525  assert(ASTCtx && PP && HeaderFileURIs);
526  assert(CompletionAllocator && CompletionTUInfo);
527  assert(ASTNode.OrigD);
528  // Indexing API puts canonical decl into D, which might not have a valid
529  // source location for implicit/built-in decls. Fallback to original decl in
530  // such cases.
531  if (D->getLocation().isInvalid())
532  D = ASTNode.OrigD;
533  // If OrigD is an declaration associated with a friend declaration and it's
534  // not a definition, skip it. Note that OrigD is the occurrence that the
535  // collector is currently visiting.
536  if ((ASTNode.OrigD->getFriendObjectKind() !=
537  Decl::FriendObjectKind::FOK_None) &&
538  !(Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
539  return true;
540  // A declaration created for a friend declaration should not be used as the
541  // canonical declaration in the index. Use OrigD instead, unless we've already
542  // picked a replacement for D
543  if (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None)
544  D = CanonicalDecls.try_emplace(D, ASTNode.OrigD).first->second;
545  // Flag to mark that D should be considered canonical meaning its declaration
546  // will override any previous declaration for the Symbol.
547  bool DeclIsCanonical = false;
548  // Avoid treating ObjCImplementationDecl as a canonical declaration if it has
549  // a corresponding non-implicit and non-forward declared ObjcInterfaceDecl.
550  if (const auto *IID = dyn_cast<ObjCImplementationDecl>(D)) {
551  DeclIsCanonical = true;
552  if (const auto *CID = IID->getClassInterface())
553  if (const auto *DD = CID->getDefinition())
554  if (!DD->isImplicitInterfaceDecl())
555  D = DD;
556  }
557  // Avoid treating ObjCCategoryImplDecl as a canonical declaration in favor of
558  // its ObjCCategoryDecl if it has one.
559  if (const auto *CID = dyn_cast<ObjCCategoryImplDecl>(D)) {
560  DeclIsCanonical = true;
561  if (const auto *CD = CID->getCategoryDecl())
562  D = CD;
563  }
564  const NamedDecl *ND = dyn_cast<NamedDecl>(D);
565  if (!ND)
566  return true;
567 
568  auto ID = getSymbolIDCached(ND);
569  if (!ID)
570  return true;
571 
572  // Mark D as referenced if this is a reference coming from the main file.
573  // D may not be an interesting symbol, but it's cheaper to check at the end.
574  auto &SM = ASTCtx->getSourceManager();
575  if (Opts.CountReferences &&
576  (Roles & static_cast<unsigned>(index::SymbolRole::Reference)) &&
577  SM.getFileID(SM.getSpellingLoc(Loc)) == SM.getMainFileID())
578  ReferencedSymbols.insert(ID);
579 
580  // ND is the canonical (i.e. first) declaration. If it's in the main file
581  // (which is not a header), then no public declaration was visible, so assume
582  // it's main-file only.
583  bool IsMainFileOnly =
584  SM.isWrittenInMainFile(SM.getExpansionLoc(ND->getBeginLoc())) &&
585  !isHeaderFile(SM.getFileEntryRefForID(SM.getMainFileID())->getName(),
586  ASTCtx->getLangOpts());
587  // In C, printf is a redecl of an implicit builtin! So check OrigD instead.
588  if (ASTNode.OrigD->isImplicit() ||
589  !shouldCollectSymbol(*ND, *ASTCtx, Opts, IsMainFileOnly))
590  return true;
591 
592  // Note: we need to process relations for all decl occurrences, including
593  // refs, because the indexing code only populates relations for specific
594  // occurrences. For example, RelationBaseOf is only populated for the
595  // occurrence inside the base-specifier.
596  processRelations(*ND, ID, Relations);
597 
598  bool CollectRef = static_cast<bool>(Opts.RefFilter & toRefKind(Roles));
599  // Unlike other fields, e.g. Symbols (which use spelling locations), we use
600  // file locations for references (as it aligns the behavior of clangd's
601  // AST-based xref).
602  // FIXME: we should try to use the file locations for other fields.
603  if (CollectRef &&
604  (!IsMainFileOnly || Opts.CollectMainFileRefs ||
605  ND->isExternallyVisible()) &&
606  !isa<NamespaceDecl>(ND)) {
607  auto FileLoc = SM.getFileLoc(Loc);
608  auto FID = SM.getFileID(FileLoc);
609  if (Opts.RefsInHeaders || FID == SM.getMainFileID()) {
610  addRef(ID, SymbolRef{FileLoc, FID, Roles,
611  getRefContainer(ASTNode.Parent, Opts),
612  isSpelled(FileLoc, *ND)});
613  }
614  }
615  // Don't continue indexing if this is a mere reference.
616  if (!(Roles & (static_cast<unsigned>(index::SymbolRole::Declaration) |
617  static_cast<unsigned>(index::SymbolRole::Definition))))
618  return true;
619 
620  // FIXME: ObjCPropertyDecl are not properly indexed here:
621  // - ObjCPropertyDecl may have an OrigD of ObjCPropertyImplDecl, which is
622  // not a NamedDecl.
623  auto *OriginalDecl = dyn_cast<NamedDecl>(ASTNode.OrigD);
624  if (!OriginalDecl)
625  return true;
626 
627  const Symbol *BasicSymbol = Symbols.find(ID);
628  if (isPreferredDeclaration(*OriginalDecl, Roles))
629  // If OriginalDecl is preferred, replace/create the existing canonical
630  // declaration (e.g. a class forward declaration). There should be at most
631  // one duplicate as we expect to see only one preferred declaration per
632  // TU, because in practice they are definitions.
633  BasicSymbol = addDeclaration(*OriginalDecl, std::move(ID), IsMainFileOnly);
634  else if (!BasicSymbol || DeclIsCanonical)
635  BasicSymbol = addDeclaration(*ND, std::move(ID), IsMainFileOnly);
636 
637  if (Roles & static_cast<unsigned>(index::SymbolRole::Definition))
638  addDefinition(*OriginalDecl, *BasicSymbol);
639 
640  return true;
641 }
642 
643 void SymbolCollector::handleMacros(const MainFileMacros &MacroRefsToIndex) {
644  assert(HeaderFileURIs && PP);
645  const auto &SM = PP->getSourceManager();
646  const auto *MainFileEntry = SM.getFileEntryForID(SM.getMainFileID());
647  assert(MainFileEntry);
648 
649  const std::string &MainFileURI = HeaderFileURIs->toURI(MainFileEntry);
650  // Add macro references.
651  for (const auto &IDToRefs : MacroRefsToIndex.MacroRefs) {
652  for (const auto &MacroRef : IDToRefs.second) {
653  const auto &Range = MacroRef.Rng;
654  bool IsDefinition = MacroRef.IsDefinition;
655  Ref R;
660  R.Location.FileURI = MainFileURI.c_str();
661  R.Kind = IsDefinition ? RefKind::Definition : RefKind::Reference;
662  Refs.insert(IDToRefs.first, R);
663  if (IsDefinition) {
664  Symbol S;
665  S.ID = IDToRefs.first;
666  auto StartLoc = cantFail(sourceLocationInMainFile(SM, Range.start));
667  auto EndLoc = cantFail(sourceLocationInMainFile(SM, Range.end));
668  S.Name = toSourceCode(SM, SourceRange(StartLoc, EndLoc));
669  S.SymInfo.Kind = index::SymbolKind::Macro;
670  S.SymInfo.SubKind = index::SymbolSubKind::None;
671  S.SymInfo.Properties = index::SymbolPropertySet();
673  S.Origin = Opts.Origin;
675  // Make the macro visible for code completion if main file is an
676  // include-able header.
677  if (!HeaderFileURIs->getIncludeHeader(SM.getMainFileID()).empty()) {
680  }
681  Symbols.insert(S);
682  }
683  }
684  }
685 }
686 
687 bool SymbolCollector::handleMacroOccurrence(const IdentifierInfo *Name,
688  const MacroInfo *MI,
689  index::SymbolRoleSet Roles,
690  SourceLocation Loc) {
691  assert(PP);
692  // Builtin macros don't have useful locations and aren't needed in completion.
693  if (MI->isBuiltinMacro())
694  return true;
695 
696  const auto &SM = PP->getSourceManager();
697  auto DefLoc = MI->getDefinitionLoc();
698  // Also avoid storing predefined macros like __DBL_MIN__.
699  if (SM.isWrittenInBuiltinFile(DefLoc) ||
700  Name->getName() == "__GCC_HAVE_DWARF2_CFI_ASM")
701  return true;
702 
703  auto ID = getSymbolIDCached(Name->getName(), MI, SM);
704  if (!ID)
705  return true;
706 
707  auto SpellingLoc = SM.getSpellingLoc(Loc);
708  bool IsMainFileOnly =
709  SM.isInMainFile(SM.getExpansionLoc(DefLoc)) &&
710  !isHeaderFile(SM.getFileEntryRefForID(SM.getMainFileID())->getName(),
711  ASTCtx->getLangOpts());
712  // Do not store references to main-file macros.
713  if ((static_cast<unsigned>(Opts.RefFilter) & Roles) && !IsMainFileOnly &&
714  (Opts.RefsInHeaders || SM.getFileID(SpellingLoc) == SM.getMainFileID())) {
715  // FIXME: Populate container information for macro references.
716  // FIXME: All MacroRefs are marked as Spelled now, but this should be
717  // checked.
718  addRef(ID, SymbolRef{Loc, SM.getFileID(Loc), Roles, /*Container=*/nullptr,
719  /*Spelled=*/true});
720  }
721 
722  // Collect symbols.
723  if (!Opts.CollectMacro)
724  return true;
725 
726  // Skip main-file macros if we are not collecting them.
727  if (IsMainFileOnly && !Opts.CollectMainFileSymbols)
728  return false;
729 
730  // Mark the macro as referenced if this is a reference coming from the main
731  // file. The macro may not be an interesting symbol, but it's cheaper to check
732  // at the end.
733  if (Opts.CountReferences &&
734  (Roles & static_cast<unsigned>(index::SymbolRole::Reference)) &&
735  SM.getFileID(SpellingLoc) == SM.getMainFileID())
736  ReferencedSymbols.insert(ID);
737 
738  // Don't continue indexing if this is a mere reference.
739  // FIXME: remove macro with ID if it is undefined.
740  if (!(Roles & static_cast<unsigned>(index::SymbolRole::Declaration) ||
741  Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
742  return true;
743 
744  // Only collect one instance in case there are multiple.
745  if (Symbols.find(ID) != nullptr)
746  return true;
747 
748  Symbol S;
749  S.ID = std::move(ID);
750  S.Name = Name->getName();
751  if (!IsMainFileOnly) {
754  }
755  S.SymInfo = index::getSymbolInfoForMacro(*MI);
756  S.Origin = Opts.Origin;
757  // FIXME: use the result to filter out symbols.
758  shouldIndexFile(SM.getFileID(Loc));
759  if (auto DeclLoc = getTokenLocation(DefLoc))
760  S.CanonicalDeclaration = *DeclLoc;
761 
762  CodeCompletionResult SymbolCompletion(Name);
763  const auto *CCS = SymbolCompletion.CreateCodeCompletionStringForMacro(
764  *PP, *CompletionAllocator, *CompletionTUInfo);
765  std::string Signature;
766  std::string SnippetSuffix;
768  S.Signature = Signature;
770 
771  IndexedMacros.insert(Name);
772  setIncludeLocation(S, DefLoc);
773  Symbols.insert(S);
774  return true;
775 }
776 
777 void SymbolCollector::processRelations(
778  const NamedDecl &ND, const SymbolID &ID,
779  ArrayRef<index::SymbolRelation> Relations) {
780  for (const auto &R : Relations) {
781  auto RKind = indexableRelation(R);
782  if (!RKind)
783  continue;
784  const Decl *Object = R.RelatedSymbol;
785 
786  auto ObjectID = getSymbolIDCached(Object);
787  if (!ObjectID)
788  continue;
789 
790  // Record the relation.
791  // TODO: There may be cases where the object decl is not indexed for some
792  // reason. Those cases should probably be removed in due course, but for
793  // now there are two possible ways to handle it:
794  // (A) Avoid storing the relation in such cases.
795  // (B) Store it anyways. Clients will likely lookup() the SymbolID
796  // in the index and find nothing, but that's a situation they
797  // probably need to handle for other reasons anyways.
798  // We currently do (B) because it's simpler.
799  if (*RKind == RelationKind::BaseOf)
800  this->Relations.insert({ID, *RKind, ObjectID});
801  else if (*RKind == RelationKind::OverriddenBy)
802  this->Relations.insert({ObjectID, *RKind, ID});
803  }
804 }
805 
806 void SymbolCollector::setIncludeLocation(const Symbol &S, SourceLocation Loc) {
807  if (Opts.CollectIncludePath)
808  if (shouldCollectIncludePath(S.SymInfo.Kind))
809  // Use the expansion location to get the #include header since this is
810  // where the symbol is exposed.
811  IncludeFiles[S.ID] =
812  PP->getSourceManager().getDecomposedExpansionLoc(Loc).first;
813 }
814 
816  // At the end of the TU, add 1 to the refcount of all referenced symbols.
817  for (const auto &ID : ReferencedSymbols) {
818  if (const auto *S = Symbols.find(ID)) {
819  // SymbolSlab::Builder returns const symbols because strings are interned
820  // and modifying returned symbols without inserting again wouldn't go
821  // well. const_cast is safe here as we're modifying a data owned by the
822  // Symbol. This reduces time spent in SymbolCollector by ~1%.
823  ++const_cast<Symbol *>(S)->References;
824  }
825  }
826  if (Opts.CollectMacro) {
827  assert(PP);
828  // First, drop header guards. We can't identify these until EOF.
829  for (const IdentifierInfo *II : IndexedMacros) {
830  if (const auto *MI = PP->getMacroDefinition(II).getMacroInfo())
831  if (auto ID =
832  getSymbolIDCached(II->getName(), MI, PP->getSourceManager()))
833  if (MI->isUsedForHeaderGuard())
834  Symbols.erase(ID);
835  }
836  }
837  // Fill in IncludeHeaders.
838  // We delay this until end of TU so header guards are all resolved.
839  llvm::SmallString<128> QName;
840  for (const auto &Entry : IncludeFiles) {
841  if (const Symbol *S = Symbols.find(Entry.first)) {
842  llvm::StringRef IncludeHeader;
843  // Look for an overridden include header for this symbol specifically.
844  if (Opts.Includes) {
845  QName = S->Scope;
846  QName.append(S->Name);
847  IncludeHeader = Opts.Includes->mapSymbol(QName);
848  if (!IncludeHeader.empty()) {
849  if (IncludeHeader.front() != '"' && IncludeHeader.front() != '<')
850  IncludeHeader = HeaderFileURIs->toURI(IncludeHeader);
851  else if (IncludeHeader == "<utility>" && QName == "std::move" &&
852  S->Signature.contains(','))
853  IncludeHeader = "<algorithm>";
854  }
855  }
856  // Otherwise find the approprate include header for the defining file.
857  if (IncludeHeader.empty())
858  IncludeHeader = HeaderFileURIs->getIncludeHeader(Entry.second);
859 
860  // Symbols in slabs aren't mutable, insert() has to walk all the strings
861  if (!IncludeHeader.empty()) {
862  Symbol NewSym = *S;
863  NewSym.IncludeHeaders.push_back({IncludeHeader, 1});
864  Symbols.insert(NewSym);
865  }
866  }
867  }
868 
869  ReferencedSymbols.clear();
870  IncludeFiles.clear();
871 }
872 
873 const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND, SymbolID ID,
874  bool IsMainFileOnly) {
875  auto &Ctx = ND.getASTContext();
876  auto &SM = Ctx.getSourceManager();
877 
878  Symbol S;
879  S.ID = std::move(ID);
880  std::string QName = printQualifiedName(ND);
881  // FIXME: this returns foo:bar: for objective-C methods, we prefer only foo:
882  // for consistency with CodeCompletionString and a clean name/signature split.
883  std::tie(S.Scope, S.Name) = splitQualifiedName(QName);
884  std::string TemplateSpecializationArgs = printTemplateSpecializationArgs(ND);
885  S.TemplateSpecializationArgs = TemplateSpecializationArgs;
886 
887  // We collect main-file symbols, but do not use them for code completion.
888  if (!IsMainFileOnly && isIndexedForCodeCompletion(ND, Ctx))
890  if (isImplementationDetail(&ND))
892  if (!IsMainFileOnly)
894  S.SymInfo = index::getSymbolInfo(&ND);
895  auto Loc = nameLocation(ND, SM);
896  assert(Loc.isValid() && "Invalid source location for NamedDecl");
897  // FIXME: use the result to filter out symbols.
898  shouldIndexFile(SM.getFileID(Loc));
899  if (auto DeclLoc = getTokenLocation(Loc))
900  S.CanonicalDeclaration = *DeclLoc;
901 
902  S.Origin = Opts.Origin;
903  if (ND.getAvailability() == AR_Deprecated)
905 
906  // Add completion info.
907  // FIXME: we may want to choose a different redecl, or combine from several.
908  assert(ASTCtx && PP && "ASTContext and Preprocessor must be set.");
909  // We use the primary template, as clang does during code completion.
910  CodeCompletionResult SymbolCompletion(&getTemplateOrThis(ND), 0);
911  const auto *CCS = SymbolCompletion.CreateCodeCompletionString(
912  *ASTCtx, *PP, CodeCompletionContext::CCC_Symbol, *CompletionAllocator,
913  *CompletionTUInfo,
914  /*IncludeBriefComments*/ false);
915  std::string Documentation =
916  formatDocumentation(*CCS, getDocComment(Ctx, SymbolCompletion,
917  /*CommentsFromHeaders=*/true));
919  if (Opts.StoreAllDocumentation)
920  S.Documentation = Documentation;
921  Symbols.insert(S);
922  return Symbols.find(S.ID);
923  }
924  S.Documentation = Documentation;
925  std::string Signature;
926  std::string SnippetSuffix;
928  S.Signature = Signature;
930  std::string ReturnType = getReturnType(*CCS);
932 
933  llvm::Optional<OpaqueType> TypeStorage;
935  TypeStorage = OpaqueType::fromCompletionResult(*ASTCtx, SymbolCompletion);
936  if (TypeStorage)
937  S.Type = TypeStorage->raw();
938  }
939 
940  Symbols.insert(S);
941  setIncludeLocation(S, ND.getLocation());
942  return Symbols.find(S.ID);
943 }
944 
945 void SymbolCollector::addDefinition(const NamedDecl &ND,
946  const Symbol &DeclSym) {
947  if (DeclSym.Definition)
948  return;
949  const auto &SM = ND.getASTContext().getSourceManager();
950  auto Loc = nameLocation(ND, SM);
951  shouldIndexFile(SM.getFileID(Loc));
952  auto DefLoc = getTokenLocation(Loc);
953  // If we saw some forward declaration, we end up copying the symbol.
954  // This is not ideal, but avoids duplicating the "is this a definition" check
955  // in clang::index. We should only see one definition.
956  if (!DefLoc)
957  return;
958  Symbol S = DeclSym;
959  // FIXME: use the result to filter out symbols.
960  S.Definition = *DefLoc;
961  Symbols.insert(S);
962 }
963 
965  if (!Opts.FileFilter)
966  return true;
967  auto I = FilesToIndexCache.try_emplace(FID);
968  if (I.second)
969  I.first->second = Opts.FileFilter(ASTCtx->getSourceManager(), FID);
970  return I.first->second;
971 }
972 
973 void SymbolCollector::addRef(SymbolID ID, const SymbolRef &SR) {
974  const auto &SM = ASTCtx->getSourceManager();
975  // FIXME: use the result to filter out references.
976  shouldIndexFile(SR.FID);
977  if (const auto *FE = SM.getFileEntryForID(SR.FID)) {
978  auto Range = getTokenRange(SR.Loc, SM, ASTCtx->getLangOpts());
979  Ref R;
980  R.Location.Start = Range.first;
981  R.Location.End = Range.second;
982  R.Location.FileURI = HeaderFileURIs->toURI(FE).c_str();
983  R.Kind = toRefKind(SR.Roles, SR.Spelled);
984  R.Container = getSymbolIDCached(SR.Container);
985  Refs.insert(ID, R);
986  }
987 }
988 
989 SymbolID SymbolCollector::getSymbolIDCached(const Decl *D) {
990  auto It = DeclToIDCache.try_emplace(D, SymbolID{});
991  if (It.second)
992  It.first->second = getSymbolID(D);
993  return It.first->second;
994 }
995 
996 SymbolID SymbolCollector::getSymbolIDCached(const llvm::StringRef MacroName,
997  const MacroInfo *MI,
998  const SourceManager &SM) {
999  auto It = MacroToIDCache.try_emplace(MI, SymbolID{});
1000  if (It.second)
1001  It.first->second = getSymbolID(MacroName, MI, SM);
1002  return It.first->second;
1003 }
1004 } // namespace clangd
1005 } // namespace clang
clang::clangd::Ref::Kind
RefKind Kind
Definition: Ref.h:88
clang::clangd::Symbol::IndexedForCodeCompletion
@ IndexedForCodeCompletion
Whether or not this symbol is meant to be used for the code completion.
Definition: Symbol.h:119
Range
CharSourceRange Range
SourceRange for the file name.
Definition: IncludeOrderCheck.cpp:38
Loc
SourceLocation Loc
Definition: KernelNameRestrictionCheck.cpp:45
SymbolID.h
References
unsigned References
Definition: CodeComplete.cpp:178
clang::clangd::RelationKind::BaseOf
@ BaseOf
clang::clangd::SymbolCollector::HeaderFileURICache::toURI
const std::string & toURI(llvm::StringRef Path)
Definition: SymbolCollector.cpp:241
E
const Expr * E
Definition: AvoidBindCheck.cpp:88
clang::clangd::SymbolLocation::End
Position End
Definition: SymbolLocation.h:54
CodeComplete.h
clang::clangd::Symbol::ID
SymbolID ID
The ID of the symbol.
Definition: Symbol.h:38
clang::clangd::RefKind::Unknown
@ Unknown
clang::clangd::SymbolCollector::handleMacros
void handleMacros(const MainFileMacros &MacroRefsToIndex)
Definition: SymbolCollector.cpp:643
clang::clangd::RefKind::Declaration
@ Declaration
clang::clangd::Path
std::string Path
A typedef to represent a file path.
Definition: Path.h:26
clang::clangd::SymbolCollector::HeaderFileURICache::getIncludeHeader
llvm::StringRef getIncludeHeader(FileID FID)
Definition: SymbolCollector.cpp:251
SymbolLocation.h
clang::clangd::SymbolCollector::shouldCollectSymbol
static bool shouldCollectSymbol(const NamedDecl &ND, const ASTContext &ASTCtx, const Options &Opts, bool IsMainFileSymbol)
Returns true is ND should be collected.
Definition: SymbolCollector.cpp:466
clang::clangd::SymbolCollector::handleDeclOccurrence
bool handleDeclOccurrence(const Decl *D, index::SymbolRoleSet Roles, ArrayRef< index::SymbolRelation > Relations, SourceLocation Loc, index::IndexDataConsumer::ASTNodeInfo ASTNode) override
Definition: SymbolCollector.cpp:521
clang::clangd::ParsedAST::getASTContext
ASTContext & getASTContext()
Note that the returned ast will not contain decls from the preamble that were not deserialized during...
Definition: ParsedAST.cpp:697
clang::clangd::SymbolKind::Object
@ Object
clang::clangd::splitQualifiedName
std::pair< StringRef, StringRef > splitQualifiedName(StringRef QName)
Definition: SourceCode.cpp:488
clang::clangd::RefKind
RefKind
Describes the kind of a cross-reference.
Definition: Ref.h:28
clang::clangd::SymbolSlab::Builder::erase
void erase(const SymbolID &ID)
Removes the symbol with an ID, if it exists.
Definition: Symbol.h:209
clang::clangd::SymbolSlab::Builder::find
const Symbol * find(const SymbolID &ID)
Returns the symbol with an ID, if it exists. Valid until insert/remove.
Definition: Symbol.h:212
clang::clangd::URI::create
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
Definition: URI.cpp:209
clang::clangd::OpaqueType::fromCompletionResult
static llvm::Optional< OpaqueType > fromCompletionResult(ASTContext &Ctx, const CodeCompletionResult &R)
Create a type from a code completion result.
Definition: ExpectedTypes.cpp:86
Kind
BindArgumentKind Kind
Definition: AvoidBindCheck.cpp:59
clang::clangd::SymbolLocation::Start
Position Start
The symbol range, using half-open range [Start, End).
Definition: SymbolLocation.h:53
Filename
std::string Filename
Filename as a string.
Definition: IncludeOrderCheck.cpp:39
clang::clangd::Symbol::Deprecated
@ Deprecated
Indicates if the symbol is deprecated.
Definition: Symbol.h:121
clang::clangd::Range::start
Position start
The range's start position.
Definition: Protocol.h:184
clang::clangd::SymbolCollector::shouldIndexFile
bool shouldIndexFile(FileID FID)
Returns true if we are interested in references and declarations from FID.
Definition: SymbolCollector.cpp:964
Ctx
Context Ctx
Definition: TUScheduler.cpp:495
clang::clangd::Symbol::VisibleOutsideFile
@ VisibleOutsideFile
Symbol is visible to other files (not e.g. a static helper function).
Definition: Symbol.h:125
llvm::sys
Definition: BenchmarkHeader.h:10
clang::clangd::MainFileMacros::MacroRefs
llvm::DenseMap< SymbolID, std::vector< MacroOccurrence > > MacroRefs
Definition: CollectMacros.h:31
clang::clangd::SymbolCollector::finish
void finish() override
Definition: SymbolCollector.cpp:815
clang::clangd::nameLocation
SourceLocation nameLocation(const clang::Decl &D, const SourceManager &SM)
Find the source location of the identifier for D.
Definition: AST.cpp:167
clang::clangd::sourceLocToPosition
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
Definition: SourceCode.cpp:213
clang::clangd::SymbolCollector::HeaderFileURICache
Definition: SymbolCollector.cpp:199
clang::clangd::getDocComment
std::string getDocComment(const ASTContext &Ctx, const CodeCompletionResult &Result, bool CommentsFromHeaders)
Gets a minimally formatted documentation comment of Result, with comment markers stripped.
Definition: CodeCompletionStrings.cpp:61
clang::clangd::ParsedAST::getLangOpts
const LangOptions & getLangOpts() const
Definition: ParsedAST.h:80
Pos
size_t Pos
Definition: NoLintDirectiveHandler.cpp:97
clang::clangd::Position::line
int line
Line position in a document (zero-based).
Definition: Protocol.h:155
run-clang-tidy.make_absolute
def make_absolute(f, directory)
Definition: run-clang-tidy.py:86
clang::clangd::isSelfContainedHeader
bool isSelfContainedHeader(const FileEntry *FE, FileID FID, const SourceManager &SM, HeaderSearch &HeaderInfo)
This scans source code, and should not be called when using a preamble.
Definition: SourceCode.cpp:1222
clang::clangd::formatDocumentation
std::string formatDocumentation(const CodeCompletionString &CCS, llvm::StringRef DocComment)
Assembles formatted documentation for a completion result.
Definition: CodeCompletionStrings.cpp:241
Relation.h
clang::clangd::Symbol::ReturnType
llvm::StringRef ReturnType
Type when this symbol is used in an expression.
Definition: Symbol.h:80
CanonicalIncludes.h
ns1::ns2::D
@ D
Definition: CategoricalFeature.h:3
clang::clangd::SymbolCollector::HeaderFileURICache::toURI
const std::string & toURI(const FileEntry *FE)
Definition: SymbolCollector.cpp:229
Decl
const FunctionDecl * Decl
Definition: AvoidBindCheck.cpp:100
CodeCompletionStrings.h
clang::clangd::getCanonicalPath
llvm::Optional< std::string > getCanonicalPath(const FileEntry *F, const SourceManager &SourceMgr)
Get the canonical path of F.
Definition: SourceCode.cpp:511
clang::clangd::Ref::Container
SymbolID Container
The ID of the symbol whose definition contains this reference.
Definition: Ref.h:92
clang::clangd::CanonicalIncludes
Maps a definition location onto an #include file, based on a set of filename rules.
Definition: CanonicalIncludes.h:37
clang::clangd::Ref::Location
SymbolLocation Location
The source location where the symbol is named.
Definition: Ref.h:87
clang::clangd::printQualifiedName
std::string printQualifiedName(const NamedDecl &ND)
Returns the qualified name of ND.
Definition: AST.cpp:174
clang::clangd::Symbol::Origin
SymbolOrigin Origin
Where this symbol came from. Usually an index provides a constant value.
Definition: Symbol.h:61
clang::clangd::Symbol::ImplementationDetail
@ ImplementationDetail
Symbol is an implementation detail.
Definition: Symbol.h:123
clang::clangd::getSymbolInfo
std::vector< SymbolDetails > getSymbolInfo(ParsedAST &AST, Position Pos)
Get info about symbols at Pos.
Definition: XRefs.cpp:1514
clang::clangd::MainFileMacros
Definition: CollectMacros.h:29
clang::clangd::Symbol
The class presents a C++ symbol, e.g.
Definition: Symbol.h:36
clang::clangd::Symbol::Flags
SymbolFlag Flags
Definition: Symbol.h:128
clang::clangd::Symbol::SymInfo
index::SymbolInfo SymInfo
The symbol information, like symbol kind.
Definition: Symbol.h:40
clang::clangd::printTemplateSpecializationArgs
std::string printTemplateSpecializationArgs(const NamedDecl &ND)
Prints template arguments of a decl as written in the source code, including enclosing '<' and '>',...
Definition: AST.cpp:254
clang::clangd::SymbolLocation::FileURI
const char * FileURI
Definition: SymbolLocation.h:64
ExpectedTypes.h
clang::clangd::SymbolLocation::Position::setColumn
void setColumn(uint32_t Column)
Definition: SymbolLocation.cpp:22
SnippetSuffix
std::string SnippetSuffix
Definition: CodeComplete.cpp:450
clang::clangd::Position::character
int character
Character offset on a line in a document (zero-based).
Definition: Protocol.h:160
clang::clangd::hasReservedScope
bool hasReservedScope(const DeclContext &DC)
Returns true if this scope would be written with a reserved name.
Definition: AST.cpp:387
clang::clangd::RefKind::Reference
@ Reference
clang::clangd::RefSlab::Builder::insert
void insert(const SymbolID &ID, const Ref &S)
Adds a ref to the slab. Deep copy: Strings will be owned by the slab.
Definition: Ref.cpp:36
clang::clangd::Range::end
Position end
The range's end position.
Definition: Protocol.h:187
clang::clangd::Symbol::Name
llvm::StringRef Name
The unqualified name of the symbol, e.g. "bar" (for ns::bar).
Definition: Symbol.h:42
clang::doc::SymbolID
std::array< uint8_t, 20 > SymbolID
Definition: Representation.h:30
Name
Token Name
Definition: MacroToEnumCheck.cpp:89
clang::clangd::isIndexedForCodeCompletion
bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx)
Definition: CodeComplete.cpp:2087
SymbolKind
clang::find_all_symbols::SymbolInfo::SymbolKind SymbolKind
Definition: SymbolInfo.cpp:19
clang::clangd::Symbol::CanonicalDeclaration
SymbolLocation CanonicalDeclaration
The location of the preferred declaration of the symbol.
Definition: Symbol.h:56
clang::clangd::isProtoFile
bool isProtoFile(SourceLocation Loc, const SourceManager &SM)
Returns true if the given location is in a generated protobuf file.
Definition: SourceCode.cpp:1170
Entry
Definition: Modularize.cpp:427
clang::clangd::getSymbolID
SymbolID getSymbolID(const Decl *D)
Gets the symbol ID for a declaration. Returned SymbolID might be null.
Definition: AST.cpp:337
SourceCode.h
clang::clangd::Symbol::CompletionSnippetSuffix
llvm::StringRef CompletionSnippetSuffix
What to insert when completing this symbol, after the symbol name.
Definition: Symbol.h:74
clang::clangd::SymbolCollector::handleMacroOccurrence
bool handleMacroOccurrence(const IdentifierInfo *Name, const MacroInfo *MI, index::SymbolRoleSet Roles, SourceLocation Loc) override
Definition: SymbolCollector.cpp:687
clang::clangd::isHeaderFile
bool isHeaderFile(llvm::StringRef FileName, llvm::Optional< LangOptions > LangOpts)
Infers whether this is a header from the FileName and LangOpts (if presents).
Definition: SourceCode.cpp:1158
clang::clangd::RefKind::Spelled
@ Spelled
ID
static char ID
Definition: Logger.cpp:74
clang::clangd::Ref
Represents a symbol occurrence in the source file.
Definition: Ref.h:85
clang::clangd::getSignature
void getSignature(const CodeCompletionString &CCS, std::string *Signature, std::string *Snippet, std::string *RequiredQualifiers, bool CompletingPattern)
Formats the signature for an item, as a display string and snippet.
Definition: CodeCompletionStrings.cpp:97
clang::clangd::SymbolCollector::initialize
void initialize(ASTContext &Ctx) override
Definition: SymbolCollector.cpp:457
clang::clangd::Symbol::TemplateSpecializationArgs
llvm::StringRef TemplateSpecializationArgs
Argument list in human-readable format, will be displayed to help disambiguate between different spec...
Definition: Symbol.h:69
clang::tidy::bugprone::model::MixFlags::None
@ None
Mix between the two parameters is not possible.
clang::clangd::Range
Definition: Protocol.h:182
C
const Criteria C
Definition: FunctionCognitiveComplexityCheck.cpp:93
clang::clangd::SymbolLocation::Position::setLine
void setLine(uint32_t Line)
Definition: SymbolLocation.cpp:17
clang::clangd::Symbol::Scope
llvm::StringRef Scope
The containing namespace. e.g. "" (global), "ns::" (top-level namespace).
Definition: Symbol.h:44
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::tidy::bugprone::model::MixFlags::Canonical
@ Canonical
The two mix because the types refer to the same CanonicalType, but we do not elaborate as to how.
clang::clangd::isInsideMainFile
bool isInsideMainFile(SourceLocation Loc, const SourceManager &SM)
Returns true iff Loc is inside the main file.
Definition: SourceCode.cpp:414
clang::clangd::SymbolCollector::Options
Definition: SymbolCollector.h:51
LangOpts
const LangOptions * LangOpts
Definition: ExtractFunction.cpp:366
SymbolCollector.h
clang::clangd::SymbolCollector::HeaderFileURICache::HeaderFileURICache
HeaderFileURICache(Preprocessor *&PP, const SourceManager &SM, const SymbolCollector::Options &Opts)
Definition: SymbolCollector.cpp:222
clang::clangd::Symbol::Definition
SymbolLocation Definition
The location of the symbol's definition, if one was found.
Definition: Symbol.h:47
clang::clangd::getReturnType
std::string getReturnType(const CodeCompletionString &CCS)
Gets detail to be used as the detail field in an LSP completion item.
Definition: CodeCompletionStrings.cpp:271
clang::clangd::hasReservedName
bool hasReservedName(const Decl &D)
Returns true if this is a NamedDecl with a reserved name.
Definition: AST.cpp:380
clang::clangd::isImplementationDetail
bool isImplementationDetail(const Decl *D)
Returns true if the declaration is considered implementation detail based on heuristics.
Definition: AST.cpp:162
ReturnType
std::string ReturnType
Definition: CodeComplete.cpp:452
URI.h
clang::clangd::SymbolID
Definition: SymbolID.h:32
clang::clangd::Symbol::Signature
llvm::StringRef Signature
A brief description of the symbol that can be appended in the completion candidate list.
Definition: Symbol.h:65
clang::clangd::RefKind::Definition
@ Definition
clang::clangd::Symbol::Type
llvm::StringRef Type
Raw representation of the OpaqueType of the symbol, used for scoring purposes.
Definition: Symbol.h:85
clang::clangd::ParsedAST::getSourceManager
SourceManager & getSourceManager()
Definition: ParsedAST.h:73
clang::clangd::SymbolCollector::SymbolCollector
SymbolCollector(Options Opts)
Definition: SymbolCollector.cpp:454
clang::clangd::Symbol::IncludeHeaders
llvm::SmallVector< IncludeHeaderWithReferences, 1 > IncludeHeaders
One Symbol can potentially be included via different headers.
Definition: Symbol.h:111
clang::clangd::RelationKind::OverriddenBy
@ OverriddenBy
clang::clangd::toSourceCode
llvm::StringRef toSourceCode(const SourceManager &SM, SourceRange R)
Returns the source code covered by the source range.
Definition: SourceCode.cpp:443
clang::clangd::ASTNode
Simplified description of a clang AST node.
Definition: Protocol.h:1815
clang::clangd::Symbol::Documentation
llvm::StringRef Documentation
Documentation including comment for the symbol declaration.
Definition: Symbol.h:76
clang::clangd::sourceLocationInMainFile
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
Definition: SourceCode.cpp:453
clang::clangd::SymbolSlab::Builder::insert
void insert(const Symbol &S)
Adds a symbol, overwriting any existing one with the same ID.
Definition: Symbol.cpp:50
Signature
std::string Signature
Definition: CodeComplete.cpp:451
AST.h
clang::clangd::SymbolCollector::~SymbolCollector
~SymbolCollector()