mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-22 15:45:08 +00:00
Fix reindexing for header files
This commit is contained in:
parent
d83b1591a4
commit
4d9567a0c2
2
foo/.vscode/settings.json
vendored
2
foo/.vscode/settings.json
vendored
@ -1,5 +1,5 @@
|
||||
// Place your settings in this file to overwrite default and user settings.
|
||||
{
|
||||
"editor.lineNumbers": "on",
|
||||
"cquery.cacheDirectory": "C:/Users/jacob/AppData/Roaming/Code/User/workspaceStorage/ff57708adc5718d939d7a59c9d5270c7/jacobdufault.cquery/cquerycache/"
|
||||
"cquery.cacheDirectory": "C:/Users/jacob/Desktop/superindex/indexer/CACHE"
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
#if false
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct MyBar {
|
||||
int x;
|
||||
int aaaa1;
|
||||
int aaaa2;
|
||||
int aaaa3;
|
||||
static int foobez;
|
||||
|
||||
// This is some awesome docs.
|
||||
float MemberFunc(int a, char b, std::vector<int> foo);
|
||||
float MemberFunc2(int a, char b, std::vector<int> foo);
|
||||
|
||||
// The names are some extra state.
|
||||
std::vector<std::string> names;
|
||||
};
|
||||
|
||||
int MyBar::foobez;
|
||||
|
||||
int foo() {
|
||||
int a = 10;
|
||||
MyBar foooo;
|
||||
MyBar f;
|
||||
MyBar f2;
|
||||
}
|
||||
|
||||
float MyBar::MemberFunc(int a, char b, std::vector<int> foo) {
|
||||
this->x = 100;
|
||||
this->MemberFunc(0, 0, {});
|
||||
|
||||
return ::foo();
|
||||
}
|
||||
#endif
|
111
foo/a.cc
111
foo/a.cc
@ -1,111 +0,0 @@
|
||||
#if false
|
||||
/*
|
||||
abc
|
||||
daaa
|
||||
faf
|
||||
dakkdakk
|
||||
abaa
|
||||
*/
|
||||
#include <string>
|
||||
|
||||
#include "a.h"
|
||||
|
||||
|
||||
struct iface {
|
||||
virtual void foo() = 0;
|
||||
};
|
||||
struct impl : public iface {
|
||||
void foo() override {}
|
||||
};
|
||||
|
||||
void doit() {
|
||||
iface* f;
|
||||
f->foo();
|
||||
}
|
||||
|
||||
struct Middle : public Parent {
|
||||
void foo() override {}
|
||||
};
|
||||
struct DerivedA : public Middle {
|
||||
void foo() override {}
|
||||
};
|
||||
struct DerivedB : public Middle {
|
||||
void foo() override {}
|
||||
};
|
||||
struct Derived2B : public DerivedB {
|
||||
void foo() override {}
|
||||
};
|
||||
|
||||
struct Derived2C : public DerivedB {
|
||||
void foo() override;
|
||||
};
|
||||
|
||||
|
||||
void Derived2C::foo() {}
|
||||
|
||||
void User() {
|
||||
Parent p;
|
||||
Middle m;
|
||||
DerivedA da;
|
||||
DerivedB db;
|
||||
Derived2B d2b;
|
||||
|
||||
p.foo();
|
||||
m.foo();
|
||||
da.foo();
|
||||
db.foo();
|
||||
d2b.foo();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
struct Saaaaaa {};
|
||||
|
||||
struct S2 {
|
||||
S2() {}
|
||||
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
struct MyFoo {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
void f() {
|
||||
S2 s2;
|
||||
s2.a += 10;
|
||||
s2.b -= 100;
|
||||
s2.b -= 5;
|
||||
|
||||
MyFoo f;
|
||||
// f.name = 10;
|
||||
f.name = "okay";
|
||||
|
||||
MyFoo f2;
|
||||
f2.name = "yes!";
|
||||
}
|
||||
|
||||
|
||||
void baz();
|
||||
|
||||
void foo();
|
||||
void foo();
|
||||
|
||||
void foo() {}
|
||||
|
||||
/**/
|
||||
void caller() {
|
||||
MyFoo fff;
|
||||
fff.name = "this name";
|
||||
baz();
|
||||
baz();
|
||||
baz();
|
||||
foo();
|
||||
|
||||
foo();
|
||||
foo();
|
||||
}
|
||||
#endif
|
6
foo/b.cc
6
foo/b.cc
@ -1,4 +1,8 @@
|
||||
#include "a.h"
|
||||
|
||||
enum Foo {
|
||||
#include "a.h"
|
||||
};
|
||||
|
||||
void faz() {
|
||||
foobar();
|
||||
}
|
@ -896,7 +896,7 @@ bool IndexMain_DoIndex(IndexerConfig* config,
|
||||
queue_do_index->PriorityEnqueue(std::move(dep_index_request));
|
||||
}
|
||||
|
||||
project->UpdateModificationTime(index_request->path, old_index->last_modification_time);
|
||||
project->UpdateFileState(index_request->path, old_index->import_file, old_index->last_modification_time);
|
||||
|
||||
Index_DoIdMap response(nullptr, std::move(old_index));
|
||||
queue_do_id_map->Enqueue(std::move(response));
|
||||
@ -912,10 +912,13 @@ bool IndexMain_DoIndex(IndexerConfig* config,
|
||||
}
|
||||
|
||||
// Parse request and send a response.
|
||||
std::string import_file = index_request->path;
|
||||
|
||||
// Skip index if file modification time didn't change.
|
||||
optional<Project::Entry> entry = project->FindCompilationEntryForFile(index_request->path);
|
||||
if (entry && entry->last_modification_time) {
|
||||
import_file = entry->import_file;
|
||||
|
||||
int64_t modification_time = GetLastModificationTime(index_request->path);
|
||||
if (modification_time == *entry->last_modification_time) {
|
||||
time.ResetAndPrint("Skipping index update on " + index_request->path + " since file modification time has not changed");
|
||||
@ -923,12 +926,14 @@ bool IndexMain_DoIndex(IndexerConfig* config,
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<IndexedFile>> indexes = Parse(config, file_consumer_shared, index_request->path, index_request->args);
|
||||
std::vector<std::unique_ptr<IndexedFile>> indexes = Parse(config, file_consumer_shared, index_request->path, import_file, index_request->args);
|
||||
time.ResetAndPrint("Parsing/indexing " + index_request->path);
|
||||
|
||||
for (auto& current_index : indexes) {
|
||||
std::cerr << "Got index for " << current_index->path << std::endl;
|
||||
|
||||
project->UpdateFileState(current_index->path, current_index->import_file, current_index->last_modification_time);
|
||||
|
||||
std::unique_ptr<IndexedFile> old_index = LoadCachedFile(config, current_index->path);
|
||||
time.ResetAndPrint("Loading cached index");
|
||||
|
||||
|
@ -192,6 +192,9 @@ struct IndexParam {
|
||||
// Only use this when strictly needed (ie, primary translation unit is
|
||||
// needed). Most logic should get the IndexedFile instance via
|
||||
// |file_consumer|.
|
||||
//
|
||||
// This can be null if we're not generating an index for the primary
|
||||
// translation unit.
|
||||
IndexedFile* primary_file;
|
||||
|
||||
FileConsumer* file_consumer;
|
||||
@ -698,7 +701,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||
if (!db)
|
||||
return;
|
||||
|
||||
if (is_first_time_visiting_file)
|
||||
if (is_first_time_visiting_file && param->primary_file)
|
||||
param->primary_file->dependencies.push_back(db->path);
|
||||
|
||||
NamespaceHelper* ns = ¶m->ns;
|
||||
@ -1156,7 +1159,7 @@ void indexEntityReference(CXClientData client_data,
|
||||
if (!db)
|
||||
return;
|
||||
|
||||
if (is_first_time_visiting_file)
|
||||
if (is_first_time_visiting_file && param->primary_file)
|
||||
param->primary_file->dependencies.push_back(db->path);
|
||||
|
||||
// ref->cursor mainFile=0
|
||||
@ -1332,17 +1335,21 @@ void indexEntityReference(CXClientData client_data,
|
||||
|
||||
|
||||
|
||||
std::vector<std::unique_ptr<IndexedFile>> Parse(
|
||||
IndexerConfig* config, FileConsumer::SharedState* file_consumer_shared,
|
||||
std::string desired_index_file, std::string import_file, std::vector<std::string> args,
|
||||
bool dump_ast) {
|
||||
|
||||
std::vector<std::unique_ptr<IndexedFile>> Parse(IndexerConfig* config, FileConsumer::SharedState* file_consumer_shared, std::string filename, std::vector<std::string> args, bool dump_ast) {
|
||||
if (!config->enableIndexing)
|
||||
return {};
|
||||
|
||||
filename = NormalizePath(filename);
|
||||
desired_index_file = NormalizePath(desired_index_file);
|
||||
import_file = NormalizePath(import_file);
|
||||
|
||||
clang::Index index(0 /*excludeDeclarationsFromPCH*/,
|
||||
0 /*displayDiagnostics*/);
|
||||
std::vector<CXUnsavedFile> unsaved_files;
|
||||
clang::TranslationUnit tu(config, index, filename, args, unsaved_files, CXTranslationUnit_KeepGoing);
|
||||
clang::TranslationUnit tu(config, index, import_file, args, unsaved_files, CXTranslationUnit_KeepGoing);
|
||||
|
||||
if (dump_ast)
|
||||
Dump(tu.document_cursor());
|
||||
@ -1357,16 +1364,21 @@ std::vector<std::unique_ptr<IndexedFile>> Parse(IndexerConfig* config, FileConsu
|
||||
FileConsumer file_consumer(file_consumer_shared);
|
||||
IndexParam param(&file_consumer);
|
||||
|
||||
CXFile file = clang_getFile(tu.cx_tu, filename.c_str());
|
||||
CXFile file = clang_getFile(tu.cx_tu, desired_index_file.c_str());
|
||||
param.primary_file = file_consumer.ForceLocal(file);
|
||||
if (desired_index_file != import_file)
|
||||
param.primary_file = nullptr;
|
||||
|
||||
std::cerr << "!! [START] Indexing " << filename << std::endl;
|
||||
if (desired_index_file != import_file)
|
||||
std::cerr << "!! [START] Indexing desired_index_file=" << desired_index_file << ", import_file=" << import_file << std::endl;
|
||||
else
|
||||
std::cerr << "!! [START] Indexing " << desired_index_file << std::endl;
|
||||
CXIndexAction index_action = clang_IndexAction_create(index.cx_index);
|
||||
clang_indexTranslationUnit(index_action, ¶m, callbacks, sizeof(callbacks),
|
||||
CXIndexOpt_IndexFunctionLocalSymbols | CXIndexOpt_SkipParsedBodiesInSession | CXIndexOpt_IndexImplicitTemplateInstantiations,
|
||||
tu.cx_tu);
|
||||
clang_IndexAction_dispose(index_action);
|
||||
std::cerr << "!! [END] Indexing " << filename << std::endl;
|
||||
std::cerr << "!! [END] Indexing " << desired_index_file << std::endl;
|
||||
|
||||
auto result = param.file_consumer->TakeLocalState();
|
||||
for (auto& entry : result) {
|
||||
@ -1378,27 +1390,28 @@ std::vector<std::unique_ptr<IndexedFile>> Parse(IndexerConfig* config, FileConsu
|
||||
entry->id_cache.primary_file = entry->path;
|
||||
|
||||
entry->last_modification_time = GetLastModificationTime(entry->path);
|
||||
entry->import_file = import_file;
|
||||
}
|
||||
|
||||
// TODO: Fix interesting checks.
|
||||
for (auto& entry : result) {
|
||||
for (auto& type : entry->types) {
|
||||
if (!type.HasInterestingState()) {
|
||||
std::cerr << "!!!! NO INTERESTING STATE FOR " << entry->path << " of !!! " << filename << std::endl;
|
||||
std::cerr << "!!!! NO INTERESTING STATE FOR " << entry->path << " of !!! " << desired_index_file << std::endl;
|
||||
std::cerr << "!!!! USR " << type.def.usr << std::endl;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
for (auto& func : entry->funcs) {
|
||||
if (!func.HasInterestingState()) {
|
||||
std::cerr << "!!!! NO INTERESTING STATE FOR " << entry->path << " of !!! " << filename << std::endl;
|
||||
std::cerr << "!!!! NO INTERESTING STATE FOR " << entry->path << " of !!! " << desired_index_file << std::endl;
|
||||
std::cerr << "!!!! USR " << func.def.usr << std::endl;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
for (auto& var : entry->vars) {
|
||||
if (!var.HasInterestingState()) {
|
||||
std::cerr << "!!!! NO INTERESTING STATE FOR " << entry->path << " of !!! " << filename << std::endl;
|
||||
std::cerr << "!!!! NO INTERESTING STATE FOR " << entry->path << " of !!! " << desired_index_file << std::endl;
|
||||
std::cerr << "!!!! USR " << var.def.usr << std::endl;
|
||||
assert(false);
|
||||
}
|
||||
|
@ -471,6 +471,12 @@ struct IndexedFile {
|
||||
std::string path;
|
||||
int64_t last_modification_time = 0;
|
||||
|
||||
// The path to the translation unit cc file which caused the creation of this
|
||||
// IndexedFile. When parsing a translation unit we generate many IndexedFile
|
||||
// instances (ie, each header has a separate one). When the user edits a
|
||||
// header we need to lookup the original translation unit and reindex that.
|
||||
std::string import_file;
|
||||
|
||||
// The content of |path| when it was indexed.
|
||||
//std::string content;
|
||||
|
||||
@ -494,5 +500,10 @@ struct IndexedFile {
|
||||
std::string ToString();
|
||||
};
|
||||
|
||||
std::vector<std::unique_ptr<IndexedFile>> Parse(IndexerConfig* config, FileConsumer::SharedState* file_consumer_shared, std::string filename, std::vector<std::string> args, bool dump_ast = false);
|
||||
// |import_file| is the cc file which is what gets passed to clang.
|
||||
// |desired_index_file| is the (h or cc) file which has actually changed.
|
||||
std::vector<std::unique_ptr<IndexedFile>> Parse(
|
||||
IndexerConfig* config, FileConsumer::SharedState* file_consumer_shared,
|
||||
std::string desired_index_file, std::string import_file, std::vector<std::string> args,
|
||||
bool dump_ast = false);
|
||||
void IndexInit();
|
||||
|
@ -28,12 +28,10 @@ TranslationUnit::TranslationUnit(
|
||||
for (const std::string& arg : config->extraClangArguments)
|
||||
args.push_back(arg.c_str());
|
||||
|
||||
#if false
|
||||
std::cerr << "Parsing " << filepath << " with args ";
|
||||
for (const auto& arg : args)
|
||||
std::cerr << arg << " ";
|
||||
std::cerr << std::endl;
|
||||
#endif
|
||||
|
||||
CXErrorCode error_code = clang_parseTranslationUnit2(
|
||||
index.cx_index,
|
||||
|
@ -250,6 +250,7 @@ void Project::Load(const std::string& directory) {
|
||||
}
|
||||
|
||||
optional<Project::Entry> Project::FindCompilationEntryForFile(const std::string& filename) {
|
||||
// TODO: There might be a lot of thread contention here.
|
||||
std::lock_guard<std::mutex> lock(entries_modification_mutex_);
|
||||
|
||||
auto it = absolute_path_to_entry_index_.find(filename);
|
||||
@ -258,19 +259,32 @@ optional<Project::Entry> Project::FindCompilationEntryForFile(const std::string&
|
||||
return nullopt;
|
||||
}
|
||||
|
||||
void Project::UpdateModificationTime(const std::string& filename, uint64_t modification_time) {
|
||||
// TODO: There might be a lot of thread contention here.
|
||||
std::lock_guard<std::mutex> lock(entries_modification_mutex_);
|
||||
|
||||
auto it = absolute_path_to_entry_index_.find(filename);
|
||||
if (it != absolute_path_to_entry_index_.end()) {
|
||||
entries[it->second].last_modification_time = modification_time;
|
||||
void Project::UpdateFileState(const std::string& filename, const std::string& import_file, uint64_t modification_time) {
|
||||
{
|
||||
// TODO: There might be a lot of thread contention here.
|
||||
std::lock_guard<std::mutex> lock(entries_modification_mutex_);
|
||||
auto it = absolute_path_to_entry_index_.find(filename);
|
||||
if (it != absolute_path_to_entry_index_.end()) {
|
||||
auto& entry = entries[it->second];
|
||||
entry.import_file = import_file;
|
||||
entry.last_modification_time = modification_time;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
{
|
||||
optional<Project::Entry> import_entry = FindCompilationEntryForFile(import_file);
|
||||
|
||||
Project::Entry entry;
|
||||
entry.filename = filename;
|
||||
if (import_entry)
|
||||
entry.args = import_entry->args;
|
||||
|
||||
entry.import_file = import_file;
|
||||
entry.last_modification_time = modification_time;
|
||||
|
||||
// TODO: There might be a lot of thread contention here.
|
||||
std::lock_guard<std::mutex> lock(entries_modification_mutex_);
|
||||
absolute_path_to_entry_index_[filename] = entries.size();
|
||||
entries.push_back(entry);
|
||||
}
|
||||
|
@ -14,6 +14,8 @@ struct Project {
|
||||
struct Entry {
|
||||
std::string filename;
|
||||
std::vector<std::string> args;
|
||||
|
||||
std::string import_file;
|
||||
optional<uint64_t> last_modification_time;
|
||||
};
|
||||
|
||||
@ -33,6 +35,6 @@ struct Project {
|
||||
optional<Entry> FindCompilationEntryForFile(const std::string& filename);
|
||||
|
||||
// Update the modification time for the given filename. This is thread-safe.
|
||||
void UpdateModificationTime(const std::string& filename, uint64_t modification_time);
|
||||
void UpdateFileState(const std::string& filename, const std::string& import_file, uint64_t modification_time);
|
||||
};
|
||||
|
||||
|
@ -229,6 +229,7 @@ void Reflect(TVisitor& visitor, IndexedFile& value) {
|
||||
if (!gTestOutputMode) {
|
||||
REFLECT_MEMBER(version);
|
||||
REFLECT_MEMBER(last_modification_time);
|
||||
REFLECT_MEMBER(import_file);
|
||||
}
|
||||
REFLECT_MEMBER(dependencies);
|
||||
REFLECT_MEMBER(types);
|
||||
|
20
src/test.cc
20
src/test.cc
@ -137,14 +137,18 @@ void RunTests() {
|
||||
|
||||
// Run test.
|
||||
std::cout << "[START] " << path << std::endl;
|
||||
std::vector<std::unique_ptr<IndexedFile>> dbs = Parse(&config, &file_consumer_shared, path, {
|
||||
"-xc++",
|
||||
"-std=c++11",
|
||||
"-IC:/Users/jacob/Desktop/superindex/indexer/third_party/",
|
||||
"-IC:/Users/jacob/Desktop/superindex/indexer/third_party/doctest/",
|
||||
"-IC:/Users/jacob/Desktop/superindex/indexer/third_party/rapidjson/include",
|
||||
"-IC:/Users/jacob/Desktop/superindex/indexer/src"
|
||||
}, false /*dump_ast*/);
|
||||
std::vector<std::unique_ptr<IndexedFile>> dbs = Parse(
|
||||
&config, &file_consumer_shared,
|
||||
path, path,
|
||||
{
|
||||
"-xc++",
|
||||
"-std=c++11",
|
||||
"-IC:/Users/jacob/Desktop/superindex/indexer/third_party/",
|
||||
"-IC:/Users/jacob/Desktop/superindex/indexer/third_party/doctest/",
|
||||
"-IC:/Users/jacob/Desktop/superindex/indexer/third_party/rapidjson/include",
|
||||
"-IC:/Users/jacob/Desktop/superindex/indexer/src"
|
||||
},
|
||||
false /*dump_ast*/);
|
||||
|
||||
#if false
|
||||
for (auto& db : dbs) {
|
||||
|
Loading…
Reference in New Issue
Block a user