Use workspace.getPackageFor to get analysis roots from open files

Using ContextRoot.root locations directly leads to analyzing the whole
workspace for Bazel workspaces.

Change-Id: I44a31a5bc6043eaaea0e9c83f6261d54443ad7a3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196494
Commit-Queue: Ivan Inozemtsev <iinozemtsev@google.com>
Reviewed-by: Danny Tuppeny <danny@tuppeny.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index 0dca37a..afe1dc7 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -49,6 +49,7 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
+import 'package:collection/collection.dart';
 import 'package:http/http.dart' as http;
 import 'package:meta/meta.dart';
 import 'package:watcher/watcher.dart';
@@ -666,17 +667,22 @@
     final contextLocator = ContextLocator(resourceProvider: resourceProvider);
     final roots = contextLocator.locateRoots(includedPaths: openFiles);
 
-    // For files in folders that don't have pubspecs, a root would be
-    // produced for the root of the drive which we do not want, so filter those out.
-    roots.removeWhere((root) => root.root.isRoot);
-
-    // Find any files that are no longer covered by roots because of the above
-    // removal.
-    final additionalFiles =
-        openFiles.where((file) => !roots.any((root) => root.isAnalyzed(file)));
+    var packages = <String>{};
+    var additionalFiles = <String>[];
+    for (var file in openFiles) {
+      var package = roots
+          .where((root) => root.isAnalyzed(file))
+          .map((root) => root.workspace.findPackageFor(file)?.root)
+          .firstWhereOrNull((p) => p != null);
+      if (package != null && !resourceProvider.getFolder(package).isRoot) {
+        packages.add(package);
+      } else {
+        additionalFiles.add(file);
+      }
+    }
 
     return [
-      ...roots.map((root) => root.root.path),
+      ...packages,
       ...additionalFiles,
     ];
   }
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart
index fb9fcdf..a1b7707 100644
--- a/pkg/analysis_server/test/lsp/initialization_test.dart
+++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -29,6 +29,27 @@
         registrationFor(registrations, method)?.registerOptions);
   }
 
+  Future<void> test_bazelWorkspace() async {
+    var workspacePath = '/home/user/ws';
+    // Make it a Bazel workspace.
+    newFile(convertPath('$workspacePath/WORKSPACE'));
+
+    var packagePath = '$workspacePath/team/project1';
+
+    // Make it a Blaze project.
+    newFile(convertPath('$packagePath/BUILD'));
+
+    final file1 = convertPath('$packagePath/lib/file1.dart');
+    newFile(file1);
+
+    await initialize(allowEmptyRootUri: true);
+
+    // Expect that context manager includes a whole package.
+    await openFile(Uri.file(file1), '');
+    expect(server.contextManager.includedPaths,
+        equals([convertPath(packagePath)]));
+  }
+
   Future<void> test_completionRegistrations_triggerCharacters() async {
     final registrations = <Registration>[];
     final initResponse = await monitorDynamicRegistrations(