@@ -44,14 +44,16 @@ import 'package:analyzer_plugin/protocol/protocol_constants.dart' as protocol;
44
44
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as protocol;
45
45
import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' ;
46
46
47
- typedef _ErrorAndProtocolError = ({
47
+ /// A pair, matching a [Diagnostic] with it's equivalent
48
+ /// [protocol.AnalysisError] .
49
+ typedef _DiagnosticAndAnalysisError = ({
48
50
Diagnostic diagnostic,
49
- protocol.AnalysisError protocolError ,
51
+ protocol.AnalysisError analysisError ,
50
52
});
51
53
52
54
typedef _PluginState = ({
53
55
AnalysisContext analysisContext,
54
- List <_ErrorAndProtocolError > errors,
56
+ List <_DiagnosticAndAnalysisError > errors,
55
57
});
56
58
57
59
/// The server that communicates with the analysis server, passing requests and
@@ -201,7 +203,7 @@ class PluginServer {
201
203
var errorFixesList = < protocol.AnalysisErrorFixes > [];
202
204
203
205
var workspace = DartChangeWorkspace ([analysisContext.currentSession]);
204
- for (var (: diagnostic, : protocolError ) in lintAtOffset) {
206
+ for (var (: diagnostic, : analysisError ) in lintAtOffset) {
205
207
var context = DartFixContext (
206
208
// TODO(srawlins): Use a real instrumentation service. Other
207
209
// implementations get InstrumentationService from AnalysisServer.
@@ -223,7 +225,7 @@ class PluginServer {
223
225
224
226
if (fixes.isNotEmpty) {
225
227
fixes.sort (Fix .compareFixes);
226
- var errorFixes = protocol.AnalysisErrorFixes (protocolError );
228
+ var errorFixes = protocol.AnalysisErrorFixes (analysisError );
227
229
errorFixesList.add (errorFixes);
228
230
for (var fix in fixes) {
229
231
errorFixes.fixes.add (protocol.PrioritizedSourceChange (1 , fix.change));
@@ -282,7 +284,7 @@ class PluginServer {
282
284
.where ((p) => file_paths.isDart (_resourceProvider.pathContext, p))
283
285
.toSet ();
284
286
285
- await _analyzeFiles (analysisContext: analysisContext, paths: paths);
287
+ await _analyzeLibraries (analysisContext: analysisContext, paths: paths);
286
288
});
287
289
_channel.sendNotification (
288
290
protocol.PluginStatusParams (
@@ -291,52 +293,65 @@ class PluginServer {
291
293
);
292
294
}
293
295
294
- Future <void > _analyzeFile ({
296
+ /// Analyzes the library at the given [libraryPath] , sending an
297
+ /// 'analysis.errors' [Notification] for each compilation unit.
298
+ Future <void > _analyzeLibrary ({
295
299
required AnalysisContext analysisContext,
296
- required String path ,
300
+ required String libraryPath ,
297
301
}) async {
298
- var file = _resourceProvider.getFile (path );
302
+ var file = _resourceProvider.getFile (libraryPath );
299
303
var analysisOptions = analysisContext.getAnalysisOptionsForFile (file);
300
- var diagnostics = await _computeDiagnostics (
304
+ var analysisErrorsByPath = await _computeAnalysisErrors (
301
305
analysisContext,
302
- path ,
306
+ libraryPath ,
303
307
analysisOptions: analysisOptions as AnalysisOptionsImpl ,
304
308
);
305
- _channel.sendNotification (
306
- protocol.AnalysisErrorsParams (path, diagnostics).toNotification (),
307
- );
309
+ for (var MapEntry (key: path, value: analysisErrors)
310
+ in analysisErrorsByPath.entries) {
311
+ _channel.sendNotification (
312
+ protocol.AnalysisErrorsParams (path, analysisErrors).toNotification (),
313
+ );
314
+ }
308
315
}
309
316
310
- /// Analyzes the files at the given [paths] .
311
- Future <void > _analyzeFiles ({
317
+ /// Analyzes the libraries at the given [paths] .
318
+ Future <void > _analyzeLibraries ({
312
319
required AnalysisContext analysisContext,
313
320
required Set <String > paths,
314
321
}) async {
315
322
// First analyze priority files.
316
323
for (var path in _priorityPaths) {
317
324
if (paths.remove (path)) {
318
- await _analyzeFile (analysisContext: analysisContext, path: path);
325
+ await _analyzeLibrary (
326
+ analysisContext: analysisContext,
327
+ libraryPath: path,
328
+ );
319
329
}
320
330
}
321
331
322
332
// Then analyze the remaining files.
323
333
for (var path in paths) {
324
- await _analyzeFile (analysisContext: analysisContext, path: path);
334
+ await _analyzeLibrary (
335
+ analysisContext: analysisContext,
336
+ libraryPath: path,
337
+ );
325
338
}
326
339
}
327
340
328
- Future <List <protocol.AnalysisError >> _computeDiagnostics (
341
+ /// Computes and returns [protocol.AnalysisError] s for each of the parts in
342
+ /// the library at [libraryPath] .
343
+ Future <Map <String , List <protocol.AnalysisError >>> _computeAnalysisErrors (
329
344
AnalysisContext analysisContext,
330
- String path , {
345
+ String libraryPath , {
331
346
required AnalysisOptionsImpl analysisOptions,
332
347
}) async {
333
348
var libraryResult = await analysisContext.currentSession.getResolvedLibrary (
334
- path ,
349
+ libraryPath ,
335
350
);
336
351
if (libraryResult is ! ResolvedLibraryResult ) {
337
352
// We only handle analyzing at the library-level. Below, we work through
338
353
// each of the compilation units found in `libraryResult`.
339
- return const [] ;
354
+ return const {} ;
340
355
}
341
356
342
357
var diagnosticListeners = {
@@ -426,8 +441,8 @@ class PluginServer {
426
441
427
442
// The list of the `AnalysisError`s and their associated
428
443
// `protocol.AnalysisError`s.
429
- var diagnosticsAndProtocolErrors =
430
- < ({Diagnostic diagnostic, protocol.AnalysisError protocolError })> [];
444
+ var diagnosticsAndAnalysisErrors =
445
+ < ({Diagnostic diagnostic, protocol.AnalysisError analysisError })> [];
431
446
432
447
diagnosticListeners.forEach ((unitResult, listener) {
433
448
var ignoreInfo = IgnoreInfo .forDart (unitResult.unit, unitResult.content);
@@ -442,9 +457,9 @@ class PluginServer {
442
457
});
443
458
444
459
for (var diagnostic in diagnostics) {
445
- diagnosticsAndProtocolErrors .add ((
460
+ diagnosticsAndAnalysisErrors .add ((
446
461
diagnostic: diagnostic,
447
- protocolError : protocol.AnalysisError (
462
+ analysisError : protocol.AnalysisError (
448
463
severityMapping[diagnostic.diagnosticCode] ??
449
464
protocol.AnalysisErrorSeverity .INFO ,
450
465
protocol.AnalysisErrorType .STATIC_WARNING ,
@@ -459,11 +474,22 @@ class PluginServer {
459
474
}
460
475
});
461
476
462
- _recentState[path ] = (
477
+ _recentState[libraryPath ] = (
463
478
analysisContext: analysisContext,
464
- errors: [...diagnosticsAndProtocolErrors ],
479
+ errors: [...diagnosticsAndAnalysisErrors ],
465
480
);
466
- return diagnosticsAndProtocolErrors.map ((e) => e.protocolError).toList ();
481
+
482
+ // A map that has a key for each unit's path. It is important to collect the
483
+ // analysis errors for each unit, even if it has none. We must send a
484
+ // notification for each unit, even if there are no analysis errors to
485
+ // report.
486
+ var analysisErrorsByPath = < String , List <protocol.AnalysisError >> {
487
+ for (var unitResult in libraryResult.units) unitResult.path: [],
488
+ };
489
+ for (var (diagnostic: _, : analysisError) in diagnosticsAndAnalysisErrors) {
490
+ analysisErrorsByPath[analysisError.location.file]! .add (analysisError);
491
+ }
492
+ return analysisErrorsByPath;
467
493
}
468
494
469
495
/// Converts the severity of [code] into a [protocol.AnalysisErrorSeverity] .
@@ -601,7 +627,7 @@ class PluginServer {
601
627
/// one or more files. The implementation may check if these files should
602
628
/// be analyzed, do such analysis, and send diagnostics.
603
629
///
604
- /// By default invokes [_analyzeFiles ] only for files that are analyzed in
630
+ /// By default invokes [_analyzeLibraries ] only for files that are analyzed in
605
631
/// this [analysisContext] .
606
632
Future <void > _handleAffectedFiles ({
607
633
required AnalysisContext analysisContext,
@@ -611,7 +637,10 @@ class PluginServer {
611
637
.where (analysisContext.contextRoot.isAnalyzed)
612
638
.toSet ();
613
639
614
- await _analyzeFiles (analysisContext: analysisContext, paths: analyzedPaths);
640
+ await _analyzeLibraries (
641
+ analysisContext: analysisContext,
642
+ paths: analyzedPaths,
643
+ );
615
644
}
616
645
617
646
/// Handles an 'analysis.setContextRoots' request.
0 commit comments