get libraries to fix from the context collection

Fixes: https://github.com/dart-lang/sdk/issues/43694

Also implements recursive fix semantics consistent with `dart analyze`.



Change-Id: I349650a0c1704c2e2be84287b46de17ecc132d56
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166602
Commit-Queue: Phil Quitslund <pquitslund@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 570c266..b702179 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -42,9 +42,11 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
+import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/src/dart/analysis/results.dart' as engine;
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart' as engine;
+import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/error/codes.dart' as engine;
 import 'package:analyzer/src/exception/exception.dart';
 import 'package:analyzer/src/generated/engine.dart' as engine;
@@ -105,15 +107,21 @@
         }
       }
 
-      var paths = <String>[];
-      for (var include in params.included) {
-        var resource = server.resourceProvider.getResource(include);
-        resource.collectDartFilePaths(paths);
-      }
-
       var workspace = DartChangeWorkspace(server.currentSessions);
       var processor = BulkFixProcessor(workspace);
-      var changeBuilder = await processor.fixErrorsInLibraries(paths);
+
+      String sdkPath;
+      var sdk = server.findSdk();
+      if (sdk is FolderBasedDartSdk) {
+        sdkPath = sdk.directory.path;
+      }
+      var collection = AnalysisContextCollectionImpl(
+        includedPaths: params.included,
+        resourceProvider: server.resourceProvider,
+        sdkPath: sdkPath,
+      );
+      var changeBuilder = await processor.fixErrors(collection.contexts);
+
       var response = EditBulkFixesResult(changeBuilder.sourceChange.edits)
           .toResponse(request.id);
       server.sendResponse(response);
@@ -1315,15 +1323,3 @@
 /// [_RefactoringManager] throws instances of this class internally to stop
 /// processing in a manager that was reset.
 class _ResetError {}
-
-extension ResourceExtension on Resource {
-  void collectDartFilePaths(List<String> paths) {
-    if (this is File && AnalysisEngine.isDartFileName(path)) {
-      paths.add(path);
-    } else if (this is Folder) {
-      for (var child in (this as Folder).getChildren()) {
-        child.collectDartFilePaths(paths);
-      }
-    }
-  }
-}
diff --git a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
index 5bd6ce2..0de1a9d 100644
--- a/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/bulk_fix_processor.dart
@@ -61,10 +61,12 @@
 import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
 import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer/dart/analysis/analysis_context.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/source/error_processor.dart';
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 
@@ -341,16 +343,22 @@
   }
 
   /// Return a change builder that has been used to create fixes for the
