mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-26 09:31:59 +00:00
Always normalize project file entry when passing it to clang.
This makes clang_codeCompleteAt much faster.
This commit is contained in:
parent
1836a50a48
commit
5605dfbb00
@ -92,20 +92,24 @@ optional<std::string> SourceFileType(const std::string& path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
||||||
Config* initOpts,
|
Config* init_opts,
|
||||||
ProjectConfig* config,
|
ProjectConfig* config,
|
||||||
const CompileCommandsEntry& entry) {
|
const CompileCommandsEntry& entry) {
|
||||||
|
|
||||||
auto cleanup_maybe_relative_path = [&](const std::string& path) {
|
auto cleanup_maybe_relative_path = [&](const std::string& path) {
|
||||||
// TODO/FIXME: Normalization will fail for paths that do not exist. Should
|
// TODO/FIXME: Normalization will fail for paths that do not exist. Should
|
||||||
// it return an optional<std::string>?
|
// it return an optional<std::string>?
|
||||||
assert(!path.empty());
|
assert(!path.empty());
|
||||||
if (path[0] == '/' || entry.directory.empty())
|
if (path[0] == '/' || entry.directory.empty())
|
||||||
return NormalizePathWithTestOptOut(path);
|
return NormalizePathWithTestOptOut(path);
|
||||||
|
if (EndsWith(entry.directory, "/"))
|
||||||
|
return NormalizePathWithTestOptOut(entry.directory + path);
|
||||||
return NormalizePathWithTestOptOut(entry.directory + "/" + path);
|
return NormalizePathWithTestOptOut(entry.directory + "/" + path);
|
||||||
};
|
};
|
||||||
|
|
||||||
Project::Entry result;
|
Project::Entry result;
|
||||||
result.filename = NormalizePathWithTestOptOut(entry.file);
|
result.filename = NormalizePathWithTestOptOut(entry.file);
|
||||||
|
std::string base_name = GetBaseName(entry.file);
|
||||||
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
@ -137,6 +141,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
result.args.push_back("clang++");
|
result.args.push_back("clang++");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add -working-directory if not provided.
|
||||||
if (!AnyStartsWith(entry.args, "-working-directory")) {
|
if (!AnyStartsWith(entry.args, "-working-directory")) {
|
||||||
result.args.emplace_back("-working-directory");
|
result.args.emplace_back("-working-directory");
|
||||||
result.args.push_back(entry.directory);
|
result.args.push_back(entry.directory);
|
||||||
@ -144,14 +149,14 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
|
|
||||||
// Clang does not have good hueristics for determining source language, we
|
// Clang does not have good hueristics for determining source language, we
|
||||||
// should explicitly specify it.
|
// should explicitly specify it.
|
||||||
if (auto source_file_type = SourceFileType(entry.file)) {
|
if (optional<std::string> file_type = SourceFileType(entry.file)) {
|
||||||
if (!AnyStartsWith(entry.args, "-x")) {
|
if (!AnyStartsWith(entry.args, "-x")) {
|
||||||
result.args.push_back("-x" + *source_file_type);
|
result.args.push_back("-x" + *file_type);
|
||||||
}
|
}
|
||||||
if (!AnyStartsWith(entry.args, "-std=")) {
|
if (!AnyStartsWith(entry.args, "-std=")) {
|
||||||
if (*source_file_type == "c")
|
if (*file_type == "c")
|
||||||
result.args.push_back("-std=gnu11");
|
result.args.push_back("-std=gnu11");
|
||||||
else if (*source_file_type == "c++")
|
else if (*file_type == "c++")
|
||||||
result.args.push_back("-std=c++14");
|
result.args.push_back("-std=c++14");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,6 +221,10 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is most likely the file path we will be passing to clang.
|
||||||
|
if (EndsWith(arg, base_name))
|
||||||
|
arg = cleanup_maybe_relative_path(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.args.push_back(arg);
|
result.args.push_back(arg);
|
||||||
@ -237,13 +246,14 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
|
|
||||||
// Using -fparse-all-comments enables documententation in the indexer and in
|
// Using -fparse-all-comments enables documententation in the indexer and in
|
||||||
// code completion.
|
// code completion.
|
||||||
if (initOpts->enableComments > 1 && !AnyStartsWith(result.args, "-fparse-all-comments"))
|
if (init_opts->enableComments > 1 && !AnyStartsWith(result.args, "-fparse-all-comments")) {
|
||||||
result.args.push_back("-fparse-all-comments");
|
result.args.push_back("-fparse-all-comments");
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Project::Entry> LoadFromDirectoryListing(Config* initOpts, ProjectConfig* config) {
|
std::vector<Project::Entry> LoadFromDirectoryListing(Config* init_opts, ProjectConfig* config) {
|
||||||
std::vector<Project::Entry> result;
|
std::vector<Project::Entry> result;
|
||||||
|
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
@ -271,7 +281,7 @@ std::vector<Project::Entry> LoadFromDirectoryListing(Config* initOpts, ProjectCo
|
|||||||
e.file = file;
|
e.file = file;
|
||||||
e.args = args;
|
e.args = args;
|
||||||
e.args.push_back(e.file);
|
e.args.push_back(e.file);
|
||||||
result.push_back(GetCompilationEntryFromCompileCommandEntry(initOpts, config, e));
|
result.push_back(GetCompilationEntryFromCompileCommandEntry(init_opts, config, e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,12 +289,12 @@ std::vector<Project::Entry> LoadFromDirectoryListing(Config* initOpts, ProjectCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
||||||
Config* initOpts,
|
Config* init_opts,
|
||||||
ProjectConfig* config,
|
ProjectConfig* config,
|
||||||
const std::string& opt_compilation_db_dir) {
|
const std::string& opt_compilation_db_dir) {
|
||||||
// If there is a .cquery file always load using directory listing.
|
// If there is a .cquery file always load using directory listing.
|
||||||
if (FileExists(config->project_dir + "/.cquery"))
|
if (FileExists(config->project_dir + "/.cquery"))
|
||||||
return LoadFromDirectoryListing(initOpts, config);
|
return LoadFromDirectoryListing(init_opts, config);
|
||||||
|
|
||||||
// Try to load compile_commands.json, but fallback to a project listing.
|
// Try to load compile_commands.json, but fallback to a project listing.
|
||||||
const auto& compilation_db_dir = opt_compilation_db_dir.empty()
|
const auto& compilation_db_dir = opt_compilation_db_dir.empty()
|
||||||
@ -297,7 +307,7 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
|||||||
if (cx_db_load_error == CXCompilationDatabase_CanNotLoadDatabase) {
|
if (cx_db_load_error == CXCompilationDatabase_CanNotLoadDatabase) {
|
||||||
LOG_S(INFO) << "Unable to load compile_commands.json located at \""
|
LOG_S(INFO) << "Unable to load compile_commands.json located at \""
|
||||||
<< compilation_db_dir << "\"; using directory listing instead.";
|
<< compilation_db_dir << "\"; using directory listing instead.";
|
||||||
return LoadFromDirectoryListing(initOpts, config);
|
return LoadFromDirectoryListing(init_opts, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer clang_time;
|
Timer clang_time;
|
||||||
@ -341,7 +351,7 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
|||||||
absolute_filename = directory + "/" + relative_filename;
|
absolute_filename = directory + "/" + relative_filename;
|
||||||
entry.file = NormalizePathWithTestOptOut(absolute_filename);
|
entry.file = NormalizePathWithTestOptOut(absolute_filename);
|
||||||
|
|
||||||
result.push_back(GetCompilationEntryFromCompileCommandEntry(initOpts, config, entry));
|
result.push_back(GetCompilationEntryFromCompileCommandEntry(init_opts, config, entry));
|
||||||
our_time.Pause();
|
our_time.Pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,7 +406,7 @@ int ComputeGuessScore(const std::string& a, const std::string& b) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void Project::Load(Config* initOpts,
|
void Project::Load(Config* init_opts,
|
||||||
const std::vector<std::string>& extra_flags,
|
const std::vector<std::string>& extra_flags,
|
||||||
const std::string& opt_compilation_db_dir,
|
const std::string& opt_compilation_db_dir,
|
||||||
const std::string& root_directory,
|
const std::string& root_directory,
|
||||||
@ -407,7 +417,7 @@ void Project::Load(Config* initOpts,
|
|||||||
config.project_dir = root_directory;
|
config.project_dir = root_directory;
|
||||||
config.resource_dir = resource_directory;
|
config.resource_dir = resource_directory;
|
||||||
entries =
|
entries =
|
||||||
LoadCompilationEntriesFromDirectory(initOpts, &config, opt_compilation_db_dir);
|
LoadCompilationEntriesFromDirectory(init_opts, &config, opt_compilation_db_dir);
|
||||||
|
|
||||||
// Cleanup / postprocess include directories.
|
// Cleanup / postprocess include directories.
|
||||||
quote_include_directories.assign(config.quote_dirs.begin(),
|
quote_include_directories.assign(config.quote_dirs.begin(),
|
||||||
@ -479,7 +489,7 @@ TEST_SUITE("Project") {
|
|||||||
std::vector<std::string> expected) {
|
std::vector<std::string> expected) {
|
||||||
g_disable_normalize_path_for_test = true;
|
g_disable_normalize_path_for_test = true;
|
||||||
|
|
||||||
Config initOpts;
|
Config init_opts;
|
||||||
ProjectConfig config;
|
ProjectConfig config;
|
||||||
config.project_dir = "/w/c/s/";
|
config.project_dir = "/w/c/s/";
|
||||||
config.resource_dir = "/w/resource_dir/";
|
config.resource_dir = "/w/resource_dir/";
|
||||||
@ -489,7 +499,7 @@ TEST_SUITE("Project") {
|
|||||||
entry.args = raw;
|
entry.args = raw;
|
||||||
entry.file = file;
|
entry.file = file;
|
||||||
Project::Entry result =
|
Project::Entry result =
|
||||||
GetCompilationEntryFromCompileCommandEntry(&initOpts, &config, entry);
|
GetCompilationEntryFromCompileCommandEntry(&init_opts, &config, entry);
|
||||||
|
|
||||||
if (result.args != expected) {
|
if (result.args != expected) {
|
||||||
std::cout << "Raw: " << StringJoin(raw) << std::endl;
|
std::cout << "Raw: " << StringJoin(raw) << std::endl;
|
||||||
@ -517,7 +527,7 @@ TEST_SUITE("Project") {
|
|||||||
/* raw */ {"clang", "-lstdc++", "myfile.cc"},
|
/* raw */ {"clang", "-lstdc++", "myfile.cc"},
|
||||||
/* expected */
|
/* expected */
|
||||||
{"clang", "-working-directory", "/dir/", "-xc++", "-std=c++14",
|
{"clang", "-working-directory", "/dir/", "-xc++", "-std=c++14",
|
||||||
"-lstdc++", "myfile.cc", "-resource-dir=/w/resource_dir/",
|
"-lstdc++", "&/dir/myfile.cc", "-resource-dir=/w/resource_dir/",
|
||||||
"-Wno-unknown-warning-option"});
|
"-Wno-unknown-warning-option"});
|
||||||
|
|
||||||
CheckFlags(
|
CheckFlags(
|
||||||
@ -539,7 +549,7 @@ TEST_SUITE("Project") {
|
|||||||
/* raw */ {"cc", "-O0", "foo/bar.c"},
|
/* raw */ {"cc", "-O0", "foo/bar.c"},
|
||||||
/* expected */
|
/* expected */
|
||||||
{"cc", "-working-directory", "/home/user", "-xc", "-std=gnu11",
|
{"cc", "-working-directory", "/home/user", "-xc", "-std=gnu11",
|
||||||
"-O0", "foo/bar.c", "-resource-dir=/w/resource_dir/",
|
"-O0", "&/home/user/foo/bar.c", "-resource-dir=/w/resource_dir/",
|
||||||
"-Wno-unknown-warning-option"});
|
"-Wno-unknown-warning-option"});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -897,7 +907,7 @@ TEST_SUITE("Project") {
|
|||||||
"debian_jessie_amd64-sysroot",
|
"debian_jessie_amd64-sysroot",
|
||||||
"-fno-exceptions",
|
"-fno-exceptions",
|
||||||
"-fvisibility-inlines-hidden",
|
"-fvisibility-inlines-hidden",
|
||||||
"../../ash/login/ui/lock_screen_sanity_unittest.cc",
|
"&/w/c/s/out/Release/../../ash/login/ui/lock_screen_sanity_unittest.cc",
|
||||||
"-resource-dir=/w/resource_dir/",
|
"-resource-dir=/w/resource_dir/",
|
||||||
"-Wno-unknown-warning-option"});
|
"-Wno-unknown-warning-option"});
|
||||||
}
|
}
|
||||||
@ -1221,13 +1231,13 @@ TEST_SUITE("Project") {
|
|||||||
"debian_jessie_amd64-sysroot",
|
"debian_jessie_amd64-sysroot",
|
||||||
"-fno-exceptions",
|
"-fno-exceptions",
|
||||||
"-fvisibility-inlines-hidden",
|
"-fvisibility-inlines-hidden",
|
||||||
"../../apps/app_lifetime_monitor.cc",
|
"&/w/c/s/out/Release/../../apps/app_lifetime_monitor.cc",
|
||||||
"-resource-dir=/w/resource_dir/",
|
"-resource-dir=/w/resource_dir/",
|
||||||
"-Wno-unknown-warning-option"});
|
"-Wno-unknown-warning-option"});
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Directory extraction") {
|
TEST_CASE("Directory extraction") {
|
||||||
Config initOpts;
|
Config init_opts;
|
||||||
ProjectConfig config;
|
ProjectConfig config;
|
||||||
config.project_dir = "/w/c/s/";
|
config.project_dir = "/w/c/s/";
|
||||||
|
|
||||||
@ -1257,7 +1267,7 @@ TEST_SUITE("Project") {
|
|||||||
"foo.cc"};
|
"foo.cc"};
|
||||||
entry.file = "foo.cc";
|
entry.file = "foo.cc";
|
||||||
Project::Entry result =
|
Project::Entry result =
|
||||||
GetCompilationEntryFromCompileCommandEntry(&initOpts, &config, entry);
|
GetCompilationEntryFromCompileCommandEntry(&init_opts, &config, entry);
|
||||||
|
|
||||||
std::unordered_set<std::string> angle_expected{
|
std::unordered_set<std::string> angle_expected{
|
||||||
"&/a_absolute1", "&/a_absolute2", "&/base/a_relative1",
|
"&/a_absolute1", "&/a_absolute2", "&/base/a_relative1",
|
||||||
|
@ -34,7 +34,7 @@ struct Project {
|
|||||||
// used instead. Otherwise, a recursive directory listing of all *.cpp, *.cc,
|
// used instead. Otherwise, a recursive directory listing of all *.cpp, *.cc,
|
||||||
// *.h, and *.hpp files will be used. clang arguments can be specified in a
|
// *.h, and *.hpp files will be used. clang arguments can be specified in a
|
||||||
// .cquery file located inside of |root_directory|.
|
// .cquery file located inside of |root_directory|.
|
||||||
void Load(Config* initOpts,
|
void Load(Config* init_opts,
|
||||||
const std::vector<std::string>& extra_flags,
|
const std::vector<std::string>& extra_flags,
|
||||||
const std::string& opt_compilation_db_dir,
|
const std::string& opt_compilation_db_dir,
|
||||||
const std::string& root_directory,
|
const std::string& root_directory,
|
||||||
|
@ -10,14 +10,6 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
bool gTestOutputMode = false;
|
bool gTestOutputMode = false;
|
||||||
|
|
||||||
std::string GetBaseName(const std::string& path) {
|
|
||||||
size_t last_slash = path.find_last_of('/');
|
|
||||||
if (last_slash != std::string::npos && (last_slash + 1) < path.size())
|
|
||||||
return path.substr(last_slash + 1);
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// uint8_t
|
// uint8_t
|
||||||
|
@ -86,6 +86,13 @@ bool EndsWithAny(const std::string& value,
|
|||||||
[&value](const std::string& ending) { return EndsWith(value, ending); });
|
[&value](const std::string& ending) { return EndsWith(value, ending); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string GetBaseName(const std::string& path) {
|
||||||
|
size_t last_slash = path.find_last_of('/');
|
||||||
|
if (last_slash != std::string::npos && (last_slash + 1) < path.size())
|
||||||
|
return path.substr(last_slash + 1);
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
// See http://stackoverflow.com/a/29752943
|
// See http://stackoverflow.com/a/29752943
|
||||||
std::string ReplaceAll(const std::string& source,
|
std::string ReplaceAll(const std::string& source,
|
||||||
const std::string& from,
|
const std::string& from,
|
||||||
|
@ -28,6 +28,9 @@ bool StartsWithAny(const std::string& value,
|
|||||||
bool EndsWithAny(const std::string& value,
|
bool EndsWithAny(const std::string& value,
|
||||||
const std::vector<std::string>& endings);
|
const std::vector<std::string>& endings);
|
||||||
|
|
||||||
|
// Returns the basename of |path|, ie, "foo/bar.cc" => "bar.cc".
|
||||||
|
std::string GetBaseName(const std::string& path);
|
||||||
|
|
||||||
std::string ReplaceAll(const std::string& source,
|
std::string ReplaceAll(const std::string& source,
|
||||||
const std::string& from,
|
const std::string& from,
|
||||||
const std::string& to);
|
const std::string& to);
|
||||||
|
Loading…
Reference in New Issue
Block a user