mirror of
https://github.com/MaskRay/ccls.git
synced 2024-11-22 07:35:08 +00:00
experimental/filesystem -> LLVM/Support/FileSystem.h; sparsepp -> DenseMap
This commit is contained in:
parent
c81ca26a2e
commit
36729818c3
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -4,9 +4,6 @@
|
|||||||
[submodule "third_party/doctest"]
|
[submodule "third_party/doctest"]
|
||||||
path = third_party/doctest
|
path = third_party/doctest
|
||||||
url = https://github.com/onqtam/doctest
|
url = https://github.com/onqtam/doctest
|
||||||
[submodule "third_party/sparsepp"]
|
|
||||||
path = third_party/sparsepp
|
|
||||||
url = https://github.com/greg7mdp/sparsepp
|
|
||||||
[submodule "third_party/loguru"]
|
[submodule "third_party/loguru"]
|
||||||
path = third_party/loguru
|
path = third_party/loguru
|
||||||
url = https://github.com/emilk/loguru
|
url = https://github.com/emilk/loguru
|
||||||
|
@ -91,10 +91,9 @@ if(NOT SYSTEM_CLANG)
|
|||||||
target_compile_options(ccls PRIVATE -nostdinc++ -cxx-isystem ${CLANG_ROOT}/include/c++/v1)
|
target_compile_options(ccls PRIVATE -nostdinc++ -cxx-isystem ${CLANG_ROOT}/include/c++/v1)
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL Linux)
|
if(${CMAKE_SYSTEM_NAME} STREQUAL Linux)
|
||||||
# Don't use -stdlib=libc++ because while ccls is linked with libc++, bundled clang+llvm require libstdc++
|
# Don't use -stdlib=libc++ because while ccls is linked with libc++, bundled clang+llvm require libstdc++
|
||||||
target_link_libraries(ccls PRIVATE -L${CLANG_ROOT}/lib c++ c++experimental c++abi)
|
target_link_libraries(ccls PRIVATE -L${CLANG_ROOT}/lib c++ c++abi)
|
||||||
else()
|
|
||||||
# FreeBSD uses system libcxxrt.a and does not need libc++abi.
|
# FreeBSD defaults to -stdlib=libc++ and uses system libcxxrt.a
|
||||||
target_link_libraries(ccls PRIVATE -stdlib=libc++ -L${CLANG_ROOT}/lib c++experimental)
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -121,25 +120,17 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL Darwin)
|
|||||||
target_link_libraries(ccls PRIVATE -lc++experimental)
|
target_link_libraries(ccls PRIVATE -lc++experimental)
|
||||||
|
|
||||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL Linux)
|
elseif(${CMAKE_SYSTEM_NAME} STREQUAL Linux)
|
||||||
if(NOT CLANG_USE_BUNDLED_LIBC++)
|
|
||||||
target_link_libraries(ccls PRIVATE -lstdc++fs)
|
|
||||||
endif()
|
|
||||||
# loguru calls dladdr
|
# loguru calls dladdr
|
||||||
target_link_libraries(ccls PRIVATE ${CMAKE_DL_LIBS})
|
target_link_libraries(ccls PRIVATE ${CMAKE_DL_LIBS})
|
||||||
|
|
||||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL FreeBSD)
|
elseif(${CMAKE_SYSTEM_NAME} STREQUAL FreeBSD)
|
||||||
# loguru::stacktrace_as_stdstring calls backtrace_symbols
|
# loguru::stacktrace_as_stdstring calls backtrace_symbols
|
||||||
# sparsepp/spp_memory.h uses libkvm
|
|
||||||
# src/platform_posix.cc uses libthr
|
# src/platform_posix.cc uses libthr
|
||||||
find_package(Backtrace REQUIRED)
|
find_package(Backtrace REQUIRED)
|
||||||
target_link_libraries(ccls PRIVATE ${Backtrace_LIBRARIES} kvm thr)
|
target_link_libraries(ccls PRIVATE ${Backtrace_LIBRARIES} thr)
|
||||||
if(SYSTEM_CLANG)
|
if(SYSTEM_CLANG)
|
||||||
target_link_libraries(ccls PRIVATE c++experimental)
|
target_link_libraries(ccls PRIVATE c++experimental)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL Windows)
|
|
||||||
# sparsepp/spp_memory.h uses LibPsapi
|
|
||||||
target_link_libraries(ccls PRIVATE Psapi)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
### Definitions
|
### Definitions
|
||||||
@ -156,7 +147,6 @@ target_include_directories(ccls PRIVATE
|
|||||||
src
|
src
|
||||||
third_party
|
third_party
|
||||||
third_party/rapidjson/include
|
third_party/rapidjson/include
|
||||||
third_party/sparsepp
|
|
||||||
third_party/loguru
|
third_party/loguru
|
||||||
third_party/doctest)
|
third_party/doctest)
|
||||||
|
|
||||||
|
@ -70,6 +70,7 @@ set(_Clang_REQUIRED_VARS Clang_LIBRARY Clang_INCLUDE_DIR Clang_EXECUTABLE
|
|||||||
|
|
||||||
_Clang_find_library(Clang_LIBRARY clang)
|
_Clang_find_library(Clang_LIBRARY clang)
|
||||||
_Clang_find_add_library(clangDriver)
|
_Clang_find_add_library(clangDriver)
|
||||||
|
_Clang_find_add_library(clangBasic)
|
||||||
_Clang_find_add_library(LLVMOption)
|
_Clang_find_add_library(LLVMOption)
|
||||||
_Clang_find_add_library(LLVMSupport)
|
_Clang_find_add_library(LLVMSupport)
|
||||||
_Clang_find_add_library(LLVMDemangle)
|
_Clang_find_add_library(LLVMDemangle)
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
#include "clang_complete.h"
|
#include "clang_complete.h"
|
||||||
|
|
||||||
#include "clang_utils.h"
|
#include "clang_utils.h"
|
||||||
#include "filesystem.hh"
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
|
#include "filesystem.hh"
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
#include <loguru.hpp>
|
#include <loguru.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -29,8 +31,9 @@ unsigned Flags() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string StripFileType(const std::string& path) {
|
std::string StripFileType(const std::string& path) {
|
||||||
fs::path p(path);
|
SmallString<128> Ret;
|
||||||
return p.parent_path() / p.stem();
|
sys::path::append(Ret, sys::path::parent_path(path), sys::path::stem(path));
|
||||||
|
return Ret.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetCompletionPriority(const CXCompletionString& str,
|
unsigned GetCompletionPriority(const CXCompletionString& str,
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#include "clang_utils.h"
|
#include "clang_utils.h"
|
||||||
|
|
||||||
#include "filesystem.hh"
|
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
|
#include "filesystem.hh"
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
lsRange GetLsRangeForFixIt(const CXSourceRange& range) {
|
lsRange GetLsRangeForFixIt(const CXSourceRange& range) {
|
||||||
@ -115,8 +117,11 @@ std::string FileName(CXFile file) {
|
|||||||
// clang_getFileName return values may contain ..
|
// clang_getFileName return values may contain ..
|
||||||
ret = NormalizePath(ToString(clang_getFileName(file)));
|
ret = NormalizePath(ToString(clang_getFileName(file)));
|
||||||
// Resolve /usr/include/c++/7.3.0 symlink.
|
// Resolve /usr/include/c++/7.3.0 symlink.
|
||||||
if (!StartsWith(ret, g_config->projectRoot))
|
if (!StartsWith(ret, g_config->projectRoot)) {
|
||||||
ret = fs::canonical(ret);
|
SmallString<256> dest;
|
||||||
|
sys::fs::real_path(ret, dest);
|
||||||
|
ret = dest.str();
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#include "filesystem.hh"
|
#include "filesystem.hh"
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
static void GetFilesInFolderHelper(
|
static void GetFilesInFolderHelper(
|
||||||
@ -10,31 +10,33 @@ static void GetFilesInFolderHelper(
|
|||||||
bool recursive,
|
bool recursive,
|
||||||
std::string output_prefix,
|
std::string output_prefix,
|
||||||
const std::function<void(const std::string&)>& handler) {
|
const std::function<void(const std::string&)>& handler) {
|
||||||
std::queue<std::pair<fs::path, fs::path>> q;
|
std::error_code ec;
|
||||||
q.emplace(fs::path(folder), fs::path(output_prefix));
|
if (recursive)
|
||||||
while (!q.empty()) {
|
for (sys::fs::recursive_directory_iterator I(folder, ec), E; I != E && !ec;
|
||||||
try {
|
I.increment(ec)) {
|
||||||
for (auto it = fs::directory_iterator(q.front().first);
|
std::string path = I->path(), filename = sys::path::filename(path);
|
||||||
it != fs::directory_iterator(); ++it) {
|
|
||||||
auto path = it->path();
|
|
||||||
std::string filename = path.filename();
|
|
||||||
if (filename[0] != '.' || filename == ".ccls") {
|
if (filename[0] != '.' || filename == ".ccls") {
|
||||||
fs::file_status status = it->symlink_status();
|
SmallString<256> Path;
|
||||||
if (fs::is_regular_file(status))
|
if (output_prefix.size()) {
|
||||||
handler(q.front().second / filename);
|
sys::path::append(Path, output_prefix, path);
|
||||||
else if (fs::is_directory(status) || fs::is_symlink(status)) {
|
handler(Path.str());
|
||||||
if (recursive) {
|
} else
|
||||||
std::string child_dir = q.front().second / filename;
|
handler(path);
|
||||||
if (fs::is_directory(status))
|
|
||||||
q.push(make_pair(path, child_dir));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
for (sys::fs::directory_iterator I(folder, ec), E; I != E && !ec;
|
||||||
|
I.increment(ec)) {
|
||||||
|
std::string path = I->path(), filename = sys::path::filename(path);
|
||||||
|
if (filename[0] != '.' || filename == ".ccls") {
|
||||||
|
SmallString<256> Path;
|
||||||
|
if (output_prefix.size()) {
|
||||||
|
sys::path::append(Path, output_prefix, path);
|
||||||
|
handler(Path.str());
|
||||||
|
} else
|
||||||
|
handler(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (fs::filesystem_error&) {
|
|
||||||
}
|
|
||||||
q.pop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetFilesInFolder(std::string folder,
|
void GetFilesInFolder(std::string folder,
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <experimental/filesystem>
|
#include <llvm/Support/FileSystem.h>
|
||||||
|
#include <llvm/Support/Path.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace fs = std::experimental::filesystem;
|
|
||||||
|
|
||||||
void GetFilesInFolder(std::string folder,
|
void GetFilesInFolder(std::string folder,
|
||||||
bool recursive,
|
bool recursive,
|
||||||
bool add_folder_to_path,
|
bool add_folder_to_path,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "cache_manager.h"
|
#include "cache_manager.h"
|
||||||
#include "diagnostics_engine.h"
|
#include "diagnostics_engine.h"
|
||||||
#include "filesystem.hh"
|
|
||||||
#include "import_pipeline.h"
|
#include "import_pipeline.h"
|
||||||
#include "include_complete.h"
|
#include "include_complete.h"
|
||||||
#include "message_handler.h"
|
#include "message_handler.h"
|
||||||
@ -11,6 +10,9 @@
|
|||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "working_files.h"
|
#include "working_files.h"
|
||||||
|
|
||||||
|
#include "filesystem.hh"
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
#include <loguru.hpp>
|
#include <loguru.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -492,9 +494,9 @@ struct Handler_Initialize : BaseMessageHandler<In_InitializeRequest> {
|
|||||||
config->projectRoot = project_path;
|
config->projectRoot = project_path;
|
||||||
// Create two cache directories for files inside and outside of the
|
// Create two cache directories for files inside and outside of the
|
||||||
// project.
|
// project.
|
||||||
fs::create_directories(config->cacheDirectory +
|
sys::fs::create_directories(config->cacheDirectory +
|
||||||
EscapeFileName(config->projectRoot));
|
EscapeFileName(config->projectRoot));
|
||||||
fs::create_directories(config->cacheDirectory + '@' +
|
sys::fs::create_directories(config->cacheDirectory + '@' +
|
||||||
EscapeFileName(config->projectRoot));
|
EscapeFileName(config->projectRoot));
|
||||||
|
|
||||||
g_config = std::move(config);
|
g_config = std::move(config);
|
||||||
|
@ -35,15 +35,17 @@ using namespace llvm::opt;
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct CompileCommandsEntry {
|
struct CompileCommandsEntry {
|
||||||
fs::path directory;
|
std::string directory;
|
||||||
std::string file;
|
std::string file;
|
||||||
std::string command;
|
std::string command;
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
|
|
||||||
fs::path ResolveIfRelative(fs::path path) const {
|
std::string ResolveIfRelative(std::string path) const {
|
||||||
if (path.is_absolute())
|
if (sys::path::is_absolute(path))
|
||||||
return path;
|
return path;
|
||||||
return directory / path;
|
SmallString<256> Ret;
|
||||||
|
sys::path::append(Ret, directory, path);
|
||||||
|
return Ret.str();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
MAKE_REFLECT_STRUCT(CompileCommandsEntry, directory, file, command, args);
|
MAKE_REFLECT_STRUCT(CompileCommandsEntry, directory, file, command, args);
|
||||||
@ -56,7 +58,7 @@ 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::vector<std::string> extra_flags;
|
||||||
fs::path project_dir;
|
std::string project_dir;
|
||||||
ProjectMode mode = ProjectMode::CompileCommandsJson;
|
ProjectMode mode = ProjectMode::CompileCommandsJson;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -72,7 +74,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
const CompileCommandsEntry& entry) {
|
const CompileCommandsEntry& entry) {
|
||||||
Project::Entry result;
|
Project::Entry result;
|
||||||
result.filename = entry.file;
|
result.filename = entry.file;
|
||||||
const std::string base_name = fs::path(entry.file).filename();
|
const std::string base_name = sys::path::filename(entry.file);
|
||||||
|
|
||||||
// Expand %c %cpp %clang
|
// Expand %c %cpp %clang
|
||||||
std::vector<std::string> args;
|
std::vector<std::string> args;
|
||||||
@ -145,7 +147,7 @@ Project::Entry GetCompilationEntryFromCompileCommandEntry(
|
|||||||
if (!Args.hasArg(OPT_resource_dir))
|
if (!Args.hasArg(OPT_resource_dir))
|
||||||
args.push_back("-resource-dir=" + g_config->clang.resourceDir);
|
args.push_back("-resource-dir=" + g_config->clang.resourceDir);
|
||||||
if (!Args.hasArg(OPT_working_directory))
|
if (!Args.hasArg(OPT_working_directory))
|
||||||
args.push_back("-working-directory=" + entry.directory.string());
|
args.push_back("-working-directory=" + entry.directory);
|
||||||
|
|
||||||
// There could be a clang version mismatch between what the project uses and
|
// There could be a clang version mismatch between what the project uses and
|
||||||
// what ccls uses. Make sure we do not emit warnings for mismatched options.
|
// what ccls uses. Make sure we do not emit warnings for mismatched options.
|
||||||
@ -176,10 +178,11 @@ std::vector<std::string> ReadCompilerArgumentsFromFile(
|
|||||||
std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig* config) {
|
std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig* config) {
|
||||||
std::vector<Project::Entry> result;
|
std::vector<Project::Entry> result;
|
||||||
config->mode = ProjectMode::DotCcls;
|
config->mode = ProjectMode::DotCcls;
|
||||||
LOG_IF_S(WARNING, !fs::exists(config->project_dir / ".ccls") &&
|
SmallString<256> Path;
|
||||||
config->extra_flags.empty())
|
sys::path::append(Path, config->project_dir, ".ccls");
|
||||||
<< "ccls has no clang arguments. Considering adding either a "
|
LOG_IF_S(WARNING, !sys::fs::exists(Path) && config->extra_flags.empty())
|
||||||
"compile_commands.json or .ccls file. See the ccls README for "
|
<< "ccls has no clang arguments. Use either "
|
||||||
|
"compile_commands.json or .ccls, See ccls README for "
|
||||||
"more information.";
|
"more information.";
|
||||||
|
|
||||||
std::unordered_map<std::string, std::vector<std::string>> folder_args;
|
std::unordered_map<std::string, std::vector<std::string>> folder_args;
|
||||||
@ -190,21 +193,20 @@ std::vector<Project::Entry> LoadFromDirectoryListing(ProjectConfig* config) {
|
|||||||
[&folder_args, &files](const std::string& path) {
|
[&folder_args, &files](const std::string& path) {
|
||||||
if (SourceFileLanguage(path) != LanguageId::Unknown) {
|
if (SourceFileLanguage(path) != LanguageId::Unknown) {
|
||||||
files.push_back(path);
|
files.push_back(path);
|
||||||
} else if (fs::path(path).filename() == ".ccls") {
|
} else if (sys::path::filename(path) == ".ccls") {
|
||||||
LOG_S(INFO) << "Using .ccls arguments from " << path;
|
LOG_S(INFO) << "Using .ccls arguments from " << path;
|
||||||
folder_args.emplace(
|
folder_args.emplace(sys::path::parent_path(path),
|
||||||
fs::path(path).parent_path().string(),
|
|
||||||
ReadCompilerArgumentsFromFile(path));
|
ReadCompilerArgumentsFromFile(path));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const std::string project_dir = config->project_dir.string();
|
const std::string& project_dir = config->project_dir;
|
||||||
const auto& project_dir_args = folder_args[project_dir];
|
const auto& project_dir_args = folder_args[project_dir];
|
||||||
LOG_IF_S(INFO, !project_dir_args.empty())
|
LOG_IF_S(INFO, !project_dir_args.empty())
|
||||||
<< "Using .ccls arguments " << StringJoin(project_dir_args);
|
<< "Using .ccls arguments " << StringJoin(project_dir_args);
|
||||||
|
|
||||||
auto GetCompilerArgumentForFile = [&project_dir, &folder_args](fs::path cur) {
|
auto GetCompilerArgumentForFile = [&project_dir, &folder_args](std::string cur) {
|
||||||
while (!(cur = cur.parent_path()).empty()) {
|
while (!(cur = sys::path::parent_path(cur)).empty()) {
|
||||||
auto it = folder_args.find(cur);
|
auto it = folder_args.find(cur);
|
||||||
if (it != folder_args.end())
|
if (it != folder_args.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
@ -235,16 +237,20 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
|||||||
ProjectConfig* project,
|
ProjectConfig* project,
|
||||||
const std::string& opt_compilation_db_dir) {
|
const std::string& opt_compilation_db_dir) {
|
||||||
// If there is a .ccls file always load using directory listing.
|
// If there is a .ccls file always load using directory listing.
|
||||||
if (fs::exists(project->project_dir / ".ccls"))
|
SmallString<256> Path;
|
||||||
|
sys::path::append(Path, project->project_dir, ".ccls");
|
||||||
|
if (sys::fs::exists(Path))
|
||||||
return LoadFromDirectoryListing(project);
|
return LoadFromDirectoryListing(project);
|
||||||
|
|
||||||
// If |compilationDatabaseCommand| is specified, execute it to get the compdb.
|
// If |compilationDatabaseCommand| is specified, execute it to get the compdb.
|
||||||
fs::path comp_db_dir;
|
std::string comp_db_dir;
|
||||||
|
Path.clear();
|
||||||
if (g_config->compilationDatabaseCommand.empty()) {
|
if (g_config->compilationDatabaseCommand.empty()) {
|
||||||
project->mode = ProjectMode::CompileCommandsJson;
|
project->mode = ProjectMode::CompileCommandsJson;
|
||||||
// Try to load compile_commands.json, but fallback to a project listing.
|
// Try to load compile_commands.json, but fallback to a project listing.
|
||||||
comp_db_dir = opt_compilation_db_dir.empty() ? project->project_dir.string()
|
comp_db_dir = opt_compilation_db_dir.empty() ? project->project_dir
|
||||||
: opt_compilation_db_dir;
|
: opt_compilation_db_dir;
|
||||||
|
sys::path::append(Path, comp_db_dir, "compile_commands.json");
|
||||||
} else {
|
} else {
|
||||||
project->mode = ProjectMode::ExternalCommand;
|
project->mode = ProjectMode::ExternalCommand;
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@ -254,6 +260,7 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
|||||||
if (!mkdtemp(tmpdir))
|
if (!mkdtemp(tmpdir))
|
||||||
return {};
|
return {};
|
||||||
comp_db_dir = tmpdir;
|
comp_db_dir = tmpdir;
|
||||||
|
sys::path::append(Path, comp_db_dir, "compile_commands.json");
|
||||||
rapidjson::StringBuffer input;
|
rapidjson::StringBuffer input;
|
||||||
rapidjson::Writer<rapidjson::StringBuffer> writer(input);
|
rapidjson::Writer<rapidjson::StringBuffer> writer(input);
|
||||||
JsonWriter json_writer(&writer);
|
JsonWriter json_writer(&writer);
|
||||||
@ -262,14 +269,12 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
|||||||
std::vector<std::string>{g_config->compilationDatabaseCommand,
|
std::vector<std::string>{g_config->compilationDatabaseCommand,
|
||||||
project->project_dir},
|
project->project_dir},
|
||||||
input.GetString());
|
input.GetString());
|
||||||
FILE* fout = fopen((comp_db_dir / "compile_commands.json").c_str(), "wb");
|
FILE* fout = fopen(Path.c_str(), "wb");
|
||||||
fwrite(contents.c_str(), contents.size(), 1, fout);
|
fwrite(contents.c_str(), contents.size(), 1, fout);
|
||||||
fclose(fout);
|
fclose(fout);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path comp_db_path = comp_db_dir / "compile_commands.json";
|
|
||||||
LOG_S(INFO) << "Trying to load " << comp_db_path.string();
|
|
||||||
CXCompilationDatabase_Error cx_db_load_error;
|
CXCompilationDatabase_Error cx_db_load_error;
|
||||||
CXCompilationDatabase cx_db = clang_CompilationDatabase_fromDirectory(
|
CXCompilationDatabase cx_db = clang_CompilationDatabase_fromDirectory(
|
||||||
comp_db_dir.c_str(), &cx_db_load_error);
|
comp_db_dir.c_str(), &cx_db_load_error);
|
||||||
@ -277,17 +282,18 @@ std::vector<Project::Entry> LoadCompilationEntriesFromDirectory(
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// TODO
|
// TODO
|
||||||
#else
|
#else
|
||||||
unlink(comp_db_path.c_str());
|
unlink(Path.c_str());
|
||||||
rmdir(comp_db_dir.c_str());
|
rmdir(comp_db_dir.c_str());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cx_db_load_error == CXCompilationDatabase_CanNotLoadDatabase) {
|
if (cx_db_load_error == CXCompilationDatabase_CanNotLoadDatabase) {
|
||||||
LOG_S(INFO) << "Unable to load " << comp_db_path.string()
|
LOG_S(INFO) << "unable to load " << Path.c_str()
|
||||||
<< "; using directory listing instead.";
|
<< "; using directory listing instead.";
|
||||||
return LoadFromDirectoryListing(project);
|
return LoadFromDirectoryListing(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_S(INFO) << "loaded " << Path.c_str();
|
||||||
|
|
||||||
Timer clang_time;
|
Timer clang_time;
|
||||||
Timer our_time;
|
Timer our_time;
|
||||||
clang_time.Pause();
|
clang_time.Pause();
|
||||||
@ -437,13 +443,12 @@ Project::Entry Project::FindCompilationEntryForFile(
|
|||||||
|
|
||||||
// |best_entry| probably has its own path in the arguments. We need to remap
|
// |best_entry| probably has its own path in the arguments. We need to remap
|
||||||
// that path to the new filename.
|
// that path to the new filename.
|
||||||
fs::path best_entry_base_name = fs::path(best_entry->filename).filename();
|
std::string best_entry_base_name = sys::path::filename(best_entry->filename);
|
||||||
for (std::string& arg : result.args) {
|
for (std::string& arg : result.args) {
|
||||||
try {
|
try {
|
||||||
if (arg == best_entry->filename ||
|
if (arg == best_entry->filename ||
|
||||||
fs::path(arg).filename() == best_entry_base_name) {
|
sys::path::filename(arg) == best_entry_base_name)
|
||||||
arg = filename;
|
arg = filename;
|
||||||
}
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
16
src/query.cc
16
src/query.cc
@ -154,7 +154,7 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IndexFile& indexed) {
|
|||||||
|
|
||||||
// Returns true if an element with the same file is found.
|
// Returns true if an element with the same file is found.
|
||||||
template <typename Q>
|
template <typename Q>
|
||||||
bool TryReplaceDef(std::forward_list<Q>& def_list, Q&& def) {
|
bool TryReplaceDef(llvm::SmallVectorImpl<Q>& def_list, Q&& def) {
|
||||||
for (auto& def1 : def_list)
|
for (auto& def1 : def_list)
|
||||||
if (def1.spell->file_id == def.spell->file_id) {
|
if (def1.spell->file_id == def.spell->file_id) {
|
||||||
def1 = std::move(def);
|
def1 = std::move(def);
|
||||||
@ -262,18 +262,22 @@ void QueryDatabase::RemoveUsrs(
|
|||||||
case SymbolKind::Func: {
|
case SymbolKind::Func: {
|
||||||
for (auto usr : to_remove) {
|
for (auto usr : to_remove) {
|
||||||
QueryFunc& func = Func(usr);
|
QueryFunc& func = Func(usr);
|
||||||
func.def.remove_if([=](const QueryFunc::Def& def) {
|
auto it = llvm::find_if(func.def, [=](const QueryFunc::Def& def) {
|
||||||
return def.spell->file_id == file_id;
|
return def.spell->file_id == file_id;
|
||||||
});
|
});
|
||||||
|
if (it != func.def.end())
|
||||||
|
func.def.erase(it);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SymbolKind::Var: {
|
case SymbolKind::Var: {
|
||||||
for (auto usr : to_remove) {
|
for (auto usr : to_remove) {
|
||||||
QueryVar& var = Var(usr);
|
QueryVar& var = Var(usr);
|
||||||
var.def.remove_if([=](const QueryVar::Def& def) {
|
auto it = llvm::find_if(var.def, [=](const QueryVar::Def& def) {
|
||||||
return def.spell->file_id == file_id;
|
return def.spell->file_id == file_id;
|
||||||
});
|
});
|
||||||
|
if (it != var.def.end())
|
||||||
|
var.def.erase(it);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -348,7 +352,7 @@ void QueryDatabase::Update(int file_id,
|
|||||||
QueryFunc& existing = Func(u.first);
|
QueryFunc& existing = Func(u.first);
|
||||||
existing.usr = u.first;
|
existing.usr = u.first;
|
||||||
if (!TryReplaceDef(existing.def, std::move(def))) {
|
if (!TryReplaceDef(existing.def, std::move(def))) {
|
||||||
existing.def.push_front(std::move(def));
|
existing.def.push_back(std::move(def));
|
||||||
UpdateSymbols(&existing.symbol_idx, SymbolKind::Func, u.first);
|
UpdateSymbols(&existing.symbol_idx, SymbolKind::Func, u.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -364,7 +368,7 @@ void QueryDatabase::Update(int file_id,
|
|||||||
QueryType& existing = Type(u.first);
|
QueryType& existing = Type(u.first);
|
||||||
existing.usr = u.first;
|
existing.usr = u.first;
|
||||||
if (!TryReplaceDef(existing.def, std::move(def))) {
|
if (!TryReplaceDef(existing.def, std::move(def))) {
|
||||||
existing.def.push_front(std::move(def));
|
existing.def.push_back(std::move(def));
|
||||||
UpdateSymbols(&existing.symbol_idx, SymbolKind::Type, u.first);
|
UpdateSymbols(&existing.symbol_idx, SymbolKind::Type, u.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -380,7 +384,7 @@ void QueryDatabase::Update(int file_id,
|
|||||||
QueryVar& existing = Var(u.first);
|
QueryVar& existing = Var(u.first);
|
||||||
existing.usr = u.first;
|
existing.usr = u.first;
|
||||||
if (!TryReplaceDef(existing.def, std::move(def))) {
|
if (!TryReplaceDef(existing.def, std::move(def))) {
|
||||||
existing.def.push_front(std::move(def));
|
existing.def.push_back(std::move(def));
|
||||||
if (!existing.def.front().is_local())
|
if (!existing.def.front().is_local())
|
||||||
UpdateSymbols(&existing.symbol_idx, SymbolKind::Var, u.first);
|
UpdateSymbols(&existing.symbol_idx, SymbolKind::Var, u.first);
|
||||||
}
|
}
|
||||||
|
17
src/query.h
17
src/query.h
@ -3,9 +3,8 @@
|
|||||||
#include "indexer.h"
|
#include "indexer.h"
|
||||||
#include "serializer.h"
|
#include "serializer.h"
|
||||||
|
|
||||||
#include <sparsepp/spp.h>
|
#include <llvm/ADT/DenseMap.h>
|
||||||
|
#include <llvm/ADT/SmallVector.h>
|
||||||
#include <forward_list>
|
|
||||||
|
|
||||||
struct QueryFile;
|
struct QueryFile;
|
||||||
struct QueryType;
|
struct QueryType;
|
||||||
@ -69,7 +68,7 @@ using UsrUpdate =
|
|||||||
struct QueryFunc : QueryEntity<QueryFunc, FuncDef> {
|
struct QueryFunc : QueryEntity<QueryFunc, FuncDef> {
|
||||||
Usr usr;
|
Usr usr;
|
||||||
int symbol_idx = -1;
|
int symbol_idx = -1;
|
||||||
std::forward_list<Def> def;
|
llvm::SmallVector<Def, 1> def;
|
||||||
std::vector<Use> declarations;
|
std::vector<Use> declarations;
|
||||||
std::vector<Use> uses;
|
std::vector<Use> uses;
|
||||||
std::vector<Usr> derived;
|
std::vector<Usr> derived;
|
||||||
@ -78,7 +77,7 @@ struct QueryFunc : QueryEntity<QueryFunc, FuncDef> {
|
|||||||
struct QueryType : QueryEntity<QueryType, TypeDef> {
|
struct QueryType : QueryEntity<QueryType, TypeDef> {
|
||||||
Usr usr;
|
Usr usr;
|
||||||
int symbol_idx = -1;
|
int symbol_idx = -1;
|
||||||
std::forward_list<Def> def;
|
llvm::SmallVector<Def, 1> def;
|
||||||
std::vector<Use> declarations;
|
std::vector<Use> declarations;
|
||||||
std::vector<Use> uses;
|
std::vector<Use> uses;
|
||||||
std::vector<Usr> derived;
|
std::vector<Usr> derived;
|
||||||
@ -88,7 +87,7 @@ struct QueryType : QueryEntity<QueryType, TypeDef> {
|
|||||||
struct QueryVar : QueryEntity<QueryVar, VarDef> {
|
struct QueryVar : QueryEntity<QueryVar, VarDef> {
|
||||||
Usr usr;
|
Usr usr;
|
||||||
int symbol_idx = -1;
|
int symbol_idx = -1;
|
||||||
std::forward_list<Def> def;
|
llvm::SmallVector<Def, 1> def;
|
||||||
std::vector<Use> declarations;
|
std::vector<Use> declarations;
|
||||||
std::vector<Use> uses;
|
std::vector<Use> uses;
|
||||||
};
|
};
|
||||||
@ -138,9 +137,9 @@ struct QueryDatabase {
|
|||||||
|
|
||||||
std::vector<QueryFile> files;
|
std::vector<QueryFile> files;
|
||||||
std::unordered_map<std::string, int> name2file_id;
|
std::unordered_map<std::string, int> name2file_id;
|
||||||
spp::sparse_hash_map<Usr, QueryFunc> usr2func;
|
llvm::DenseMap<Usr, QueryFunc> usr2func;
|
||||||
spp::sparse_hash_map<Usr, QueryType> usr2type;
|
llvm::DenseMap<Usr, QueryType> usr2type;
|
||||||
spp::sparse_hash_map<Usr, QueryVar> usr2var;
|
llvm::DenseMap<Usr, QueryVar> usr2var;
|
||||||
|
|
||||||
// Marks the given Usrs as invalid.
|
// Marks the given Usrs as invalid.
|
||||||
void RemoveUsrs(SymbolKind usr_kind, const std::vector<Usr>& to_remove);
|
void RemoveUsrs(SymbolKind usr_kind, const std::vector<Usr>& to_remove);
|
||||||
|
@ -11,7 +11,7 @@ Maybe<Use> GetDefinitionExtent(QueryDatabase* db, SymbolIdx sym);
|
|||||||
// Get defining declaration (if exists) or an arbitrary declaration (otherwise)
|
// Get defining declaration (if exists) or an arbitrary declaration (otherwise)
|
||||||
// for each id.
|
// for each id.
|
||||||
template <typename Q>
|
template <typename Q>
|
||||||
std::vector<Use> GetDeclarations(spp::sparse_hash_map<Usr, Q>& usr2entity,
|
std::vector<Use> GetDeclarations(llvm::DenseMap<Usr, Q>& usr2entity,
|
||||||
const std::vector<Usr>& usrs) {
|
const std::vector<Usr>& usrs) {
|
||||||
std::vector<Use> ret;
|
std::vector<Use> ret;
|
||||||
ret.reserve(usrs.size());
|
ret.reserve(usrs.size());
|
||||||
@ -135,7 +135,7 @@ void EachOccurrenceWithParent(QueryDatabase* db,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename Q, typename Fn>
|
template <typename Q, typename Fn>
|
||||||
void EachDefinedEntity(spp::sparse_hash_map<Usr, Q>& collection,
|
void EachDefinedEntity(llvm::DenseMap<Usr, Q>& collection,
|
||||||
const std::vector<Usr>& usrs,
|
const std::vector<Usr>& usrs,
|
||||||
Fn&& fn) {
|
Fn&& fn) {
|
||||||
for (Usr usr : usrs) {
|
for (Usr usr : usrs) {
|
||||||
|
@ -160,7 +160,7 @@ void Reflect(Writer& visitor, IndexInclude& value) {
|
|||||||
REFLECT_MEMBER_START();
|
REFLECT_MEMBER_START();
|
||||||
REFLECT_MEMBER(line);
|
REFLECT_MEMBER(line);
|
||||||
if (gTestOutputMode) {
|
if (gTestOutputMode) {
|
||||||
std::string basename = fs::path(value.resolved_path).filename();
|
std::string basename = llvm::sys::path::filename(value.resolved_path);
|
||||||
if (!StartsWith(value.resolved_path, "&"))
|
if (!StartsWith(value.resolved_path, "&"))
|
||||||
basename = "&" + basename;
|
basename = "&" + basename;
|
||||||
REFLECT_MEMBER2("resolved_path", basename);
|
REFLECT_MEMBER2("resolved_path", basename);
|
||||||
|
11
src/utils.cc
11
src/utils.cc
@ -1,6 +1,7 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include "filesystem.hh"
|
#include "filesystem.hh"
|
||||||
|
using namespace llvm;
|
||||||
#include "platform.h"
|
#include "platform.h"
|
||||||
|
|
||||||
#include <doctest/doctest.h>
|
#include <doctest/doctest.h>
|
||||||
@ -137,12 +138,10 @@ void WriteToFile(const std::string& filename, const std::string& content) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<int64_t> LastWriteTime(const std::string& filename) {
|
std::optional<int64_t> LastWriteTime(const std::string& filename) {
|
||||||
std::error_code ec;
|
sys::fs::file_status Status;
|
||||||
auto ftime = fs::last_write_time(filename, ec);
|
if (sys::fs::status(filename, Status))
|
||||||
if (ec) return std::nullopt;
|
return {};
|
||||||
return std::chrono::time_point_cast<std::chrono::nanoseconds>(ftime)
|
return Status.getLastModificationTime().time_since_epoch().count();
|
||||||
.time_since_epoch()
|
|
||||||
.count();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetDefaultResourceDirectory() {
|
std::string GetDefaultResourceDirectory() {
|
||||||
|
1
third_party/sparsepp
vendored
1
third_party/sparsepp
vendored
@ -1 +0,0 @@
|
|||||||
Subproject commit 1ca7189fe81ee8c59bf08196852f70843a68a63a
|
|
Loading…
Reference in New Issue
Block a user