@@ -151,20 +151,13 @@ namespace vcpkg
151151 MessageSink& sink;
152152 };
153153
154- // Stores all diagnostics into a vector, while passing through status lines to an underlying MessageSink.
155- struct BufferedDiagnosticContext final : DiagnosticContext
154+ struct BasicBufferedDiagnosticContext : DiagnosticContext
156155 {
157- BufferedDiagnosticContext (MessageSink& status_sink) : status_sink(status_sink) { }
158-
159156 virtual void report (const DiagnosticLine& line) override ;
160157 virtual void report (DiagnosticLine&& line) override ;
161158
162- virtual void statusln (const LocalizedString& message) override ;
163- virtual void statusln (LocalizedString&& message) override ;
164- virtual void statusln (const MessageLine& message) override ;
165- virtual void statusln (MessageLine&& message) override ;
159+ // statusln intentionally unimplemented
166160
167- MessageSink& status_sink;
168161 std::vector<DiagnosticLine> lines;
169162
170163 // Prints all diagnostics to the supplied sink.
@@ -178,6 +171,62 @@ namespace vcpkg
178171 bool empty () const noexcept ;
179172 };
180173
174+ // Stores all diagnostics into a vector, while passing through status lines to an underlying MessageSink.
175+ struct SinkBufferedDiagnosticContext final : BasicBufferedDiagnosticContext
176+ {
177+ SinkBufferedDiagnosticContext (MessageSink& status_sink) : status_sink(status_sink) { }
178+
179+ virtual void statusln (const LocalizedString& message) override ;
180+ virtual void statusln (LocalizedString&& message) override ;
181+ virtual void statusln (const MessageLine& message) override ;
182+ virtual void statusln (MessageLine&& message) override ;
183+
184+ MessageSink& status_sink;
185+ };
186+
187+ struct ContextBufferedDiagnosticContext final : BasicBufferedDiagnosticContext
188+ {
189+ ContextBufferedDiagnosticContext (DiagnosticContext& status_context) : status_context(status_context) { }
190+
191+ virtual void statusln (const LocalizedString& message) override ;
192+ virtual void statusln (LocalizedString&& message) override ;
193+ virtual void statusln (const MessageLine& message) override ;
194+ virtual void statusln (MessageLine&& message) override ;
195+
196+ DiagnosticContext& status_context;
197+ };
198+
199+ struct FullyBufferedDiagnosticContext ;
200+
201+ struct DiagnosticOrMessageLine
202+ {
203+ DiagnosticOrMessageLine (const DiagnosticLine& dl);
204+ DiagnosticOrMessageLine (DiagnosticLine&& dl);
205+ DiagnosticOrMessageLine (const MessageLine& ml);
206+ DiagnosticOrMessageLine (MessageLine&& ml);
207+
208+ DiagnosticOrMessageLine (const DiagnosticOrMessageLine& other);
209+ DiagnosticOrMessageLine (DiagnosticOrMessageLine&& other);
210+
211+ DiagnosticOrMessageLine& operator =(const DiagnosticOrMessageLine&) = delete ;
212+
213+ ~DiagnosticOrMessageLine ();
214+
215+ std::string to_string () const ;
216+ void to_string (std::string& target) const ;
217+
218+ private:
219+ friend FullyBufferedDiagnosticContext;
220+
221+ union
222+ {
223+ DiagnosticLine dl;
224+ MessageLine ml;
225+ };
226+
227+ bool is_diagnostic;
228+ };
229+
181230 // Stores all diagnostics and status messages into a vector. This is generally used for background thread or similar
182231 // scenarios where even status messages can't be immediately printed.
183232 struct FullyBufferedDiagnosticContext final : DiagnosticContext
@@ -190,28 +239,29 @@ namespace vcpkg
190239 virtual void statusln (const MessageLine& message) override ;
191240 virtual void statusln (MessageLine&& message) override ;
192241
193- std::vector<MessageLine> lines;
194-
195242 // Prints all diagnostics to the supplied sink.
196243 void print_to (MessageSink& sink) const ;
197244 // Converts this message into a string
198245 // Prefer print() if possible because it applies color
199246 std::string to_string () const ;
200247 void to_string (std::string& target) const ;
248+ // Emits all status messages and reports all diagnostics to the supplied context
249+ void report_to (DiagnosticContext& context) const &;
250+ void report_to (DiagnosticContext& context) &&;
201251
202252 bool empty () const noexcept ;
253+
254+ private:
255+ std::vector<DiagnosticOrMessageLine> lines;
203256 };
204257
205258 // DiagnosticContext for attempted operations that may be recovered.
206259 // Stores all diagnostics and passes through all status messages. Afterwards, call commit() to report all
207260 // diagnostics to the outer DiagnosticContext, or handle() to forget them.
208- struct AttemptDiagnosticContext final : DiagnosticContext
261+ struct AttemptDiagnosticContext final : BasicBufferedDiagnosticContext
209262 {
210263 AttemptDiagnosticContext (DiagnosticContext& inner_context) : inner_context(inner_context) { }
211264
212- virtual void report (const DiagnosticLine& line) override ;
213- virtual void report (DiagnosticLine&& line) override ;
214-
215265 virtual void statusln (const LocalizedString& message) override ;
216266 virtual void statusln (LocalizedString&& message) override ;
217267 virtual void statusln (const MessageLine& message) override ;
@@ -223,7 +273,6 @@ namespace vcpkg
223273 ~AttemptDiagnosticContext ();
224274
225275 DiagnosticContext& inner_context;
226- std::vector<DiagnosticLine> lines;
227276 };
228277
229278 // Wraps another DiagnosticContext and reduces the severity of any reported diagnostics to warning from error.
@@ -312,11 +361,11 @@ namespace vcpkg
312361 // The overload for functors that return Optional<T>
313362 template <class Fn , class ... Args>
314363 auto adapt_context_to_expected (Fn functor, Args&&... args) -> ExpectedL<
315- typename AdaptContextUnwrapOptional<std::invoke_result_t<Fn, BufferedDiagnosticContext &, Args...>>::type>
364+ typename AdaptContextUnwrapOptional<std::invoke_result_t<Fn, SinkBufferedDiagnosticContext &, Args...>>::type>
316365 {
317- using Unwrapper = AdaptContextUnwrapOptional<std::invoke_result_t <Fn, BufferedDiagnosticContext &, Args...>>;
366+ using Unwrapper = AdaptContextUnwrapOptional<std::invoke_result_t <Fn, SinkBufferedDiagnosticContext &, Args...>>;
318367 using ReturnType = ExpectedL<typename Unwrapper::type>;
319- BufferedDiagnosticContext bdc{out_sink};
368+ SinkBufferedDiagnosticContext bdc{out_sink};
320369 decltype (auto ) maybe_result = functor (bdc, std::forward<Args>(args)...);
321370 if (auto result = maybe_result.get ())
322371 {
@@ -381,11 +430,11 @@ namespace vcpkg
381430 // The overload for functors that return std::unique_ptr<T>
382431 template <class Fn , class ... Args>
383432 auto adapt_context_to_expected (Fn functor, Args&&... args) -> ExpectedL<
384- typename AdaptContextDetectUniquePtr<std::invoke_result_t<Fn, BufferedDiagnosticContext &, Args...>>::type>
433+ typename AdaptContextDetectUniquePtr<std::invoke_result_t<Fn, SinkBufferedDiagnosticContext &, Args...>>::type>
385434 {
386- using ReturnType = ExpectedL<
387- typename AdaptContextDetectUniquePtr< std::invoke_result_t <Fn, BufferedDiagnosticContext &, Args...>>::type>;
388- BufferedDiagnosticContext bdc{out_sink};
435+ using ReturnType = ExpectedL<typename AdaptContextDetectUniquePtr<
436+ std::invoke_result_t <Fn, SinkBufferedDiagnosticContext &, Args...>>::type>;
437+ SinkBufferedDiagnosticContext bdc{out_sink};
389438 decltype (auto ) maybe_result = functor (bdc, std::forward<Args>(args)...);
390439 if (maybe_result)
391440 {
0 commit comments