deprecate analysis options `sdkVersionConstraint` getter

Noteworthy:

* deprecates the `sdkVersionConstraint` getter and updates uses
* migrates tests for sdk contstraints in the absence of a pubspec from context_builder_test to analysis_context_collection_test
* makes `pubPackages` getter broadly visible

Next step: remove the code that sets the `sdkVersionConstraint` in the analysis options object and remove the getter.


Change-Id: I443cdd15ec8d28ac6fa6786e06c1e4b027eee747
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/341084
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Keerti Parthasarathy <keertip@google.com>
Commit-Queue: Phil Quitslund <pquitslund@google.com>
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 3e8b392..ab57c1e 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -29,6 +29,8 @@
 import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:analyzer/src/workspace/blaze.dart';
 import 'package:analyzer/src/workspace/blaze_watcher.dart';
+import 'package:analyzer/src/workspace/pub.dart';
+import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
 import 'package:analyzer_plugin/utilities/analyzer_converter.dart';
 import 'package:path/path.dart' as path;
@@ -351,19 +353,23 @@
 
   /// Use the given analysis [driver] to analyze the content of the analysis
   /// options file at the given [path].
-  void _analyzeAnalysisOptionsYaml(AnalysisDriver driver, String path) {
+  void _analyzeAnalysisOptionsYaml(
+      AnalysisDriver driver, WorkspacePackage? package, String path) {
     var convertedErrors = const <protocol.AnalysisError>[];
     try {
       var file = resourceProvider.getFile(path);
       var analysisOptions = driver.getAnalysisOptionsForFile(file);
       var content = file.readAsStringSync();
       var lineInfo = LineInfo.fromContent(content);
+      var sdkVersionConstraint = (package is PubWorkspacePackage)
+          ? package.sdkVersionConstraint
+          : null;
       var errors = analyzeAnalysisOptions(
         file.createSource(),
         content,
         driver.sourceFactory,
         driver.currentSession.analysisContext.contextRoot.root.path,
-        analysisOptions.sdkVersionConstraint,
+        sdkVersionConstraint,
       );
       var converter = AnalyzerConverter();
       convertedErrors = converter.convertAnalysisErrors(errors,
@@ -589,7 +595,9 @@
 
           if (optionsFile != null &&
               analysisContext.contextRoot.isAnalyzed(optionsFile.path)) {
-            _analyzeAnalysisOptionsYaml(driver, optionsFile.path);
+            var package = analysisContext.contextRoot.workspace
+                .findPackageFor(optionsFile.path);
+            _analyzeAnalysisOptionsYaml(driver, package, optionsFile.path);
           }
 
           var packageName = rootFolder.shortName;
diff --git a/pkg/analysis_server/lib/src/handler/legacy/edit_get_fixes.dart b/pkg/analysis_server/lib/src/handler/legacy/edit_get_fixes.dart
index b55993f..1605cc0 100644
--- a/pkg/analysis_server/lib/src/handler/legacy/edit_get_fixes.dart
+++ b/pkg/analysis_server/lib/src/handler/legacy/edit_get_fixes.dart
@@ -25,6 +25,7 @@
 import 'package:analyzer/src/pubspec/pubspec_validator.dart';
 import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer/src/util/file_paths.dart' as file_paths;
+import 'package:analyzer/src/workspace/pub.dart';
 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:yaml/yaml.dart';
 
@@ -105,14 +106,16 @@
     var session = driver.currentSession;
     var sourceFactory = driver.sourceFactory;
     var analysisContext = session.analysisContext;
-    var analysisOptions =
-        analysisContext.getAnalysisOptionsForFile(optionsFile);
+    var package =
+        analysisContext.contextRoot.workspace.findPackageFor(optionsFile.path);
+    var sdkVersionConstraint =
+        (package is PubWorkspacePackage) ? package.sdkVersionConstraint : null;
     var errors = analyzeAnalysisOptions(
       optionsFile.createSource(),
       content,
       sourceFactory,
       analysisContext.contextRoot.root.path,
-      analysisOptions.sdkVersionConstraint,
+      sdkVersionConstraint,
     );
     var options = _getOptions(sourceFactory, content);
     if (options == null) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/code_actions/analysis_options.dart b/pkg/analysis_server/lib/src/lsp/handlers/code_actions/analysis_options.dart
index ca04eee..6d79e03 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/code_actions/analysis_options.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/code_actions/analysis_options.dart
@@ -11,6 +11,7 @@
 import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
 import 'package:analyzer/src/generated/source.dart' show SourceFactory;
 import 'package:analyzer/src/task/options.dart';
+import 'package:analyzer/src/workspace/pub.dart';
 import 'package:yaml/yaml.dart';
 
 /// Produces [CodeAction]s from analysis options fixes.
@@ -57,15 +58,17 @@
       return [];
     }
 
-    final analysisContext = session.analysisContext;
-    final analysisOptions =
-        analysisContext.getAnalysisOptionsForFile(optionsFile);
+    final contextRoot = session.analysisContext.contextRoot;
+    final package = contextRoot.workspace.findPackageFor(optionsFile.path);
+    final sdkVersionConstraint =
+        (package is PubWorkspacePackage) ? package.sdkVersionConstraint : null;
+
     final errors = analyzeAnalysisOptions(
       optionsFile.createSource(),
       content,
       sourceFactory,
-      analysisContext.contextRoot.root.path,
-      analysisOptions.sdkVersionConstraint,
+      contextRoot.root.path,
+      sdkVersionConstraint,
     );
 
     final codeActions = <CodeActionWithPriority>[];
diff --git a/pkg/analysis_server/lib/src/services/user_prompts/dart_fix_prompt_manager.dart b/pkg/analysis_server/lib/src/services/user_prompts/dart_fix_prompt_manager.dart
index 1e48143..3d3695f 100644
--- a/pkg/analysis_server/lib/src/services/user_prompts/dart_fix_prompt_manager.dart
+++ b/pkg/analysis_server/lib/src/services/user_prompts/dart_fix_prompt_manager.dart
@@ -14,7 +14,7 @@
 import 'package:analysis_server/src/services/correction/bulk_fix_processor.dart';
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
 import 'package:analysis_server/src/services/user_prompts/user_prompts.dart';
-import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
+import 'package:analyzer/src/workspace/pub.dart';
 import 'package:collection/collection.dart';
 import 'package:meta/meta.dart';
 
@@ -72,10 +72,12 @@
   Map<String, List<String?>> get currentContextSdkConstraints {
     final constraintMap = <String, List<String?>>{};
     for (final context in server.contextManager.analysisContexts) {
-      var sdkConstraints = (context as DriverBasedAnalysisContext)
-          .allAnalysisOptions
-          .map((o) => o.sdkVersionConstraint?.toString())
-          .toList();
+      var workspace = context.contextRoot.workspace;
+      var sdkConstraints = workspace is PubWorkspace
+          ? workspace.pubPackages
+              .map((p) => p.sdkVersionConstraint?.toString())
+              .toList()
+          : <String>[];
       constraintMap[context.contextRoot.root.path] = sdkConstraints;
     }
     return constraintMap;
diff --git a/pkg/analyzer/lib/dart/analysis/analysis_options.dart b/pkg/analyzer/lib/dart/analysis/analysis_options.dart
index 0d105f9..87a8424 100644
--- a/pkg/analyzer/lib/dart/analysis/analysis_options.dart
+++ b/pkg/analyzer/lib/dart/analysis/analysis_options.dart
@@ -49,7 +49,7 @@
 
   /// The version range for the SDK specified in `pubspec.yaml`, or `null` if
   /// there is no `pubspec.yaml` or if it does not contain an SDK range.
-  // TODO(pq): @Deprecated('Use `PubWorkspacePackage.sdkVersionConstraint` instead')
+  @Deprecated('Use `PubWorkspacePackage.sdkVersionConstraint` instead')
   VersionConstraint? get sdkVersionConstraint;
 
   /// Return `true` if analysis is to generate warning results (e.g. best
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index ad41b60..4337a17 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -262,6 +262,8 @@
       var extractor = SdkConstraintExtractor(pubspecFile);
       var sdkVersionConstraint = extractor.constraint();
       if (sdkVersionConstraint != null) {
+        // TODO(pq): remove
+        // ignore: deprecated_member_use_from_same_package
         options.sdkVersionConstraint = sdkVersionConstraint;
       }
     }
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder2.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder2.dart
index 007fb91..920c448 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder2.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder2.dart
@@ -191,6 +191,8 @@
         var extractor = SdkConstraintExtractor(pubspecFile);
         var sdkVersionConstraint = extractor.constraint();
         if (sdkVersionConstraint != null) {
+          // TODO(pq): remove
+          // ignore: deprecated_member_use_from_same_package
           options.sdkVersionConstraint = sdkVersionConstraint;
         }
       }
@@ -324,6 +326,8 @@
       var extractor = SdkConstraintExtractor(pubspecFile);
       var sdkVersionConstraint = extractor.constraint();
       if (sdkVersionConstraint != null) {
+        // TODO(pq): remove
+        // ignore: deprecated_member_use_from_same_package
         options.sdkVersionConstraint = sdkVersionConstraint;
       }
     }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 6d9399e..b6d2057 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -51,6 +51,7 @@
 import 'package:analyzer/src/task/strong/checker.dart';
 import 'package:analyzer/src/util/performance/operation_performance.dart';
 import 'package:analyzer/src/utilities/extensions/version.dart';
+import 'package:analyzer/src/workspace/pub.dart';
 import 'package:collection/collection.dart';
 import 'package:path/path.dart' as path;
 
@@ -495,7 +496,9 @@
     // Find code that uses features from an SDK version that does not satisfy
     // the SDK constraints specified in analysis options.
     //
-    var sdkVersionConstraint = _analysisOptions.sdkVersionConstraint;
+    var package = file.workspacePackage;
+    var sdkVersionConstraint =
+        (package is PubWorkspacePackage) ? package.sdkVersionConstraint : null;
     if (sdkVersionConstraint != null) {
       SdkConstraintVerifier verifier = SdkConstraintVerifier(
         errorReporter,
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index bb7596c..901facf 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -166,6 +166,7 @@
   Uint32List? _signatureForElements;
 
   @override
+  @Deprecated('Use `PubWorkspacePackage.sdkVersionConstraint` instead')
   VersionConstraint? sdkVersionConstraint;
 
   /// The constraint on the language version for every Dart file.
@@ -265,6 +266,7 @@
       strictInference = options.strictInference;
       strictRawTypes = options.strictRawTypes;
     }
+    // ignore: deprecated_member_use_from_same_package
     sdkVersionConstraint = options.sdkVersionConstraint;
   }
 
@@ -319,7 +321,10 @@
       ApiSignature buffer = ApiSignature();
 
       // Append environment.
+      // TODO(pq): remove
+      // ignore: deprecated_member_use_from_same_package
       if (sdkVersionConstraint != null) {
+        // ignore: deprecated_member_use_from_same_package
         buffer.addString(sdkVersionConstraint.toString());
       }
 
diff --git a/pkg/analyzer/lib/src/workspace/pub.dart b/pkg/analyzer/lib/src/workspace/pub.dart
index 9db13d4..7539b2b 100644
--- a/pkg/analyzer/lib/src/workspace/pub.dart
+++ b/pkg/analyzer/lib/src/workspace/pub.dart
@@ -264,7 +264,6 @@
     return PackageMapUriResolver(provider, packageMap);
   }
 
