A bit more code cleanup in project.cc

This commit is contained in:
Jacob Dufault 2017-09-21 20:09:11 -07:00
parent a96be1d6e5
commit bd8582e718

View File

@ -26,9 +26,11 @@ MAKE_REFLECT_STRUCT(CompileCommandsEntry, directory, file, command, args);
namespace { namespace {
struct IncludeDirectories { struct ProjectConfig {
std::unordered_set<std::string> quote_dirs; std::unordered_set<std::string> quote_dirs;
std::unordered_set<std::string> angle_dirs; std::unordered_set<std::string> angle_dirs;
std::vector<std::string> extra_flags;
std::string project_dir;
}; };
static const char* kBlacklistMulti[] = {"-MF", "-Xclang"}; static const char* kBlacklistMulti[] = {"-MF", "-Xclang"};
@ -88,8 +90,7 @@ bool IsCFile(const std::string& path) {
} }
Project::Entry GetCompilationEntryFromCompileCommandEntry( Project::Entry GetCompilationEntryFromCompileCommandEntry(
IncludeDirectories* includes, ProjectConfig* config,
const std::vector<std::string>& extra_flags,
const CompileCommandsEntry& entry) { const CompileCommandsEntry& entry) {
Project::Entry result; Project::Entry result;
result.filename = NormalizePath(entry.file); result.filename = NormalizePath(entry.file);
@ -98,7 +99,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
bool add_next_flag_quote = false; bool add_next_flag_quote = false;
bool add_next_flag_angle = false; bool add_next_flag_angle = false;
result.args.reserve(entry.args.size() + extra_flags.size()); result.args.reserve(entry.args.size() + config->extra_flags.size());
for (size_t i = 0; i < entry.args.size(); ++i) { for (size_t i = 0; i < entry.args.size(); ++i) {
std::string arg = entry.args[i]; std::string arg = entry.args[i];
@ -122,9 +123,9 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
make_next_flag_absolute = false; make_next_flag_absolute = false;
if (add_next_flag_quote) if (add_next_flag_quote)
includes->quote_dirs.insert(arg); config->quote_dirs.insert(arg);
if (add_next_flag_angle) if (add_next_flag_angle)
includes->angle_dirs.insert(arg); config->angle_dirs.insert(arg);
add_next_flag_quote = false; add_next_flag_quote = false;
add_next_flag_angle = false; add_next_flag_angle = false;
} }
@ -148,9 +149,9 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
arg = flag_type + path; arg = flag_type + path;
} }
if (ShouldAddToQuoteIncludes(arg)) if (ShouldAddToQuoteIncludes(arg))
includes->quote_dirs.insert(path); config->quote_dirs.insert(path);
if (ShouldAddToAngleIncludes(arg)) if (ShouldAddToAngleIncludes(arg))
includes->angle_dirs.insert(path); config->angle_dirs.insert(path);
break; break;
} }
} }
@ -159,7 +160,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
} }
// We don't do any special processing on user-given extra flags. // We don't do any special processing on user-given extra flags.
for (const auto& flag : extra_flags) for (const auto& flag : config->extra_flags)
result.args.push_back(flag); result.args.push_back(flag);
// Clang does not have good hueristics for determining source language, we // Clang does not have good hueristics for determining source language, we
@ -180,45 +181,13 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
return result; return result;
} }
/* TODO: Fix this function, it may be way faster than libclang's implementation.
std::vector<Project::Entry> LoadFromCompileCommandsJson(
std::unordered_set<std::string>& quote_includes,
std::unordered_set<std::string>& angle_includes, const std::vector<std::string>&
extra_flags, const std::string& project_directory) {
optional<std::string> compile_commands_content = ReadContent(project_directory
+ "/compile_commands.json"); if (!compile_commands_content) return {};
rapidjson::Document reader;
reader.Parse(compile_commands_content->c_str());
if (reader.HasParseError())
return {};
std::vector<CompileCommandsEntry> entries;
Reflect(reader, entries);
std::vector<Project::Entry> result;
result.reserve(entries.size());
for (auto& entry : entries) {
if (entry.args.empty() && !entry.command.empty())
entry.args = SplitString(entry.command, " ");
result.push_back(GetCompilationEntryFromCompileCommandEntry(quote_includes,
angle_includes, extra_flags, entry));
}
return result;
}
*/
std::vector<Project::Entry> LoadFromDirectoryListing( std::vector<Project::Entry> LoadFromDirectoryListing(
IncludeDirectories* includes, ProjectConfig* config) {
const std::vector<std::string>& extra_flags,
const std::string& project_directory) {
std::vector<Project::Entry> result; std::vector<Project::Entry> result;
std::vector<std::string> args; std::vector<std::string> args;
std::cerr << "Using arguments: "; std::cerr << "Using arguments: ";
for (const std::string& line : ReadLines(project_directory + "/clang_args")) { for (const std::string& line : ReadLines(config->project_dir + "/clang_args")) {
if (line.empty() || StartsWith(line, "#")) if (line.empty() || StartsWith(line, "#"))
continue; continue;
if (!args.empty()) if (!args.empty())
@ -229,7 +198,7 @@ std::vector<Project::Entry> LoadFromDirectoryListing(
std::cerr << std::endl; std::cerr << std::endl;
std::vector<std::string> files = GetFilesInFolder( std::vector<std::string> files = GetFilesInFolder(
project_directory, true /*recursive*/, true /*add_folder_to_path*/); config->project_dir, true /*recursive*/, true /*add_folder_to_path*/);
for (const std::string& file : files) { for (const std::string& file : files) {
if (EndsWith(file, ".cc") || EndsWith(file, ".cpp") || if (EndsWith(file, ".cc") || EndsWith(file, ".cpp") ||
EndsWith(file, ".c")) { EndsWith(file, ".c")) {
@ -237,7 +206,7 @@ std::vector<Project::Entry> LoadFromDirectoryListing(
e.file = NormalizePath(file); e.file = NormalizePath(file);
e.args = args; e.args = args;
result.push_back( result.push_back(
GetCompilationEntryFromCompileCommandEntry(includes, extra_flags, e)); GetCompilationEntryFromCompileCommandEntry(config, e));
} }
} }
@ -245,21 +214,17 @@ std::vector<Project::Entry> LoadFromDirectoryListing(
} }
std::vector<Project::Entry> LoadCompilationEntriesFromDirectory( std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
IncludeDirectories* includes, ProjectConfig* config) {
const std::vector<std::string>& extra_flags,
const std::string& project_directory) {
// TODO: Figure out if this function or the clang one is faster.
// return LoadFromCompileCommandsJson(extra_flags, project_directory);
std::cerr << "Trying to load compile_commands.json" << std::endl; // Try to load compile_commands.json, but fallback to a project listing.
LOG_S(INFO) << "Trying to load compile_commands.json";
CXCompilationDatabase_Error cx_db_load_error; CXCompilationDatabase_Error cx_db_load_error;
CXCompilationDatabase cx_db = clang_CompilationDatabase_fromDirectory( CXCompilationDatabase cx_db = clang_CompilationDatabase_fromDirectory(
project_directory.c_str(), &cx_db_load_error); config->project_dir.c_str(), &cx_db_load_error);
if (cx_db_load_error == CXCompilationDatabase_CanNotLoadDatabase) { if (cx_db_load_error == CXCompilationDatabase_CanNotLoadDatabase) {
std::cerr << "Unable to load compile_commands.json located at \"" LOG_S(INFO) << "Unable to load compile_commands.json located at \""
<< project_directory << "\"; using directory listing instead." << config->project_dir << "\"; using directory listing instead.";
<< std::endl; return LoadFromDirectoryListing(config);
return LoadFromDirectoryListing(includes, extra_flags, project_directory);
} }
CXCompileCommands cx_commands = CXCompileCommands cx_commands =
@ -288,7 +253,7 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
clang::ToString(clang_CompileCommand_getArg(cx_command, j))); clang::ToString(clang_CompileCommand_getArg(cx_command, j)));
result.push_back(GetCompilationEntryFromCompileCommandEntry( result.push_back(GetCompilationEntryFromCompileCommandEntry(
includes, extra_flags, entry)); config, entry));
} }
clang_CompileCommands_dispose(cx_commands); clang_CompileCommands_dispose(cx_commands);
@ -339,15 +304,17 @@ int ComputeGuessScore(const std::string& a, const std::string& b) {
void Project::Load(const std::vector<std::string>& extra_flags, void Project::Load(const std::vector<std::string>& extra_flags,
const std::string& directory) { const std::string& directory) {
IncludeDirectories includes; // Load data.
entries = ProjectConfig config;
LoadCompilationEntriesFromDirectory(&includes, extra_flags, directory); config.extra_flags = extra_flags;
config.project_dir = directory;
quote_include_directories.assign(includes.quote_dirs.begin(), entries = LoadCompilationEntriesFromDirectory(&config);
includes.quote_dirs.end());
angle_include_directories.assign(includes.angle_dirs.begin(),
includes.angle_dirs.end());
// Cleanup / postprocess include directories.
quote_include_directories.assign(config.quote_dirs.begin(),
config.quote_dirs.end());
angle_include_directories.assign(config.angle_dirs.begin(),
config.angle_dirs.end());
for (std::string& path : quote_include_directories) { for (std::string& path : quote_include_directories) {
EnsureEndsInSlash(path); EnsureEndsInSlash(path);
LOG_S(INFO) << "quote_include_dir: " << path; LOG_S(INFO) << "quote_include_dir: " << path;
@ -357,6 +324,7 @@ void Project::Load(const std::vector<std::string>& extra_flags,
LOG_S(INFO) << "angle_include_dir: " << path; LOG_S(INFO) << "angle_include_dir: " << path;
} }
// Setup project entries.
absolute_path_to_entry_index_.resize(entries.size()); absolute_path_to_entry_index_.resize(entries.size());
for (int i = 0; i < entries.size(); ++i) for (int i = 0; i < entries.size(); ++i)
absolute_path_to_entry_index_[entries[i].filename] = i; absolute_path_to_entry_index_[entries[i].filename] = i;