36 #include "llvm/ADT/STLExtras.h" 49 SmallString<128> Result = Path.rtrim(
'/');
50 native(Result, sys::path::Style::posix);
51 if (Result.empty() || Result.front() !=
'/')
52 Result.insert(Result.begin(),
'/');
61 llvm::DenseMap<hash_code, SmallVector<hash_code, 4>> DownEdges;
64 for (
const auto &S : Sources) {
66 dlog(
"Source {0} = {1}, MaxUp = {2}", Canonical, S.second.Cost,
67 S.second.MaxUpTraversals);
69 StringRef Rest = Canonical;
70 llvm::hash_code Hash = hash_value(Rest);
71 for (
unsigned I = 0; !Rest.empty(); ++I) {
72 Rest = parent_path(Rest, sys::path::Style::posix);
73 auto NextHash = hash_value(Rest);
74 auto &Down = DownEdges[NextHash];
75 if (std::find(Down.begin(), Down.end(), Hash) == Down.end())
76 DownEdges[NextHash].push_back(Hash);
78 if (I > S.getValue().MaxUpTraversals) {
79 if (Cache.find(Hash) != Cache.end())
82 unsigned Cost = S.getValue().Cost + I * Opts.
UpCost;
83 auto R = Cache.try_emplace(Hash, Cost);
85 if (Cost < R.first->second) {
86 R.first->second = Cost;
98 std::queue<hash_code> Next;
99 for (
auto Child : DownEdges.lookup(hash_value(llvm::StringRef(
""))))
101 while (!Next.empty()) {
102 auto ParentCost = Cache.lookup(Next.front());
103 for (
auto Child : DownEdges.lookup(Next.front())) {
105 Cache.try_emplace(Child,
kUnreachable).first->getSecond();
106 if (ParentCost + Opts.
DownCost < ChildCost)
107 ChildCost = ParentCost + Opts.
DownCost;
117 SmallVector<hash_code, 16> Ancestors;
119 for (StringRef Rest = Canonical; !Rest.empty();
120 Rest = parent_path(Rest, sys::path::Style::posix)) {
121 auto Hash = hash_value(Rest);
122 auto It = Cache.find(Hash);
123 if (It != Cache.end()) {
127 Ancestors.push_back(Hash);
131 for (hash_code Hash : reverse(Ancestors)) {
134 Cache.try_emplace(Hash, Cost);
136 dlog(
"distance({0} = {1})", Path, Cost);
141 auto R = Cache.try_emplace(llvm::hash_value(URI), FileDistance::kUnreachable);
143 return R.first->getSecond();
145 dlog(
"distance({0} = {1})", URI, U->body());
146 R.first->second = forScheme(U->scheme()).
distance(U->body());
148 log(
"URIDistance::distance() of unparseable {0}: {1}", URI, U.takeError());
150 return R.first->second;
154 auto &Delegate = ByScheme[
Scheme];
156 llvm::StringMap<SourceParams> SchemeSources;
157 for (
const auto &Source : Sources) {
159 SchemeSources.try_emplace(U->body(), Source.getValue());
161 consumeError(U.takeError());
163 dlog(
"FileDistance for scheme {0}: {1}/{2} sources", Scheme,
164 SchemeSources.size(), Sources.size());
165 Delegate.reset(
new FileDistance(std::move(SchemeSources), Opts));
static const char * Scheme
Some operations such as code completion produce a set of candidates.
void log(const char *Fmt, Ts &&... Vals)
std::string Path
A typedef to represent a file path.
FileDistance(llvm::StringMap< SourceParams > Sources, const FileDistanceOptions &Opts={})
unsigned distance(llvm::StringRef URI)
static constexpr unsigned kUnreachable
static SmallString< 128 > canonicalize(StringRef 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< URI > parse(llvm::StringRef Uri)
Parse a URI string "<scheme>:[//<authority>/]<path>".
unsigned distance(llvm::StringRef Path)