-  @visibleForTesting
   List<PubWorkspacePackage> get pubPackages => [_theOnlyPackage];
 
   /// For some package file, which may or may not be a package source (it could
diff --git a/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart b/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart
index f31f4ff..1c035cb 100644
--- a/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart
@@ -224,6 +224,40 @@
     registerLintRules();
   }
 
+  test_basicWorkspace() async {
+    final workspaceRootPath = '/home';
+    final testPackageRootPath = '$workspaceRootPath/test';
+
+    newSinglePackageConfigJsonFile(
+      packagePath: testPackageRootPath,
+      name: 'test',
+    );
+
+    newFile('$testPackageRootPath/lib/a.dart', '');
+
+    final contextCollection = AnalysisContextCollectionImpl(
+      resourceProvider: resourceProvider,
+      sdkPath: sdkRoot.path,
+      includedPaths: [
+        getFolder(workspaceRootPath).path,
+      ],
+    );
+
+    _assertContextCollectionText(contextCollection, r'''
+contexts
+  /home/test
+    packagesFile: /home/test/.dart_tool/package_config.json
+    workspace: workspace_0
+    analyzedFiles
+      /home/test/lib/a.dart
+        uri: package:test/a.dart
+        workspacePackage_0_0
+workspaces
+  workspace_0: BasicWorkspace
+    root: /home/test
+''');
+  }
+
   test_pubWorkspace_multipleAnalysisOptions() async {
     final workspaceRootPath = '/home';
     final testPackageRootPath = '$workspaceRootPath/test';
diff --git a/pkg/analyzer/test/src/dart/analysis/context_builder2_test.dart b/pkg/analyzer/test/src/dart/analysis/context_builder2_test.dart
index f499a68..9b38190 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_builder2_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_builder2_test.dart
@@ -88,28 +88,6 @@
     );
   }
 
