Skip to content

Commit 8532092

Browse files
authored
Merge pull request swiftlang#71907 from artemcm/ScannerDiagsPerQuery
[Dependency Scanning] Collect emitted diagnostics per-scan-query
2 parents 4a6bd7d + d2a8e32 commit 8532092

File tree

9 files changed

+187
-68
lines changed

9 files changed

+187
-68
lines changed

include/swift-c/DependencyScan/DependencyScan.h

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ typedef struct {
6161
size_t count;
6262
} swiftscan_dependency_set_t;
6363

64+
typedef enum {
65+
SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR = 0,
66+
SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING = 1,
67+
SWIFTSCAN_DIAGNOSTIC_SEVERITY_NOTE = 2,
68+
SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK = 3
69+
} swiftscan_diagnostic_severity_t;
70+
71+
typedef struct {
72+
swiftscan_diagnostic_info_t *diagnostics;
73+
size_t count;
74+
} swiftscan_diagnostic_set_t;
75+
6476
//=== Batch Scan Input Specification --------------------------------------===//
6577

6678
/// Opaque container to a container of batch scan entry information.
@@ -92,6 +104,12 @@ SWIFTSCAN_PUBLIC swiftscan_dependency_set_t *
92104
swiftscan_dependency_graph_get_dependencies(
93105
swiftscan_dependency_graph_t result);
94106

107+
// Return value disposed of together with the dependency_graph
108+
// using `swiftscan_dependency_graph_dispose`
109+
SWIFTSCAN_PUBLIC swiftscan_diagnostic_set_t *
110+
swiftscan_dependency_graph_get_diagnostics(
111+
swiftscan_dependency_graph_t result);
112+
95113
//=== Dependency Module Info Functions ------------------------------------===//
96114

97115
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
@@ -277,6 +295,11 @@ swiftscan_batch_scan_entry_get_is_swift(swiftscan_batch_scan_entry_t entry);
277295
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
278296
swiftscan_import_set_get_imports(swiftscan_import_set_t result);
279297

298+
// Return value disposed of together with the dependency_graph
299+
// using `swiftscan_import_set_dispose`
300+
SWIFTSCAN_PUBLIC swiftscan_diagnostic_set_t *
301+
swiftscan_import_set_get_diagnostics(swiftscan_import_set_t result);
302+
280303
//=== Scanner Invocation Functions ----------------------------------------===//
281304

