19#include "clang/AST/Attr.h"
20#include "clang/AST/Decl.h"
21#include "clang/AST/DeclFriend.h"
22#include "clang/AST/DeclTemplate.h"
23#include "clang/Index/IndexSymbol.h"
24#include "llvm/ADT/ArrayRef.h"
25#include "llvm/ADT/STLExtras.h"
26#include "llvm/ADT/SmallVector.h"
27#include "llvm/ADT/StringRef.h"
31#define DEBUG_TYPE "FindSymbols"
57bool isStatic(
const Decl *D) {
58 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
59 return CMD->isStatic();
60 if (
const VarDecl *VD = llvm::dyn_cast<VarDecl>(D))
61 return VD->isStaticDataMember() || VD->isStaticLocal();
62 if (
const auto *OPD = llvm::dyn_cast<ObjCPropertyDecl>(D))
63 return OPD->isClassProperty();
64 if (
const auto *OMD = llvm::dyn_cast<ObjCMethodDecl>(D))
65 return OMD->isClassMethod();
66 if (
const auto *FD = llvm::dyn_cast<FunctionDecl>(D))
67 return FD->isStatic();
72bool isConst(QualType T) {
75 T = T.getNonReferenceType();
76 if (T.isConstQualified())
78 if (
const auto *AT = T->getAsArrayTypeUnsafe())
79 return isConst(AT->getElementType());
80 if (isConst(T->getPointeeType()))
88bool isConst(
const Decl *D) {
89 if (llvm::isa<EnumConstantDecl>(D) || llvm::isa<NonTypeTemplateParmDecl>(D))
91 if (llvm::isa<FieldDecl>(D) || llvm::isa<VarDecl>(D) ||
92 llvm::isa<MSPropertyDecl>(D) || llvm::isa<BindingDecl>(D)) {
93 if (isConst(llvm::cast<ValueDecl>(D)->getType()))
96 if (
const auto *OCPD = llvm::dyn_cast<ObjCPropertyDecl>(D)) {
97 if (OCPD->isReadOnly())
100 if (
const auto *MPD = llvm::dyn_cast<MSPropertyDecl>(D)) {
101 if (!MPD->hasSetter())
104 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) {
108 if (
const auto *FD = llvm::dyn_cast<FunctionDecl>(D))
109 return isConst(FD->getReturnType());
115bool isAbstract(
const Decl *D) {
116 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
117 return CMD->isPureVirtual();
118 if (
const auto *CRD = llvm::dyn_cast<CXXRecordDecl>(D))
119 return CRD->hasDefinition() && CRD->isAbstract();
124bool isVirtual(
const Decl *D) {
125 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
126 return CMD->isVirtual();
132bool isFinal(
const Decl *D) {
133 if (
const auto *CRD = dyn_cast<CXXMethodDecl>(D))
134 return CRD->hasAttr<FinalAttr>();
136 if (
const auto *CRD = dyn_cast<CXXRecordDecl>(D))
137 return CRD->hasAttr<FinalAttr>();
146bool isOverrides(
const NamedDecl *ND) {
147 if (
const auto *
MD = llvm::dyn_cast<CXXMethodDecl>(ND)) {
148 if (!
MD->isVirtual())
151 for (
const auto *Overridden :
MD->overridden_methods()) {
153 assert(Overridden->isVirtual());
155 if (!Overridden->isPureVirtual())
166bool isImplements(
const NamedDecl *ND) {
167 if (
const auto *
MD = llvm::dyn_cast<CXXMethodDecl>(ND)) {
168 if (
MD->size_overridden_methods() == 0 ||
MD->isPureVirtual())
171 for (
const auto *Overridden :
MD->overridden_methods()) {
172 if (!Overridden->isPureVirtual())
182bool isUniqueDefinition(
const NamedDecl *Decl) {
183 if (
auto *Func = dyn_cast<FunctionDecl>(Decl))
184 return Func->isThisDeclarationADefinition();
185 if (
auto *Klass = dyn_cast<CXXRecordDecl>(Decl))
186 return Klass->isThisDeclarationADefinition();
187 if (
auto *Iface = dyn_cast<ObjCInterfaceDecl>(Decl))
188 return Iface->isThisDeclarationADefinition();
189 if (
auto *Proto = dyn_cast<ObjCProtocolDecl>(Decl))
190 return Proto->isThisDeclarationADefinition();
191 if (
auto *Var = dyn_cast<VarDecl>(Decl))
192 return Var->isThisDeclarationADefinition();
193 return isa<TemplateTypeParmDecl>(Decl) ||
194 isa<NonTypeTemplateParmDecl>(Decl) ||
195 isa<TemplateTemplateParmDecl>(Decl) || isa<ObjCCategoryDecl>(Decl) ||
196 isa<ObjCImplDecl>(Decl);
209 const SymbolTags VirtualAndOverridesMask = VirtualMask | OverridesMask;
212 if (ST & ImplementsMask)
213 ST &= ~VirtualAndOverridesMask;
217 ST &= ~VirtualAndOverridesMask;
220 if (ST & (OverridesMask | AbstractMask))
227 using clang::index::SymbolKind;
228 using clang::index::SymbolLanguage;
230 if (S.
SymInfo.Lang != SymbolLanguage::CXX)
233 return llvm::is_contained({SymbolKind::InstanceMethod,
234 SymbolKind::StaticMethod, SymbolKind::Constructor,
235 SymbolKind::Destructor,
236 SymbolKind::ConversionFunction},
240template <
typename E>
constexpr E enumIncrement(E Value) {
241 return static_cast<E
>(
static_cast<std::underlying_type_t<E>
>(Value) + 1);
246 return (1 <<
static_cast<unsigned>(ST));
251 const auto IsDef = isUniqueDefinition(&ND);
253 if (ND.isDeprecated())
268 if (isOverrides(&ND))
274 if (isImplements(&ND))
277 if (not isa<UnresolvedUsingValueDecl>(ND)) {
287 switch (ND.getAccess()) {
305 std::vector<SymbolTag> Tags;
319 for (
unsigned I = MinTag; I <= MaxTag; ++I) {
329 isCXXClassMethod(S) ? filterSymbolTags(S.
Tags) : S.
Tags;
336 std::vector<SymbolTag> Tags;
342 if (isa<CXXMethodDecl>(ND))
343 FilteredTags = filterSymbolTags(STGS);
349 Tag = enumIncrement(Tag)) {
357using ScoredSymbolInfo = std::pair<float, SymbolInformation>;
358struct ScoredSymbolGreater {
359 bool operator()(
const ScoredSymbolInfo &L,
const ScoredSymbolInfo &R) {
360 if (L.first != R.first)
361 return L.first > R.first;
362 return L.second.name < R.second.name;
367bool approximateScopeMatch(llvm::StringRef Scope, llvm::StringRef Query) {
368 assert(Scope.empty() || Scope.ends_with(
"::"));
369 assert(Query.empty() || Query.ends_with(
"::"));
370 while (!Scope.empty() && !Query.empty()) {
371 auto Colons = Scope.find(
"::");
372 assert(Colons != llvm::StringRef::npos);
374 llvm::StringRef LeadingSpecifier = Scope.slice(0, Colons + 2);
375 Scope = Scope.slice(Colons + 2, llvm::StringRef::npos);
376 Query.consume_front(LeadingSpecifier);
378 return Query.empty();
384 llvm::StringRef TUPath) {
387 return error(
"Could not resolve path for file '{0}': {1}", Loc.
FileURI,
396 L.
range = {Start, End};
401 llvm::StringRef TUPath) {
407llvm::Expected<std::vector<SymbolInformation>>
409 const SymbolIndex *
const Index, llvm::StringRef HintPath) {
410 std::vector<SymbolInformation> Result;
421 Req.
Query = std::string(Names.second);
424 auto HasLeadingColons = Names.first.consume_front(
"::");
428 if (HasLeadingColons || !Names.first.empty())
429 Req.
Scopes = {std::string(Names.first)};
438 Req.
Limit.value_or(std::numeric_limits<size_t>::max()));
442 ReqScope = Names.first](
const Symbol &Sym) {
443 llvm::StringRef Scope = Sym.Scope;
446 if (AnyScope && !approximateScopeMatch(Scope, ReqScope))
449 auto Loc = symbolToLocation(Sym, HintPath);
451 log(
"Workspace symbols: {0}", Loc.takeError());
461 Relevance.InBaseClass = AnyScope && Scope != ReqScope;
462 if (
auto NameMatch = Filter.
match(Sym.
Name))
463 Relevance.NameMatch = *NameMatch;
465 log(
"Workspace symbol: {0} didn't match query {1}", Sym.Name,
469 Relevance.merge(Sym);
470 auto QualScore = Quality.evaluateHeuristics();
471 auto RelScore = Relevance.evaluateHeuristics();
473 dlog(
"FindSymbols: {0}{1} = {2}\n{3}{4}\n", Sym.
Scope, Sym.
Name, Score,
479 Info.location = *Loc;
480 Scope.consume_back(
"::");
481 Info.containerName = Scope.str();
484 Info.score = Relevance.NameMatch > std::numeric_limits<float>::epsilon()
485 ? Score / Relevance.NameMatch
490 for (
auto &R : std::move(Top).items())
491 Result.push_back(std::move(R.second));
496std::string getSymbolName(ASTContext &Ctx,
const NamedDecl &ND) {
499 if (
const auto *Container = dyn_cast<ObjCContainerDecl>(&ND))
500 return printObjCContainer(*Container);
503 if (
const auto *Method = dyn_cast<ObjCMethodDecl>(&ND)) {
505 llvm::raw_string_ostream OS(Name);
507 OS << (Method->isInstanceMethod() ?
'-' :
'+');
508 Method->getSelector().print(OS);
515std::string getSymbolDetail(ASTContext &Ctx,
const NamedDecl &ND) {
516 PrintingPolicy
P(Ctx.getPrintingPolicy());
517 P.SuppressScope =
true;
518 P.SuppressUnwrittenScope =
true;
519 P.AnonymousTagNameStyle =
520 llvm::to_underlying(PrintingPolicy::AnonymousTagMode::Plain);
521 P.PolishForDeclaration =
true;
523 llvm::raw_string_ostream OS(Detail);
524 if (ND.getDescribedTemplateParams()) {
527 if (
const auto *VD = dyn_cast<ValueDecl>(&ND)) {
529 if (isa<CXXConstructorDecl>(VD)) {
530 std::string ConstructorType = VD->getType().getAsString(P);
532 llvm::StringRef WithoutVoid = ConstructorType;
533 WithoutVoid.consume_front(
"void ");
535 }
else if (!isa<CXXDestructorDecl>(VD)) {
536 VD->getType().print(OS, P);
538 }
else if (
const auto *TD = dyn_cast<TagDecl>(&ND)) {
539 OS << TD->getKindName();
540 }
else if (isa<TypedefNameDecl>(&ND)) {
542 }
else if (isa<ConceptDecl>(&ND)) {
545 return std::move(OS.str());
548std::optional<DocumentSymbol> declToSym(ASTContext &Ctx,
const NamedDecl &ND) {
549 auto &SM = Ctx.getSourceManager();
551 SourceLocation BeginLoc = ND.getBeginLoc();
552 SourceLocation EndLoc = ND.getEndLoc();
553 const auto SymbolRange =
558 index::SymbolInfo SymInfo = index::getSymbolInfo(&ND);
564 SI.name = getSymbolName(Ctx, ND);
566 SI.deprecated = ND.isDeprecated();
569 SI.detail = getSymbolDetail(Ctx, ND);
572 SourceLocation NameLoc = ND.getLocation();
573 SourceLocation FallbackNameLoc;
574 if (NameLoc.isMacroID()) {
577 FallbackNameLoc = SM.getExpansionLoc(NameLoc);
578 NameLoc = SM.getSpellingLoc(NameLoc);
580 NameLoc = SM.getExpansionLoc(NameLoc);
583 auto ComputeSelectionRange = [&](SourceLocation L) -> Range {
586 SM, Lexer::getLocForEndOfToken(L, 0, SM, Ctx.getLangOpts()));
587 return Range{NameBegin, NameEnd};
590 SI.selectionRange = ComputeSelectionRange(NameLoc);
591 if (!SI.range.contains(SI.selectionRange) && FallbackNameLoc.isValid()) {
595 SI.selectionRange = ComputeSelectionRange(FallbackNameLoc);
597 if (!SI.range.contains(SI.selectionRange)) {
600 SI.range = SI.selectionRange;
613class DocumentOutline {
619 DocumentSymbol Symbol;
622 llvm::SmallVector<SourceLocation> EnclosingMacroLoc;
625 DocumentSymbol build() && {
626 for (SymBuilder &C : Children) {
627 Symbol.children.push_back(std::move(C).build());
633 std::min(Symbol.range.start, Symbol.children.back().range.start);
635 std::max(Symbol.range.end, Symbol.children.back().range.end);
637 return std::move(Symbol);
641 SymBuilder &addChild(DocumentSymbol S) {
643 Children.back().EnclosingMacroLoc = EnclosingMacroLoc;
644 Children.back().Symbol = std::move(S);
654 SymBuilder &inMacro(
const syntax::Token &Tok,
const SourceManager &SM,
655 std::optional<syntax::TokenBuffer::Expansion> Exp) {
656 if (llvm::is_contained(EnclosingMacroLoc, Tok.location()))
660 Children.back().EnclosingMacroLoc.back() == Tok.location())
664 Sym.name = Tok.text(SM).str();
665 Sym.kind = SymbolKind::Null;
666 Sym.range = Sym.selectionRange =
673 Exp->Spelled.front().location(),
674 Exp->Spelled.back().endLocation()));
676 llvm::raw_string_ostream OS(Sym.detail);
677 const syntax::Token *Prev =
nullptr;
678 for (
const auto &Tok : Exp->Spelled.drop_front()) {
680 if (OS.tell() > 80) {
684 if (Prev && Prev->endLocation() != Tok.location())
690 SymBuilder &Child = addChild(std::move(Sym));
691 Child.EnclosingMacroLoc.push_back(Tok.location());
697 DocumentOutline(ParsedAST &AST) :
AST(
AST) {}
700 std::vector<DocumentSymbol> build() {
702 for (
auto &TopLevel :
AST.getLocalTopLevelDecls())
703 traverseDecl(TopLevel, Root);
704 return std::move(std::move(Root).build().children);
708 enum class VisitKind {
No, OnlyDecl, OnlyChildren, DeclAndChildren };
710 void traverseDecl(Decl *D, SymBuilder &Parent) {
715 if (
auto *Templ = llvm::dyn_cast<TemplateDecl>(D)) {
717 if (
auto *TD = Templ->getTemplatedDecl())
724 if (
auto *Friend = llvm::dyn_cast<FriendDecl>(D)) {
726 llvm::dyn_cast_or_null<FunctionDecl>(Friend->getFriendDecl())) {
727 if (Func->isThisDeclarationADefinition())
732 VisitKind Visit = shouldVisit(D);
733 if (Visit == VisitKind::No)
736 if (Visit == VisitKind::OnlyChildren)
737 return traverseChildren(D, Parent);
739 auto *ND = llvm::cast<NamedDecl>(D);
740 auto Sym = declToSym(
AST.getASTContext(), *ND);
743 SymBuilder &MacroParent = possibleMacroContainer(
D->getLocation(), Parent);
744 SymBuilder &Child = MacroParent.addChild(std::move(*Sym));
746 if (Visit == VisitKind::OnlyDecl)
749 assert(Visit == VisitKind::DeclAndChildren &&
"Unexpected VisitKind");
750 traverseChildren(ND, Child);
768 SymBuilder &possibleMacroContainer(SourceLocation TargetLoc,
769 SymBuilder &Parent) {
770 const auto &SM =
AST.getSourceManager();
773 SymBuilder *CurParent = &Parent;
774 for (SourceLocation Loc = TargetLoc; Loc.isMacroID();
775 Loc = SM.getImmediateMacroCallerLoc(Loc)) {
778 if (SM.isMacroArgExpansion(Loc)) {
780 MacroBody = SM.getFileID(SM.getImmediateExpansionRange(Loc).getBegin());
783 MacroBody = SM.getFileID(Loc);
787 SourceLocation MacroName =
788 SM.getSLocEntry(MacroBody).getExpansion().getExpansionLocStart();
791 if (!MacroName.isValid() || !MacroName.isFileID())
794 if (
auto *Tok =
AST.getTokens().spelledTokenContaining(MacroName))
795 CurParent = &CurParent->inMacro(
796 *Tok, SM,
AST.getTokens().expansionStartingAt(Tok));
801 void traverseChildren(Decl *D, SymBuilder &Builder) {
802 auto *Scope = llvm::dyn_cast<DeclContext>(D);
805 for (
auto *C : Scope->decls())
806 traverseDecl(C, Builder);
809 VisitKind shouldVisit(Decl *D) {
811 return VisitKind::No;
813 if (llvm::isa<LinkageSpecDecl>(D) || llvm::isa<ExportDecl>(D))
814 return VisitKind::OnlyChildren;
816 if (!llvm::isa<NamedDecl>(D))
817 return VisitKind::No;
819 if (
auto *Func = llvm::dyn_cast<FunctionDecl>(D)) {
822 if (
auto *Info = Func->getTemplateSpecializationInfo()) {
823 if (!
Info->isExplicitInstantiationOrSpecialization())
824 return VisitKind::No;
828 return VisitKind::OnlyDecl;
838 if (
auto *TemplSpec = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D)) {
839 if (TemplSpec->isExplicitInstantiationOrSpecialization())
840 return TemplSpec->isExplicitSpecialization()
841 ? VisitKind::DeclAndChildren
842 : VisitKind::OnlyDecl;
843 return VisitKind::No;
845 if (
auto *TemplSpec = llvm::dyn_cast<VarTemplateSpecializationDecl>(D)) {
846 if (TemplSpec->isExplicitInstantiationOrSpecialization())
847 return TemplSpec->isExplicitSpecialization()
848 ? VisitKind::DeclAndChildren
849 : VisitKind::OnlyDecl;
850 return VisitKind::No;
853 return VisitKind::DeclAndChildren;
859struct PragmaMarkSymbol {
860 DocumentSymbol DocSym;
866void mergePragmas(DocumentSymbol &Root, ArrayRef<PragmaMarkSymbol> Pragmas) {
867 while (!Pragmas.empty()) {
869 PragmaMarkSymbol
P = std::move(Pragmas.front());
870 Pragmas = Pragmas.drop_front();
871 DocumentSymbol *Cur = &Root;
872 while (Cur->range.contains(
P.DocSym.range)) {
873 bool Swapped =
false;
874 for (
auto &C : Cur->children) {
877 if (
C.range.contains(
P.DocSym.range)) {
889 Cur->children.emplace_back(std::move(
P.DocSym));
900 bool TerminatedByNextPragma =
false;
901 for (
auto &NextPragma : Pragmas) {
903 if (!Cur->range.contains(NextPragma.DocSym.range))
908 if (llvm::any_of(Cur->children, [&NextPragma](
const auto &Child) {
909 return Child.range.contains(NextPragma.DocSym.range);
914 auto It = llvm::partition(Cur->children,
915 [&P, &NextPragma](
const auto &S) ->
bool {
916 return !(P.DocSym.range < S.range &&
917 S.range < NextPragma.DocSym.range);
919 P.DocSym.children.assign(make_move_iterator(It),
920 make_move_iterator(Cur->children.end()));
921 Cur->children.erase(It, Cur->children.end());
922 TerminatedByNextPragma =
true;
925 if (!TerminatedByNextPragma) {
928 auto It = llvm::partition(Cur->children, [&P](
const auto &S) ->
bool {
929 return !(P.DocSym.range < S.range);
931 P.DocSym.children.assign(make_move_iterator(It),
932 make_move_iterator(Cur->children.end()));
933 Cur->children.erase(It, Cur->children.end());
936 for (DocumentSymbol &Sym :
P.DocSym.children)
938 Cur->children.emplace_back(std::move(
P.DocSym));
942PragmaMarkSymbol markToSymbol(
const PragmaMark &P) {
943 StringRef Name = StringRef(
P.Trivia).trim();
944 bool IsGroup =
false;
951 StringRef MaybeGroupName = Name;
952 if (MaybeGroupName.consume_front(
"-") &&
953 (MaybeGroupName.ltrim() != MaybeGroupName || MaybeGroupName.empty())) {
954 Name = MaybeGroupName.empty() ?
"(unnamed group)" : MaybeGroupName.ltrim();
956 }
else if (Name.empty()) {
957 Name =
"(unnamed mark)";
960 Sym.name = Name.str();
961 Sym.kind = SymbolKind::File;
963 Sym.selectionRange =
P.Rng;
964 return {Sym, IsGroup};
967std::vector<DocumentSymbol> collectDocSymbols(ParsedAST &AST) {
968 std::vector<DocumentSymbol> Syms = DocumentOutline(AST).build();
970 const auto &PragmaMarks =
AST.getMarks();
971 if (PragmaMarks.empty())
974 std::vector<PragmaMarkSymbol> Pragmas;
975 Pragmas.reserve(PragmaMarks.size());
976 for (
const auto &P : PragmaMarks)
977 Pragmas.push_back(markToSymbol(P));
980 {std::numeric_limits<int>::max(), std::numeric_limits<int>::max()}};
982 Root.children = std::move(Syms);
983 Root.range = EntireFile;
984 mergePragmas(Root, llvm::ArrayRef(Pragmas));
985 return Root.children;
991 return collectDocSymbols(
AST);
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for Markdown output.")
clang::find_all_symbols::SymbolInfo::SymbolKind SymbolKind
std::optional< float > match(llvm::StringRef Word)
Stores and provides access to parsed AST.
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
virtual bool fuzzyFind(const FuzzyFindRequest &Req, llvm::function_ref< void(const Symbol &)> Callback) const =0
Matches symbols in the index fuzzily and applies Callback on each matched symbol before returning.
TopN<T> is a lossy container that preserves only the "best" N elements.
bool push(value_type &&V)
static llvm::Expected< std::string > resolve(const URI &U, llvm::StringRef HintPath="")
Resolves the absolute path of U.
std::pair< StringRef, StringRef > splitQualifiedName(StringRef QName)
llvm::Expected< Location > indexToLSPLocation(const SymbolLocation &Loc, llvm::StringRef TUPath)
Helper function for deriving an LSP Location from an index SymbolLocation.
@ Info
An information message.
std::optional< SourceRange > toHalfOpenFileRange(const SourceManager &SM, const LangOptions &LangOpts, SourceRange R)
Turns a token range into a half-open range and checks its correctness.
uint32_t SymbolTags
A bitmask type representing symbol tags supported by LSP.
Range halfOpenToRange(const SourceManager &SM, CharSourceRange R)
std::string printName(const ASTContext &Ctx, const NamedDecl &ND)
Prints unqualified name of the decl for the purpose of displaying it to the user.
SymbolTag
Symbol tags are extra annotations that can be attached to a symbol.
std::vector< SymbolTag > getSymbolTags(const Symbol &S)
Returns the SymbolTag values for the given indexed S.
bool isInsideMainFile(SourceLocation Loc, const SourceManager &SM)
Returns true iff Loc is inside the main file.
llvm::Expected< Location > symbolToLocation(const Symbol &Sym, llvm::StringRef TUPath)
Helper function for deriving an LSP Location for a Symbol.
void unionRanges(Range &A, Range B)
llvm::Error error(std::error_code EC, const char *Fmt, Ts &&... Vals)
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
SymbolTags toSymbolTagBitmask(const SymbolTag ST)
Converts a single SymbolTag to a bitmask.
llvm::Expected< std::vector< DocumentSymbol > > getDocumentSymbols(ParsedAST &AST)
Retrieves the symbols contained in the "main file" section of an AST in the same order that they appe...
@ No
Diagnostics must be generated for this snapshot.
std::string Path
A typedef to represent a file path.
llvm::Expected< std::vector< SymbolInformation > > getWorkspaceSymbols(llvm::StringRef Query, int Limit, const SymbolIndex *const Index, llvm::StringRef HintPath)
Searches for the symbols matching Query.
SymbolKind indexSymbolKindToSymbolKind(const index::SymbolInfo &Info)
bool isSpelledInSource(SourceLocation Loc, const SourceManager &SM)
Returns true if the token at Loc is spelled in the source code.
float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance)
Combine symbol quality and relevance into a single score.
std::vector< SymbolTag > expandTagBitmask(const SymbolTags STGS)
SymbolTags computeSymbolTags(const NamedDecl &ND)
Computes symbol tags for a given NamedDecl.
cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccessCheck P
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
std::vector< std::string > Scopes
If this is non-empty, symbols must be in at least one of the scopes (e.g.
std::string Query
A query string for the fuzzy find.
bool AnyScope
If set to true, allow symbols from any scope.
std::optional< uint32_t > Limit
The number of top candidates to return.
URIForFile uri
The text document's URI.
int line
Line position in a document (zero-based).
int character
Character offset on a line in a document (zero-based).
Position Start
The symbol range, using half-open range [Start, End).
Attributes of a symbol that affect how much we like it.
void merge(const CodeCompletionResult &SemaCCResult)
Attributes of a symbol-query pair that affect how much we like it.
llvm::StringRef Name
The name of the symbol (for ContextWords). Must be explicitly assigned.
Ensure we have enough bits to represent all SymbolTag values.
SymbolLocation Definition
The location of the symbol's definition, if one was found.
SymbolTags Tags
Symbol tags for LSP protocol (Deprecated, Static, Virtual, Abstract, Final, ReadOnly,...
index::SymbolInfo SymInfo
The symbol information, like symbol kind.
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 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.
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.