clang-tools 10.0.0

XRefs.cpp
Go to the documentation of this file.
1 //===--- XRefs.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 #include "XRefs.h"
9 #include "AST.h"
10 #include "CodeCompletionStrings.h"
11 #include "FindSymbols.h"
12 #include "FindTarget.h"
13 #include "Logger.h"
14 #include "ParsedAST.h"
15 #include "Protocol.h"
16 #include "Selection.h"
17 #include "SourceCode.h"
18 #include "URI.h"
19 #include "index/Index.h"
20 #include "index/Merge.h"
21 #include "index/Relation.h"
22 #include "index/SymbolLocation.h"
23 #include "clang/AST/ASTContext.h"
24 #include "clang/AST/Decl.h"
25 #include "clang/AST/DeclCXX.h"
26 #include "clang/AST/DeclTemplate.h"
27 #include "clang/AST/ExprCXX.h"
28 #include "clang/AST/Type.h"
29 #include "clang/Basic/LLVM.h"
30 #include "clang/Basic/SourceLocation.h"
31 #include "clang/Basic/SourceManager.h"
32 #include "clang/Index/IndexDataConsumer.h"
33 #include "clang/Index/IndexSymbol.h"
34 #include "clang/Index/IndexingAction.h"
35 #include "clang/Index/IndexingOptions.h"
36 #include "clang/Index/USRGeneration.h"
37 #include "llvm/ADT/ArrayRef.h"
38 #include "llvm/ADT/None.h"
39 #include "llvm/ADT/STLExtras.h"
40 #include "llvm/ADT/StringExtras.h"
41 #include "llvm/ADT/StringRef.h"
42 #include "llvm/Support/Casting.h"
43 #include "llvm/Support/Path.h"
44 #include "llvm/Support/raw_ostream.h"
45
46 namespace clang {
47 namespace clangd {
48 namespace {
49
50 // Returns the single definition of the entity declared by D, if visible.
51 // In particular:
52 // - for non-redeclarable kinds (e.g. local vars), return D
53 // - for kinds that allow multiple definitions (e.g. namespaces), return nullptr
54 // Kinds of nodes that always return nullptr here will not have definitions
55 // reported by locateSymbolAt().
56 const NamedDecl *getDefinition(const NamedDecl *D) {
57 assert(D);
58 // Decl has one definition that we can find.
59 if (const auto *TD = dyn_cast<TagDecl>(D))
60 return TD->getDefinition();
61 if (const auto *VD = dyn_cast<VarDecl>(D))
62 return VD->getDefinition();
63 if (const auto *FD = dyn_cast<FunctionDecl>(D))
64 return FD->getDefinition();
65 // Only a single declaration is allowed.
66 if (isa<ValueDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
67 isa<TemplateTemplateParmDecl>(D)) // except cases above
68 return D;
69 // Multiple definitions are allowed.
70 return nullptr; // except cases above
71 }
72
73 void logIfOverflow(const SymbolLocation &Loc) {
74 if (Loc.Start.hasOverflow() || Loc.End.hasOverflow())
75 log("Possible overflow in symbol location: {0}", Loc);
76 }
77
78 // Convert a SymbolLocation to LSP's Location.
79 // TUPath is used to resolve the path of URI.
80 // FIXME: figure out a good home for it, and share the implementation with
81 // FindSymbols.
82 llvm::Optional<Location> toLSPLocation(const SymbolLocation &Loc,
83 llvm::StringRef TUPath) {
84 if (!Loc)
85 return None;
86 auto Uri = URI::parse(Loc.FileURI);
87 if (!Uri) {
88 elog("Could not parse URI {0}: {1}", Loc.FileURI, Uri.takeError());
89 return None;
90 }
91 auto U = URIForFile::fromURI(*Uri, TUPath);
92 if (!U) {
93 elog("Could not resolve URI {0}: {1}", Loc.FileURI, U.takeError());
94 return None;
95 }
96
97 Location LSPLoc;
98 LSPLoc.uri = std::move(*U);
99 LSPLoc.range.start.line = Loc.Start.line();
100 LSPLoc.range.start.character = Loc.Start.column();
101 LSPLoc.range.end.line = Loc.End.line();
102 LSPLoc.range.end.character = Loc.End.column();
103 logIfOverflow(Loc);
104 return LSPLoc;
105 }
106
107 SymbolLocation toIndexLocation(const Location &Loc, std::string &URIStorage) {
108 SymbolLocation SymLoc;
109 URIStorage = Loc.uri.uri();
110 SymLoc.FileURI = URIStorage.c_str();
111 SymLoc.Start.setLine(Loc.range.start.line);
112 SymLoc.Start.setColumn(Loc.range.start.character);
113 SymLoc.End.setLine(Loc.range.end.line);
114 SymLoc.End.setColumn(Loc.range.end.character);
115 return SymLoc;
116 }
117
118 // Returns the preferred location between an AST location and an index location.
119 SymbolLocation getPreferredLocation(const Location &ASTLoc,
120 const SymbolLocation &IdxLoc,
121 std::string &Scratch) {
122 // Also use a dummy symbol for the index location so that other fields (e.g.
123 // definition) are not factored into the preference.
124 Symbol ASTSym, IdxSym;
125 ASTSym.ID = IdxSym.ID = SymbolID("dummy_id");
126 ASTSym.CanonicalDeclaration = toIndexLocation(ASTLoc, Scratch);
127 IdxSym.CanonicalDeclaration = IdxLoc;
128 auto Merged = mergeSymbol(ASTSym, IdxSym);
129 return Merged.CanonicalDeclaration;
130 }
131
132 std::vector<const NamedDecl *> getDeclAtPosition(ParsedAST &AST,
133 SourceLocation Pos,
134 DeclRelationSet Relations) {
135 FileID FID;
136 unsigned Offset;
137 std::tie(FID, Offset) = AST.getSourceManager().getDecomposedSpellingLoc(Pos);
138 SelectionTree Selection(AST.getASTContext(), AST.getTokens(), Offset);
139 std::vector<const NamedDecl *> Result;
140 if (const SelectionTree::Node *N = Selection.commonAncestor()) {
141 auto Decls = targetDecl(N->ASTNode, Relations);
142 Result.assign(Decls.begin(), Decls.end());
143 }
144 return Result;
145 }
146
147 llvm::Optional<Location> makeLocation(ASTContext &AST, SourceLocation TokLoc,
148 llvm::StringRef TUPath) {
149 const SourceManager &SourceMgr = AST.getSourceManager();
150 const FileEntry *F = SourceMgr.getFileEntryForID(SourceMgr.getFileID(TokLoc));
151 if (!F)
152 return None;
153 auto FilePath = getCanonicalPath(F, SourceMgr);
154 if (!FilePath) {
155 log("failed to get path!");
156 return None;
157 }
158 if (auto Range =
159 getTokenRange(AST.getSourceManager(), AST.getLangOpts(), TokLoc)) {
160 Location L;
161 L.uri = URIForFile::canonicalize(*FilePath, TUPath);
162 L.range = *Range;
163 return L;
164 }
165 return None;
166 }
167
168 } // namespace
169
170 std::vector<DocumentLink> getDocumentLinks(ParsedAST &AST) {
171 const auto &SM = AST.getSourceManager();
172 auto MainFilePath =
173 getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
174 if (!MainFilePath) {
175 elog("Failed to get a path for the main file, so no links");
176 return {};
177 }
178
179 std::vector<DocumentLink> Result;
180 for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) {
181 if (!Inc.Resolved.empty()) {
182 Result.push_back(DocumentLink(
183 {Inc.R, URIForFile::canonicalize(Inc.Resolved, *MainFilePath)}));
184 }
185 }
186
187 return Result;
188 }
189
190 std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos,
191 const SymbolIndex *Index) {
192 const auto &SM = AST.getSourceManager();
193 auto MainFilePath =
194 getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
195 if (!MainFilePath) {
196 elog("Failed to get a path for the main file, so no references");
197 return {};
198 }
199
200 // Treat #included files as symbols, to enable go-to-definition on them.
201 for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) {
202 if (!Inc.Resolved.empty() && Inc.R.start.line == Pos.line) {
203 LocatedSymbol File;
204 File.Name = llvm::sys::path::filename(Inc.Resolved);
205 File.PreferredDeclaration = {
206 URIForFile::canonicalize(Inc.Resolved, *MainFilePath), Range{}};
207 File.Definition = File.PreferredDeclaration;
208 // We're not going to find any further symbols on #include lines.
209 return {std::move(File)};
210 }
211 }
212
213 // Macros are simple: there's no declaration/definition distinction.
214 // As a consequence, there's no need to look them up in the index either.
215 SourceLocation IdentStartLoc = SM.getMacroArgExpandedLocation(
216 getBeginningOfIdentifier(Pos, AST.getSourceManager(), AST.getLangOpts()));
217 std::vector<LocatedSymbol> Result;
218 if (auto M = locateMacroAt(IdentStartLoc, AST.getPreprocessor())) {
219 if (auto Loc = makeLocation(AST.getASTContext(),
220 M->Info->getDefinitionLoc(), *MainFilePath)) {
221 LocatedSymbol Macro;
222 Macro.Name = M->Name;
223 Macro.PreferredDeclaration = *Loc;
224 Macro.Definition = Loc;
225 Result.push_back(std::move(Macro));
226
227 // Don't look at the AST or index if we have a macro result.
228 // (We'd just return declarations referenced from the macro's
229 // expansion.)
230 return Result;
231 }
232 }
233
234 // Decls are more complicated.
235 // The AST contains at least a declaration, maybe a definition.
236 // These are up-to-date, and so generally preferred over index results.
237 // We perform a single batch index lookup to find additional definitions.
238
239 // Results follow the order of Symbols.Decls.
240 // Keep track of SymbolID -> index mapping, to fill in index data later.
241 llvm::DenseMap<SymbolID, size_t> ResultIndex;
242
243 SourceLocation SourceLoc;
244 if (auto L = sourceLocationInMainFile(SM, Pos)) {
245 SourceLoc = *L;
246 } else {
247 elog("locateSymbolAt failed to convert position to source location: {0}",
248 L.takeError());
249 return Result;
250 }
251
252 // Emit all symbol locations (declaration or definition) from AST.
253 DeclRelationSet Relations =
254 DeclRelation::TemplatePattern | DeclRelation::Alias;
255 for (const NamedDecl *D : getDeclAtPosition(AST, SourceLoc, Relations)) {
256 const NamedDecl *Def = getDefinition(D);
257 const NamedDecl *Preferred = Def ? Def : D;
258
259 // If we're at the point of declaration of a template specialization,
260 // it's more useful to navigate to the template declaration.
261 if (SM.getMacroArgExpandedLocation(Preferred->getLocation()) ==
262 IdentStartLoc) {
263 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Preferred)) {
264 D = CTSD->getSpecializedTemplate();
265 Def = getDefinition(D);
266 Preferred = Def ? Def : D;
267 }
268 }
269
270 auto Loc = makeLocation(AST.getASTContext(), nameLocation(*Preferred, SM),
271 *MainFilePath);
272 if (!Loc)
273 continue;
274
275 Result.emplace_back();
276 Result.back().Name = printName(AST.getASTContext(), *D);
277 Result.back().PreferredDeclaration = *Loc;
278 // Preferred is always a definition if possible, so this check works.
279 if (Def == Preferred)
280 Result.back().Definition = *Loc;
281
282 // Record SymbolID for index lookup later.
283 if (auto ID = getSymbolID(Preferred))
284 ResultIndex[*ID] = Result.size() - 1;
285 }
286
287 // Now query the index for all Symbol IDs we found in the AST.
288 if (Index && !ResultIndex.empty()) {
289 LookupRequest QueryRequest;
290 for (auto It : ResultIndex)
291 QueryRequest.IDs.insert(It.first);
292 std::string Scratch;
293 Index->lookup(QueryRequest, [&](const Symbol &Sym) {
294 auto &R = Result[ResultIndex.lookup(Sym.ID)];
295
296 if (R.Definition) { // from AST
297 // Special case: if the AST yielded a definition, then it may not be
298 // the right *declaration*. Prefer the one from the index.
299 if (auto Loc = toLSPLocation(Sym.CanonicalDeclaration, *MainFilePath))
300 R.PreferredDeclaration = *Loc;
301
302 // We might still prefer the definition from the index, e.g. for
303 // generated symbols.
304 if (auto Loc = toLSPLocation(
305 getPreferredLocation(*R.Definition, Sym.Definition, Scratch),
306 *MainFilePath))
307 R.Definition = *Loc;
308 } else {
309 R.Definition = toLSPLocation(Sym.Definition, *MainFilePath);
310
311 // Use merge logic to choose AST or index declaration.
312 if (auto Loc = toLSPLocation(
313 getPreferredLocation(R.PreferredDeclaration,
314 Sym.CanonicalDeclaration, Scratch),
315 *MainFilePath))
316 R.PreferredDeclaration = *Loc;
317 }
318 });
319 }
320
321 return Result;
322 }
323
324 namespace {
325
326 /// Collects references to symbols within the main file.
327 class ReferenceFinder : public index::IndexDataConsumer {
328 public:
329 struct Reference {
330 SourceLocation Loc;
331 index::SymbolRoleSet Role;
332 };
333
334 ReferenceFinder(ASTContext &AST, Preprocessor &PP,
335 const std::vector<const NamedDecl *> &TargetDecls)
336 : AST(AST) {
337 for (const NamedDecl *D : TargetDecls)
338 CanonicalTargets.insert(D->getCanonicalDecl());
339 }
340
341 std::vector<Reference> take() && {
342 llvm::sort(References, [](const Reference &L, const Reference &R) {
343 return std::tie(L.Loc, L.Role) < std::tie(R.Loc, R.Role);
344 });
345 // We sometimes see duplicates when parts of the AST get traversed twice.
346 References.erase(std::unique(References.begin(), References.end(),
347 [](const Reference &L, const Reference &R) {
348 return std::tie(L.Loc, L.Role) ==
349 std::tie(R.Loc, R.Role);
350 }),
351 References.end());
352 return std::move(References);
353 }
354
355 bool
356 handleDeclOccurrence(const Decl *D, index::SymbolRoleSet Roles,
357 llvm::ArrayRef<index::SymbolRelation> Relations,
358 SourceLocation Loc,
359 index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
360 assert(D->isCanonicalDecl() && "expect D to be a canonical declaration");
361 const SourceManager &SM = AST.getSourceManager();
362 Loc = SM.getFileLoc(Loc);
363 if (isInsideMainFile(Loc, SM) && CanonicalTargets.count(D))
364 References.push_back({Loc, Roles});
365 return true;
366 }
367
368 private:
369 llvm::SmallSet<const Decl *, 4> CanonicalTargets;
370 std::vector<Reference> References;
371 const ASTContext &AST;
372 };
373
374 std::vector<ReferenceFinder::Reference>
375 findRefs(const std::vector<const NamedDecl *> &Decls, ParsedAST &AST) {
376 ReferenceFinder RefFinder(AST.getASTContext(), AST.getPreprocessor(), Decls);
377 index::IndexingOptions IndexOpts;
378 IndexOpts.SystemSymbolFilter =
379 index::IndexingOptions::SystemSymbolFilterKind::All;
380 IndexOpts.IndexFunctionLocals = true;
381 IndexOpts.IndexParametersInDeclarations = true;
382 IndexOpts.IndexTemplateParameters = true;
383 indexTopLevelDecls(AST.getASTContext(), AST.getPreprocessor(),
384 AST.getLocalTopLevelDecls(), RefFinder, IndexOpts);
385 return std::move(RefFinder).take();
386 }
387
388 } // namespace
389
390 std::vector<DocumentHighlight> findDocumentHighlights(ParsedAST &AST,
391 Position Pos) {
392 const SourceManager &SM = AST.getSourceManager();
393 // FIXME: show references to macro within file?
394 DeclRelationSet Relations =
395 DeclRelation::TemplatePattern | DeclRelation::Alias;
396 auto References = findRefs(
397 getDeclAtPosition(AST,
398 SM.getMacroArgExpandedLocation(getBeginningOfIdentifier(
399 Pos, SM, AST.getLangOpts())),
400 Relations),
401 AST);
402
403 // FIXME: we may get multiple DocumentHighlights with the same location and
404 // different kinds, deduplicate them.
405 std::vector<DocumentHighlight> Result;
406 for (const auto &Ref : References) {
407 if (auto Range =
408 getTokenRange(AST.getSourceManager(), AST.getLangOpts(), Ref.Loc)) {
409 DocumentHighlight DH;
410 DH.range = *Range;
411 if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Write))
412 DH.kind = DocumentHighlightKind::Write;
413 else if (Ref.Role & index::SymbolRoleSet(index::SymbolRole::Read))
414 DH.kind = DocumentHighlightKind::Read;
415 else
416 DH.kind = DocumentHighlightKind::Text;
417 Result.push_back(std::move(DH));
418 }
419 }
420 return Result;
421 }
422
423 ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
424 const SymbolIndex *Index) {
425 if (!Limit)
426 Limit = std::numeric_limits<uint32_t>::max();
427 ReferencesResult Results;
428 const SourceManager &SM = AST.getSourceManager();
429 auto MainFilePath =
430 getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
431 if (!MainFilePath) {
432 elog("Failed to get a path for the main file, so no references");
433 return Results;
434 }
435 auto URIMainFile = URIForFile::canonicalize(*MainFilePath, *MainFilePath);
436 auto Loc = SM.getMacroArgExpandedLocation(
437 getBeginningOfIdentifier(Pos, SM, AST.getLangOpts()));
438 RefsRequest Req;
439
440 if (auto Macro = locateMacroAt(Loc, AST.getPreprocessor())) {
441 // Handle references to macro.
442 if (auto MacroSID = getSymbolID(Macro->Name, Macro->Info, SM)) {
443 // Collect macro references from main file.
444 const auto &IDToRefs = AST.getMacros().MacroRefs;
445 auto Refs = IDToRefs.find(*MacroSID);
446 if (Refs != IDToRefs.end()) {
447 for (const auto Ref : Refs->second) {
448 Location Result;
449 Result.range = Ref;
450 Result.uri = URIMainFile;
451 Results.References.push_back(std::move(Result));
452 }
453 }
454 Req.IDs.insert(*MacroSID);
455 }
456 } else {
457 // Handle references to Decls.
458
459 // We also show references to the targets of using-decls, so we include
460 // DeclRelation::Underlying.
461 DeclRelationSet Relations = DeclRelation::TemplatePattern |
462 DeclRelation::Alias | DeclRelation::Underlying;
463 auto Decls = getDeclAtPosition(AST, Loc, Relations);
464
465 // We traverse the AST to find references in the main file.
466 auto MainFileRefs = findRefs(Decls, AST);
467 // We may get multiple refs with the same location and different Roles, as
468 // cross-reference is only interested in locations, we deduplicate them
469 // by the location to avoid emitting duplicated locations.
470 MainFileRefs.erase(std::unique(MainFileRefs.begin(), MainFileRefs.end(),
471 [](const ReferenceFinder::Reference &L,
472 const ReferenceFinder::Reference &R) {
473 return L.Loc == R.Loc;
474 }),
475 MainFileRefs.end());
476 for (const auto &Ref : MainFileRefs) {
477 if (auto Range = getTokenRange(SM, AST.getLangOpts(), Ref.Loc)) {
478 Location Result;
479 Result.range = *Range;
480 Result.uri = URIMainFile;
481 Results.References.push_back(std::move(Result));
482 }
483 }
484 if (Index && Results.References.size() <= Limit) {
485 for (const Decl *D : Decls) {
486 // Not all symbols can be referenced from outside (e.g.
487 // function-locals).
488 // TODO: we could skip TU-scoped symbols here (e.g. static functions) if
489 // we know this file isn't a header. The details might be tricky.
490 if (D->getParentFunctionOrMethod())
491 continue;
492 if (auto ID = getSymbolID(D))
493 Req.IDs.insert(*ID);
494 }
495 }
496 }
497 // Now query the index for references from other files.
498 if (!Req.IDs.empty() && Index && Results.References.size() <= Limit) {
499 Req.Limit = Limit;
500 Results.HasMore |= Index->refs(Req, [&](const Ref &R) {
501 // No need to continue process if we reach the limit.
502 if (Results.References.size() > Limit)
503 return;
504 auto LSPLoc = toLSPLocation(R.Location, *MainFilePath);
505 // Avoid indexed results for the main file - the AST is authoritative.
506 if (!LSPLoc || LSPLoc->uri.file() == *MainFilePath)
507 return;
508
509 Results.References.push_back(std::move(*LSPLoc));
510 });
511 }
512 if (Results.References.size() > Limit) {
513 Results.HasMore = true;
514 Results.References.resize(Limit);
515 }
516 return Results;
517 }
518
519 std::vector<SymbolDetails> getSymbolInfo(ParsedAST &AST, Position Pos) {
520 const SourceManager &SM = AST.getSourceManager();
521 auto Loc = SM.getMacroArgExpandedLocation(
522 getBeginningOfIdentifier(Pos, SM, AST.getLangOpts()));
523
524 std::vector<SymbolDetails> Results;
525
526 // We also want the targets of using-decls, so we include
527 // DeclRelation::Underlying.
528 DeclRelationSet Relations = DeclRelation::TemplatePattern |
529 DeclRelation::Alias | DeclRelation::Underlying;
530 for (const NamedDecl *D : getDeclAtPosition(AST, Loc, Relations)) {
531 SymbolDetails NewSymbol;
532 std::string QName = printQualifiedName(*D);
533 std::tie(NewSymbol.containerName, NewSymbol.name) =
534 splitQualifiedName(QName);
535
536 if (NewSymbol.containerName.empty()) {
537 if (const auto *ParentND =
538 dyn_cast_or_null<NamedDecl>(D->getDeclContext()))
539 NewSymbol.containerName = printQualifiedName(*ParentND);
540 }
541 llvm::SmallString<32> USR;
542 if (!index::generateUSRForDecl(D, USR)) {
543 NewSymbol.USR = USR.str();
544 NewSymbol.ID = SymbolID(NewSymbol.USR);
545 }
546 Results.push_back(std::move(NewSymbol));
547 }
548
549 if (auto M = locateMacroAt(Loc, AST.getPreprocessor())) {
550 SymbolDetails NewMacro;
551 NewMacro.name = M->Name;
552 llvm::SmallString<32> USR;
553 if (!index::generateUSRForMacro(NewMacro.name, M->Info->getDefinitionLoc(),
554 SM, USR)) {
555 NewMacro.USR = USR.str();
556 NewMacro.ID = SymbolID(NewMacro.USR);
557 }
558 Results.push_back(std::move(NewMacro));
559 }
560
561 return Results;
562 }
563
564 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LocatedSymbol &S) {
565 OS << S.Name << ": " << S.PreferredDeclaration;
566 if (S.Definition)
567 OS << " def=" << *S.Definition;
568 return OS;
569 }
570
571 // FIXME(nridge): Reduce duplication between this function and declToSym().
572 static llvm::Optional<TypeHierarchyItem>
573 declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND) {
574 auto &SM = Ctx.getSourceManager();
575
576 SourceLocation NameLoc = nameLocation(ND, Ctx.getSourceManager());
577 // getFileLoc is a good choice for us, but we also need to make sure
578 // sourceLocToPosition won't switch files, so we call getSpellingLoc on top of
579 // that to make sure it does not switch files.
580 // FIXME: sourceLocToPosition should not switch files!
581 SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc()));
582 SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc()));
583 if (NameLoc.isInvalid() || BeginLoc.isInvalid() || EndLoc.isInvalid())
584 return llvm::None;
585
586 Position NameBegin = sourceLocToPosition(SM, NameLoc);
587 Position NameEnd = sourceLocToPosition(
588 SM, Lexer::getLocForEndOfToken(NameLoc, 0, SM, Ctx.getLangOpts()));
589
590 index::SymbolInfo SymInfo = index::getSymbolInfo(&ND);
591 // FIXME: this is not classifying constructors, destructors and operators
592 // correctly (they're all "methods").
593 SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind);
594
595 TypeHierarchyItem THI;
596 THI.name = printName(Ctx, ND);
597 THI.kind = SK;
598 THI.deprecated = ND.isDeprecated();
599 THI.range =
600 Range{sourceLocToPosition(SM, BeginLoc), sourceLocToPosition(SM, EndLoc)};
601 THI.selectionRange = Range{NameBegin, NameEnd};
602 if (!THI.range.contains(THI.selectionRange)) {
603 // 'selectionRange' must be contained in 'range', so in cases where clang
604 // reports unrelated ranges we need to reconcile somehow.
605 THI.range = THI.selectionRange;
606 }
607
608 auto FilePath =
609 getCanonicalPath(SM.getFileEntryForID(SM.getFileID(BeginLoc)), SM);
610 auto TUPath = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
611 if (!FilePath || !TUPath)
612 return llvm::None; // Not useful without a uri.
613 THI.uri = URIForFile::canonicalize(*FilePath, *TUPath);
614
615 return THI;
616 }
617
618 static Optional<TypeHierarchyItem>
619 symbolToTypeHierarchyItem(const Symbol &S, const SymbolIndex *Index,
620 PathRef TUPath) {
621 auto Loc = symbolToLocation(S, TUPath);
622 if (!Loc) {
623 log("Type hierarchy: {0}", Loc.takeError());
624 return llvm::None;
625 }
626 TypeHierarchyItem THI;
627 THI.name = S.Name;
628 THI.kind = indexSymbolKindToSymbolKind(S.SymInfo.Kind);
629 THI.deprecated = (S.Flags & Symbol::Deprecated);
630 THI.selectionRange = Loc->range;
631 // FIXME: Populate 'range' correctly
632 // (https://github.com/clangd/clangd/issues/59).
633 THI.range = THI.selectionRange;
634 THI.uri = Loc->uri;
635 // Store the SymbolID in the 'data' field. The client will
636 // send this back in typeHierarchy/resolve, allowing us to
637 // continue resolving additional levels of the type hierarchy.
638 THI.data = S.ID.str();
639
640 return std::move(THI);
641 }
642
643 static void fillSubTypes(const SymbolID &ID,
644 std::vector<TypeHierarchyItem> &SubTypes,
645 const SymbolIndex *Index, int Levels, PathRef TUPath) {
646 RelationsRequest Req;
647 Req.Subjects.insert(ID);
648 Req.Predicate = RelationKind::BaseOf;
649 Index->relations(Req, [&](const SymbolID &Subject, const Symbol &Object) {
650 if (Optional<TypeHierarchyItem> ChildSym =
651 symbolToTypeHierarchyItem(Object, Index, TUPath)) {
652 if (Levels > 1) {
653 ChildSym->children.emplace();
654 fillSubTypes(Object.ID, *ChildSym->children, Index, Levels - 1, TUPath);
655 }
656 SubTypes.emplace_back(std::move(*ChildSym));
657 }
658 });
659 }
660
661 using RecursionProtectionSet = llvm::SmallSet<const CXXRecordDecl *, 4>;
662
663 static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx,
664 std::vector<TypeHierarchyItem> &SuperTypes,
665 RecursionProtectionSet &RPSet) {
666 // typeParents() will replace dependent template specializations
667 // with their class template, so to avoid infinite recursion for
668 // certain types of hierarchies, keep the templates encountered
669 // along the parent chain in a set, and stop the recursion if one
670 // starts to repeat.
671 auto *Pattern = CXXRD.getDescribedTemplate() ? &CXXRD : nullptr;
672 if (Pattern) {
673 if (!RPSet.insert(Pattern).second) {
674 return;
675 }
676 }
677
678 for (const CXXRecordDecl *ParentDecl : typeParents(&CXXRD)) {
679 if (Optional<TypeHierarchyItem> ParentSym =
680 declToTypeHierarchyItem(ASTCtx, *ParentDecl)) {
681 ParentSym->parents.emplace();
682 fillSuperTypes(*ParentDecl, ASTCtx, *ParentSym->parents, RPSet);
683 SuperTypes.emplace_back(std::move(*ParentSym));
684 }
685 }
686
687 if (Pattern) {
688 RPSet.erase(Pattern);
689 }
690 }
691
692 const CXXRecordDecl *findRecordTypeAt(ParsedAST &AST, Position Pos) {
693 const SourceManager &SM = AST.getSourceManager();
694 SourceLocation SourceLocationBeg = SM.getMacroArgExpandedLocation(
695 getBeginningOfIdentifier(Pos, SM, AST.getLangOpts()));
696 unsigned Offset =
697 AST.getSourceManager().getDecomposedSpellingLoc(SourceLocationBeg).second;
698 SelectionTree Selection(AST.getASTContext(), AST.getTokens(), Offset);
699 const SelectionTree::Node *N = Selection.commonAncestor();
700 if (!N)
701 return nullptr;
702
703 // Note: explicitReferenceTargets() will search for both template
704 // instantiations and template patterns, and prefer the former if available
705 // (generally, one will be available for non-dependent specializations of a
706 // class template).
707 auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Underlying);
708 if (Decls.empty())
709 return nullptr;
710
711 const NamedDecl *D = Decls[0];
712
713 if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
714 // If this is a variable, use the type of the variable.
715 return VD->getType().getTypePtr()->getAsCXXRecordDecl();
716 }
717
718 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
719 // If this is a method, use the type of the class.
720 return Method->getParent();
721 }
722
723 // We don't handle FieldDecl because it's not clear what behaviour
724 // the user would expect: the enclosing class type (as with a
725 // method), or the field's type (as with a variable).
726
727 return dyn_cast<CXXRecordDecl>(D);
728 }
729
730 std::vector<const CXXRecordDecl *> typeParents(const CXXRecordDecl *CXXRD) {
731 std::vector<const CXXRecordDecl *> Result;
732
733 // If this is an invalid instantiation, instantiation of the bases
734 // may not have succeeded, so fall back to the template pattern.
735 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD)) {
736 if (CTSD->isInvalidDecl())
737 CXXRD = CTSD->getSpecializedTemplate()->getTemplatedDecl();
738 }
739
740 for (auto Base : CXXRD->bases()) {
741 const CXXRecordDecl *ParentDecl = nullptr;
742
743 const Type *Type = Base.getType().getTypePtr();
744 if (const RecordType *RT = Type->getAs<RecordType>()) {
745 ParentDecl = RT->getAsCXXRecordDecl();
746 }
747
748 if (!ParentDecl) {
749 // Handle a dependent base such as "Base<T>" by using the primary
750 // template.
751 if (const TemplateSpecializationType *TS =
752 Type->getAs<TemplateSpecializationType>()) {
753 TemplateName TN = TS->getTemplateName();
754 if (TemplateDecl *TD = TN.getAsTemplateDecl()) {
755 ParentDecl = dyn_cast<CXXRecordDecl>(TD->getTemplatedDecl());
756 }
757 }
758 }
759
760 if (ParentDecl)
761 Result.push_back(ParentDecl);
762 }
763
764 return Result;
765 }
766
767 llvm::Optional<TypeHierarchyItem>
768 getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels,
769 TypeHierarchyDirection Direction, const SymbolIndex *Index,
770 PathRef TUPath) {
771 const CXXRecordDecl *CXXRD = findRecordTypeAt(AST, Pos);
772 if (!CXXRD)
773 return llvm::None;
774
775 Optional<TypeHierarchyItem> Result =
776 declToTypeHierarchyItem(AST.getASTContext(), *CXXRD);
777 if (!Result)
778 return Result;
779
780 if (Direction == TypeHierarchyDirection::Parents ||
781 Direction == TypeHierarchyDirection::Both) {
782 Result->parents.emplace();
783
784 RecursionProtectionSet RPSet;
785 fillSuperTypes(*CXXRD, AST.getASTContext(), *Result->parents, RPSet);
786 }
787
788 if ((Direction == TypeHierarchyDirection::Children ||
789 Direction == TypeHierarchyDirection::Both) &&
790 ResolveLevels > 0) {
791 Result->children.emplace();
792
793 if (Index) {
794 // The index does not store relationships between implicit
795 // specializations, so if we have one, use the template pattern instead.
796 if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CXXRD))
797 CXXRD = CTSD->getTemplateInstantiationPattern();
798
799 if (Optional<SymbolID> ID = getSymbolID(CXXRD))
800 fillSubTypes(*ID, *Result->children, Index, ResolveLevels, TUPath);
801 }
802 }
803
804 return Result;
805 }
806
807 void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels,
808 TypeHierarchyDirection Direction,
809 const SymbolIndex *Index) {
810 // We only support typeHierarchy/resolve for children, because for parents
811 // we ignore ResolveLevels and return all levels of parents eagerly.
812 if (Direction == TypeHierarchyDirection::Parents || ResolveLevels == 0)
813 return;
814
815 Item.children.emplace();
816
817 if (Index && Item.data) {
818 // We store the item's SymbolID in the 'data' field, and the client
819 // passes it back to us in typeHierarchy/resolve.
820 if (Expected<SymbolID> ID = SymbolID::fromStr(*Item.data)) {
821 fillSubTypes(*ID, *Item.children, Index, ResolveLevels, Item.uri.file());
822 }
823 }
824 }
825
826 llvm::DenseSet<const Decl *> getNonLocalDeclRefs(ParsedAST &AST,
827 const FunctionDecl *FD) {
828 if (!FD->hasBody())
829 return {};
830 llvm::DenseSet<const Decl *> DeclRefs;
831 findExplicitReferences(FD, [&](ReferenceLoc Ref) {
832 for (const Decl *D : Ref.Targets) {
833 if (!index::isFunctionLocalSymbol(D) && !D->isTemplateParameter() &&
834 !Ref.IsDecl)
835 DeclRefs.insert(D);
836 }
837 });
838 return DeclRefs;
839 }
840 } // namespace clangd
841 } // namespace clang
clang::clangd::SymbolIndex::lookup
virtual void lookup(const LookupRequest &Req, llvm::function_ref< void(const Symbol &)> Callback) const =0
Looks up symbols with any of the given symbol IDs and applies Callback on each matched symbol...
clang::clangd::SymbolDetails::USR
std::string USR
Unified Symbol Resolution identifier This is an opaque string uniquely identifying a symbol...
Definition: Protocol.h:857
Limit
int Limit
Definition: FindSymbolsTests.cpp:71
clang::clangd::printName
std::string printName(const ASTContext &Ctx, const NamedDecl &ND)
Prints unqualified name of the decl for the purpose of displaying it to the user. ...
Definition: AST.cpp:208
clang::clangd::declToTypeHierarchyItem
static llvm::Optional< TypeHierarchyItem > declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND)
Definition: XRefs.cpp:573
clang::clangd::TypeHierarchyItem::children
llvm::Optional< std::vector< TypeHierarchyItem > > children
If this type hierarchy item is resolved, it contains the direct children of the current item...
Definition: Protocol.h:1172
clang::clangd::fillSuperTypes
static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, std::vector< TypeHierarchyItem > &SuperTypes, RecursionProtectionSet &RPSet)
Definition: XRefs.cpp:663
clang::clangd::DeclRelationSet
Definition: FindTarget.h:163
Decl
const FunctionDecl * Decl
Definition: AvoidBindCheck.cpp:93
clang::clangd::RefsRequest::IDs
llvm::DenseSet< SymbolID > IDs
Definition: Index.h:68
clang::clangd::symbolToTypeHierarchyItem
static Optional< TypeHierarchyItem > symbolToTypeHierarchyItem(const Symbol &S, const SymbolIndex *Index, PathRef TUPath)
Definition: XRefs.cpp:619
clang::clangd::TypeHierarchyDirection::Parents
AST.h
clang::clangd::printQualifiedName
std::string printQualifiedName(const NamedDecl &ND)
Returns the qualified name of ND.
Definition: AST.cpp:169
clang::clangd::nameLocation
SourceLocation nameLocation(const clang::Decl &D, const SourceManager &SM)
Find the source location of the identifier for D.
Definition: AST.cpp:162
clang::clangd::HighlightingKind::Macro
clang::clangd::Location::range
Range range
Definition: Protocol.h:185
clang::clangd::ParsedAST::getLangOpts
const LangOptions & getLangOpts() const
Definition: ParsedAST.h:80
FindSymbols.h
clang::clangd::getSymbolID
llvm::Optional< SymbolID > getSymbolID(const Decl *D)
Gets the symbol ID for a declaration, if possible.
Definition: AST.cpp:286
clang::clangd::DocumentHighlight::range
Range range
The range this highlight applies to.
Definition: Protocol.h:1101
clang::clangd::TypeHierarchyDirection::Both
clang::clangd::ParsedAST::getPreprocessor
Preprocessor & getPreprocessor()
Definition: ParsedAST.cpp:430
Index.h
clang::clangd::ReferenceLoc
Information about a reference written in the source code, independent of the actual AST node that thi...
Definition: FindTarget.h:119
clang::clangd::SelectionTree::Node
Definition: Selection.h:95
clang::clangd::getDocumentLinks
std::vector< DocumentLink > getDocumentLinks(ParsedAST &AST)
Get all document links.
Definition: XRefs.cpp:170
clang::clangd::SymbolID::fromStr
static llvm::Expected< SymbolID > fromStr(llvm::StringRef)
Definition: SymbolID.cpp:35
clang::clangd::RecursionProtectionSet
llvm::SmallSet< const CXXRecordDecl *, 4 > RecursionProtectionSet
Definition: XRefs.cpp:661
clang::clangd::resolveTypeHierarchy
void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels, TypeHierarchyDirection Direction, const SymbolIndex *Index)
Definition: XRefs.cpp:807
clang::clangd::DeclRelation::TemplatePattern
This is the pattern the template specialization was instantiated from.
clang::clangd::SymbolIndex
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
Definition: Index.h:85
SourceCode.h
clang::clangd::LookupRequest::IDs
llvm::DenseSet< SymbolID > IDs
Definition: Index.h:64
clang::clangd::splitQualifiedName
std::pair< StringRef, StringRef > splitQualifiedName(StringRef QName)
Definition: SourceCode.cpp:599
clang::clangd::indexSymbolKindToSymbolKind
SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind)
Definition: Protocol.cpp:216
clang::clangd::isInsideMainFile
bool isInsideMainFile(SourceLocation Loc, const SourceManager &SM)
Returns true iff Loc is inside the main file.
Definition: SourceCode.cpp:534
clang::clangd::Ref
Represents a symbol occurrence in the source file.
Definition: Ref.h:52
Protocol.h
clang::clangd::LocatedSymbol::Definition
llvm::Optional< Location > Definition
Definition: XRefs.h:44
clang::clangd::getBeginningOfIdentifier
SourceLocation getBeginningOfIdentifier(const Position &Pos, const SourceManager &SM, const LangOptions &LangOpts)
Get the beginning SourceLocation at a specified Pos in the main file.
Definition: SourceCode.cpp:277
clang::clangd::TypeHierarchyItem::data
llvm::Optional< std::string > data
An optional &#39;data&#39; filed, which can be used to identify a type hierarchy item in a resolve request...
Definition: Protocol.h:1176
clang::clangd::RefsRequest
Definition: Index.h:67
clang::clangd::Position
Definition: Protocol.h:127
clang::clangd::Location::uri
URIForFile uri
The text document&#39;s URI.
Definition: Protocol.h:184
clang::clangd::PathRef
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:23
Results
std::vector< CodeCompletionResult > Results
Definition: CodeComplete.cpp:689
clang::clangd::TypeHierarchyItem::name
std::string name
The human readable name of the hierarchy item.
Definition: Protocol.h:1138
clang::clangd::findReferences
ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, const SymbolIndex *Index)
Returns references of the symbol at a specified Pos.
Definition: XRefs.cpp:423
clang::clangd::RelationKind::BaseOf
clang::clangd::TextDocumentSyncKind::None
Documents should not be synced at all.
clang::clangd::TypeHierarchyItem::selectionRange
Range selectionRange
The range that should be selected and revealed when this type hierarchy item is being picked...
Definition: Protocol.h:1162
clang::clangd::elog
void elog(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:56
clang::clangd::sourceLocationInMainFile
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
Definition: SourceCode.cpp:571
clang::clangd::DeclRelation::Alias
This declaration is an alias that was referred to.
clang::clangd::ParsedAST::getTokens
const syntax::TokenBuffer & getTokens() const
Tokens recorded while parsing the main file.
Definition: ParsedAST.h:102
clang::clangd::TypeHierarchyItem::range
Range range
The range enclosing this type hierarchy item not including leading/trailing whitespace but everything...
Definition: Protocol.h:1157
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:424
clang::clangd::SymbolDetails::name
std::string name
Definition: Protocol.h:848
clang::clangd::Symbol::ID
SymbolID ID
The ID of the symbol.
Definition: Symbol.h:38
clang::clangd::Symbol::SymInfo
index::SymbolInfo SymInfo
The symbol information, like symbol kind.
Definition: Symbol.h:40
clang::clangd::DocumentHighlightKind::Read
clang::clangd::DocumentHighlight
A document highlight is a range inside a text document which deserves special attention.
Definition: Protocol.h:1099
clang::clangd::ReferencesResult
Definition: XRefs.h:59
clang::clangd::MainFileMacros::MacroRefs
llvm::DenseMap< SymbolID, std::vector< Range > > MacroRefs
Definition: CollectMacros.h:28
clang::clangd::SymbolKind::Object
clang::clangd::Symbol::Definition
SymbolLocation Definition
The location of the symbol&#39;s definition, if one was found.
Definition: Symbol.h:47
clang::clangd::SymbolDetails::ID
llvm::Optional< SymbolID > ID
Definition: Protocol.h:859
Ctx
Context Ctx
Definition: TUScheduler.cpp:237
clang::clangd::getSymbolInfo
std::vector< SymbolDetails > getSymbolInfo(ParsedAST &AST, Position Pos)
Get info about symbols at Pos.
Definition: XRefs.cpp:519
clang::clangd::LocatedSymbol::Name
std::string Name
Definition: XRefs.h:40
QName
std::string QName
Definition: DiagnosticsTests.cpp:523
clang::clangd::Range
Definition: Protocol.h:156
clang::clangd::ParsedAST::getIncludeStructure
const IncludeStructure & getIncludeStructure() const
Definition: ParsedAST.cpp:480
clang::clangd::SymbolOrigin::AST
SymbolInfo
clang::find_all_symbols::SymbolInfo SymbolInfo
Definition: FindAllSymbolsMain.cpp:38
clang::clangd::DocumentHighlightKind::Text
clang::clangd::URIForFile::fromURI
static llvm::Expected< URIForFile > fromURI(const URI &U, llvm::StringRef HintPath)
Definition: Protocol.cpp:45
clang::clangd::Symbol::Flags
SymbolFlag Flags
Definition: Symbol.h:128
clang::clangd::explicitReferenceTargets
llvm::SmallVector< const NamedDecl *, 1 > explicitReferenceTargets(DynTypedNode N, DeclRelationSet Mask)
Definition: FindTarget.cpp:519
CodeCompletionStrings.h
clang::clangd::Ref::Location
SymbolLocation Location
The source location where the symbol is named.
Definition: Ref.h:54
clang::clangd::SymbolID::str
std::string str() const
Definition: SymbolID.cpp:33
clang::clangd::log
void log(const char *Fmt, Ts &&... Vals)
Definition: Logger.h:62
clang::clangd::ReferencesResult::HasMore
bool HasMore
Definition: XRefs.h:61
Role
index::SymbolRoleSet Role
Definition: XRefs.cpp:331
Relation.h
clang::clangd::SymbolIndex::refs
virtual bool refs(const RefsRequest &Req, llvm::function_ref< void(const Ref &)> Callback) const =0
Finds all occurrences (e.g.
clang::clangd::URIForFile::canonicalize
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.
Definition: Protocol.cpp:32
clang::clangd::SymbolDetails::containerName
std::string containerName
Definition: Protocol.h:850
clang::clangd::Symbol::CanonicalDeclaration
SymbolLocation CanonicalDeclaration
The location of the preferred declaration of the symbol.
Definition: Symbol.h:56
clang::clangd::LocatedSymbol::PreferredDeclaration
Location PreferredDeclaration
Definition: XRefs.h:42
clang::clangd::mergeSymbol
Symbol mergeSymbol(const Symbol &L, const Symbol &R)
Definition: Merge.cpp:172
clang::clangd::fillSubTypes
static void fillSubTypes(const SymbolID &ID, std::vector< TypeHierarchyItem > &SubTypes, const SymbolIndex *Index, int Levels, PathRef TUPath)
Definition: XRefs.cpp:643
clang::clangd::ReferenceLoc::Targets
llvm::SmallVector< const NamedDecl *, 1 > Targets
A list of targets referenced by this name.
Definition: FindTarget.h:131
clang::clangd::CompletionItemKind::Method
clang::clangd::getTokenRange
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
Definition: SourceCode.cpp:227
Pos
Position Pos
Definition: SourceCode.cpp:772
clang::clangd::findDocumentHighlights
std::vector< DocumentHighlight > findDocumentHighlights(ParsedAST &AST, Position Pos)
Returns highlights for all usages of a symbol at Pos.
Definition: XRefs.cpp:390
Loc
SourceLocation Loc
Definition: XRefs.cpp:330
clang::clangd::DocumentHighlightKind::Write
clang::clangd::RelationsRequest::Subjects
llvm::DenseSet< SymbolID > Subjects
Definition: Index.h:77
clang::clangd::symbolToLocation
llvm::Expected< Location > symbolToLocation(const Symbol &Sym, llvm::StringRef HintPath)
Helper function for deriving an LSP Location for a Symbol.
Definition: FindSymbols.cpp:42
clang::clangd::targetDecl
llvm::SmallVector< const NamedDecl *, 1 > targetDecl(const ast_type_traits::DynTypedNode &N, DeclRelationSet Mask)
targetDecl() finds the declaration referred to by an AST node.
Definition: FindTarget.cpp:509
clang::clangd::sourceLocToPosition
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
Definition: SourceCode.cpp:200
clang::clangd::ParsedAST
Stores and provides access to parsed AST.
Definition: ParsedAST.h:46
clang::clangd::ParsedAST::getSourceManager
SourceManager & getSourceManager()
Definition: ParsedAST.h:73
clang::clangd::Position::line
int line
Line position in a document (zero-based).
Definition: Protocol.h:129
Logger.h
Offset
size_t Offset
Definition: CodeComplete.cpp:1022
clang::clangd::RefKind::Reference
clang::clangd::ParsedAST::getMacros
const MainFileMacros & getMacros() const
Gets all macro references (definition, expansions) present in the main file, including those in the p...
Definition: ParsedAST.cpp:444
clang::clangd::TypeHierarchyDirection::Children
clang::clangd::Range::contains
bool contains(Position Pos) const
Definition: Protocol.h:173
Merge.h
clang::clangd::Symbol
The class presents a C++ symbol, e.g.
Definition: Symbol.h:36
clang::clangd::LocatedSymbol
Definition: XRefs.h:38
clang::clangd::IncludeStructure::MainFileIncludes
std::vector< Inclusion > MainFileIncludes
Definition: Headers.h:111
clang::clangd::LookupRequest
Definition: Index.h:63
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
clang::clangd::findRecordTypeAt
const CXXRecordDecl * findRecordTypeAt(ParsedAST &AST, Position Pos)
Find the record type references at Pos.
Definition: XRefs.cpp:692
References
unsigned References
Definition: CodeComplete.cpp:157
ParsedAST.h
clang::clangd::SymbolKind
SymbolKind
A symbol kind.
Definition: Protocol.h:300
clang::clangd::findExplicitReferences
void findExplicitReferences(const Stmt *S, llvm::function_ref< void(ReferenceLoc)> Out)
Recursively traverse S and report all references explicitly written in the code.
Definition: FindTarget.cpp:867
FindTarget.h
clang::clangd::Symbol::Name
llvm::StringRef Name
The unqualified name of the symbol, e.g. "bar" (for ns::bar).
Definition: Symbol.h:42
clang::clangd::RelationsRequest
Definition: Index.h:76
clang::tidy::bugprone::PP
static Preprocessor * PP
Definition: BadSignalToKillThreadCheck.cpp:28
clang::clangd::DeclRelation::Underlying
This is the underlying declaration for an alias, decltype etc.
clang::clangd::SelectionTree
Definition: Selection.h:65
clang::clangd::RefsRequest::Limit
llvm::Optional< uint32_t > Limit
If set, limit the number of refers returned from the index.
Definition: Index.h:73
Range
CharSourceRange Range
SourceRange for the file name.
Definition: IncludeOrderCheck.cpp:38
clang::clangd::DocumentHighlight::kind
DocumentHighlightKind kind
The highlight kind, default is DocumentHighlightKind.Text.
Definition: Protocol.h:1104
clang::clangd::getTypeHierarchy
llvm::Optional< TypeHierarchyItem > getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels, TypeHierarchyDirection Direction, const SymbolIndex *Index, PathRef TUPath)
Get type hierarchy information at Pos.
Definition: XRefs.cpp:768
clang::clangd::getCanonicalPath
llvm::Optional< std::string > getCanonicalPath(const FileEntry *F, const SourceManager &SourceMgr)
Get the canonical path of F.
Definition: SourceCode.cpp:622
URI.h
clang::clangd::TypeHierarchyItem::kind
SymbolKind kind
The kind of the hierarchy item. For instance, class or interface.
Definition: Protocol.h:1145
clang::clangd::locateSymbolAt
std::vector< LocatedSymbol > locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Get definition of symbol at a specified Pos.
Definition: XRefs.cpp:190
clang::clangd::Symbol::Deprecated
Indicates if the symbol is deprecated.
Definition: Symbol.h:121
clang::clangd::URI::parse
static llvm::Expected< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".
Definition: URI.cpp:164
Refs
RefSlab Refs
Definition: SymbolCollectorTests.cpp:296
clang::clangd::DocumentLink
A range in a text document that links to an internal or external resource, like another text document...
Definition: Protocol.h:1269
Base
std::unique_ptr< GlobalCompilationDatabase > Base
Definition: GlobalCompilationDatabaseTests.cpp:83
clang::clangd::operator<<
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
Definition: CodeComplete.cpp:1850
clang::clangd::TypeHierarchyItem::uri
URIForFile uri
The URI of the text document where this type hierarchy item belongs to.
Definition: Protocol.h:1151
clang::doc::SymbolID
std::array< uint8_t, 20 > SymbolID
Definition: Representation.h:30
clang::clangd::locateMacroAt
llvm::Optional< DefinedMacro > locateMacroAt(SourceLocation Loc, Preprocessor &PP)
Gets the macro at a specified Loc.
Definition: SourceCode.cpp:987
Selection.h
clang::clangd::SymbolIndex::relations
virtual void relations(const RelationsRequest &Req, llvm::function_ref< void(const SymbolID &Subject, const Symbol &Object)> Callback) const =0
Finds all relations (S, P, O) stored in the index such that S is among Req.Subjects and P is Req...
Type
NodeType Type
Definition: HTMLGenerator.cpp:73
clang::clangd::TypeHierarchyItem::deprecated
bool deprecated
true if the hierarchy item is deprecated. Otherwise, false.
Definition: Protocol.h:1148
clang::clangd::SymbolDetails
Represents information about identifier.
Definition: Protocol.h:847
XRefs.h
clang::clangd::Location
Definition: Protocol.h:182
clang::clangd::ReferencesResult::References
std::vector< Location > References
Definition: XRefs.h:60
clang::clangd::TypeHierarchyDirection
TypeHierarchyDirection
Definition: Protocol.h:1121
clang::clangd::typeParents
std::vector< const CXXRecordDecl * > typeParents(const CXXRecordDecl *CXXRD)
Given a record type declaration, find its base (parent) types.
Definition: XRefs.cpp:730
clang::clangd::getNonLocalDeclRefs
llvm::DenseSet< const Decl * > getNonLocalDeclRefs(ParsedAST &AST, const FunctionDecl *FD)
Returns all decls that are referenced in the FD except local symbols.
Definition: XRefs.cpp:826
SymbolLocation.h
clang::clangd::RelationsRequest::Predicate
RelationKind Predicate
Definition: Index.h:78
clang::clangd::URIForFile::file
llvm::StringRef file() const
Retrieves absolute path to the file.
Definition: Protocol.h:93
Index
const SymbolIndex * Index
Definition: Dexp.cpp:84
clang::clangd::SymbolID
Definition: SymbolID.h:31
clang::clangd::TypeHierarchyItem
Definition: Protocol.h:1136
Location
Definition: Modularize.cpp:383