[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++-*------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
[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 "FindSymbols.h"
|
|
|
|
|
2018-07-06 03:35:01 +08:00
|
|
|
#include "AST.h"
|
2018-06-07 14:55:59 +08:00
|
|
|
#include "FuzzyMatch.h"
|
2019-09-04 17:46:06 +08:00
|
|
|
#include "ParsedAST.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"
|
[clangd] Move non-clang base pieces into separate support/ lib. NFCI
Summary:
This enforces layering, reduces a sprawling clangd/ directory, and makes life
easier for embedders.
Reviewers: kbobyrev
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79014
2020-04-28 23:49:17 +08:00
|
|
|
#include "support/Logger.h"
|
2018-11-23 23:21:19 +08:00
|
|
|
#include "clang/AST/DeclTemplate.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"
|
2020-10-05 17:52:58 +08:00
|
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/ADT/SmallVector.h"
|
[clangd] Add a textual fallback for go-to-definition
Summary:
This facilitates performing go-to-definition in contexts where AST-based
resolution does not work, such as comments, string literals, preprocessor
disabled regions, and macro definitions, based on textual lookup in the index.
Partially fixes https://github.com/clangd/clangd/issues/241
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D72874
2020-03-06 05:47:32 +08:00
|
|
|
#include "llvm/ADT/StringRef.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-11-23 23:21:19 +08:00
|
|
|
#include "llvm/Support/ScopedPrinter.h"
|
2020-10-05 17:52:58 +08:00
|
|
|
#include <tuple>
|
[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
|
|
|
#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 {
|
|
|
|
|
[clangd] Add support for type hierarchy (super types only for now)
Summary:
Patch by Nathan Ridge(@nridge)!
This is an LSP extension proposed here:
https://github.com/Microsoft/vscode-languageserver-node/pull/426
An example client implementation can be found here:
https://github.com/theia-ide/theia/pull/3802
Reviewers: kadircet, sammccall
Reviewed By: kadircet
Subscribers: jdoerfert, sammccall, cfe-commits, mgorny, dschaefer, simark, ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, kadircet
Tags: #clang
Differential Revision: https://reviews.llvm.org/D56370
llvm-svn: 356445
2019-03-19 17:27:04 +08:00
|
|
|
namespace {
|
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.
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-10-05 17:52:58 +08:00
|
|
|
// Returns true if \p Query can be found as a sub-sequence inside \p Scope.
|
|
|
|
bool approximateScopeMatch(llvm::StringRef Scope, llvm::StringRef Query) {
|
|
|
|
assert(Scope.empty() || Scope.endswith("::"));
|
|
|
|
assert(Query.empty() || Query.endswith("::"));
|
|
|
|
while (!Scope.empty() && !Query.empty()) {
|
|
|
|
auto Colons = Scope.find("::");
|
|
|
|
assert(Colons != llvm::StringRef::npos);
|
|
|
|
|
|
|
|
llvm::StringRef LeadingSpecifier = Scope.slice(0, Colons + 2);
|
|
|
|
Scope = Scope.slice(Colons + 2, llvm::StringRef::npos);
|
|
|
|
Query.consume_front(LeadingSpecifier);
|
|
|
|
}
|
|
|
|
return Query.empty();
|
|
|
|
}
|
|
|
|
|
[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] Add a textual fallback for go-to-definition
Summary:
This facilitates performing go-to-definition in contexts where AST-based
resolution does not work, such as comments, string literals, preprocessor
disabled regions, and macro definitions, based on textual lookup in the index.
Partially fixes https://github.com/clangd/clangd/issues/241
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D72874
2020-03-06 05:47:32 +08:00
|
|
|
llvm::Expected<Location> indexToLSPLocation(const SymbolLocation &Loc,
|
|
|
|
llvm::StringRef TUPath) {
|
|
|
|
auto Path = URI::resolve(Loc.FileURI, TUPath);
|
2020-09-14 17:33:12 +08:00
|
|
|
if (!Path)
|
|
|
|
return error("Could not resolve path for file '{0}': {1}", Loc.FileURI,
|
|
|
|
Path.takeError());
|
[clangd] Type hierarchy subtypes
Summary:
This builds on the relations support added in D59407, D62459, D62471,
and D62839 to implement type hierarchy subtypes.
Reviewers: kadircet
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, mgrang, arphaman,
jdoerfert, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D58880
llvm-svn: 363506
2019-06-16 10:31:37 +08:00
|
|
|
Location L;
|
[clangd] Add a textual fallback for go-to-definition
Summary:
This facilitates performing go-to-definition in contexts where AST-based
resolution does not work, such as comments, string literals, preprocessor
disabled regions, and macro definitions, based on textual lookup in the index.
Partially fixes https://github.com/clangd/clangd/issues/241
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D72874
2020-03-06 05:47:32 +08:00
|
|
|
L.uri = URIForFile::canonicalize(*Path, TUPath);
|
[clangd] Type hierarchy subtypes
Summary:
This builds on the relations support added in D59407, D62459, D62471,
and D62839 to implement type hierarchy subtypes.
Reviewers: kadircet
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, mgrang, arphaman,
jdoerfert, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D58880
llvm-svn: 363506
2019-06-16 10:31:37 +08:00
|
|
|
Position Start, End;
|
[clangd] Add a textual fallback for go-to-definition
Summary:
This facilitates performing go-to-definition in contexts where AST-based
resolution does not work, such as comments, string literals, preprocessor
disabled regions, and macro definitions, based on textual lookup in the index.
Partially fixes https://github.com/clangd/clangd/issues/241
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D72874
2020-03-06 05:47:32 +08:00
|
|
|
Start.line = Loc.Start.line();
|
|
|
|
Start.character = Loc.Start.column();
|
|
|
|
End.line = Loc.End.line();
|
|
|
|
End.character = Loc.End.column();
|
[clangd] Type hierarchy subtypes
Summary:
This builds on the relations support added in D59407, D62459, D62471,
and D62839 to implement type hierarchy subtypes.
Reviewers: kadircet
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, mgrang, arphaman,
jdoerfert, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D58880
llvm-svn: 363506
2019-06-16 10:31:37 +08:00
|
|
|
L.range = {Start, End};
|
|
|
|
return L;
|
|
|
|
}
|
|
|
|
|
[clangd] Add a textual fallback for go-to-definition
Summary:
This facilitates performing go-to-definition in contexts where AST-based
resolution does not work, such as comments, string literals, preprocessor
disabled regions, and macro definitions, based on textual lookup in the index.
Partially fixes https://github.com/clangd/clangd/issues/241
Reviewers: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D72874
2020-03-06 05:47:32 +08:00
|
|
|
llvm::Expected<Location> symbolToLocation(const Symbol &Sym,
|
|
|
|
llvm::StringRef TUPath) {
|
|
|
|
// Prefer the definition over e.g. a function declaration in a header
|
|
|
|
return indexToLSPLocation(
|
|
|
|
Sym.Definition ? Sym.Definition : Sym.CanonicalDeclaration, TUPath);
|
|
|
|
}
|
|
|
|
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Expected<std::vector<SymbolInformation>>
|
|
|
|
getWorkspaceSymbols(llvm::StringRef Query, int Limit,
|
|
|
|
const SymbolIndex *const Index, llvm::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;
|
|
|
|
|
2020-10-05 17:52:58 +08:00
|
|
|
// Lookup for qualified names are performed as:
|
|
|
|
// - Exact namespaces are boosted by the index.
|
|
|
|
// - Approximate matches are (sub-scope match) included via AnyScope logic.
|
|
|
|
// - Non-matching namespaces (no sub-scope match) are post-filtered.
|
[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
|
|
|
auto Names = splitQualifiedName(Query);
|
|
|
|
|
|
|
|
FuzzyFindRequest Req;
|
2020-01-29 03:23:46 +08:00
|
|
|
Req.Query = std::string(Names.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
|
|
|
|
2020-10-05 17:52:58 +08:00
|
|
|
// FuzzyFind doesn't want leading :: qualifier.
|
|
|
|
auto HasLeadingColons = Names.first.consume_front("::");
|
|
|
|
// Limit the query to specific namespace if it is fully-qualified.
|
|
|
|
Req.AnyScope = !HasLeadingColons;
|
|
|
|
// Boost symbols from desired namespace.
|
|
|
|
if (HasLeadingColons || !Names.first.empty())
|
2020-01-29 03:23:46 +08:00
|
|
|
Req.Scopes = {std::string(Names.first)};
|
2020-10-05 17:52:58 +08:00
|
|
|
if (Limit) {
|
2018-09-13 22:27:03 +08:00
|
|
|
Req.Limit = Limit;
|
2020-10-05 17:52:58 +08:00
|
|
|
// If we are boosting a specific scope allow more results to be retrieved,
|
|
|
|
// since some symbols from preferred namespaces might not make the cut.
|
|
|
|
if (Req.AnyScope && !Req.Scopes.empty())
|
|
|
|
*Req.Limit *= 5;
|
|
|
|
}
|
2018-09-13 22:27:03 +08:00
|
|
|
TopN<ScoredSymbolInfo, ScoredSymbolGreater> Top(
|
|
|
|
Req.Limit ? *Req.Limit : std::numeric_limits<size_t>::max());
|
2018-06-07 14:55:59 +08:00
|
|
|
FuzzyMatcher Filter(Req.Query);
|
2020-10-05 17:52:58 +08:00
|
|
|
|
|
|
|
Index->fuzzyFind(Req, [HintPath, &Top, &Filter, AnyScope = Req.AnyScope,
|
|
|
|
ReqScope = Names.first](const Symbol &Sym) {
|
|
|
|
llvm::StringRef Scope = Sym.Scope;
|
|
|
|
// Fuzzyfind might return symbols from irrelevant namespaces if query was
|
|
|
|
// not fully-qualified, drop those.
|
|
|
|
if (AnyScope && !approximateScopeMatch(Scope, ReqScope))
|
|
|
|
return;
|
|
|
|
|
[clangd] Type hierarchy subtypes
Summary:
This builds on the relations support added in D59407, D62459, D62471,
and D62839 to implement type hierarchy subtypes.
Reviewers: kadircet
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, mgrang, arphaman,
jdoerfert, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D58880
llvm-svn: 363506
2019-06-16 10:31:37 +08:00
|
|
|
auto Loc = symbolToLocation(Sym, HintPath);
|
|
|
|
if (!Loc) {
|
|
|
|
log("Workspace symbols: {0}", Loc.takeError());
|
[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;
|
|
|
|
}
|
[clangd] Type hierarchy subtypes
Summary:
This builds on the relations support added in D59407, D62459, D62471,
and D62839 to implement type hierarchy subtypes.
Reviewers: kadircet
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, mgrang, arphaman,
jdoerfert, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D58880
llvm-svn: 363506
2019-06-16 10:31:37 +08:00
|
|
|
|
2018-06-07 14:55:59 +08:00
|
|
|
SymbolQualitySignals Quality;
|
|
|
|
Quality.merge(Sym);
|
|
|
|
SymbolRelevanceSignals Relevance;
|
2019-05-06 18:25:10 +08:00
|
|
|
Relevance.Name = Sym.Name;
|
2018-06-07 14:55:59 +08:00
|
|
|
Relevance.Query = SymbolRelevanceSignals::Generic;
|
2020-10-05 17:52:58 +08:00
|
|
|
// If symbol and request scopes do not match exactly, apply a penalty.
|
|
|
|
Relevance.InBaseClass = AnyScope && Scope != ReqScope;
|
2018-06-07 14:55:59 +08:00
|
|
|
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);
|
2020-09-29 01:19:51 +08:00
|
|
|
auto Score = evaluateSymbolAndRelevance(Quality.evaluateHeuristics(),
|
|
|
|
Relevance.evaluateHeuristics());
|
[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
|
|
|
|
2020-10-05 17:52:58 +08:00
|
|
|
SymbolInformation Info;
|
|
|
|
Info.name = (Sym.Name + Sym.TemplateSpecializationArgs).str();
|
|
|
|
Info.kind = indexSymbolKindToSymbolKind(Sym.SymInfo.Kind);
|
|
|
|
Info.location = *Loc;
|
|
|
|
Scope.consume_back("::");
|
|
|
|
Info.containerName = Scope.str();
|
|
|
|
|
2020-10-06 03:41:35 +08:00
|
|
|
// Exposed score excludes fuzzy-match component, for client-side re-ranking.
|
|
|
|
Info.score = Score / Relevance.NameMatch;
|
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 {
|
2018-11-23 23:21:19 +08:00
|
|
|
llvm::Optional<DocumentSymbol> declToSym(ASTContext &Ctx, const NamedDecl &ND) {
|
|
|
|
auto &SM = Ctx.getSourceManager();
|
2018-07-06 03:35:01 +08:00
|
|
|
|
2019-01-03 21:28:05 +08:00
|
|
|
SourceLocation BeginLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getBeginLoc()));
|
2018-11-23 23:21:19 +08:00
|
|
|
SourceLocation EndLoc = SM.getSpellingLoc(SM.getFileLoc(ND.getEndLoc()));
|
2020-07-13 21:02:47 +08:00
|
|
|
const auto SymbolRange =
|
|
|
|
toHalfOpenFileRange(SM, Ctx.getLangOpts(), {BeginLoc, EndLoc});
|
|
|
|
if (!SymbolRange)
|
2018-11-23 23:21:19 +08:00
|
|
|
return llvm::None;
|
|
|
|
|
|
|
|
index::SymbolInfo SymInfo = index::getSymbolInfo(&ND);
|
2020-10-26 22:31:29 +08:00
|
|
|
// FIXME: This is not classifying constructors, destructors and operators
|
|
|
|
// correctly.
|
2018-11-23 23:21:19 +08:00
|
|
|
SymbolKind SK = indexSymbolKindToSymbolKind(SymInfo.Kind);
|
|
|
|
|
|
|
|
DocumentSymbol SI;
|
|
|
|
SI.name = printName(Ctx, ND);
|
|
|
|
SI.kind = SK;
|
|
|
|
SI.deprecated = ND.isDeprecated();
|
2020-07-13 21:02:47 +08:00
|
|
|
SI.range = Range{sourceLocToPosition(SM, SymbolRange->getBegin()),
|
|
|
|
sourceLocToPosition(SM, SymbolRange->getEnd())};
|
2020-09-22 14:30:21 +08:00
|
|
|
|
|
|
|
SourceLocation NameLoc = ND.getLocation();
|
|
|
|
SourceLocation FallbackNameLoc;
|
|
|
|
if (NameLoc.isMacroID()) {
|
|
|
|
if (isSpelledInSource(NameLoc, SM)) {
|
|
|
|
// Prefer the spelling loc, but save the expansion loc as a fallback.
|
|
|
|
FallbackNameLoc = SM.getExpansionLoc(NameLoc);
|
|
|
|
NameLoc = SM.getSpellingLoc(NameLoc);
|
|
|
|
} else {
|
|
|
|
NameLoc = SM.getExpansionLoc(NameLoc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
auto ComputeSelectionRange = [&](SourceLocation L) -> Range {
|
|
|
|
Position NameBegin = sourceLocToPosition(SM, L);
|
|
|
|
Position NameEnd = sourceLocToPosition(
|
|
|
|
SM, Lexer::getLocForEndOfToken(L, 0, SM, Ctx.getLangOpts()));
|
|
|
|
return Range{NameBegin, NameEnd};
|
|
|
|
};
|
|
|
|
|
|
|
|
SI.selectionRange = ComputeSelectionRange(NameLoc);
|
|
|
|
if (!SI.range.contains(SI.selectionRange) && FallbackNameLoc.isValid()) {
|
|
|
|
// 'selectionRange' must be contained in 'range'. In cases where clang
|
|
|
|
// reports unrelated ranges, we first try falling back to the expansion
|
|
|
|
// loc for the selection range.
|
|
|
|
SI.selectionRange = ComputeSelectionRange(FallbackNameLoc);
|
|
|
|
}
|
2018-11-23 23:21:19 +08:00
|
|
|
if (!SI.range.contains(SI.selectionRange)) {
|
2020-09-22 14:30:21 +08:00
|
|
|
// If the containment relationship still doesn't hold, throw away
|
|
|
|
// 'range' and use 'selectionRange' for both.
|
2018-11-23 23:21:19 +08:00
|
|
|
SI.range = SI.selectionRange;
|
2018-07-06 03:35:01 +08:00
|
|
|
}
|
2018-11-23 23:21:19 +08:00
|
|
|
return SI;
|
|
|
|
}
|
2018-07-06 03:35:01 +08:00
|
|
|
|
2019-08-14 18:49:32 +08:00
|
|
|
/// A helper class to build an outline for the parse AST. It traverses the AST
|
2018-11-23 23:21:19 +08:00
|
|
|
/// directly instead of using RecursiveASTVisitor (RAV) for three main reasons:
|
2019-08-14 18:49:32 +08:00
|
|
|
/// - there is no way to keep RAV from traversing subtrees we are not
|
2018-11-23 23:21:19 +08:00
|
|
|
/// interested in. E.g. not traversing function locals or implicit template
|
|
|
|
/// instantiations.
|
2019-08-14 18:49:32 +08:00
|
|
|
/// - it's easier to combine results of recursive passes,
|
2018-11-23 23:21:19 +08:00
|
|
|
/// - visiting decls is actually simple, so we don't hit the complicated
|
2019-08-14 18:49:32 +08:00
|
|
|
/// cases that RAV mostly helps with (types, expressions, etc.)
|
2018-11-23 23:21:19 +08:00
|
|
|
class DocumentOutline {
|
|
|
|
public:
|
|
|
|
DocumentOutline(ParsedAST &AST) : AST(AST) {}
|
|
|
|
|
|
|
|
/// Builds the document outline for the generated AST.
|
|
|
|
std::vector<DocumentSymbol> build() {
|
|
|
|
std::vector<DocumentSymbol> Results;
|
|
|
|
for (auto &TopLevel : AST.getLocalTopLevelDecls())
|
|
|
|
traverseDecl(TopLevel, Results);
|
|
|
|
return Results;
|
2018-07-06 03:35:01 +08:00
|
|
|
}
|
|
|
|
|
2018-11-23 23:21:19 +08:00
|
|
|
private:
|
2020-08-03 17:34:14 +08:00
|
|
|
enum class VisitKind { No, OnlyDecl, OnlyChildren, DeclAndChildren };
|
2018-07-06 03:35:01 +08:00
|
|
|
|
2018-11-23 23:21:19 +08:00
|
|
|
void traverseDecl(Decl *D, std::vector<DocumentSymbol> &Results) {
|
2020-01-21 02:02:48 +08:00
|
|
|
if (auto *Templ = llvm::dyn_cast<TemplateDecl>(D)) {
|
|
|
|
// TemplatedDecl might be null, e.g. concepts.
|
|
|
|
if (auto *TD = Templ->getTemplatedDecl())
|
|
|
|
D = TD;
|
|
|
|
}
|
2020-08-03 17:34:14 +08:00
|
|
|
|
|
|
|
VisitKind Visit = shouldVisit(D);
|
2018-11-23 23:21:19 +08:00
|
|
|
if (Visit == VisitKind::No)
|
|
|
|
return;
|
2020-08-03 17:34:14 +08:00
|
|
|
|
|
|
|
if (Visit == VisitKind::OnlyChildren)
|
|
|
|
return traverseChildren(D, Results);
|
|
|
|
|
|
|
|
auto *ND = llvm::cast<NamedDecl>(D);
|
|
|
|
auto Sym = declToSym(AST.getASTContext(), *ND);
|
2018-11-23 23:21:19 +08:00
|
|
|
if (!Sym)
|
|
|
|
return;
|
|
|
|
Results.push_back(std::move(*Sym));
|
2020-08-03 17:34:14 +08:00
|
|
|
|
|
|
|
if (Visit == VisitKind::OnlyDecl)
|
|
|
|
return;
|
|
|
|
|
|
|
|
assert(Visit == VisitKind::DeclAndChildren && "Unexpected VisitKind");
|
|
|
|
traverseChildren(ND, Results.back().children);
|
2018-11-23 23:21:19 +08:00
|
|
|
}
|
2018-07-06 03:35:01 +08:00
|
|
|
|
2018-11-23 23:21:19 +08:00
|
|
|
void traverseChildren(Decl *D, std::vector<DocumentSymbol> &Results) {
|
|
|
|
auto *Scope = llvm::dyn_cast<DeclContext>(D);
|
|
|
|
if (!Scope)
|
|
|
|
return;
|
|
|
|
for (auto *C : Scope->decls())
|
|
|
|
traverseDecl(C, Results);
|
|
|
|
}
|
2018-07-06 03:35:01 +08:00
|
|
|
|
2020-08-03 17:34:14 +08:00
|
|
|
VisitKind shouldVisit(Decl *D) {
|
2018-11-23 23:21:19 +08:00
|
|
|
if (D->isImplicit())
|
|
|
|
return VisitKind::No;
|
2018-07-06 03:35:01 +08:00
|
|
|
|
2020-08-03 17:34:14 +08:00
|
|
|
if (llvm::isa<LinkageSpecDecl>(D) || llvm::isa<ExportDecl>(D))
|
|
|
|
return VisitKind::OnlyChildren;
|
|
|
|
|
|
|
|
if (!llvm::isa<NamedDecl>(D))
|
|
|
|
return VisitKind::No;
|
|
|
|
|
2018-11-23 23:21:19 +08:00
|
|
|
if (auto Func = llvm::dyn_cast<FunctionDecl>(D)) {
|
|
|
|
// Some functions are implicit template instantiations, those should be
|
|
|
|
// ignored.
|
|
|
|
if (auto *Info = Func->getTemplateSpecializationInfo()) {
|
|
|
|
if (!Info->isExplicitInstantiationOrSpecialization())
|
|
|
|
return VisitKind::No;
|
|
|
|
}
|
|
|
|
// Only visit the function itself, do not visit the children (i.e.
|
|
|
|
// function parameters, etc.)
|
|
|
|
return VisitKind::OnlyDecl;
|
|
|
|
}
|
|
|
|
// Handle template instantiations. We have three cases to consider:
|
|
|
|
// - explicit instantiations, e.g. 'template class std::vector<int>;'
|
|
|
|
// Visit the decl itself (it's present in the code), but not the
|
|
|
|
// children.
|
|
|
|
// - implicit instantiations, i.e. not written by the user.
|
|
|
|
// Do not visit at all, they are not present in the code.
|
|
|
|
// - explicit specialization, e.g. 'template <> class vector<bool> {};'
|
|
|
|
// Visit both the decl and its children, both are written in the code.
|
|
|
|
if (auto *TemplSpec = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D)) {
|
|
|
|
if (TemplSpec->isExplicitInstantiationOrSpecialization())
|
|
|
|
return TemplSpec->isExplicitSpecialization()
|
|
|
|
? VisitKind::DeclAndChildren
|
|
|
|
: VisitKind::OnlyDecl;
|
|
|
|
return VisitKind::No;
|
|
|
|
}
|
|
|
|
if (auto *TemplSpec = llvm::dyn_cast<VarTemplateSpecializationDecl>(D)) {
|
|
|
|
if (TemplSpec->isExplicitInstantiationOrSpecialization())
|
|
|
|
return TemplSpec->isExplicitSpecialization()
|
|
|
|
? VisitKind::DeclAndChildren
|
|
|
|
: VisitKind::OnlyDecl;
|
|
|
|
return VisitKind::No;
|
|
|
|
}
|
|
|
|
// For all other cases, visit both the children and the decl.
|
|
|
|
return VisitKind::DeclAndChildren;
|
2018-07-06 03:35:01 +08:00
|
|
|
}
|
|
|
|
|
2018-11-23 23:21:19 +08:00
|
|
|
ParsedAST &AST;
|
|
|
|
};
|
2018-07-06 03:35:01 +08:00
|
|
|
|
2018-11-23 23:21:19 +08:00
|
|
|
std::vector<DocumentSymbol> collectDocSymbols(ParsedAST &AST) {
|
|
|
|
return DocumentOutline(AST).build();
|
|
|
|
}
|
|
|
|
} // namespace
|
2018-07-06 03:35:01 +08:00
|
|
|
|
2018-11-23 23:21:19 +08:00
|
|
|
llvm::Expected<std::vector<DocumentSymbol>> getDocumentSymbols(ParsedAST &AST) {
|
|
|
|
return collectDocSymbols(AST);
|
2018-07-06 03:35:01 +08:00
|
|
|
}
|
|
|
|
|
[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
|