mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-24 08:35:08 +00:00
textDocument/references workspace/symbol: add folders
For textDocument/reference, base/excludeRole/role has been lifted from params.context.* to params.*
This commit is contained in:
parent
26d76b75c7
commit
90a94cbb4f
@ -60,7 +60,7 @@ MAKE_REFLECT_STRUCT(DidChangeWatchedFilesParam::Event, uri, type);
|
||||
MAKE_REFLECT_STRUCT(DidChangeWatchedFilesParam, changes);
|
||||
MAKE_REFLECT_STRUCT(DidChangeWorkspaceFoldersParam::Event, added, removed);
|
||||
MAKE_REFLECT_STRUCT(DidChangeWorkspaceFoldersParam, event);
|
||||
MAKE_REFLECT_STRUCT(WorkspaceSymbolParam, query);
|
||||
MAKE_REFLECT_STRUCT(WorkspaceSymbolParam, query, folders);
|
||||
|
||||
namespace {
|
||||
struct CclsSemanticHighlightSymbol {
|
||||
|
@ -174,6 +174,9 @@ struct DidChangeWorkspaceFoldersParam {
|
||||
};
|
||||
struct WorkspaceSymbolParam {
|
||||
std::string query;
|
||||
|
||||
// ccls extensions
|
||||
std::vector<std::string> folders;
|
||||
};
|
||||
|
||||
// TODO llvm 8 llvm::unique_function
|
||||
|
@ -22,10 +22,10 @@ limitations under the License.
|
||||
|
||||
namespace ccls {
|
||||
namespace {
|
||||
std::vector<Use> GetNonDefDeclarationTargets(DB *db, SymbolRef sym) {
|
||||
std::vector<DeclRef> GetNonDefDeclarationTargets(DB *db, SymbolRef sym) {
|
||||
switch (sym.kind) {
|
||||
case SymbolKind::Var: {
|
||||
std::vector<Use> ret = GetNonDefDeclarations(db, sym);
|
||||
std::vector<DeclRef> ret = GetNonDefDeclarations(db, sym);
|
||||
// If there is no declaration, jump to its type.
|
||||
if (ret.empty()) {
|
||||
for (auto &def : db->GetVar(sym).def)
|
||||
|
@ -22,18 +22,23 @@ namespace ccls {
|
||||
namespace {
|
||||
struct ReferenceParam : public TextDocumentPositionParam {
|
||||
struct Context {
|
||||
bool base = true;
|
||||
// Exclude references with any |Role| bits set.
|
||||
Role excludeRole = Role::None;
|
||||
// Include the declaration of the current symbol.
|
||||
bool includeDeclaration = false;
|
||||
// Include references with all |Role| bits set.
|
||||
Role role = Role::None;
|
||||
} context;
|
||||
|
||||
// ccls extension
|
||||
// If not empty, restrict to specified folders.
|
||||
std::vector<std::string> folders;
|
||||
// For Type, also return references of base types.
|
||||
bool base = true;
|
||||
// Exclude references with any |Role| bits set.
|
||||
Role excludeRole = Role::None;
|
||||
// Include references with all |Role| bits set.
|
||||
Role role = Role::None;
|
||||
};
|
||||
MAKE_REFLECT_STRUCT(ReferenceParam::Context, base, excludeRole,
|
||||
includeDeclaration, role);
|
||||
MAKE_REFLECT_STRUCT(ReferenceParam, textDocument, position, context);
|
||||
MAKE_REFLECT_STRUCT(ReferenceParam::Context, includeDeclaration);
|
||||
MAKE_REFLECT_STRUCT(ReferenceParam, textDocument, position, context, folders,
|
||||
base, excludeRole, role);
|
||||
} // namespace
|
||||
|
||||
void MessageHandler::textDocument_references(Reader &reader, ReplyOnce &reply) {
|
||||
@ -42,10 +47,13 @@ void MessageHandler::textDocument_references(Reader &reader, ReplyOnce &reply) {
|
||||
QueryFile *file = FindFile(reply, param.textDocument.uri.GetPath());
|
||||
if (!file)
|
||||
return;
|
||||
std::vector<lsLocation> result;
|
||||
WorkingFile *wfile = wfiles->GetFileByFilename(file->def->path);
|
||||
if (!file)
|
||||
if (!wfile)
|
||||
return;
|
||||
for (auto &folder : param.folders)
|
||||
EnsureEndsInSlash(folder);
|
||||
std::vector<uint8_t> file_set = db->GetFileSet(param.folders);
|
||||
std::vector<lsLocation> result;
|
||||
|
||||
std::unordered_set<Use> seen_uses;
|
||||
int line = param.position.line;
|
||||
@ -56,24 +64,23 @@ void MessageHandler::textDocument_references(Reader &reader, ReplyOnce &reply) {
|
||||
seen.insert(sym.usr);
|
||||
std::vector<Usr> stack{sym.usr};
|
||||
if (sym.kind != SymbolKind::Func)
|
||||
param.context.base = false;
|
||||
param.base = false;
|
||||
while (stack.size()) {
|
||||
sym.usr = stack.back();
|
||||
stack.pop_back();
|
||||
auto fn = [&](Use use, lsSymbolKind parent_kind) {
|
||||
if (Role(use.role & param.context.role) == param.context.role &&
|
||||
!(use.role & param.context.excludeRole) &&
|
||||
seen_uses.insert(use).second)
|
||||
if (auto loc = GetLsLocation(db, wfiles, use)) {
|
||||
if (file_set[use.file_id] &&
|
||||
Role(use.role & param.role) == param.role &&
|
||||
!(use.role & param.excludeRole) && seen_uses.insert(use).second)
|
||||
if (auto loc = GetLsLocation(db, wfiles, use))
|
||||
result.push_back(*loc);
|
||||
}
|
||||
};
|
||||
WithEntity(db, sym, [&](const auto &entity) {
|
||||
lsSymbolKind parent_kind = lsSymbolKind::Unknown;
|
||||
for (auto &def : entity.def)
|
||||
if (def.spell) {
|
||||
parent_kind = GetSymbolKind(db, sym);
|
||||
if (param.context.base)
|
||||
if (param.base)
|
||||
for (Usr usr : def.GetBases())
|
||||
if (!seen.count(usr)) {
|
||||
seen.insert(usr);
|
||||
|
@ -22,6 +22,7 @@ limitations under the License.
|
||||
#include "query_utils.hh"
|
||||
|
||||
#include <llvm/ADT/STLExtras.h>
|
||||
#include <llvm/ADT/StringRef.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <ctype.h>
|
||||
@ -96,23 +97,35 @@ void MessageHandler::workspace_didChangeWorkspaceFolders(
|
||||
namespace {
|
||||
// Lookup |symbol| in |db| and insert the value into |result|.
|
||||
bool AddSymbol(
|
||||
DB *db, WorkingFiles *wfiles, SymbolIdx sym, bool use_detailed,
|
||||
DB *db, WorkingFiles *wfiles, const std::vector<uint8_t> &file_set,
|
||||
SymbolIdx sym, bool use_detailed,
|
||||
std::vector<std::tuple<lsSymbolInformation, int, SymbolIdx>> *result) {
|
||||
std::optional<lsSymbolInformation> info = GetSymbolInfo(db, sym, true);
|
||||
if (!info)
|
||||
return false;
|
||||
|
||||
Use loc;
|
||||
if (Maybe<DeclRef> dr = GetDefinitionSpell(db, sym))
|
||||
loc = *dr;
|
||||
else {
|
||||
auto decls = GetNonDefDeclarations(db, sym);
|
||||
if (decls.empty())
|
||||
return false;
|
||||
loc = decls[0];
|
||||
Maybe<DeclRef> dr;
|
||||
bool in_folder = false;
|
||||
WithEntity(db, sym, [&](const auto &entity) {
|
||||
for (auto &def : entity.def)
|
||||
if (def.spell) {
|
||||
dr = def.spell;
|
||||
if (!in_folder && (in_folder = file_set[def.spell->file_id]))
|
||||
break;
|
||||
}
|
||||
});
|
||||
if (!dr) {
|
||||
auto &decls = GetNonDefDeclarations(db, sym);
|
||||
for (auto &dr1 : decls) {
|
||||
dr = dr1;
|
||||
if (!in_folder && (in_folder = file_set[dr1.file_id]))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!in_folder)
|
||||
return false;
|
||||
|
||||
std::optional<lsLocation> ls_location = GetLsLocation(db, wfiles, loc);
|
||||
std::optional<lsLocation> ls_location = GetLsLocation(db, wfiles, *dr);
|
||||
if (!ls_location)
|
||||
return false;
|
||||
info->location = *ls_location;
|
||||
@ -124,7 +137,10 @@ bool AddSymbol(
|
||||
void MessageHandler::workspace_symbol(WorkspaceSymbolParam ¶m,
|
||||
ReplyOnce &reply) {
|
||||
std::vector<lsSymbolInformation> result;
|
||||
std::string query = param.query;
|
||||
const std::string &query = param.query;
|
||||
for (auto &folder : param.folders)
|
||||
EnsureEndsInSlash(folder);
|
||||
std::vector<uint8_t> file_set = db->GetFileSet(param.folders);
|
||||
|
||||
// {symbol info, matching detailed_name or short_name, index}
|
||||
std::vector<std::tuple<lsSymbolInformation, int, SymbolIdx>> cands;
|
||||
@ -141,7 +157,7 @@ void MessageHandler::workspace_symbol(WorkspaceSymbolParam ¶m,
|
||||
std::string_view detailed_name = db->GetSymbolName(sym, true);
|
||||
int pos = ReverseSubseqMatch(query_without_space, detailed_name, sensitive);
|
||||
return pos >= 0 &&
|
||||
AddSymbol(db, wfiles, sym,
|
||||
AddSymbol(db, wfiles, file_set, sym,
|
||||
detailed_name.find(':', pos) != std::string::npos,
|
||||
&cands) &&
|
||||
cands.size() >= g_config->workspaceSymbol.maxNum;
|
||||
|
18
src/query.cc
18
src/query.cc
@ -468,4 +468,22 @@ std::string_view DB::GetSymbolName(SymbolIdx sym, bool qualified) {
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::vector<uint8_t> DB::GetFileSet(const std::vector<std::string> &folders) {
|
||||
if (folders.empty())
|
||||
return std::vector<uint8_t>(files.size(), 1);
|
||||
std::vector<uint8_t> file_set(files.size());
|
||||
for (QueryFile &file : files)
|
||||
if (file.def) {
|
||||
bool ok = false;
|
||||
for (auto &folder : folders)
|
||||
if (llvm::StringRef(file.def->path).startswith(folder)) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
if (ok)
|
||||
file_set[file.id] = 1;
|
||||
}
|
||||
return file_set;
|
||||
}
|
||||
} // namespace ccls
|
||||
|
@ -181,6 +181,7 @@ struct DB {
|
||||
void Update(const Lid2file_id &, int file_id,
|
||||
std::vector<std::pair<Usr, QueryVar::Def>> &&us);
|
||||
std::string_view GetSymbolName(SymbolIdx sym, bool qualified);
|
||||
std::vector<uint8_t> GetFileSet(const std::vector<std::string> &folders);
|
||||
|
||||
bool HasFunc(Usr usr) const { return func_usr.count(usr); }
|
||||
bool HasType(Usr usr) const { return type_usr.count(usr); }
|
||||
|
@ -95,25 +95,19 @@ std::vector<Use> GetVarDeclarations(DB *db, const std::vector<Usr> &usrs,
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Use> GetNonDefDeclarations(DB *db, SymbolIdx sym) {
|
||||
std::vector<Use> ret;
|
||||
std::vector<DeclRef> &GetNonDefDeclarations(DB *db, SymbolIdx sym) {
|
||||
static std::vector<DeclRef> empty;
|
||||
switch (sym.kind) {
|
||||
case SymbolKind::Func:
|
||||
for (auto &d : db->GetFunc(sym).declarations)
|
||||
ret.push_back(d);
|
||||
break;
|
||||
return db->GetFunc(sym).declarations;
|
||||
case SymbolKind::Type:
|
||||
for (auto &d : db->GetType(sym).declarations)
|
||||
ret.push_back(d);
|
||||
break;
|
||||
return db->GetType(sym).declarations;
|
||||
case SymbolKind::Var:
|
||||
for (auto &d : db->GetVar(sym).declarations)
|
||||
ret.push_back(d);
|
||||
break;
|
||||
return db->GetVar(sym).declarations;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return empty;
|
||||
}
|
||||
|
||||
std::vector<Use> GetUsesForAllBases(DB *db, QueryFunc &root) {
|
||||
|
@ -30,7 +30,7 @@ std::vector<Use> GetTypeDeclarations(DB *, const std::vector<Usr> &);
|
||||
std::vector<Use> GetVarDeclarations(DB *, const std::vector<Usr> &, unsigned);
|
||||
|
||||
// Get non-defining declarations.
|
||||
std::vector<Use> GetNonDefDeclarations(DB *db, SymbolIdx sym);
|
||||
std::vector<DeclRef> &GetNonDefDeclarations(DB *db, SymbolIdx sym);
|
||||
|
||||
std::vector<Use> GetUsesForAllBases(DB *db, QueryFunc &root);
|
||||
std::vector<Use> GetUsesForAllDerived(DB *db, QueryFunc &root);
|
||||
|
Loading…
Reference in New Issue
Block a user