@@ -42,7 +42,8 @@ enum class SwiftCacheToolAction {
42
42
Invalid,
43
43
PrintBaseKey,
44
44
PrintOutputKeys,
45
- ValidateOutputs
45
+ ValidateOutputs,
46
+ RenderDiags
46
47
};
47
48
48
49
struct OutputEntry {
@@ -134,11 +135,13 @@ class SwiftCacheToolInvocation {
134
135
.Case (" print-base-key" , SwiftCacheToolAction::PrintBaseKey)
135
136
.Case (" print-output-keys" , SwiftCacheToolAction::PrintOutputKeys)
136
137
.Case (" validate-outputs" , SwiftCacheToolAction::ValidateOutputs)
138
+ .Case (" render-diags" , SwiftCacheToolAction::RenderDiags)
137
139
.Default (SwiftCacheToolAction::Invalid);
138
140
139
141
if (ActionKind == SwiftCacheToolAction::Invalid) {
140
- llvm::errs () << " Invalid option specified for -cache-tool-action: "
141
- << " use print-base-key|print-output-keys|validate-outputs\n " ;
142
+ llvm::errs ()
143
+ << " Invalid option specified for -cache-tool-action: "
144
+ << " print-base-key|print-output-keys|validate-outputs|render-diags\n " ;
142
145
return 1 ;
143
146
}
144
147
@@ -153,6 +156,8 @@ class SwiftCacheToolInvocation {
153
156
return printOutputKeys ();
154
157
case SwiftCacheToolAction::ValidateOutputs:
155
158
return validateOutputs ();
159
+ case SwiftCacheToolAction::RenderDiags:
160
+ return renderDiags ();
156
161
case SwiftCacheToolAction::Invalid:
157
162
return 0 ; // No action. Probably just print help. Return.
158
163
}
@@ -202,6 +207,10 @@ class SwiftCacheToolInvocation {
202
207
return true ;
203
208
}
204
209
210
+ // Disable diagnostic caching from this fake instance.
211
+ if (auto *CDP = Instance.getCachingDiagnosticsProcessor ())
212
+ CDP->endDiagnosticCapture ();
213
+
205
214
return false ;
206
215
}
207
216
@@ -233,6 +242,7 @@ class SwiftCacheToolInvocation {
233
242
234
243
int printOutputKeys ();
235
244
int validateOutputs ();
245
+ int renderDiags ();
236
246
};
237
247
238
248
} // end anonymous namespace
@@ -283,6 +293,10 @@ int SwiftCacheToolInvocation::printOutputKeys() {
283
293
Invocation.getFrontendOptions ().InputsAndOutputs .getAllInputs (),
284
294
addFromInputFile);
285
295
296
+ // Add diagnostics file.
297
+ addOutputKey (" <cached-diagnostics>" , file_types::ID::TY_CachedDiagnostics,
298
+ " <cached-diagnostics>" );
299
+
286
300
if (hasError)
287
301
return 1 ;
288
302
@@ -301,6 +315,26 @@ int SwiftCacheToolInvocation::printOutputKeys() {
301
315
return 0 ;
302
316
}
303
317
318
+ static llvm::Expected<llvm::json::Array>
319
+ readOutputEntriesFromFile (StringRef Path) {
320
+ auto JSONContent = llvm::MemoryBuffer::getFile (Path);
321
+ if (!JSONContent)
322
+ return llvm::createStringError (JSONContent.getError (),
323
+ " failed to read input file" );
324
+
325
+ auto JSONValue = llvm::json::parse ((*JSONContent)->getBuffer ());
326
+ if (!JSONValue)
327
+ return llvm::createStringError (llvm::inconvertibleErrorCode (),
328
+ " failed to parse input file as JSON" );
329
+
330
+ auto Keys = JSONValue->getAsArray ();
331
+ if (!Keys)
332
+ return llvm::createStringError (llvm::inconvertibleErrorCode (),
333
+ " invalid JSON format for input file" );
334
+
335
+ return *Keys;
336
+ }
337
+
304
338
int SwiftCacheToolInvocation::validateOutputs () {
305
339
auto DB = llvm::cas::createOnDiskUnifiedCASDatabases (CASPath);
306
340
if (!DB)
@@ -310,22 +344,10 @@ int SwiftCacheToolInvocation::validateOutputs() {
310
344
Instance.getDiags ().addConsumer (PDC);
311
345
312
346
auto validateCacheKeysFromFile = [&](const std::string &Path) {
313
- auto JSONContent = llvm::MemoryBuffer::getFile (Path);
314
- if (!JSONContent) {
315
- llvm::errs () << " failed to read " << Path << " : "
316
- << JSONContent.getError ().message () << " \n " ;
317
- return true ;
318
- }
319
- auto JSONValue = llvm::json::parse ((*JSONContent)->getBuffer ());
320
- if (!JSONValue) {
321
- llvm::errs () << " failed to parse " << Path << " : "
322
- << toString (JSONValue.takeError ()) << " \n " ;
323
- return true ;
324
- }
325
-
326
- auto Keys = JSONValue->getAsArray ();
347
+ auto Keys = readOutputEntriesFromFile (Path);
327
348
if (!Keys) {
328
- llvm::errs () << " invalid keys format in " << Path << " \n " ;
349
+ llvm::errs () << " cannot read file " << Path << " : "
350
+ << toString (Keys.takeError ()) << " \n " ;
329
351
return true ;
330
352
}
331
353
@@ -350,6 +372,51 @@ int SwiftCacheToolInvocation::validateOutputs() {
350
372
return llvm::any_of (Inputs, validateCacheKeysFromFile);
351
373
}
352
374
375
+ int SwiftCacheToolInvocation::renderDiags () {
376
+ if (setupCompiler ())
377
+ return 1 ;
378
+
379
+ auto *CDP = Instance.getCachingDiagnosticsProcessor ();
380
+ if (!CDP) {
381
+ llvm::errs () << " provided commandline doesn't support cached diagnostics\n " ;
382
+ return 1 ;
383
+ }
384
+
385
+ auto renderDiagsFromFile = [&](const std::string &Path) {
386
+ auto Keys = readOutputEntriesFromFile (Path);
387
+ if (!Keys) {
388
+ llvm::errs () << " cannot read file " << Path << " : "
389
+ << toString (Keys.takeError ()) << " \n " ;
390
+ return true ;
391
+ }
392
+
393
+ for (const auto & Entry : *Keys) {
394
+ if (auto *Obj = Entry.getAsObject ()) {
395
+ if (auto Kind = Obj->getString (" OutputKind" )) {
396
+ if (*Kind != " cached-diagnostics" )
397
+ continue ;
398
+ }
399
+ if (auto Key = Obj->getString (" CacheKey" )) {
400
+ if (auto Buffer = loadCachedCompileResultFromCacheKey (
401
+ Instance.getObjectStore (), Instance.getActionCache (),
402
+ Instance.getDiags (), *Key)) {
403
+ if (auto E = CDP->replayCachedDiagnostics (Buffer->getBuffer ())) {
404
+ llvm::errs () << " failed to replay cache: "
405
+ << toString (std::move (E)) << " \n " ;
406
+ return true ;
407
+ }
408
+ return false ;
409
+ }
410
+ }
411
+ }
412
+ }
413
+ llvm::errs () << " cannot locate cached diagnostics in file\n " ;
414
+ return true ;
415
+ };
416
+
417
+ return llvm::any_of (Inputs, renderDiagsFromFile);
418
+ }
419
+
353
420
int swift_cache_tool_main (ArrayRef<const char *> Args, const char *Argv0,
354
421
void *MainAddr) {
355
422
INITIALIZE_LLVM ();
0 commit comments