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