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);
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.

View File

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

View File

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