From 9f3e0ce0dcc4bb7f4ffdb20334ffa99b486c64e2 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 20 Feb 2018 12:43:02 -0800 Subject: [PATCH] Improve finding definition/declaration and work around #463 --- src/messages/text_document_code_action.cc | 9 +-- src/messages/text_document_definition.cc | 21 +++--- src/query_utils.cc | 82 +++++++++++++---------- 3 files changed, 65 insertions(+), 47 deletions(-) diff --git a/src/messages/text_document_code_action.cc b/src/messages/text_document_code_action.cc index a9d597ae..ee01a377 100644 --- a/src/messages/text_document_code_action.cc +++ b/src/messages/text_document_code_action.cc @@ -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. diff --git a/src/messages/text_document_definition.cc b/src/messages/text_document_definition.cc index b46e590f..eafedccd 100644 --- a/src/messages/text_document_definition.cc +++ b/src/messages/text_document_definition.cc @@ -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 to find the best match. - std::tuple best_score{INT_MAX, true, 0}; + // For symbols whose short/detailed names contain |query| as a + // substring, we use the tuple to find the best match. + std::tuple 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 = GetDefinitionSpellingOfSymbol(db, db->symbols[i]); if (!use) continue; - std::tuple score{ - int(detailed_name.size() - query.size()), use->file != file_id, + std::tuple 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; diff --git a/src/query_utils.cc b/src/query_utils.cc index 0e86215d..592a4ec3 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -24,19 +24,21 @@ Maybe 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 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 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 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 ToUses(QueryDatabase* db, const std::vector& 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 GetUsesOfSymbol(QueryDatabase* db, QueryType& type = db->GetType(sym); std::vector 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 GetUsesOfSymbol(QueryDatabase* db, QueryFunc& func = db->GetFunc(sym); std::vector 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 GetUsesOfSymbol(QueryDatabase* db, QueryVar& var = db->GetVar(sym); std::vector 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;