diff --git a/foo/.vscode/settings.json b/foo/.vscode/settings.json index 3cd417bf..7c74e0aa 100644 --- a/foo/.vscode/settings.json +++ b/foo/.vscode/settings.json @@ -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" } \ No newline at end of file diff --git a/foo/_empty_test.cc b/foo/_empty_test.cc deleted file mode 100644 index d3b3f523..00000000 --- a/foo/_empty_test.cc +++ /dev/null @@ -1,35 +0,0 @@ -#if false -#include -#include - -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 foo); - float MemberFunc2(int a, char b, std::vector foo); - - // The names are some extra state. - std::vector names; -}; - -int MyBar::foobez; - -int foo() { - int a = 10; - MyBar foooo; - MyBar f; - MyBar f2; -} - -float MyBar::MemberFunc(int a, char b, std::vector foo) { - this->x = 100; - this->MemberFunc(0, 0, {}); - - return ::foo(); -} -#endif \ No newline at end of file diff --git a/foo/a.cc b/foo/a.cc deleted file mode 100644 index 928c8ff1..00000000 --- a/foo/a.cc +++ /dev/null @@ -1,111 +0,0 @@ -#if false -/* -abc -daaa -faf -dakkdakk -abaa -*/ -#include - -#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 \ No newline at end of file diff --git a/foo/a.h b/foo/a.h index cd6e7b7f..1db6b5e0 100644 --- a/foo/a.h +++ b/foo/a.h @@ -1 +1,3 @@ -a,b,c \ No newline at end of file + + +void foobar() {} \ No newline at end of file diff --git a/foo/b.cc b/foo/b.cc index 2c226e7f..7038852a 100644 --- a/foo/b.cc +++ b/foo/b.cc @@ -1,4 +1,8 @@ +#include "a.h" enum Foo { - #include "a.h" -}; \ No newline at end of file +}; + +void faz() { + foobar(); +} \ No newline at end of file diff --git a/src/command_line.cc b/src/command_line.cc index c254da56..0045fee2 100644 --- a/src/command_line.cc +++ b/src/command_line.cc @@ -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 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> indexes = Parse(config, file_consumer_shared, index_request->path, index_request->args); + std::vector> 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 old_index = LoadCachedFile(config, current_index->path); time.ResetAndPrint("Loading cached index"); diff --git a/src/indexer.cc b/src/indexer.cc index fa02e8d0..e38722d4 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -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> Parse( + IndexerConfig* config, FileConsumer::SharedState* file_consumer_shared, + std::string desired_index_file, std::string import_file, std::vector args, + bool dump_ast) { -std::vector> Parse(IndexerConfig* config, FileConsumer::SharedState* file_consumer_shared, std::string filename, std::vector 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 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> 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> 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); } diff --git a/src/indexer.h b/src/indexer.h index 100eb821..2ca728a8 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -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> Parse(IndexerConfig* config, FileConsumer::SharedState* file_consumer_shared, std::string filename, std::vector 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> Parse( + IndexerConfig* config, FileConsumer::SharedState* file_consumer_shared, + std::string desired_index_file, std::string import_file, std::vector args, + bool dump_ast = false); void IndexInit(); diff --git a/src/libclangmm/TranslationUnit.cc b/src/libclangmm/TranslationUnit.cc index 4313e4c5..e84257fc 100644 --- a/src/libclangmm/TranslationUnit.cc +++ b/src/libclangmm/TranslationUnit.cc @@ -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, diff --git a/src/project.cc b/src/project.cc index 9420bdcf..65b6e9ac 100644 --- a/src/project.cc +++ b/src/project.cc @@ -250,6 +250,7 @@ void Project::Load(const std::string& directory) { } optional Project::FindCompilationEntryForFile(const std::string& filename) { + // TODO: There might be a lot of thread contention here. std::lock_guard lock(entries_modification_mutex_); auto it = absolute_path_to_entry_index_.find(filename); @@ -258,19 +259,32 @@ optional 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 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 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 import_entry = FindCompilationEntryForFile(import_file); + Project::Entry entry; entry.filename = filename; - entry.last_modification_time = modification_time; + 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 lock(entries_modification_mutex_); absolute_path_to_entry_index_[filename] = entries.size(); entries.push_back(entry); } diff --git a/src/project.h b/src/project.h index b71d520d..3727ed76 100644 --- a/src/project.h +++ b/src/project.h @@ -14,6 +14,8 @@ struct Project { struct Entry { std::string filename; std::vector args; + + std::string import_file; optional last_modification_time; }; @@ -33,6 +35,6 @@ struct Project { optional 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); }; diff --git a/src/serializer.cc b/src/serializer.cc index 440e4a9c..c990e291 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -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); diff --git a/src/test.cc b/src/test.cc index cabd727e..5abfe7ce 100644 --- a/src/test.cc +++ b/src/test.cc @@ -137,14 +137,18 @@ void RunTests() { // Run test. std::cout << "[START] " << path << std::endl; - std::vector> 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> 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) {