18 #include "clang/AST/DeclTemplate.h" 19 #include "clang/Index/IndexDataConsumer.h" 20 #include "clang/Index/IndexSymbol.h" 21 #include "clang/Index/IndexingAction.h" 22 #include "llvm/Support/FormatVariadic.h" 23 #include "llvm/Support/Path.h" 24 #include "llvm/Support/ScopedPrinter.h" 26 #define DEBUG_TYPE "FindSymbols" 40 case index::SymbolKind::Module:
42 case index::SymbolKind::Namespace:
44 case index::SymbolKind::NamespaceAlias:
46 case index::SymbolKind::Macro:
48 case index::SymbolKind::Enum:
50 case index::SymbolKind::Struct:
52 case index::SymbolKind::Class:
54 case index::SymbolKind::Protocol:
56 case index::SymbolKind::Extension:
58 case index::SymbolKind::Union:
60 case index::SymbolKind::TypeAlias:
62 case index::SymbolKind::Function:
64 case index::SymbolKind::Variable:
66 case index::SymbolKind::Field:
68 case index::SymbolKind::EnumConstant:
70 case index::SymbolKind::InstanceMethod:
71 case index::SymbolKind::ClassMethod:
72 case index::SymbolKind::StaticMethod:
74 case index::SymbolKind::InstanceProperty:
75 case index::SymbolKind::ClassProperty:
76 case index::SymbolKind::StaticProperty:
78 case index::SymbolKind::Constructor:
79 case index::SymbolKind::Destructor:
81 case index::SymbolKind::ConversionFunction:
83 case index::SymbolKind::Parameter:
85 case index::SymbolKind::Using:
88 llvm_unreachable(
"invalid symbol kind");
91 using ScoredSymbolInfo = std::pair<float, SymbolInformation>;
92 struct ScoredSymbolGreater {
93 bool operator()(
const ScoredSymbolInfo &L,
const ScoredSymbolInfo &R) {
94 if (L.first != R.first)
95 return L.first > R.first;
96 return L.second.name < R.second.name;
102 llvm::Expected<std::vector<SymbolInformation>>
105 std::vector<SymbolInformation>
Result;
106 if (Query.empty() || !
Index)
112 Req.
Query = Names.second;
115 bool IsGlobalQuery = Names.first.consume_front(
"::");
118 if (IsGlobalQuery || !Names.first.empty())
119 Req.
Scopes = {Names.first};
124 TopN<ScoredSymbolInfo, ScoredSymbolGreater> Top(
125 Req.Limit ? *Req.Limit : std::numeric_limits<size_t>::max());
126 FuzzyMatcher Filter(Req.Query);
127 Index->fuzzyFind(Req, [HintPath, &Top, &Filter](
const Symbol &Sym) {
129 auto &CD = Sym.Definition ? Sym.Definition : Sym.CanonicalDeclaration;
132 log(
"Workspace symbol: Could not parse URI '{0}' for symbol '{1}'.",
133 CD.FileURI, Sym.Name);
138 log(
"Workspace symbol: Could not resolve path for URI '{0}' for symbol " 140 Uri->toString(), Sym.Name);
148 Start.line = CD.Start.line();
149 Start.character = CD.Start.column();
150 End.line = CD.End.line();
151 End.character = CD.End.column();
152 L.range = {Start, End};
153 SymbolKind SK = indexSymbolKindToSymbolKind(Sym.SymInfo.Kind);
154 std::string Scope = Sym.Scope;
155 llvm::StringRef ScopeRef = Scope;
156 ScopeRef.consume_back(
"::");
157 SymbolInformation
Info = {Sym.Name, SK, L, ScopeRef};
161 SymbolRelevanceSignals Relevance;
163 if (
auto NameMatch = Filter.match(Sym.Name))
164 Relevance.NameMatch = *NameMatch;
166 log(
"Workspace symbol: {0} didn't match query {1}", Sym.Name,
170 Relevance.merge(Sym);
173 dlog(
"FindSymbols: {0}{1} = {2}\n{3}{4}\n", Sym.Scope, Sym.Name, Score,
176 Top.push({Score, std::move(Info)});
178 for (
auto &R : std::move(Top).items())
179 Result.push_back(std::move(R.second));
184 llvm::Optional<DocumentSymbol> declToSym(ASTContext &
Ctx,
const NamedDecl &ND) {
185 auto &SM = Ctx.getSourceManager();
192 SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc()));
193 SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc()));
194 if (NameLoc.isInvalid() || BeginLoc.isInvalid() || EndLoc.isInvalid())
197 if (!SM.isWrittenInMainFile(NameLoc) || !SM.isWrittenInMainFile(BeginLoc) ||
198 !SM.isWrittenInMainFile(EndLoc))
203 SM, Lexer::getLocForEndOfToken(NameLoc, 0, SM, Ctx.getLangOpts()));
208 SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind);
213 SI.deprecated = ND.isDeprecated();
216 SI.selectionRange =
Range{NameBegin, NameEnd};
217 if (!SI.range.contains(SI.selectionRange)) {
220 SI.range = SI.selectionRange;
233 class DocumentOutline {
235 DocumentOutline(ParsedAST &
AST) : AST(AST) {}
238 std::vector<DocumentSymbol> build() {
239 std::vector<DocumentSymbol>
Results;
240 for (
auto &TopLevel :
AST.getLocalTopLevelDecls())
241 traverseDecl(TopLevel, Results);
246 enum class VisitKind {
No, OnlyDecl, DeclAndChildren };
248 void traverseDecl(Decl *
D, std::vector<DocumentSymbol> &Results) {
249 if (
auto *Templ = llvm::dyn_cast<TemplateDecl>(D))
250 D = Templ->getTemplatedDecl();
251 auto *ND = llvm::dyn_cast<NamedDecl>(
D);
254 VisitKind Visit = shouldVisit(ND);
257 llvm::Optional<DocumentSymbol> Sym = declToSym(
AST.getASTContext(), *ND);
260 if (Visit == VisitKind::DeclAndChildren)
261 traverseChildren(D, Sym->children);
262 Results.push_back(std::move(*Sym));
265 void traverseChildren(Decl *D, std::vector<DocumentSymbol> &Results) {
266 auto *Scope = llvm::dyn_cast<DeclContext>(
D);
269 for (
auto *C : Scope->decls())
270 traverseDecl(C, Results);
273 VisitKind shouldVisit(NamedDecl *D) {
277 if (
auto Func = llvm::dyn_cast<FunctionDecl>(D)) {
280 if (
auto *Info = Func->getTemplateSpecializationInfo()) {
281 if (!Info->isExplicitInstantiationOrSpecialization())
286 return VisitKind::OnlyDecl;
296 if (
auto *TemplSpec = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D)) {
297 if (TemplSpec->isExplicitInstantiationOrSpecialization())
298 return TemplSpec->isExplicitSpecialization()
299 ? VisitKind::DeclAndChildren
300 : VisitKind::OnlyDecl;
303 if (
auto *TemplSpec = llvm::dyn_cast<VarTemplateSpecializationDecl>(D)) {
304 if (TemplSpec->isExplicitInstantiationOrSpecialization())
305 return TemplSpec->isExplicitSpecialization()
306 ? VisitKind::DeclAndChildren
307 : VisitKind::OnlyDecl;
311 return VisitKind::DeclAndChildren;
317 std::vector<DocumentSymbol> collectDocSymbols(ParsedAST &
AST) {
318 return DocumentOutline(AST).build();
323 return collectDocSymbols(AST);
std::string printName(const ASTContext &Ctx, const NamedDecl &ND)
Prints unqualified name of the decl for the purpose of displaying it to the user. ...
SignatureQualitySignals Quality
llvm::Expected< std::vector< SymbolInformation > > getWorkspaceSymbols(llvm::StringRef Query, int Limit, const SymbolIndex *const Index, llvm::StringRef HintPath)
Searches for the symbols matching Query.
Diagnostics must be generated for this snapshot.
clang::find_all_symbols::SymbolInfo::SymbolKind SymbolKind
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
SourceLocation findNameLoc(const clang::Decl *D)
Find the identifier source location of the given D.
std::vector< CodeCompletionResult > Results
Documents should not be synced at all.
std::vector< std::string > Scopes
If this is non-empty, symbols must be in at least one of the scopes (e.g.
std::vector< SymbolDetails > getSymbolInfo(ParsedAST &AST, Position Pos)
Get info about symbols at Pos.
clang::find_all_symbols::SymbolInfo SymbolInfo
void log(const char *Fmt, Ts &&... Vals)
std::string Path
A typedef to represent a file path.
std::string Query
A query string for the fuzzy find.
static URIForFile canonicalize(llvm::StringRef AbsPath, llvm::StringRef TUPath)
Canonicalizes AbsPath via URI.
SymbolKind
The SymbolInfo Type.
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
Position sourceLocToPosition(const SourceManager &SM, SourceLocation Loc)
Turn a SourceLocation into a [line, column] pair.
Stores and provides access to parsed AST.
float evaluateSymbolAndRelevance(float SymbolQuality, float SymbolRelevance)
Combine symbol quality and relevance into a single score.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
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...
CharSourceRange Range
SourceRange for the file name.
std::pair< llvm::StringRef, llvm::StringRef > splitQualifiedName(llvm::StringRef QName)
From "a::b::c", return {"a::b::", "c"}.
static llvm::Expected< std::string > resolve(const URI &U, llvm::StringRef HintPath="")
Resolves the absolute path of U.
static llvm::Expected< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".
const SymbolIndex * Index