Add Config::maxXrefResults and improve textDocument/definition

-std=c++11 => -std=c++14 for generic lambda
This commit is contained in:
Fangrui Song 2018-02-20 15:40:31 -08:00
parent 40ab5900de
commit 65ba98c3f8
9 changed files with 68 additions and 52 deletions

View File

@ -162,6 +162,8 @@ struct Config {
}; };
Completion completion; Completion completion;
// Maximum number of definition/reference/... results.
int maxXrefResults = 500;
struct Extension { struct Extension {
// If true, reference results will include "containerName". // If true, reference results will include "containerName".
bool referenceContainer = false; bool referenceContainer = false;
@ -231,6 +233,7 @@ MAKE_REFLECT_STRUCT(Config,
client, client,
completion, completion,
maxXrefResults,
extension, extension,
index, index,

View File

@ -28,12 +28,12 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> {
if (sym.kind == SymbolKind::Type) { if (sym.kind == SymbolKind::Type) {
if (const auto* def = db->GetType(sym).AnyDef()) if (const auto* def = db->GetType(sym).AnyDef())
out.result = GetLsLocations(db, working_files, out.result = GetLsLocations(db, working_files,
ToUses(db, def->parents)); ToUses(db, def->parents), config->maxXrefResults);
break; break;
} else if (sym.kind == SymbolKind::Func) { } else if (sym.kind == SymbolKind::Func) {
if (const auto* def = db->GetFunc(sym).AnyDef()) if (const auto* def = db->GetFunc(sym).AnyDef())
out.result = GetLsLocations(db, working_files, out.result = GetLsLocations(db, working_files, ToUses(db, def->base),
ToUses(db, def->base)); config->maxXrefResults);
break; break;
} }
} }

View File

@ -32,7 +32,8 @@ struct CqueryCallersHandler : BaseMessageHandler<Ipc_CqueryCallers> {
uses.push_back(func_ref); uses.push_back(func_ref);
for (Use func_ref : GetCallersForAllDerivedFunctions(db, func)) for (Use func_ref : GetCallersForAllDerivedFunctions(db, func))
uses.push_back(func_ref); 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); QueueManager::WriteStdout(IpcId::CqueryCallers, out);

View File

@ -27,13 +27,13 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> {
FindSymbolsAtLocation(working_file, file, request->params.position)) { FindSymbolsAtLocation(working_file, file, request->params.position)) {
if (sym.kind == SymbolKind::Type) { if (sym.kind == SymbolKind::Type) {
QueryType& type = db->GetType(sym); QueryType& type = db->GetType(sym);
out.result = out.result = GetLsLocations(db, working_files, ToUses(db, type.derived),
GetLsLocations(db, working_files, ToUses(db, type.derived)); config->maxXrefResults);
break; break;
} else if (sym.kind == SymbolKind::Func) { } else if (sym.kind == SymbolKind::Func) {
QueryFunc& func = db->GetFunc(sym); QueryFunc& func = db->GetFunc(sym);
out.result = out.result = GetLsLocations(db, working_files, ToUses(db, func.derived),
GetLsLocations(db, working_files, ToUses(db, func.derived)); config->maxXrefResults);
break; break;
} }
} }

View File

@ -39,7 +39,8 @@ struct CqueryVarsHandler : BaseMessageHandler<Ipc_CqueryVars> {
case SymbolKind::Type: { case SymbolKind::Type: {
QueryType& type = db->types[id.id]; QueryType& type = db->types[id.id];
out.result = out.result =
GetLsLocations(db, working_files, ToUses(db, type.instances)); GetLsLocations(db, working_files, ToUses(db, type.instances),
config->maxXrefResults);
break; break;
} }
} }

View File