282305
/// Create an \c swiftscan_scan_invocation_t instance.
@@ -378,18 +401,6 @@ SWIFTSCAN_PUBLIC swiftscan_import_set_t swiftscan_import_set_create(
378401

379402

380403
//=== Scanner Diagnostics -------------------------------------------------===//
381-
typedef enum {
382-
SWIFTSCAN_DIAGNOSTIC_SEVERITY_ERROR = 0,
383-
SWIFTSCAN_DIAGNOSTIC_SEVERITY_WARNING = 1,
384-
SWIFTSCAN_DIAGNOSTIC_SEVERITY_NOTE = 2,
385-
SWIFTSCAN_DIAGNOSTIC_SEVERITY_REMARK = 3
386-
} swiftscan_diagnostic_severity_t;
387-
388-
typedef struct {
389-
swiftscan_diagnostic_info_t *diagnostics;
390-
size_t count;
391-
} swiftscan_diagnostic_set_t;
392-
393404
/// For the specified \c scanner instance, query all insofar emitted diagnostics
394405
SWIFTSCAN_PUBLIC swiftscan_diagnostic_set_t*
395406
swiftscan_scanner_diagnostics_query(swiftscan_scanner_t scanner);

include/swift/DependencyScan/DependencyScanImpl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ struct swiftscan_dependency_graph_s {
3030

3131
/// The complete list of modules discovered
3232
swiftscan_dependency_set_t *dependencies;
33+
34+
/// Diagnostics produced during this scan
35+
swiftscan_diagnostic_set_t *diagnostics;
3336
};
3437

3538
struct swiftscan_dependency_info_s {
@@ -192,6 +195,8 @@ struct swiftscan_batch_scan_entry_s {
192195
struct swiftscan_import_set_s {
193196
/// The complete list of imports discovered
194197
swiftscan_string_set_t *imports;
198+
/// Diagnostics produced during this import scan
199+
swiftscan_diagnostic_set_t *diagnostics;
195200
};
196201

197202
struct swiftscan_scan_invocation_s {

include/swift/DependencyScan/DependencyScanningTool.h

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,48 @@
2424
namespace swift {
2525
namespace dependencies {
2626
class DependencyScanningTool;
27+
class DependencyScanDiagnosticCollector;
28+
29+
struct ScanQueryInstance {
30+
std::unique_ptr<CompilerInstance> ScanInstance;
31+
std::unique_ptr<DependencyScanDiagnosticCollector> ScanDiagnostics;
32+
};
2733

2834
/// 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(); }
35+
class DependencyScanDiagnosticCollector : public DiagnosticConsumer {
3436
private:
3537
struct ScannerDiagnosticInfo {
3638
std::string Message;
3739
llvm::SourceMgr::DiagKind Severity;
3840
};
39-
40-
void handleDiagnostic(SourceManager &SM,
41-
const DiagnosticInfo &Info) override;
42-
void addDiagnostic(SourceManager &SM, const DiagnosticInfo &Info);
41+
42+
void handleDiagnostic(SourceManager &SM, const DiagnosticInfo &Info) override;
4343
std::vector<ScannerDiagnosticInfo> Diagnostics;
44-
// FIXME: For now, we isolate access to shared state of this object
45-
// but we really should make sure that it doesn't get shared.
46-
llvm::sys::SmartMutex<true> ScanningDiagnosticConsumerStateLock;
44+
45+
protected:
46+
virtual void addDiagnostic(SourceManager &SM, const DiagnosticInfo &Info);
47+
48+
public:
49+
friend DependencyScanningTool;
50+
DependencyScanDiagnosticCollector() {}
51+
void reset() { Diagnostics.clear(); }
52+
const std::vector<ScannerDiagnosticInfo> &getDiagnostics() const {
53+
return Diagnostics;
54+
}
4755
};
4856

57+
/// Locking variant of the above diagnostic collector that guards accesses to
58+
/// its state with a lock.
59+
class LockingDependencyScanDiagnosticCollector
60+
: public DependencyScanDiagnosticCollector {
61+
private:
62+
void addDiagnostic(SourceManager &SM, const DiagnosticInfo &Info) override;
63+
llvm::sys::SmartMutex<true> ScanningDiagnosticConsumerStateLock;
64+
65+
public:
66+
friend DependencyScanningTool;
67+
LockingDependencyScanDiagnosticCollector() {}
68+
};
4969

5070
/// Given a set of arguments to a print-target-info frontend tool query, produce the
5171
/// JSON target info.
@@ -93,19 +113,19 @@ class DependencyScanningTool {
93113
/// Discard the tool's current `SharedCache` and start anew.
94114
void resetCache();
95115
/// Query diagnostics consumed so far.
96-
std::vector<DependencyScannerDiagnosticCollectingConsumer::ScannerDiagnosticInfo> getDiagnostics();
116+
std::vector<DependencyScanDiagnosticCollector::ScannerDiagnosticInfo> getDiagnostics();
97117
/// Discared the collection of diagnostics encountered so far.
98118
void resetDiagnostics();
99119

100120
/// Using the specified invocation command, instantiate a CompilerInstance
101121
/// that will be used for this scan.
102-
llvm::ErrorOr<std::unique_ptr<CompilerInstance>>
122+
llvm::ErrorOr<ScanQueryInstance>
103123
initCompilerInstanceForScan(ArrayRef<const char *> Command);
104124

105125
private:
106126
/// Using the specified invocation command, initialize the scanner instance
107127
/// for this scan. Returns the `CompilerInstance` that will be used.
108-
llvm::ErrorOr<std::unique_ptr<CompilerInstance>>
128+
llvm::ErrorOr<ScanQueryInstance>
109129
initScannerForAction(ArrayRef<const char *> Command);
110130

111131
/// Shared cache of module dependencies, re-used by individual full-scan queries
@@ -120,7 +140,7 @@ class DependencyScanningTool {
120140
llvm::sys::SmartMutex<true> DependencyScanningToolStateLock;
121141

122142
/// A shared consumer that accumulates encountered diagnostics.
123-
DependencyScannerDiagnosticCollectingConsumer CDC;
143+
LockingDependencyScanDiagnosticCollector CDC;
124144
llvm::BumpPtrAllocator Alloc;
125145
llvm::StringSaver Saver;
126146
};

include/swift/DependencyScan/ScanDependencies.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class ModuleDependenciesCache;
3030
class SwiftDependencyScanningService;
3131

3232
namespace dependencies {
33+
class DependencyScanDiagnosticCollector;
3334

3435
using CompilerArgInstanceCacheMap =
3536
llvm::StringMap<std::tuple<std::unique_ptr<CompilerInstance>,
@@ -59,16 +60,19 @@ bool batchScanDependencies(CompilerInstance &instance,
5960
/// Scans the dependencies of the main module of \c instance.
6061
llvm::ErrorOr<swiftscan_dependency_graph_t>
6162
performModuleScan(CompilerInstance &instance,
63+
DependencyScanDiagnosticCollector *diagnostics,
6264
ModuleDependenciesCache &cache);
6365

6466
/// Scans the main module of \c instance for all direct module imports
6567
llvm::ErrorOr<swiftscan_import_set_t>
6668
performModulePrescan(CompilerInstance &instance,
69+
DependencyScanDiagnosticCollector *diagnostics,
6770
ModuleDependenciesCache &cache);
6871

6972
/// Batch scan the dependencies for modules specified in \c batchInputFile.
7073
std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t>>
7174
performBatchModuleScan(CompilerInstance &invocationInstance,
75+
DependencyScanDiagnosticCollector *diagnostics,
7276
ModuleDependenciesCache &invocationCache,
7377
CompilerArgInstanceCacheMap *versionedPCMInstanceCache,
7478
llvm::StringSaver &saver,

lib/DependencyScan/DependencyScanningTool.cpp

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,16 @@ llvm::ErrorOr<swiftscan_string_ref_t> getTargetInfo(ArrayRef<const char *> Comma
6868
return c_string_utils::create_clone(ResultStr.c_str());
6969
}
7070

71-
void DependencyScannerDiagnosticCollectingConsumer::handleDiagnostic(SourceManager &SM,
71+
void DependencyScanDiagnosticCollector::handleDiagnostic(SourceManager &SM,
7272
const DiagnosticInfo &Info) {
7373
addDiagnostic(SM, Info);
7474
for (auto ChildInfo : Info.ChildDiagnosticInfo) {
7575
addDiagnostic(SM, *ChildInfo);
7676
}
7777
}
7878

79-
void DependencyScannerDiagnosticCollectingConsumer::addDiagnostic(SourceManager &SM, const DiagnosticInfo &Info) {
80-
llvm::sys::SmartScopedLock<true> Lock(ScanningDiagnosticConsumerStateLock);
79+
void DependencyScanDiagnosticCollector::addDiagnostic(
80+
SourceManager &SM, const DiagnosticInfo &Info) {
8181
// Determine what kind of diagnostic we're emitting.
8282
llvm::SourceMgr::DiagKind SMKind;
8383
switch (Info.Kind) {
@@ -115,6 +115,12 @@ void DependencyScannerDiagnosticCollectingConsumer::addDiagnostic(SourceManager
115115
Diagnostics.push_back(ScannerDiagnosticInfo{Msg.getMessage().str(), SMKind});
116116
}
117117

118+
void LockingDependencyScanDiagnosticCollector::addDiagnostic(
119+
SourceManager &SM, const DiagnosticInfo &Info) {
120+
llvm::sys::SmartScopedLock<true> Lock(ScanningDiagnosticConsumerStateLock);
121+
DependencyScanDiagnosticCollector::addDiagnostic(SM, Info);
122+
}
123+
118124
DependencyScanningTool::DependencyScanningTool()
119125
: ScanningService(std::make_unique<SwiftDependencyScanningService>()),
120126
VersionedPCMInstanceCacheCache(
@@ -126,18 +132,20 @@ DependencyScanningTool::getDependencies(
126132
ArrayRef<const char *> Command,
127133
const llvm::StringSet<> &PlaceholderModules) {
128134
// The primary instance used to scan the query Swift source-code
129-
auto InstanceOrErr = initScannerForAction(Command);
130-
if (std::error_code EC = InstanceOrErr.getError())
135+
auto QueryContextOrErr = initScannerForAction(Command);
136+
if (std::error_code EC = QueryContextOrErr.getError())
131137
return EC;
132-
auto Instance = std::move(*InstanceOrErr);
138+
auto QueryContext = std::move(*QueryContextOrErr);
133139

134140
// Local scan cache instance, wrapping the shared global cache.
135141
ModuleDependenciesCache cache(
136-
*ScanningService, Instance->getMainModule()->getNameStr().str(),
137-
Instance->getInvocation().getFrontendOptions().ExplicitModulesOutputPath,
138-
Instance->getInvocation().getModuleScanningHash());
142+
*ScanningService, QueryContext.ScanInstance->getMainModule()->getNameStr().str(),
143+
QueryContext.ScanInstance->getInvocation().getFrontendOptions().ExplicitModulesOutputPath,
144+
QueryContext.ScanInstance->getInvocation().getModuleScanningHash());
139145
// Execute the scanning action, retrieving the in-memory result
140-
auto DependenciesOrErr = performModuleScan(*Instance.get(), cache);
146+
auto DependenciesOrErr = performModuleScan(*QueryContext.ScanInstance.get(),
147+
QueryContext.ScanDiagnostics.get(),
148+
cache);
141149
if (DependenciesOrErr.getError())
142150
return std::make_error_code(std::errc::not_supported);
143151
auto Dependencies = std::move(*DependenciesOrErr);
@@ -148,17 +156,19 @@ DependencyScanningTool::getDependencies(
148156
llvm::ErrorOr<swiftscan_import_set_t>
149157
DependencyScanningTool::getImports(ArrayRef<const char *> Command) {
150158
// The primary instance used to scan the query Swift source-code
151-
auto InstanceOrErr = initScannerForAction(Command);
152-
if (std::error_code EC = InstanceOrErr.getError())
159+
auto QueryContextOrErr = initScannerForAction(Command);
160+
if (std::error_code EC = QueryContextOrErr.getError())
153161
return EC;
154-
auto Instance = std::move(*InstanceOrErr);
162+
auto QueryContext = std::move(*QueryContextOrErr);
155163

156164
// Local scan cache instance, wrapping the shared global cache.
157165
ModuleDependenciesCache cache(
158-
*ScanningService, Instance->getMainModule()->getNameStr().str(),
159-
Instance->getInvocation().getFrontendOptions().ExplicitModulesOutputPath,
160-
Instance->getInvocation().getModuleScanningHash());
161-
auto DependenciesOrErr = performModulePrescan(*Instance.get(), cache);
166+
*ScanningService, QueryContext.ScanInstance->getMainModule()->getNameStr().str(),
167+
QueryContext.ScanInstance->getInvocation().getFrontendOptions().ExplicitModulesOutputPath,
168+
QueryContext.ScanInstance->getInvocation().getModuleScanningHash());
169+
auto DependenciesOrErr = performModulePrescan(*QueryContext.ScanInstance.get(),
170+
QueryContext.ScanDiagnostics.get(),
171+
cache);
162172
if (DependenciesOrErr.getError())
163173
return std::make_error_code(std::errc::not_supported);
164174
auto Dependencies = std::move(*DependenciesOrErr);
@@ -172,19 +182,20 @@ DependencyScanningTool::getDependencies(
172182
const std::vector<BatchScanInput> &BatchInput,
173183
const llvm::StringSet<> &PlaceholderModules) {
174184
// The primary instance used to scan Swift modules
175-
auto InstanceOrErr = initScannerForAction(Command);
176-
if (std::error_code EC = InstanceOrErr.getError())
185+
auto QueryContextOrErr = initScannerForAction(Command);
186+
if (std::error_code EC = QueryContextOrErr.getError())
177187
return std::vector<llvm::ErrorOr<swiftscan_dependency_graph_t>>(
178188
BatchInput.size(), std::make_error_code(std::errc::invalid_argument));
179-
auto Instance = std::move(*InstanceOrErr);
189+
auto QueryContext = std::move(*QueryContextOrErr);
180190

181191
// Local scan cache instance, wrapping the shared global cache.
182192
ModuleDependenciesCache cache(
183-
*ScanningService, Instance->getMainModule()->getNameStr().str(),
184-
Instance->getInvocation().getFrontendOptions().ExplicitModulesOutputPath,
185-
Instance->getInvocation().getModuleScanningHash());
193+
*ScanningService, QueryContext.ScanInstance->getMainModule()->getNameStr().str(),
194+
QueryContext.ScanInstance->getInvocation().getFrontendOptions().ExplicitModulesOutputPath,
195+
QueryContext.ScanInstance->getInvocation().getModuleScanningHash());
186196
auto BatchScanResults = performBatchModuleScan(
187-
*Instance.get(), cache, VersionedPCMInstanceCacheCache.get(),
197+
*QueryContext.ScanInstance.get(), QueryContext.ScanDiagnostics.get(),
198+
cache, VersionedPCMInstanceCacheCache.get(),
188199
Saver, BatchInput);
189200

190201
return BatchScanResults;
@@ -221,7 +232,7 @@ void DependencyScanningTool::resetCache() {
221232
}
222233

223234
std::vector<
224-
DependencyScannerDiagnosticCollectingConsumer::ScannerDiagnosticInfo>
235+
DependencyScanDiagnosticCollector::ScannerDiagnosticInfo>
225236
DependencyScanningTool::getDiagnostics() {
226237
llvm::sys::SmartScopedLock<true> Lock(DependencyScanningToolStateLock);
227238
return CDC.Diagnostics;
@@ -232,25 +243,27 @@ void DependencyScanningTool::resetDiagnostics() {
232243
CDC.reset();
233244
}
234245

235-
llvm::ErrorOr<std::unique_ptr<CompilerInstance>>
246+
llvm::ErrorOr<ScanQueryInstance>
236247
DependencyScanningTool::initScannerForAction(
237248
ArrayRef<const char *> Command) {
238249
// The remainder of this method operates on shared state in the
239250
// scanning service and global LLVM state with:
240251
// llvm::cl::ResetAllOptionOccurrences
241252
llvm::sys::SmartScopedLock<true> Lock(DependencyScanningToolStateLock);
242-
auto instanceOrErr = initCompilerInstanceForScan(Command);
243-
if (instanceOrErr.getError())
244-
return instanceOrErr;
245-
return instanceOrErr;
253+
return initCompilerInstanceForScan(Command);
246254
}
247255

248-
llvm::ErrorOr<std::unique_ptr<CompilerInstance>>
256+
llvm::ErrorOr<ScanQueryInstance>
249257
DependencyScanningTool::initCompilerInstanceForScan(
250258
ArrayRef<const char *> CommandArgs) {
251259
// State unique to an individual scan
252260
auto Instance = std::make_unique<CompilerInstance>();
261+
auto ScanDiagnosticConsumer = std::make_unique<DependencyScanDiagnosticCollector>();
262+
263+
// FIXME: The shared CDC must be deprecated once all clients have switched
264+
// to using per-scan diagnostic output embedded in the `swiftscan_dependency_graph_s`
253265
Instance->addDiagnosticConsumer(&CDC);
266+
Instance->addDiagnosticConsumer(ScanDiagnosticConsumer.get());
254267

255268
// Basic error checking on the arguments
256269
if (CommandArgs.empty()) {
@@ -300,7 +313,8 @@ DependencyScanningTool::initCompilerInstanceForScan(
300313

301314
(void)Instance->getMainModule();
302315

303-
return Instance;
316+
return ScanQueryInstance{std::move(Instance),
317+
std::move(ScanDiagnosticConsumer)};
304318
}
305319

306320
} // namespace dependencies

0 commit comments

Comments
 (0)