Move Workspace creation into ContextLocatorImpl.

Change-Id: I98f85e4365cd3190781827c79c9b1dedf0702a2d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/206671
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index e143315..502ea26 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -6,103 +6,9 @@
 import 'dart:core';
 
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/context/packages.dart';
-import 'package:analyzer/src/workspace/basic.dart';
-import 'package:analyzer/src/workspace/bazel.dart';
-import 'package:analyzer/src/workspace/gn.dart';
-import 'package:analyzer/src/workspace/package_build.dart';
-import 'package:analyzer/src/workspace/pub.dart';
-import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:yaml/yaml.dart';
 
-/// A utility class used to build an analysis context for a given directory.
-///
-/// The construction of analysis contexts is as follows:
-///
-/// 1. Determine how package: URI's are to be resolved. This follows the lookup
-///    algorithm defined by the [package specification][1].
-///
-/// 2. Using the results of step 1, look in each package for an embedder file
-///    (_embedder.yaml). If one exists then it defines the SDK. If multiple such
-///    files exist then use the first one found. Otherwise, use the default SDK.
-///
-/// 3. Look for an analysis options file (`analysis_options.yaml`) and process
-///    the options in the file.
-///
-/// 4. Create a new context. Initialize its source factory based on steps 1, 2
-///    and 3. Initialize its analysis options from step 4.
-///
-/// [1]: https://github.com/dart-lang/dart_enhancement_proposals/blob/master/Accepted/0005%20-%20Package%20Specification/DEP-pkgspec.md.
-class ContextBuilder {
-  /// Return [Packages] to analyze a resource with the [rootPath].
-  static Packages createPackageMap({
-    required ResourceProvider resourceProvider,
-    required ContextBuilderOptions options,
-    required String rootPath,
-  }) {
-    var configPath = options.defaultPackageFilePath;
-    if (configPath != null) {
-      var configFile = resourceProvider.getFile(configPath);
-      return parsePackagesFile(resourceProvider, configFile);
-    } else {
-      var resource = resourceProvider.getResource(rootPath);
-      return findPackagesFrom(resourceProvider, resource);
-    }
-  }
-
-  /// If [packages] is provided, it will be used for the [Workspace],
-  /// otherwise the packages file from [options] will be used, or discovered
-  /// from [rootPath].
-  ///
-  /// TODO(scheglov) Make [packages] required, remove [options] and discovery.
-  static Workspace createWorkspace({
-    required ResourceProvider resourceProvider,
-    required ContextBuilderOptions options,
-    Packages? packages,
-    required String rootPath,
-    bool lookForBazelBuildFileSubstitutes = true,
-  }) {
-    packages ??= ContextBuilder.createPackageMap(
-      resourceProvider: resourceProvider,
-      options: options,
-      rootPath: rootPath,
-    );
-    var packageMap = <String, List<Folder>>{};
-    for (var package in packages.packages) {
-      packageMap[package.name] = [package.libFolder];
-    }
-
-    if (_hasPackageFileInPath(resourceProvider, rootPath)) {
-      // A Bazel or Gn workspace that includes a '.packages' file is treated
-      // like a normal (non-Bazel/Gn) directory. But may still use
-      // package:build or Pub.
-      return PackageBuildWorkspace.find(
-              resourceProvider, packageMap, rootPath) ??
-          PubWorkspace.find(resourceProvider, packageMap, rootPath) ??
-          BasicWorkspace.find(resourceProvider, packageMap, rootPath);
-    }
-    Workspace? workspace = BazelWorkspace.find(resourceProvider, rootPath,
-        lookForBuildFileSubstitutes: lookForBazelBuildFileSubstitutes);
-    workspace ??= GnWorkspace.find(resourceProvider, rootPath);
-    workspace ??=
-        PackageBuildWorkspace.find(resourceProvider, packageMap, rootPath);
-    workspace ??= PubWorkspace.find(resourceProvider, packageMap, rootPath);
-    workspace ??= BasicWorkspace.find(resourceProvider, packageMap, rootPath);
-    return workspace;
-  }
-
-  /// Return `true` if either the directory at [rootPath] or a parent of that
-  /// directory contains a `.packages` file.
-  static bool _hasPackageFileInPath(
-      ResourceProvider resourceProvider, String rootPath) {
-    var folder = resourceProvider.getFolder(rootPath);
-    return folder.withAncestors.any((current) {
-      return current.getChildAssumingFile('.packages').exists;
-    });
-  }
-}
-
-/// Options used by a [ContextBuilder].
+/// TODO(scheglov) It is not used, inline it.
 class ContextBuilderOptions {
   /// The file path of the analysis options file that should be used in place of
   /// any file in the root directory or a parent of the root directory, or `null`
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
index c1dfa14..7927eca 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
@@ -10,14 +10,16 @@
 import 'package:analyzer/file_system/physical_file_system.dart'
     show PhysicalResourceProvider;
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
-import 'package:analyzer/src/context/builder.dart' as old;
-import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/context_root.dart';
 import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:analyzer/src/util/yaml.dart';
 import 'package:analyzer/src/workspace/basic.dart';
+import 'package:analyzer/src/workspace/bazel.dart';
+import 'package:analyzer/src/workspace/gn.dart';
+import 'package:analyzer/src/workspace/package_build.dart';
+import 'package:analyzer/src/workspace/pub.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:glob/glob.dart';
 import 'package:path/path.dart';
@@ -366,12 +368,34 @@
       packages = Packages.empty;
     }
 
