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 "clang/Tooling/Inclusions/HeaderAnalysis.h"
32#include "llvm/ADT/ArrayRef.h"
33#include "llvm/Support/Casting.h"
34#include "llvm/Support/FileSystem.h"
35#include "llvm/Support/Path.h"
44const NamedDecl &getTemplateOrThis(
const NamedDecl &ND) {
45 if (
auto *T = ND.getDescribedTemplate())
54bool isPrivateProtoDecl(
const NamedDecl &ND) {
55 const auto &SM = ND.getASTContext().getSourceManager();
60 if (ND.getIdentifier() ==
nullptr)
62 auto Name = ND.getIdentifier()->getName();
63 if (!
Name.contains(
'_'))
74 return (ND.getKind() != Decl::EnumConstant) || llvm::any_of(
Name, islower);
81 using SK = index::SymbolKind;
92 case SK::EnumConstant:
103std::pair<SymbolLocation::Position, SymbolLocation::Position>
104getTokenRange(SourceLocation TokLoc,
const SourceManager &SM,
105 const LangOptions &LangOpts) {
106 auto CreatePosition = [&SM](SourceLocation
Loc) {
108 SymbolLocation::Position
Pos;
109 Pos.setLine(LSPLoc.line);
110 Pos.setColumn(LSPLoc.character);
114 auto TokenLength = clang::Lexer::MeasureTokenLength(TokLoc, SM, LangOpts);
115 return {CreatePosition(TokLoc),
116 CreatePosition(TokLoc.getLocWithOffset(TokenLength))};
124bool isPreferredDeclaration(
const NamedDecl &ND, index::SymbolRoleSet Roles) {
125 const auto &SM = ND.getASTContext().getSourceManager();
126 if (isa<TagDecl>(ND))
127 return (Roles &
static_cast<unsigned>(index::SymbolRole::Definition)) &&
129 if (
const auto *ID = dyn_cast<ObjCInterfaceDecl>(&ND))
130 return ID->isThisDeclarationADefinition();
131 if (
const auto *PD = dyn_cast<ObjCProtocolDecl>(&ND))
132 return PD->isThisDeclarationADefinition();
136RefKind toRefKind(index::SymbolRoleSet Roles,
bool Spelled =
false) {
138 if (Roles &
static_cast<unsigned>(index::SymbolRole::Declaration))
140 if (Roles &
static_cast<unsigned>(index::SymbolRole::Definition))
142 if (Roles &
static_cast<unsigned>(index::SymbolRole::Reference))
149std::optional<RelationKind> indexableRelation(
const index::SymbolRelation &R) {
150 if (R.Roles &
static_cast<unsigned>(index::SymbolRole::RelationBaseOf))
152 if (R.Roles &
static_cast<unsigned>(index::SymbolRole::RelationOverrideOf))
158bool isSpelled(SourceLocation
Loc,
const NamedDecl &ND) {
159 auto Name = ND.getDeclName();
160 const auto NameKind =
Name.getNameKind();
161 if (NameKind != DeclarationName::Identifier &&
162 NameKind != DeclarationName::CXXConstructorName)
164 const auto &
AST = ND.getASTContext();
165 const auto &SM =
AST.getSourceManager();
166 const auto &LO =
AST.getLangOpts();
168 if (clang::Lexer::getRawToken(
Loc, Tok, SM, LO))
170 auto StrName =
Name.getAsString();
171 return clang::Lexer::getSpelling(Tok, SM, LO) == StrName;
179 struct FrameworkUmbrellaSpelling {
181 std::optional<std::string> PublicHeader;
184 std::optional<std::string> PrivateHeader;
190 const SourceManager &SM;
192 llvm::StringRef FallbackDir;
193 llvm::DenseMap<const FileEntry *, const std::string *> CacheFEToURI;
194 llvm::StringMap<std::string> CachePathToURI;
195 llvm::DenseMap<FileID, llvm::StringRef> CacheFIDToInclude;
196 llvm::StringMap<std::string> CachePathToFrameworkSpelling;
197 llvm::StringMap<FrameworkUmbrellaSpelling>
198 CacheFrameworkToUmbrellaHeaderSpelling;
203 : PP(PP), SM(SM), Includes(Opts.Includes), FallbackDir(Opts.FallbackDir) {
208 const std::string &
toURI(
const FileEntryRef FE) {
209 auto R = CacheFEToURI.try_emplace(FE);
212 R.first->second = &toURIInternal(CanonPath ? *CanonPath : FE.getName());
214 return *R.first->second;
221 if (
auto File = SM.getFileManager().getFileRef(
Path))
223 return toURIInternal(
Path);
231 auto R = CacheFIDToInclude.try_emplace(FID);
233 R.first->second = getIncludeHeaderUncached(FID);
234 return R.first->second;
240 const std::string &toURIInternal(llvm::StringRef
Path) {
241 auto R = CachePathToURI.try_emplace(
Path);
243 llvm::SmallString<256> AbsPath =
Path;
244 if (!llvm::sys::path::is_absolute(AbsPath) && !FallbackDir.empty())
245 llvm::sys::fs::make_absolute(FallbackDir, AbsPath);
246 assert(llvm::sys::path::is_absolute(AbsPath) &&
247 "If the VFS can't make paths absolute, a FallbackDir must be "
249 llvm::sys::path::remove_dots(AbsPath,
true);
252 return R.first->second;
255 struct FrameworkHeaderPath {
258 llvm::StringRef HeadersParentDir;
261 llvm::StringRef HeaderSubpath;
263 bool IsPrivateHeader;
266 std::optional<FrameworkHeaderPath>
267 splitFrameworkHeaderPath(llvm::StringRef
Path) {
268 using namespace llvm::sys;
269 path::reverse_iterator I = path::rbegin(
Path);
270 path::reverse_iterator Prev = I;
271 path::reverse_iterator
E = path::rend(
Path);
273 if (*I ==
"Headers") {
274 FrameworkHeaderPath HeaderPath;
275 HeaderPath.HeadersParentDir =
Path.substr(0, I -
E);
276 HeaderPath.HeaderSubpath =
Path.substr(Prev -
E);
277 HeaderPath.IsPrivateHeader =
false;
280 if (*I ==
"PrivateHeaders") {
281 FrameworkHeaderPath HeaderPath;
282 HeaderPath.HeadersParentDir =
Path.substr(0, I -
E);
283 HeaderPath.HeaderSubpath =
Path.substr(Prev -
E);
284 HeaderPath.IsPrivateHeader =
true;
299 std::optional<std::string> getFrameworkUmbrellaSpelling(
300 llvm::StringRef Framework, SrcMgr::CharacteristicKind HeadersDirKind,
301 HeaderSearch &HS, FrameworkHeaderPath &HeaderPath) {
302 auto Res = CacheFrameworkToUmbrellaHeaderSpelling.try_emplace(Framework);
303 auto *CachedSpelling = &Res.first->second;
305 return HeaderPath.IsPrivateHeader ? CachedSpelling->PrivateHeader
306 : CachedSpelling->PublicHeader;
308 bool IsSystem = isSystem(HeadersDirKind);
309 SmallString<256> UmbrellaPath(HeaderPath.HeadersParentDir);
310 llvm::sys::path::append(UmbrellaPath,
"Headers", Framework +
".h");
312 llvm::vfs::Status Status;
313 auto StatErr = HS.getFileMgr().getNoncachedStatValue(UmbrellaPath, Status);
316 CachedSpelling->PublicHeader = llvm::formatv(
"<{0}/{0}.h>", Framework);
318 CachedSpelling->PublicHeader =
319 llvm::formatv(
"\"{0}/{0}.h\"", Framework);
322 UmbrellaPath = HeaderPath.HeadersParentDir;
323 llvm::sys::path::append(UmbrellaPath,
"PrivateHeaders",
324 Framework +
"_Private.h");
326 StatErr = HS.getFileMgr().getNoncachedStatValue(UmbrellaPath, Status);
329 CachedSpelling->PrivateHeader =
330 llvm::formatv(
"<{0}/{0}_Private.h>", Framework);
332 CachedSpelling->PrivateHeader =
333 llvm::formatv(
"\"{0}/{0}_Private.h\"", Framework);
335 return HeaderPath.IsPrivateHeader ? CachedSpelling->PrivateHeader
336 : CachedSpelling->PublicHeader;
343 std::optional<llvm::StringRef> getFrameworkHeaderIncludeSpelling(
344 const FileEntry *FE, llvm::StringRef Framework, HeaderSearch &HS) {
345 auto Res = CachePathToFrameworkSpelling.try_emplace(FE->getName());
346 auto *CachedHeaderSpelling = &Res.first->second;
348 return llvm::StringRef(*CachedHeaderSpelling);
350 auto HeaderPath = splitFrameworkHeaderPath(FE->getName());
354 CachePathToFrameworkSpelling.erase(Res.first);
357 auto DirKind = HS.getFileDirFlavor(FE);
358 if (
auto UmbrellaSpelling =
359 getFrameworkUmbrellaSpelling(Framework, DirKind, HS, *HeaderPath)) {
360 *CachedHeaderSpelling = *UmbrellaSpelling;
361 return llvm::StringRef(*CachedHeaderSpelling);
364 if (isSystem(DirKind))
365 *CachedHeaderSpelling =
366 llvm::formatv(
"<{0}/{1}>", Framework, HeaderPath->HeaderSubpath)
369 *CachedHeaderSpelling =
370 llvm::formatv(
"\"{0}/{1}\"", Framework, HeaderPath->HeaderSubpath)
372 return llvm::StringRef(*CachedHeaderSpelling);
375 llvm::StringRef getIncludeHeaderUncached(FileID FID) {
376 const auto FE = SM.getFileEntryRefForID(FID);
377 if (!FE || FE->getName().empty())
379 llvm::StringRef
Filename = FE->getName();
384 Includes->mapHeader(*SM.getFileEntryRefForID(FID));
389 return toURI(Canonical);
394 auto &HS = PP->getHeaderSearchInfo();
395 if (
const auto *HFI = HS.getExistingFileInfo(*FE,
false))
396 if (!HFI->Framework.empty())
398 getFrameworkHeaderIncludeSpelling(*FE, HFI->Framework, HS))
401 if (!tooling::isSelfContainedHeader(*FE, PP->getSourceManager(),
402 PP->getHeaderSearchInfo())) {
407 return getIncludeHeaderUncached(SM.getFileID(SM.getIncludeLoc(FID)));
417std::optional<SymbolLocation>
418SymbolCollector::getTokenLocation(SourceLocation TokLoc) {
419 const auto &SM = ASTCtx->getSourceManager();
420 const auto FE = SM.getFileEntryRefForID(SM.getFileID(TokLoc));
424 SymbolLocation Result;
425 Result.FileURI = HeaderFileURIs->toURI(*FE).c_str();
426 auto Range = getTokenRange(TokLoc, SM, ASTCtx->getLangOpts());
427 Result.Start =
Range.first;
428 Result.End =
Range.second;
438 HeaderFileURIs = std::make_unique<HeaderFileURICache>(
439 this->PP, ASTCtx->getSourceManager(), Opts);
440 CompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>();
442 std::make_unique<CodeCompletionTUInfo>(CompletionAllocator);
446 const ASTContext &ASTCtx,
448 bool IsMainFileOnly) {
450 if (ND.getDeclName().isEmpty())
454 if (IsMainFileOnly && !Opts.CollectMainFileSymbols)
458 if (!IsMainFileOnly && ND.isInAnonymousNamespace())
462 if (index::isFunctionLocalSymbol(&ND))
463 return isa<RecordDecl>(ND) ||
464 (ND.isCXXInstanceMember() && ND.isFunctionOrFunctionTemplate());
470 const auto *DeclCtx = ND.getDeclContext();
471 switch (DeclCtx->getDeclKind()) {
472 case Decl::TranslationUnit:
473 case Decl::Namespace:
474 case Decl::LinkageSpec:
476 case Decl::ObjCProtocol:
477 case Decl::ObjCInterface:
478 case Decl::ObjCCategory:
479 case Decl::ObjCCategoryImpl:
480 case Decl::ObjCImplementation:
485 if (!isa<RecordDecl>(DeclCtx))
490 if (isPrivateProtoDecl(ND))
492 if (!Opts.CollectReserved &&
503 const auto *ND = dyn_cast<NamedDecl>(Enclosing);
507 Enclosing = dyn_cast_or_null<Decl>(Enclosing->getDeclContext());
514 const Decl *D, index::SymbolRoleSet Roles,
515 llvm::ArrayRef<index::SymbolRelation> Relations, SourceLocation
Loc,
516 index::IndexDataConsumer::ASTNodeInfo
ASTNode) {
517 assert(ASTCtx && PP && HeaderFileURIs);
518 assert(CompletionAllocator && CompletionTUInfo);
523 if (D->getLocation().isInvalid())
528 if ((
ASTNode.OrigD->getFriendObjectKind() !=
529 Decl::FriendObjectKind::FOK_None) &&
530 !(Roles &
static_cast<unsigned>(index::SymbolRole::Definition)))
535 if (D->getFriendObjectKind() != Decl::FriendObjectKind::FOK_None)
536 D = CanonicalDecls.try_emplace(D,
ASTNode.OrigD).first->second;
539 bool DeclIsCanonical =
false;
542 if (
const auto *IID = dyn_cast<ObjCImplementationDecl>(D)) {
543 DeclIsCanonical =
true;
544 if (
const auto *CID = IID->getClassInterface())
545 if (
const auto *DD = CID->getDefinition())
546 if (!DD->isImplicitInterfaceDecl())
551 if (
const auto *CID = dyn_cast<ObjCCategoryImplDecl>(D)) {
552 DeclIsCanonical =
true;
553 if (
const auto *CD = CID->getCategoryDecl())
556 const NamedDecl *ND = dyn_cast<NamedDecl>(D);
560 auto ID = getSymbolIDCached(ND);
566 auto &SM = ASTCtx->getSourceManager();
568 (Roles &
static_cast<unsigned>(index::SymbolRole::Reference)) &&
569 SM.getFileID(SM.getSpellingLoc(
Loc)) == SM.getMainFileID())
570 ReferencedSymbols.insert(ID);
575 bool IsMainFileOnly =
576 SM.isWrittenInMainFile(SM.getExpansionLoc(ND->getBeginLoc())) &&
577 !
isHeaderFile(SM.getFileEntryRefForID(SM.getMainFileID())->getName(),
578 ASTCtx->getLangOpts());
580 if (
ASTNode.OrigD->isImplicit() ||
588 processRelations(*ND, ID, Relations);
590 bool CollectRef =
static_cast<bool>(Opts.
RefFilter & toRefKind(Roles));
597 ND->isExternallyVisible()) &&
598 !isa<NamespaceDecl>(ND)) {
599 auto FileLoc = SM.getFileLoc(
Loc);
600 auto FID = SM.getFileID(FileLoc);
602 addRef(ID, SymbolRef{FileLoc, FID, Roles,
604 isSpelled(FileLoc, *ND)});
608 if (!(Roles & (
static_cast<unsigned>(index::SymbolRole::Declaration) |
609 static_cast<unsigned>(index::SymbolRole::Definition))))
615 auto *OriginalDecl = dyn_cast<NamedDecl>(
ASTNode.OrigD);
620 if (isPreferredDeclaration(*OriginalDecl, Roles))
625 BasicSymbol = addDeclaration(*OriginalDecl, std::move(ID), IsMainFileOnly);
626 else if (!BasicSymbol || DeclIsCanonical)
627 BasicSymbol = addDeclaration(*ND, std::move(ID), IsMainFileOnly);
629 if (Roles &
static_cast<unsigned>(index::SymbolRole::Definition))
630 addDefinition(*OriginalDecl, *BasicSymbol);
636 assert(HeaderFileURIs && PP);
637 const auto &SM = PP->getSourceManager();
638 const auto MainFileEntryRef = SM.getFileEntryRefForID(SM.getMainFileID());
639 assert(MainFileEntryRef);
641 const std::string &MainFileURI = HeaderFileURIs->toURI(*MainFileEntryRef);
643 for (
const auto &IDToRefs : MacroRefsToIndex.
MacroRefs) {
644 for (
const auto &MacroRef : IDToRefs.second) {
645 const auto &
Range = MacroRef.Rng;
646 bool IsDefinition = MacroRef.IsDefinition;
654 Refs.
insert(IDToRefs.first, R);
657 S.
ID = IDToRefs.first;
661 S.
SymInfo.Kind = index::SymbolKind::Macro;
662 S.
SymInfo.SubKind = index::SymbolSubKind::None;
663 S.
SymInfo.Properties = index::SymbolPropertySet();
664 S.
SymInfo.Lang = index::SymbolLanguage::C;
669 if (!HeaderFileURIs->getIncludeHeader(SM.getMainFileID()).empty()) {
681 index::SymbolRoleSet Roles,
682 SourceLocation
Loc) {
685 if (MI->isBuiltinMacro())
688 const auto &SM = PP->getSourceManager();
689 auto DefLoc = MI->getDefinitionLoc();
692 if (SM.isWrittenInBuiltinFile(DefLoc) ||
693 SM.isWrittenInCommandLineFile(DefLoc) ||
694 Name->getName() ==
"__GCC_HAVE_DWARF2_CFI_ASM")
697 auto ID = getSymbolIDCached(
Name->getName(), MI, SM);
701 auto SpellingLoc = SM.getSpellingLoc(
Loc);
702 bool IsMainFileOnly =
703 SM.isInMainFile(SM.getExpansionLoc(DefLoc)) &&
704 !
isHeaderFile(SM.getFileEntryRefForID(SM.getMainFileID())->getName(),
705 ASTCtx->getLangOpts());
707 if ((
static_cast<unsigned>(Opts.
RefFilter) & Roles) && !IsMainFileOnly &&
708 (Opts.
RefsInHeaders || SM.getFileID(SpellingLoc) == SM.getMainFileID())) {
712 addRef(ID, SymbolRef{
Loc, SM.getFileID(
Loc), Roles,
nullptr,
728 (Roles &
static_cast<unsigned>(index::SymbolRole::Reference)) &&
729 SM.getFileID(SpellingLoc) == SM.getMainFileID())
730 ReferencedSymbols.insert(ID);
734 if (!(Roles &
static_cast<unsigned>(index::SymbolRole::Declaration) ||
735 Roles &
static_cast<unsigned>(index::SymbolRole::Definition)))
739 if (Symbols.
find(ID) !=
nullptr)
743 S.
ID = std::move(ID);
745 if (!IsMainFileOnly) {
749 S.
SymInfo = index::getSymbolInfoForMacro(*MI);
753 if (
auto DeclLoc = getTokenLocation(DefLoc))
756 CodeCompletionResult SymbolCompletion(
Name);
757 const auto *CCS = SymbolCompletion.CreateCodeCompletionStringForMacro(
758 *PP, *CompletionAllocator, *CompletionTUInfo);
762 SymbolCompletion.CursorKind);
766 IndexedMacros.insert(
Name);
767 setIncludeLocation(S, DefLoc);
772void SymbolCollector::processRelations(
773 const NamedDecl &ND,
const SymbolID &ID,
774 ArrayRef<index::SymbolRelation> Relations) {
775 for (
const auto &R : Relations) {
776 auto RKind = indexableRelation(R);
781 auto ObjectID = getSymbolIDCached(
Object);
795 this->Relations.insert({ID, *RKind, ObjectID});
797 this->Relations.insert({ObjectID, *RKind, ID});
801void SymbolCollector::setIncludeLocation(
const Symbol &S, SourceLocation
Loc) {
807 PP->getSourceManager().getDecomposedExpansionLoc(
Loc).first;
812 for (
const auto &ID : ReferencedSymbols) {
813 if (
const auto *S = Symbols.
find(ID)) {
824 for (
const IdentifierInfo *II : IndexedMacros) {
825 if (
const auto *MI = PP->getMacroDefinition(II).getMacroInfo())
827 getSymbolIDCached(II->getName(), MI, PP->getSourceManager()))
828 if (MI->isUsedForHeaderGuard())
832 llvm::DenseMap<FileID, bool> FileToContainsImportsOrObjC;
835 for (
const auto &[SID, FID] : IncludeFiles) {
837 llvm::StringRef IncludeHeader;
842 if (!IncludeHeader.empty()) {
843 if (IncludeHeader.front() !=
'"' && IncludeHeader.front() !=
'<')
844 IncludeHeader = HeaderFileURIs->toURI(IncludeHeader);
845 else if (IncludeHeader ==
"<utility>" && S->Scope ==
"std::" &&
846 S->Name ==
"move" && S->Signature.contains(
','))
847 IncludeHeader =
"<algorithm>";
851 if (IncludeHeader.empty())
852 IncludeHeader = HeaderFileURIs->getIncludeHeader(FID);
855 if (!IncludeHeader.empty()) {
857 auto CollectDirectives = shouldCollectIncludePath(S->SymInfo.Kind);
862 auto [It, Inserted] = FileToContainsImportsOrObjC.try_emplace(FID);
864 It->second = FilesWithObjCConstructs.contains(FID) ||
865 tooling::codeContainsImports(
866 ASTCtx->getSourceManager().getBufferData(FID));
879 ReferencedSymbols.clear();
880 IncludeFiles.clear();
881 FilesWithObjCConstructs.clear();
884const Symbol *SymbolCollector::addDeclaration(
const NamedDecl &ND,
SymbolID ID,
885 bool IsMainFileOnly) {
886 auto &Ctx = ND.getASTContext();
887 auto &SM = Ctx.getSourceManager();
890 S.
ID = std::move(ID);
905 S.
SymInfo = index::getSymbolInfo(&ND);
907 assert(
Loc.isValid() &&
"Invalid source location for NamedDecl");
909 auto FID = SM.getFileID(
Loc);
911 if (
auto DeclLoc = getTokenLocation(
Loc))
915 if (ND.getAvailability() == AR_Deprecated)
920 assert(ASTCtx && PP &&
"ASTContext and Preprocessor must be set.");
922 CodeCompletionResult SymbolCompletion(&getTemplateOrThis(ND), 0);
923 const auto *CCS = SymbolCompletion.CreateCodeCompletionString(
924 *ASTCtx, *PP, CodeCompletionContext::CCC_Symbol, *CompletionAllocator,
927 std::string Documentation =
934 return Symbols.
find(S.
ID);
940 SymbolCompletion.CursorKind);
946 std::optional<OpaqueType> TypeStorage;
950 S.
Type = TypeStorage->raw();
954 setIncludeLocation(S, ND.getLocation());
955 if (S.
SymInfo.Lang == index::SymbolLanguage::ObjC)
956 FilesWithObjCConstructs.insert(FID);
957 return Symbols.
find(S.
ID);
960void SymbolCollector::addDefinition(
const NamedDecl &ND,
961 const Symbol &DeclSym) {
962 if (DeclSym.Definition)
964 const auto &SM = ND.getASTContext().getSourceManager();
967 auto DefLoc = getTokenLocation(
Loc);
982 auto I = FilesToIndexCache.try_emplace(FID);
984 I.first->second = Opts.
FileFilter(ASTCtx->getSourceManager(), FID);
985 return I.first->second;
988void SymbolCollector::addRef(
SymbolID ID,
const SymbolRef &SR) {
989 const auto &SM = ASTCtx->getSourceManager();
992 if (
const auto FE = SM.getFileEntryRefForID(SR.FID)) {
993 auto Range = getTokenRange(SR.Loc, SM, ASTCtx->getLangOpts());
998 R.
Kind = toRefKind(SR.Roles, SR.Spelled);
999 R.
Container = getSymbolIDCached(SR.Container);
1004SymbolID SymbolCollector::getSymbolIDCached(
const Decl *D) {
1005 auto It = DeclToIDCache.try_emplace(D, SymbolID{});
1008 return It.first->second;
1012 const MacroInfo *MI,
1013 const SourceManager &SM) {
1014 auto It = MacroToIDCache.try_emplace(MI, SymbolID{});
1017 return It.first->second;
const FunctionDecl * Decl
std::string SnippetSuffix
CharSourceRange Range
SourceRange for the file name.
std::string Filename
Filename as a string.
Maps a definition location onto an #include file, based on a set of filename rules.
llvm::StringRef mapSymbol(llvm::StringRef Scope, llvm::StringRef Name, const LangOptions &L) const
Returns the overridden include for a qualified symbol with, or "".
static std::optional< OpaqueType > fromCompletionResult(ASTContext &Ctx, const CodeCompletionResult &R)
Create a type from a code completion result.
void insert(const SymbolID &ID, const Ref &S)
Adds a ref to the slab. Deep copy: Strings will be owned by the slab.
bool shouldIndexFile(FileID FID)
Returns true if we are interested in references and declarations from FID.
static bool shouldCollectSymbol(const NamedDecl &ND, const ASTContext &ASTCtx, const Options &Opts, bool IsMainFileSymbol)
Returns true is ND should be collected.
static const Decl * getRefContainer(const Decl *Enclosing, const SymbolCollector::Options &Opts)
SymbolCollector(Options Opts)
bool handleDeclOccurrence(const Decl *D, index::SymbolRoleSet Roles, ArrayRef< index::SymbolRelation > Relations, SourceLocation Loc, index::IndexDataConsumer::ASTNodeInfo ASTNode) override
void handleMacros(const MainFileMacros &MacroRefsToIndex)
void initialize(ASTContext &Ctx) override
bool handleMacroOccurrence(const IdentifierInfo *Name, const MacroInfo *MI, index::SymbolRoleSet Roles, SourceLocation Loc) override
const Symbol * find(const SymbolID &ID)
Returns the symbol with an ID, if it exists. Valid until insert/remove.
void erase(const SymbolID &ID)
Removes the symbol with an ID, if it exists.
void insert(const Symbol &S)
Adds a symbol, overwriting any existing one with the same ID.
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
std::string printTemplateSpecializationArgs(const NamedDecl &ND)
Prints template arguments of a decl as written in the source code, including enclosing '<' and '>',...
std::pair< StringRef, StringRef > splitQualifiedName(StringRef QName)
SymbolID getSymbolID(const Decl *D)
Gets the symbol ID for a declaration. Returned SymbolID might be null.
std::string formatDocumentation(const CodeCompletionString &CCS, llvm::StringRef DocComment)
Assembles formatted documentation for a completion result.
std::string Path
A typedef to represent a file path.
bool isInsideMainFile(SourceLocation Loc, const SourceManager &SM)
Returns true iff Loc is inside the main file.
SourceLocation nameLocation(const clang::Decl &D, const SourceManager &SM)
Find the source location of the identifier for D.
std::string getReturnType(const CodeCompletionString &CCS)
Gets detail to be used as the detail field in an LSP completion item.
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
bool hasReservedName(const Decl &D)
Returns true if this is a NamedDecl with a reserved name.
llvm::StringRef toSourceCode(const SourceManager &SM, SourceRange R)
Returns the source code covered by the source range.
RefKind
Describes the kind of a cross-reference.
void getSignature(const CodeCompletionString &CCS, std::string *Signature, std::string *Snippet, CodeCompletionResult::ResultKind ResultKind, CXCursorKind CursorKind, std::string *RequiredQualifiers)
Formats the signature for an item, as a display string and snippet.
std::optional< std::string > getCanonicalPath(const FileEntryRef F, const SourceManager &SourceMgr)
Get the canonical path of F.
llvm::Expected< SourceLocation > sourceLocationInMainFile(const SourceManager &SM, Position P)
Return the file location, corresponding to P.
bool isImplementationDetail(const Decl *D)
Returns true if the declaration is considered implementation detail based on heuristics.
bool hasReservedScope(const DeclContext &DC)
Returns true if this scope would be written with a reserved name.
std::string printQualifiedName(const NamedDecl &ND)
Returns the qualified name of ND.
bool isProtoFile(SourceLocation Loc, const SourceManager &SM)
Returns true if the given location is in a generated protobuf file.
std::string getDocComment(const ASTContext &Ctx, const CodeCompletionResult &Result, bool CommentsFromHeaders)
Gets a minimally formatted documentation comment of Result, with comment markers stripped.
bool isHeaderFile(llvm::StringRef FileName, std::optional< LangOptions > LangOpts)
Infers whether this is a header from the FileName and LangOpts (if presents).
bool isIndexedForCodeCompletion(const NamedDecl &ND, ASTContext &ASTCtx)
std::array< uint8_t, 20 > SymbolID
@ Canonical
The two mix because the types refer to the same CanonicalType, but we do not elaborate as to how.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Simplified description of a clang AST node.
llvm::DenseMap< SymbolID, std::vector< MacroOccurrence > > MacroRefs
int line
Line position in a document (zero-based).
int character
Character offset on a line in a document (zero-based).
Position start
The range's start position.
Position end
The range's end position.
Represents a symbol occurrence in the source file.
SymbolID Container
The ID of the symbol whose definition contains this reference.
SymbolLocation Location
The source location where the symbol is named.
bool CollectMacro
Collect macros.
const CanonicalIncludes * Includes
If set, this is used to map symbol #include path to a potentially different #include path.
RefKind RefFilter
The symbol ref kinds that will be collected.
bool CollectMainFileSymbols
Collect symbols local to main-files, such as static functions, symbols inside an anonymous namespace,...
bool StoreAllDocumentation
If set to true, SymbolCollector will collect doc for all symbols.
bool CollectMainFileRefs
Collect references to main-file symbols.
bool RefsInHeaders
If set to true, SymbolCollector will collect all refs (from main file and included headers); otherwis...
std::function< bool(const SourceManager &, FileID)> FileFilter
If this is set, only collect symbols/references from a file if FileFilter(SM, FID) is true.
void setColumn(uint32_t Column)
void setLine(uint32_t Line)
Position Start
The symbol range, using half-open range [Start, End).
The class presents a C++ symbol, e.g.
@ IndexedForCodeCompletion
Whether or not this symbol is meant to be used for the code completion.
@ Deprecated
Indicates if the symbol is deprecated.
@ ImplementationDetail
Symbol is an implementation detail.
@ VisibleOutsideFile
Symbol is visible to other files (not e.g. a static helper function).
@ Include
#include "header.h"
@ Import
#import "header.h"
SymbolLocation Definition
The location of the symbol's definition, if one was found.
llvm::StringRef Type
Raw representation of the OpaqueType of the symbol, used for scoring purposes.
llvm::StringRef Documentation
Documentation including comment for the symbol declaration.
index::SymbolInfo SymInfo
The symbol information, like symbol kind.
llvm::SmallVector< IncludeHeaderWithReferences, 1 > IncludeHeaders
One Symbol can potentially be included via different headers.
llvm::StringRef Name
The unqualified name of the symbol, e.g. "bar" (for ns::bar).
llvm::StringRef Scope
The containing namespace. e.g. "" (global), "ns::" (top-level namespace).
llvm::StringRef Signature
A brief description of the symbol that can be appended in the completion candidate list.
llvm::StringRef ReturnType
Type when this symbol is used in an expression.
llvm::StringRef TemplateSpecializationArgs
Argument list in human-readable format, will be displayed to help disambiguate between different spec...
SymbolLocation CanonicalDeclaration
The location of the preferred declaration of the symbol.
llvm::StringRef CompletionSnippetSuffix
What to insert when completing this symbol, after the symbol name.
SymbolID ID
The ID of the symbol.
SymbolOrigin Origin
Where this symbol came from. Usually an index provides a constant value.