@ -9,10 +9,6 @@
#include <cstdlib> #include <cstdlib>
namespace { namespace {
void PushBack(std::vector<lsLocation>* result, optional<lsLocation> location) {
if (location)
result->push_back(*location);
}
struct Ipc_TextDocumentDefinition struct Ipc_TextDocumentDefinition
: public RequestMessage<Ipc_TextDocumentDefinition> { : public RequestMessage<Ipc_TextDocumentDefinition> {
@ -84,41 +80,29 @@ struct TextDocumentDefinitionHandler
// - symbol has declaration but no definition (ie, pure virtual) // - symbol has declaration but no definition (ie, pure virtual)
// - start at spelling but end at extent for better mouse tooltip // - start at spelling but end at extent for better mouse tooltip
// - goto declaration while in definition of recursive type // - goto declaration while in definition of recursive type
std::vector<Use> uses;
Maybe<Use> def_loc = GetDefinitionSpellingOfSymbol(db, sym); EachDef(db, sym, [&](const auto& def) {
if (def.spell && def.extent) {
// We use spelling start and extent end because this causes vscode to Use spell = *def.spell;
// highlight the entire definition when previewing / hoving with the // If on a definition, clear |uses| to find declarations below.
// mouse. if (spell.file == file_id &&
Maybe<Use> extent = GetDefinitionExtentOfSymbol(db, sym); spell.range.Contains(target_line, target_column)) {
if (def_loc && extent) uses.clear();
def_loc->range.end = extent->range.end; return false;
}
// If the cursor is currently at or in the definition we should goto // We use spelling start and extent end because this causes vscode
// the declaration if possible. We also want to use declarations if // to highlight the entire definition when previewing / hoving with
// we're pointing to, ie, a pure virtual function which has no // the mouse.
// definition. spell.range.end = def.extent->range.end;
if (!def_loc || (def_loc->file == file_id && uses.push_back(spell);
def_loc->range.Contains(target_line, target_column))) {
// Goto declaration.
std::vector<Use> targets = GetGotoDefinitionTargets(db, sym);
for (Use target : targets) {
optional<lsLocation> ls_target =
GetLsLocation(db, working_files, target);
if (ls_target)
out.result.push_back(*ls_target);
} }
// We found some declarations. Break so we don't add the definition return true;
// location. });
if (!out.result.empty())
break;
}
if (def_loc) {
PushBack(&out.result, GetLsLocation(db, working_files, *def_loc));
}
if (uses.empty())
uses = GetGotoDefinitionTargets(db, sym);
AddRange(&out.result,
GetLsLocations(db, working_files, uses, config->maxXrefResults));
if (!out.result.empty()) if (!out.result.empty())
break; break;
} }

View File

@ -403,10 +403,10 @@ optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
return ret; return ret;
} }
std::vector<lsLocation> GetLsLocations( std::vector<lsLocation> GetLsLocations(QueryDatabase* db,
QueryDatabase* db, WorkingFiles* working_files,
WorkingFiles* working_files, const std::vector<Use>& uses,
const std::vector<Use>& uses) { int limit) {
std::vector<lsLocation> ret; std::vector<lsLocation> ret;
for (Use use : uses) { for (Use use : uses) {
optional<lsLocation> location = optional<lsLocation> location =
@ -416,6 +416,8 @@ std::vector<lsLocation> GetLsLocations(
} }
std::sort(ret.begin(), ret.end()); std::sort(ret.begin(), ret.end());
ret.erase(std::unique(ret.begin(), ret.end()), ret.end()); ret.erase(std::unique(ret.begin(), ret.end()), ret.end());
if (ret.size() > limit)
ret.resize(limit);
return ret; return ret;
} }

View File

@ -47,7 +47,8 @@ optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
bool extension); bool extension);
std::vector<lsLocation> GetLsLocations(QueryDatabase* db, std::vector<lsLocation> GetLsLocations(QueryDatabase* db,
WorkingFiles* working_files, WorkingFiles* working_files,
const std::vector<Use>& refs); const std::vector<Use>& refs,
int limit);
// Returns a symbol. The symbol will have *NOT* have a location assigned. // Returns a symbol. The symbol will have *NOT* have a location assigned.
optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db, optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
WorkingFiles* working_files, WorkingFiles* working_files,
@ -62,6 +63,30 @@ void EmitDiagnostics(WorkingFiles* working_files,
std::string path, std::string path,
std::vector<lsDiagnostic> diagnostics); std::vector<lsDiagnostic> diagnostics);
template <typename Fn>
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 <typename Q, typename Fn> template <typename Q, typename Fn>
void EachWithGen(std::vector<Q>& collection, Id<Q> x, Fn fn) { void EachWithGen(std::vector<Q>& collection, Id<Q> x, Fn fn) {
Q& obj = collection[x.id]; Q& obj = collection[x.id];

View File

@ -174,7 +174,7 @@ def configure(ctx):
cxxflags.append('-Wno-unused-result') cxxflags.append('-Wno-unused-result')
if all(not x.startswith('-std=') for x in ctx.env.CXXFLAGS): 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: if ctx.options.use_clang_cxx:
# include/clang/Format/Format.h error: multi-line comment # include/clang/Format/Format.h error: multi-line comment