This revision was automatically updated to reflect the committed changes.
Closed by commit rG3975c3be8041: [clangd] Fix conversion from Windows UNC paths
to file URI format. (authored by walrus, committed by kbobyrev).
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D84172/new/
https://reviews.llvm.org/D84172
Files:
clang-tools-extra/clangd/URI.cpp
clang-tools-extra/clangd/unittests/URITests.cpp
Index: clang-tools-extra/clangd/unittests/URITests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/URITests.cpp
+++ clang-tools-extra/clangd/unittests/URITests.cpp
@@ -76,6 +76,16 @@
#endif
}
+TEST(URITest, CreateUNC) {
+#ifdef _WIN32
+ EXPECT_THAT(createOrDie("\\\\test.org\\x\\y\\z"), "file://test.org/x/y/z");
+ EXPECT_THAT(createOrDie("\\\\10.0.0.1\\x\\y\\z"), "file://10.0.0.1/x/y/z");
+#else
+ EXPECT_THAT(createOrDie("//test.org/x/y/z"), "file://test.org/x/y/z");
+ EXPECT_THAT(createOrDie("//10.0.0.1/x/y/z"), "file://10.0.0.1/x/y/z");
+#endif
+}
+
TEST(URITest, FailedCreate) {
EXPECT_ERROR(URI::create("/x/y/z", "no"));
// Path has to be absolute.
@@ -127,15 +137,32 @@
EXPECT_THAT(resolveOrDie(parseOrDie("file:///c:/x/y/z")), "c:\\x\\y\\z");
#else
EXPECT_EQ(resolveOrDie(parseOrDie("file:/a/b/c")), "/a/b/c");
- EXPECT_EQ(resolveOrDie(parseOrDie("file://auth/a/b/c")), "/a/b/c");
+ EXPECT_EQ(resolveOrDie(parseOrDie("file://auth/a/b/c")), "//auth/a/b/c");
EXPECT_THAT(resolveOrDie(parseOrDie("file://au%3dth/%28x%29/y/%20z")),
- "/(x)/y/ z");
+ "//au=th/(x)/y/ z");
EXPECT_THAT(resolveOrDie(parseOrDie("file:///c:/x/y/z")), "c:/x/y/z");
#endif
EXPECT_EQ(resolveOrDie(parseOrDie("unittest:///a"), testPath("x")),
testPath("a"));
}
+TEST(URITest, ResolveUNC) {
+#ifdef _WIN32
+ EXPECT_THAT(resolveOrDie(parseOrDie("file://example.com/x/y/z")),
+ "\\\\example.com\\x\\y\\z");
+ EXPECT_THAT(resolveOrDie(parseOrDie("file://127.0.0.1/x/y/z")),
+ "\\\\127.0.0.1\\x\\y\\z");
+ // Ensure non-traditional file URI still resolves to correct UNC path.
+ EXPECT_THAT(resolveOrDie(parseOrDie("file:////127.0.0.1/x/y/z")),
+ "\\\\127.0.0.1\\x\\y\\z");
+#else
+ EXPECT_THAT(resolveOrDie(parseOrDie("file://example.com/x/y/z")),
+ "//example.com/x/y/z");
+ EXPECT_THAT(resolveOrDie(parseOrDie("file://127.0.0.1/x/y/z")),
+ "//127.0.0.1/x/y/z");
+#endif
+}
+
std::string resolvePathOrDie(llvm::StringRef AbsPath,
llvm::StringRef HintPath = "") {
auto Path = URI::resolvePath(AbsPath, HintPath);
Index: clang-tools-extra/clangd/URI.cpp
===================================================================
--- clang-tools-extra/clangd/URI.cpp
+++ clang-tools-extra/clangd/URI.cpp
@@ -26,6 +26,15 @@
llvm::inconvertibleErrorCode());
}
+bool isWindowsPath(llvm::StringRef Path) {
+ return Path.size() > 1 && llvm::isAlpha(Path[0]) && Path[1] == ':';
+}
+
+bool isNetworkPath(llvm::StringRef Path) {
+ return Path.size() > 2 && Path[0] == Path[1] &&
+ llvm::sys::path::is_separator(Path[0]);
+}
+
/// This manages file paths in the file system. All paths in the scheme
/// are absolute (with leading '/').
/// Note that this scheme is hardcoded into the library and not registered in
@@ -33,28 +42,40 @@
class FileSystemScheme : public URIScheme {
public:
llvm::Expected<std::string>
- getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body,
+ getAbsolutePath(llvm::StringRef Authority, llvm::StringRef Body,
llvm::StringRef /*HintPath*/) const override {
if (!Body.startswith("/"))
return make_string_error("File scheme: expect body to be an absolute "
"path starting with '/': " +
Body);
- // For Windows paths e.g. /X:
- if (Body.size() > 2 && Body[0] == '/' && Body[2] == ':')
+ llvm::SmallString<128> Path;
+ if (!Authority.empty()) {
+ // Windows UNC paths e.g. file://server/share => \\server\share
+ ("//" + Authority).toVector(Path);
+ } else if (isWindowsPath(Body.substr(1))) {
+ // Windows paths e.g. file:///X:/path => X:\path
Body.consume_front("/");
- llvm::SmallVector<char, 16> Path(Body.begin(), Body.end());
+ }
+ Path.append(Body);
llvm::sys::path::native(Path);
- return std::string(Path.begin(), Path.end());
+ return std::string(Path);
}
llvm::Expected<URI>
uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override {
std::string Body;
- // For Windows paths e.g. X:
- if (AbsolutePath.size() > 1 && AbsolutePath[1] == ':')
+ llvm::StringRef Authority;
+ llvm::StringRef Root = llvm::sys::path::root_name(AbsolutePath);
+ if (isNetworkPath(Root)) {
+ // Windows UNC paths e.g. \\server\share => file://server/share
+ Authority = Root.drop_front(2);
+ AbsolutePath.consume_front(Root);
+ } else if (isWindowsPath(Root)) {
+ // Windows paths e.g. X:\path => file:///X:/path
Body = "/";
+ }
Body += llvm::sys::path::convert_to_slash(AbsolutePath);
- return URI("file", /*Authority=*/"", Body);
+ return URI("file", Authority, Body);
}
};
@@ -96,13 +117,13 @@
void percentEncode(llvm::StringRef Content, std::string &Out) {
std::string Result;
for (unsigned char C : Content)
- if (shouldEscape(C))
- {
+ if (shouldEscape(C)) {
Out.push_back('%');
Out.push_back(llvm::hexdigit(C / 16));
Out.push_back(llvm::hexdigit(C % 16));
- } else
- { Out.push_back(C); }
+ } else {
+ Out.push_back(C);
+ }
}
/// Decodes a string according to percent-encoding.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits