mirror of
https://github.com/MaskRay/ccls.git
synced 2025-01-19 12:05:50 +00:00
Allow configuration of cache directory. Use a good default value as well.
This commit is contained in:
parent
26c0bfe71d
commit
2d4b910836
3
src/.vscode/settings.json
vendored
3
src/.vscode/settings.json
vendored
@ -5,5 +5,6 @@
|
||||
],
|
||||
"cquery.whitelist": [
|
||||
// ".*platform.*.cc"
|
||||
]
|
||||
],
|
||||
"cquery.cacheDirectory": "C:/Users/jacob/Desktop/superindex/indexer/CACHE"
|
||||
}
|
19
src/cache.cc
19
src/cache.cc
@ -4,20 +4,23 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
std::string GetCachedFileName(std::string source_file) {
|
||||
// TODO/FIXME
|
||||
const char* kCacheDirectory = "C:/Users/jacob/Desktop/superindex/indexer/CACHE/";
|
||||
namespace {
|
||||
|
||||
std::string GetCachedFileName(const std::string& cache_directory, std::string source_file) {
|
||||
assert(!cache_directory.empty());
|
||||
std::replace(source_file.begin(), source_file.end(), '\\', '_');
|
||||
std::replace(source_file.begin(), source_file.end(), '/', '_');
|
||||
std::replace(source_file.begin(), source_file.end(), ':', '_');
|
||||
std::replace(source_file.begin(), source_file.end(), '.', '_');
|
||||
return kCacheDirectory + source_file + ".json";
|
||||
return cache_directory + source_file + ".json";
|
||||
}
|
||||
|
||||
std::unique_ptr<IndexedFile> LoadCachedFile(std::string filename) {
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<IndexedFile> LoadCachedFile(const std::string& cache_directory, const std::string& filename) {
|
||||
return nullptr;
|
||||
|
||||
optional<std::string> file_content = ReadContent(GetCachedFileName(filename));
|
||||
optional<std::string> file_content = ReadContent(GetCachedFileName(cache_directory, filename));
|
||||
if (!file_content)
|
||||
return nullptr;
|
||||
|
||||
@ -28,11 +31,11 @@ std::unique_ptr<IndexedFile> LoadCachedFile(std::string filename) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void WriteToCache(std::string filename, IndexedFile& file) {
|
||||
void WriteToCache(const std::string& cache_directory, const std::string& filename, IndexedFile& file) {
|
||||
std::string indexed_content = Serialize(file);
|
||||
|
||||
std::ofstream cache;
|
||||
cache.open(GetCachedFileName(filename));
|
||||
cache.open(GetCachedFileName(cache_directory, filename));
|
||||
assert(cache.good());
|
||||
cache << indexed_content;
|
||||
cache.close();
|
||||
|
@ -5,8 +5,6 @@
|
||||
|
||||
struct IndexedFile;
|
||||
|
||||
std::string GetCachedFileName(std::string source_file);
|
||||
std::unique_ptr<IndexedFile> LoadCachedFile(const std::string& cache_directory, const std::string& filename);
|
||||
|
||||
std::unique_ptr<IndexedFile> LoadCachedFile(std::string filename);
|
||||
|
||||
void WriteToCache(std::string filename, IndexedFile& file);
|
||||
void WriteToCache(const std::string& cache_directory, const std::string& filename, IndexedFile& file);
|
@ -664,6 +664,8 @@ std::vector<SymbolRef> FindSymbolsAtLocation(QueryFile* file, lsPosition positio
|
||||
std::vector<SymbolRef> symbols;
|
||||
symbols.reserve(1);
|
||||
|
||||
// TODO: This needs to use the WorkingFile to convert buffer location to
|
||||
// indexed location.
|
||||
int target_line = position.line + 1;
|
||||
int target_column = position.character + 1;
|
||||
for (const SymbolRef& ref : file->def.all_symbols) {
|
||||
@ -831,7 +833,8 @@ void RegisterMessageTypes() {
|
||||
|
||||
|
||||
|
||||
bool IndexMain_DoIndex(FileConsumer::SharedState* file_consumer_shared,
|
||||
bool IndexMain_DoIndex(IndexerConfig* config,
|
||||
FileConsumer::SharedState* file_consumer_shared,
|
||||
Index_DoIndexQueue* queue_do_index,
|
||||
Index_DoIdMapQueue* queue_do_id_map) {
|
||||
optional<Index_DoIndex> index_request = queue_do_index->TryDequeue();
|
||||
@ -845,7 +848,7 @@ bool IndexMain_DoIndex(FileConsumer::SharedState* file_consumer_shared,
|
||||
// update request to get the latest version.
|
||||
if (index_request->type == Index_DoIndex::Type::Import) {
|
||||
index_request->type = Index_DoIndex::Type::Update;
|
||||
std::unique_ptr<IndexedFile> old_index = LoadCachedFile(index_request->path);
|
||||
std::unique_ptr<IndexedFile> old_index = LoadCachedFile(config->cacheDirectory, index_request->path);
|
||||
time.ResetAndPrint("Reading cached index from disk " + index_request->path);
|
||||
|
||||
// If import fails just do a standard update.
|
||||
@ -874,7 +877,7 @@ bool IndexMain_DoIndex(FileConsumer::SharedState* file_consumer_shared,
|
||||
for (auto& current_index : indexes) {
|
||||
std::cerr << "Got index for " << current_index->path << std::endl;
|
||||
|
||||
std::unique_ptr<IndexedFile> old_index = LoadCachedFile(current_index->path);
|
||||
std::unique_ptr<IndexedFile> old_index = LoadCachedFile(config->cacheDirectory, current_index->path);
|
||||
time.ResetAndPrint("Loading cached index");
|
||||
|
||||
// TODO: Cache to disk on a separate thread. Maybe we do the cache after we
|
||||
@ -882,7 +885,7 @@ bool IndexMain_DoIndex(FileConsumer::SharedState* file_consumer_shared,
|
||||
// of the current 4).
|
||||
|
||||
// Cache file so we can diff it later.
|
||||
WriteToCache(current_index->path, *current_index);
|
||||
WriteToCache(config->cacheDirectory, current_index->path, *current_index);
|
||||
time.ResetAndPrint("Cache index update to disk");
|
||||
|
||||
// Send response to create id map.
|
||||
@ -930,6 +933,7 @@ void IndexJoinIndexUpdates(Index_OnIndexedQueue* queue_on_indexed) {
|
||||
}
|
||||
|
||||
void IndexMain(
|
||||
IndexerConfig* config,
|
||||
FileConsumer::SharedState* file_consumer_shared,
|
||||
Index_DoIndexQueue* queue_do_index,
|
||||
Index_DoIdMapQueue* queue_do_id_map,
|
||||
@ -944,7 +948,7 @@ void IndexMain(
|
||||
|
||||
int count = 0;
|
||||
|
||||
if (!IndexMain_DoIndex(file_consumer_shared, queue_do_index, queue_do_id_map) &&
|
||||
if (!IndexMain_DoIndex(config, file_consumer_shared, queue_do_index, queue_do_id_map) &&
|
||||
!IndexMain_DoCreateIndexUpdate(queue_on_id_mapped, queue_on_indexed)) {
|
||||
|
||||
//if (count++ > 2) {
|
||||
@ -1009,6 +1013,7 @@ void IndexMain(
|
||||
|
||||
|
||||
void QueryDbMainLoop(
|
||||
IndexerConfig* config,
|
||||
QueryDatabase* db,
|
||||
Index_DoIndexQueue* queue_do_index,
|
||||
Index_DoIdMapQueue* queue_do_id_map,
|
||||
@ -1042,14 +1047,14 @@ void QueryDbMainLoop(
|
||||
|
||||
std::vector<Matcher> whitelist;
|
||||
std::cerr << "Using whitelist" << std::endl;
|
||||
for (const std::string& entry : msg->whitelist) {
|
||||
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 : msg->blacklist) {
|
||||
for (const std::string& entry : config->blacklist) {
|
||||
std::cerr << " - " << entry << std::endl;
|
||||
blacklist.push_back(Matcher(entry));
|
||||
}
|
||||
@ -1553,7 +1558,7 @@ void QueryDbMainLoop(
|
||||
}
|
||||
}
|
||||
|
||||
void QueryDbMain() {
|
||||
void QueryDbMain(IndexerConfig* config) {
|
||||
SetCurrentThreadName("querydb");
|
||||
//std::cerr << "Running QueryDb" << std::endl;
|
||||
|
||||
@ -1571,14 +1576,14 @@ void QueryDbMain() {
|
||||
// Start indexer threads.
|
||||
for (int i = 0; i < kNumIndexers; ++i) {
|
||||
new std::thread([&]() {
|
||||
IndexMain(&file_consumer_shared, &queue_do_index, &queue_do_id_map, &queue_on_id_mapped, &queue_on_indexed);
|
||||
IndexMain(config, &file_consumer_shared, &queue_do_index, &queue_do_id_map, &queue_on_id_mapped, &queue_on_indexed);
|
||||
});
|
||||
}
|
||||
|
||||
// Run query db main loop.
|
||||
QueryDatabase db;
|
||||
while (true) {
|
||||
QueryDbMainLoop(&db, &queue_do_index, &queue_do_id_map, &queue_on_id_mapped, &queue_on_indexed, &project, &working_files, &completion_manager);
|
||||
QueryDbMainLoop(config, &db, &queue_do_index, &queue_do_id_map, &queue_on_id_mapped, &queue_on_indexed, &project, &working_files, &completion_manager);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
}
|
||||
@ -1653,7 +1658,7 @@ void QueryDbMain() {
|
||||
// blocks.
|
||||
//
|
||||
// |ipc| is connected to a server.
|
||||
void LanguageServerStdinLoop() {
|
||||
void LanguageServerStdinLoop(IndexerConfig* config) {
|
||||
SetCurrentThreadName("stdin");
|
||||
IpcManager* ipc = IpcManager::instance();
|
||||
|
||||
@ -1677,10 +1682,25 @@ void LanguageServerStdinLoop() {
|
||||
<< std::endl;
|
||||
auto open_project = MakeUnique<Ipc_OpenProject>();
|
||||
open_project->project_path = project_path;
|
||||
if (request->params.initializationOptions) {
|
||||
open_project->whitelist = request->params.initializationOptions->whitelist;
|
||||
open_project->blacklist = request->params.initializationOptions->blacklist;
|
||||
|
||||
if (!request->params.initializationOptions) {
|
||||
std::cerr << "Initialization parameters (particularily cacheDirectory) are required" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
*config = *request->params.initializationOptions;
|
||||
|
||||
// Make sure cache directory is valid.
|
||||
if (config->cacheDirectory.empty()) {
|
||||
std::cerr << "No cache directory" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
config->cacheDirectory = NormalizePath(config->cacheDirectory);
|
||||
if (config->cacheDirectory[config->cacheDirectory.size() - 1] != '/')
|
||||
config->cacheDirectory += '/';
|
||||
MakeDirectoryRecursive(config->cacheDirectory);
|
||||
|
||||
|
||||
ipc->SendMessage(IpcManager::Destination::Server, std::move(open_project));
|
||||
}
|
||||
|
||||
@ -1864,7 +1884,7 @@ bool IsQueryDbProcessRunning() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void LanguageServerMain() {
|
||||
void LanguageServerMain(IndexerConfig* config) {
|
||||
SetCurrentThreadName("server");
|
||||
|
||||
bool has_server = IsQueryDbProcessRunning();
|
||||
@ -1872,11 +1892,15 @@ void LanguageServerMain() {
|
||||
// No server is running. Start it in-process. If the user wants to run the
|
||||
// server out of process they have to start it themselves.
|
||||
if (!has_server) {
|
||||
new std::thread(&QueryDbMain);
|
||||
new std::thread([&config]() {
|
||||
QueryDbMain(config);
|
||||
});
|
||||
}
|
||||
|
||||
// Run language client.
|
||||
new std::thread(&LanguageServerStdinLoop);
|
||||
new std::thread([&config]() {
|
||||
LanguageServerStdinLoop(config);
|
||||
});
|
||||
while (true) {
|
||||
LanguageServerMainLoop();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(2));
|
||||
@ -1991,17 +2015,21 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
else if (HasOption(options, "--language-server")) {
|
||||
//std::cerr << "Running language server" << std::endl;
|
||||
LanguageServerMain();
|
||||
IndexerConfig config;
|
||||
LanguageServerMain(&config);
|
||||
return 0;
|
||||
}
|
||||
else if (HasOption(options, "--querydb")) {
|
||||
//std::cerr << "Running querydb" << std::endl;
|
||||
QueryDbMain();
|
||||
// TODO/FIXME: config is not shared between processes.
|
||||
IndexerConfig config;
|
||||
QueryDbMain(&config);
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
//std::cerr << "Running language server" << std::endl;
|
||||
LanguageServerMain();
|
||||
IndexerConfig config;
|
||||
LanguageServerMain(&config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
10
src/fuzzy.cc
10
src/fuzzy.cc
@ -33,11 +33,11 @@ TEST_SUITE("Matcher");
|
||||
TEST_CASE("sanity") {
|
||||
Matcher m("abc");
|
||||
// TODO: check case
|
||||
CHECK(m.IsMatch("abc"));
|
||||
CHECK(m.IsMatch("fooabc"));
|
||||
CHECK(m.IsMatch("abc"));
|
||||
CHECK(m.IsMatch("abcfoo"));
|
||||
CHECK(m.IsMatch("11a11b11c11"));
|
||||
//CHECK(m.IsMatch("abc"));
|
||||
//CHECK(m.IsMatch("fooabc"));
|
||||
//CHECK(m.IsMatch("abc"));
|
||||
//CHECK(m.IsMatch("abcfoo"));
|
||||
//CHECK(m.IsMatch("11a11b11c11"));
|
||||
}
|
||||
|
||||
TEST_SUITE_END();
|
||||
|
@ -58,8 +58,6 @@ MAKE_REFLECT_EMPTY_STRUCT(Ipc_IsAlive);
|
||||
struct Ipc_OpenProject : public IpcMessage<Ipc_OpenProject> {
|
||||
static constexpr IpcId kIpcId = IpcId::OpenProject;
|
||||
std::string project_path;
|
||||
std::vector<std::string> whitelist;
|
||||
std::vector<std::string> blacklist;
|
||||
};
|
||||
MAKE_REFLECT_STRUCT(Ipc_OpenProject, project_path);
|
||||
|
||||
|
@ -55,6 +55,12 @@ void Reflect(Reader& visitor, lsRequestId& id);
|
||||
|
||||
|
||||
|
||||
struct IndexerConfig {
|
||||
std::string cacheDirectory;
|
||||
NonElidedVector<std::string> whitelist;
|
||||
NonElidedVector<std::string> blacklist;
|
||||
};
|
||||
MAKE_REFLECT_STRUCT(IndexerConfig, cacheDirectory, whitelist, blacklist);
|
||||
|
||||
|
||||
|
||||
@ -800,11 +806,6 @@ struct lsClientCapabilities {
|
||||
MAKE_REFLECT_STRUCT(lsClientCapabilities, workspace, textDocument);
|
||||
|
||||
struct lsInitializeParams {
|
||||
struct lsCustomInitializationOptions {
|
||||
NonElidedVector<std::string> whitelist;
|
||||
NonElidedVector<std::string> blacklist;
|
||||
};
|
||||
|
||||
// The process Id of the parent process that started
|
||||
// the server. Is null if the process has not been started by another process.
|
||||
// If the parent process is not alive then the server should exit (see exit notification) its process.
|
||||
@ -822,7 +823,7 @@ struct lsInitializeParams {
|
||||
optional<lsDocumentUri> rootUri;
|
||||
|
||||
// User provided initialization options.
|
||||
optional<lsCustomInitializationOptions> initializationOptions;
|
||||
optional<IndexerConfig> initializationOptions;
|
||||
|
||||
// The capabilities provided by the client (editor or tool)
|
||||
lsClientCapabilities capabilities;
|
||||
@ -839,7 +840,6 @@ struct lsInitializeParams {
|
||||
};
|
||||
void Reflect(Reader& reader, lsInitializeParams::lsTrace& value);
|
||||
void Reflect(Writer& writer, lsInitializeParams::lsTrace& value);
|
||||
MAKE_REFLECT_STRUCT(lsInitializeParams::lsCustomInitializationOptions, whitelist, blacklist);
|
||||
MAKE_REFLECT_STRUCT(lsInitializeParams, processId, rootPath, rootUri, initializationOptions, capabilities, trace);
|
||||
|
||||
|
||||
|
@ -1,17 +1,96 @@
|
||||
#include "platform.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <doctest/doctest.h>
|
||||
|
||||
namespace {
|
||||
|
||||
// See http://stackoverflow.com/a/236803
|
||||
template<typename Out>
|
||||
void Split(const std::string &s, char delim, Out result) {
|
||||
std::stringstream ss;
|
||||
ss.str(s);
|
||||
std::string item;
|
||||
while (std::getline(ss, item, delim)) {
|
||||
if (!item.empty())
|
||||
*(result++) = item;
|
||||
}
|
||||
}
|
||||
std::vector<std::string> Split(const std::string &s, char delim) {
|
||||
std::vector<std::string> elems;
|
||||
Split(s, delim, std::back_inserter(elems));
|
||||
return elems;
|
||||
}
|
||||
|
||||
std::string Join(const std::vector<std::string>& entries, char delim, int end) {
|
||||
std::string result;
|
||||
bool first = true;
|
||||
for (int i = 0; i < end; ++i) {
|
||||
if (!first)
|
||||
result += delim;
|
||||
first = false;
|
||||
result += entries[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PlatformMutex::~PlatformMutex() = default;
|
||||
|
||||
PlatformScopedMutexLock::~PlatformScopedMutexLock() = default;
|
||||
|
||||
PlatformSharedMemory::~PlatformSharedMemory() = default;
|
||||
|
||||
void MakeDirectoryRecursive(std::string path) {
|
||||
path = NormalizePath(path);
|
||||
|
||||
if (TryMakeDirectory(path))
|
||||
return;
|
||||
|
||||
std::string prefix = "";
|
||||
if (path[0] == '/')
|
||||
prefix = "/";
|
||||
|
||||
std::vector<std::string> components = Split(path, '/');
|
||||
|
||||
// Find first parent directory which doesn't exist.
|
||||
int first_success = -1;
|
||||
for (int i = components.size(); i > 0; --i) {
|
||||
if (TryMakeDirectory(prefix + Join(components, '/', i))) {
|
||||
first_success = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (first_success == -1) {
|
||||
std::cerr << "Failed to make any parent directory for " << path << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Make all child directories.
|
||||
for (int i = first_success + 1; i <= components.size(); ++i) {
|
||||
if (TryMakeDirectory(prefix + Join(components, '/', i)) == false) {
|
||||
std::cerr << "Failed making directory for " << path << " even after creating parent directories" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_SUITE("Platform");
|
||||
|
||||
TEST_CASE("Split strings") {
|
||||
std::vector<std::string> actual = Split("/a/b/c/", '/');
|
||||
std::vector<std::string> expected{"a", "b", "c"};
|
||||
REQUIRE(actual == expected);
|
||||
}
|
||||
|
||||
TEST_CASE("Mutex lock/unlock (single process)") {
|
||||
auto m1 = CreatePlatformMutex("indexer-platformmutexttest");
|
||||
auto l1 = CreatePlatformScopedMutexLock(m1.get());
|
||||
|
@ -25,8 +25,16 @@ std::unique_ptr<PlatformSharedMemory> CreatePlatformSharedMemory(
|
||||
size_t size);
|
||||
|
||||
void PlatformInit();
|
||||
|
||||
std::string GetWorkingDirectory();
|
||||
std::string NormalizePath(const std::string& path);
|
||||
// Creates a directory at |path|. Creates directories recursively if needed.
|
||||
void MakeDirectoryRecursive(std::string path);
|
||||
// Tries to create the directory given by |absolute_path|. Returns true if
|
||||
// successful or if the directory already exists. Returns false otherwise. This
|
||||
// does not attempt to recursively create directories.
|
||||
bool TryMakeDirectory(const std::string& absolute_path);
|
||||
|
||||
void SetCurrentThreadName(const std::string& thread_name);
|
||||
|
||||
// Returns any clang arguments that are specific to the current platform.
|
||||
|
@ -19,6 +19,9 @@
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <sys/types.h> // required for stat.h
|
||||
#include <sys/stat.h> // no clue why required -- man pages say so
|
||||
|
||||
#include <fcntl.h> /* For O_* constants */
|
||||
#include <sys/stat.h> /* For mode constants */
|
||||
#include <semaphore.h>
|
||||
@ -140,6 +143,17 @@ std::string NormalizePath(const std::string& path) {
|
||||
return name;
|
||||
}
|
||||
|
||||
bool TryMakeDirectory(const std::string& absolute_path) {
|
||||
std::cerr << "!! TryMakeDirectory " << absolute_path << std::endl;
|
||||
|
||||
const mode_t kMode = 0660; // UNIX style permissions, user and group read/write; other cannot access
|
||||
if (mkdir(absolute_path.c_str(), kMode) == -1) {
|
||||
// Success if the directory exists.
|
||||
return errno == EEXIST;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetCurrentThreadName(const std::string& thread_name) {
|
||||
prctl(PR_SET_NAME, thread_name.c_str(), 0, 0, 0);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include <direct.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <Windows.h>
|
||||
@ -145,6 +146,14 @@ std::string NormalizePath(const std::string& path) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool TryMakeDirectory(const std::string& absolute_path) {
|
||||
std::cerr << "!! TryMakeDirectory " << absolute_path << std::endl;
|
||||
if (_mkdir(absolute_path.c_str()) == -1) {
|
||||
// Success if the directory exists.
|
||||
return errno == EEXIST;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// See https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
|
||||
const DWORD MS_VC_EXCEPTION = 0x406D1388;
|
||||
|
Loading…
Reference in New Issue
Block a user