From 65ba98c3f8b414b4bc51900e7c654e0049e8aff9 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 20 Feb 2018 15:40:31 -0800 Subject: [PATCH] Add Config::maxXrefResults and improve textDocument/definition -std=c++11 => -std=c++14 for generic lambda --- src/config.h | 3 ++ src/messages/cquery_base.cc | 6 +-- src/messages/cquery_callers.cc | 3 +- src/messages/cquery_derived.cc | 8 ++-- src/messages/cquery_vars.cc | 3 +- src/messages/text_document_definition.cc | 58 +++++++++--------------- src/query_utils.cc | 10 ++-- src/query_utils.h | 27 ++++++++++- wscript | 2 +- 9 files changed, 68 insertions(+), 52 deletions(-) diff --git a/src/config.h b/src/config.h index 996a3bf2..ef5aa50a 100644 --- a/src/config.h +++ b/src/config.h @@ -162,6 +162,8 @@ struct Config { }; Completion completion; + // Maximum number of definition/reference/... results. + int maxXrefResults = 500; struct Extension { // If true, reference results will include "containerName". bool referenceContainer = false; @@ -231,6 +233,7 @@ MAKE_REFLECT_STRUCT(Config, client, completion, + maxXrefResults, extension, index, diff --git a/src/messages/cquery_base.cc b/src/messages/cquery_base.cc index 226999cc..2022d1a8 100644 --- a/src/messages/cquery_base.cc +++ b/src/messages/cquery_base.cc @@ -28,12 +28,12 @@ struct CqueryBaseHandler : BaseMessageHandler { if (sym.kind == SymbolKind::Type) { if (const auto* def = db->GetType(sym).AnyDef()) out.result = GetLsLocations(db, working_files, - ToUses(db, def->parents)); + ToUses(db, def->parents), config->maxXrefResults); break; } else if (sym.kind == SymbolKind::Func) { if (const auto* def = db->GetFunc(sym).AnyDef()) - out.result = GetLsLocations(db, working_files, - ToUses(db, def->base)); + out.result = GetLsLocations(db, working_files, ToUses(db, def->base), + config->maxXrefResults); break; } } diff --git a/src/messages/cquery_callers.cc b/src/messages/cquery_callers.cc index 8be078d1..a0dd2edf 100644 --- a/src/messages/cquery_callers.cc +++ b/src/messages/cquery_callers.cc @@ -32,7 +32,8 @@ struct CqueryCallersHandler : BaseMessageHandler { uses.push_back(func_ref); for (Use func_ref : GetCallersForAllDerivedFunctions(db, func)) uses.push_back(func_ref); - out.result = GetLsLocations(db, working_files, uses); + out.result = GetLsLocations(db, working_files, uses, config->maxXrefResults); + break; } } QueueManager::WriteStdout(IpcId::CqueryCallers, out); diff --git a/src/messages/cquery_derived.cc b/src/messages/cquery_derived.cc index be4e3945..f6f1a1d0 100644 --- a/src/messages/cquery_derived.cc +++ b/src/messages/cquery_derived.cc @@ -27,13 +27,13 @@ struct CqueryDerivedHandler : BaseMessageHandler { FindSymbolsAtLocation(working_file, file, request->params.position)) { if (sym.kind == SymbolKind::Type) { QueryType& type = db->GetType(sym); - out.result = - GetLsLocations(db, working_files, ToUses(db, type.derived)); + out.result = GetLsLocations(db, working_files, ToUses(db, type.derived), + config->maxXrefResults); break; } else if (sym.kind == SymbolKind::Func) { QueryFunc& func = db->GetFunc(sym); - out.result = - GetLsLocations(db, working_files, ToUses(db, func.derived)); + out.result = GetLsLocations(db, working_files, ToUses(db, func.derived), + config->maxXrefResults); break; } } diff --git a/src/messages/cquery_vars.cc b/src/messages/cquery_vars.cc index 68fab4c5..544d3890 100644 --- a/src/messages/cquery_vars.cc +++ b/src/messages/cquery_vars.cc @@ -39,7 +39,8 @@ struct CqueryVarsHandler : BaseMessageHandler { case SymbolKind::Type: { QueryType& type = db->types[id.id]; out.result = - GetLsLocations(db, working_files, ToUses(db, type.instances)); + GetLsLocations(db, working_files, ToUses(db, type.instances), + config->maxXrefResults); break; } } diff --git a/src/messages/text_document_definition.cc b/src/messages/text_document_definition.cc index 38f6b46a..6773f0c9 100644 --- a/src/messages/text_document_definition.cc +++ b/src/messages/text_document_definition.cc @@ -9,10 +9,6 @@ #include namespace { -void PushBack(std::vector* result, optional location) { - if (location) - result->push_back(*location); -} struct Ipc_TextDocumentDefinition : public RequestMessage { @@ -84,41 +80,29 @@ struct TextDocumentDefinitionHandler // - symbol has declaration but no definition (ie, pure virtual) // - start at spelling but end at extent for better mouse tooltip // - goto declaration while in definition of recursive type - - Maybe def_loc = GetDefinitionSpellingOfSymbol(db, sym); - - // We use spelling start and extent end because this causes vscode to - // highlight the entire definition when previewing / hoving with the - // mouse. - Maybe extent = GetDefinitionExtentOfSymbol(db, sym); - if (def_loc && extent) - def_loc->range.end = extent->range.end; - - // If the cursor is currently at or in the definition we should goto - // the declaration if possible. We also want to use declarations if - // we're pointing to, ie, a pure virtual function which has no - // definition. - if (!def_loc || (def_loc->file == file_id && - def_loc->range.Contains(target_line, target_column))) { - // Goto declaration. - - std::vector targets = GetGotoDefinitionTargets(db, sym); - for (Use target : targets) { - optional ls_target = - GetLsLocation(db, working_files, target); - if (ls_target) - out.result.push_back(*ls_target); + std::vector uses; + EachDef(db, sym, [&](const auto& def) { + if (def.spell && def.extent) { + Use spell = *def.spell; + // If on a definition, clear |uses| to find declarations below. + if (spell.file == file_id && + spell.range.Contains(target_line, target_column)) { + uses.clear(); + return false; + } + // We use spelling start and extent end because this causes vscode + // to highlight the entire definition when previewing / hoving with + // the mouse. + spell.range.end = def.extent->range.end; + uses.push_back(spell); } - // We found some declarations. Break so we don't add the definition - // location. - if (!out.result.empty()) - break; - } - - if (def_loc) { - PushBack(&out.result, GetLsLocation(db, working_files, *def_loc)); - } + return true; + }); + if (uses.empty()) + uses = GetGotoDefinitionTargets(db, sym); + AddRange(&out.result, + GetLsLocations(db, working_files, uses, config->maxXrefResults)); if (!out.result.empty()) break; } diff --git a/src/query_utils.cc b/src/query_utils.cc index 8c0c2c0d..f0719992 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -403,10 +403,10 @@ optional GetLsLocationEx(QueryDatabase* db, return ret; } -std::vector GetLsLocations( - QueryDatabase* db, - WorkingFiles* working_files, - const std::vector& uses) { +std::vector GetLsLocations(QueryDatabase* db, + WorkingFiles* working_files, + const std::vector& uses, + int limit) { std::vector ret; for (Use use : uses) { optional location = @@ -416,6 +416,8 @@ std::vector GetLsLocations( } std::sort(ret.begin(), ret.end()); ret.erase(std::unique(ret.begin(), ret.end()), ret.end()); + if (ret.size() > limit) + ret.resize(limit); return ret; } diff --git a/src/query_utils.h b/src/query_utils.h index 8f437cff..132093fe 100644 --- a/src/query_utils.h +++ b/src/query_utils.h @@ -47,7 +47,8 @@ optional GetLsLocationEx(QueryDatabase* db, bool extension); std::vector GetLsLocations(QueryDatabase* db, WorkingFiles* working_files, - const std::vector& refs); + const std::vector& refs, + int limit); // Returns a symbol. The symbol will have *NOT* have a location assigned. optional GetSymbolInfo(QueryDatabase* db, WorkingFiles* working_files, @@ -62,6 +63,30 @@ void EmitDiagnostics(WorkingFiles* working_files, std::string path, std::vector diagnostics); +template +void EachDef(QueryDatabase* db, SymbolIdx sym, Fn fn) { + switch (sym.kind) { + case SymbolKind::Invalid: + case SymbolKind::File: + break; + case SymbolKind::Func: + for (auto& def : db->GetFunc(sym).def) + if (!fn(def)) + break; + break; + case SymbolKind::Type: + for (auto& def : db->GetType(sym).def) + if (!fn(def)) + break; + break; + case SymbolKind::Var: + for (auto& def : db->GetVar(sym).def) + if (!fn(def)) + break; + break; + } +} + template void EachWithGen(std::vector& collection, Id x, Fn fn) { Q& obj = collection[x.id]; diff --git a/wscript b/wscript index 8c80eb0a..8eb0a1cf 100644 --- a/wscript +++ b/wscript @@ -174,7 +174,7 @@ def configure(ctx): cxxflags.append('-Wno-unused-result') if all(not x.startswith('-std=') for x in ctx.env.CXXFLAGS): - cxxflags.append('-std=c++11') + cxxflags.append('-std=c++14') if ctx.options.use_clang_cxx: # include/clang/Format/Format.h error: multi-line comment