diff clang-tools-extra/clangd/URI.cpp @ 221:79ff65ed7e25

LLVM12 Original
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 15 Jun 2021 19:15:29 +0900
parents 1d019706d866
children c4bab56944e8
line wrap: on
line diff
--- a/clang-tools-extra/clangd/URI.cpp	Tue Jun 15 19:13:43 2021 +0900
+++ b/clang-tools-extra/clangd/URI.cpp	Tue Jun 15 19:15:29 2021 +0900
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "URI.h"
+#include "support/Logger.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/Error.h"
@@ -21,9 +22,13 @@
 namespace clangd {
 namespace {
 
-inline llvm::Error make_string_error(const llvm::Twine &Message) {
-  return llvm::make_error<llvm::StringError>(Message,
-                                             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
@@ -33,28 +38,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] == ':')
+      return error("File scheme: expect body to be an absolute path starting "
+                   "with '/': {0}",
+                   Body);
+    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);
   }
 };
 
@@ -63,13 +80,12 @@
   if (Scheme == "file")
     return std::make_unique<FileSystemScheme>();
 
-  for (auto I = URISchemeRegistry::begin(), E = URISchemeRegistry::end();
-       I != E; ++I) {
-    if (I->getName() != Scheme)
+  for (const auto &URIScheme : URISchemeRegistry::entries()) {
+    if (URIScheme.getName() != Scheme)
       continue;
-    return I->instantiate();
+    return URIScheme.instantiate();
   }
-  return make_string_error("Can't find scheme: " + Scheme);
+  return error("Can't find scheme: {0}", Scheme);
 }
 
 bool shouldEscape(unsigned char C) {
@@ -95,15 +111,14 @@
 /// - Reserved characters always escaped with exceptions like '/'.
 /// - All other characters are escaped.
 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.
@@ -167,12 +182,11 @@
 
   auto Pos = Uri.find(':');
   if (Pos == llvm::StringRef::npos)
-    return make_string_error("Scheme must be provided in URI: " + OrigUri);
+    return error("Scheme must be provided in URI: {0}", OrigUri);
   auto SchemeStr = Uri.substr(0, Pos);
   U.Scheme = percentDecode(SchemeStr);
   if (!isValidScheme(U.Scheme))
-    return make_string_error(llvm::formatv("Invalid scheme: {0} (decoded: {1})",
-                                           SchemeStr, U.Scheme));
+    return error("Invalid scheme: {0} (decoded: {1})", SchemeStr, U.Scheme);
   Uri = Uri.substr(Pos + 1);
   if (Uri.consume_front("//")) {
     Pos = Uri.find('/');
@@ -197,7 +211,7 @@
 llvm::Expected<URI> URI::create(llvm::StringRef AbsolutePath,
                                 llvm::StringRef Scheme) {
   if (!llvm::sys::path::is_absolute(AbsolutePath))
-    return make_string_error("Not a valid absolute path: " + AbsolutePath);
+    return error("Not a valid absolute path: {0}", AbsolutePath);
   auto S = findSchemeByName(Scheme);
   if (!S)
     return S.takeError();