[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"
|
|
|
|
|
|
|
|
#include "Logger.h"
|
2018-06-07 14:55:59 +08:00
|
|
|
#include "FuzzyMatch.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 "SourceCode.h"
|
2018-06-07 14:55:59 +08:00
|
|
|
#include "Quality.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"
|
|
|
|
#include "clang/Index/IndexSymbol.h"
|
|
|
|
#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) {
|
|
|
|
log(llvm::formatv(
|
|
|
|
"Workspace symbol: Could not parse URI '{0}' for symbol '{1}'.",
|
|
|
|
CD.FileURI, Sym.Name));
|
|
|
|
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) {
|
|
|
|
log(llvm::formatv("Workspace symbol: Could not resolve path for URI "
|
|
|
|
"'{0}' for symbol '{1}'.",
|
|
|
|
(*Uri).toString(), Sym.Name.str()));
|
|
|
|
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 {
|
|
|
|
log(llvm::formatv("Workspace symbol: {0} didn't match query {1}",
|
|
|
|
Sym.Name, Filter.pattern()));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Relevance.merge(Sym);
|
|
|
|
auto Score =
|
|
|
|
evaluateSymbolAndRelevance(Quality.evaluate(), Relevance.evaluate());
|
|
|
|
LLVM_DEBUG(llvm::dbgs() << "FindSymbols: " << Sym.Scope << Sym.Name << " = "
|
|
|
|
<< Score << "\n"
|
|
|
|
<< Quality << Relevance << "\n");
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|