diagnostics; use custom DenseMapInfo

This commit is contained in:
Fangrui Song 2018-09-11 16:42:04 -07:00
parent c9e6b31dd0
commit a45686ae1b
6 changed files with 57 additions and 62 deletions

View File

@ -200,17 +200,15 @@ bool Parse(CompilerInstance &Clang) {
return true;
}
void CompletionPreloadMain(CompletionManager *completion_manager) {
void CompletionPreloadMain(CompletionManager *manager) {
while (true) {
// Fetching the completion request blocks until we have a request.
auto request = completion_manager->preload_requests_.Dequeue();
auto request = manager->preload_requests_.Dequeue();
// If we don't get a session then that means we don't care about the file
// anymore - abandon the request.
std::shared_ptr<CompletionSession> session =
completion_manager->TryGetSession(request.path,
false /*mark_as_completion*/,
false /*create_if_needed*/);
std::shared_ptr<CompletionSession> session = manager->TryGetSession(
request.path, false /*mark_as_completion*/, false /*create_if_needed*/);
if (!session)
continue;
@ -222,6 +220,11 @@ void CompletionPreloadMain(CompletionManager *completion_manager) {
if (std::unique_ptr<CompilerInvocation> CI =
BuildCompilerInvocation(args, session->FS))
session->BuildPreamble(*CI);
if (g_config->diagnostics.onSave) {
lsTextDocumentIdentifier document;
document.uri = lsDocumentUri::FromPath(request.path);
manager->diagnostic_request_.PushBack({document}, true);
}
}
}
@ -416,7 +419,7 @@ void CompletionManager::DiagnosticsUpdate(
void CompletionManager::NotifyView(const std::string &path) {
// Only reparse the file if we create a new CompletionSession.
if (EnsureCompletionOrCreatePreloadSession(path))
preload_requests_.PushBack(PreloadRequest(path), true);
preload_requests_.PushBack(PreloadRequest{path}, true);
}
void CompletionManager::NotifySave(const std::string &filename) {
@ -425,7 +428,7 @@ void CompletionManager::NotifySave(const std::string &filename) {
//
EnsureCompletionOrCreatePreloadSession(filename);
preload_requests_.PushBack(PreloadRequest(filename), true);
preload_requests_.PushBack(PreloadRequest{filename}, true);
}
void CompletionManager::NotifyClose(const std::string &filename) {

View File

@ -86,10 +86,6 @@ struct CompletionManager {
using OnDropped = std::function<void(lsRequestId request_id)>;
struct PreloadRequest {
PreloadRequest(const std::string &path)
: request_time(std::chrono::high_resolution_clock::now()), path(path) {}
std::chrono::time_point<std::chrono::high_resolution_clock> request_time;
std::string path;
};
struct CompletionRequest {

View File

@ -49,8 +49,6 @@ struct Handler_TextDocumentDidSave
Project::Entry entry = project->FindCompilationEntryForFile(path);
pipeline::Index(entry.filename, entry.args, IndexMode::Normal);
clang_complete->NotifySave(path);
if (g_config->diagnostics.onSave)
clang_complete->DiagnosticsUpdate(params.textDocument);
}
};
REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidSave);

View File

@ -250,36 +250,37 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) {
.outline2refcnt[SymbolRef{{dr.extent, usr, kind, dr.role}}] += delta;
};
auto UpdateUses = [&](Usr usr, SymbolKind kind,
llvm::DenseMap<WrappedUsr, int> &entity_usr,
auto &entities, auto &p, bool hint_implicit) {
auto R = entity_usr.try_emplace({usr}, entity_usr.size());
if (R.second)
vars.emplace_back().usr = usr;
auto &entity = entities[R.first->second];
for (Use &use : p.first) {
if (hint_implicit && use.role & Role::Implicit) {
// Make ranges of implicit function calls larger (spanning one more
// column to the left/right). This is hacky but useful. e.g.
// textDocument/definition on the space/semicolon in `A a;` or ` 42;`
// will take you to the constructor.
if (use.range.start.column > 0)
use.range.start.column--;
use.range.end.column++;
}
Ref(prev_lid2file_id, usr, kind, use, -1);
}
RemoveRange(entity.uses, p.first);
for (Use &use : p.second) {
if (hint_implicit && use.role & Role::Implicit) {
if (use.range.start.column > 0)
use.range.start.column--;
use.range.end.column++;
}
Ref(lid2file_id, usr, kind, use, 1);
}
AddRange(entity.uses, p.second);
};
auto UpdateUses =
[&](Usr usr, SymbolKind kind,
llvm::DenseMap<Usr, int, DenseMapInfoForUsr> &entity_usr,
auto &entities, auto &p, bool hint_implicit) {
auto R = entity_usr.try_emplace(usr, entity_usr.size());
if (R.second)
vars.emplace_back().usr = usr;
auto &entity = entities[R.first->second];
for (Use &use : p.first) {
if (hint_implicit && use.role & Role::Implicit) {
// Make ranges of implicit function calls larger (spanning one more
// column to the left/right). This is hacky but useful. e.g.
// textDocument/definition on the space/semicolon in `A a;` or `
// 42;` will take you to the constructor.
if (use.range.start.column > 0)
use.range.start.column--;
use.range.end.column++;
}
Ref(prev_lid2file_id, usr, kind, use, -1);
}
RemoveRange(entity.uses, p.first);
for (Use &use : p.second) {
if (hint_implicit && use.role & Role::Implicit) {
if (use.range.start.column > 0)
use.range.start.column--;
use.range.end.column++;
}
Ref(lid2file_id, usr, kind, use, 1);
}
AddRange(entity.uses, p.second);
};
if (u->files_removed)
files[name2file_id[LowerPathIfInsensitive(*u->files_removed)]].def =

View File

@ -147,14 +147,11 @@ struct IndexUpdate {
UseUpdate vars_uses;
};
struct WrappedUsr {
Usr usr;
};
template <> struct llvm::DenseMapInfo<WrappedUsr> {
static inline WrappedUsr getEmptyKey() { return {0}; }
static inline WrappedUsr getTombstoneKey() { return {~0ULL}; }
static unsigned getHashValue(WrappedUsr w) { return w.usr; }
static bool isEqual(WrappedUsr l, WrappedUsr r) { return l.usr == r.usr; }
struct DenseMapInfoForUsr {
static inline Usr getEmptyKey() { return 0; }
static inline Usr getTombstoneKey() { return ~0ULL; }
static unsigned getHashValue(Usr w) { return w; }
static bool isEqual(Usr l, Usr r) { return l == r; }
};
using Lid2file_id = std::unordered_map<int, int>;
@ -164,7 +161,7 @@ using Lid2file_id = std::unordered_map<int, int>;
struct DB {
std::vector<QueryFile> files;
llvm::StringMap<int> name2file_id;
llvm::DenseMap<WrappedUsr, int> func_usr, type_usr, var_usr;
llvm::DenseMap<Usr, int, DenseMapInfoForUsr> func_usr, type_usr, var_usr;
std::vector<QueryFunc> funcs;
std::vector<QueryType> types;
std::vector<QueryVar> vars;
@ -184,13 +181,13 @@ struct DB {
std::vector<std::pair<Usr, QueryVar::Def>> &&us);
std::string_view GetSymbolName(SymbolIdx sym, bool qualified);
bool HasFunc(Usr usr) const { return func_usr.count({usr}); }
bool HasType(Usr usr) const { return type_usr.count({usr}); }
bool HasVar(Usr usr) const { return var_usr.count({usr}); }
bool HasFunc(Usr usr) const { return func_usr.count(usr); }
bool HasType(Usr usr) const { return type_usr.count(usr); }
bool HasVar(Usr usr) const { return var_usr.count(usr); }
QueryFunc &Func(Usr usr) { return funcs[func_usr[{usr}]]; }
QueryType &Type(Usr usr) { return types[type_usr[{usr}]]; }
QueryVar &Var(Usr usr) { return vars[var_usr[{usr}]]; }
QueryFunc &Func(Usr usr) { return funcs[func_usr[usr]]; }
QueryType &Type(Usr usr) { return types[type_usr[usr]]; }
QueryVar &Var(Usr usr) { return vars[var_usr[usr]]; }
QueryFile &GetFile(SymbolIdx ref) { return files[ref.usr]; }
QueryFunc &GetFunc(SymbolIdx ref) { return Func(ref.usr); }

View File

@ -30,9 +30,9 @@ int ComputeRangeSize(const Range &range) {
}
template <typename Q>
std::vector<Use> GetDeclarations(llvm::DenseMap<WrappedUsr, int> &entity_usr,
std::vector<Q> &entities,
const std::vector<Usr> &usrs) {
std::vector<Use>
GetDeclarations(llvm::DenseMap<Usr, int, DenseMapInfoForUsr> &entity_usr,
std::vector<Q> &entities, const std::vector<Usr> &usrs) {
std::vector<Use> ret;
ret.reserve(usrs.size());
for (Usr usr : usrs) {