Add 'cquery: Freshen Index' command.

This validates every file is indexed to its current state. It is very useful after, ie, a git checkout.
This commit is contained in:
Jacob Dufault 2017-04-20 21:50:31 -07:00
parent ead75bb7a3
commit 145bf87d70
7 changed files with 125 additions and 64 deletions

View File

@ -187,6 +187,7 @@ struct IpcManager {
RegisterId<Ipc_IsAlive>(ipc.get());
RegisterId<Ipc_OpenProject>(ipc.get());
RegisterId<Ipc_Cout>(ipc.get());
RegisterId<Ipc_CqueryFreshenIndex>(ipc.get());
return ipc;
}
};
@ -784,6 +785,7 @@ struct Index_DoIndex {
ImportAndUpdate,
ImportOnly,
Parse,
Freshen,
};
Index_DoIndex(Type type, const std::string& path, const optional<std::vector<std::string>>& args)
@ -839,6 +841,7 @@ void RegisterMessageTypes() {
MessageRegistry::instance()->Register<Ipc_TextDocumentCodeLens>();
MessageRegistry::instance()->Register<Ipc_CodeLensResolve>();
MessageRegistry::instance()->Register<Ipc_WorkspaceSymbol>();
MessageRegistry::instance()->Register<Ipc_CqueryFreshenIndex>();
}
@ -870,7 +873,16 @@ void RegisterMessageTypes() {
void DispatchDependencyImports(Index_DoIndexQueue* queue_do_index,
Index_DoIndex::Type request_type,
const std::vector<std::string>& dependencies) {
// Import all dependencies.
for (auto& dependency_path : dependencies) {
std::cerr << "- Dispatching dependency import " << dependency_path << std::endl;
queue_do_index->PriorityEnqueue(Index_DoIndex(request_type, dependency_path, nullopt));
}
}
void ImportCachedIndex(IndexerConfig* config,
Index_DoIndexQueue* queue_do_index,
@ -886,11 +898,7 @@ void ImportCachedIndex(IndexerConfig* config,
if (!cache)
return;
// Import all dependencies.
for (auto& dependency_path : cache->dependencies) {
std::cerr << "- Dispatching dependency import " << dependency_path << std::endl;
queue_do_index->PriorityEnqueue(Index_DoIndex(Index_DoIndex::Type::ImportOnly, dependency_path, nullopt));
}
DispatchDependencyImports(queue_do_index, Index_DoIndex::Type::ImportOnly, cache->dependencies);
*last_modification_time = cache->last_modification_time;
Index_DoIdMap response(nullptr, std::move(cache));
@ -901,16 +909,27 @@ void ParseFile(IndexerConfig* config,
FileConsumer::SharedState* file_consumer_shared,
Index_DoIdMapQueue* queue_do_id_map,
const std::string& path,
const optional<std::vector<std::string>>& args) {
const optional<std::vector<std::string>>& args,
std::vector<std::string>* opt_out_dependencies) {
Timer time;
// Parse request and send a response.
std::unique_ptr<IndexedFile> cached_path_index = LoadCachedFile(config, path);
// Skip index if file modification time didn't change.
if (cached_path_index && GetLastModificationTime(path) == cached_path_index->last_modification_time) {
time.ResetAndPrint("Skipping index update on " + path + " since file modification time has not changed");
return;
if (cached_path_index) {
// Give the user dependencies if requested.
if (opt_out_dependencies)
*opt_out_dependencies = cached_path_index->dependencies;
// Skip index if file modification time didn't change.
int64_t modification_time = GetLastModificationTime(path);
if (modification_time == cached_path_index->last_modification_time) {
time.ResetAndPrint("Skipping index update on " + path + " since file modification time has not changed");
return;
}
else {
time.ResetAndPrint("Modification time on " + path + " has changed from " + std::to_string(cached_path_index->last_modification_time) + " to " + std::to_string(modification_time));
}
}
std::vector<std::unique_ptr<IndexedFile>> indexes = Parse(
@ -982,7 +1001,14 @@ bool IndexMain_DoIndex(IndexerConfig* config,
}
case Index_DoIndex::Type::Parse: {
ParseFile(config, file_consumer_shared, queue_do_id_map, index_request->path, index_request->args);
ParseFile(config, file_consumer_shared, queue_do_id_map, index_request->path, index_request->args, nullptr);
break;
}
case Index_DoIndex::Type::Freshen: {
std::vector<std::string> dependencies;
ParseFile(config, file_consumer_shared, queue_do_id_map, index_request->path, index_request->args, &dependencies);
DispatchDependencyImports(queue_do_index, Index_DoIndex::Type::Freshen, dependencies);
break;
}
}
@ -1145,60 +1171,28 @@ void QueryDbMainLoop(
Ipc_OpenProject* msg = static_cast<Ipc_OpenProject*>(message.get());
std::string path = msg->project_path;
std::vector<Matcher> whitelist;
std::cerr << "Using whitelist" << std::endl;
for (const std::string& entry : config->whitelist) {
std::cerr << " - " << entry << std::endl;
whitelist.push_back(Matcher(entry));
}
std::vector<Matcher> blacklist;
std::cerr << "Using blacklist" << std::endl;
for (const std::string& entry : config->blacklist) {
std::cerr << " - " << entry << std::endl;
blacklist.push_back(Matcher(entry));
}
project->Load(path);
std::cerr << "Loaded compilation entries (" << project->entries.size() << " files)" << std::endl;
//for (int i = 0; i < 10; ++i)
//std::cerr << project->entries[i].filename << std::endl;
for (int i = 0; i < project->entries.size(); ++i) {
const Project::Entry& entry = project->entries[i];
std::string filepath = entry.filename;
const Matcher* is_bad = nullptr;
for (const Matcher& m : whitelist) {
if (!m.IsMatch(filepath)) {
is_bad = &m;
break;
}
}
if (is_bad) {
std::cerr << "[" << i << "/" << (project->entries.size() - 1) << "] Failed whitelist check \"" << is_bad->regex_string << "\"; skipping " << filepath << std::endl;
continue;
}
for (const Matcher& m : blacklist) {
if (m.IsMatch(filepath)) {
is_bad = &m;
break;
}
}
if (is_bad) {
std::cerr << "[" << i << "/" << (project->entries.size() - 1) << "] Failed blacklist check \"" << is_bad->regex_string << "\"; skipping " << filepath << std::endl;
continue;
}
project->ForAllFilteredFiles(config, [&](int i, const Project::Entry& entry) {
std::cerr << "[" << i << "/" << (project->entries.size() - 1)
<< "] Dispatching index request for file " << filepath
<< "] Dispatching index request for file " << entry.filename
<< std::endl;
queue_do_index->Enqueue(Index_DoIndex(Index_DoIndex::Type::ImportAndUpdate, filepath, entry.args));
}
queue_do_index->Enqueue(Index_DoIndex(Index_DoIndex::Type::ImportAndUpdate, entry.filename, entry.args));
});
break;
}
case IpcId::CqueryFreshenIndex: {
std::cerr << "Freshening " << project->entries.size() << " files" << std::endl;
project->ForAllFilteredFiles(config, [&](int i, const Project::Entry& entry) {
std::cerr << "[" << i << "/" << (project->entries.size() - 1)
<< "] Dispatching index request for file " << entry.filename
<< std::endl;
queue_do_index->Enqueue(Index_DoIndex(Index_DoIndex::Type::Freshen, entry.filename, entry.args));
});
break;
}
@ -1876,7 +1870,8 @@ void LanguageServerStdinLoop(IndexerConfig* config) {
case IpcId::TextDocumentReferences:
case IpcId::TextDocumentDocumentSymbol:
case IpcId::TextDocumentCodeLens:
case IpcId::WorkspaceSymbol: {
case IpcId::WorkspaceSymbol:
case IpcId::CqueryFreshenIndex: {
ipc->SendMessage(IpcManager::Destination::Server, std::move(message));
break;
}

View File

@ -465,7 +465,7 @@ struct IdCache {
struct IndexedFile {
IdCache id_cache;
static constexpr int kCurrentVersion = 1;
static constexpr int kCurrentVersion = 2;
int version = 0;
std::string path;

View File

@ -39,6 +39,9 @@ const char* IpcIdToString(IpcId id) {
case IpcId::WorkspaceSymbol:
return "workspace/symbol";
case IpcId::CqueryFreshenIndex: {
return "$cquery/freshenIndex";
}
case IpcId::Quit:
return "$quit";

View File

@ -25,6 +25,9 @@ enum class IpcId : int {
CodeLensResolve,
WorkspaceSymbol,
// Custom messages
CqueryFreshenIndex,
// Internal implementation detail.
Quit,
IsAlive,

View File

@ -1340,7 +1340,7 @@ struct lsWorkspaceSymbolParams {
std::string query;
};
MAKE_REFLECT_STRUCT(lsWorkspaceSymbolParams, query);
struct Ipc_WorkspaceSymbol : public IpcMessage<Ipc_WorkspaceSymbol > {
struct Ipc_WorkspaceSymbol : public IpcMessage<Ipc_WorkspaceSymbol> {
const static IpcId kIpcId = IpcId::WorkspaceSymbol;
lsRequestId id;
lsWorkspaceSymbolParams params;
@ -1381,4 +1381,11 @@ void Reflect(TVisitor& visitor, Out_ShowLogMessage& value) {
REFLECT_MEMBER2("method", value.method());
REFLECT_MEMBER(params);
REFLECT_MEMBER_END();
}
}
struct Ipc_CqueryFreshenIndex : public IpcMessage<Ipc_CqueryFreshenIndex> {
const static IpcId kIpcId = IpcId::CqueryFreshenIndex;
lsRequestId id;
};
MAKE_REFLECT_STRUCT(Ipc_CqueryFreshenIndex, id);

View File

@ -1,5 +1,6 @@
#include "project.h"
#include "fuzzy.h"
#include "libclangmm/Utility.h"
#include "platform.h"
#include "serializer.h"
@ -261,4 +262,51 @@ optional<std::vector<std::string>> Project::FindArgsForFile(const std::string& f
if (!entry)
return nullopt;
return entry->args;
}
}
void Project::ForAllFilteredFiles(IndexerConfig* config, std::function<void(int i, const Entry& entry)> action) {
std::vector<Matcher> whitelist;
std::cerr << "Using whitelist" << std::endl;
for (const std::string& entry : config->whitelist) {
std::cerr << " - " << entry << std::endl;
whitelist.push_back(Matcher(entry));
}
std::vector<Matcher> blacklist;
std::cerr << "Using blacklist" << std::endl;
for (const std::string& entry : config->blacklist) {
std::cerr << " - " << entry << std::endl;
blacklist.push_back(Matcher(entry));
}
for (int i = 0; i < entries.size(); ++i) {
const Project::Entry& entry = entries[i];
std::string filepath = entry.filename;
const Matcher* is_bad = nullptr;
for (const Matcher& m : whitelist) {
if (!m.IsMatch(filepath)) {
is_bad = &m;
break;
}
}
if (is_bad) {
std::cerr << "[" << i << "/" << (entries.size() - 1) << "] Failed whitelist check \"" << is_bad->regex_string << "\"; skipping " << filepath << std::endl;
continue;
}
for (const Matcher& m : blacklist) {
if (m.IsMatch(filepath)) {
is_bad = &m;
break;
}
}
if (is_bad) {
std::cerr << "[" << i << "/" << (entries.size() - 1) << "] Failed blacklist check \"" << is_bad->regex_string << "\"; skipping " << filepath << std::endl;
continue;
}
action(i, entries[i]);
}
}

View File

@ -1,8 +1,11 @@
#pragma once
#include "language_server_api.h"
#include <optional.h>
#include <sparsepp/spp.h>
#include <functional>
#include <mutex>
#include <string>
#include <vector>
@ -32,5 +35,7 @@ struct Project {
// Helper that uses FindCompilationEntryForFile.
optional<std::vector<std::string>> FindArgsForFile(const std::string& filename);
void ForAllFilteredFiles(IndexerConfig* config, std::function<void(int i, const Entry& entry)> action);
};