mirror of
https://github.com/MaskRay/ccls.git
synced 2025-02-16 21:58:08 +00:00
Look for .cquery in any directory above the source file in the hierarchy. (#409)
* Look for .cquery in any directory above the source file in the hierarchy. Currently cquery only reads compiler arguments (.cquery) from project root. Under some circumstances (e.g. remote compiling), generating a compilation database with correct path in it is non-trivial, and allowing per directory compile arguments usually helps. * unused var buf
This commit is contained in:
parent
6933870962
commit
54c587a700
@ -44,7 +44,6 @@ std::string GetWorkingDirectory() {
|
||||
std::string NormalizePath(const std::string& path) {
|
||||
DWORD retval = 0;
|
||||
TCHAR buffer[MAX_PATH] = TEXT("");
|
||||
TCHAR buf[MAX_PATH] = TEXT("");
|
||||
TCHAR** lpp_part = {NULL};
|
||||
|
||||
retval = GetFullPathName(path.c_str(), MAX_PATH, buffer, lpp_part);
|
||||
|
@ -270,38 +270,66 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Project::Entry> LoadFromDirectoryListing(Config* init_opts,
|
||||
ProjectConfig* config) {
|
||||
std::vector<Project::Entry> result;
|
||||
|
||||
std::vector<std::string> ReadCompilerArgumentsFromFile(
|
||||
const std::string& path) {
|
||||
std::vector<std::string> args;
|
||||
for (std::string line :
|
||||
ReadLinesWithEnding(config->project_dir + "/.cquery")) {
|
||||
for (std::string line : ReadLinesWithEnding(path)) {
|
||||
TrimInPlace(line);
|
||||
if (line.empty() || StartsWith(line, "#"))
|
||||
continue;
|
||||
args.push_back(line);
|
||||
}
|
||||
LOG_IF_S(INFO, !args.empty())
|
||||
<< "Using .cquery arguments " << StringJoin(args);
|
||||
return args;
|
||||
}
|
||||
|
||||
std::vector<Project::Entry> LoadFromDirectoryListing(Config* init_opts,
|
||||
ProjectConfig* config) {
|
||||
std::vector<Project::Entry> result;
|
||||
LOG_IF_S(WARNING, !FileExists(config->project_dir + "/.cquery") &&
|
||||
config->extra_flags.empty())
|
||||
<< "cquery has no clang arguments. Considering adding either a "
|
||||
"compile_commands.json or .cquery file. See the cquery README for "
|
||||
"more information.";
|
||||
|
||||
std::vector<std::string> files = GetFilesInFolder(
|
||||
config->project_dir, true /*recursive*/, true /*add_folder_to_path*/);
|
||||
for (const std::string& file : files) {
|
||||
if (SourceFileType(file)) {
|
||||
CompileCommandsEntry e;
|
||||
e.directory = config->project_dir;
|
||||
e.file = file;
|
||||
e.args = args;
|
||||
e.args.push_back(e.file);
|
||||
result.push_back(
|
||||
GetCompilationEntryFromCompileCommandEntry(init_opts, config, e));
|
||||
std::unordered_map<std::string, std::vector<std::string>> folder_args;
|
||||
std::vector<std::string> files;
|
||||
|
||||
GetFilesInFolder(
|
||||
config->project_dir, true /*recursive*/, true /*add_folder_to_path*/,
|
||||
[&folder_args, &files](const std::string& path) {
|
||||
if (SourceFileType(path)) {
|
||||
files.push_back(path);
|
||||
} else if (GetBaseName(path) == ".cquery") {
|
||||
LOG_S(INFO) << "Using .cquery arguments from " << path;
|
||||
folder_args.emplace(GetDirName(path),
|
||||
ReadCompilerArgumentsFromFile(path));
|
||||
}
|
||||
});
|
||||
|
||||
const auto& project_dir_args = folder_args[config->project_dir];
|
||||
LOG_IF_S(INFO, !project_dir_args.empty())
|
||||
<< "Using .cquery arguments " << StringJoin(project_dir_args);
|
||||
|
||||
auto GetCompilerArgumentForFile = [&config,
|
||||
&folder_args](const std::string& path) {
|
||||
for (std::string cur = GetDirName(path);
|
||||
NormalizePath(cur) != config->project_dir; cur = GetDirName(cur)) {
|
||||
auto it = folder_args.find(cur);
|
||||
if (it != folder_args.end()) {
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
return folder_args[config->project_dir];
|
||||
};
|
||||
|
||||
for (const std::string& file : files) {
|
||||
CompileCommandsEntry e;
|
||||
e.directory = config->project_dir;
|
||||
e.file = file;
|
||||
e.args = GetCompilerArgumentForFile(file);
|
||||
e.args.push_back(e.file);
|
||||
result.push_back(
|
||||
GetCompilationEntryFromCompileCommandEntry(init_opts, config, e));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
13
src/utils.cc
13
src/utils.cc
@ -120,6 +120,15 @@ bool FindAnyPartial(const std::string& value,
|
||||
});
|
||||
}
|
||||
|
||||
std::string GetDirName(std::string path) {
|
||||
if (path.size() && path.back() == '/')
|
||||
path.pop_back();
|
||||
size_t last_slash = path.find_last_of('/');
|
||||
if (last_slash == std::string::npos) return ".";
|
||||
if (last_slash == 0) return "/";
|
||||
return path.substr(0, last_slash);
|
||||
}
|
||||
|
||||
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())
|
||||
@ -205,14 +214,14 @@ static void GetFilesInFolderHelper(
|
||||
goto bail;
|
||||
}
|
||||
|
||||
// Skip all dot files.
|
||||
// Skip all dot files except .cquery.
|
||||
//
|
||||
// The nested ifs are intentional, branching order is subtle here.
|
||||
//
|
||||
// Note that in the future if we do support dot directories/files, we must
|
||||
// always ignore the '.' and '..' directories otherwise this will loop
|
||||
// infinitely.
|
||||
if (file.name[0] != '.') {
|
||||
if (file.name[0] != '.' || strcmp(file.name, ".cquery") == 0) {
|
||||
if (file.is_dir) {
|
||||
if (recursive) {
|
||||
std::string child_dir = q.front().second + file.name + "/";
|
||||
|
@ -33,7 +33,8 @@ bool EndsWithAny(const std::string& value,
|
||||
const std::vector<std::string>& endings);
|
||||
bool FindAnyPartial(const std::string& value,
|
||||
const std::vector<std::string>& values);
|
||||
|
||||
// Returns the dirname of |path|, i.e. "foo/bar.cc" => "foo", "foo" => ".", "/foo" => "/".
|
||||
std::string GetDirName(std::string path);
|
||||
// Returns the basename of |path|, ie, "foo/bar.cc" => "bar.cc".
|
||||
std::string GetBaseName(const std::string& path);
|
||||
// Returns |path| without the filetype, ie, "foo/bar.cc" => "foo/bar".
|
||||
|
Loading…
Reference in New Issue
Block a user