Skip to content

Commit 3211b93

Browse files
authored
Merge pull request #60999 from artemcm/LibSwiftScanDiagnostics
[Dependency Scanner] Add API to query emitted diagnostics during a scan
2 parents 06595f6 + 6061516 commit 3211b93

File tree

6 files changed

+193
-7
lines changed

6 files changed

+193
-7
lines changed

include/swift-c/DependencyScan/DependencyScan.h

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
/// SWIFTSCAN_VERSION_MINOR should increase when there are API additions.
2626
/// SWIFTSCAN_VERSION_MAJOR is intended for "major" source/ABI breaking changes.
2727
#define SWIFTSCAN_VERSION_MAJOR 0
28-
#define SWIFTSCAN_VERSION_MINOR 2
28+
#define SWIFTSCAN_VERSION_MINOR 3
2929

3030
SWIFTSCAN_BEGIN_DECLS
3131

@@ -52,6 +52,9 @@ typedef struct swiftscan_dependency_graph_s *swiftscan_dependency_graph_t;
5252
/// Opaque container to contain the result of a dependency prescan.
5353
typedef struct swiftscan_import_set_s *swiftscan_import_set_t;
5454

55+
/// Opaque container to contain the info of a diagnostics emitted by the scanner.
56+
typedef struct swiftscan_diagnostic_info_s *swiftscan_diagnostic_info_t;
57+
5558
/// Full Dependency Graph (Result)
5659
typedef struct {
5760
swiftscan_dependency_info_t *modules;
@@ -329,6 +332,37 @@ swiftscan_batch_scan_result_create(swiftscan_scanner_t scanner,
329332
SWIFTSCAN_PUBLIC swiftscan_import_set_t swiftscan_import_set_create(
330333
swiftscan_scanner_t scanner, swiftscan_scan_invocation_t invocation);
331334

335+
336+
//=== Scanner Diagnostics -------------------------------------------------===//
337+
typedef enum {
338+
SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR = 0,
339+
SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING = 1,
340+
SWIFTSCAN_DIAGNOSTIC_SEVERITY_NOTE = 2,
341+
SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK = 3
342+
} swiftscan_diagnostic_severity_t;
343+
344+
typedef struct {
345+
swiftscan_diagnostic_info_t *diagnostics;
346+
size_t count;
347+
} swiftscan_diagnostic_set_t;
348+
349+
/// For the specified \c scanner instance, query all insofar emitted diagnostics
350+
SWIFTSCAN_PUBLIC swiftscan_diagnostic_set_t*
351+
swiftscan_scanner_diagnostics_query(swiftscan_scanner_t scanner);
352+
353+
/// For the specified \c scanner instance, reset its diagnostic state
354+
SWIFTSCAN_PUBLIC void
355+
swiftscan_scanner_diagnostics_reset(swiftscan_scanner_t scanner);
356+
357+
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
358+
swiftscan_diagnostic_get_message(swiftscan_diagnostic_info_t diagnostic);
359+
360+
SWIFTSCAN_PUBLIC swiftscan_diagnostic_severity_t
361+
swiftscan_diagnostic_get_severity(swiftscan_diagnostic_info_t diagnostic);
362+
363+
SWIFTSCAN_PUBLIC void
364+
swiftscan_diagnostics_set_dispose(swiftscan_diagnostic_set_t* diagnostics);
365+
332366
//=== Scanner Cache Operations --------------------------------------------===//
333367
// The following operations expose an implementation detail of the dependency
334368
// scanner: its module dependencies cache. This is done in order

include/swift/DependencyScan/DependencyScanImpl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,10 @@ struct swiftscan_scan_invocation_s {
160160
swiftscan_string_set_t *argv;
161161
};
162162

163+
struct swiftscan_diagnostic_info_s {
164+
swiftscan_string_ref_t message;
165+
swiftscan_diagnostic_severity_t severity;
166+
// TODO: SourceLoc
167+
};
168+
163169
#endif // SWIFT_C_DEPENDENCY_SCAN_IMPL_H

include/swift/DependencyScan/DependencyScanningTool.h

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,28 @@
2323

2424
namespace swift {
2525
namespace dependencies {
26+
class DependencyScanningTool;
27+
28+
/// Diagnostic consumer that simply collects the diagnostics emitted so-far
29+
class DependencyScannerDiagnosticCollectingConsumer : public DiagnosticConsumer {
30+
public:
31+
friend DependencyScanningTool;
32+
DependencyScannerDiagnosticCollectingConsumer() {}
33+
void reset() { Diagnostics.clear(); }
34+
private:
35+
struct ScannerDiagnosticInfo {
36+
std::string Message;
37+
llvm::SourceMgr::DiagKind Severity;
38+
};
39+
40+
void handleDiagnostic(SourceManager &SM,
41+
const DiagnosticInfo &Info) override;
42+
ScannerDiagnosticInfo convertDiagnosticInfo(SourceManager &SM,
43+
const DiagnosticInfo &Info);
44+
void addDiagnostic(SourceManager &SM, const DiagnosticInfo &Info);
45+
std::vector<ScannerDiagnosticInfo> Diagnostics;
46+
};
47+
2648

2749
/// Given a set of arguments to a print-target-info frontend tool query, produce the
2850
/// JSON target info.
@@ -68,6 +90,10 @@ class DependencyScanningTool {
6890
bool loadCache(llvm::StringRef path);
6991
/// Discard the tool's current `SharedCache` and start anew.
7092
void resetCache();
93+
94+
const std::vector<DependencyScannerDiagnosticCollectingConsumer::ScannerDiagnosticInfo>& getDiagnostics() const { return CDC.Diagnostics; }
95+
/// Discared the collection of diagnostics encountered so far.
96+
void resetDiagnostics();
7197

7298
private:
7399
/// Using the specified invocation command, initialize the scanner instance
@@ -88,8 +114,8 @@ class DependencyScanningTool {
88114
/// command-line options specified in the batch scan input entry.
89115
std::unique_ptr<CompilerArgInstanceCacheMap> VersionedPCMInstanceCacheCache;
90116

91-
/// A shared consumer that, for now, just prints the encountered diagnostics.
92-
PrintingDiagnosticConsumer PDC;
117+
/// A shared consumer that accumulates encountered diagnostics.
118+
DependencyScannerDiagnosticCollectingConsumer CDC;
93119
llvm::BumpPtrAllocator Alloc;
94120
llvm::StringSaver Saver;
95121
};

lib/DependencyScan/DependencyScanningTool.cpp

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,58 @@ llvm::ErrorOr<swiftscan_string_ref_t> getTargetInfo(ArrayRef<const char *> Comma
5656
return c_string_utils::create_clone(ResultStr.c_str());
5757
}
5858

59+
void DependencyScannerDiagnosticCollectingConsumer::handleDiagnostic(SourceManager &SM,
60+
const DiagnosticInfo &Info) {
61+
addDiagnostic(SM, Info);
62+
for (auto ChildInfo : Info.ChildDiagnosticInfo) {
63+
addDiagnostic(SM, *ChildInfo);
64+
}
65+
}
66+
67+
void DependencyScannerDiagnosticCollectingConsumer::addDiagnostic(SourceManager &SM, const DiagnosticInfo &Info) {
68+
// Determine what kind of diagnostic we're emitting.
69+
llvm::SourceMgr::DiagKind SMKind;
70+
switch (Info.Kind) {
71+
case DiagnosticKind::Error:
72+
SMKind = llvm::SourceMgr::DK_Error;
73+
break;
74+
case DiagnosticKind::Warning:
75+
SMKind = llvm::SourceMgr::DK_Warning;
76+
break;
77+
case DiagnosticKind::Note:
78+
SMKind = llvm::SourceMgr::DK_Note;
79+
break;
80+
case DiagnosticKind::Remark:
81+
SMKind = llvm::SourceMgr::DK_Remark;
82+
break;
83+
}
84+
// Translate ranges.
85+
SmallVector<llvm::SMRange, 2> Ranges;
86+
for (auto R : Info.Ranges)
87+
Ranges.push_back(getRawRange(SM, R));
88+
// Translate fix-its.
89+
SmallVector<llvm::SMFixIt, 2> FixIts;
90+
for (DiagnosticInfo::FixIt F : Info.FixIts)
91+
FixIts.push_back(getRawFixIt(SM, F));
92+
93+
std::string ResultingMessage;
94+
llvm::raw_string_ostream Stream(ResultingMessage);
95+
const llvm::SourceMgr &rawSM = SM.getLLVMSourceMgr();
96+
97+
// Actually substitute the diagnostic arguments into the diagnostic text.
98+
llvm::SmallString<256> Text;
99+
llvm::raw_svector_ostream Out(Text);
100+
DiagnosticEngine::formatDiagnosticText(Out, Info.FormatString,
101+
Info.FormatArgs);
102+
auto Msg = SM.GetMessage(Info.Loc, SMKind, Text, Ranges, FixIts);
103+
Diagnostics.push_back(ScannerDiagnosticInfo{Msg.getMessage().str(), SMKind});
104+
}
105+
59106
DependencyScanningTool::DependencyScanningTool()
60107
: SharedCache(std::make_unique<GlobalModuleDependenciesCache>()),
61108
VersionedPCMInstanceCacheCache(
62109
std::make_unique<CompilerArgInstanceCacheMap>()),
63-
PDC(), Alloc(), Saver(Alloc) {}
110+
CDC(), Alloc(), Saver(Alloc) {}
64111

65112
llvm::ErrorOr<swiftscan_dependency_graph_t>
66113
DependencyScanningTool::getDependencies(
@@ -126,15 +173,15 @@ DependencyScanningTool::getDependencies(
126173
void DependencyScanningTool::serializeCache(llvm::StringRef path) {
127174
SourceManager SM;
128175
DiagnosticEngine Diags(SM);
129-
Diags.addConsumer(PDC);
176+
Diags.addConsumer(CDC);
130177
module_dependency_cache_serialization::writeInterModuleDependenciesCache(
131178
Diags, path, *SharedCache);
132179
}
133180

134181
bool DependencyScanningTool::loadCache(llvm::StringRef path) {
135182
SourceManager SM;
136183
DiagnosticEngine Diags(SM);
137-
Diags.addConsumer(PDC);
184+
Diags.addConsumer(CDC);
138185
SharedCache = std::make_unique<GlobalModuleDependenciesCache>();
139186
bool readFailed =
140187
module_dependency_cache_serialization::readInterModuleDependenciesCache(
@@ -149,6 +196,10 @@ void DependencyScanningTool::resetCache() {
149196
SharedCache.reset(new GlobalModuleDependenciesCache());
150197
}
151198

199+
void DependencyScanningTool::resetDiagnostics() {
200+
CDC.reset();
201+
}
202+
152203
llvm::ErrorOr<std::unique_ptr<CompilerInstance>>
153204
DependencyScanningTool::initScannerForAction(
154205
ArrayRef<const char *> Command) {
@@ -165,7 +216,7 @@ DependencyScanningTool::initCompilerInstanceForScan(
165216
ArrayRef<const char *> CommandArgs) {
166217
// State unique to an individual scan
167218
auto Instance = std::make_unique<CompilerInstance>();
168-
Instance->addDiagnosticConsumer(&PDC);
219+
Instance->addDiagnosticConsumer(&CDC);
169220

170221
// Basic error checking on the arguments
171222
if (CommandArgs.empty()) {

tools/libSwiftScan/libSwiftScan.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,70 @@ swiftscan_compiler_supported_features_query() {
534534
return swift::c_string_utils::create_set(allFeatures);
535535
}
536536

537+
//=== Scanner Diagnostics -------------------------------------------------===//
538+
swiftscan_diagnostic_set_t*
539+
swiftscan_scanner_diagnostics_query(swiftscan_scanner_t scanner) {
540+
DependencyScanningTool *ScanningTool = unwrap(scanner);
541+
auto NumDiagnostics = ScanningTool->getDiagnostics().size();
542+
543+
swiftscan_diagnostic_set_t *Result = new swiftscan_diagnostic_set_t;
544+
Result->count = NumDiagnostics;
545+
Result->diagnostics = new swiftscan_diagnostic_info_t[NumDiagnostics];
546+
547+
for (size_t i = 0; i < NumDiagnostics; ++i) {
548+
const auto &Diagnostic = ScanningTool->getDiagnostics()[i];
549+
swiftscan_diagnostic_info_s *DiagnosticInfo = new swiftscan_diagnostic_info_s;
550+
DiagnosticInfo->message = swift::c_string_utils::create_clone(Diagnostic.Message.c_str());
551+
switch (Diagnostic.Severity) {
552+
case llvm::SourceMgr::DK_Error:
553+
DiagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR;
554+
break;
555+
case llvm::SourceMgr::DK_Warning:
556+
DiagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING;
557+
break;
558+
case llvm::SourceMgr::DK_Note:
559+
DiagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_NOTE;
560+
break;
561+
case llvm::SourceMgr::DK_Remark:
562+
DiagnosticInfo->severity = SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK;
563+
break;
564+
}
565+
Result->diagnostics[i] = DiagnosticInfo;
566+
}
567+
568+
return Result;
569+
}
570+
571+
void
572+
swiftscan_scanner_diagnostics_reset(swiftscan_scanner_t scanner) {
573+
DependencyScanningTool *ScanningTool = unwrap(scanner);
574+
ScanningTool->resetDiagnostics();
575+
}
576+
577+
swiftscan_string_ref_t
578+
swiftscan_diagnostic_get_message(swiftscan_diagnostic_info_t diagnostic) {
579+
return diagnostic->message;
580+
}
581+
582+
swiftscan_diagnostic_severity_t
583+
swiftscan_diagnostic_get_severity(swiftscan_diagnostic_info_t diagnostic) {
584+
return diagnostic->severity;
585+
}
586+
587+
void swiftscan_diagnostic_dispose(swiftscan_diagnostic_info_t diagnostic) {
588+
swiftscan_string_dispose(diagnostic->message);
589+
delete diagnostic;
590+
}
591+
592+
void
593+
swiftscan_diagnostics_set_dispose(swiftscan_diagnostic_set_t* diagnostics){
594+
for (size_t i = 0; i < diagnostics->count; ++i) {
595+
swiftscan_diagnostic_dispose(diagnostics->diagnostics[i]);
596+
}
597+
delete[] diagnostics->diagnostics;
598+
delete diagnostics;
599+
}
600+
537601
//=== Experimental Compiler Invocation Functions ------------------------===//
538602

539603
int invoke_swift_compiler(int argc, const char **argv) {

tools/libSwiftScan/libSwiftScan.exports

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,9 @@ swiftscan_compiler_target_info_query
5959
swiftscan_scanner_cache_serialize
6060
swiftscan_scanner_cache_load
6161
swiftscan_scanner_cache_reset
62+
swiftscan_scanner_diagnostics_query
63+
swiftscan_scanner_diagnostics_reset
64+
swiftscan_diagnostic_get_message
65+
swiftscan_diagnostic_get_severity
66+
swiftscan_diagnostics_set_dispose
6267
invoke_swift_compiler

0 commit comments

Comments
 (0)