Improve finding definition/declaration and work around #463

This commit is contained in:
Fangrui Song 2018-02-20 12:43:02 -08:00
parent 84b2187d2a
commit 9f3e0ce0dc
3 changed files with 65 additions and 47 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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;