mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-25 00:55: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
c4bf9c5d6a
commit
c8e57ee7b3
@ -48,7 +48,7 @@ MAKE_REFLECT_STRUCT(DidChangeWatchedFilesParam::Event, uri, type);
|
|||||||
MAKE_REFLECT_STRUCT(DidChangeWatchedFilesParam, changes);
|
MAKE_REFLECT_STRUCT(DidChangeWatchedFilesParam, changes);
|
||||||
MAKE_REFLECT_STRUCT(DidChangeWorkspaceFoldersParam::Event, added, removed);
|
MAKE_REFLECT_STRUCT(DidChangeWorkspaceFoldersParam::Event, added, removed);
|
||||||
MAKE_REFLECT_STRUCT(DidChangeWorkspaceFoldersParam, event);
|
MAKE_REFLECT_STRUCT(DidChangeWorkspaceFoldersParam, event);
|
||||||
MAKE_REFLECT_STRUCT(WorkspaceSymbolParam, query);
|
MAKE_REFLECT_STRUCT(WorkspaceSymbolParam, query, folders);
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct CclsSemanticHighlightSymbol {
|
struct CclsSemanticHighlightSymbol {
|
||||||
|
@ -162,6 +162,9 @@ struct DidChangeWorkspaceFoldersParam {
|
|||||||
};
|
};
|
||||||
struct WorkspaceSymbolParam {
|
struct WorkspaceSymbolParam {
|
||||||
std::string query;
|
std::string query;
|
||||||
|
|
||||||
|
// ccls extensions
|
||||||
|
std::vector<std::string> folders;
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO llvm 8 llvm::unique_function
|
// TODO llvm 8 llvm::unique_function
|
||||||
|
@ -10,10 +10,10 @@
|
|||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
namespace {
|
namespace {
|
||||||
std::vector<Use> GetNonDefDeclarationTargets(DB *db, SymbolRef sym) {
|
std::vector<DeclRef> GetNonDefDeclarationTargets(DB *db, SymbolRef sym) {
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Var: {
|
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 there is no declaration, jump to its type.
|
||||||
if (ret.empty()) {
|
if (ret.empty()) {
|
||||||
for (auto &def : db->GetVar(sym).def)
|
for (auto &def : db->GetVar(sym).def)
|
||||||
|
@ -10,18 +10,23 @@ namespace ccls {
|
|||||||
namespace {
|
namespace {
|
||||||
struct ReferenceParam : public TextDocumentPositionParam {
|
struct ReferenceParam : public TextDocumentPositionParam {
|
||||||
struct Context {
|
struct Context {
|
||||||
bool base = true;
|
|
||||||
// Exclude references with any |Role| bits set.
|
|
||||||
Role excludeRole = Role::None;
|
|
||||||
// Include the declaration of the current symbol.
|
// Include the declaration of the current symbol.
|
||||||
bool includeDeclaration = false;
|
bool includeDeclaration = false;
|
||||||
// Include references with all |Role| bits set.
|
|
||||||
Role role = Role::None;
|
|
||||||
} context;
|
} 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,
|
MAKE_REFLECT_STRUCT(ReferenceParam::Context, includeDeclaration);
|
||||||
includeDeclaration, role);
|
MAKE_REFLECT_STRUCT(ReferenceParam, textDocument, position, context, folders,
|
||||||
MAKE_REFLECT_STRUCT(ReferenceParam, textDocument, position, context);
|
base, excludeRole, role);
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void MessageHandler::textDocument_references(Reader &reader, ReplyOnce &reply) {
|
void MessageHandler::textDocument_references(Reader &reader, ReplyOnce &reply) {
|
||||||
@ -30,10 +35,13 @@ void MessageHandler::textDocument_references(Reader &reader, ReplyOnce &reply) {
|
|||||||
QueryFile *file = FindFile(reply, param.textDocument.uri.GetPath());
|
QueryFile *file = FindFile(reply, param.textDocument.uri.GetPath());
|
||||||
if (!file)
|
if (!file)
|
||||||
return;
|
return;
|
||||||
std::vector<lsLocation> result;
|
|
||||||
WorkingFile *wfile = wfiles->GetFileByFilename(file->def->path);
|
WorkingFile *wfile = wfiles->GetFileByFilename(file->def->path);
|
||||||
if (!file)
|
if (!wfile)
|
||||||
return;
|
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;
|
std::unordered_set<Use> seen_uses;
|
||||||
int line = param.position.line;
|
int line = param.position.line;
|
||||||
@ -44,24 +52,23 @@ void MessageHandler::textDocument_references(Reader &reader, ReplyOnce &reply) {
|
|||||||
seen.insert(sym.usr);
|
seen.insert(sym.usr);
|
||||||
std::vector<Usr> stack{sym.usr};
|
std::vector<Usr> stack{sym.usr};
|
||||||
if (sym.kind != SymbolKind::Func)
|
if (sym.kind != SymbolKind::Func)
|
||||||
param.context.base = false;
|
param.base = false;
|
||||||
while (stack.size()) {
|
while (stack.size()) {
|
||||||
sym.usr = stack.back();
|
sym.usr = stack.back();
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
auto fn = [&](Use use, lsSymbolKind parent_kind) {
|
auto fn = [&](Use use, lsSymbolKind parent_kind) {
|
||||||
if (Role(use.role & param.context.role) == param.context.role &&
|
if (file_set[use.file_id] &&
|
||||||
!(use.role & param.context.excludeRole) &&
|
Role(use.role & param.role) == param.role &&
|
||||||
seen_uses.insert(use).second)
|
!(use.role & param.excludeRole) && seen_uses.insert(use).second)
|
||||||
if (auto loc = GetLsLocation(db, wfiles, use)) {
|
if (auto loc = GetLsLocation(db, wfiles, use))
|
||||||
result.push_back(*loc);
|
result.push_back(*loc);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
WithEntity(db, sym, [&](const auto &entity) {
|
WithEntity(db, sym, [&](const auto &entity) {
|
||||||
lsSymbolKind parent_kind = lsSymbolKind::Unknown;
|
lsSymbolKind parent_kind = lsSymbolKind::Unknown;
|
||||||
for (auto &def : entity.def)
|
for (auto &def : entity.def)
|
||||||
if (def.spell) {
|
if (def.spell) {
|
||||||
parent_kind = GetSymbolKind(db, sym);
|
parent_kind = GetSymbolKind(db, sym);
|
||||||
if (param.context.base)
|
if (param.base)
|
||||||
for (Usr usr : def.GetBases())
|
for (Usr usr : def.GetBases())
|
||||||
if (!seen.count(usr)) {
|
if (!seen.count(usr)) {
|
||||||
seen.insert(usr);
|
seen.insert(usr);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "query_utils.hh"
|
#include "query_utils.hh"
|
||||||
|
|
||||||
#include <llvm/ADT/STLExtras.h>
|
#include <llvm/ADT/STLExtras.h>
|
||||||
|
#include <llvm/ADT/StringRef.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -84,23 +85,35 @@ void MessageHandler::workspace_didChangeWorkspaceFolders(
|
|||||||
namespace {
|
namespace {
|
||||||
// Lookup |symbol| in |db| and insert the value into |result|.
|
// Lookup |symbol| in |db| and insert the value into |result|.
|
||||||
bool AddSymbol(
|
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::vector<std::tuple<lsSymbolInformation, int, SymbolIdx>> *result) {
|
||||||
std::optional<lsSymbolInformation> info = GetSymbolInfo(db, sym, true);
|
std::optional<lsSymbolInformation> info = GetSymbolInfo(db, sym, true);
|
||||||
if (!info)
|
if (!info)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Use loc;
|
Maybe<DeclRef> dr;
|
||||||
if (Maybe<DeclRef> dr = GetDefinitionSpell(db, sym))
|
bool in_folder = false;
|
||||||
loc = *dr;
|
WithEntity(db, sym, [&](const auto &entity) {
|
||||||
else {
|
for (auto &def : entity.def)
|
||||||
auto decls = GetNonDefDeclarations(db, sym);
|
if (def.spell) {
|
||||||
if (decls.empty())
|
dr = def.spell;
|
||||||
return false;
|
if (!in_folder && (in_folder = file_set[def.spell->file_id]))
|
||||||
loc = decls[0];
|
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)
|
if (!ls_location)
|
||||||
return false;
|
return false;
|
||||||
info->location = *ls_location;
|
info->location = *ls_location;
|
||||||
@ -112,7 +125,10 @@ bool AddSymbol(
|
|||||||
void MessageHandler::workspace_symbol(WorkspaceSymbolParam ¶m,
|
void MessageHandler::workspace_symbol(WorkspaceSymbolParam ¶m,
|
||||||
ReplyOnce &reply) {
|
ReplyOnce &reply) {
|
||||||
std::vector<lsSymbolInformation> result;
|
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}
|
// {symbol info, matching detailed_name or short_name, index}
|
||||||
std::vector<std::tuple<lsSymbolInformation, int, SymbolIdx>> cands;
|
std::vector<std::tuple<lsSymbolInformation, int, SymbolIdx>> cands;
|
||||||
@ -129,7 +145,7 @@ void MessageHandler::workspace_symbol(WorkspaceSymbolParam ¶m,
|
|||||||
std::string_view detailed_name = db->GetSymbolName(sym, true);
|
std::string_view detailed_name = db->GetSymbolName(sym, true);
|
||||||
int pos = ReverseSubseqMatch(query_without_space, detailed_name, sensitive);
|
int pos = ReverseSubseqMatch(query_without_space, detailed_name, sensitive);
|
||||||
return pos >= 0 &&
|
return pos >= 0 &&
|
||||||
AddSymbol(db, wfiles, sym,
|
AddSymbol(db, wfiles, file_set, sym,
|
||||||
detailed_name.find(':', pos) != std::string::npos,
|
detailed_name.find(':', pos) != std::string::npos,
|
||||||
&cands) &&
|
&cands) &&
|
||||||
cands.size() >= g_config->workspaceSymbol.maxNum;
|
cands.size() >= g_config->workspaceSymbol.maxNum;
|
||||||
|
18
src/query.cc
18
src/query.cc
@ -456,4 +456,22 @@ std::string_view DB::GetSymbolName(SymbolIdx sym, bool qualified) {
|
|||||||
}
|
}
|
||||||
return "";
|
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
|
} // namespace ccls
|
||||||
|
@ -170,6 +170,7 @@ struct DB {
|
|||||||
void Update(const Lid2file_id &, int file_id,
|
void Update(const Lid2file_id &, int file_id,
|
||||||
std::vector<std::pair<Usr, QueryVar::Def>> &&us);
|
std::vector<std::pair<Usr, QueryVar::Def>> &&us);
|
||||||
std::string_view GetSymbolName(SymbolIdx sym, bool qualified);
|
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 HasFunc(Usr usr) const { return func_usr.count(usr); }
|
||||||
bool HasType(Usr usr) const { return type_usr.count(usr); }
|
bool HasType(Usr usr) const { return type_usr.count(usr); }
|
||||||
|
@ -83,25 +83,19 @@ std::vector<Use> GetVarDeclarations(DB *db, const std::vector<Usr> &usrs,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Use> GetNonDefDeclarations(DB *db, SymbolIdx sym) {
|
std::vector<DeclRef> &GetNonDefDeclarations(DB *db, SymbolIdx sym) {
|
||||||
std::vector<Use> ret;
|
static std::vector<DeclRef> empty;
|
||||||
switch (sym.kind) {
|
switch (sym.kind) {
|
||||||
case SymbolKind::Func:
|
case SymbolKind::Func:
|
||||||
for (auto &d : db->GetFunc(sym).declarations)
|
return db->GetFunc(sym).declarations;
|
||||||
ret.push_back(d);
|
|
||||||
break;
|
|
||||||
case SymbolKind::Type:
|
case SymbolKind::Type:
|
||||||
for (auto &d : db->GetType(sym).declarations)
|
return db->GetType(sym).declarations;
|
||||||
ret.push_back(d);
|
|
||||||
break;
|
|
||||||
case SymbolKind::Var:
|
case SymbolKind::Var:
|
||||||
for (auto &d : db->GetVar(sym).declarations)
|
return db->GetVar(sym).declarations;
|
||||||
ret.push_back(d);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return ret;
|
return empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Use> GetUsesForAllBases(DB *db, QueryFunc &root) {
|
std::vector<Use> GetUsesForAllBases(DB *db, QueryFunc &root) {
|
||||||
|
@ -18,7 +18,7 @@ std::vector<Use> GetTypeDeclarations(DB *, const std::vector<Usr> &);
|
|||||||
std::vector<Use> GetVarDeclarations(DB *, const std::vector<Usr> &, unsigned);
|
std::vector<Use> GetVarDeclarations(DB *, const std::vector<Usr> &, unsigned);
|
||||||
|
|
||||||
// Get non-defining declarations.
|
// 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> GetUsesForAllBases(DB *db, QueryFunc &root);
|
||||||
std::vector<Use> GetUsesForAllDerived(DB *db, QueryFunc &root);
|
std::vector<Use> GetUsesForAllDerived(DB *db, QueryFunc &root);
|
||||||
|
Loading…
Reference in New Issue
Block a user