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;
// 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,

View File

@ -28,12 +28,12 @@ struct CqueryBaseHandler : BaseMessageHandler<Ipc_CqueryBase> {
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;
}
}

View File

@ -32,7 +32,8 @@ struct CqueryCallersHandler : BaseMessageHandler<Ipc_CqueryCallers> {
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);

View File

@ -27,13 +27,13 @@ struct CqueryDerivedHandler : BaseMessageHandler<Ipc_CqueryDerived> {
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;
}
}

View File

@ -39,7 +39,8 @@ struct CqueryVarsHandler : BaseMessageHandler<Ipc_CqueryVars> {
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;
}
}

View File

@ -9,10 +9,6 @@
#include <cstdlib>
namespace {
void PushBack(std::vector<lsLocation>* result, optional<lsLocation> location) {
if (location)
result->push_back(*location);
}
struct Ipc_TextDocumentDefinition
: public RequestMessage<Ipc_TextDocumentDefinition> {
@ -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<Use> 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<Use> 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<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);
std::vector<Use> 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 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));
// 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);
}
return true;
});
if (uses.empty())
uses = GetGotoDefinitionTargets(db, sym);
AddRange(&out.result,
GetLsLocations(db, working_files, uses, config->maxXrefResults));
if (!out.result.empty())
break;
}

View File

@ -403,10 +403,10 @@ optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
return ret;
}
std::vector<lsLocation> GetLsLocations(
QueryDatabase* db,
std::vector<lsLocation> GetLsLocations(QueryDatabase* db,
WorkingFiles* working_files,
const std::vector<Use>& uses) {
const std::vector<Use>& uses,
int limit) {
std::vector<lsLocation> ret;
for (Use use : uses) {
optional<lsLocation> location =
@ -416,6 +416,8 @@ std::vector<lsLocation> 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;
}

View File

@ -47,7 +47,8 @@ optional<lsLocationEx> GetLsLocationEx(QueryDatabase* db,
bool extension);
std::vector<lsLocation> GetLsLocations(QueryDatabase* db,
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.
optional<lsSymbolInformation> GetSymbolInfo(QueryDatabase* db,
WorkingFiles* working_files,
@ -62,6 +63,30 @@ void EmitDiagnostics(WorkingFiles* working_files,
std::string path,
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>
void EachWithGen(std::vector<Q>& collection, Id<Q> x, Fn fn) {
Q& obj = collection[x.id];

View File

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