From bf9a55de7112f42f44ada6c20e71d3fc3b251e4d Mon Sep 17 00:00:00 2001 From: Remi Thebault Date: Mon, 19 Jun 2023 15:18:44 +0200 Subject: [PATCH] normalize uri and CCDB filename on Windows drive letter is now always lower case --- protocol/source/served/lsp/uri.d | 11 ++++++++--- workspace-d/source/workspaced/com/ccdb.d | 22 ++++++++++++++++++---- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/protocol/source/served/lsp/uri.d b/protocol/source/served/lsp/uri.d index 06003dd6..c2fa2348 100644 --- a/protocol/source/served/lsp/uri.d +++ b/protocol/source/served/lsp/uri.d @@ -19,7 +19,12 @@ DocumentUri uriFromFile(scope const(char)[] file) if ((!isAbsolute(file) && !file.startsWith("/")) || !file.length) throw new Exception(text("Tried to pass relative path '", file, "' to uriFromFile")); - file = file.buildNormalizedPath.replace("\\", "/"); + file = file.buildNormalizedPath(); + version(Windows) + { + file = file.replace("\\", "/"); + file = driveName(file).toLower() ~ stripDrive(file); + } assert(file.length); if (file.ptr[0] != '/') file = '/' ~ file; // always triple slash at start but never quad slash @@ -34,7 +39,7 @@ unittest version (Windows) { - + assertEquals(uriFromFile(`C:\Home\foo\bar.d`), `file://c%3A/Home/foo/bar.d`); } else { @@ -283,7 +288,7 @@ unittest { assertEquals(uriNormalize(`b/../a.d`), `a.d`); assertEquals(uriNormalize(`b/../../a.d`), `../a.d`); - + foreach (prefix; ["file:///", "file://", "", "/", "//"]) { assertEquals(uriNormalize(prefix ~ `foo/bar/./a.d`), prefix ~ `foo/bar/a.d`); diff --git a/workspace-d/source/workspaced/com/ccdb.d b/workspace-d/source/workspaced/com/ccdb.d index e0831920..58071186 100644 --- a/workspace-d/source/workspaced/com/ccdb.d +++ b/workspace-d/source/workspaced/com/ccdb.d @@ -6,6 +6,7 @@ module workspaced.com.ccdb; import std.exception; import std.json; import std.path; +import std.string; import fs = std.file; import workspaced.api; @@ -144,7 +145,7 @@ class ClangCompilationDatabaseComponent : ComponentWrapper /// in the database. CompileCommand getCompileCommand(string filename) @property { - auto normalized = buildNormalizedPath(filename); + const normalized = normalizedCcdbPath(filename); auto ccp = normalized in _compileCommands; if (ccp) return *ccp; @@ -171,8 +172,10 @@ public class CompileCommand import std.algorithm : map; import std.array : array; - this.directory = enforce("directory" in json, "'directory' missing from Clang compilation database entry") - .str; + this.directory = normalizedCcdbPath( + enforce("directory" in json, "'directory' missing from Clang compilation database entry") + .str + ); this.file = enforce("file" in json, "'file' missing from Clang compilation database entry") .str; @@ -209,7 +212,7 @@ public class CompileCommand string getNormalizedFilePath() const { - return getPath(file).buildNormalizedPath(); + return normalizedCcdbPath(getPath(file)); } string getPath(string filename) const @@ -303,6 +306,17 @@ public class CompileCommand } } +string normalizedCcdbPath(string filePath) +{ + const normalized = filePath.buildNormalizedPath(); + // Let the drive be lower case on Windows (not handled by buildNormalizedPath). + // This is needed because commands are resolved by simple string comparison. + version (Windows) + return driveName(normalized).toLower() ~ stripDrive(normalized); + else + return normalized; +} + void feedOptions( in CompileCommand cc, ref HashSet!string imports,