Normalize paths on Windows

1. Normalize paths in LSP document URIs and project root to forward
slash and uppercase drive letters.
2. Normalize paths in compile_commands.json to forward slash and
uppercase drive letters.
3. Normalize paths from directory listing to forward slash. (Drive
letter should be same as input dir path, which is already uppercase
since path of project root dir is normalized)
4. Add llvm::sys::path::convert_to_slash after certain llvm::sys::path
and llvm::fs calls.
This commit is contained in:
Riatre Foo 2018-09-12 03:13:54 +08:00 committed by Fangrui Song
parent 709a2654a8
commit 3c5ab61762
7 changed files with 31 additions and 12 deletions

View File

@ -28,7 +28,7 @@ namespace {
std::string StripFileType(const std::string &path) { std::string StripFileType(const std::string &path) {
SmallString<128> Ret; SmallString<128> Ret;
sys::path::append(Ret, sys::path::parent_path(path), sys::path::stem(path)); sys::path::append(Ret, sys::path::parent_path(path), sys::path::stem(path));
return Ret.str(); return sys::path::convert_to_slash(Ret);
} }
bool LocationInRange(SourceLocation L, CharSourceRange R, bool LocationInRange(SourceLocation L, CharSourceRange R,

View File

@ -22,7 +22,7 @@ std::string FileName(const FileEntry &file) {
if (!StartsWith(ret, g_config->projectRoot)) { if (!StartsWith(ret, g_config->projectRoot)) {
SmallString<256> dest; SmallString<256> dest;
sys::fs::real_path(ret, dest); sys::fs::real_path(ret, dest);
ret = dest.str(); ret = sys::path::convert_to_slash(dest.str());
} }
return ret; return ret;
} }

View File

@ -47,7 +47,7 @@ void GetFilesInFolder(std::string folder, bool recursive, bool dir_prefix,
if (sys::fs::is_regular_file(Status)) { if (sys::fs::is_regular_file(Status)) {
if (!dir_prefix) if (!dir_prefix)
path = path.substr(folder.size()); path = path.substr(folder.size());
handler(path); handler(sys::path::convert_to_slash(path));
} else if (recursive && sys::fs::is_directory(Status) && } else if (recursive && sys::fs::is_directory(Status) &&
!seen.count(ID = Status.getUniqueID())) { !seen.count(ID = Status.getUniqueID())) {
curr.push_back(path); curr.push_back(path);

View File

@ -552,7 +552,7 @@ public:
if (!llvm::sys::path::is_absolute(Path) && if (!llvm::sys::path::is_absolute(Path) &&
!SM.getFileManager().makeAbsolutePath(Path)) !SM.getFileManager().makeAbsolutePath(Path))
return -1; return -1;
it->second.second = Path.str(); it->second.second = llvm::sys::path::convert_to_slash(Path.str());
} }
return it->second.first; return it->second.first;
} }

View File

@ -8,6 +8,7 @@
#include <rapidjson/writer.h> #include <rapidjson/writer.h>
#include <algorithm>
#include <stdio.h> #include <stdio.h>
MessageRegistry *MessageRegistry::instance_ = nullptr; MessageRegistry *MessageRegistry::instance_ = nullptr;
@ -208,10 +209,15 @@ void lsDocumentUri::SetPath(const std::string &path) {
} }
std::string lsDocumentUri::GetPath() const { std::string lsDocumentUri::GetPath() const {
if (raw_uri.compare(0, 8, "file:///")) if (raw_uri.compare(0, 7, "file://")) {
LOG_S(WARNING)
<< "Received potentially bad URI (not starting with file://): "
<< raw_uri;
return raw_uri; return raw_uri;
}
std::string ret; std::string ret;
#ifdef _WIN32 #ifdef _WIN32
// Skipping the initial "/" on Windows
size_t i = 8; size_t i = 8;
#else #else
size_t i = 7; size_t i = 7;
@ -224,8 +230,14 @@ std::string lsDocumentUri::GetPath() const {
ret.push_back(from_hex(raw_uri[i + 1]) * 16 + from_hex(raw_uri[i + 2])); ret.push_back(from_hex(raw_uri[i + 1]) * 16 + from_hex(raw_uri[i + 2]));
i += 2; i += 2;
} else } else
ret.push_back(raw_uri[i] == '\\' ? '/' : raw_uri[i]); ret.push_back(raw_uri[i]);
} }
#ifdef _WIN32
std::replace(ret.begin(), ret.end(), '\\', '/');
if (ret.size() > 1 && ret[0] >= 'a' && ret[0] <= 'z' && ret[1] == ':') {
ret[0] = toupper(ret[0]);
}
#endif
return ret; return ret;
} }

View File

@ -23,14 +23,19 @@ std::string NormalizePath(const std::string &path) {
TCHAR buffer[MAX_PATH] = TEXT(""); TCHAR buffer[MAX_PATH] = TEXT("");
TCHAR **lpp_part = {NULL}; TCHAR **lpp_part = {NULL};
std::string result;
retval = GetFullPathName(path.c_str(), MAX_PATH, buffer, lpp_part); retval = GetFullPathName(path.c_str(), MAX_PATH, buffer, lpp_part);
// fail, return original // fail, return original
if (retval == 0) if (retval == 0)
return path; result = path;
else
result = buffer;
std::string result = buffer;
std::replace(result.begin(), result.end(), '\\', '/'); std::replace(result.begin(), result.end(), '\\', '/');
// std::transform(result.begin(), result.end(), result.begin(), ::tolower); // Normalize drive letter.
if (result.size() > 1 && result[0] >= 'a' && result[0] <= 'z' &&
result[1] == ':')
result[0] = toupper(result[0]);
return result; return result;
} }

View File

@ -160,7 +160,8 @@ struct ProjectProcessor {
HeaderSearchOptions &HeaderOpts = CI->getHeaderSearchOpts(); HeaderSearchOptions &HeaderOpts = CI->getHeaderSearchOpts();
for (auto &E : HeaderOpts.UserEntries) { for (auto &E : HeaderOpts.UserEntries) {
std::string path = ResolveIfRelative(entry.directory, E.Path); std::string path =
NormalizePath(ResolveIfRelative(entry.directory, E.Path));
switch (E.Group) { switch (E.Group) {
default: default:
config->angle_dirs.insert(path); config->angle_dirs.insert(path);
@ -315,8 +316,9 @@ LoadEntriesFromDirectory(ProjectConfig *project,
ProjectProcessor proc(project); ProjectProcessor proc(project);
for (tooling::CompileCommand &Cmd : CDB->getAllCompileCommands()) { for (tooling::CompileCommand &Cmd : CDB->getAllCompileCommands()) {
Project::Entry entry; Project::Entry entry;
entry.directory = std::move(Cmd.Directory); entry.directory = NormalizePath(Cmd.Directory);
entry.filename = ResolveIfRelative(entry.directory, Cmd.Filename); entry.filename =
NormalizePath(ResolveIfRelative(entry.directory, Cmd.Filename));
entry.args = std::move(Cmd.CommandLine); entry.args = std::move(Cmd.CommandLine);
proc.Process(entry); proc.Process(entry);
if (Seen.insert(entry.filename).second) if (Seen.insert(entry.filename).second)