[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
//===--- FindSymbols.cpp ------------------------------------*- C++-*------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "FindSymbols.h"
|
|
|
|
|
2018-07-06 03:35:01 +08:00
|
|
|
#include "AST.h"
|
|
|
|
#include "ClangdUnit.h"
|
2018-06-07 14:55:59 +08:00
|
|
|
#include "FuzzyMatch.h"
|
2018-07-06 03:35:01 +08:00
|
|
|
#include "Logger.h"
|
2018-06-07 14:55:59 +08:00
|
|
|
#include "Quality.h"
|
2018-07-06 03:35:01 +08:00
|
|
|
#include "SourceCode.h"
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
#include "index/Index.h"
|
2018-07-06 03:35:01 +08:00
|
|
|
#include "clang/Index/IndexDataConsumer.h"
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
#include "clang/Index/IndexSymbol.h"
|
2018-07-06 03:35:01 +08:00
|
|
|
#include "clang/Index/IndexingAction.h"
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
#include "llvm/Support/FormatVariadic.h"
|
|
|
|
#include "llvm/Support/Path.h"
|
|
|
|
|
2018-06-07 14:55:59 +08:00
|
|
|
#define DEBUG_TYPE "FindSymbols"
|
|
|
|
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
// Convert a index::SymbolKind to clangd::SymbolKind (LSP)
|
|
|
|
// Note, some are not perfect matches and should be improved when this LSP
|
|
|
|
// issue is addressed:
|
|
|
|
// https://github.com/Microsoft/language-server-protocol/issues/344
|
|
|
|
SymbolKind indexSymbolKindToSymbolKind(index::SymbolKind Kind) {
|
|
|
|
switch (Kind) {
|
|
|
|
case index::SymbolKind::Unknown:
|
|
|
|
return SymbolKind::Variable;
|
|
|
|
case index::SymbolKind::Module:
|
|
|
|
return SymbolKind::Module;
|
|
|
|
case index::SymbolKind::Namespace:
|
|
|
|
return SymbolKind::Namespace;
|
|
|
|
case index::SymbolKind::NamespaceAlias:
|
|
|
|
return SymbolKind::Namespace;
|
|
|
|
case index::SymbolKind::Macro:
|
|
|
|
return SymbolKind::String;
|
|
|
|
case index::SymbolKind::Enum:
|
|
|
|
return SymbolKind::Enum;
|
|
|
|
case index::SymbolKind::Struct:
|
|
|
|
return SymbolKind::Struct;
|
|
|
|
case index::SymbolKind::Class:
|
|
|
|
return SymbolKind::Class;
|
|
|
|
case index::SymbolKind::Protocol:
|
|
|
|
return SymbolKind::Interface;
|
|
|
|
case index::SymbolKind::Extension:
|
|
|
|
return SymbolKind::Interface;
|
|
|
|
case index::SymbolKind::Union:
|
|
|
|
return SymbolKind::Class;
|
|
|
|
case index::SymbolKind::TypeAlias:
|
|
|
|
return SymbolKind::Class;
|
|
|
|
case index::SymbolKind::Function:
|
|
|
|
return SymbolKind::Function;
|
|
|
|
case index::SymbolKind::Variable:
|
|
|
|
return SymbolKind::Variable;
|
|
|
|
case index::SymbolKind::Field:
|
|
|
|
return SymbolKind::Field;
|
|
|
|
case index::SymbolKind::EnumConstant:
|
|
|
|
return SymbolKind::EnumMember;
|
|
|
|
case index::SymbolKind::InstanceMethod:
|
|
|
|
case index::SymbolKind::ClassMethod:
|
|
|
|
case index::SymbolKind::StaticMethod:
|
|
|
|
return SymbolKind::Method;
|
|
|
|
case index::SymbolKind::InstanceProperty:
|
|
|
|
case index::SymbolKind::ClassProperty:
|
|
|
|
case index::SymbolKind::StaticProperty:
|
|
|
|
return SymbolKind::Property;
|
|
|
|
case index::SymbolKind::Constructor:
|
|
|
|
case index::SymbolKind::Destructor:
|
|
|
|
return SymbolKind::Method;
|
|
|
|
case index::SymbolKind::ConversionFunction:
|
|
|
|
return SymbolKind::Function;
|
|
|
|
case index::SymbolKind::Parameter:
|
|
|
|
return SymbolKind::Variable;
|
|
|
|
case index::SymbolKind::Using:
|
|
|
|
return SymbolKind::Namespace;
|
|
|
|
}
|
|
|
|
llvm_unreachable("invalid symbol kind");
|
|
|
|
}
|
|
|
|
|
2018-06-07 14:55:59 +08:00
|
|
|
using ScoredSymbolInfo = std::pair<float, SymbolInformation>;
|
|
|
|
struct ScoredSymbolGreater {
|
|
|
|
bool operator()(const ScoredSymbolInfo &L, const ScoredSymbolInfo &R) {
|
|
|
|
if (L.first != R.first)
|
|
|
|
return L.first > R.first;
|
|
|
|
return L.second.name < R.second.name; // Earlier name is better.
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
llvm::Expected<std::vector<SymbolInformation>>
|
2018-06-19 17:33:53 +08:00
|
|
|
getWorkspaceSymbols(StringRef Query, int Limit, const SymbolIndex *const Index,
|
|
|
|
StringRef HintPath) {
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
std::vector<SymbolInformation> Result;
|
|
|
|
if (Query.empty() || !Index)
|
|
|
|
return Result;
|
|
|
|
|
|
|
|
auto Names = splitQualifiedName(Query);
|
|
|
|
|
|
|
|
FuzzyFindRequest Req;
|
|
|
|
Req.Query = Names.second;
|
|
|
|
|
|
|
|
// FuzzyFind doesn't want leading :: qualifier
|
|
|
|
bool IsGlobalQuery = Names.first.consume_front("::");
|
|
|
|
// Restrict results to the scope in the query string if present (global or
|
|
|
|
// not).
|
|
|
|
if (IsGlobalQuery || !Names.first.empty())
|
|
|
|
Req.Scopes = {Names.first};
|
|
|
|
if (Limit)
|
|
|
|
Req.MaxCandidateCount = Limit;
|
2018-06-07 14:55:59 +08:00
|
|
|
TopN<ScoredSymbolInfo, ScoredSymbolGreater> Top(Req.MaxCandidateCount);
|
|
|
|
FuzzyMatcher Filter(Req.Query);
|
2018-06-19 17:33:53 +08:00
|
|
|
Index->fuzzyFind(Req, [HintPath, &Top, &Filter](const Symbol &Sym) {
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
// Prefer the definition over e.g. a function declaration in a header
|
|
|
|
auto &CD = Sym.Definition ? Sym.Definition : Sym.CanonicalDeclaration;
|
|
|
|
auto Uri = URI::parse(CD.FileURI);
|
|
|
|
if (!Uri) {
|
[clangd] Upgrade logging facilities with levels and formatv.
Summary:
log() is split into four functions:
- elog()/log()/vlog() have different severity levels, allowing filtering
- dlog() is a lazy macro which uses LLVM_DEBUG - it logs to the logger, but
conditionally based on -debug-only flag and is omitted in release builds
All logging functions use formatv-style format strings now, e.g:
log("Could not resolve URI {0}: {1}", URI, Result.takeError());
Existing log sites have been split between elog/log/vlog by best guess.
This includes a workaround for passing Error to formatv that can be
simplified when D49170 or similar lands.
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D49008
llvm-svn: 336785
2018-07-11 18:35:11 +08:00
|
|
|
log("Workspace symbol: Could not parse URI '{0}' for symbol '{1}'.",
|
|
|
|
CD.FileURI, Sym.Name);
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
return;
|
|
|
|
}
|
2018-06-19 17:33:53 +08:00
|
|
|
auto Path = URI::resolve(*Uri, HintPath);
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
if (!Path) {
|
[clangd] Upgrade logging facilities with levels and formatv.
Summary:
log() is split into four functions:
- elog()/log()/vlog() have different severity levels, allowing filtering
- dlog() is a lazy macro which uses LLVM_DEBUG - it logs to the logger, but
conditionally based on -debug-only flag and is omitted in release builds
All logging functions use formatv-style format strings now, e.g:
log("Could not resolve URI {0}: {1}", URI, Result.takeError());
Existing log sites have been split between elog/log/vlog by best guess.
This includes a workaround for passing Error to formatv that can be
simplified when D49170 or similar lands.
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D49008
llvm-svn: 336785
2018-07-11 18:35:11 +08:00
|
|
|
log("Workspace symbol: Could not resolve path for URI '{0}' for symbol "
|
|
|
|
"'{1}'.",
|
|
|
|
Uri->toString(), Sym.Name);
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
Location L;
|
|
|
|
L.uri = URIForFile((*Path));
|
|
|
|
Position Start, End;
|
|
|
|
Start.line = CD.Start.Line;
|
|
|
|
Start.character = CD.Start.Column;
|
|
|
|
End.line = CD.End.Line;
|
|
|
|
End.character = CD.End.Column;
|
|
|
|
L.range = {Start, End};
|
|
|
|
SymbolKind SK = indexSymbolKindToSymbolKind(Sym.SymInfo.Kind);
|
|
|
|
std::string Scope = Sym.Scope;
|
|
|
|
StringRef ScopeRef = Scope;
|
|
|
|
ScopeRef.consume_back("::");
|
2018-06-07 14:55:59 +08:00
|
|
|
SymbolInformation Info = {Sym.Name, SK, L, ScopeRef};
|
|
|
|
|
|
|
|
SymbolQualitySignals Quality;
|
|
|
|
Quality.merge(Sym);
|
|
|
|
SymbolRelevanceSignals Relevance;
|
|
|
|
Relevance.Query = SymbolRelevanceSignals::Generic;
|
|
|
|
if (auto NameMatch = Filter.match(Sym.Name))
|
|
|
|
Relevance.NameMatch = *NameMatch;
|
|
|
|
else {
|
[clangd] Upgrade logging facilities with levels and formatv.
Summary:
log() is split into four functions:
- elog()/log()/vlog() have different severity levels, allowing filtering
- dlog() is a lazy macro which uses LLVM_DEBUG - it logs to the logger, but
conditionally based on -debug-only flag and is omitted in release builds
All logging functions use formatv-style format strings now, e.g:
log("Could not resolve URI {0}: {1}", URI, Result.takeError());
Existing log sites have been split between elog/log/vlog by best guess.
This includes a workaround for passing Error to formatv that can be
simplified when D49170 or similar lands.
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D49008
llvm-svn: 336785
2018-07-11 18:35:11 +08:00
|
|
|
log("Workspace symbol: {0} didn't match query {1}", Sym.Name,
|
|
|
|
Filter.pattern());
|
2018-06-07 14:55:59 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
Relevance.merge(Sym);
|
|
|
|
auto Score =
|
|
|
|
evaluateSymbolAndRelevance(Quality.evaluate(), Relevance.evaluate());
|
[clangd] Upgrade logging facilities with levels and formatv.
Summary:
log() is split into four functions:
- elog()/log()/vlog() have different severity levels, allowing filtering
- dlog() is a lazy macro which uses LLVM_DEBUG - it logs to the logger, but
conditionally based on -debug-only flag and is omitted in release builds
All logging functions use formatv-style format strings now, e.g:
log("Could not resolve URI {0}: {1}", URI, Result.takeError());
Existing log sites have been split between elog/log/vlog by best guess.
This includes a workaround for passing Error to formatv that can be
simplified when D49170 or similar lands.
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D49008
llvm-svn: 336785
2018-07-11 18:35:11 +08:00
|
|
|
dlog("FindSymbols: {0}{1} = {2}\n{3}{4}\n", Sym.Scope, Sym.Name, Score,
|
|
|
|
Quality, Relevance);
|
2018-06-07 14:55:59 +08:00
|
|
|
|
|
|
|
Top.push({Score, std::move(Info)});
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
});
|
2018-06-07 14:55:59 +08:00
|
|
|
for (auto &R : std::move(Top).items())
|
|
|
|
Result.push_back(std::move(R.second));
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
2018-07-06 03:35:01 +08:00
|
|
|
namespace {
|
|
|
|
/// Finds document symbols in the main file of the AST.
|
|
|
|
class DocumentSymbolsConsumer : public index::IndexDataConsumer {
|
|
|
|
ASTContext &AST;
|
|
|
|
std::vector<SymbolInformation> Symbols;
|
|
|
|
// We are always list document for the same file, so cache the value.
|
|
|
|
llvm::Optional<URIForFile> MainFileUri;
|
|
|
|
|
|
|
|
public:
|
|
|
|
DocumentSymbolsConsumer(ASTContext &AST) : AST(AST) {}
|
|
|
|
std::vector<SymbolInformation> takeSymbols() { return std::move(Symbols); }
|
|
|
|
|
|
|
|
void initialize(ASTContext &Ctx) override {
|
|
|
|
// Compute the absolute path of the main file which we will use for all
|
|
|
|
// results.
|
|
|
|
const SourceManager &SM = AST.getSourceManager();
|
|
|
|
const FileEntry *F = SM.getFileEntryForID(SM.getMainFileID());
|
|
|
|
if (!F)
|
|
|
|
return;
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
auto FilePath = getRealPath(F, SM);
|
2018-07-06 03:35:01 +08:00
|
|
|
if (FilePath)
|
|
|
|
MainFileUri = URIForFile(*FilePath);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool shouldIncludeSymbol(const NamedDecl *ND) {
|
|
|
|
if (!ND || ND->isImplicit())
|
|
|
|
return false;
|
|
|
|
// Skip anonymous declarations, e.g (anonymous enum/class/struct).
|
|
|
|
if (ND->getDeclName().isEmpty())
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
handleDeclOccurence(const Decl *, index::SymbolRoleSet Roles,
|
|
|
|
ArrayRef<index::SymbolRelation> Relations,
|
|
|
|
SourceLocation Loc,
|
|
|
|
index::IndexDataConsumer::ASTNodeInfo ASTNode) override {
|
|
|
|
assert(ASTNode.OrigD);
|
|
|
|
// No point in continuing the index consumer if we could not get the
|
|
|
|
// absolute path of the main file.
|
|
|
|
if (!MainFileUri)
|
|
|
|
return false;
|
|
|
|
// We only want declarations and definitions, i.e. no references.
|
|
|
|
if (!(Roles & static_cast<unsigned>(index::SymbolRole::Declaration) ||
|
|
|
|
Roles & static_cast<unsigned>(index::SymbolRole::Definition)))
|
|
|
|
return true;
|
|
|
|
SourceLocation NameLoc = findNameLoc(ASTNode.OrigD);
|
|
|
|
const SourceManager &SourceMgr = AST.getSourceManager();
|
|
|
|
// We should be only be looking at "local" decls in the main file.
|
|
|
|
if (!SourceMgr.isWrittenInMainFile(NameLoc)) {
|
|
|
|
// Even thought we are visiting only local (non-preamble) decls,
|
2018-09-05 16:01:37 +08:00
|
|
|
// we can get here when in the presence of "extern" decls.
|
2018-07-06 03:35:01 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
const NamedDecl *ND = llvm::dyn_cast<NamedDecl>(ASTNode.OrigD);
|
|
|
|
if (!shouldIncludeSymbol(ND))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
SourceLocation EndLoc =
|
|
|
|
Lexer::getLocForEndOfToken(NameLoc, 0, SourceMgr, AST.getLangOpts());
|
|
|
|
Position Begin = sourceLocToPosition(SourceMgr, NameLoc);
|
|
|
|
Position End = sourceLocToPosition(SourceMgr, EndLoc);
|
|
|
|
Range R = {Begin, End};
|
|
|
|
Location L;
|
|
|
|
L.uri = *MainFileUri;
|
|
|
|
L.range = R;
|
|
|
|
|
|
|
|
std::string QName = printQualifiedName(*ND);
|
|
|
|
StringRef Scope, Name;
|
|
|
|
std::tie(Scope, Name) = splitQualifiedName(QName);
|
|
|
|
Scope.consume_back("::");
|
|
|
|
|
|
|
|
index::SymbolInfo SymInfo = index::getSymbolInfo(ND);
|
|
|
|
SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind);
|
|
|
|
|
|
|
|
SymbolInformation SI;
|
|
|
|
SI.name = Name;
|
|
|
|
SI.kind = SK;
|
|
|
|
SI.location = L;
|
|
|
|
SI.containerName = Scope;
|
|
|
|
Symbols.push_back(std::move(SI));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
llvm::Expected<std::vector<SymbolInformation>>
|
|
|
|
getDocumentSymbols(ParsedAST &AST) {
|
|
|
|
DocumentSymbolsConsumer DocumentSymbolsCons(AST.getASTContext());
|
|
|
|
|
|
|
|
index::IndexingOptions IndexOpts;
|
|
|
|
IndexOpts.SystemSymbolFilter =
|
|
|
|
index::IndexingOptions::SystemSymbolFilterKind::DeclarationsOnly;
|
|
|
|
IndexOpts.IndexFunctionLocals = false;
|
|
|
|
indexTopLevelDecls(AST.getASTContext(), AST.getLocalTopLevelDecls(),
|
|
|
|
DocumentSymbolsCons, IndexOpts);
|
|
|
|
|
|
|
|
return DocumentSymbolsCons.takeSymbols();
|
|
|
|
}
|
|
|
|
|
[clangd] Implementation of workspace/symbol request
Summary:
This is a basic implementation of the "workspace/symbol" request which is
used to find symbols by a string query. Since this is similar to code completion
in terms of result, this implementation reuses the "fuzzyFind" in order to get
matches. For now, the scoring algorithm is the same as code completion and
improvements could be done in the future.
The index model doesn't contain quite enough symbols for this to cover
common symbols like methods, enum class enumerators, functions in unamed
namespaces, etc. The index model will be augmented separately to achieve this.
Reviewers: sammccall, ilya-biryukov
Reviewed By: sammccall
Subscribers: jkorous, hokein, simark, sammccall, klimek, mgorny, ilya-biryukov, mgrang, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44882
llvm-svn: 330637
2018-04-24 04:00:52 +08:00
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|