-  void test_analysisOptions_sdkVersionConstraint_hasPubspec_hasSdk() {
-    var projectPath = convertPath('/home/test');
-    var pubspec = newPubspecYamlFile(projectPath, '''
-environment:
-  sdk: ^2.1.0
-''');
-
-    var analysisContext = _createSingleAnalysisContext(projectPath);
-    var analysisOptions =
-        analysisContext.getAnalysisOptionsImplForFile(pubspec);
-    expect(analysisOptions.sdkVersionConstraint.toString(), '^2.1.0');
-  }
-
-  void test_analysisOptions_sdkVersionConstraint_noPubspec() {
-    var projectPath = convertPath('/home/test');
-    var file = newFile('$projectPath/lib/a.dart', '');
-
-    var analysisContext = _createSingleAnalysisContext(projectPath);
-    var analysisOptions = analysisContext.getAnalysisOptionsForFile(file);
-    expect(analysisOptions.sdkVersionConstraint, isNull);
-  }
-
   test_createContext_declaredVariables() {
     DeclaredVariables declaredVariables =
         DeclaredVariables.fromMap({'foo': 'true'});
diff --git a/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart b/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
index 41c4d90..e4e5c77 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_builder_test.dart
@@ -87,27 +87,6 @@
     );
   }
 
