mirror of
https://github.com/MaskRay/ccls.git
synced 2025-02-22 00:19:28 +00:00
Improve finding definition/declaration and work around #463
This commit is contained in:
parent
84b2187d2a
commit
9f3e0ce0dc
@ -488,10 +488,11 @@ struct TextDocumentCodeActionHandler
|
||||
include_insert_strings.insert(item->textEdit->newText);
|
||||
else if (!item->insertText.empty())
|
||||
include_insert_strings.insert(item->insertText);
|
||||
else
|
||||
assert(false &&
|
||||
"unable to determine insert string for include "
|
||||
"completion item");
|
||||
else {
|
||||
// FIXME https://github.com/cquery-project/cquery/issues/463
|
||||
LOG_S(WARNING) << "unable to determine insert string for include "
|
||||
"completion item";
|
||||
}
|
||||
}
|
||||
|
||||
// Build code action.
|
||||
|
@ -135,25 +135,28 @@ struct TextDocumentDefinitionHandler
|
||||
lsPosition position = request->params.position;
|
||||
const std::string& buffer = working_file->buffer_content;
|
||||
std::string query = LexWordAroundPos(position, buffer);
|
||||
bool has_scope = query.find(':') != std::string::npos;
|
||||
|
||||
// For symbols whose detailed names contain |query| as a substring,
|
||||
// we use the tuple <length difference, not in the same file, line
|
||||
// distance> to find the best match.
|
||||
std::tuple<int, bool, int> best_score{INT_MAX, true, 0};
|
||||
// For symbols whose short/detailed names contain |query| as a
|
||||
// substring, we use the tuple <length difference, matching position,
|
||||
// not in the same file, line distance> to find the best match.
|
||||
std::tuple<int, int, bool, int> best_score{INT_MAX, 0, true, 0};
|
||||
int best_i = -1;
|
||||
for (int i = 0; i < (int)db->symbols.size(); ++i) {
|
||||
if (db->symbols[i].kind == SymbolKind::Invalid)
|
||||
continue;
|
||||
std::string_view detailed_name = db->GetSymbolDetailedName(i);
|
||||
auto idx = detailed_name.find(query);
|
||||
if (idx == std::string::npos)
|
||||
|
||||
std::string_view name = has_scope ? db->GetSymbolDetailedName(i)
|
||||
: db->GetSymbolShortName(i);
|
||||
auto pos = name.find(query);
|
||||
if (pos == std::string::npos)
|
||||
continue;
|
||||
Maybe<Use> use = GetDefinitionSpellingOfSymbol(db, db->symbols[i]);
|
||||
if (!use)
|
||||
continue;
|
||||
|
||||
std::tuple<int, bool, int> score{
|
||||
int(detailed_name.size() - query.size()), use->file != file_id,
|
||||
std::tuple<int, int, bool, int> score{
|
||||
int(name.size() - query.size()), int(pos), use->file != file_id,
|
||||
std::abs(use->range.start.line - position.line)};
|
||||
if (score < best_score) {
|
||||
best_score = score;
|
||||
|
@ -24,19 +24,21 @@ Maybe<Use> GetDefinitionSpellingOfSymbol(QueryDatabase* db,
|
||||
case SymbolKind::File:
|
||||
break;
|
||||
case SymbolKind::Func: {
|
||||
if (const auto* def = db->GetFunc(sym).AnyDef())
|
||||
return def->spell;
|
||||
for (auto& def : db->GetFunc(sym).def)
|
||||
if (def.spell)
|
||||
return def.spell;
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Type: {
|
||||
if (const auto* def = db->GetType(sym).AnyDef())
|
||||
return def->spell;
|
||||
for (auto& def : db->GetType(sym).def)
|
||||
if (def.spell)
|
||||
return def.spell;
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Var: {
|
||||
const QueryVar::Def* def = db->GetVar(sym).AnyDef();
|
||||
if (def)
|
||||
return def->spell;
|
||||
for (auto& def : db->GetVar(sym).def)
|
||||
if (def.spell)
|
||||
return def.spell;
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Invalid:
|
||||
@ -52,19 +54,21 @@ Maybe<Use> GetDefinitionExtentOfSymbol(QueryDatabase* db, SymbolIdx sym) {
|
||||
return Use(Range(Position(0, 0), Position(0, 0)), sym.id, sym.kind,
|
||||
Role::None, QueryFileId(sym.id));
|
||||
case SymbolKind::Func: {
|
||||
if (const auto* def = db->GetFunc(sym).AnyDef())
|
||||
return def->extent;
|
||||
for (auto& def : db->GetFunc(sym).def)
|
||||
if (def.extent)
|
||||
return def.extent;
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Type: {
|
||||
if (const auto* def = db->GetType(sym).AnyDef())
|
||||
return def->extent;
|
||||
for (auto& def : db->GetType(sym).def)
|
||||
if (def.extent)
|
||||
return def.extent;
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Var: {
|
||||
const QueryVar::Def* def = db->GetVar(sym).AnyDef();
|
||||
if (def)
|
||||
return def->extent;
|
||||
for (auto& def : db->GetVar(sym).def)
|
||||
if (def.extent)
|
||||
return def.extent;
|
||||
break;
|
||||
}
|
||||
case SymbolKind::Invalid: {
|
||||
@ -112,10 +116,14 @@ std::vector<Use> ToUses(QueryDatabase* db,
|
||||
ret.reserve(ids.size());
|
||||
for (auto id : ids) {
|
||||
QueryFunc& func = db->funcs[id.id];
|
||||
const QueryFunc::Def* def = func.AnyDef();
|
||||
if (def && def->spell)
|
||||
ret.push_back(*def->spell);
|
||||
else if (func.declarations.size())
|
||||
bool has_def = false;
|
||||
for (auto& def : func.def)
|
||||
if (def.spell) {
|
||||
ret.push_back(*def.spell);
|
||||
has_def = true;
|
||||
break;
|
||||
}
|
||||
if (!has_def && func.declarations.size())
|
||||
ret.push_back(func.declarations[0]);
|
||||
}
|
||||
return ret;
|
||||
@ -127,9 +135,11 @@ std::vector<Use> ToUses(QueryDatabase* db,
|
||||
ret.reserve(ids.size());
|
||||
for (auto id : ids) {
|
||||
QueryType& type = db->types[id.id];
|
||||
const QueryType::Def* def = type.AnyDef();
|
||||
if (def && def->spell)
|
||||
ret.push_back(*def->spell);
|
||||
for (auto& def : type.def)
|
||||
if (def.spell) {
|
||||
ret.push_back(*def.spell);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -139,10 +149,14 @@ std::vector<Use> ToUses(QueryDatabase* db, const std::vector<QueryVarId>& ids) {
|
||||
ret.reserve(ids.size());
|
||||
for (auto id : ids) {
|
||||
QueryVar& var = db->vars[id.id];
|
||||
const QueryVar::Def* def = var.AnyDef();
|
||||
if (def && def->spell)
|
||||
ret.push_back(*def->spell);
|
||||
else if (var.declarations.size())
|
||||
bool has_def = false;
|
||||
for (auto& def : var.def)
|
||||
if (def.spell) {
|
||||
ret.push_back(*def.spell);
|
||||
has_def = true;
|
||||
break;
|
||||
}
|
||||
if (!has_def && var.declarations.size())
|
||||
ret.push_back(var.declarations[0]);
|
||||
}
|
||||
return ret;
|
||||
@ -156,9 +170,9 @@ std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
|
||||
QueryType& type = db->GetType(sym);
|
||||
std::vector<Use> ret = type.uses;
|
||||
if (include_decl) {
|
||||
const QueryType::Def* def = type.AnyDef();
|
||||
if (def && def->spell)
|
||||
ret.push_back(*def->spell);
|
||||
for (auto& def : type.def)
|
||||
if (def.spell)
|
||||
ret.push_back(*def.spell);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -166,9 +180,9 @@ std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
|
||||
QueryFunc& func = db->GetFunc(sym);
|
||||
std::vector<Use> ret = func.uses;
|
||||
if (include_decl) {
|
||||
const QueryFunc::Def* def = func.AnyDef();
|
||||
if (def && def->spell)
|
||||
ret.push_back(*def->spell);
|
||||
for (auto& def : func.def)
|
||||
if (def.spell)
|
||||
ret.push_back(*def.spell);
|
||||
AddRange(&ret, func.declarations);
|
||||
}
|
||||
return ret;
|
||||
@ -177,9 +191,9 @@ std::vector<Use> GetUsesOfSymbol(QueryDatabase* db,
|
||||
QueryVar& var = db->GetVar(sym);
|
||||
std::vector<Use> ret = var.uses;
|
||||
if (include_decl) {
|
||||
const QueryVar::Def* def = var.AnyDef();
|
||||
if (def && def->spell)
|
||||
ret.push_back(*def->spell);
|
||||
for (auto& def : var.def)
|
||||
if (def.spell)
|
||||
ret.push_back(*def.spell);
|
||||
ret.insert(ret.end(), var.declarations.begin(), var.declarations.end());
|
||||
}
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user