mirror of
https://github.com/MaskRay/ccls.git
synced 2025-01-18 11:35:49 +00:00
Support workspaces as symlinks and symlinks within a workspace
Fix #639
This commit is contained in:
parent
5108cfafcb
commit
ca95f48a53
@ -20,12 +20,22 @@ using namespace clang;
|
|||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
std::string pathFromFileEntry(const FileEntry &file) {
|
std::string pathFromFileEntry(const FileEntry &file) {
|
||||||
StringRef name = file.tryGetRealPathName();
|
std::string ret;
|
||||||
if (name.empty())
|
if (file.getName().startswith("/../")) {
|
||||||
name = file.getName();
|
// Resolve symlinks outside of working folders. This handles leading path
|
||||||
std::string ret = normalizePath(name);
|
// components, e.g. (/lib -> /usr/lib) in
|
||||||
// Resolve symlinks outside of workspace folders, e.g. /usr/include/c++/7.3.0
|
// /../lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/utility
|
||||||
return normalizeFolder(ret) ? ret : realPath(ret);
|
ret = file.tryGetRealPathName();
|
||||||
|
} else {
|
||||||
|
// If getName() refers to a file within a workspace folder, we prefer it
|
||||||
|
// (which may be a symlink).
|
||||||
|
ret = normalizePath(file.getName());
|
||||||
|
}
|
||||||
|
if (normalizeFolder(ret))
|
||||||
|
return ret;
|
||||||
|
ret = realPath(ret);
|
||||||
|
normalizeFolder(ret);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isInsideMainFile(const SourceManager &sm, SourceLocation sl) {
|
bool isInsideMainFile(const SourceManager &sm, SourceLocation sl) {
|
||||||
|
@ -348,17 +348,16 @@ void do_initialize(MessageHandler *m, InitializeParam ¶m,
|
|||||||
std::string path = wf.uri.getPath();
|
std::string path = wf.uri.getPath();
|
||||||
ensureEndsInSlash(path);
|
ensureEndsInSlash(path);
|
||||||
std::string real = realPath(path) + '/';
|
std::string real = realPath(path) + '/';
|
||||||
workspaceFolders.emplace_back(path, path == real ? "" : real);
|
workspaceFolders.emplace_back(path, real);
|
||||||
}
|
}
|
||||||
if (workspaceFolders.empty()) {
|
if (workspaceFolders.empty()) {
|
||||||
std::string real = realPath(project_path) + '/';
|
std::string real = realPath(project_path) + '/';
|
||||||
workspaceFolders.emplace_back(project_path,
|
workspaceFolders.emplace_back(project_path, real);
|
||||||
project_path == real ? "" : real);
|
|
||||||
}
|
}
|
||||||
std::sort(workspaceFolders.begin(), workspaceFolders.end(),
|
std::sort(workspaceFolders.begin(), workspaceFolders.end(),
|
||||||
[](auto &l, auto &r) { return l.first.size() > r.first.size(); });
|
[](auto &l, auto &r) { return l.first.size() > r.first.size(); });
|
||||||
for (auto &[folder, real] : workspaceFolders)
|
for (auto &[folder, real] : workspaceFolders)
|
||||||
if (real.empty())
|
if (real == folder)
|
||||||
LOG_S(INFO) << "workspace folder: " << folder;
|
LOG_S(INFO) << "workspace folder: " << folder;
|
||||||
else
|
else
|
||||||
LOG_S(INFO) << "workspace folder: " << folder << " -> " << real;
|
LOG_S(INFO) << "workspace folder: " << folder << " -> " << real;
|
||||||
|
@ -433,7 +433,9 @@ void Project::loadDirectory(const std::string &root, Project::Folder &folder) {
|
|||||||
// If workspace folder is real/ but entries use symlink/, convert to
|
// If workspace folder is real/ but entries use symlink/, convert to
|
||||||
// real/.
|
// real/.
|
||||||
entry.directory = realPath(cmd.Directory);
|
entry.directory = realPath(cmd.Directory);
|
||||||
|
entry.directory.push_back('/');
|
||||||
normalizeFolder(entry.directory);
|
normalizeFolder(entry.directory);
|
||||||
|
entry.directory.pop_back();
|
||||||
doPathMapping(entry.directory);
|
doPathMapping(entry.directory);
|
||||||
entry.filename =
|
entry.filename =
|
||||||
realPath(resolveIfRelative(entry.directory, cmd.Filename));
|
realPath(resolveIfRelative(entry.directory, cmd.Filename));
|
||||||
|
@ -138,11 +138,15 @@ std::string realPath(const std::string &path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool normalizeFolder(std::string &path) {
|
bool normalizeFolder(std::string &path) {
|
||||||
for (auto &[root, real] : g_config->workspaceFolders)
|
for (auto &[root, real] : g_config->workspaceFolders) {
|
||||||
if (real.size() && llvm::StringRef(path).startswith(real)) {
|
StringRef p(path);
|
||||||
|
if (p.startswith(root))
|
||||||
|
return true;
|
||||||
|
if (p.startswith(real)) {
|
||||||
path = root + path.substr(real.size());
|
path = root + path.substr(real.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user