-  void test_analysisOptions_sdkVersionConstraint_hasPubspec_hasSdk() {
-    var projectPath = convertPath('/home/test');
-    newPubspecYamlFile(projectPath, '''
-environment:
-  sdk: ^2.1.0
-''');
-
-    var analysisContext = _createSingleAnalysisContext(projectPath);
-    var analysisOptions = analysisContext.analysisOptionsImpl;
-    expect(analysisOptions.sdkVersionConstraint.toString(), '^2.1.0');
-  }
-
-  void test_analysisOptions_sdkVersionConstraint_noPubspec() {
-    var projectPath = convertPath('/home/test');
-    newFile('$projectPath/lib/a.dart', '');
-
-    var analysisContext = _createSingleAnalysisContext(projectPath);
-    var analysisOptions = analysisContext.driver.analysisOptions;
-    expect(analysisOptions.sdkVersionConstraint, isNull);
-  }
-
   test_createContext_declaredVariables() {
     DeclaredVariables declaredVariables =
         DeclaredVariables.fromMap({'foo': 'true'});
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 882c8a4..dab50cd 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -26,6 +26,7 @@
 import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:analyzer/src/util/yaml.dart';
 import 'package:analyzer/src/utilities/legacy.dart';
+import 'package:analyzer/src/workspace/pub.dart';
 import 'package:analyzer_cli/src/analyzer_impl.dart';
 import 'package:analyzer_cli/src/batch_mode.dart';
 import 'package:analyzer_cli/src/error_formatter.dart';
@@ -246,12 +247,18 @@
           var analysisOptions = analysisDriver.getAnalysisOptionsForFile(file);
           var content = file.readAsStringSync();
           var lineInfo = LineInfo.fromContent(content);
+          var contextRoot =
+              analysisDriver.currentSession.analysisContext.contextRoot;
+          var package = contextRoot.workspace.findPackageFor(file.path);
+          var sdkVersionConstraint = (package is PubWorkspacePackage)
+              ? package.sdkVersionConstraint
+              : null;
           var errors = analyzeAnalysisOptions(
             file.createSource(),
             content,
             analysisDriver.sourceFactory,
-            analysisDriver.currentSession.analysisContext.contextRoot.root.path,
-            analysisOptions.sdkVersionConstraint,
+            contextRoot.root.path,
+            sdkVersionConstraint,
           );
           await formatter.formatErrors([
             ErrorsResultImpl(