diff --git a/src/file_consumer.cc b/src/file_consumer.cc index eb3a9a7c..680e6ebc 100644 --- a/src/file_consumer.cc +++ b/src/file_consumer.cc @@ -1,36 +1,66 @@ #include "file_consumer.h" #include "indexer.h" +#include "platform.h" #include "utils.h" +namespace { + +std::string FileName(CXFile file) { + CXString cx_name = clang_getFileName(file); + std::string name = clang::ToString(cx_name); + return NormalizePath(name); +} + +} // namespace + +bool operator==(const CXFileUniqueID& a, const CXFileUniqueID& b) { + return a.data[0] == b.data[0] && a.data[1] == b.data[1] && a.data[2] == b.data[2]; +} + FileConsumer::FileConsumer(SharedState* shared_state) : shared_(shared_state) {} -IndexedFile* FileConsumer::TryConsumeFile(const std::string& file, bool* is_first_ownership) { +IndexedFile* FileConsumer::TryConsumeFile(CXFile file, bool* is_first_ownership) { assert(is_first_ownership); + CXFileUniqueID file_id; + if (clang_getFileUniqueID(file, &file_id) != 0) { + std::cerr << "Could not get unique file id for " << FileName(file) << std::endl; + return nullptr; + } + // Try to find cached local result. - auto it = local_.find(file); + auto it = local_.find(file_id); if (it != local_.end()) { *is_first_ownership = false; return it->second.get(); } + std::string file_name = FileName(file); + // No result in local; we need to query global. bool did_insert = false; { std::lock_guard lock(shared_->mutex); - did_insert = shared_->files.insert(file).second; + did_insert = shared_->files.insert(file_name).second; } *is_first_ownership = did_insert; - local_[file] = did_insert ? MakeUnique(file) : nullptr; - return local_[file].get(); + local_[file_id] = did_insert ? MakeUnique(file_name) : nullptr; + return local_[file_id].get(); } -IndexedFile* FileConsumer::ForceLocal(const std::string& file) { - auto it = local_.find(file); +IndexedFile* FileConsumer::ForceLocal(CXFile file) { + CXFileUniqueID file_id; + if (clang_getFileUniqueID(file, &file_id) != 0) { + std::cerr << "Could not get unique file id for " << FileName(file) << std::endl; + return nullptr; + } + + auto it = local_.find(file_id); if (it == local_.end()) - local_[file] = MakeUnique(file); - return local_[file].get(); + local_[file_id] = MakeUnique(FileName(file)); + assert(local_.find(file_id) != local_.end()); + return local_[file_id].get(); } std::vector> FileConsumer::TakeLocalState() { diff --git a/src/file_consumer.h b/src/file_consumer.h index e628b301..671a72f9 100644 --- a/src/file_consumer.h +++ b/src/file_consumer.h @@ -1,11 +1,20 @@ #pragma once +#include "utils.h" + +#include + +#include #include #include #include struct IndexedFile; +// Needed for unordered_map usage below. +MAKE_HASHABLE(CXFileUniqueID, t.data[0], t.data[1], t.data[2]); +bool operator==(const CXFileUniqueID& a, const CXFileUniqueID& b); + // FileConsumer is used by the indexer. When it encouters a file, it tries to // take ownership over it. If the indexer has ownership over a file, it will // produce an index, otherwise, it will emit nothing for that declarations @@ -27,15 +36,15 @@ struct FileConsumer { // Returns IndexedFile for the file or nullptr. |is_first_ownership| is set // to true iff the function just took ownership over the file. Otherwise it // is set to false. - IndexedFile* TryConsumeFile(const std::string& file, bool* is_first_ownership); + IndexedFile* TryConsumeFile(CXFile file, bool* is_first_ownership); // Forcibly create a local file, even if it has already been parsed. - IndexedFile* ForceLocal(const std::string& file); + IndexedFile* ForceLocal(CXFile file); // Returns and passes ownership of all local state. std::vector> TakeLocalState(); private: - std::unordered_map> local_; + std::unordered_map> local_; SharedState* shared_; }; \ No newline at end of file diff --git a/src/indexer.cc b/src/indexer.cc index 2e9f1c49..69e82cab 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -711,10 +711,9 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // TODO: Use clang_getFileUniqueID CXFile file; clang_getSpellingLocation(clang_indexLoc_getCXSourceLocation(decl->loc), &file, nullptr, nullptr, nullptr); - std::string filename = NormalizePath(clang::ToString(clang_getFileName(file))); IndexParam* param = static_cast(client_data); bool is_first_time_visiting_file = false; - IndexedFile* db = param->file_consumer->TryConsumeFile(filename, &is_first_time_visiting_file); + IndexedFile* db = param->file_consumer->TryConsumeFile(file, &is_first_time_visiting_file); if (!db) return; @@ -1170,10 +1169,9 @@ void indexEntityReference(CXClientData client_data, // TODO: Use clang_getFileUniqueID CXFile file; clang_getSpellingLocation(clang_indexLoc_getCXSourceLocation(ref->loc), &file, nullptr, nullptr, nullptr); - std::string filename = NormalizePath(clang::ToString(clang_getFileName(file))); IndexParam* param = static_cast(client_data); bool is_first_time_visiting_file = false; - IndexedFile* db = param->file_consumer->TryConsumeFile(filename, &is_first_time_visiting_file); + IndexedFile* db = param->file_consumer->TryConsumeFile(file, &is_first_time_visiting_file); if (!db) return; @@ -1415,7 +1413,8 @@ std::vector> Parse(FileConsumer* file_consumer, std IndexParam param(file_consumer); - param.primary_file = file_consumer->ForceLocal(filename); + CXFile file = clang_getFile(tu.cx_tu, filename.c_str()); + param.primary_file = file_consumer->ForceLocal(file); std::cerr << "!! [START] Indexing " << filename << std::endl; CXIndexAction index_action = clang_IndexAction_create(index.cx_index);