This commit is contained in:
Jacob Dufault 2017-07-29 21:24:02 -07:00
parent c83b9eab77
commit ee20d79dcc
10 changed files with 913 additions and 436 deletions

View File

@ -7,4 +7,7 @@
"cquery.whitelist": [ "cquery.whitelist": [
//".*platform.*.cc" //".*platform.*.cc"
], ],
"cquery.launch.command": "cquery.exe",
"cquery.launch.workingDirectory": "C:/Users/jacob/Desktop/cquery/x64/Release",
"cquery.launch.autoRestart": false
} }

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,8 @@
#include "serializer.h" #include "serializer.h"
#include "timer.h" #include "timer.h"
#include <loguru.hpp>
#include <algorithm> #include <algorithm>
#include <chrono> #include <chrono>
@ -89,6 +91,11 @@ struct NamespaceHelper {
}; };
struct IndexParam { struct IndexParam {
std::unordered_set<CXFile> seen_cx_files;
std::vector<std::string> seen_files;
std::unordered_map<std::string, std::string> file_contents;
std::unordered_map<std::string, int64_t> file_modification_times;
// 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 IndexFile instance via // needed). Most logic should get the IndexFile instance via
// |file_consumer|. // |file_consumer|.
@ -109,11 +116,28 @@ IndexFile* ConsumeFile(IndexParam* param, CXFile file) {
bool is_first_ownership = false; bool is_first_ownership = false;
IndexFile* db = param->file_consumer->TryConsumeFile(file, &is_first_ownership); IndexFile* db = param->file_consumer->TryConsumeFile(file, &is_first_ownership);
// Mark dependency in primary file. If primary_file is null that means we're // If this is the first time we have seen the file (ignoring if we are
// doing a re-index in which case the dependency has already been established // generating an index for it):
// in a previous index run. if (param->seen_cx_files.insert(file).second) {
if (is_first_ownership && param->primary_file) std::string file_name = FileName(file);
param->primary_file->dependencies.push_back(db->path);
// Add to all files we have seen so we can generate proper dependency
// graph.
param->seen_files.push_back(file_name);
// Set modification time.
param->file_modification_times[file_name] = GetLastModificationTime(file_name);
// Capture file contents in |param->file_contents| if it was not specified
// at the start of indexing.
if (db && param->file_contents.find(file_name) == param->file_contents.end()) {
optional<std::string> content = ReadContent(file_name);
if (content)
param->file_contents[file_name] = *content;
else
LOG_S(ERROR) << "[indexer] Failed to read file content for " << file_name;
}
}
if (is_first_ownership) { if (is_first_ownership) {
// Report skipped source range list. // Report skipped source range list.
@ -1532,13 +1556,13 @@ void indexEntityReference(CXClientData client_data,
FileContents::FileContents(const std::string& path, const std::string& content) : path(path), content(content) {}
std::vector<std::unique_ptr<IndexFile>> Parse( std::vector<std::unique_ptr<IndexFile>> Parse(
Config* config, FileConsumer::SharedState* file_consumer_shared, Config* config, FileConsumer::SharedState* file_consumer_shared,
std::string file, std::string file,
std::vector<std::string> args, std::vector<std::string> args,
const std::string& file_contents_path, std::vector<FileContents> file_contents,
const optional<std::string>& file_contents,
PerformanceImportFile* perf, PerformanceImportFile* perf,
clang::Index* index, clang::Index* index,
bool dump_ast) { bool dump_ast) {
@ -1550,17 +1574,15 @@ std::vector<std::unique_ptr<IndexFile>> Parse(
Timer timer; Timer timer;
//clang::Index index(0 /*excludeDeclarationsFromPCH*/,
// 0 /*displayDiagnostics*/);
std::vector<CXUnsavedFile> unsaved_files; std::vector<CXUnsavedFile> unsaved_files;
if (file_contents) { for (const FileContents& contents : file_contents) {
CXUnsavedFile unsaved; CXUnsavedFile unsaved;
unsaved.Filename = file_contents_path.c_str(); unsaved.Filename = contents.path.c_str();
unsaved.Contents = file_contents->c_str(); unsaved.Contents = contents.content.c_str();
unsaved.Length = (unsigned long)file_contents->size(); unsaved.Length = (unsigned long)contents.content.size();
unsaved_files.push_back(unsaved); unsaved_files.push_back(unsaved);
} }
clang::TranslationUnit tu(index, file, args, unsaved_files, CXTranslationUnit_KeepGoing | CXTranslationUnit_DetailedPreprocessingRecord); clang::TranslationUnit tu(index, file, args, unsaved_files, CXTranslationUnit_KeepGoing | CXTranslationUnit_DetailedPreprocessingRecord);
if (tu.did_fail) { if (tu.did_fail) {
std::cerr << "!! Failed creating translation unit for " << file << std::endl; std::cerr << "!! Failed creating translation unit for " << file << std::endl;
@ -1590,6 +1612,7 @@ std::vector<std::unique_ptr<IndexFile>> Parse(
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 " << file << std::endl; //std::cerr << "!! [END] Indexing " << file << std::endl;
@ -1598,10 +1621,25 @@ std::vector<std::unique_ptr<IndexFile>> Parse(
perf->index_build = timer.ElapsedMicrosecondsAndReset(); perf->index_build = timer.ElapsedMicrosecondsAndReset();
auto result = param.file_consumer->TakeLocalState(); auto result = param.file_consumer->TakeLocalState();
for (auto& entry : result) { for (std::unique_ptr<IndexFile>& entry : result) {
entry->last_modification_time = GetLastModificationTime(entry->path);
entry->import_file = file; entry->import_file = file;
entry->args = args; entry->args = args;
// Update file contents and modification time.
entry->file_contents_ = param.file_contents[entry->path];
entry->last_modification_time = param.file_modification_times[entry->path];
// Update dependencies for the file. Do not include the file in its own
// dependency set.
entry->dependencies = param.seen_files;
entry->dependencies.erase(std::find(
entry->dependencies.begin(), entry->dependencies.end(), entry->path));
// Make sure we are using correct file contents.
for (const FileContents& contents : file_contents) {
if (entry->path == contents.path)
entry->file_contents_ = contents.content;
}
} }
return result; return result;

View File

@ -482,6 +482,8 @@ struct IndexFile {
// Diagnostics found when indexing this file. Not serialized. // Diagnostics found when indexing this file. Not serialized.
NonElidedVector<lsDiagnostic> diagnostics_; NonElidedVector<lsDiagnostic> diagnostics_;
// File contents at the time of index. Not serialized.
std::string file_contents_;
IndexFile(const std::string& path); IndexFile(const std::string& path);
@ -498,6 +500,13 @@ struct IndexFile {
std::string ToString(); std::string ToString();
}; };
struct FileContents {
std::string path;
std::string content;
FileContents(const std::string& path, const std::string& content);
};
// |import_file| is the cc file which is what gets passed to clang. // |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. // |desired_index_file| is the (h or cc) file which has actually changed.
// |dependencies| are the existing dependencies of |import_file| if this is a reparse. // |dependencies| are the existing dependencies of |import_file| if this is a reparse.
@ -505,8 +514,7 @@ std::vector<std::unique_ptr<IndexFile>> Parse(
Config* config, FileConsumer::SharedState* file_consumer_shared, Config* config, FileConsumer::SharedState* file_consumer_shared,
std::string file, std::string file,
std::vector<std::string> args, std::vector<std::string> args,
const std::string& file_contents_path, std::vector<FileContents> file_contents,
const optional<std::string>& file_contents,
PerformanceImportFile* perf, PerformanceImportFile* perf,
clang::Index* index, clang::Index* index,
bool dump_ast = false); bool dump_ast = false);

View File

@ -4,6 +4,7 @@
#include <optional.h> #include <optional.h>
#include <doctest/doctest.h> #include <doctest/doctest.h>
#include <loguru.hpp>
#include <cassert> #include <cassert>
#include <cstdint> #include <cstdint>
@ -304,6 +305,7 @@ QueryVarId GetQueryVarIdFromUsr(QueryDatabase* query_db, const Usr& usr) {
IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids) IdMap::IdMap(QueryDatabase* query_db, const IdCache& local_ids)
: local_ids(local_ids) { : local_ids(local_ids) {
LOG_S(INFO) << "Creating IdMap for " << local_ids.primary_file;
primary_file = GetQueryFileIdFromPath(query_db, local_ids.primary_file); primary_file = GetQueryFileIdFromPath(query_db, local_ids.primary_file);
cached_type_ids_.resize(local_ids.type_id_to_usr.size()); cached_type_ids_.resize(local_ids.type_id_to_usr.size());

View File

@ -136,7 +136,7 @@ void RunTests() {
"-isystemC:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.10.25017/include", "-isystemC:/Program Files (x86)/Microsoft Visual Studio/2017/Community/VC/Tools/MSVC/14.10.25017/include",
"-isystemC:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt" "-isystemC:/Program Files (x86)/Windows Kits/10/Include/10.0.15063.0/ucrt"
}, },
"", nullopt, {},
&perf, &perf,
&index, &index,
false /*dump_ast*/); false /*dump_ast*/);

View File

@ -8,6 +8,7 @@ enum Foo {
OUTPUT: funky_enum.h OUTPUT: funky_enum.h
{ {
"dependencies": ["C:/Users/jacob/Desktop/cquery/tests/multi_file/funky_enum.cc"],
"types": [{ "types": [{
"id": 0, "id": 0,
"usr": "c:@E@Foo", "usr": "c:@E@Foo",

View File

@ -7,6 +7,7 @@ void Impl() {
/* /*
OUTPUT: header.h OUTPUT: header.h
{ {
"dependencies": ["C:/Users/jacob/Desktop/cquery/tests/multi_file/impl.cc"],
"types": [{ "types": [{
"id": 0, "id": 0,
"usr": "c:@S@Base", "usr": "c:@S@Base",

View File

@ -7,6 +7,7 @@ void impl() {
/* /*
OUTPUT: simple_header.h OUTPUT: simple_header.h
{ {
"dependencies": ["C:/Users/jacob/Desktop/cquery/tests/multi_file/simple_impl.cc"],
"funcs": [{ "funcs": [{
"id": 0, "id": 0,
"usr": "c:@F@header#", "usr": "c:@F@header#",

View File

@ -5,6 +5,7 @@ void Buffer::CreateSharedBuffer() {}
/* /*
OUTPUT: static.h OUTPUT: static.h
{ {
"dependencies": ["C:/Users/jacob/Desktop/cquery/tests/multi_file/static.cc"],
"types": [{ "types": [{
"id": 0, "id": 0,
"usr": "c:@S@Buffer", "usr": "c:@S@Buffer",