Fix reindexing for header files

This commit is contained in:
Jacob Dufault 2017-04-20 00:25:38 -07:00
parent d83b1591a4
commit 4d9567a0c2
13 changed files with 92 additions and 184 deletions

View File

@ -1,5 +1,5 @@
// Place your settings in this file to overwrite default and user settings. // Place your settings in this file to overwrite default and user settings.
{ {
"editor.lineNumbers": "on", "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"
} }

View File

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

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

View File

@ -1 +1,3 @@
a,b,c
void foobar() {}

View File

@ -1,4 +1,8 @@
#include "a.h"
enum Foo { enum Foo {
#include "a.h"
}; };
void faz() {
foobar();
}

View File

@ -896,7 +896,7 @@ bool IndexMain_DoIndex(IndexerConfig* config,
queue_do_index->PriorityEnqueue(std::move(dep_index_request)); 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)); Index_DoIdMap response(nullptr, std::move(old_index));
queue_do_id_map->Enqueue(std::move(response)); queue_do_id_map->Enqueue(std::move(response));
@ -912,10 +912,13 @@ bool IndexMain_DoIndex(IndexerConfig* config,
} }
// Parse request and send a response. // Parse request and send a response.
std::string import_file = index_request->path;
// Skip index if file modification time didn't change. // Skip index if file modification time didn't change.
optional<Project::Entry> entry = project->FindCompilationEntryForFile(index_request->path); optional<Project::Entry> entry = project->FindCompilationEntryForFile(index_request->path);
if (entry && entry->last_modification_time) { if (entry && entry->last_modification_time) {
import_file = entry->import_file;
int64_t modification_time = GetLastModificationTime(index_request->path); int64_t modification_time = GetLastModificationTime(index_request->path);
if (modification_time == *entry->last_modification_time) { if (modification_time == *entry->last_modification_time) {
time.ResetAndPrint("Skipping index update on " + index_request->path + " since file modification time has not changed"); 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); time.ResetAndPrint("Parsing/indexing " + index_request->path);
for (auto& current_index : indexes) { for (auto& current_index : indexes) {
std::cerr << "Got index for " << current_index->path << std::endl; 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); std::unique_ptr<IndexedFile> old_index = LoadCachedFile(config, current_index->path);
time.ResetAndPrint("Loading cached index"); time.ResetAndPrint("Loading cached index");

View File

@ -192,6 +192,9 @@ struct IndexParam {
// Only use this when strictly needed (ie, primary translation unit is // Only use this when strictly needed (ie, primary translation unit is
// needed). Most logic should get the IndexedFile instance via // needed). Most logic should get the IndexedFile instance via
// |file_consumer|. // |file_consumer|.
//
// This can be null if we're not generating an index for the primary
// translation unit.
IndexedFile* primary_file; IndexedFile* primary_file;
FileConsumer* file_consumer; FileConsumer* file_consumer;
@ -698,7 +701,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
if (!db) if (!db)
return; return;
if (is_first_time_visiting_file) if (is_first_time_visiting_file && param->primary_file)
param->primary_file->dependencies.push_back(db->path); param->primary_file->dependencies.push_back(db->path);
NamespaceHelper* ns = &param->ns; NamespaceHelper* ns = &param->ns;
@ -1156,7 +1159,7 @@ void indexEntityReference(CXClientData client_data,
if (!db) if (!db)
return; return;
if (is_first_time_visiting_file) if (is_first_time_visiting_file && param->primary_file)
param->primary_file->dependencies.push_back(db->path); param->primary_file->dependencies.push_back(db->path);
// ref->cursor mainFile=0 // 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) if (!config->enableIndexing)
return {}; return {};
filename = NormalizePath(filename); desired_index_file = NormalizePath(desired_index_file);
import_file = NormalizePath(import_file);
clang::Index index(0 /*excludeDeclarationsFromPCH*/, clang::Index index(0 /*excludeDeclarationsFromPCH*/,
0 /*displayDiagnostics*/); 0 /*displayDiagnostics*/);
std::vector<CXUnsavedFile> unsaved_files; 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) if (dump_ast)
Dump(tu.document_cursor()); Dump(tu.document_cursor());
@ -1357,16 +1364,21 @@ std::vector<std::unique_ptr<IndexedFile>> Parse(IndexerConfig* config, FileConsu
FileConsumer file_consumer(file_consumer_shared); FileConsumer file_consumer(file_consumer_shared);
IndexParam param(&file_consumer); 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); 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); CXIndexAction index_action = clang_IndexAction_create(index.cx_index);
clang_indexTranslationUnit(index_action, &param, callbacks, sizeof(callbacks), clang_indexTranslationUnit(index_action, &param, callbacks, sizeof(callbacks),
CXIndexOpt_IndexFunctionLocalSymbols | CXIndexOpt_SkipParsedBodiesInSession | CXIndexOpt_IndexImplicitTemplateInstantiations, CXIndexOpt_IndexFunctionLocalSymbols | CXIndexOpt_SkipParsedBodiesInSession | CXIndexOpt_IndexImplicitTemplateInstantiations,
tu.cx_tu); tu.cx_tu);
clang_IndexAction_dispose(index_action); 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(); auto result = param.file_consumer->TakeLocalState();
for (auto& entry : result) { 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->id_cache.primary_file = entry->path;
entry->last_modification_time = GetLastModificationTime(entry->path); entry->last_modification_time = GetLastModificationTime(entry->path);
entry->import_file = import_file;
} }
// TODO: Fix interesting checks. // TODO: Fix interesting checks.
for (auto& entry : result) { for (auto& entry : result) {
for (auto& type : entry->types) { for (auto& type : entry->types) {
if (!type.HasInterestingState()) { 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; std::cerr << "!!!! USR " << type.def.usr << std::endl;
assert(false); assert(false);
} }
} }
for (auto& func : entry->funcs) { for (auto& func : entry->funcs) {
if (!func.HasInterestingState()) { 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; std::cerr << "!!!! USR " << func.def.usr << std::endl;
assert(false); assert(false);
} }
} }
for (auto& var : entry->vars) { for (auto& var : entry->vars) {
if (!var.HasInterestingState()) { 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; std::cerr << "!!!! USR " << var.def.usr << std::endl;
assert(false); assert(false);
} }

View File

@ -471,6 +471,12 @@ struct IndexedFile {
std::string path; std::string path;
int64_t last_modification_time = 0; 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. // The content of |path| when it was indexed.
//std::string content; //std::string content;
@ -494,5 +500,10 @@ struct IndexedFile {
std::string ToString(); 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(); void IndexInit();

View File

@ -28,12 +28,10 @@ TranslationUnit::TranslationUnit(
for (const std::string& arg : config->extraClangArguments) for (const std::string& arg : config->extraClangArguments)
args.push_back(arg.c_str()); args.push_back(arg.c_str());
#if false
std::cerr << "Parsing " << filepath << " with args "; std::cerr << "Parsing " << filepath << " with args ";
for (const auto& arg : args) for (const auto& arg : args)
std::cerr << arg << " "; std::cerr << arg << " ";
std::cerr << std::endl; std::cerr << std::endl;
#endif
CXErrorCode error_code = clang_parseTranslationUnit2( CXErrorCode error_code = clang_parseTranslationUnit2(
index.cx_index, index.cx_index,

View File

@ -250,6 +250,7 @@ void Project::Load(const std::string& directory) {
} }
optional<Project::Entry> Project::FindCompilationEntryForFile(const std::string& filename) { 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_); std::lock_guard<std::mutex> lock(entries_modification_mutex_);
auto it = absolute_path_to_entry_index_.find(filename); auto it = absolute_path_to_entry_index_.find(filename);
@ -258,19 +259,32 @@ optional<Project::Entry> Project::FindCompilationEntryForFile(const std::string&
return nullopt; return nullopt;
} }
void Project::UpdateModificationTime(const std::string& filename, uint64_t 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. // TODO: There might be a lot of thread contention here.
std::lock_guard<std::mutex> lock(entries_modification_mutex_); std::lock_guard<std::mutex> lock(entries_modification_mutex_);
auto it = absolute_path_to_entry_index_.find(filename); auto it = absolute_path_to_entry_index_.find(filename);
if (it != absolute_path_to_entry_index_.end()) { if (it != absolute_path_to_entry_index_.end()) {
entries[it->second].last_modification_time = modification_time; 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; Project::Entry entry;
entry.filename = filename; entry.filename = filename;
if (import_entry)
entry.args = import_entry->args;
entry.import_file = import_file;
entry.last_modification_time = modification_time; 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(); absolute_path_to_entry_index_[filename] = entries.size();
entries.push_back(entry); entries.push_back(entry);
} }

View File

@ -14,6 +14,8 @@ struct Project {
struct Entry { struct Entry {
std::string filename; std::string filename;
std::vector<std::string> args; std::vector<std::string> args;
std::string import_file;
optional<uint64_t> last_modification_time; optional<uint64_t> last_modification_time;
}; };
@ -33,6 +35,6 @@ struct Project {
optional<Entry> FindCompilationEntryForFile(const std::string& filename); optional<Entry> FindCompilationEntryForFile(const std::string& filename);
// Update the modification time for the given filename. This is thread-safe. // 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);
}; };

View File

@ -229,6 +229,7 @@ void Reflect(TVisitor& visitor, IndexedFile& value) {
if (!gTestOutputMode) { if (!gTestOutputMode) {
REFLECT_MEMBER(version); REFLECT_MEMBER(version);
REFLECT_MEMBER(last_modification_time); REFLECT_MEMBER(last_modification_time);
REFLECT_MEMBER(import_file);
} }
REFLECT_MEMBER(dependencies); REFLECT_MEMBER(dependencies);
REFLECT_MEMBER(types); REFLECT_MEMBER(types);

View File

@ -137,14 +137,18 @@ void RunTests() {
// Run test. // Run test.
std::cout << "[START] " << path << std::endl; std::cout << "[START] " << path << std::endl;
std::vector<std::unique_ptr<IndexedFile>> dbs = Parse(&config, &file_consumer_shared, path, { std::vector<std::unique_ptr<IndexedFile>> dbs = Parse(
&config, &file_consumer_shared,
path, path,
{
"-xc++", "-xc++",
"-std=c++11", "-std=c++11",
"-IC:/Users/jacob/Desktop/superindex/indexer/third_party/", "-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/doctest/",
"-IC:/Users/jacob/Desktop/superindex/indexer/third_party/rapidjson/include", "-IC:/Users/jacob/Desktop/superindex/indexer/third_party/rapidjson/include",
"-IC:/Users/jacob/Desktop/superindex/indexer/src" "-IC:/Users/jacob/Desktop/superindex/indexer/src"
}, false /*dump_ast*/); },
false /*dump_ast*/);
#if false #if false
for (auto& db : dbs) { for (auto& db : dbs) {