18 #include "clang/Index/IndexDataConsumer.h" 19 #include "clang/Index/IndexSymbol.h" 20 #include "clang/Index/IndexingAction.h" 21 #include "llvm/Support/FormatVariadic.h" 22 #include "llvm/Support/Path.h" 24 #define DEBUG_TYPE "FindSymbols" 39 case index::SymbolKind::Module:
41 case index::SymbolKind::Namespace:
43 case index::SymbolKind::NamespaceAlias:
45 case index::SymbolKind::Macro:
47 case index::SymbolKind::Enum:
49 case index::SymbolKind::Struct:
51 case index::SymbolKind::Class:
53 case index::SymbolKind::Protocol:
55 case index::SymbolKind::Extension:
57 case index::SymbolKind::Union:
59 case index::SymbolKind::TypeAlias:
61 case index::SymbolKind::Function:
63 case index::SymbolKind::Variable:
65 case index::SymbolKind::Field:
67 case index::SymbolKind::EnumConstant:
69 case index::SymbolKind::InstanceMethod:
70 case index::SymbolKind::ClassMethod:
71 case index::SymbolKind::StaticMethod:
73 case index::SymbolKind::InstanceProperty:
74 case index::SymbolKind::ClassProperty:
75 case index::SymbolKind::StaticProperty:
77 case index::SymbolKind::Constructor:
78 case index::SymbolKind::Destructor:
80 case index::SymbolKind::ConversionFunction:
82 case index::SymbolKind::Parameter:
84 case index::SymbolKind::Using:
87 llvm_unreachable(
"invalid symbol kind");
90 using ScoredSymbolInfo = std::pair<float, SymbolInformation>;
91 struct ScoredSymbolGreater {
92 bool operator()(
const ScoredSymbolInfo &L,
const ScoredSymbolInfo &R) {
93 if (L.first != R.first)
94 return L.first > R.first;
95 return L.second.name < R.second.name;
101 llvm::Expected<std::vector<SymbolInformation>>
103 StringRef HintPath) {
104 std::vector<SymbolInformation> Result;
105 if (Query.empty() || !Index)
111 Req.
Query = Names.second;
114 bool IsGlobalQuery = Names.first.consume_front(
"::");
117 if (IsGlobalQuery || !Names.first.empty())
118 Req.
Scopes = {Names.first};
120 Req.MaxCandidateCount = Limit;
121 TopN<ScoredSymbolInfo, ScoredSymbolGreater> Top(Req.MaxCandidateCount);
122 FuzzyMatcher Filter(Req.Query);
123 Index->fuzzyFind(Req, [HintPath, &Top, &Filter](
const Symbol &Sym) {
125 auto &CD = Sym.Definition ? Sym.Definition : Sym.CanonicalDeclaration;
128 log(
"Workspace symbol: Could not parse URI '{0}' for symbol '{1}'.",
129 CD.FileURI, Sym.Name);
134 log(
"Workspace symbol: Could not resolve path for URI '{0}' for symbol " 136 Uri->toString(), Sym.Name);
140 L.uri = URIForFile((*
Path));
142 Start.line = CD.Start.Line;
143 Start.character = CD.Start.Column;
144 End.line = CD.End.Line;
145 End.character = CD.End.Column;
146 L.range = {Start, End};
147 SymbolKind SK = indexSymbolKindToSymbolKind(Sym.SymInfo.Kind);
148 std::string Scope = Sym.Scope;
149 StringRef ScopeRef = Scope;
150 ScopeRef.consume_back(
"::");
151 SymbolInformation
Info = {Sym.Name, SK, L, ScopeRef};
153 SymbolQualitySignals Quality;
155 SymbolRelevanceSignals Relevance;
157 if (
auto NameMatch = Filter.match(Sym.Name))
158 Relevance.NameMatch = *NameMatch;
160 log(
"Workspace symbol: {0} didn't match query {1}", Sym.Name,
164 Relevance.merge(Sym);
167 dlog(
"FindSymbols: {0}{1} = {2}\n{3}{4}\n", Sym.Scope, Sym.Name, Score,
170 Top.push({Score, std::move(Info)});
172 for (
auto &R : std::move(Top).items())
173 Result.push_back(std::move(R.second));
179 class DocumentSymbolsConsumer :
public index::IndexDataConsumer {
181 std::vector<SymbolInformation> Symbols;
183 llvm::Optional<URIForFile> MainFileUri;
186 DocumentSymbolsConsumer(ASTContext &AST) : AST(AST) {}
187 std::vector<SymbolInformation> takeSymbols() {
return std::move(Symbols); }
189 void initialize(ASTContext &
Ctx)
override {
192 const SourceManager &SM = AST.getSourceManager();
193 const FileEntry *F = SM.getFileEntryForID(SM.getMainFileID());
198 MainFileUri = URIForFile(*FilePath);
201 bool shouldIncludeSymbol(
const NamedDecl *ND) {
202 if (!ND || ND->isImplicit())
205 if (ND->getDeclName().isEmpty())
211 handleDeclOccurence(
const Decl *, index::SymbolRoleSet Roles,
212 ArrayRef<index::SymbolRelation> Relations,
214 index::IndexDataConsumer::ASTNodeInfo ASTNode)
override {
215 assert(ASTNode.OrigD);
221 if (!(Roles & static_cast<unsigned>(index::SymbolRole::Declaration) ||
222 Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
224 SourceLocation NameLoc =
findNameLoc(ASTNode.OrigD);
225 const SourceManager &SourceMgr = AST.getSourceManager();
227 if (!SourceMgr.isWrittenInMainFile(NameLoc)) {
232 const NamedDecl *ND = llvm::dyn_cast<NamedDecl>(ASTNode.OrigD);
233 if (!shouldIncludeSymbol(ND))
236 SourceLocation EndLoc =
237 Lexer::getLocForEndOfToken(NameLoc, 0, SourceMgr, AST.getLangOpts());
240 Range R = {Begin, End};
242 L.uri = *MainFileUri;
246 StringRef Scope,
Name;
248 Scope.consume_back(
"::");
251 SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind);
253 SymbolInformation SI;
257 SI.containerName = Scope;
258 Symbols.push_back(std::move(SI));
264 llvm::Expected<std::vector<SymbolInformation>>
266 DocumentSymbolsConsumer DocumentSymbolsCons(AST.
getASTContext());
268 index::IndexingOptions IndexOpts;
269 IndexOpts.SystemSymbolFilter =
270 index::IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly;
271 IndexOpts.IndexFunctionLocals =
false;
273 DocumentSymbolsCons, IndexOpts);
275 return DocumentSymbolsCons.takeSymbols();
SourceLocation Loc
'#' location in the include directive
std::string printQualifiedName(const NamedDecl &ND)
Returns the qualified name of ND.
llvm::Expected< std::vector< SymbolInformation > > getDocumentSymbols(ParsedAST &AST)
Retrieves the symbols contained in the "main file" section of an AST in the same order that they appe...
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.
llvm::Expected< std::vector< SymbolInformation > > getWorkspaceSymbols(StringRef Query, int Limit, const SymbolIndex *const Index, StringRef HintPath)
ASTContext & getASTContext()
Note that the returned ast will not contain decls from the preamble that were not deserialized during...
std::vector< std::string > Scopes
If this is non-empty, symbols must be in at least one of the scopes (e.g.
ArrayRef< Decl * > getLocalTopLevelDecls()
This function returns top-level decls present in the main file of the AST.
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.
SymbolKind
The SymbolInfo Type.
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++ -*-===//
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"}.
llvm::Optional< std::string > getAbsoluteFilePath(const FileEntry *F, const SourceManager &SourceMgr)
Get the absolute file path of a given file entry.
static llvm::Expected< std::string > resolve(const URI &U, llvm::StringRef HintPath="")
Resolves the absolute path of U.
tooling::ExecutionContext * Ctx
static llvm::Expected< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".