14 #include "llvm/ADT/ScopeExit.h"
15 #include "llvm/ADT/StringMap.h"
16 #include "llvm/Support/Path.h"
27 std::chrono::steady_clock::time_point ValidTime = {};
28 llvm::SmallVector<CompiledFragment, 1> CachedValue;
29 llvm::sys::TimePoint<> MTime = {};
37 auto Buf =
FS.getBufferForFile(
Path);
47 if (Buf->get()->getBufferSize() != Size) {
55 CachedValue.push_back(std::move(
Fragment).compile(DC));
70 llvm::Optional<std::chrono::steady_clock::time_point> FreshTime,
71 std::vector<CompiledFragment> &
Out) {
72 std::lock_guard<std::mutex> Lock(Mu);
74 auto Return = llvm::make_scope_exit(
75 [&] { llvm::copy(CachedValue, std::back_inserter(
Out)); });
78 if (FreshTime && ValidTime >= FreshTime)
82 auto MarkTime = llvm::make_scope_exit(
83 [&] { ValidTime = std::chrono::steady_clock::now(); });
86 assert(llvm::sys::path::is_absolute(
Path));
88 auto Stat =
FS->status(
Path);
90 if (!Stat || !Stat->isRegularFile()) {
97 if (Size == Stat->getSize() && MTime == Stat->getLastModificationTime())
101 Size = Stat->getSize();
102 MTime = Stat->getLastModificationTime();
103 fillCacheFromDisk(*
FS, DC);
109 class AbsFileProvider :
public Provider {
113 std::vector<CompiledFragment>
115 std::vector<CompiledFragment> Result;
122 assert(llvm::sys::path::is_absolute(
Path));
127 return std::make_unique<AbsFileProvider>(AbsPath,
FS);
130 std::unique_ptr<Provider>
133 class RelFileProvider :
public Provider {
137 mutable std::mutex Mu;
141 mutable llvm::StringMap<FileConfigCache> Cache;
143 std::vector<CompiledFragment>
145 namespace path = llvm::sys::path;
151 llvm::StringRef
Parent = path::parent_path(P.
Path);
152 llvm::SmallVector<llvm::StringRef, 8> Ancestors;
153 for (
auto I = path::begin(
Parent, path::Style::posix),
158 if (I->end() <
Parent.begin() && I->end() >
Parent.end())
160 Ancestors.emplace_back(
Parent.begin(), I->end() -
Parent.begin());
163 llvm::SmallVector<FileConfigCache *, 8> Caches;
165 std::lock_guard<std::mutex> Lock(Mu);
166 for (llvm::StringRef Ancestor : Ancestors) {
167 auto R = Cache.try_emplace(Ancestor);
170 llvm::SmallString<256> ConfigPath = Ancestor;
171 path::append(ConfigPath, RelPath);
172 R.first->second.Path = ConfigPath.str().str();
174 Caches.push_back(&R.first->second);
179 std::vector<CompiledFragment> Result;
187 : RelPath(RelPath),
FS(
FS) {
188 assert(llvm::sys::path::is_relative(RelPath));
192 return std::make_unique<RelFileProvider>(RelPath,
FS);
195 std::unique_ptr<Provider>
197 struct CombinedProvider :
Provider {
198 std::vector<const Provider *> Providers;
200 std::vector<CompiledFragment>
202 std::vector<CompiledFragment> Result;
203 for (
const auto &
Provider : Providers) {
205 Result.push_back(std::move(
Fragment));
210 auto Result = std::make_unique<CombinedProvider>();
211 Result->Providers = std::move(Providers);
220 for (
const auto &
Fragment : getFragments(P, DC))