-    return old.ContextBuilder.createWorkspace(
-      resourceProvider: resourceProvider,
-      packages: packages,
-      options: ContextBuilderOptions(), // TODO(scheglov) remove it
-      rootPath: folder.path,
-    );
+    // TODO(scheglov) Can we use Packages instead?
+    var packageMap = <String, List<Folder>>{};
+    for (var package in packages.packages) {
+      packageMap[package.name] = [package.libFolder];
+    }
+
+    var rootPath = folder.path;
+
+    // TODO(scheglov) Do we need this?
+    if (_hasPackageFileInPath(rootPath)) {
+      // A Bazel or Gn workspace that includes a '.packages' file is treated
+      // like a normal (non-Bazel/Gn) directory. But may still use
+      // package:build or Pub.
+      return PackageBuildWorkspace.find(
+              resourceProvider, packageMap, rootPath) ??
+          PubWorkspace.find(resourceProvider, packageMap, rootPath) ??
+          BasicWorkspace.find(resourceProvider, packageMap, rootPath);
+    }
+
+    Workspace? workspace;
+    workspace = BazelWorkspace.find(resourceProvider, rootPath,
+        lookForBuildFileSubstitutes: false);
+    workspace ??= GnWorkspace.find(resourceProvider, rootPath);
+    workspace ??=
+        PackageBuildWorkspace.find(resourceProvider, packageMap, rootPath);
+    workspace ??= PubWorkspace.find(resourceProvider, packageMap, rootPath);
+    workspace ??= BasicWorkspace.find(resourceProvider, packageMap, rootPath);
+    return workspace;
   }
 
   File? _findDefaultOptionsFile(Workspace workspace) {
@@ -491,6 +515,15 @@
     return _getFile(folder, file_paths.dotPackages);
   }
 
+  /// Return `true` if either the directory at [rootPath] or a parent of that
+  /// directory contains a `.packages` file.
+  bool _hasPackageFileInPath(String rootPath) {
+    var folder = resourceProvider.getFolder(rootPath);
+    return folder.withAncestors.any((current) {
+      return current.getChildAssumingFile('.packages').exists;
+    });
+  }
+
   /// Add to the given lists of [folders] and [files] all of the resources in
   /// the given list of [paths] that exist and are not contained within one of
   /// the folders.
diff --git a/pkg/analyzer/lib/src/workspace/simple.dart b/pkg/analyzer/lib/src/workspace/simple.dart
index 51d96d2..02413ce 100644
--- a/pkg/analyzer/lib/src/workspace/simple.dart
+++ b/pkg/analyzer/lib/src/workspace/simple.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/context/builder.dart';
 import 'package:analyzer/src/generated/sdk.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/source/package_map_resolver.dart';
@@ -12,9 +11,6 @@
 
 /// An abstract class for simple workspaces which do not feature any build
 /// artifacts or generated files.
-///
-/// The [packageMap] and [packageUrlResolver] are simple derivations from the
-/// [ContextBuilder] and [ResourceProvider] required for the class.
 abstract class SimpleWorkspace extends Workspace {
   /// The [ResourceProvider] by which paths are converted into [Resource]s.
   final ResourceProvider provider;