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": [
//".*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 "timer.h"
#include <loguru.hpp>
#include <algorithm>
#include <chrono>
@ -89,6 +91,11 @@ struct NamespaceHelper {
};
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
// needed). Most logic should get the IndexFile instance via
// |file_consumer|.
@ -109,11 +116,28 @@ IndexFile* ConsumeFile(IndexParam* param, CXFile file) {
bool is_first_ownership = false;
IndexFile* db = param->file_consumer->TryConsumeFile(file, &is_first_ownership);
// Mark dependency in primary file. If primary_file is null that means we're
// doing a re-index in which case the dependency has already been established
// in a previous index run.
if (is_first_ownership && param->primary_file)
param->primary_file->dependencies.push_back(db->path);
// If this is the first time we have seen the file (ignoring if we are
// generating an index for it):
if (param->seen_cx_files.insert(file).second) {
std::string file_name = FileName(file);
// 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) {
// 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(
Config* config, FileConsumer::SharedState* file_consumer_shared,
std::string file,
std::vector<std::string> args,
const std::string& file_contents_path,
const optional<std::string>& file_contents,
std::vector<FileContents> file_contents,
PerformanceImportFile* perf,
clang::Index* index,
bool dump_ast) {
@ -1550,17 +1574,15 @@ std::vector<std::unique_ptr<IndexFile>> Parse(
Timer timer;
//clang::Index index(0 /*excludeDeclarationsFromPCH*/,
// 0 /*displayDiagnostics*/);
std::vector<CXUnsavedFile> unsaved_files;
if (file_contents) {
for (const FileContents& contents : file_contents) {
CXUnsavedFile unsaved;
unsaved.Filename = file_contents_path.c_str();
unsaved.Contents = file_contents->c_str();
unsaved.Length = (unsigned long)file_contents->size();
unsaved.Filename = contents.path.c_str();
unsaved.Contents = contents.content.c_str();
unsaved.Length = (unsigned long)contents.content.size();
unsaved_files.push_back(unsaved);
}
clang::TranslationUnit tu(index, file, args, unsaved_files, CXTranslationUnit_KeepGoing | CXTranslationUnit_DetailedPreprocessingRecord);
if (tu.did_fail) {
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),
CXIndexOpt_IndexFunctionLocalSymbols | CXIndexOpt_SkipParsedBodiesInSession | CXIndexOpt_IndexImplicitTemplateInstantiations,
tu.cx_tu);
clang_IndexAction_dispose(index_action);
//std::cerr << "!! [END] Indexing " << file << std::endl;
@ -1598,10 +1621,25 @@ std::vector<std::unique_ptr<IndexFile>> Parse(
perf->index_build = timer.ElapsedMicrosecondsAndReset();
auto result = param.file_consumer->TakeLocalState();
for (auto& entry : result) {
entry->last_modification_time = GetLastModificationTime(entry->path);
for (std::unique_ptr<IndexFile>& entry : result) {
entry->import_file = file;
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;

View File

@ -482,6 +482,8 @@ struct IndexFile {
// Diagnostics found when indexing this file. Not serialized.
NonElidedVector<lsDiagnostic> diagnostics_;
// File contents at the time of index. Not serialized.
std::string file_contents_;
IndexFile(const std::string& path);
@ -498,6 +500,13 @@ struct IndexFile {
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.
// |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.
@ -505,8 +514,7 @@ std::vector<std::unique_ptr<IndexFile>> Parse(
Config* config, FileConsumer::SharedState* file_consumer_shared,
std::string file,
std::vector<std::string> args,
const std::string& file_contents_path,
const optional<std::string>& file_contents,
std::vector<FileContents> file_contents,
PerformanceImportFile* perf,
clang::Index* index,
bool dump_ast = false);

View File

@ -4,6 +4,7 @@
#include <optional.h>
#include <doctest/doctest.h>
#include <loguru.hpp>
#include <cassert>
#include <cstdint>
@ -304,6 +305,7 @@ QueryVarId GetQueryVarIdFromUsr(QueryDatabase* query_db, const Usr& usr) {
IdMap::IdMap(QueryDatabase* query_db, const IdCache& 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);
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)/Windows Kits/10/Include/10.0.15063.0/ucrt"
},
"", nullopt,
{},
&perf,
&index,
false /*dump_ast*/);

View File

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

View File

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

View File

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

View File

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