Response on index error. (#319)

This commit is contained in:
scturtle 2018-01-20 15:56:49 +08:00 committed by Fangrui Song
parent 57e95590e8
commit b8a3e089ce
9 changed files with 57 additions and 35 deletions

View File

@ -6,7 +6,7 @@ namespace {
struct ClangIndexer : IIndexer {
~ClangIndexer() override = default;
std::vector<std::unique_ptr<IndexFile>> Index(
optional<std::vector<std::unique_ptr<IndexFile>>> Index(
Config* config,
FileConsumerSharedState* file_consumer_shared,
std::string file,
@ -50,7 +50,7 @@ struct TestIndexer : IIndexer {
~TestIndexer() override = default;
std::vector<std::unique_ptr<IndexFile>> Index(
optional<std::vector<std::unique_ptr<IndexFile>>> Index(
Config* config,
FileConsumerSharedState* file_consumer_shared,
std::string file,
@ -61,7 +61,7 @@ struct TestIndexer : IIndexer {
if (it == indexes.end()) {
// Don't return any indexes for unexpected data.
assert(false && "no indexes");
return {};
return nullopt;
}
// FIXME: allow user to control how many times we return the index for a

View File

@ -1,5 +1,7 @@
#pragma once
#include <optional.h>
#include <initializer_list>
#include <memory>
#include <string>
@ -32,7 +34,7 @@ struct IIndexer {
std::initializer_list<TestEntry> entries);
virtual ~IIndexer() = default;
virtual std::vector<std::unique_ptr<IndexFile>> Index(
virtual optional<std::vector<std::unique_ptr<IndexFile>>> Index(
Config* config,
FileConsumerSharedState* file_consumer_shared,
std::string file,

View File

@ -321,9 +321,8 @@ void ParseFile(Config* config,
ImportManager* import_manager,
ICacheManager* cache_manager,
IIndexer* indexer,
bool is_interactive,
const Project::Entry& entry,
const std::string& entry_contents) {
const Index_Request& request,
const Project::Entry& entry) {
// If the file is inferred, we may not actually be able to parse that file
// directly (ie, a header file, which are not listed in the project). If this
// file is inferred, then try to use the file which originally imported it.
@ -337,33 +336,46 @@ void ParseFile(Config* config,
// Try to load the file from cache.
if (TryLoadFromCache(file_consumer_shared, timestamp_manager,
modification_timestamp_fetcher, import_manager,
cache_manager, is_interactive, entry,
cache_manager, request.is_interactive, entry,
path_to_index) == CacheLoadResult::DoNotParse) {
return;
}
LOG_S(INFO) << "Parsing " << path_to_index;
std::vector<FileContents> file_contents =
PreloadFileContents(cache_manager, entry, entry_contents, path_to_index);
std::vector<FileContents> file_contents = PreloadFileContents(
cache_manager, entry, request.contents, path_to_index);
std::vector<Index_DoIdMap> result;
PerformanceImportFile perf;
std::vector<std::unique_ptr<IndexFile>> indexes =
indexer->Index(config, file_consumer_shared, path_to_index, entry.args,
file_contents, &perf);
for (std::unique_ptr<IndexFile>& new_index : indexes) {
auto indexes = indexer->Index(config, file_consumer_shared, path_to_index,
entry.args, file_contents, &perf);
if (!indexes) {
if (config->enableIndexing &&
std::holds_alternative<int64_t>(request.id)) {
Out_Error out;
out.id = request.id;
out.error.code = lsErrorCodes::InternalError;
out.error.message = "Failed to index " + path_to_index;
QueueManager::WriteStdout(IpcId::Unknown, out);
}
return;
}
for (std::unique_ptr<IndexFile>& new_index : *indexes) {
Timer time;
// Only emit diagnostics for non-interactive sessions, which makes it easier
// to identify indexing problems. For interactive sessions, diagnostics are
// handled by code completion.
if (!is_interactive)
if (!request.is_interactive)
EmitDiagnostics(working_files, new_index->path, new_index->diagnostics_);
// When main thread does IdMap request it will request the previous index if
// needed.
LOG_S(INFO) << "Emitting index result for " << new_index->path;
result.push_back(Index_DoIdMap(std::move(new_index), perf, is_interactive,
result.push_back(Index_DoIdMap(std::move(new_index), perf,
request.is_interactive,
true /*write_to_disk*/));
}
@ -389,7 +401,7 @@ bool IndexMain_DoParse(
entry.args = request->args;
ParseFile(config, working_files, file_consumer_shared, timestamp_manager,
modification_timestamp_fetcher, import_manager, cache_manager,
indexer, request->is_interactive, entry, request->contents);
indexer, request.value(), entry);
return true;
}
@ -518,11 +530,13 @@ void IndexWithTuFromCodeCompletion(
PerformanceImportFile perf;
ClangIndex index;
std::vector<std::unique_ptr<IndexFile>> indexes = ParseWithTu(
auto indexes = ParseWithTu(
file_consumer_shared, &perf, tu, &index, path, args, file_contents);
if (!indexes)
return;
std::vector<Index_DoIdMap> result;
for (std::unique_ptr<IndexFile>& new_index : indexes) {
for (std::unique_ptr<IndexFile>& new_index : *indexes) {
Timer time;
// When main thread does IdMap request it will request the previous index if

View File

@ -1894,7 +1894,7 @@ void OnIndexReference(CXClientData client_data, const CXIdxEntityRefInfo* ref) {
}
}
std::vector<std::unique_ptr<IndexFile>> Parse(
optional<std::vector<std::unique_ptr<IndexFile>>> Parse(
Config* config,
FileConsumerSharedState* file_consumer_shared,
std::string file,
@ -1924,7 +1924,7 @@ std::vector<std::unique_ptr<IndexFile>> Parse(
CXTranslationUnit_KeepGoing |
CXTranslationUnit_DetailedPreprocessingRecord);
if (!tu)
return {};
return nullopt;
perf->index_parse = timer.ElapsedMicrosecondsAndReset();
@ -1935,7 +1935,7 @@ std::vector<std::unique_ptr<IndexFile>> Parse(
unsaved_files);
}
std::vector<std::unique_ptr<IndexFile>> ParseWithTu(
optional<std::vector<std::unique_ptr<IndexFile>>> ParseWithTu(
FileConsumerSharedState* file_consumer_shared,
PerformanceImportFile* perf,
ClangTranslationUnit* tu,
@ -1982,8 +1982,9 @@ std::vector<std::unique_ptr<IndexFile>> ParseWithTu(
CXIndexOpt_IndexImplicitTemplateInstantiations,
tu->cx_tu);
if (index_result != CXError_Success) {
LOG_S(WARNING) << "Indexing " << file
<< " failed with errno=" << index_result;
LOG_S(ERROR) << "Indexing " << file
<< " failed with errno=" << index_result;
return nullopt;
}
clang_IndexAction_dispose(index_action);

View File

@ -539,7 +539,7 @@ struct NamespaceHelper {
// |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.
std::vector<std::unique_ptr<IndexFile>> Parse(
optional<std::vector<std::unique_ptr<IndexFile>>> Parse(
Config* config,
FileConsumerSharedState* file_consumer_shared,
std::string file,
@ -548,7 +548,7 @@ std::vector<std::unique_ptr<IndexFile>> Parse(
PerformanceImportFile* perf,
ClangIndex* index,
bool dump_ast = false);
std::vector<std::unique_ptr<IndexFile>> ParseWithTu(
optional<std::vector<std::unique_ptr<IndexFile>>> ParseWithTu(
FileConsumerSharedState* file_consumer_shared,
PerformanceImportFile* perf,
ClangTranslationUnit* tu,

View File

@ -221,8 +221,9 @@ struct InitializeHandler : BaseMessageHandler<Ipc_InitializeRequest> {
}
bool is_interactive =
working_files->GetFileByFilename(entry.filename) != nullptr;
queue->index_request.Enqueue(Index_Request(
entry.filename, entry.args, is_interactive, *content));
queue->index_request.Enqueue(
Index_Request(entry.filename, entry.args, is_interactive,
*content, request->id));
});
// We need to support multiple concurrent index processes.

View File

@ -8,11 +8,13 @@
Index_Request::Index_Request(const std::string& path,
const std::vector<std::string>& args,
bool is_interactive,
const std::string& contents)
const std::string& contents,
lsRequestId id)
: path(path),
args(args),
is_interactive(is_interactive),
contents(contents) {}
contents(contents),
id(id) {}
Index_DoIdMap::Index_DoIdMap(std::unique_ptr<IndexFile> current,
PerformanceImportFile perf,

View File

@ -20,11 +20,13 @@ struct Index_Request {
std::vector<std::string> args;
bool is_interactive;
std::string contents; // Preloaded contents. Useful for tests.
lsRequestId id;
Index_Request(const std::string& path,
const std::vector<std::string>& args,
bool is_interactive,
const std::string& contents);
const std::string& contents,
lsRequestId id={});
};
struct Index_DoIdMap {

View File

@ -170,9 +170,9 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) {
Config config;
FileConsumerSharedState file_consumer_shared;
PerformanceImportFile perf;
std::vector<std::unique_ptr<IndexFile>> dbs =
Parse(&config, &file_consumer_shared, path, flags, {}, &perf, &index,
false /*dump_ast*/);
auto dbs = Parse(&config, &file_consumer_shared, path, flags, {}, &perf,
&index, false /*dump_ast*/);
assert(dbs);
for (const auto& entry : all_expected_output) {
const std::string& expected_path = entry.first;
@ -203,7 +203,7 @@ bool RunIndexTests(const std::string& filter_path, bool enable_update) {
};
// Get output from index operation.
IndexFile* db = FindDbForPathEnding(expected_path, dbs);
IndexFile* db = FindDbForPathEnding(expected_path, *dbs);
assert(db);
if (!db->diagnostics_.empty()) {
std::cout << "For " << path << std::endl;