-  /// diagnostics in the libraries at the given [libraryPaths].
-  Future<ChangeBuilder> fixErrorsInLibraries(List<String> libraryPaths) async {
-    for (var path in libraryPaths) {
-      var session = workspace.getSession(path);
-      var kind = await session.getSourceKind(path);
-      if (kind == SourceKind.LIBRARY) {
-        var libraryResult = await session.getResolvedLibrary(path);
-        await _fixErrorsInLibrary(libraryResult);
+  /// diagnostics in the libraries in the given [contexts].
+  Future<ChangeBuilder> fixErrors(List<AnalysisContext> contexts) async {
+    for (var context in contexts) {
+      for (var path in context.contextRoot.analyzedFiles()) {
+        if (!AnalysisEngine.isDartFileName(path)) {
+          continue;
+        }
+        var kind = await context.currentSession.getSourceKind(path);
+        if (kind != SourceKind.LIBRARY) {
+          continue;
+        }
+        var library = await context.currentSession.getResolvedLibrary(path);
+        await _fixErrorsInLibrary(library);
       }
     }
+
     return builder;
   }
 
diff --git a/pkg/analysis_server/test/edit/bulk_fixes_test.dart b/pkg/analysis_server/test/edit/bulk_fixes_test.dart
index cf1c6c7..18f2356 100644
--- a/pkg/analysis_server/test/edit/bulk_fixes_test.dart
+++ b/pkg/analysis_server/test/edit/bulk_fixes_test.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/edit/edit_domain.dart';
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:linter/src/rules.dart';
 import 'package:test/test.dart';
@@ -38,10 +39,77 @@
     super.setUp();
     registerLintRules();
     handler = EditDomainHandler(server);
+    createProject();
+  }
+
+  Future<void> test_annotateOverrides_excludedSubProject() async {
+    // Root project.
+    addAnalysisOptionsFile('''
+analyzer:
+  exclude:
+    - test/data/**
+''');
+
+    // Sub-project.
+    var subprojectRoot = '$projectPath/test/data/subproject';
+    newFile('$subprojectRoot/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}',
+        content: '''
+linter:
+  rules:
+    - annotate_overrides
+''');
+
+    newFile('$subprojectRoot/${AnalysisEngine.PUBSPEC_YAML_FILE}', content: '''
+name: subproject
+''');
+
+    newFile('$subprojectRoot/test.dart', content: '''
+class A {
+  void f() {}
+}
+class B extends A {
+  void f() { }
+}
+''');
+
+    await assertNoEdits();
+  }
+
+  Future<void> test_annotateOverrides_subProject() async {
+    var subprojectRoot = '$projectPath/test/data/subproject';
+    newFile('$subprojectRoot/${AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE}',
+        content: '''
+linter:
+  rules:
+    - annotate_overrides
+''');
+
+    newFile('$subprojectRoot/${AnalysisEngine.PUBSPEC_YAML_FILE}', content: '''
+name: subproject
+''');
+
+    testFile = '$subprojectRoot/test.dart';
+    addTestFile('''
+class A {
+  void f() {}
+}
+class B extends A {
+  void f() { }
+}
+''');
+
+    await assertEditEquals('''
+class A {
+  void f() {}
+}
+class B extends A {
+  @override
+  void f() { }
+}
+''');
   }
 
   Future<void> test_unnecessaryNew() async {
-    createProject();
     addAnalysisOptionsFile('''
 linter:
   rules:
@@ -59,7 +127,6 @@
   }
 
   Future<void> test_unnecessaryNew_ignoredInOptions() async {
-    createProject();
     addAnalysisOptionsFile('''
 analyzer:
   errors:
@@ -76,7 +143,6 @@
   }
 
   Future<void> test_unnecessaryNew_ignoredInSource() async {
-    createProject();
     addAnalysisOptionsFile('''
 linter:
   rules:
@@ -91,7 +157,7 @@
   }
 
   Future<List<SourceFileEdit>> _getBulkEdits() async {
-    var request = EditBulkFixesParams([testFile]).toRequest('0');
+    var request = EditBulkFixesParams([projectPath]).toRequest('0');
     var response = await waitResponse(request);
     var result = EditBulkFixesResult.fromResponse(response);
     return result.edits;
diff --git a/pkg/analysis_server/test/integration/edit/bulk_fixes_test.dart b/pkg/analysis_server/test/integration/edit/bulk_fixes_test.dart
index 922c0c8..9b42331 100644
--- a/pkg/analysis_server/test/integration/edit/bulk_fixes_test.dart
+++ b/pkg/analysis_server/test/integration/edit/bulk_fixes_test.dart
@@ -2,6 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/src/generated/engine.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -27,11 +28,23 @@
     standardAnalysisSetup();
   }
 
-  @failingTest
   Future<void> test_bulk_fix_override() async {
-    setupTarget();
+    writeFile(sourcePath(AnalysisEngine.ANALYSIS_OPTIONS_YAML_FILE), '''
+linter:
+  rules:
+    - annotate_overrides
+''');
+    writeFile(sourcePath('test.dart'), '''
+class A {
+  void f() {}
+}
+class B extends A {
+  void f() { }
+}
+''');
+    standardAnalysisSetup();
 
     var result = await sendEditBulkFixes([sourceDirectory.path]);
-    expect(result.edits.length, 1);
+    expect(result.edits, hasLength(1));
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/bulk/bulk_fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/bulk/bulk_fix_processor.dart
index ef3a83a..bd51bc3 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/bulk/bulk_fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/bulk/bulk_fix_processor.dart
@@ -58,7 +58,7 @@
     var tracker = DeclarationsTracker(MemoryByteStore(), resourceProvider);
     tracker.addContext(driver.analysisContext);
     var changeBuilder =
-        await BulkFixProcessor(workspace).fixErrorsInLibraries([testFile]);
+        await BulkFixProcessor(workspace).fixErrors([driver.analysisContext]);
     return changeBuilder.sourceChange;
   }