11 #include "llvm/ADT/Twine.h" 12 #include "llvm/Support/Error.h" 13 #include "llvm/Support/Format.h" 14 #include "llvm/Support/Path.h" 24 inline llvm::Error make_string_error(
const llvm::Twine &
Message) {
25 return llvm::make_error<llvm::StringError>(
Message,
26 llvm::inconvertibleErrorCode());
31 class FileSystemScheme :
public URIScheme {
35 llvm::Expected<std::string>
36 getAbsolutePath(llvm::StringRef , llvm::StringRef Body,
37 llvm::StringRef )
const override {
38 if (!Body.startswith(
"/"))
39 return make_string_error(
"File scheme: expect body to be an absolute " 40 "path starting with '/': " +
43 if (Body.size() > 2 && Body[0] ==
'/' && Body[2] ==
':')
44 Body.consume_front(
"/");
45 llvm::SmallVector<char, 16>
Path(Body.begin(), Body.end());
46 llvm::sys::path::native(
Path);
47 return std::string(
Path.begin(),
Path.end());
51 uriFromAbsolutePath(llvm::StringRef AbsolutePath)
const override {
52 using namespace llvm::sys;
56 if (AbsolutePath.size() > 1 && AbsolutePath[1] ==
':')
58 Body += path::convert_to_slash(AbsolutePath);
59 return URI(Scheme,
"", Body);
65 static URISchemeRegistry::Add<FileSystemScheme>
66 X(FileSystemScheme::Scheme,
67 "URI scheme for absolute paths in the file system.");
69 llvm::Expected<std::unique_ptr<URIScheme>>
70 findSchemeByName(llvm::StringRef
Scheme) {
71 for (
auto I = URISchemeRegistry::begin(), E = URISchemeRegistry::end();
73 if (I->getName() !=
Scheme)
75 return I->instantiate();
77 return make_string_error(
"Can't find scheme: " + Scheme);
80 bool shouldEscape(
unsigned char C) {
82 if ((C >=
'a' && C <=
'z') || (C >=
'A' && C <=
'Z') ||
83 (C >=
'0' && C <=
'9'))
100 std::string percentEncode(llvm::StringRef Content) {
102 llvm::raw_string_ostream OS(Result);
103 for (
unsigned char C : Content)
105 OS <<
'%' << llvm::format_hex_no_prefix(C, 2);
114 std::string percentDecode(llvm::StringRef Content) {
116 for (
auto I = Content.begin(), E = Content.end(); I != E; ++I) {
121 if (*I ==
'%' && I + 2 < Content.end() && llvm::isHexDigit(*(I + 1)) &&
122 llvm::isHexDigit(*(I + 2))) {
123 Result.push_back(llvm::hexFromNibbles(*(I + 1), *(I + 2)));
126 Result.push_back(*I);
133 URI::URI(llvm::StringRef
Scheme, llvm::StringRef Authority,
134 llvm::StringRef Body)
135 : Scheme(Scheme), Authority(Authority), Body(Body) {
136 assert(!Scheme.empty());
137 assert((Authority.empty() || Body.startswith(
"/")) &&
138 "URI body must start with '/' when authority is present.");
143 llvm::raw_string_ostream OS(Result);
144 OS << percentEncode(Scheme) <<
":";
145 if (Authority.empty() && Body.empty())
149 if (!Authority.empty() || llvm::StringRef(Body).startswith(
"/"))
150 OS <<
"//" << percentEncode(Authority);
151 OS << percentEncode(Body);
158 llvm::StringRef Uri = OrigUri;
160 auto Pos = Uri.find(
':');
161 if (
Pos == 0 ||
Pos == llvm::StringRef::npos)
162 return make_string_error(
"Scheme must be provided in URI: " + OrigUri);
163 U.Scheme = percentDecode(Uri.substr(0,
Pos));
164 Uri = Uri.substr(
Pos + 1);
165 if (Uri.consume_front(
"//")) {
167 U.Authority = percentDecode(Uri.substr(0,
Pos));
168 Uri = Uri.substr(
Pos);
170 U.Body = percentDecode(Uri);
175 llvm::StringRef Scheme) {
176 if (!llvm::sys::path::is_absolute(AbsolutePath))
177 return make_string_error(
"Not a valid absolute path: " + AbsolutePath);
178 auto S = findSchemeByName(Scheme);
180 return S.takeError();
181 return S->get()->uriFromAbsolutePath(AbsolutePath);
185 auto U =
create(AbsolutePath,
"file");
188 return std::move(*U);
192 llvm::StringRef HintPath) {
193 auto S = findSchemeByName(Uri.Scheme);
195 return S.takeError();
196 return S->get()->getAbsolutePath(Uri.Authority, Uri.Body, HintPath);
200 auto S = findSchemeByName(Uri.Scheme);
202 return S.takeError();
203 return S->get()->getIncludeSpelling(Uri);
static const char * Scheme
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
static const StringRef Message
static ClangTidyModuleRegistry::Add< AbseilModule > X("abseil-module", "Add Abseil checks.")
static URI createFile(llvm::StringRef AbsolutePath)
This creates a file:// URI for AbsolutePath. The path must be absolute.
llvm::Registry< URIScheme > URISchemeRegistry
By default, a "file" scheme is supported where URI paths are always absolute in the file system...
std::string Path
A typedef to represent a file path.
static llvm::Expected< URI > create(llvm::StringRef AbsolutePath, llvm::StringRef Scheme)
Creates a URI for a file in the given scheme.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
A URI describes the location of a source file.
static llvm::Expected< std::string > resolve(const URI &U, llvm::StringRef HintPath="")
Resolves the absolute path of U.
static llvm::Expected< std::string > includeSpelling(const URI &U)
Gets the preferred spelling of this file for #include, if there is one, e.g.
static llvm::Expected< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".
std::string toString() const
Returns a string URI with all components percent-encoded.