141 lines · c
1//===--- URI.h - File URIs with schemes --------------------------*- C++-*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_URI_H10#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_URI_H11 12#include "llvm/ADT/StringRef.h"13#include "llvm/Support/Error.h"14#include "llvm/Support/Registry.h"15 16namespace clang {17namespace clangd {18 19/// A URI describes the location of a source file.20/// In the simplest case, this is a "file" URI that directly encodes the21/// absolute path to a file. More abstract cases are possible: a shared index22/// service might expose repo:// URIs that are relative to the source control23/// root.24///25/// Clangd handles URIs of the form <scheme>:[//<authority>]<body>. It doesn't26/// further split the authority or body into constituent parts (e.g. query27/// strings is included in the body).28class URI {29public:30 URI(llvm::StringRef Scheme, llvm::StringRef Authority, llvm::StringRef Body);31 32 /// Returns decoded scheme e.g. "https"33 llvm::StringRef scheme() const { return Scheme; }34 /// Returns decoded authority e.g. "reviews.lvm.org"35 llvm::StringRef authority() const { return Authority; }36 /// Returns decoded body e.g. "/D41946"37 llvm::StringRef body() const { return Body; }38 39 /// Returns a string URI with all components percent-encoded.40 std::string toString() const;41 42 /// Creates a URI for a file in the given scheme. \p Scheme must be43 /// registered. The URI is percent-encoded.44 static llvm::Expected<URI> create(llvm::StringRef AbsolutePath,45 llvm::StringRef Scheme);46 47 // Similar to above except this picks a registered scheme that works. If none48 // works, this falls back to "file" scheme.49 static URI create(llvm::StringRef AbsolutePath);50 51 /// This creates a file:// URI for \p AbsolutePath. The path must be absolute.52 static URI createFile(llvm::StringRef AbsolutePath);53 54 /// Parse a URI string "<scheme>:[//<authority>/]<path>". Percent-encoded55 /// characters in the URI will be decoded.56 static llvm::Expected<URI> parse(llvm::StringRef Uri);57 58 /// Resolves the absolute path of \p U. If there is no matching scheme, or the59 /// URI is invalid in the scheme, this returns an error.60 ///61 /// \p HintPath A related path, such as the current file or working directory,62 /// which can help disambiguate when the same file exists in many workspaces.63 static llvm::Expected<std::string> resolve(const URI &U,64 llvm::StringRef HintPath = "");65 66 /// Same as above, in addition it parses the \p FileURI using URI::parse.67 static llvm::Expected<std::string> resolve(llvm::StringRef FileURI,68 llvm::StringRef HintPath = "");69 70 /// Resolves \p AbsPath into a canonical path of its URI, by converting71 /// \p AbsPath to URI and resolving the URI to get th canonical path.72 /// This ensures that paths with the same URI are resolved into consistent73 /// file path.74 static llvm::Expected<std::string> resolvePath(llvm::StringRef AbsPath,75 llvm::StringRef HintPath = "");76 77 /// Gets the preferred spelling of this file for #include, if there is one,78 /// e.g. <system_header.h>, "path/to/x.h".79 ///80 /// This allows URI schemas to provide their customized include paths.81 ///82 /// Returns an empty string if normal include-shortening based on the absolute83 /// path should be used.84 /// Fails if the URI is not valid in the schema.85 static llvm::Expected<std::string> includeSpelling(const URI &U);86 87 friend bool operator==(const URI &LHS, const URI &RHS) {88 return std::tie(LHS.Scheme, LHS.Authority, LHS.Body) ==89 std::tie(RHS.Scheme, RHS.Authority, RHS.Body);90 }91 92 friend bool operator<(const URI &LHS, const URI &RHS) {93 return std::tie(LHS.Scheme, LHS.Authority, LHS.Body) <94 std::tie(RHS.Scheme, RHS.Authority, RHS.Body);95 }96 97private:98 URI() = default;99 100 std::string Scheme;101 std::string Authority;102 std::string Body;103};104 105/// URIScheme is an extension point for teaching clangd to recognize a custom106/// URI scheme. This is expected to be implemented and exposed via the107/// URISchemeRegistry.108class URIScheme {109public:110 virtual ~URIScheme() = default;111 112 /// Returns the absolute path of the file corresponding to the URI113 /// authority+body in the file system. See URI::resolve for semantics of114 /// \p HintPath.115 virtual llvm::Expected<std::string>116 getAbsolutePath(llvm::StringRef Authority, llvm::StringRef Body,117 llvm::StringRef HintPath) const = 0;118 119 virtual llvm::Expected<URI>120 uriFromAbsolutePath(llvm::StringRef AbsolutePath) const = 0;121 122 /// Returns the include path of the file (e.g. <path>, "path"), which can be123 /// #included directly. See URI::includeSpelling for details.124 virtual llvm::Expected<std::string> getIncludeSpelling(const URI &U) const {125 return ""; // no customized include path for this scheme.126 }127};128 129/// By default, a "file" scheme is supported where URI paths are always absolute130/// in the file system.131typedef llvm::Registry<URIScheme> URISchemeRegistry;132 133} // namespace clangd134} // namespace clang135 136namespace llvm {137extern template class Registry<clang::clangd::URIScheme>;138} // namespace llvm139 140#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_URI_H141