CMake Nightly Date Stamp
[kiteware-cmake.git] / Source / cmListFileCache.h
blobe4e6eb37ed9593beb89c4f9dddfb197e781f2826
1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #pragma once
5 #include "cmConfigure.h" // IWYU pragma: keep
7 #include <iosfwd>
8 #include <memory>
9 #include <string>
10 #include <utility>
11 #include <vector>
13 #include <cm/optional>
15 #include "cmConstStack.h"
16 #include "cmList.h"
17 #include "cmSystemTools.h"
19 /** \class cmListFileCache
20 * \brief A class to cache list file contents.
22 * cmListFileCache is a class used to cache the contents of parsed
23 * cmake list files.
26 class cmMessenger;
28 struct cmListFileArgument
30 enum Delimiter
32 Unquoted,
33 Quoted,
34 Bracket
36 cmListFileArgument() = default;
37 cmListFileArgument(std::string v, Delimiter d, long line)
38 : Value(std::move(v))
39 , Delim(d)
40 , Line(line)
43 bool operator==(const cmListFileArgument& r) const
45 return (this->Value == r.Value) && (this->Delim == r.Delim);
47 bool operator!=(const cmListFileArgument& r) const { return !(*this == r); }
48 std::string Value;
49 Delimiter Delim = Unquoted;
50 long Line = 0;
53 class cmListFileFunction
55 public:
56 cmListFileFunction(std::string name, long line, long lineEnd,
57 std::vector<cmListFileArgument> args)
58 : Impl{ std::make_shared<Implementation>(std::move(name), line, lineEnd,
59 std::move(args)) }
63 std::string const& OriginalName() const noexcept
65 return this->Impl->OriginalName;
68 std::string const& LowerCaseName() const noexcept
70 return this->Impl->LowerCaseName;
73 long Line() const noexcept { return this->Impl->Line; }
74 long LineEnd() const noexcept { return this->Impl->LineEnd; }
76 std::vector<cmListFileArgument> const& Arguments() const noexcept
78 return this->Impl->Arguments;
81 private:
82 struct Implementation
84 Implementation(std::string name, long line, long lineEnd,
85 std::vector<cmListFileArgument> args)
86 : OriginalName{ std::move(name) }
87 , LowerCaseName{ cmSystemTools::LowerCase(this->OriginalName) }
88 , Line{ line }
89 , LineEnd{ lineEnd }
90 , Arguments{ std::move(args) }
94 std::string OriginalName;
95 std::string LowerCaseName;
96 long Line = 0;
97 long LineEnd = 0;
98 std::vector<cmListFileArgument> Arguments;
101 std::shared_ptr<Implementation const> Impl;
104 class cmListFileContext
106 public:
107 std::string Name;
108 std::string FilePath;
109 long Line = 0;
110 static long const DeferPlaceholderLine = -1;
111 cm::optional<std::string> DeferId;
113 cmListFileContext() = default;
114 // This move constructor is marked `noexcept` yet `clang-tidy` 14 reports it
115 // as being able to throw an exception. Suppress the warning as there doesn't
116 // seem to be any way for this to happen given the member types.
117 // NOLINTNEXTLINE(bugprone-exception-escape)
118 cmListFileContext(cmListFileContext&& /*other*/) noexcept = default;
119 cmListFileContext(const cmListFileContext& /*other*/) = default;
120 cmListFileContext& operator=(const cmListFileContext& /*other*/) = default;
121 #if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
122 cmListFileContext& operator=(cmListFileContext&& /*other*/) noexcept =
123 default;
124 #else
125 // The move assignment operators for several STL classes did not become
126 // noexcept until C++17, which causes some tools to warn about this move
127 // assignment operator throwing an exception when it shouldn't.
128 cmListFileContext& operator=(cmListFileContext&& /*other*/) noexcept =
129 delete;
130 #endif
132 cmListFileContext(std::string name, std::string filePath, long line)
133 : Name(std::move(name))
134 , FilePath(std::move(filePath))
135 , Line(line)
139 static cmListFileContext FromListFilePath(std::string const& filePath)
141 // We are entering a file-level scope but have not yet reached
142 // any specific line or command invocation within it. This context
143 // is useful to print when it is at the top but otherwise can be
144 // skipped during call stack printing.
145 cmListFileContext lfc;
146 lfc.FilePath = filePath;
147 return lfc;
150 static cmListFileContext FromListFileFunction(
151 cmListFileFunction const& lff, std::string const& fileName,
152 cm::optional<std::string> deferId = {})
154 cmListFileContext lfc;
155 lfc.FilePath = fileName;
156 lfc.Line = lff.Line();
157 lfc.Name = lff.OriginalName();
158 lfc.DeferId = std::move(deferId);
159 return lfc;
163 std::ostream& operator<<(std::ostream&, cmListFileContext const&);
164 bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs);
165 bool operator==(cmListFileContext const& lhs, cmListFileContext const& rhs);
166 bool operator!=(cmListFileContext const& lhs, cmListFileContext const& rhs);
168 // Represent a backtrace (call stack) with efficient value semantics.
169 class cmListFileBacktrace
170 : public cmConstStack<cmListFileContext, cmListFileBacktrace>
172 using cmConstStack::cmConstStack;
173 friend class cmConstStack<cmListFileContext, cmListFileBacktrace>;
175 #ifndef cmListFileCache_cxx
176 extern template class cmConstStack<cmListFileContext, cmListFileBacktrace>;
177 #endif
179 // Wrap type T as a value with a backtrace. For purposes of
180 // ordering and equality comparison, only the original value is
181 // used. The backtrace is considered incidental.
182 template <typename T>
183 class BT
185 public:
186 BT(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace())
187 : Value(std::move(v))
188 , Backtrace(std::move(bt))
191 T Value;
192 cmListFileBacktrace Backtrace;
193 friend bool operator==(BT<T> const& l, BT<T> const& r)
195 return l.Value == r.Value;
197 friend bool operator<(BT<T> const& l, BT<T> const& r)
199 return l.Value < r.Value;
201 friend bool operator==(BT<T> const& l, T const& r) { return l.Value == r; }
202 friend bool operator==(T const& l, BT<T> const& r) { return l == r.Value; }
205 std::ostream& operator<<(std::ostream& os, BT<std::string> const& s);
207 // Wrap type T as a value with potentially multiple backtraces. For purposes
208 // of ordering and equality comparison, only the original value is used. The
209 // backtrace is considered incidental.
210 template <typename T>
211 class BTs
213 public:
214 BTs(T v = T(), cmListFileBacktrace bt = cmListFileBacktrace())
215 : Value(std::move(v))
217 this->Backtraces.emplace_back(std::move(bt));
219 T Value;
220 std::vector<cmListFileBacktrace> Backtraces;
221 friend bool operator==(BTs<T> const& l, BTs<T> const& r)
223 return l.Value == r.Value;
225 friend bool operator<(BTs<T> const& l, BTs<T> const& r)
227 return l.Value < r.Value;
229 friend bool operator==(BTs<T> const& l, T const& r) { return l.Value == r; }
230 friend bool operator==(T const& l, BTs<T> const& r) { return l == r.Value; }
233 std::vector<BT<std::string>> cmExpandListWithBacktrace(
234 std::string const& list,
235 cmListFileBacktrace const& bt = cmListFileBacktrace(),
236 cmList::EmptyElements emptyArgs = cmList::EmptyElements::No);
238 struct cmListFile
240 bool ParseFile(const char* path, cmMessenger* messenger,
241 cmListFileBacktrace const& lfbt);
243 bool ParseString(const char* str, const char* virtual_filename,
244 cmMessenger* messenger, cmListFileBacktrace const& lfbt);
246 std::vector<cmListFileFunction> Functions;