19#include "clang/AST/Decl.h"
20#include "clang/AST/DeclFriend.h"
21#include "clang/AST/DeclTemplate.h"
22#include "clang/Index/IndexSymbol.h"
23#include "llvm/ADT/ArrayRef.h"
24#include "llvm/ADT/STLExtras.h"
25#include "llvm/ADT/SmallVector.h"
26#include "llvm/ADT/StringRef.h"
30#define DEBUG_TYPE "FindSymbols"
56bool isStatic(
const Decl *D) {
57 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
58 return CMD->isStatic();
59 if (
const VarDecl *VD = llvm::dyn_cast<VarDecl>(D))
60 return VD->isStaticDataMember() || VD->isStaticLocal();
61 if (
const auto *OPD = llvm::dyn_cast<ObjCPropertyDecl>(D))
62 return OPD->isClassProperty();
63 if (
const auto *OMD = llvm::dyn_cast<ObjCMethodDecl>(D))
64 return OMD->isClassMethod();
65 if (
const auto *FD = llvm::dyn_cast<FunctionDecl>(D))
66 return FD->isStatic();
71bool isConst(QualType T) {
74 T = T.getNonReferenceType();
75 if (T.isConstQualified())
77 if (
const auto *AT = T->getAsArrayTypeUnsafe())
78 return isConst(AT->getElementType());
79 if (isConst(T->getPointeeType()))
87bool isConst(
const Decl *D) {
88 if (llvm::isa<EnumConstantDecl>(D) || llvm::isa<NonTypeTemplateParmDecl>(D))
90 if (llvm::isa<FieldDecl>(D) || llvm::isa<VarDecl>(D) ||
91 llvm::isa<MSPropertyDecl>(D) || llvm::isa<BindingDecl>(D)) {
92 if (isConst(llvm::cast<ValueDecl>(D)->getType()))
95 if (
const auto *OCPD = llvm::dyn_cast<ObjCPropertyDecl>(D)) {
96 if (OCPD->isReadOnly())
99 if (
const auto *MPD = llvm::dyn_cast<MSPropertyDecl>(D)) {
100 if (!MPD->hasSetter())
103 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D)) {
107 if (
const auto *FD = llvm::dyn_cast<FunctionDecl>(D))
108 return isConst(FD->getReturnType());
114bool isAbstract(
const Decl *D) {
115 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
116 return CMD->isPureVirtual();
117 if (
const auto *CRD = llvm::dyn_cast<CXXRecordDecl>(D))
118 return CRD->hasDefinition() && CRD->isAbstract();
123bool isVirtual(
const Decl *D) {
124 if (
const auto *CMD = llvm::dyn_cast<CXXMethodDecl>(D))
125 return CMD->isVirtual();
131bool isFinal(
const Decl *D) {
132 if (
const auto *CRD = dyn_cast<CXXMethodDecl>(D))
133 return CRD->hasAttr<FinalAttr>();
135 if (
const auto *CRD = dyn_cast<CXXRecordDecl>(D))
136 return CRD->hasAttr<FinalAttr>();
145bool isOverrides(
const NamedDecl *ND) {
146 if (
const auto *
MD = llvm::dyn_cast<CXXMethodDecl>(ND)) {
147 if (!
MD->isVirtual())
150 for (
const auto *Overridden :
MD->overridden_methods()) {
152 assert(Overridden->isVirtual());
154 if (!Overridden->isPureVirtual())
165bool isImplements(
const NamedDecl *ND) {
166 if (
const auto *
MD = llvm::dyn_cast<CXXMethodDecl>(ND)) {
167 if (
MD->size_overridden_methods() == 0 ||
MD->isPureVirtual())
170 for (
const auto *Overridden :
MD->overridden_methods()) {
171 if (!Overridden->isPureVirtual())
181bool isUniqueDefinition(
const NamedDecl *Decl) {
182 if (
auto *Func = dyn_cast<FunctionDecl>(Decl))
183 return Func->isThisDeclarationADefinition();
184 if (
auto *Klass = dyn_cast<CXXRecordDecl>(Decl))
185 return Klass->isThisDeclarationADefinition();
186 if (
auto *Iface = dyn_cast<ObjCInterfaceDecl>(Decl))
187 return Iface->isThisDeclarationADefinition();
188 if (
auto *Proto = dyn_cast<ObjCProtocolDecl>(Decl))
189 return Proto->isThisDeclarationADefinition();
190 if (
auto *Var = dyn_cast<VarDecl>(Decl))
191 return Var->isThisDeclarationADefinition();
192 return isa<TemplateTypeParmDecl>(Decl) ||
193 isa<NonTypeTemplateParmDecl>(Decl) ||
194 isa<TemplateTemplateParmDecl>(Decl) || isa<ObjCCategoryDecl>(Decl) ||
195 isa<ObjCImplDecl>(Decl);
208 const SymbolTags VirtualAndOverridesMask = VirtualMask | OverridesMask;
211 if (ST & ImplementsMask)
212 ST &= ~VirtualAndOverridesMask;
216 ST &= ~VirtualAndOverridesMask;
219 if (ST & (OverridesMask | AbstractMask))
226 using clang::index::SymbolKind;
227 using clang::index::SymbolLanguage;
229 if (S.
SymInfo.Lang != SymbolLanguage::CXX)
232 return llvm::is_contained({SymbolKind::InstanceMethod,
233 SymbolKind::StaticMethod, SymbolKind::Constructor,
234 SymbolKind::Destructor,
235 SymbolKind::ConversionFunction},
239template <
typename E>
constexpr E enumIncrement(E Value) {
240 return static_cast<E
>(
static_cast<std::underlying_type_t<E>
>(Value) + 1);
245 return (1 <<
static_cast<unsigned>(ST));
250 const auto IsDef = isUniqueDefinition(&ND);
252 if (ND.isDeprecated())
267 if (isOverrides(&ND))
273 if (isImplements(&ND))
276 if (not isa<UnresolvedUsingValueDecl>(ND)) {
286 switch (ND.getAccess()) {
304 std::vector<SymbolTag> Tags;
318 for (
unsigned I = MinTag; I <= MaxTag; ++I) {
328 isCXXClassMethod(S) ? filterSymbolTags(S.
Tags) : S.
Tags;
335 std::vector<SymbolTag> Tags;
341 if (isa<CXXMethodDecl>(ND))
342 FilteredTags = filterSymbolTags(STGS);
348 Tag = enumIncrement(Tag)) {
356using ScoredSymbolInfo = std::pair<float, SymbolInformation>;
357struct ScoredSymbolGreater {
358 bool operator()(
const ScoredSymbolInfo &L,
const ScoredSymbolInfo &R) {
359 if (L.first != R.first)
360 return L.first > R.first;
361 return L.second.name < R.second.name;
366bool approximateScopeMatch(llvm::StringRef Scope, llvm::StringRef Query) {
367 assert(Scope.empty() || Scope.ends_with(
"::"));
368 assert(Query.empty() || Query.ends_with(
"::"));
369 while (!Scope.empty() && !Query.empty()) {
370 auto Colons = Scope.find(
"::");
371 assert(Colons != llvm::StringRef::npos);
373 llvm::StringRef LeadingSpecifier = Scope.slice(0, Colons + 2);
374 Scope = Scope.slice(Colons + 2, llvm::StringRef::npos);
375 Query.consume_front(LeadingSpecifier);
377 return Query.empty();
383 llvm::StringRef TUPath) {
386 return error(
"Could not resolve path for file '{0}': {1}", Loc.
FileURI,
395 L.
range = {Start, End};
400 llvm::StringRef TUPath) {
406llvm::Expected<std::vector<SymbolInformation>>
408 const SymbolIndex *
const Index, llvm::StringRef HintPath) {
409 std::vector<SymbolInformation> Result;
420 Req.
Query = std::string(Names.second);
423 auto HasLeadingColons = Names.first.consume_front(
"::");
427 if (HasLeadingColons || !Names.first.empty())
428 Req.
Scopes = {std::string(Names.first)};
437 Req.
Limit.value_or(std::numeric_limits<size_t>::max()));
441 ReqScope = Names.first](
const Symbol &Sym) {
442 llvm::StringRef Scope = Sym.Scope;
445 if (AnyScope && !approximateScopeMatch(Scope, ReqScope))
448 auto Loc = symbolToLocation(Sym, HintPath);
450 log(
"Workspace symbols: {0}", Loc.takeError());
460 Relevance.InBaseClass = AnyScope && Scope != ReqScope;
461 if (
auto NameMatch = Filter.
match(Sym.
Name))
462 Relevance.NameMatch = *NameMatch;
464 log(
"Workspace symbol: {0} didn't match query {1}", Sym.Name,
468 Relevance.merge(Sym);
469 auto QualScore = Quality.evaluateHeuristics();
470 auto RelScore = Relevance.evaluateHeuristics();
472 dlog(
"FindSymbols: {0}{1} = {2}\n{3}{4}\n", Sym.
Scope, Sym.
Name, Score,
478 Info.location = *Loc;
479 Scope.consume_back(
"::");
480 Info.containerName = Scope.str();
483 Info.score = Relevance.NameMatch > std::numeric_limits<float>::epsilon()
484 ? Score / Relevance.NameMatch
489 for (
auto &R : std::move(Top).items())
490 Result.push_back(std::move(R.second));
495std::string getSymbolName(ASTContext &Ctx,
const NamedDecl &ND) {
498 if (
const auto *Container = dyn_cast<ObjCContainerDecl>(&ND))
499 return printObjCContainer(*Container);
502 if (
const auto *Method = dyn_cast<ObjCMethodDecl>(&ND)) {
504 llvm::raw_string_ostream OS(Name);
506 OS << (Method->isInstanceMethod() ?
'-' :
'+');
507 Method->getSelector().print(OS);
514std::string getSymbolDetail(ASTContext &Ctx,
const NamedDecl &ND) {
515 PrintingPolicy
P(Ctx.getPrintingPolicy());
516 P.SuppressScope =
true;
517 P.SuppressUnwrittenScope =
true;
518 P.AnonymousTagNameStyle =
519 llvm::to_underlying(PrintingPolicy::AnonymousTagMode::Plain);
520 P.PolishForDeclaration =
true;
522 llvm::raw_string_ostream OS(Detail);
523 if (ND.getDescribedTemplateParams()) {
526 if (
const auto *VD = dyn_cast<ValueDecl>(&ND)) {
528 if (isa<CXXConstructorDecl>(VD)) {
529 std::string ConstructorType = VD->getType().getAsString(P);
531 llvm::StringRef WithoutVoid = ConstructorType;
532 WithoutVoid.consume_front(
"void ");
534 }
else if (!isa<CXXDestructorDecl>(VD)) {
535 VD->getType().print(OS, P);
537 }
else if (
const auto *TD = dyn_cast<TagDecl>(&ND)) {
538 OS << TD->getKindName();
539 }
else if (isa<TypedefNameDecl>(&ND)) {
541 }
else if (isa<ConceptDecl>(&ND)) {
544 return std::move(OS.str());
547std::optional<DocumentSymbol> declToSym(ASTContext &Ctx,
const NamedDecl &ND) {
548 auto &SM = Ctx.getSourceManager();
550 SourceLocation BeginLoc = ND.getBeginLoc();
551 SourceLocation EndLoc = ND.getEndLoc();
552 const auto SymbolRange =
557 index::SymbolInfo SymInfo = index::getSymbolInfo(&ND);
563 SI.name = getSymbolName(Ctx, ND);
565 SI.deprecated = ND.isDeprecated();
568 SI.detail = getSymbolDetail(Ctx, ND);
571 SourceLocation NameLoc = ND.getLocation();
572 SourceLocation FallbackNameLoc;
573 if (NameLoc.isMacroID()) {
576 FallbackNameLoc = SM.getExpansionLoc(NameLoc);
577 NameLoc = SM.getSpellingLoc(NameLoc);
579 NameLoc = SM.getExpansionLoc(NameLoc);
582 auto ComputeSelectionRange = [&](SourceLocation L) -> Range {
585 SM, Lexer::getLocForEndOfToken(L, 0, SM, Ctx.getLangOpts()));
586 return Range{NameBegin, NameEnd};
589 SI.selectionRange = ComputeSelectionRange(NameLoc);
590 if (!SI.range.contains(SI.selectionRange) && FallbackNameLoc.isValid()) {
594 SI.selectionRange = ComputeSelectionRange(FallbackNameLoc);
596 if (!SI.range.contains(SI.selectionRange)) {
599 SI.range = SI.selectionRange;
612class DocumentOutline {
618 DocumentSymbol Symbol;
621 llvm::SmallVector<SourceLocation> EnclosingMacroLoc;
624 DocumentSymbol build() && {
625 for (SymBuilder &C : Children) {
626 Symbol.children.push_back(std::move(C).build());
632 std::min(Symbol.range.start, Symbol.children.back().range.start);
634 std::max(Symbol.range.end, Symbol.children.back().range.end);
636 return std::move(Symbol);
640 SymBuilder &addChild(DocumentSymbol S) {
642 Children.back().EnclosingMacroLoc = EnclosingMacroLoc;
643 Children.back().Symbol = std::move(S);
653 SymBuilder &inMacro(
const syntax::Token &Tok,
const SourceManager &SM,
654 std::optional<syntax::TokenBuffer::Expansion> Exp) {
655 if (llvm::is_contained(EnclosingMacroLoc, Tok.location()))
659 Children.back().EnclosingMacroLoc.back() == Tok.location())
663 Sym.name = Tok.text(SM).str();
664 Sym.kind = SymbolKind::Null;
665 Sym.range = Sym.selectionRange =
672 Exp->Spelled.front().location(),
673 Exp->Spelled.back().endLocation()));
675 llvm::raw_string_ostream OS(Sym.detail);
676 const syntax::Token *Prev =
nullptr;
677 for (
const auto &Tok : Exp->Spelled.drop_front()) {
679 if (OS.tell() > 80) {
683 if (Prev && Prev->endLocation() != Tok.location())
689 SymBuilder &Child = addChild(std::move(Sym));
690 Child.EnclosingMacroLoc.push_back(Tok.location());
696 DocumentOutline(ParsedAST &AST) :
AST(
AST) {}
699 std::vector<DocumentSymbol> build() {
701 for (
auto &TopLevel :
AST.getLocalTopLevelDecls())
702 traverseDecl(TopLevel, Root);
703 return std::move(std::move(Root).build().children);
707 enum class VisitKind {
No, OnlyDecl, OnlyChildren, DeclAndChildren };
709 void traverseDecl(Decl *D, SymBuilder &Parent) {
714 if (
auto *Templ = llvm::dyn_cast<TemplateDecl>(D)) {
716 if (
auto *TD = Templ->getTemplatedDecl())
723 if (
auto *Friend = llvm::dyn_cast<FriendDecl>(D)) {
725 llvm::dyn_cast_or_null<FunctionDecl>(Friend->getFriendDecl())) {
726 if (Func->isThisDeclarationADefinition())
731 VisitKind Visit = shouldVisit(D);
732 if (Visit == VisitKind::No)
735 if (Visit == VisitKind::OnlyChildren)
736 return traverseChildren(D, Parent);
738 auto *ND = llvm::cast<NamedDecl>(D);
739 auto Sym = declToSym(
AST.getASTContext(), *ND);
742 SymBuilder &MacroParent = possibleMacroContainer(
D->getLocation(), Parent);
743 SymBuilder &Child = MacroParent.addChild(std::move(*Sym));
745 if (Visit == VisitKind::OnlyDecl)
748 assert(Visit == VisitKind::DeclAndChildren &&
"Unexpected VisitKind");
749 traverseChildren(ND, Child);
767 SymBuilder &possibleMacroContainer(SourceLocation TargetLoc,
768 SymBuilder &Parent) {
769 const auto &SM =
AST.getSourceManager();
772 SymBuilder *CurParent = &Parent;
773 for (SourceLocation Loc = TargetLoc; Loc.isMacroID();
774 Loc = SM.getImmediateMacroCallerLoc(Loc)) {
777 if (SM.isMacroArgExpansion(Loc)) {
779 MacroBody = SM.getFileID(SM.getImmediateExpansionRange(Loc).getBegin());
782 MacroBody = SM.getFileID(Loc);
786 SourceLocation MacroName =
787 SM.getSLocEntry(MacroBody).getExpansion().getExpansionLocStart();
790 if (!MacroName.isValid() || !MacroName.isFileID())
793 if (
auto *Tok =
AST.getTokens().spelledTokenContaining(MacroName))
794 CurParent = &CurParent->inMacro(
795 *Tok, SM,
AST.getTokens().expansionStartingAt(Tok));
800 void traverseChildren(Decl *D, SymBuilder &Builder) {
801 auto *Scope = llvm::dyn_cast<DeclContext>(D);
804 for (
auto *C : Scope->decls())
805 traverseDecl(C, Builder);
808 VisitKind shouldVisit(Decl *D) {
810 return VisitKind::No;
812 if (llvm::isa<LinkageSpecDecl>(D) || llvm::isa<ExportDecl>(D))
813 return VisitKind::OnlyChildren;
815 if (!llvm::isa<NamedDecl>(D))
816 return VisitKind::No;
818 if (
auto *Func = llvm::dyn_cast<FunctionDecl>(D)) {
821 if (
auto *Info = Func->getTemplateSpecializationInfo()) {
822 if (!
Info->isExplicitInstantiationOrSpecialization())
823 return VisitKind::No;
827 return VisitKind::OnlyDecl;
837 if (
auto *TemplSpec = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D)) {
838 if (TemplSpec->isExplicitInstantiationOrSpecialization())
839 return TemplSpec->isExplicitSpecialization()
840 ? VisitKind::DeclAndChildren
841 : VisitKind::OnlyDecl;
842 return VisitKind::No;
844 if (
auto *TemplSpec = llvm::dyn_cast<VarTemplateSpecializationDecl>(D)) {
845 if (TemplSpec->isExplicitInstantiationOrSpecialization())
846 return TemplSpec->isExplicitSpecialization()
847 ? VisitKind::DeclAndChildren
848 : VisitKind::OnlyDecl;
849 return VisitKind::No;
852 return VisitKind::DeclAndChildren;
858struct PragmaMarkSymbol {
859 DocumentSymbol DocSym;
865void mergePragmas(DocumentSymbol &Root, ArrayRef<PragmaMarkSymbol> Pragmas) {
866 while (!Pragmas.empty()) {
868 PragmaMarkSymbol
P = std::move(Pragmas.front());
869 Pragmas = Pragmas.drop_front();
870 DocumentSymbol *Cur = &Root;
871 while (Cur->range.contains(
P.DocSym.range)) {
872 bool Swapped =
false;
873 for (
auto &C : Cur->children) {
876 if (
C.range.contains(
P.DocSym.range)) {
888 Cur->children.emplace_back(std::move(
P.DocSym));
899 bool TerminatedByNextPragma =
false;
900 for (
auto &NextPragma : Pragmas) {
902 if (!Cur->range.contains(NextPragma.DocSym.range))
907 if (llvm::any_of(Cur->children, [&NextPragma](
const auto &Child) {
908 return Child.range.contains(NextPragma.DocSym.range);
913 auto It = llvm::partition(Cur->children,
914 [&P, &NextPragma](
const auto &S) ->
bool {
915 return !(P.DocSym.range < S.range &&
916 S.range < NextPragma.DocSym.range);
918 P.DocSym.children.assign(make_move_iterator(It),
919 make_move_iterator(Cur->children.end()));
920 Cur->children.erase(It, Cur->children.end());
921 TerminatedByNextPragma =
true;
924 if (!TerminatedByNextPragma) {
927 auto It = llvm::partition(Cur->children, [&P](
const auto &S) ->
bool {
928 return !(P.DocSym.range < S.range);
930 P.DocSym.children.assign(make_move_iterator(It),
931 make_move_iterator(Cur->children.end()));
932 Cur->children.erase(It, Cur->children.end());
935 for (DocumentSymbol &Sym :
P.DocSym.children)
937 Cur->children.emplace_back(std::move(
P.DocSym));
941PragmaMarkSymbol markToSymbol(
const PragmaMark &P) {
942 StringRef Name = StringRef(
P.Trivia).trim();
943 bool IsGroup =
false;
950 StringRef MaybeGroupName = Name;
951 if (MaybeGroupName.consume_front(
"-") &&
952 (MaybeGroupName.ltrim() != MaybeGroupName || MaybeGroupName.empty())) {
953 Name = MaybeGroupName.empty() ?
"(unnamed group)" : MaybeGroupName.ltrim();
955 }
else if (Name.empty()) {
956 Name =
"(unnamed mark)";
959 Sym.name = Name.str();
960 Sym.kind = SymbolKind::File;
962 Sym.selectionRange =
P.Rng;
963 return {Sym, IsGroup};
966std::vector<DocumentSymbol> collectDocSymbols(ParsedAST &AST) {
967 std::vector<DocumentSymbol> Syms = DocumentOutline(AST).build();
969 const auto &PragmaMarks =
AST.getMarks();
970 if (PragmaMarks.empty())
973 std::vector<PragmaMarkSymbol> Pragmas;
974 Pragmas.reserve(PragmaMarks.size());
975 for (
const auto &P : PragmaMarks)
976 Pragmas.push_back(markToSymbol(P));
979 {std::numeric_limits<int>::max(), std::numeric_limits<int>::max()}};
981 Root.children = std::move(Syms);
982 Root.range = EntireFile;
983 mergePragmas(Root, llvm::ArrayRef(Pragmas));
984 return Root.children;
990 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.