21 #include "clang/AST/ASTContext.h" 22 #include "clang/AST/Decl.h" 23 #include "clang/AST/DeclCXX.h" 24 #include "clang/AST/DeclTemplate.h" 25 #include "clang/AST/ExprCXX.h" 26 #include "clang/AST/PrettyPrinter.h" 27 #include "clang/AST/RecursiveASTVisitor.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/USRGeneration.h" 36 #include "llvm/ADT/ArrayRef.h" 37 #include "llvm/ADT/None.h" 38 #include "llvm/ADT/STLExtras.h" 39 #include "llvm/ADT/StringExtras.h" 40 #include "llvm/ADT/StringRef.h" 41 #include "llvm/Support/Casting.h" 42 #include "llvm/Support/FormatVariadic.h" 43 #include "llvm/Support/Path.h" 44 #include "llvm/Support/raw_ostream.h" 56 const Decl *getDefinition(
const Decl *
D) {
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();
66 if (isa<ValueDecl>(D) || isa<TemplateTypeParmDecl>(D) ||
67 isa<TemplateTemplateParmDecl>(D))
73 void logIfOverflow(
const SymbolLocation &
Loc) {
74 if (Loc.Start.hasOverflow() || Loc.End.hasOverflow())
75 log(
"Possible overflow in symbol location: {0}", Loc);
82 llvm::Optional<Location> toLSPLocation(
const SymbolLocation &Loc,
83 llvm::StringRef TUPath) {
88 elog(
"Could not parse URI {0}: {1}", Loc.FileURI, Uri.takeError());
93 elog(
"Could not resolve URI {0}: {1}", Loc.FileURI, U.takeError());
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();
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);
119 SymbolLocation getPreferredLocation(
const Location &ASTLoc,
120 const SymbolLocation &IdxLoc,
121 std::string &Scratch) {
124 Symbol ASTSym, IdxSym;
125 ASTSym.ID = IdxSym.ID =
SymbolID(
"dummy_id");
126 ASTSym.CanonicalDeclaration = toIndexLocation(ASTLoc, Scratch);
127 IdxSym.CanonicalDeclaration = IdxLoc;
129 return Merged.CanonicalDeclaration;
133 class DeclarationAndMacrosFinder :
public index::IndexDataConsumer {
134 std::vector<DefinedMacro> MacroInfos;
135 llvm::DenseSet<const Decl *> Decls;
136 const SourceLocation &SearchedLocation;
140 DeclarationAndMacrosFinder(
const SourceLocation &SearchedLocation,
142 : SearchedLocation(SearchedLocation), PP(PP) {}
145 std::vector<const Decl *> getFoundDecls()
const {
146 std::vector<const Decl *>
Result;
147 for (
const Decl *D : Decls)
150 llvm::sort(Result, [](
const Decl *L,
const Decl *R) {
151 return L->getBeginLoc() < R->getBeginLoc();
156 std::vector<DefinedMacro> takeMacroInfos() {
158 llvm::sort(MacroInfos,
159 [](
const DefinedMacro &Left,
const DefinedMacro &Right) {
160 return Left.Info < Right.Info;
164 std::unique(MacroInfos.begin(), MacroInfos.end(),
165 [](
const DefinedMacro &Left,
const DefinedMacro &Right) {
166 return Left.Info == Right.Info;
168 MacroInfos.erase(Last, MacroInfos.end());
169 return std::move(MacroInfos);
173 handleDeclOccurence(
const Decl *D, index::SymbolRoleSet Roles,
174 llvm::ArrayRef<index::SymbolRelation>
Relations,
176 index::IndexDataConsumer::ASTNodeInfo ASTNode)
override {
178 if (Roles & static_cast<unsigned>(index::SymbolRole::NameReference))
181 if (Loc == SearchedLocation) {
182 auto IsImplicitExpr = [](
const Expr *E) {
188 if (
const auto *CtorExpr = dyn_cast<CXXConstructExpr>(E))
189 return CtorExpr->getParenOrBraceRange().isInvalid();
190 return isa<ImplicitCastExpr>(E);
193 if (IsImplicitExpr(ASTNode.OrigE))
199 if (
const auto *Def = getDefinition(D)) {
210 void finish()
override {
211 if (
auto DefinedMacro =
locateMacroAt(SearchedLocation, PP)) {
212 MacroInfos.push_back(*DefinedMacro);
213 assert(Decls.empty());
218 struct IdentifiedSymbol {
219 std::vector<const Decl *> Decls;
223 IdentifiedSymbol getSymbolAtPosition(ParsedAST &
AST, SourceLocation Pos) {
224 auto DeclMacrosFinder =
225 DeclarationAndMacrosFinder(Pos, AST.getPreprocessor());
226 index::IndexingOptions IndexOpts;
227 IndexOpts.SystemSymbolFilter =
228 index::IndexingOptions::SystemSymbolFilterKind::All;
229 IndexOpts.IndexFunctionLocals =
true;
230 IndexOpts.IndexParametersInDeclarations =
true;
231 IndexOpts.IndexTemplateParameters =
true;
232 indexTopLevelDecls(AST.getASTContext(), AST.getPreprocessor(),
233 AST.getLocalTopLevelDecls(), DeclMacrosFinder, IndexOpts);
235 return {DeclMacrosFinder.getFoundDecls(), DeclMacrosFinder.takeMacroInfos()};
238 llvm::Optional<Location> makeLocation(ASTContext &
AST, SourceLocation TokLoc,
239 llvm::StringRef TUPath) {
240 const SourceManager &SourceMgr = AST.getSourceManager();
241 const FileEntry *F = SourceMgr.getFileEntryForID(SourceMgr.getFileID(TokLoc));
246 log(
"failed to get path!");
250 getTokenRange(AST.getSourceManager(), AST.getLangOpts(), TokLoc)) {
267 elog(
"Failed to get a path for the main file, so no references");
273 if (!Inc.Resolved.empty() && Inc.R.start.line == Pos.
line) {
275 File.
Name = llvm::sys::path::filename(Inc.Resolved);
280 return {std::move(File)};
284 SourceLocation SourceLocationBeg =
286 auto Symbols = getSymbolAtPosition(AST, SourceLocationBeg);
290 std::vector<LocatedSymbol>
Result;
291 for (
auto M : Symbols.Macros) {
292 if (
auto Loc = makeLocation(AST.
getASTContext(), M.Info->getDefinitionLoc(),
298 Result.push_back(std::move(Macro));
309 llvm::DenseMap<SymbolID, size_t> ResultIndex;
312 for (
const Decl *D : Symbols.Decls) {
317 Result.emplace_back();
318 if (
auto *ND = dyn_cast<NamedDecl>(D))
320 Result.back().PreferredDeclaration = *
Loc;
322 if (getDefinition(D) == D)
323 Result.back().Definition = *
Loc;
327 ResultIndex[*ID] = Result.size() - 1;
331 if (Index && !ResultIndex.empty()) {
333 for (
auto It : ResultIndex)
334 QueryRequest.
IDs.insert(It.first);
337 auto &R = Result[ResultIndex.lookup(Sym.
ID)];
343 R.PreferredDeclaration = *
Loc;
347 if (
auto Loc = toLSPLocation(
348 getPreferredLocation(*R.Definition, Sym.
Definition, Scratch),
352 R.Definition = toLSPLocation(Sym.
Definition, *MainFilePath);
355 if (
auto Loc = toLSPLocation(
356 getPreferredLocation(R.PreferredDeclaration,
359 R.PreferredDeclaration = *
Loc;
370 class ReferenceFinder :
public index::IndexDataConsumer {
378 ReferenceFinder(ASTContext &
AST, Preprocessor &PP,
379 const std::vector<const Decl *> &TargetDecls)
381 for (
const Decl *D : TargetDecls)
382 CanonicalTargets.insert(D->getCanonicalDecl());
385 std::vector<Reference> take() && {
387 return std::tie(L.Loc, L.CanonicalTarget, L.Role) <
388 std::tie(R.Loc, R.CanonicalTarget, R.Role);
394 return std::tie(L.CanonicalTarget, L.Loc, L.Role) ==
395 std::tie(R.CanonicalTarget, R.Loc, R.Role);
402 handleDeclOccurence(
const Decl *D, index::SymbolRoleSet Roles,
403 llvm::ArrayRef<index::SymbolRelation> Relations,
405 index::IndexDataConsumer::ASTNodeInfo ASTNode)
override {
406 assert(D->isCanonicalDecl() &&
"expect D to be a canonical declaration");
407 const SourceManager &SM =
AST.getSourceManager();
408 Loc = SM.getFileLoc(Loc);
409 if (SM.isWrittenInMainFile(Loc) && CanonicalTargets.count(D))
415 llvm::SmallSet<const Decl *, 4> CanonicalTargets;
417 const ASTContext &
AST;
420 std::vector<ReferenceFinder::Reference>
421 findRefs(
const std::vector<const Decl *> &Decls, ParsedAST &
AST) {
422 ReferenceFinder RefFinder(AST.getASTContext(), AST.getPreprocessor(), Decls);
423 index::IndexingOptions IndexOpts;
424 IndexOpts.SystemSymbolFilter =
425 index::IndexingOptions::SystemSymbolFilterKind::All;
426 IndexOpts.IndexFunctionLocals =
true;
427 IndexOpts.IndexParametersInDeclarations =
true;
428 IndexOpts.IndexTemplateParameters =
true;
429 indexTopLevelDecls(AST.getASTContext(), AST.getPreprocessor(),
430 AST.getLocalTopLevelDecls(), RefFinder, IndexOpts);
431 return std::move(RefFinder).take();
439 auto Symbols = getSymbolAtPosition(
443 std::vector<DocumentHighlight>
Result;
450 if (
Ref.Role & index::SymbolRoleSet(index::SymbolRole::Write))
452 else if (
Ref.Role & index::SymbolRoleSet(index::SymbolRole::Read))
456 Result.push_back(std::move(DH));
463 PrintingPolicy Policy(Base);
465 Policy.AnonymousTagLocations =
false;
466 Policy.TerseOutput =
true;
467 Policy.PolishForDeclaration =
true;
468 Policy.ConstantsAsWritten =
true;
469 Policy.SuppressTagKeyword =
false;
478 std::vector<std::string> Scopes;
479 const DeclContext *DC = D->getDeclContext();
480 auto GetName = [](
const Decl *
D) {
481 const NamedDecl *ND = dyn_cast<NamedDecl>(
D);
482 std::string
Name = ND->getNameAsString();
485 if (
auto RD = dyn_cast<RecordDecl>(D))
486 return (
"(anonymous " + RD->getKindName() +
")").str();
487 return std::string(
"");
490 if (
const TypeDecl *TD = dyn_cast<TypeDecl>(DC))
491 Scopes.push_back(GetName(TD));
492 else if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
493 Scopes.push_back(FD->getNameAsString());
494 DC = DC->getParent();
497 return llvm::join(llvm::reverse(Scopes),
"::");
503 const DeclContext *DC = D->getDeclContext();
505 if (
const TypeDecl *TD = dyn_cast<TypeDecl>(DC))
507 if (
const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC))
509 if (
const NamedDecl *ND = dyn_cast<NamedDecl>(DC))
510 return ND->getQualifiedNameAsString();
517 llvm::raw_string_ostream OS(Definition);
518 PrintingPolicy Policy =
520 Policy.IncludeTagDefinition =
false;
521 D->print(OS, Policy);
526 const std::vector<HoverInfo::Param> &Params) {
527 for (
size_t I = 0, E = Params.size(); I != E; ++I) {
534 static std::vector<HoverInfo::Param>
536 const PrintingPolicy &PP) {
538 std::vector<HoverInfo::Param> TempParameters;
540 for (
const Decl *Param : *Params) {
543 if (
const auto TTP = dyn_cast<TemplateTypeParmDecl>(Param)) {
544 P.
Type = TTP->wasDeclaredWithTypename() ?
"typename" :
"class";
545 if (TTP->isParameterPack())
548 if (!TTP->getName().empty())
549 P.
Name = TTP->getNameAsString();
550 if (TTP->hasDefaultArgument())
551 P.
Default = TTP->getDefaultArgument().getAsString(PP);
552 }
else if (
const auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(Param)) {
553 if (IdentifierInfo *II = NTTP->getIdentifier())
554 P.
Name = II->getName().str();
556 llvm::raw_string_ostream Out(*P.
Type);
557 NTTP->getType().print(Out, PP);
558 if (NTTP->isParameterPack())
561 if (NTTP->hasDefaultArgument()) {
563 llvm::raw_string_ostream Out(*P.
Default);
564 NTTP->getDefaultArgument()->printPretty(Out,
nullptr, PP);
566 }
else if (
const auto TTPD = dyn_cast<TemplateTemplateParmDecl>(Param)) {
567 llvm::raw_string_ostream OS(*P.
Type);
574 if (!TTPD->getName().empty())
575 P.
Name = TTPD->getNameAsString();
576 if (TTPD->hasDefaultArgument()) {
578 llvm::raw_string_ostream Out(*P.
Default);
579 TTPD->getDefaultArgument().getArgument().print(PP, Out);
582 TempParameters.push_back(std::move(P));
585 return TempParameters;
590 if (
const VarDecl *VD = llvm::dyn_cast<VarDecl>(D)) {
591 auto QT = VD->getType();
593 while (!QT->getPointeeType().isNull())
594 QT = QT->getPointeeType();
596 if (
const auto *CD = QT->getAsCXXRecordDecl())
597 return CD->getLambdaCallOperator();
602 return D->getAsFunction();
608 if (!Index || !llvm::isa<NamedDecl>(D))
610 const NamedDecl &ND = *cast<NamedDecl>(
D);
632 const ASTContext &
Ctx = D->getASTContext();
642 if (
const NamedDecl *ND = llvm::dyn_cast<NamedDecl>(D)) {
650 if (
const TemplateDecl *TD = D->getDescribedTemplate()) {
654 }
else if (
const FunctionDecl *FD = D->getAsFunction()) {
655 if (
const auto FTD = FD->getDescribedTemplate()) {
667 FD->getReturnType().print(OS, Policy);
671 for (
const ParmVarDecl *PVD : FD->parameters()) {
674 if (!PVD->getType().isNull()) {
676 llvm::raw_string_ostream OS(*P.Type);
677 PVD->getType().print(OS, Policy);
680 llvm::raw_string_ostream OS(Param);
683 elog(
"Got param with null type: {0}", Param);
685 if (!PVD->getName().empty())
686 P.Name = PVD->getNameAsString();
687 if (PVD->hasDefaultArg()) {
689 llvm::raw_string_ostream Out(*P.Default);
690 PVD->getDefaultArg()->printPretty(Out,
nullptr, Policy);
695 llvm::raw_string_ostream TypeOS(*HI.
Type);
697 if (
const VarDecl *VD = llvm::dyn_cast<VarDecl>(D))
698 VD->getType().getDesugaredType(D->getASTContext()).print(TypeOS, Policy);
701 FD->getType().print(TypeOS, Policy);
703 }
else if (
const auto *VD = dyn_cast<ValueDecl>(D)) {
705 llvm::raw_string_ostream OS(*HI.
Type);
706 VD->getType().print(OS, Policy);
712 if (
const auto *Var = dyn_cast<VarDecl>(D)) {
713 if (
const Expr *Init = Var->getInit()) {
715 if (!Init->isValueDependent() && Init->EvaluateAsRValue(Result, Ctx)) {
717 llvm::raw_string_ostream ValueOS(*HI.
Value);
718 Result.Val.printPretty(ValueOS, const_cast<ASTContext &>(Ctx),
733 llvm::raw_string_ostream OS(HI.
Name);
750 index::getSymbolInfoForMacro(*Macro.
Info).Kind);
755 SourceLocation StartLoc = Macro.
Info->getDefinitionLoc();
756 SourceLocation EndLoc = Macro.
Info->getDefinitionEndLoc();
757 if (EndLoc.isValid()) {
758 EndLoc = Lexer::getLocForEndOfToken(EndLoc, 0, SM,
761 StringRef Buffer = SM.getBufferData(SM.getFileID(StartLoc), &Invalid);
763 unsigned StartOffset = SM.getFileOffset(StartLoc);
764 unsigned EndOffset = SM.getFileOffset(EndLoc);
765 if (EndOffset <= Buffer.size() && StartOffset < EndOffset)
767 (
"#define " + Buffer.substr(StartOffset, EndOffset - StartOffset))
783 class DeducedTypeVisitor :
public RecursiveASTVisitor<DeducedTypeVisitor> {
784 SourceLocation SearchedLocation;
787 DeducedTypeVisitor(SourceLocation SearchedLocation)
788 : SearchedLocation(SearchedLocation) {}
795 bool VisitDeclaratorDecl(DeclaratorDecl *D) {
796 if (!D->getTypeSourceInfo() ||
797 D->getTypeSourceInfo()->getTypeLoc().getBeginLoc() != SearchedLocation)
800 if (
auto *AT = D->getType()->getContainedAutoType()) {
801 if (!AT->getDeducedType().isNull()) {
815 bool VisitFunctionDecl(FunctionDecl *D) {
816 if (!D->getTypeSourceInfo())
819 auto CurLoc = D->getReturnTypeSourceRange().getBegin();
821 if (CurLoc.isInvalid() && dyn_cast<CXXConversionDecl>(
D))
822 CurLoc = D->getTypeSourceInfo()->getTypeLoc().getBeginLoc();
824 if (CurLoc.isInvalid())
825 CurLoc = D->getSourceRange().getBegin();
826 if (CurLoc != SearchedLocation)
829 const AutoType *AT = D->getReturnType()->getContainedAutoType();
830 if (AT && !AT->getDeducedType().isNull()) {
833 }
else if (
auto DT = dyn_cast<DecltypeType>(D->getReturnType())) {
836 if (!DT->getUnderlyingType().isNull()) {
840 }
else if (!D->getReturnType().isNull()) {
850 bool VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
851 if (TL.getBeginLoc() != SearchedLocation)
858 const DecltypeType *DT = dyn_cast<DecltypeType>(TL.getTypePtr());
859 while (DT && !DT->getUnderlyingType().isNull()) {
861 D = DT->getAsTagDecl();
862 DT = dyn_cast<DecltypeType>(
DeducedType.getTypePtr());
868 const Decl *D =
nullptr;
875 SourceLocation SourceLocationBeg) {
879 if (!SourceLocationBeg.isValid() ||
880 Lexer::getRawToken(SourceLocationBeg, Tok, ASTCtx.getSourceManager(),
881 ASTCtx.getLangOpts(),
false) ||
882 !Tok.is(tok::raw_identifier)) {
886 if (!(Tok.is(tok::kw_auto) || Tok.is(tok::kw_decltype)))
889 DeducedTypeVisitor V(SourceLocationBeg);
891 return V.DeducedType;
902 llvm::Optional<HoverInfo> HI;
906 auto Symbols = getSymbolAtPosition(AST, SourceLocationBeg);
908 if (!Symbols.Macros.empty())
910 else if (!Symbols.Decls.empty())
916 DeducedTypeVisitor V(SourceLocationBeg);
918 if (V.DeducedType.isNull())
923 auto Replacements = format::reformat(
926 tooling::applyAllReplacements(HI->Definition, Replacements))
927 HI->Definition = *Formatted;
938 Limit = std::numeric_limits<uint32_t>::max();
944 elog(
"Failed to get a path for the main file, so no references");
948 auto Symbols = getSymbolAtPosition(AST, Loc);
952 auto MainFileRefs = findRefs(Symbols.Decls, AST);
953 for (
const auto &
Ref : MainFileRefs) {
960 Results.push_back(std::move(Result));
965 if (Index && Results.size() <
Limit) {
969 for (
const Decl *D : Symbols.Decls) {
973 if (D->getParentFunctionOrMethod())
980 Index->
refs(Req, [&](
const Ref &R) {
981 auto LSPLoc = toLSPLocation(R.
Location, *MainFilePath);
983 if (LSPLoc && LSPLoc->uri.file() != *MainFilePath)
984 Results.push_back(std::move(*LSPLoc));
987 if (Results.size() >
Limit)
988 Results.resize(Limit);
996 auto Symbols = getSymbolAtPosition(AST, Loc);
998 std::vector<SymbolDetails>
Results;
1000 for (
const Decl *D : Symbols.Decls) {
1002 if (
const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
1008 if (
const auto *ParentND =
1009 dyn_cast_or_null<NamedDecl>(ND->getDeclContext()))
1013 llvm::SmallString<32> USR;
1014 if (!index::generateUSRForDecl(D, USR)) {
1015 NewSymbol.
USR = USR.str();
1018 Results.push_back(std::move(NewSymbol));
1021 for (
const auto &Macro : Symbols.Macros) {
1023 NewMacro.
name = Macro.Name;
1024 llvm::SmallString<32> USR;
1025 if (!index::generateUSRForMacro(NewMacro.
name,
1026 Macro.Info->getDefinitionLoc(), SM, USR)) {
1027 NewMacro.
USR = USR.str();
1030 Results.push_back(std::move(NewMacro));
1044 static llvm::Optional<TypeHierarchyItem>
1046 auto &SM = Ctx.getSourceManager();
1053 SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc()));
1054 SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc()));
1055 if (NameLoc.isInvalid() || BeginLoc.isInvalid() || EndLoc.isInvalid())
1060 SM, Lexer::getLocForEndOfToken(NameLoc, 0, SM, Ctx.getLangOpts()));
1082 auto TUPath =
getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM);
1083 if (!FilePath || !TUPath)
1090 static Optional<TypeHierarchyItem>
1095 log(
"Type hierarchy: {0}", Loc.takeError());
1112 return std::move(THI);
1116 std::vector<TypeHierarchyItem> &SubTypes,
1120 Req.
Predicate = index::SymbolRole::RelationBaseOf;
1122 if (Optional<TypeHierarchyItem> ChildSym =
1125 ChildSym->children.emplace();
1126 fillSubTypes(Object.
ID, *ChildSym->children, Index, Levels - 1, TUPath);
1128 SubTypes.emplace_back(std::move(*ChildSym));
1136 std::vector<TypeHierarchyItem> &SuperTypes,
1143 auto *Pattern = CXXRD.getDescribedTemplate() ? &CXXRD :
nullptr;
1145 if (!RPSet.insert(Pattern).second) {
1150 for (
const CXXRecordDecl *ParentDecl :
typeParents(&CXXRD)) {
1151 if (Optional<TypeHierarchyItem> ParentSym =
1153 ParentSym->parents.emplace();
1155 SuperTypes.emplace_back(std::move(*ParentSym));
1160 RPSet.erase(Pattern);
1167 IdentifiedSymbol
Symbols = getSymbolAtPosition(AST, SourceLocationBeg);
1168 if (Symbols.Decls.empty())
1171 const Decl *D = Symbols.Decls[0];
1173 if (
const VarDecl *VD = dyn_cast<VarDecl>(D)) {
1175 return VD->getType().getTypePtr()->getAsCXXRecordDecl();
1178 if (
const CXXMethodDecl *
Method = dyn_cast<CXXMethodDecl>(D)) {
1180 return Method->getParent();
1187 return dyn_cast<CXXRecordDecl>(
D);
1190 std::vector<const CXXRecordDecl *>
typeParents(
const CXXRecordDecl *CXXRD) {
1191 std::vector<const CXXRecordDecl *>
Result;
1193 for (
auto Base : CXXRD->bases()) {
1194 const CXXRecordDecl *ParentDecl =
nullptr;
1197 if (
const RecordType *RT = Type->getAs<RecordType>()) {
1198 ParentDecl = RT->getAsCXXRecordDecl();
1204 if (
const TemplateSpecializationType *TS =
1205 Type->getAs<TemplateSpecializationType>()) {
1206 TemplateName TN = TS->getTemplateName();
1207 if (TemplateDecl *TD = TN.getAsTemplateDecl()) {
1208 ParentDecl = dyn_cast<CXXRecordDecl>(TD->getTemplatedDecl());
1214 Result.push_back(ParentDecl);
1220 llvm::Optional<TypeHierarchyItem>
1228 Optional<TypeHierarchyItem> Result =
1235 Result->parents.emplace();
1243 ResolveLevels > 0) {
1244 Result->children.emplace();
1248 fillSubTypes(*ID, *Result->children, Index, ResolveLevels, TUPath);
1265 if (Index && Item.
data) {
1276 if (NamespaceScope) {
1279 if (!LocalScope.empty())
1281 else if (NamespaceScope->empty())
1294 if (!Documentation.empty())
1301 std::vector<llvm::StringRef> Output;
1303 Output.push_back(*P.
Type);
1305 Output.push_back(*P.
Name);
llvm::Optional< QualType > getDeducedType(ParsedAST &AST, SourceLocation SourceLocationBeg)
Retrieves the deduced type at a given location (auto, decltype).
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...
std::string USR
Unified Symbol Resolution identifier This is an opaque string uniquely identifying a symbol...
std::string printName(const ASTContext &Ctx, const NamedDecl &ND)
Prints unqualified name of the decl for the purpose of displaying it to the user. ...
static llvm::Optional< TypeHierarchyItem > declToTypeHierarchyItem(ASTContext &Ctx, const NamedDecl &ND)
Contains detailed information about a Symbol.
llvm::Optional< std::vector< TypeHierarchyItem > > children
If this type hierarchy item is resolved, it contains the direct children of the current item...
static void fillSuperTypes(const CXXRecordDecl &CXXRD, ASTContext &ASTCtx, std::vector< TypeHierarchyItem > &SuperTypes, RecursionProtectionSet &RPSet)
llvm::DenseSet< SymbolID > IDs
static Optional< TypeHierarchyItem > symbolToTypeHierarchyItem(const Symbol &S, const SymbolIndex *Index, PathRef TUPath)
std::string printQualifiedName(const NamedDecl &ND)
Returns the qualified name of ND.
llvm::Optional< SymbolID > getSymbolID(const Decl *D)
Gets the symbol ID for a declaration, if possible.
Range range
The range this highlight applies to.
Preprocessor & getPreprocessor()
static llvm::Expected< SymbolID > fromStr(llvm::StringRef)
llvm::SmallSet< const CXXRecordDecl *, 4 > RecursionProtectionSet
void resolveTypeHierarchy(TypeHierarchyItem &Item, int ResolveLevels, TypeHierarchyDirection Direction, const SymbolIndex *Index)
const Decl * CanonicalTarget
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
llvm::Optional< std::string > Name
None for unnamed parameters.
llvm::DenseSet< SymbolID > IDs
std::pair< StringRef, StringRef > splitQualifiedName(StringRef QName)
SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind)
static HoverInfo getHoverContents(const Decl *D, const SymbolIndex *Index)
Generate a Hover object given the declaration D.
Represents a symbol occurrence in the source file.
llvm::Optional< Location > Definition
SourceLocation findNameLoc(const clang::Decl *D)
Find the identifier source location of the given D.
llvm::Optional< std::string > data
An optional 'data' filed, which can be used to identify a type hierarchy item in a resolve request...
URIForFile uri
The text document's URI.
llvm::StringRef PathRef
A typedef to represent a ref to file path.
std::vector< CodeCompletionResult > Results
std::string name
The human readable name of the hierarchy item.
llvm::Optional< std::string > Type
Pretty-printed variable type.
Documents should not be synced at all.
Range selectionRange
The range that should be selected and revealed when this type hierarchy item is being picked...
llvm::Optional< std::vector< Param > > Parameters
Set for functions, lambdas and macros with parameters.
index::SymbolRole Predicate
FormattedString present() const
Produce a user-readable information.
void elog(const char *Fmt, Ts &&... Vals)
Range range
The range enclosing this type hierarchy item not including leading/trailing whitespace but everything...
ASTContext & getASTContext()
Note that the returned ast will not contain decls from the preamble that were not deserialized during...
SourceLocation getBeginningOfIdentifier(const ParsedAST &Unit, const Position &Pos, const FileID FID)
Get the beginning SourceLocation at a specified Pos.
Represents parameters of a function, a template or a macro.
static std::string getNamespaceScope(const Decl *D)
Returns the human-readable representation for namespace containing the declaration D...
SymbolID ID
The ID of the symbol.
index::SymbolInfo SymInfo
The symbol information, like symbol kind.
std::string Definition
Source code containing the definition of the symbol.
llvm::Optional< std::string > Type
The pretty-printed parameter type, e.g.
A document highlight is a range inside a text document which deserves special attention.
static void printParams(llvm::raw_ostream &OS, const std::vector< HoverInfo::Param > &Params)
SymbolLocation Definition
The location of the symbol's definition, if one was found.
llvm::Optional< SymbolID > ID
std::vector< SymbolDetails > getSymbolInfo(ParsedAST &AST, Position Pos)
Get info about symbols at Pos.
std::string Name
Name of the symbol, does not contain any "::".
static std::string getLocalScope(const Decl *D)
Given a declaration D, return a human-readable string representing the local scope in which it is dec...
llvm::Optional< HoverInfo > getHover(ParsedAST &AST, Position Pos, format::FormatStyle Style, const SymbolIndex *Index)
Get the hover information when hovering at Pos.
const IncludeStructure & getIncludeStructure() const
clang::find_all_symbols::SymbolInfo SymbolInfo
static llvm::Expected< URIForFile > fromURI(const URI &U, llvm::StringRef HintPath)
SymbolLocation Location
The source location where the symbol is named.
void log(const char *Fmt, Ts &&... Vals)
index::SymbolRoleSet Role
llvm::Optional< std::string > Default
None if no default is provided.
llvm::StringRef Documentation
Documentation including comment for the symbol declaration.
static void enhanceFromIndex(HoverInfo &Hover, const Decl *D, const SymbolIndex *Index)
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.
static constexpr llvm::StringLiteral Name
std::string containerName
SymbolLocation CanonicalDeclaration
The location of the preferred declaration of the symbol.
Location PreferredDeclaration
Symbol mergeSymbol(const Symbol &L, const Symbol &R)
virtual void refs(const RefsRequest &Req, llvm::function_ref< void(const Ref &)> Callback) const =0
Finds all occurrences (e.g.
static void fillSubTypes(const SymbolID &ID, std::vector< TypeHierarchyItem > &SubTypes, const SymbolIndex *Index, int Levels, PathRef TUPath)
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
std::vector< DocumentHighlight > findDocumentHighlights(ParsedAST &AST, Position Pos)
Returns highlights for all usages of a symbol at Pos.
llvm::DenseSet< SymbolID > Subjects
llvm::Expected< Location > symbolToLocation(const Symbol &Sym, llvm::StringRef HintPath)
Helper function for deriving an LSP Location for a Symbol.
std::string LocalScope
Remaining named contexts in symbol's qualified name, empty string means symbol is not local...
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
llvm::Optional< std::string > NamespaceScope
For a variable named Bar, declared in clang::clangd::Foo::getFoo the following fields will hold: ...
Stores and provides access to parsed AST.
llvm::Optional< std::vector< Param > > TemplateParameters
Set for all templates(function, class, variable).
SourceManager & getSourceManager()
int line
Line position in a document (zero-based).
std::string getDeclComment(const ASTContext &Ctx, const NamedDecl &Decl)
Similar to getDocComment, but returns the comment for a NamedDecl.
static bool shouldCollectSymbol(const NamedDecl &ND, const ASTContext &ASTCtx, const Options &Opts, bool IsMainFileSymbol)
Returns true is ND should be collected.
bool contains(Position Pos) const
std::vector< Location > findReferences(ParsedAST &AST, Position Pos, uint32_t Limit, const SymbolIndex *Index)
Returns reference locations of the symbol at a specified Pos.
The class presents a C++ symbol, e.g.
std::vector< Inclusion > MainFileIncludes
llvm::Optional< std::string > ReturnType
Set for functions and lambadas.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
const CXXRecordDecl * findRecordTypeAt(ParsedAST &AST, Position Pos)
Find the record type references at Pos.
llvm::StringRef Name
The unqualified name of the symbol, e.g. "bar" (for ns::bar).
static PrintingPolicy printingPolicyForDecls(PrintingPolicy Base)
llvm::Optional< uint32_t > Limit
If set, limit the number of refers returned from the index.
CharSourceRange Range
SourceRange for the file name.
std::vector< DefinedMacro > Macros
DocumentHighlightKind kind
The highlight kind, default is DocumentHighlightKind.Text.
llvm::Optional< std::string > Value
Contains the evaluated value of the symbol if available.
llvm::Optional< TypeHierarchyItem > getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels, TypeHierarchyDirection Direction, const SymbolIndex *Index, PathRef TUPath)
Get type hierarchy information at Pos.
llvm::Optional< std::string > getCanonicalPath(const FileEntry *F, const SourceManager &SourceMgr)
Get the canonical path of F.
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
SymbolKind kind
The kind of the hierarchy item. For instance, class or interface.
static std::string printDefinition(const Decl *D)
std::vector< LocatedSymbol > locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Get definition of symbol at a specified Pos.
Indicates if the symbol is deprecated.
static llvm::Expected< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".
static std::string join(ArrayRef< SpecialMemberFunctionsCheck::SpecialMemberFunctionKind > SMFS, llvm::StringRef AndOr)
bool hasDeducedType(ParsedAST &AST, SourceLocation SourceLocationBeg)
Retrieves the deduced type at a given location (auto, decltype).
std::unique_ptr< GlobalCompilationDatabase > Base
SymbolKind Kind
Scope containing the symbol.
llvm::raw_ostream & operator<<(llvm::raw_ostream &OS, const CodeCompletion &C)
URIForFile uri
The URI of the text document where this type hierarchy item belongs to.
std::string Documentation
std::array< uint8_t, 20 > SymbolID
llvm::Optional< DefinedMacro > locateMacroAt(SourceLocation Loc, Preprocessor &PP)
static std::vector< HoverInfo::Param > fetchTemplateParameters(const TemplateParameterList *Params, const PrintingPolicy &PP)
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...
bool deprecated
true if the hierarchy item is deprecated. Otherwise, false.
Represents information about identifier.
static const FunctionDecl * getUnderlyingFunction(const Decl *D)
std::vector< const CXXRecordDecl * > typeParents(const CXXRecordDecl *CXXRD)
Given a record type declaration, find its base (parent) types.
llvm::StringRef file() const
Retrieves absolute path to the file.
const SymbolIndex * Index
static cl::opt< std::string > FormatStyle("format-style", cl::desc(R"(
Style for formatting code around applied fixes:
- 'none' (default) turns off formatting
- 'file' (literally 'file', not a placeholder)
uses .clang-format file in the closest parent
directory
- '{ <json> }' specifies options inline, e.g.
-format-style='{BasedOnStyle: llvm, IndentWidth: 8}'
- 'llvm', 'google', 'webkit', 'mozilla'
See clang-format documentation for the up-to-date
information about formatting styles and options.
This option overrides the 'FormatStyle` option in
.clang-tidy file, if any.
)"), cl::init("none"), cl::cat(ClangTidyCategory))