Version 2.14.0-377.1.beta

Merge '2.14.0-377.0.dev' into beta
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 204df98..faad814 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2021-07-02T15:48:57.033703",
+  "generated": "2021-07-27T19:27:52.638315",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -64,7 +64,7 @@
       "name": "_js_interop_checks",
       "rootUri": "../pkg/_js_interop_checks",
       "packageUri": "lib/",
-      "languageVersion": "2.7"
+      "languageVersion": "2.12"
     },
     {
       "name": "analysis_server",
@@ -142,13 +142,13 @@
       "name": "browser_launcher",
       "rootUri": "../third_party/pkg/browser_launcher",
       "packageUri": "lib/",
-      "languageVersion": "2.2"
+      "languageVersion": "2.12"
     },
     {
       "name": "build_integration",
       "rootUri": "../pkg/build_integration",
       "packageUri": "lib/",
-      "languageVersion": "2.1"
+      "languageVersion": "2.12"
     },
     {
       "name": "charcode",
@@ -250,7 +250,7 @@
       "name": "dev_compiler",
       "rootUri": "../pkg/dev_compiler",
       "packageUri": "lib/",
-      "languageVersion": "2.3"
+      "languageVersion": "2.12"
     },
     {
       "name": "devtools_shared",
@@ -354,12 +354,6 @@
       "languageVersion": "2.12"
     },
     {
-      "name": "http_retry",
-      "rootUri": "../third_party/pkg/http_retry",
-      "packageUri": "lib/",
-      "languageVersion": "2.12"
-    },
-    {
       "name": "http_throttle",
       "rootUri": "../third_party/pkg/http_throttle",
       "packageUri": "lib/",
@@ -731,13 +725,13 @@
       "name": "testing",
       "rootUri": "../pkg/testing",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.12"
     },
     {
       "name": "typed_data",
       "rootUri": "../third_party/pkg/typed_data",
       "packageUri": "lib/",
-      "languageVersion": "2.10"
+      "languageVersion": "2.12"
     },
     {
       "name": "usage",
@@ -755,7 +749,7 @@
       "name": "vm",
       "rootUri": "../pkg/vm",
       "packageUri": "lib/",
-      "languageVersion": "2.7"
+      "languageVersion": "2.12"
     },
     {
       "name": "vm_service",
@@ -797,7 +791,7 @@
       "name": "webkit_inspection_protocol",
       "rootUri": "../third_party/pkg/webkit_inspection_protocol",
       "packageUri": "lib/",
-      "languageVersion": "2.0"
+      "languageVersion": "2.12"
     },
     {
       "name": "yaml",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ed07841..b1dcdb8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -159,8 +159,26 @@
 
 #### Linter
 
-Updated the Linter to `1.7.0`, which includes changes that
+Updated the Linter to `1.8.0`, which includes changes that
 
+
+- improve performance for `prefer_is_not_empty`.
+- fix false positives in `no_logic_in_create_state`.
+- improve `package_names` to allow dart identifiers as package names.
+- fix a false-positive in `package_names` (causing keywords to wrongly get flagged).
+- fix `avoid_classes_with_only_static_member` to check for inherited members and also
+  flag classes with only methods.
+- fix `curly_braces_in_flow_control_structures` to properly flag terminating `else-if`
+  blocks.
+- improve `always_specify_types` to support type aliases.
+- fix a false positive in `unnecessary_string_interpolations` w/ nullable interpolated 
+  strings
+- fix a false positive in `avoid_function_literals_in_foreach_calls` for nullable
+  iterables.
+- fix false positives in `avoid_returning_null` w/ NNBD
+- fix false positives in `use_late_for_private_fields_and_variables` in the presence
+  of const constructors.
+- adds a new lint: `eol_at_end_of_file`.
 - fix case-sensitive false positive in `use_full_hex_values_for_flutter_colors`.
 - improve try-block and switch statement flow analysis for
   `use_build_context_synchronously`.
@@ -246,50 +264,15 @@
 [#46545]: https://github.com/dart-lang/sdk/issues/46545
 [1]: https://dart.dev/faq#q-what-browsers-do-you-support-as-javascript-compilation-targets
 
-### Language
+#### Dart Dev Compiler (DDC)
 
-*   Add an unsigned shift right operator `>>>`. Pad with zeroes, ignoring the
-    sign bit. On the web platform `int.>>>` shifts the low 32 bits interpreted
-    as an unsigned integer, so `a >>> b` gives the same result as
-    `a.toUnsigned(32) >>> b` on the VM.
+- **Breaking Change** [#44154][]: Subtyping relations of `package:js` classes
+  have been changed to be more correct and consistent with Dart2JS.
+  Like `anonymous` classes, non-`anonymous` classes will no longer check the
+  underlying type in DDC. The internal type representation of these objects have
+  changed as well, which will affect the `toString` value of these types.
 
-*   Prior to Dart 2.14, metadata (annotations) were not permitted to be
-    specified with generic type arguments.  This restriction is lifted in Dart
-    Dart 2.14.
-
-    ```dart
-    class C<T> {
-      const C();
-    }
-    @C();      // Previously permitted.
-    @C<int>(); // Previously an error, now permitted.
-    ```
-
-*   Prior to Dart 2.14, generic function types were not permitted as arguments
-    to generic classes or functions, nor to be used as generic bounds.  This
-    restriction is lifted in Dart 2.14.
-
-    ```dart
-    T wrapWithLogging<T>(T f) {
-      if (f is void Function<T>(T x)) {
-        return <S>(S x) {
-          print("Call: f<$S>($x)");
-          var r = f<S>(x);
-          print("Return: $x");
-          return r;
-        } as T;
-      } // More cases here
-      return f;
-    }
-    void foo<T>(T x) {
-      print("Foo!");
-    }
-    void main() {
-      // Previously an error, now permitted.
-      var f = wrapWithLogging<void Function<T>(T)>(foo);
-      f<int>(3);
-    }
-    ```
+[#44154]: https://github.com/dart-lang/sdk/issues/44154
 
 ## 2.13.4 - 2021-06-28
 
diff --git a/DEPS b/DEPS
index ac49b8f..613addf 100644
--- a/DEPS
+++ b/DEPS
@@ -39,7 +39,7 @@
 
   # Checked-in SDK version. The checked-in SDK is a Dart SDK distribution in a
   # cipd package used to run Dart scripts in the build and test infrastructure.
-  "sdk_tag": "version:2.13.1",
+  "sdk_tag": "version:2.14.0-293.0.dev",
 
   # co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
   # hashes. It requires access to the dart-build-access group, which EngProd
@@ -72,22 +72,22 @@
   "gperftools_revision": "180bfa10d7cb38e8b3784d60943d50e8fcef0dcb",
 
   # Revisions of /third_party/* dependencies.
-  "args_rev": "d8fea36c10ef96797be02e3d132d572445cd86f4",
-  "async_rev": "8193eac211905cf33ae1f514022fdbd843836be5",
+  "args_rev": "bf4c8796881b62fd5d3f6d86ab43014f9651eb20",
+  "async_rev": "25a7e2ec39c03622b86918cb9ce3e7d00dd283d1",
   "bazel_worker_rev": "0885637b037979afbf5bcd05fd748b309fd669c0",
   "benchmark_harness_rev": "c546dbd9f639f75cd2f75de8df2eb9f8ea15e8e7",
   "boolean_selector_rev": "665e6921ab246569420376f827bff4585dff0b14",
   "boringssl_gen_rev": "7322fc15cc065d8d2957fccce6b62a509dc4d641",
   "boringssl_rev" : "1607f54fed72c6589d560254626909a64124f091",
   "browser-compat-data_tag": "v1.0.22",
-  "browser_launcher_rev": "12ab9f351a44ac803de9bc17bb2180bb312a9dd7",
+  "browser_launcher_rev": "c6cc1025d6901926cf022e144ba109677e3548f1",
   "charcode_rev": "84ea427711e24abf3b832923959caa7dd9a8514b",
   "chrome_rev" : "19997",
   "cli_util_rev" : "8c504de5deb08fe32ecf51f9662bb37d8c708e57",
   "clock_rev" : "a494269254ba978e7ef8f192c5f7fec3fc05b9d3",
   "collection_rev": "75a7a5510979a3cd70143af85bcc1667ee233674",
-  "convert_rev": "413f591577419d8a8b95d445094a82c926650bd1",
-  "crypto_rev": "1c8ccc07b83b100216dc6dede767371043385648",
+  "convert_rev": "e063fdca4bebffecbb5e6aa5525995120982d9ce",
+  "crypto_rev": "b5024e4de2b1c474dd558bef593ddbf0bfade152",
   "csslib_rev": "e411d862fd8cc50415c1badf2632e017373b3f47",
   "dart2js_info_rev" : "e0acfeb5affdf94c53067e68bd836adf589628fd",
 
@@ -103,7 +103,7 @@
   #     and land the review.
   #
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
-  "dart_style_rev": "9d9dff90d9a2e0793ad2f795f36c2777f720eda0",
+  "dart_style_rev": "06bfd19593ed84dd288f67e02c6a753e6516288a",
 
   "dartdoc_rev" : "c9621b92c738ec21a348cc2de032858276e9c774",
   "devtools_rev" : "64cffbed6366329ad05e44d48fa2298367643bb6",
@@ -115,38 +115,37 @@
   "html_rev": "00cd3c22dac0e68e6ed9e7e4945101aedb1b3109",
   "http_io_rev": "2fa188caf7937e313026557713f7feffedd4978b",
   "http_multi_server_rev": "de1b312164c24a1690b46c6e97bd47eff40c4649",
-  "http_parser_rev": "7720bfd42a0c096734c5213478fdce92c62f0293",
-  "http_retry_rev": "845771af7bb5ab38ab740ce4a31f3b0c7680302b",
-  "http_rev": "f93c76fabdb03963303762e3fe16cbdf60799cff",
+  "http_parser_rev": "202391286ddc13c4c3c284ac5b511f04697250ed",
+  "http_rev": "778174bca2c13becd88ef3353309190b1e8b9479",
   "http_throttle_tag" : "1.0.2",
   "icu_rev" : "81d656878ec611cb0b42d52c82e9dae93920d9ba",
   "idl_parser_rev": "5fb1ebf49d235b5a70c9f49047e83b0654031eb7",
   "intl_tag": "0.17.0-nullsafety",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_rev": "7e00f893440a72de0637970325e4ea44bd1e8c8e",
-  "linter_tag": "422981ffb2fbd4010aa52381676cf745e2844dd9",
+  "linter_tag": "1.8.0",
   "lints_tag": "f9670df2a66e0ec12eb51554e70c1cbf56c8f5d0",
-  "logging_rev": "e2f633b543ef89c54688554b15ca3d7e425b86a2",
+  "logging_rev": "575781ef196e4fed4fb737e38fb4b73d62727187",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
   "markdown_rev": "9c4beaac96d8f008078e00b027915f81b665d2de",
-  "matcher_rev": "1f7b6f0cb15eb6659a1de0513571575a5c8a51d0",
+  "matcher_rev": "b411b22ec2437ba206c7a3006bbaeb519bd343d1",
   "mime_rev": "c931f4bed87221beaece356494b43731445ce7b8",
   "mockito_rev": "d39ac507483b9891165e422ec98d9fb480037c8b",
   "oauth2_rev": "7cd3284049fe5badbec9f2bea2afc41d14c01057",
   "package_config_rev": "a84c0d45401f215fbe9384df923a38f4022a3c45",
-  "path_rev": "407ab76187fade41c31e39c745b39661b710106c",
+  "path_rev": "c20d73c3516d3a0061c90f14b761ff532b9bf707",
   "pedantic_rev": "66f2f6c27581c7936482e83be80b27be2719901c",
   "platform_rev": "c20e6fa315e9f8820e51c0ae721f63aff33b8e17",
   "ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
   "pool_rev": "7abe634002a1ba8a0928eded086062f1307ccfae",
   "process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
-  "protobuf_rev": "0d03fd588df69e9863e2a2efc0059dee8f18d5b2",
-  "pub_rev": "d159e5b9f04a7e4826b6afea7b3364d48aa0dad8",
+  "protobuf_rev": "c1eb6cb51af39ccbaa1a8e19349546586a5c8e31",
+  "pub_rev": "70b1a4f9229a36bac6340ec7eae2b2068baac96c",
   "pub_semver_rev": "f50d80ef10c4b2fa5f4c8878036a4d9342c0cc82",
   "resource_rev": "6b79867d0becf5395e5819a75720963b8298e9a7",
   "root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
   "rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
-  "shelf_static_rev": "fb6b7d0ee4ad936a84e503ae6b3703cc99e61d52",
+  "shelf_static_rev": "202ec1a53c9a830c17cf3b718d089cf7eba568ad",
   "shelf_packages_handler_rev": "78302e67c035047e6348e692b0c1182131f0fe35",
   "shelf_proxy_tag": "v1.0.0",
   "shelf_rev": "46483f896cc4308ee3d8e997030ae799b72aa16a",
@@ -164,8 +163,8 @@
   "test_process_tag": "2.0.0",
   "term_glyph_rev": "6a0f9b6fb645ba75e7a00a4e20072678327a0347",
   "test_reflective_loader_rev": "54e930a11c372683792e22bddad79197728c91ce",
-  "test_rev": "030816c32b6fe78d5fb7653afbd9f63cca18bacf",
-  "typed_data_tag": "f94fc57b8e8c0e4fe4ff6cfd8290b94af52d3719",
+  "test_rev": "099dcc4d052a30c6921489cfbefa1c8531d12975",
+  "typed_data_rev": "29ce5a92b03326d0b8035916ac04f528874994bd",
   "usage_rev": "e0780cd8b2f8af69a28dc52678ffe8492da27d06",
   "vector_math_rev": "0c9f5d68c047813a6dcdeb88ba7a42daddf25025",
   "watcher_rev": "3924194385fb215cef483193ed2879a618a3d69c",
@@ -174,7 +173,7 @@
   "web_socket_channel_rev": "6448ce532445a8a458fa191d9346df071ae0acad",
   "WebCore_rev": "fb11e887f77919450e497344da570d780e078bc8",
   "webdev_rev": "b0aae7b6944d484722e6af164abedd864a2a0afa",
-  "webkit_inspection_protocol_rev": "6b15729292d030f2e5c5861022da4c5a4c11961c",
+  "webkit_inspection_protocol_rev": "dd6fb5d8b536e19cedb384d0bbf1f5631923f1e8",
   "yaml_rev": "b4c4411631bda556ce9a45af1ab0eecaf9f3ac53",
   "zlib_rev": "bf44340d1b6be1af8950bbdf664fec0cf5a831cc",
   "crashpad_rev": "bf327d8ceb6a669607b0dbab5a83a275d03f99ed",
@@ -370,9 +369,6 @@
       "@" + Var("http_multi_server_rev"),
   Var("dart_root") + "/third_party/pkg/http_parser":
       Var("dart_git") + "http_parser.git" + "@" + Var("http_parser_rev"),
-  Var("dart_root") + "/third_party/pkg/http_retry":
-      Var("dart_git") + "http_retry.git" +
-      "@" + Var("http_retry_rev"),
   Var("dart_root") + "/third_party/pkg/http_throttle":
       Var("dart_git") + "http_throttle.git" +
       "@" + Var("http_throttle_tag"),
@@ -460,7 +456,7 @@
       Var("dart_git") + "test_reflective_loader.git" +
       "@" + Var("test_reflective_loader_rev"),
   Var("dart_root") + "/third_party/pkg/typed_data":
-      Var("dart_git") + "typed_data.git" + "@" + Var("typed_data_tag"),
+      Var("dart_git") + "typed_data.git" + "@" + Var("typed_data_rev"),
   Var("dart_root") + "/third_party/pkg/usage":
       Var("dart_git") + "usage.git" + "@" + Var("usage_rev"),
   Var("dart_root") + "/third_party/pkg/vector_math":
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 7687b1d..ec4e5d2 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -109,14 +109,14 @@
     utils = imp.load_source('utils',
                             os.path.join(local_root, 'tools', 'utils.py'))
 
-    prebuilt_dartfmt = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dartfmt')
+    dart = os.path.join(utils.CheckedInSdkPath(), 'bin', 'dart')
 
     windows = utils.GuessOS() == 'win32'
     if windows:
-        prebuilt_dartfmt += '.bat'
+        dart += '.exe'
 
-    if not os.path.isfile(prebuilt_dartfmt):
-        print('WARNING: dartfmt not found: %s' % (prebuilt_dartfmt))
+    if not os.path.isfile(dart):
+        print('WARNING: dart not found: %s' % (dart))
         return []
 
     def HasFormatErrors(filename=None, contents=None):
@@ -129,13 +129,17 @@
                 if '//#' in contents:
                     return False
 
-        args = [prebuilt_dartfmt, '--set-exit-if-changed']
-        if not contents:
-            args += [filename, '-n']
+        args = [
+            dart,
+            'format',
+            '--set-exit-if-changed',
+            '--output=none',
+            '--summary=none',
+            filename,
+        ]
 
         process = subprocess.Popen(
             args, stdout=subprocess.PIPE, stdin=subprocess.PIPE)
-        process.communicate(input=contents)
 
         # Check for exit code 1 explicitly to distinguish it from a syntax error
         # in the file (exit code 65). The repo contains many Dart files that are
@@ -143,7 +147,7 @@
         # parsed and formatted. Don't treat those as errors.
         return process.returncode == 1
 
-    unformatted_files = _CheckFormat(input_api, "dartfmt", ".dart", windows,
+    unformatted_files = _CheckFormat(input_api, "dart format", ".dart", windows,
                                      HasFormatErrors)
 
     if unformatted_files:
diff --git a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
index 1130ac6..ece1bcc 100644
--- a/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
+++ b/benchmarks/SDKArtifactSizes/dart/SDKArtifactSizes.dart
@@ -34,8 +34,13 @@
 ];
 
 Future<void> reportArtifactSize(String path, String name) async {
-  final size = await File(path).length();
-  print('SDKArtifactSizes.$name(CodeSize): $size');
+  try {
+    final size = await File(path).length();
+    print('SDKArtifactSizes.$name(CodeSize): $size');
+  } on FileSystemException {
+    // Report dummy data for artifacts that don't exist for specific platforms.
+    print('SDKArtifactSizes.$name(CodeSize): 0');
+  }
 }
 
 Future<void> main() async {
diff --git a/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
index 1130ac6..ece1bcc 100644
--- a/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
+++ b/benchmarks/SDKArtifactSizes/dart2/SDKArtifactSizes.dart
@@ -34,8 +34,13 @@
 ];
 
 Future<void> reportArtifactSize(String path, String name) async {
-  final size = await File(path).length();
-  print('SDKArtifactSizes.$name(CodeSize): $size');
+  try {
+    final size = await File(path).length();
+    print('SDKArtifactSizes.$name(CodeSize): $size');
+  } on FileSystemException {
+    // Report dummy data for artifacts that don't exist for specific platforms.
+    print('SDKArtifactSizes.$name(CodeSize): 0');
+  }
 }
 
 Future<void> main() async {
diff --git a/benchmarks/SendPort/dart/SendPort.dart b/benchmarks/SendPort/dart/SendPort.dart
index a6e6044..fb950b5 100644
--- a/benchmarks/SendPort/dart/SendPort.dart
+++ b/benchmarks/SendPort/dart/SendPort.dart
@@ -175,8 +175,11 @@
 }
 
 class TreeNode {
+  @pragma('vm:entry-point') // Prevent tree shaking of this field.
   final TreeNode? left;
+  @pragma('vm:entry-point') // Prevent tree shaking of this field.
   final TreeNode? right;
+  @pragma('vm:entry-point') // Prevent tree shaking of this field.
   final int value;
 
   TreeNode(this.left, this.right, this.value);
diff --git a/benchmarks/SendPort/dart2/SendPort.dart b/benchmarks/SendPort/dart2/SendPort.dart
index 01d4042..a97acf3 100644
--- a/benchmarks/SendPort/dart2/SendPort.dart
+++ b/benchmarks/SendPort/dart2/SendPort.dart
@@ -177,8 +177,11 @@
 }
 
 class TreeNode {
+  @pragma('vm:entry-point') // Prevent tree shaking of this field.
   final TreeNode left;
+  @pragma('vm:entry-point') // Prevent tree shaking of this field.
   final TreeNode right;
+  @pragma('vm:entry-point') // Prevent tree shaking of this field.
   final int value;
 
   TreeNode(this.left, this.right, this.value);
diff --git a/build/dart/dart_action.gni b/build/dart/dart_action.gni
index c357aad..334a09a 100644
--- a/build/dart/dart_action.gni
+++ b/build/dart/dart_action.gni
@@ -51,6 +51,10 @@
       testonly = invoker.testonly
     }
 
+    if (defined(invoker.pool)) {
+      pool = invoker.pool
+    }
+
     script = "$_dart_root/build/gn_run_binary.py"
 
     if (defined(invoker.inputs)) {
@@ -109,6 +113,7 @@
                              "depfile",
                              "deps",
                              "outputs",
+                             "pool",
                              "testonly",
                              "visibility",
                            ])
@@ -256,6 +261,7 @@
                              "deps",
                              "inputs",
                              "outputs",
+                             "pool",
                              "tool",
                              "testonly",
                              "visibility",
@@ -321,6 +327,7 @@
                                "inputs",
                                "outputs",
                                "packages",
+                               "pool",
                                "script",
                                "testonly",
                                "tool",
@@ -380,6 +387,7 @@
                                "inputs",
                                "outputs",
                                "packages",
+                               "pool",
                                "testonly",
                                "tool",
                                "visibility",
diff --git a/build/fuchsia/dart.cmx b/build/fuchsia/dart.cmx
index d57d9ac..0bd0e668 100644
--- a/build/fuchsia/dart.cmx
+++ b/build/fuchsia/dart.cmx
@@ -1,27 +1,28 @@
 {
-  "program": {
-    "binary": "exe.stripped/dart"
-  },
-  "sandbox": {
-    "features": [
-      "config-data",
-      "deprecated-ambient-replace-as-executable",
-      "root-ssl-certificates",
-      "isolated-cache-storage",
-      "isolated-persistent-storage",
-      "isolated-temp"
-    ],
-    "services": [
-      "fuchsia.deprecatedtimezone.Timezone",
-      "fuchsia.device.NameProvider",
-      "fuchsia.feedback.CrashReporter",
-      "fuchsia.intl.PropertyProvider",
-      "fuchsia.logger.LogSink",
-      "fuchsia.net.NameLookup",
-      "fuchsia.posix.socket.Provider",
-      "fuchsia.sysmem.Allocator",
-      "fuchsia.timezone.Timezone",
-      "fuchsia.tracing.provider.Registry"
-    ]
-  }
+    "program": {
+        "binary": "exe.stripped/dart"
+    },
+    "sandbox": {
+        "features": [
+            "config-data",
+            "deprecated-ambient-replace-as-executable",
+            "isolated-cache-storage",
+            "isolated-persistent-storage",
+            "isolated-temp",
+            "root-ssl-certificates"
+        ],
+        "services": [
+            "fuchsia.deprecatedtimezone.Timezone",
+            "fuchsia.device.NameProvider",
+            "fuchsia.feedback.CrashReporter",
+            "fuchsia.intl.PropertyProvider",
+            "fuchsia.logger.LogSink",
+            "fuchsia.net.NameLookup",
+            "fuchsia.net.name.Lookup",
+            "fuchsia.posix.socket.Provider",
+            "fuchsia.sysmem.Allocator",
+            "fuchsia.timezone.Timezone",
+            "fuchsia.tracing.provider.Registry"
+        ]
+    }
 }
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
index 7299a94..ca0f816 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes.dart
@@ -279,7 +279,7 @@
       this.severity, this.uri, this.involvedFiles, this.codeName);
 
   factory DiagnosticMessageFromJson.fromJson(String jsonString) {
-    Map<String, Object> decoded = json.decode(jsonString);
+    Map<String, Object?> decoded = json.decode(jsonString);
     List<String> ansiFormatted =
         new List<String>.from(_asListOfString(decoded["ansiFormatted"]));
     List<String> plainTextFormatted =
diff --git a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
index 289ec96..01dd119 100644
--- a/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart
@@ -1328,6 +1328,25 @@
         r"""Extension operations can't be used in constant expressions.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalExternalConstructor =
+    messageConstEvalExternalConstructor;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalExternalConstructor = const MessageCode(
+    "ConstEvalExternalConstructor",
+    message:
+        r"""External constructors can't be evaluated in constant expressions.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeConstEvalExternalFactory = messageConstEvalExternalFactory;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageConstEvalExternalFactory = const MessageCode(
+    "ConstEvalExternalFactory",
+    message:
+        r"""External factory constructors can't be evaluated in constant expressions.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeConstEvalFailedAssertion = messageConstEvalFailedAssertion;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3992,6 +4011,16 @@
     message: r"""FFI leaf call must not have Handle argument types.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeFfiNativeAnnotationMustAnnotateStatic =
+    messageFfiNativeAnnotationMustAnnotateStatic;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageFfiNativeAnnotationMustAnnotateStatic =
+    const MessageCode("FfiNativeAnnotationMustAnnotateStatic",
+        message:
+            r"""FfiNative annotations can only be used on static functions.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(String name)> templateFfiNotStatic = const Template<
         Message Function(String name)>(
@@ -6208,6 +6237,18 @@
         message: r"""This is the enclosing class.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeJsInteropExternalExtensionMemberOnTypeInvalid =
+    messageJsInteropExternalExtensionMemberOnTypeInvalid;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageJsInteropExternalExtensionMemberOnTypeInvalid =
+    const MessageCode("JsInteropExternalExtensionMemberOnTypeInvalid",
+        message:
+            r"""JS interop or Native class required for 'external' extension members.""",
+        tip:
+            r"""Try adding a JS interop annotation to the on type class of the extension.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeJsInteropExternalMemberNotJSAnnotated =
     messageJsInteropExternalMemberNotJSAnnotated;
 
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index 0688ab2..71472cc 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -5160,7 +5160,10 @@
         // For example a(b)..<T>(c), where token is '<'.
         token = typeArg.parseArguments(token, this);
         next = token.next!;
-        assert(optional('(', next));
+        if (!optional('(', next)) {
+          listener.handleTypeArgumentApplication(token.next!);
+          typeArg = noTypeParamOrArg;
+        }
       }
       TokenType nextType = next.type;
       if (identical(nextType, TokenType.INDEX)) {
@@ -5307,7 +5310,10 @@
             listener.handleNonNullAssertExpression(bangToken);
           }
           token = typeArg.parseArguments(bangToken, this);
-          assert(optional('(', token.next!));
+          if (!optional('(', token.next!)) {
+            listener.handleTypeArgumentApplication(bangToken.next!);
+            typeArg = noTypeParamOrArg;
+          }
         }
         next = token.next!;
       } else if (optional('(', next)) {
@@ -5327,7 +5333,10 @@
             listener.handleNonNullAssertExpression(bangToken);
           }
           token = typeArg.parseArguments(bangToken, this);
-          assert(optional('(', token.next!));
+          if (!optional('(', token.next!)) {
+            listener.handleTypeArgumentApplication(bangToken.next!);
+            typeArg = noTypeParamOrArg;
+          }
         }
         next = token.next!;
       } else {
diff --git a/pkg/_js_interop_checks/lib/js_interop_checks.dart b/pkg/_js_interop_checks/lib/js_interop_checks.dart
index 4f3ba97..975fca7 100644
--- a/pkg/_js_interop_checks/lib/js_interop_checks.dart
+++ b/pkg/_js_interop_checks/lib/js_interop_checks.dart
@@ -12,6 +12,7 @@
         messageJsInteropAnonymousFactoryPositionalParameters,
         messageJsInteropEnclosingClassJSAnnotation,
         messageJsInteropEnclosingClassJSAnnotationContext,
+        messageJsInteropExternalExtensionMemberOnTypeInvalid,
         messageJsInteropExternalMemberNotJSAnnotated,
         messageJsInteropIndexNotSupported,
         messageJsInteropNamedParameters,
@@ -30,6 +31,7 @@
   bool _classHasJSAnnotation = false;
   bool _classHasAnonymousAnnotation = false;
   bool _libraryHasJSAnnotation = false;
+  Map<Reference, Extension>? _libraryExtensionsIndex;
 
   /// Libraries that use `external` to exclude from checks on external.
   static final Iterable<String> _pathsWithAllowedDartExternalUsage = <String>[
@@ -86,7 +88,8 @@
 
   @override
   void defaultMember(Member member) {
-    _checkJSInteropAnnotation(member);
+    _checkInstanceMemberJSAnnotation(member);
+    if (!_isJSInteropMember(member)) _checkDisallowedExternal(member);
     // TODO(43530): Disallow having JS interop annotations on non-external
     // members (class members or otherwise). Currently, they're being ignored.
     super.defaultMember(member);
@@ -105,14 +108,14 @@
                 cls.name, superclass.name),
             cls.fileOffset,
             cls.name.length,
-            cls.location.file);
+            cls.fileUri);
       } else if (!_classHasJSAnnotation && superHasJSAnnotation) {
         _diagnosticsReporter.report(
             templateJsInteropDartClassExtendsJSClass.withArguments(
                 cls.name, superclass.name),
             cls.fileOffset,
             cls.name.length,
-            cls.location.file);
+            cls.fileUri);
       }
     }
     // Since this is a breaking check, it is language-versioned.
@@ -129,10 +132,10 @@
         // a value for `className` that doesn't start with 'self.' or 'window.'.
         var classRegexp = new RegExp(r'^((self|window)\.)*(?<className>.*)$');
         var matches = classRegexp.allMatches(jsClass);
-        jsClass = matches.first.namedGroup('className');
+        jsClass = matches.first.namedGroup('className')!;
       }
-      if (_nativeClasses.containsKey(jsClass)) {
-        var nativeClass = _nativeClasses[jsClass];
+      var nativeClass = _nativeClasses[jsClass];
+      if (nativeClass != null) {
         _diagnosticsReporter.report(
             templateJsInteropNativeClassInAnnotation.withArguments(
                 cls.name,
@@ -140,7 +143,7 @@
                 nativeClass.enclosingLibrary.importUri.toString()),
             cls.fileOffset,
             cls.name.length,
-            cls.location.file);
+            cls.fileUri);
       }
     }
     super.visitClass(cls);
@@ -165,11 +168,12 @@
     super.visitLibrary(lib);
     _libraryIsGlobalNamespace = false;
     _libraryHasJSAnnotation = false;
+    _libraryExtensionsIndex = null;
   }
 
   @override
   void visitProcedure(Procedure procedure) {
-    _checkJSInteropAnnotation(procedure);
+    _checkInstanceMemberJSAnnotation(procedure);
     if (_classHasJSAnnotation && !procedure.isExternal) {
       // If not one of few exceptions, member is not allowed to exclude
       // `external` inside of a JS interop class.
@@ -180,43 +184,48 @@
             messageJsInteropNonExternalMember,
             procedure.fileOffset,
             procedure.name.text.length,
-            procedure.location.file);
+            procedure.fileUri);
       }
     }
-    if (!_isJSInteropMember(procedure)) return;
 
-    if (!procedure.isStatic &&
-        (procedure.name.text == '[]=' || procedure.name.text == '[]')) {
-      _diagnosticsReporter.report(
-          messageJsInteropIndexNotSupported,
-          procedure.fileOffset,
-          procedure.name.text.length,
-          procedure.location.file);
-    }
-
-    var isAnonymousFactory =
-        _classHasAnonymousAnnotation && procedure.isFactory;
-
-    if (isAnonymousFactory) {
-      if (procedure.function != null &&
-          !procedure.function.positionalParameters.isEmpty) {
-        var firstPositionalParam = procedure.function.positionalParameters[0];
-        _diagnosticsReporter.report(
-            messageJsInteropAnonymousFactoryPositionalParameters,
-            firstPositionalParam.fileOffset,
-            firstPositionalParam.name.length,
-            firstPositionalParam.location.file);
-      }
+    if (!_isJSInteropMember(procedure)) {
+      _checkDisallowedExternal(procedure);
     } else {
-      // Only factory constructors for anonymous classes are allowed to have
-      // named parameters.
-      _checkNoNamedParameters(procedure.function);
+      // Check JS interop indexing.
+      if (!procedure.isStatic &&
+          (procedure.name.text == '[]=' || procedure.name.text == '[]')) {
+        _diagnosticsReporter.report(
+            messageJsInteropIndexNotSupported,
+            procedure.fileOffset,
+            procedure.name.text.length,
+            procedure.fileUri);
+      }
+
+      // Check JS Interop positional and named parameters.
+      var isAnonymousFactory =
+          _classHasAnonymousAnnotation && procedure.isFactory;
+      if (isAnonymousFactory) {
+        // ignore: unnecessary_null_comparison
+        if (procedure.function != null &&
+            !procedure.function.positionalParameters.isEmpty) {
+          var firstPositionalParam = procedure.function.positionalParameters[0];
+          _diagnosticsReporter.report(
+              messageJsInteropAnonymousFactoryPositionalParameters,
+              firstPositionalParam.fileOffset,
+              firstPositionalParam.name!.length,
+              firstPositionalParam.location!.file);
+        }
+      } else {
+        // Only factory constructors for anonymous classes are allowed to have
+        // named parameters.
+        _checkNoNamedParameters(procedure.function);
+      }
     }
   }
 
   @override
   void visitConstructor(Constructor constructor) {
-    _checkJSInteropAnnotation(constructor);
+    _checkInstanceMemberJSAnnotation(constructor);
     if (_classHasJSAnnotation &&
         !constructor.isExternal &&
         !constructor.isSynthetic) {
@@ -225,28 +234,32 @@
           messageJsInteropNonExternalConstructor,
           constructor.fileOffset,
           constructor.name.text.length,
-          constructor.location.file);
+          constructor.fileUri);
     }
-    if (!_isJSInteropMember(constructor)) return;
 
-    _checkNoNamedParameters(constructor.function);
+    if (!_isJSInteropMember(constructor)) {
+      _checkDisallowedExternal(constructor);
+    } else {
+      _checkNoNamedParameters(constructor.function);
+    }
   }
 
   /// Reports an error if [functionNode] has named parameters.
   void _checkNoNamedParameters(FunctionNode functionNode) {
+    // ignore: unnecessary_null_comparison
     if (functionNode != null && !functionNode.namedParameters.isEmpty) {
       var firstNamedParam = functionNode.namedParameters[0];
       _diagnosticsReporter.report(
           messageJsInteropNamedParameters,
           firstNamedParam.fileOffset,
-          firstNamedParam.name.length,
-          firstNamedParam.location.file);
+          firstNamedParam.name!.length,
+          firstNamedParam.location!.file);
     }
   }
 
-  /// Reports an error if [member] does not correctly use the JS interop
-  /// annotation or the keyword `external`.
-  void _checkJSInteropAnnotation(Member member) {
+  /// Reports an error if given instance [member] is JS interop, but inside a
+  /// non JS interop class.
+  void _checkInstanceMemberJSAnnotation(Member member) {
     var enclosingClass = member.enclosingClass;
 
     if (!_classHasJSAnnotation &&
@@ -255,26 +268,38 @@
       // If in a class that is not JS interop, this member is not allowed to be
       // JS interop.
       _diagnosticsReporter.report(messageJsInteropEnclosingClassJSAnnotation,
-          member.fileOffset, member.name.text.length, member.location.file,
+          member.fileOffset, member.name.text.length, member.fileUri,
           context: <LocatedMessage>[
             messageJsInteropEnclosingClassJSAnnotationContext.withLocation(
-                enclosingClass.location.file,
+                enclosingClass.fileUri,
                 enclosingClass.fileOffset,
                 enclosingClass.name.length)
           ]);
     }
+  }
 
-    // Check for correct `external` usage.
-    if (member.isExternal &&
-        !_isAllowedExternalUsage(member) &&
-        !hasJSInteropAnnotation(member)) {
-      if (member.enclosingClass != null && !_classHasJSAnnotation ||
-          member.enclosingClass == null && !_libraryHasJSAnnotation) {
+  /// Assumes given [member] is not JS interop, and reports an error if
+  /// [member] is `external` and not an allowed `external` usage.
+  void _checkDisallowedExternal(Member member) {
+    if (member.isExternal) {
+      if (member.isExtensionMember) {
+        if (!_isNativeExtensionMember(member)) {
+          _diagnosticsReporter.report(
+              messageJsInteropExternalExtensionMemberOnTypeInvalid,
+              member.fileOffset,
+              member.name.text.length,
+              member.fileUri);
+        }
+      } else if (!hasJSInteropAnnotation(member) &&
+          !_isAllowedExternalUsage(member)) {
+        // Member could be JS annotated and not considered a JS interop member
+        // if inside a non-JS interop class. Should not report an error in this
+        // case, since a different error will already be produced.
         _diagnosticsReporter.report(
             messageJsInteropExternalMemberNotJSAnnotated,
             member.fileOffset,
             member.name.text.length,
-            member.location.file);
+            member.fileUri);
       }
     }
   }
@@ -290,13 +315,19 @@
   }
 
   /// Returns whether [member] is considered to be a JS interop member.
+  ///
+  /// A JS interop member is `external`, and is in a valid JS interop context,
+  /// which can be:
+  ///   - inside a JS interop class
+  ///   - inside an extension on a JS interop class
+  ///   - a top level member that is JS interop annotated or in a JS interop
+  ///     library
+  /// If a member belongs to a class, the class must be JS interop annotated.
   bool _isJSInteropMember(Member member) {
     if (member.isExternal) {
       if (_classHasJSAnnotation) return true;
+      if (member.isExtensionMember) return _isJSExtensionMember(member);
       if (member.enclosingClass == null) {
-        // In the case where the member does not belong to any class, a JS
-        // annotation is not needed on the library to be considered JS interop
-        // as long as the member has an annotation.
         return hasJSInteropAnnotation(member) || _libraryHasJSAnnotation;
       }
     }
@@ -304,4 +335,31 @@
     // Otherwise, not JS interop.
     return false;
   }
+
+  /// Returns whether given extension [member] is in an extension that is on a
+  /// JS interop class.
+  bool _isJSExtensionMember(Member member) {
+    return _checkExtensionMember(member, hasJSInteropAnnotation);
+  }
+
+  /// Returns whether given extension [member] is in an extension on a Native
+  /// class.
+  bool _isNativeExtensionMember(Member member) {
+    return _checkExtensionMember(member, _nativeClasses.containsValue);
+  }
+
+  /// Returns whether given extension [member] is on a class that passses the
+  /// given [validateExtensionClass].
+  bool _checkExtensionMember(Member member, Function validateExtensionClass) {
+    assert(member.isExtensionMember);
+    if (_libraryExtensionsIndex == null) {
+      _libraryExtensionsIndex = {};
+      member.enclosingLibrary.extensions.forEach((extension) =>
+          extension.members.forEach((memberDescriptor) =>
+              _libraryExtensionsIndex![memberDescriptor.member] = extension));
+    }
+
+    var onType = _libraryExtensionsIndex![member.reference]!.onType;
+    return onType is InterfaceType && validateExtensionClass(onType.classNode);
+  }
 }
diff --git a/pkg/_js_interop_checks/lib/src/js_interop.dart b/pkg/_js_interop_checks/lib/src/js_interop.dart
index 7831f2d..60a8dfd 100644
--- a/pkg/_js_interop_checks/lib/src/js_interop.dart
+++ b/pkg/_js_interop_checks/lib/src/js_interop.dart
@@ -89,7 +89,7 @@
 ///
 /// This function works regardless of whether the CFE is evaluating constants,
 /// or whether the constant is a field reference (such as "anonymous" above).
-Class _annotationClass(Expression node) {
+Class? _annotationClass(Expression node) {
   if (node is ConstantExpression) {
     var constant = node.constant;
     if (constant is InstanceConstant) return constant.classNode;
diff --git a/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
index b29d418..4159999 100644
--- a/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
+++ b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
@@ -36,26 +36,26 @@
 
   JsUtilOptimizer(this._coreTypes, ClassHierarchy hierarchy)
       : _jsTarget =
-            _coreTypes.index.getTopLevelMember('dart:_foreign_helper', 'JS'),
+            _coreTypes.index.getTopLevelProcedure('dart:_foreign_helper', 'JS'),
         _callMethodTarget =
-            _coreTypes.index.getTopLevelMember('dart:js_util', 'callMethod'),
+            _coreTypes.index.getTopLevelProcedure('dart:js_util', 'callMethod'),
         _callMethodUncheckedTargets = List<Procedure>.generate(
             5,
-            (i) => _coreTypes.index
-                .getTopLevelMember('dart:js_util', '_callMethodUnchecked$i')),
-        _getPropertyTarget =
-            _coreTypes.index.getTopLevelMember('dart:js_util', 'getProperty'),
-        _setPropertyTarget =
-            _coreTypes.index.getTopLevelMember('dart:js_util', 'setProperty'),
+            (i) => _coreTypes.index.getTopLevelProcedure(
+                'dart:js_util', '_callMethodUnchecked$i')),
+        _getPropertyTarget = _coreTypes.index
+            .getTopLevelProcedure('dart:js_util', 'getProperty'),
+        _setPropertyTarget = _coreTypes.index
+            .getTopLevelProcedure('dart:js_util', 'setProperty'),
         _setPropertyUncheckedTarget = _coreTypes.index
-            .getTopLevelMember('dart:js_util', '_setPropertyUnchecked'),
+            .getTopLevelProcedure('dart:js_util', '_setPropertyUnchecked'),
         _allowInteropTarget =
-            _coreTypes.index.getTopLevelMember('dart:js', 'allowInterop'),
+            _coreTypes.index.getTopLevelProcedure('dart:js', 'allowInterop'),
         _allowedInteropJsUtilTargets = _allowedInteropJsUtilMembers.map(
             (member) =>
-                _coreTypes.index.getTopLevelMember('dart:js_util', member)),
+                _coreTypes.index.getTopLevelProcedure('dart:js_util', member)),
         _listEmptyFactory =
-            _coreTypes.index.getMember('dart:core', 'List', 'empty'),
+            _coreTypes.index.getProcedure('dart:core', 'List', 'empty'),
         _staticTypeContext = StatefulStaticTypeContext.stacked(
             TypeEnvironment(_coreTypes, hierarchy)) {}
 
diff --git a/pkg/_js_interop_checks/pubspec.yaml b/pkg/_js_interop_checks/pubspec.yaml
index 1463e1d..bae1992 100644
--- a/pkg/_js_interop_checks/pubspec.yaml
+++ b/pkg/_js_interop_checks/pubspec.yaml
@@ -3,7 +3,7 @@
 publish_to: none
 
 environment:
-  sdk: '>=2.7.0 <3.0.0'
+  sdk: '>=2.12.0 <3.0.0'
 
 dependencies:
   _fe_analyzer_shared:
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index f63580d..2e13ba2 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -4770,13 +4770,13 @@
           The one-based index of the column containing the first character of
           the range.
         </p>
-      </dd><dt class="field"><b>endLine: int</b></dt><dd>
+      </dd><dt class="field"><b>endLine: int<span style="color:#999999"> (optional)</span></b></dt><dd>
         
         <p>
           The one-based index of the line containing the character immediately
           following the range.
         </p>
-      </dd><dt class="field"><b>endColumn: int</b></dt><dd>
+      </dd><dt class="field"><b>endColumn: int<span style="color:#999999"> (optional)</span></b></dt><dd>
         
         <p>
           The one-based index of the column containing the character immediately
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index db83350..3896905 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -40,6 +40,7 @@
 import 'package:analysis_server/src/server/features.dart';
 import 'package:analysis_server/src/server/sdk_configuration.dart';
 import 'package:analysis_server/src/services/flutter/widget_descriptions.dart';
+import 'package:analysis_server/src/utilities/process.dart';
 import 'package:analysis_server/src/utilities/request_statistics.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
@@ -130,6 +131,7 @@
     CrashReportingAttachmentsBuilder crashReportingAttachmentsBuilder,
     InstrumentationService instrumentationService, {
     http.Client? httpClient,
+    ProcessRunner? processRunner,
     RequestStatisticsHelper? requestStatistics,
     DiagnosticServer? diagnosticServer,
     this.detachableFileSystemManager,
@@ -143,6 +145,7 @@
           baseResourceProvider,
           instrumentationService,
           httpClient,
+          processRunner,
           NotificationManager(channel, baseResourceProvider.pathContext),
           requestStatistics: requestStatistics,
           enableBazelWatcher: enableBazelWatcher,
@@ -429,9 +432,11 @@
     bool isPubspec(String filePath) =>
         file_paths.isPubspecYaml(resourceProvider.pathContext, filePath);
 
-    // When a pubspec is opened, trigger package name caching for completion.
-    if (!pubPackageService.isRunning && files.any(isPubspec)) {
-      pubPackageService.beginPackageNamePreload();
+    // When pubspecs are opened, trigger pre-loading of pub package names and
+    // versions.
+    final pubspecs = files.where(isPubspec).toList();
+    if (pubspecs.isNotEmpty) {
+      pubPackageService.beginCachePreloads(pubspecs);
     }
 
     priorityFiles.clear();
@@ -679,83 +684,8 @@
   @override
   void listenAnalysisDriver(analysis.AnalysisDriver analysisDriver) {
     analysisDriver.results.listen((result) {
-      var path = result.path!;
-      filesToFlush.add(path);
-      if (analysisServer.isAnalyzed(path)) {
-        _notificationManager.recordAnalysisErrors(NotificationManager.serverId,
-            path, server.doAnalysisError_listFromEngine(result));
-      }
-      analysisServer.getDocumentationCacheFor(result)?.cacheFromResult(result);
-      analysisServer.getExtensionCacheFor(result)?.cacheFromResult(result);
-      var unit = result.unit;
-      if (unit != null) {
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.HIGHLIGHTS, path)) {
-          _runDelayed(() {
-            _notificationManager.recordHighlightRegions(
-                NotificationManager.serverId,
-                path,
-                _computeHighlightRegions(unit));
-          });
-        }
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.NAVIGATION, path)) {
-          _runDelayed(() {
-            _notificationManager.recordNavigationParams(
-                NotificationManager.serverId,
-                path,
-                _computeNavigationParams(path, unit));
-          });
-        }
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.OCCURRENCES, path)) {
-          _runDelayed(() {
-            _notificationManager.recordOccurrences(
-                NotificationManager.serverId, path, _computeOccurrences(unit));
-          });
-        }
-//          if (analysisServer._hasAnalysisServiceSubscription(
-//              AnalysisService.OUTLINE, path)) {
-//            _runDelayed(() {
-//              // TODO(brianwilkerson) Change NotificationManager to store params
-//              // so that fileKind and libraryName can be recorded / passed along.
-//              notificationManager.recordOutlines(NotificationManager.serverId,
-//                  path, _computeOutlineParams(path, unit, result.lineInfo));
-//            });
-//          }
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.CLOSING_LABELS, path)) {
-          _runDelayed(() {
-            sendAnalysisNotificationClosingLabels(
-                analysisServer, path, result.lineInfo, unit);
-          });
-        }
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.FOLDING, path)) {
-          _runDelayed(() {
-            sendAnalysisNotificationFolding(
-                analysisServer, path, result.lineInfo, unit);
-          });
-        }
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.OUTLINE, path)) {
-          _runDelayed(() {
-            sendAnalysisNotificationOutline(analysisServer, result);
-          });
-        }
-        if (analysisServer._hasAnalysisServiceSubscription(
-            AnalysisService.OVERRIDES, path)) {
-          _runDelayed(() {
-            sendAnalysisNotificationOverrides(analysisServer, path, unit);
-          });
-        }
-        if (analysisServer._hasFlutterServiceSubscription(
-            FlutterService.OUTLINE, path)) {
-          _runDelayed(() {
-            sendFlutterNotificationOutline(analysisServer, result);
-          });
-        }
-        // TODO(scheglov) Implement notifications for AnalysisService.IMPLEMENTED.
+      if (result is FileResult) {
+        _handleFileResult(result);
       }
     });
     analysisDriver.exceptions.listen(analysisServer.logExceptionResult);
@@ -763,6 +693,18 @@
   }
 
   @override
+  void pubspecChanged(String pubspecPath) {
+    analysisServer.pubPackageService.fetchPackageVersionsViaPubOutdated(
+        pubspecPath,
+        pubspecWasModified: true);
+  }
+
+  @override
+  void pubspecRemoved(String pubspecPath) {
+    analysisServer.pubPackageService.flushPackageCaches(pubspecPath);
+  }
+
+  @override
   void recordAnalysisErrors(String path, List<AnalysisError> errors) {
     filesToFlush.add(path);
     _notificationManager.recordAnalysisErrors(
@@ -788,6 +730,95 @@
     return collector.allOccurrences;
   }
 
+  void _handleFileResult(FileResult result) {
+    var path = result.path;
+    filesToFlush.add(path);
+
+    if (result is AnalysisResultWithErrors) {
+      if (analysisServer.isAnalyzed(path)) {
+        _notificationManager.recordAnalysisErrors(NotificationManager.serverId,
+            path, server.doAnalysisError_listFromEngine(result));
+      }
+    }
+
+    if (result is ResolvedUnitResult) {
+      _handleResolvedUnitResult(result);
+    }
+  }
+
+  void _handleResolvedUnitResult(ResolvedUnitResult result) {
+    var path = result.path;
+
+    analysisServer.getDocumentationCacheFor(result)?.cacheFromResult(result);
+    analysisServer.getExtensionCacheFor(result)?.cacheFromResult(result);
+
+    var unit = result.unit;
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.HIGHLIGHTS, path)) {
+      _runDelayed(() {
+        _notificationManager.recordHighlightRegions(
+            NotificationManager.serverId, path, _computeHighlightRegions(unit));
+      });
+    }
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.NAVIGATION, path)) {
+      _runDelayed(() {
+        _notificationManager.recordNavigationParams(
+            NotificationManager.serverId,
+            path,
+            _computeNavigationParams(path, unit));
+      });
+    }
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.OCCURRENCES, path)) {
+      _runDelayed(() {
+        _notificationManager.recordOccurrences(
+            NotificationManager.serverId, path, _computeOccurrences(unit));
+      });
+    }
+    // if (analysisServer._hasAnalysisServiceSubscription(
+    //     AnalysisService.OUTLINE, path)) {
+    //   _runDelayed(() {
+    //     // TODO(brianwilkerson) Change NotificationManager to store params
+    //     // so that fileKind and libraryName can be recorded / passed along.
+    //     notificationManager.recordOutlines(NotificationManager.serverId, path,
+    //         _computeOutlineParams(path, unit, result.lineInfo));
+    //   });
+    // }
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.CLOSING_LABELS, path)) {
+      _runDelayed(() {
+        sendAnalysisNotificationClosingLabels(
+            analysisServer, path, result.lineInfo, unit);
+      });
+    }
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.FOLDING, path)) {
+      _runDelayed(() {
+        sendAnalysisNotificationFolding(
+            analysisServer, path, result.lineInfo, unit);
+      });
+    }
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.OUTLINE, path)) {
+      _runDelayed(() {
+        sendAnalysisNotificationOutline(analysisServer, result);
+      });
+    }
+    if (analysisServer._hasAnalysisServiceSubscription(
+        AnalysisService.OVERRIDES, path)) {
+      _runDelayed(() {
+        sendAnalysisNotificationOverrides(analysisServer, path, unit);
+      });
+    }
+    if (analysisServer._hasFlutterServiceSubscription(
+        FlutterService.OUTLINE, path)) {
+      _runDelayed(() {
+        sendFlutterNotificationOutline(analysisServer, result);
+      });
+    }
+  }
+
   /// Run [f] in a new [Future].
   ///
   /// This method is used to delay sending notifications. If there is a more
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index 616bf9d..4b28f5c 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -19,12 +19,14 @@
 import 'package:analysis_server/src/services/completion/dart/extension_cache.dart';
 import 'package:analysis_server/src/services/correction/namespace.dart';
 import 'package:analysis_server/src/services/pub/pub_api.dart';
+import 'package:analysis_server/src/services/pub/pub_command.dart';
 import 'package:analysis_server/src/services/pub/pub_package_service.dart';
 import 'package:analysis_server/src/services/search/element_visitors.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal.dart';
 import 'package:analysis_server/src/utilities/file_string_sink.dart';
 import 'package:analysis_server/src/utilities/null_string_sink.dart';
+import 'package:analysis_server/src/utilities/process.dart';
 import 'package:analysis_server/src/utilities/request_statistics.dart';
 import 'package:analysis_server/src/utilities/tee_string_sink.dart';
 import 'package:analyzer/dart/analysis/analysis_context.dart';
@@ -152,14 +154,26 @@
     ResourceProvider baseResourceProvider,
     this.instrumentationService,
     http.Client? httpClient,
+    ProcessRunner? processRunner,
     this.notificationManager, {
     this.requestStatistics,
     bool enableBazelWatcher = false,
   })  : resourceProvider = OverlayResourceProvider(baseResourceProvider),
         pubApi = PubApi(instrumentationService, httpClient,
             Platform.environment['PUB_HOSTED_URL']) {
-    pubPackageService =
-        PubPackageService(instrumentationService, baseResourceProvider, pubApi);
+    // We can only spawn processes (eg. to run pub commands) when backed by
+    // a real file system, otherwise we may try to run commands in folders that
+    // don't really exist. If processRunner was supplied, it's likely a mock
+    // from a test in which case the pub command should still be created.
+    if (baseResourceProvider is PhysicalResourceProvider) {
+      processRunner ??= ProcessRunner();
+    }
+    final pubCommand = processRunner != null
+        ? PubCommand(instrumentationService, processRunner)
+        : null;
+
+    pubPackageService = PubPackageService(
+        instrumentationService, baseResourceProvider, pubApi, pubCommand);
     performance = performanceDuringStartup;
 
     pluginManager = PluginManager(
@@ -380,7 +394,7 @@
     }
 
     var session = getAnalysisDriver(path)?.currentSession;
-    var result = session?.getParsedUnit2(path);
+    var result = session?.getParsedUnit(path);
     return result is ParsedUnitResult ? result : null;
   }
 
diff --git a/pkg/analysis_server/lib/src/cider/rename.dart b/pkg/analysis_server/lib/src/cider/rename.dart
index 6ea1b32..71e8148 100644
--- a/pkg/analysis_server/lib/src/cider/rename.dart
+++ b/pkg/analysis_server/lib/src/cider/rename.dart
@@ -2,6 +2,8 @@
 // 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:analysis_server/src/services/correction/status.dart';
+import 'package:analysis_server/src/services/refactoring/naming_conventions.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/source/line_info.dart';
@@ -17,6 +19,14 @@
   CanRenameResponse(this.lineInfo, this.refactoringElement, this.oldName);
 }
 
+class CheckNameResponse {
+  final LineInfo lineInfo;
+  final RefactoringStatus status;
+  final String oldName;
+
+  CheckNameResponse(this.lineInfo, this.status, this.oldName);
+}
+
 class CiderRenameComputer {
   final FileResolver _fileResolver;
 
@@ -51,6 +61,32 @@
     return null;
   }
 
+  CheckNameResponse? checkNewName(String filePath, int line, int column, String name) {
+    var resolvedUnit = _fileResolver.resolve(path: filePath);
+    var lineInfo = resolvedUnit.lineInfo;
+    var offset = lineInfo.getOffsetOfLine(line) + column;
+
+    var node = NodeLocator(offset).searchWithin(resolvedUnit.unit);
+    var element = getElementOfNode(node);
+
+    if (node == null || element == null) {
+      return null;
+    }
+
+    RefactoringStatus? status;
+    if (element is LocalVariableElement) {
+      status = validateVariableName(name);
+    } else if (element is ParameterElement) {
+      status = validateParameterName(name);
+    } else if (element is FunctionElement) {
+      status = validateFunctionName(name);
+    }
+    if (status == null){
+      return null;
+    }
+    return CheckNameResponse(lineInfo, status, element.displayName);
+  }
+
   bool _canRenameElement(Element element) {
     if (element is PropertyAccessorElement) {
       element = element.variable;
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index fedd848..c4247be 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -17,17 +17,9 @@
 
   DartUnitOutlineComputer(this.resolvedUnit, {this.withBasicFlutter = false});
 
-  CompilationUnit get _unit {
-    var unit = resolvedUnit.unit;
-    if (unit == null) {
-      throw StateError('DartUnitOutlineComputer created with invalid result');
-    }
-    return unit;
-  }
-
   /// Returns the computed outline, not `null`.
   Outline compute() {
-    var unit = _unit;
+    var unit = resolvedUnit.unit;
     var unitContents = <Outline>[];
     for (var unitMember in unit.declarations) {
       if (unitMember is ClassDeclaration) {
@@ -87,17 +79,14 @@
 
   Location _getLocationOffsetLength(int offset, int length) {
     var path = resolvedUnit.path;
-    if (path == null) {
-      throw StateError('DartUnitOutlineComputer called with invalid result');
-    }
     var startLocation = resolvedUnit.lineInfo.getLocation(offset);
     var startLine = startLocation.lineNumber;
     var startColumn = startLocation.columnNumber;
     var endLocation = resolvedUnit.lineInfo.getLocation(offset + length);
     var endLine = endLocation.lineNumber;
     var endColumn = endLocation.columnNumber;
-    return Location(
-        path, offset, length, startLine, startColumn, endLine, endColumn);
+    return Location(path, offset, length, startLine, startColumn,
+        endLine: endLine, endColumn: endColumn);
   }
 
   Outline _newClassOutline(ClassDeclaration node, List<Outline> classContents) {
@@ -328,7 +317,7 @@
   }
 
   Outline _newUnitOutline(List<Outline> unitContents) {
-    var unit = _unit;
+    var unit = resolvedUnit.unit;
     var element = Element(
         ElementKind.COMPILATION_UNIT, '<unit>', Element.makeFlags(),
         location: _getLocationNode(unit));
diff --git a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
index 3a2ec51..a29230f 100644
--- a/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
+++ b/pkg/analysis_server/lib/src/computer/import_elements_computer.dart
@@ -32,12 +32,6 @@
   Future<SourceChange> createEdits(
       List<ImportedElements> importedElementsList) async {
     var unit = libraryResult.unit;
-    var path = libraryResult.path;
-    if (unit == null || path == null) {
-      // We should never reach this point because the libraryResult should be
-      // valid.
-      return SourceChange('');
-    }
     var filteredImportedElements =
         _filterImportedElements(importedElementsList);
     var libraryElement = libraryResult.libraryElement;
@@ -50,7 +44,7 @@
     }
 
     var builder = ChangeBuilder(session: libraryResult.session);
-    await builder.addDartFileEdit(path, (builder) {
+    await builder.addDartFileEdit(libraryResult.path, (builder) {
       for (var importedElements in filteredImportedElements) {
         var matchingImports =
             _findMatchingImports(existingImports, importedElements);
@@ -280,11 +274,6 @@
   /// Partially copied from DartFileEditBuilderImpl.
   _InsertionDescription _getInsertionDescription(String importUri) {
     var unit = libraryResult.unit;
-    if (unit == null) {
-      // We should never reach this point because the libraryResult should be
-      // valid.
-      return _InsertionDescription(0, after: 2);
-    }
     LibraryDirective? libraryDirective;
     var importDirectives = <ImportDirective>[];
     var otherDirectives = <Directive>[];
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 721f37c..28509f0 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -122,6 +122,12 @@
   /// TODO(scheglov) Just pass results in here?
   void listenAnalysisDriver(AnalysisDriver driver);
 
+  /// The `pubspec.yaml` at [path] was added/modified.
+  void pubspecChanged(String path);
+
+  /// The `pubspec.yaml` at [path] was removed.
+  void pubspecRemoved(String path);
+
   /// Record error information for the file with the given [path].
   void recordAnalysisErrors(String path, List<protocol.AnalysisError> errors);
 }
@@ -566,12 +572,21 @@
 
     _instrumentationService.logWatchEvent('<unknown>', path, type.toString());
 
+    final isPubpsec = file_paths.isPubspecYaml(pathContext, path);
     if (file_paths.isAnalysisOptionsYaml(pathContext, path) ||
         file_paths.isDotPackages(pathContext, path) ||
         file_paths.isPackageConfigJson(pathContext, path) ||
-        file_paths.isPubspecYaml(pathContext, path) ||
+        isPubpsec ||
         false) {
       _createAnalysisContexts();
+
+      if (isPubpsec) {
+        if (type == ChangeType.REMOVE) {
+          callbacks.pubspecRemoved(path);
+        } else {
+          callbacks.pubspecChanged(path);
+        }
+      }
       return;
     }
 
@@ -727,6 +742,12 @@
   void listenAnalysisDriver(AnalysisDriver driver) {}
 
   @override
+  void pubspecChanged(String pubspecPath) {}
+
+  @override
+  void pubspecRemoved(String pubspecPath) {}
+
+  @override
   void recordAnalysisErrors(String path, List<protocol.AnalysisError> errors) {}
 }
 
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 2e2bc5d..df5d9f6 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -63,7 +63,7 @@
       server.sendResponse(Response.fileNotAnalyzed(request, file));
       return;
     }
-    var unit = result.unit!;
+    var unit = result.unit;
 
     // Prepare the hovers.
     var hovers = <HoverInformation>[];
@@ -105,7 +105,7 @@
       elements = <ImportedElements>[];
     } else {
       elements =
-          ImportedElementsComputer(result.unit!, params.offset, params.length)
+          ImportedElementsComputer(result.unit, params.offset, params.length)
               .compute();
     }
 
@@ -166,7 +166,7 @@
       var allResults = <AnalysisNavigationParams>[];
       var result = await server.getResolvedUnit(file);
       if (result != null && result.state == ResultState.VALID) {
-        var unit = result.unit!;
+        var unit = result.unit;
         var collector = NavigationCollectorImpl();
         computeDartNavigation(
             server.resourceProvider, collector, unit, offset, length);
@@ -237,7 +237,7 @@
     }
 
     // Ensure the offset provided is a valid location in the file.
-    final unit = result.unit!;
+    final unit = result.unit;
     final computer = DartUnitSignatureComputer(
         server.getDartdocDirectiveInfoFor(result), unit, params.offset);
     if (!computer.offsetIsValid) {
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 78db63a..9a10237 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -330,7 +330,7 @@
       }
       server.requestStatistics?.addItemTimeNow(request, 'resolvedUnit');
       if (resolvedUnit.state == ResultState.VALID) {
-        if (offset < 0 || offset > resolvedUnit.content!.length) {
+        if (offset < 0 || offset > resolvedUnit.content.length) {
           server.sendResponse(Response.invalidParameter(
               request,
               'params.offset',
@@ -339,7 +339,7 @@
           return;
         }
 
-        recordRequest(performance, file, resolvedUnit.content!, offset);
+        recordRequest(performance, file, resolvedUnit.content, offset);
       }
       var declarationsTracker = server.declarationsTracker;
       if (declarationsTracker == null) {
diff --git a/pkg/analysis_server/lib/src/domain_kythe.dart b/pkg/analysis_server/lib/src/domain_kythe.dart
index b03acbb..990588e 100644
--- a/pkg/analysis_server/lib/src/domain_kythe.dart
+++ b/pkg/analysis_server/lib/src/domain_kythe.dart
@@ -47,8 +47,8 @@
         var entries = <KytheEntry>[];
         // TODO(brianwilkerson) Figure out how to get the list of files.
         var files = <String>[];
-        result.unit!.accept(KytheDartVisitor(server.resourceProvider, entries,
-            file, InheritanceManager3(), result.content!));
+        result.unit.accept(KytheDartVisitor(server.resourceProvider, entries,
+            file, InheritanceManager3(), result.content));
         allResults.add(KytheGetKytheEntriesResult(entries, files));
       }
       //
diff --git a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
index 223e056..54ffabf 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -24,7 +24,7 @@
   var context = tracker.getContext(analysisContext);
   if (context == null) return;
 
-  var librariesObject = context.getLibraries(resolvedUnit.path!);
+  var librariesObject = context.getLibraries(resolvedUnit.path);
 
   var importedUriSet = resolvedUnit.libraryElement.importedLibraries
       .map((importedLibrary) => importedLibrary.source.uri)
@@ -261,8 +261,8 @@
       0, // length
       declaration.locationStartLine,
       declaration.locationStartColumn,
-      declaration.locationStartLine, // endLine
-      declaration.locationStartColumn, // endColumn
+      endLine: declaration.locationStartLine,
+      endColumn: declaration.locationStartColumn,
     ),
     parameters: declaration.parameters,
     returnType: declaration.returnType,
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart
index 97ab5bf..7162de9 100644
--- a/pkg/analysis_server/lib/src/domains/execution/completion.dart
+++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -53,7 +53,7 @@
 
     // Compute the patched context file content.
     var targetCode = SourceEdit.applySequence(
-      contextResult.content!,
+      contextResult.content,
       changeBuilder.sourceChange.edits[0].edits,
     );
 
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index 0e5ba49..b73448c 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -32,7 +32,6 @@
 import 'package:analysis_server/src/services/correction/status.dart';
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart';
-import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart' as engine;
@@ -402,7 +401,7 @@
       return;
     }
     var libraryUnit = result.libraryElement.definingCompilationUnit;
-    if (libraryUnit != result.unit!.declaredElement) {
+    if (libraryUnit != result.unit.declaredElement) {
       // The file in the request is a part of a library. We need to pass the
       // defining compilation unit to the computer, not the part.
       result = await server.getResolvedUnit(libraryUnit.source.fullName);
@@ -484,8 +483,8 @@
       return;
     }
     var fileStamp = -1;
-    var code = result.content!;
-    var unit = result.unit!;
+    var code = result.content;
+    var unit = result.unit;
     var errors = result.errors;
     // check if there are scan/parse errors in the file
     var numScanParseErrors = _getNumberOfScanParseErrors(errors);
@@ -575,8 +574,8 @@
       if (fixes.isNotEmpty) {
         fixes.sort(Fix.SORT_BY_RELEVANCE);
         var lineInfo = LineInfo.fromContent(content);
-        ResolvedUnitResult result = engine.ResolvedUnitResultImpl(session, file,
-            Uri.file(file), true, content, lineInfo, false, null, errors);
+        var result = engine.ErrorsResultImpl(
+            session, file, Uri.file(file), lineInfo, false, errors);
         var serverError = newAnalysisError_fromEngine(result, error);
         var errorFixes = AnalysisErrorFixes(serverError);
         errorFixesList.add(errorFixes);
@@ -611,7 +610,7 @@
             var provider = TopLevelDeclarationsProvider(tracker);
             return provider.get(
               result.session.analysisContext,
-              result.path!,
+              result.path,
               name,
             );
           }, extensionCache: server.getExtensionCacheFor(result));
@@ -628,7 +627,7 @@
 error.errorCode: ${error.errorCode}
 ''';
             throw CaughtExceptionWithFiles(exception, stackTrace, {
-              file: result.content!,
+              file: result.content,
               'parameters': parametersFile,
             });
           }
@@ -674,8 +673,8 @@
       if (fixes.isNotEmpty) {
         fixes.sort(Fix.SORT_BY_RELEVANCE);
         var lineInfo = LineInfo.fromContent(content);
-        ResolvedUnitResult result = engine.ResolvedUnitResultImpl(session, file,
-            Uri.file(file), true, content, lineInfo, false, null, errors);
+        var result = engine.ErrorsResultImpl(
+            session, file, Uri.file(file), lineInfo, false, errors);
         var serverError = newAnalysisError_fromEngine(result, error);
         var errorFixes = AnalysisErrorFixes(serverError);
         errorFixesList.add(errorFixes);
@@ -723,8 +722,8 @@
       if (fixes.isNotEmpty) {
         fixes.sort(Fix.SORT_BY_RELEVANCE);
         var lineInfo = LineInfo.fromContent(content);
-        ResolvedUnitResult result = engine.ResolvedUnitResultImpl(session, file,
-            Uri.file(file), true, content, lineInfo, false, null, errors);
+        var result = engine.ErrorsResultImpl(
+            session, file, Uri.file(file), lineInfo, false, errors);
         var serverError = newAnalysisError_fromEngine(result, error);
         var errorFixes = AnalysisErrorFixes(serverError);
         errorFixesList.add(errorFixes);
@@ -767,7 +766,7 @@
 length: $length
       ''';
         throw CaughtExceptionWithFiles(exception, stackTrace, {
-          file: result.content!,
+          file: result.content,
           'parameters': parametersFile,
         });
       }
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
index 36e5272..74085faa 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_notifications.dart
@@ -15,7 +15,7 @@
     var outline = computer.compute();
     // send notification
     var params = protocol.FlutterOutlineParams(
-      resolvedUnit.path!,
+      resolvedUnit.path,
       outline,
     );
     server.sendNotification(params.toNotification());
diff --git a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
index d216445..8c3dd26 100644
--- a/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
+++ b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
@@ -31,7 +31,7 @@
 
     // Create outlines for widgets.
     var visitor = _FlutterOutlineBuilder(this);
-    resolvedUnit.unit!.accept(visitor);
+    resolvedUnit.unit.accept(visitor);
 
     // Associate Flutter outlines with Dart outlines.
     for (var outline in visitor.outlines) {
@@ -66,7 +66,7 @@
 
     var name = parameter.displayName;
 
-    var label = resolvedUnit.content!.substring(argument.offset, argument.end);
+    var label = resolvedUnit.content.substring(argument.offset, argument.end);
     if (label.contains('\n')) {
       label = '…';
     }
diff --git a/pkg/analysis_server/lib/src/lsp/client_configuration.dart b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
index 332330f..9093676 100644
--- a/pkg/analysis_server/lib/src/lsp/client_configuration.dart
+++ b/pkg/analysis_server/lib/src/lsp/client_configuration.dart
@@ -2,10 +2,102 @@
 // 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:collection/collection.dart';
+import 'package:path/path.dart' as path;
+
+/// Provides access to both global and resource-specific client configuration.
+///
+/// Resource-specific config is currently only supported at the WorkspaceFolder
+/// level so when looking up config for a resource, the nearest WorkspaceFolders
+/// config will be used.
+class LspClientConfiguration {
+  /// Global settings for the workspace.
+  ///
+  /// Used as a fallback for resource settings if no specific config is found
+  /// for the resource.
+  LspGlobalClientConfiguration _globalSettings =
+      LspGlobalClientConfiguration({});
+
+  /// Settings for each resource.
+  ///
+  /// Keys are string paths without trailing path separators (eg. 'C:\foo').
+  final Map<String, LspResourceClientConfiguration> _resourceSettings =
+      <String, LspResourceClientConfiguration>{};
+
+  /// Pattern for stripping trailing slashes that may be been provided by the
+  /// client (in WorkspaceFolder URIs) for consistent comparisons.
+  final _trailingSlashPattern = RegExp(r'[\/]+$');
+
+  /// Returns the global configuration for the whole workspace.
+  LspGlobalClientConfiguration get global => _globalSettings;
+
+  /// Returns whether or not the provided new configuration changes any values
+  /// that would require analysis roots to be updated.
+  bool affectsAnalysisRoots(LspGlobalClientConfiguration otherConfig) {
+    return _globalSettings.analysisExcludedFolders !=
+        otherConfig.analysisExcludedFolders;
+  }
+
+  /// Returns config for a given resource.
+  ///
+  /// Because we only support config at the WorkspaceFolder level, this is done
+  /// by finding the nearest WorkspaceFolder to [resourcePath] and using config
+  /// for that.
+  ///
+  /// If no specific config is available, returns [global].
+  LspResourceClientConfiguration forResource(String resourcePath) {
+    final workspaceFolder = _getWorkspaceFolderPath(resourcePath);
+
+    if (workspaceFolder == null) {
+      return _globalSettings;
+    }
+
+    return _resourceSettings[_normaliseFolderPath(workspaceFolder)] ??
+        _globalSettings;
+  }
+
+  /// Replaces all previously known configuration with updated values from the
+  /// client.
+  void replace(
+    Map<String, Object?> globalConfig,
+    Map<String, Map<String, Object?>> workspaceFolderConfig,
+  ) {
+    _globalSettings = LspGlobalClientConfiguration(globalConfig);
+
+    _resourceSettings
+      ..clear()
+      ..addAll(workspaceFolderConfig.map(
+        (key, value) => MapEntry(
+          _normaliseFolderPath(key),
+          LspResourceClientConfiguration(value, _globalSettings),
+        ),
+      ));
+  }
+
+  /// Gets the path for the WorkspaceFolder closest to [resourcePath].
+  String? _getWorkspaceFolderPath(String resourcePath) {
+    final candidates = _resourceSettings.keys
+        .where((wfPath) =>
+            wfPath == _normaliseFolderPath(resourcePath) ||
+            path.isWithin(wfPath, resourcePath))
+        .toList();
+    candidates.sort((a, b) => -a.length.compareTo(b.length));
+    return candidates.firstOrNull;
+  }
+
+  /// Normalises a folder path to never have a trailing path separator.
+  String _normaliseFolderPath(String path) =>
+      path.replaceAll(_trailingSlashPattern, '');
+}
+
 /// Wraps the client (editor) configuration to provide stronger typing and
 /// handling of default values where a setting has not been supplied.
-class LspClientConfiguration {
-  final Map<String, dynamic> _settings = <String, dynamic>{};
+///
+/// Settings in this class are only allowed to be configured at the workspace
+/// level (they will be ignored at the resource level).
+class LspGlobalClientConfiguration extends LspResourceClientConfiguration {
+  LspGlobalClientConfiguration(Map<String, Object?> settings)
+      : super(settings, null);
 
   List<String> get analysisExcludedFolders {
     // This setting is documented as a string array, but because editors are
@@ -20,30 +112,48 @@
     }
   }
 
-  bool get completeFunctionCalls => _settings['completeFunctionCalls'] ?? false;
-  bool get enableSdkFormatter => _settings['enableSdkFormatter'] ?? true;
-  int? get lineLength => _settings['lineLength'];
+  /// Whether methods/functions in completion should include parens and argument
+  /// placeholders when used in an invocation context.
+  bool get completeFunctionCalls =>
+      _settings['completeFunctionCalls'] as bool? ?? false;
 
   /// A preview flag for enabling commit characters for completions.
   ///
   /// This is a temporary setting to allow this feature to be tested without
   /// defaulting to on for everybody.
   bool get previewCommitCharacters =>
-      _settings['previewCommitCharacters'] ?? false;
+      _settings['previewCommitCharacters'] as bool? ?? false;
 
   /// Whether diagnostics should be generated for TODO comments.
-  bool get showTodos => _settings['showTodos'] ?? false;
+  bool get showTodos => _settings['showTodos'] as bool? ?? false;
+}
 
-  /// Returns whether or not the provided new configuration changes any values
-  /// that would require analysis roots to be updated.
-  bool affectsAnalysisRoots(Map<String, dynamic> newConfig) {
-    return _settings['analysisExcludedFolders'] !=
-        newConfig['analysisExcludedFolders'];
-  }
+/// Wraps the client (editor) configuration for a specific resource.
+///
+/// Settings in this class are only allowed to be configured either for a
+/// resource or for the whole workspace.
+///
+/// Right now, we treat "resource" to always mean a WorkspaceFolder since no
+/// known editors allow per-file configuration and it allows us to keep the
+/// settings cached, invalidated only when WorkspaceFolders change.
+class LspResourceClientConfiguration {
+  final Map<String, Object?> _settings;
+  final LspResourceClientConfiguration? _fallback;
 
-  void replace(Map<String, dynamic> newConfig) {
-    _settings
-      ..clear()
-      ..addAll(newConfig);
-  }
+  LspResourceClientConfiguration(this._settings, this._fallback);
+
+  /// Whether to enable the SDK formatter.
+  ///
+  /// If this setting is `false`, the formatter will be unregistered with the
+  /// client.
+  bool get enableSdkFormatter =>
+      _settings['enableSdkFormatter'] as bool? ??
+      _fallback?.enableSdkFormatter ??
+      true;
+
+  /// The line length used when formatting documents.
+  ///
+  /// If null, the formatters default will be used.
+  int? get lineLength =>
+      _settings['lineLength'] as int? ?? _fallback?.lineLength;
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all.dart
index 784e2fe..4d4f523 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/fix_all.dart
@@ -12,7 +12,6 @@
 import 'package:analysis_server/src/lsp/progress.dart';
 import 'package:analysis_server/src/services/correction/bulk_fix_processor.dart';
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
-import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
 
 class FixAllCommandHandler extends SimpleEditCommandHandler {
   FixAllCommandHandler(LspAnalysisServer server) : super(server);
@@ -48,14 +47,13 @@
       final processor =
           BulkFixProcessor(server.instrumentationService, workspace);
 
-      final collection = AnalysisContextCollectionImpl(
-        includedPaths: [path],
-        resourceProvider: server.resourceProvider,
-        sdkPath: server.sdkManager.defaultSdkDirectory,
-      );
-      final changeBuilder = await processor.fixErrors(collection.contexts);
-      final change = changeBuilder.sourceChange;
+      final context = server.contextManager.getContextFor(path);
+      if (context == null) {
+        return success(null);
+      }
 
+      final changeBuilder = await processor.fixErrorsForFile(context, path);
+      final change = changeBuilder.sourceChange;
       if (change.edits.isEmpty) {
         return success(null);
       }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
index 6b3ac68..2a81ac0 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/organize_imports.dart
@@ -41,8 +41,8 @@
     }
 
     return result.mapResult((result) {
-      final code = result.content!;
-      final unit = result.unit!;
+      final code = result.content;
+      final unit = result.unit;
 
       if (hasScanParseErrors(result.errors)) {
         // It's not uncommon for editors to run this command automatically on-save
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
index ed17c2a..20c4d27 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/perform_refactor.dart
@@ -14,6 +14,8 @@
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 
 final _manager = _RefactorManager();
 
@@ -173,6 +175,32 @@
             InlineMethodRefactoring(server.searchEngine, result, offset);
         return success(refactor);
 
+      case RefactoringKind.CONVERT_GETTER_TO_METHOD:
+        final node = NodeLocator(offset).searchWithin(result.unit);
+        final element = server.getElementOfNode(node);
+        if (element != null) {
+          if (element is PropertyAccessorElement) {
+            final refactor = ConvertGetterToMethodRefactoring(
+                server.searchEngine, result.session, element);
+            return success(refactor);
+          }
+        }
+        return error(ServerErrorCodes.InvalidCommandArguments,
+            'Location supplied to $commandName $kind is not longer valid');
+
+      case RefactoringKind.CONVERT_METHOD_TO_GETTER:
+        final node = NodeLocator(offset).searchWithin(result.unit);
+        final element = server.getElementOfNode(node);
+        if (element != null) {
+          if (element is ExecutableElement) {
+            final refactor = ConvertMethodToGetterRefactoring(
+                server.searchEngine, result.session, element);
+            return success(refactor);
+          }
+        }
+        return error(ServerErrorCodes.InvalidCommandArguments,
+            'Location supplied to $commandName $kind is not longer valid');
+
       default:
         return error(ServerErrorCodes.InvalidCommandArguments,
             'Unknown RefactoringKind $kind was supplied to $commandName');
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
index 9a530d3..e270255 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_change_workspace_folders.dart
@@ -23,8 +23,8 @@
       DidChangeWorkspaceFoldersParams.jsonHandler;
 
   @override
-  ErrorOr<void> handle(
-      DidChangeWorkspaceFoldersParams params, CancellationToken token) {
+  Future<ErrorOr<void>> handle(
+      DidChangeWorkspaceFoldersParams params, CancellationToken token) async {
     // Don't do anything if our analysis roots are not based on open workspaces.
     if (!updateAnalysisRoots) {
       return success(null);
@@ -37,7 +37,7 @@
         .map((wf) => Uri.parse(wf.uri).toFilePath())
         .toList();
 
-    server.updateWorkspaceFolders(added, removed);
+    await server.updateWorkspaceFolders(added, removed);
 
     return success(null);
   }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index 5063d04..9f7152c 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -4,12 +4,11 @@
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
-import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
-import 'package:analysis_server/plugin/edit/fix/fix_core.dart';
 import 'package:analysis_server/src/lsp/constants.dart';
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 import 'package:analysis_server/src/lsp/mapping.dart';
+import 'package:analysis_server/src/plugin/plugin_manager.dart';
 import 'package:analysis_server/src/protocol_server.dart' hide Position;
 import 'package:analysis_server/src/services/correction/assist.dart';
 import 'package:analysis_server/src/services/correction/assist_internal.dart';
@@ -21,12 +20,37 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart'
     show InconsistentAnalysisException;
-import 'package:analyzer/error/error.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/util/file_paths.dart' as file_paths;
+import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:collection/collection.dart' show groupBy;
 
 class CodeActionHandler extends MessageHandler<CodeActionParams,
     List<Either2<Command, CodeAction>>> {
+  // Because server+plugin results are different types and we lose
+  // priorites when converting them to CodeActions, store the priorities
+  // against each action in an expando. This avoids wrapping CodeActions in
+  // another wrapper class (since we can't modify the LSP-spec-generated
+  // CodeAction class).
+  final codeActionPriorities = Expando<int>();
+
+  /// A comparator that can be used to sort [CodeActions]s using priorties
+  /// in [codeActionPriorities]. The highest number priority will be sorted
+  /// before lower number priorityies. Items with the same relevance are sorted
+  /// alphabetically by their title.
+  late final Comparator<CodeAction> _codeActionComparator =
+      (CodeAction a, CodeAction b) {
+    // We should never be sorting actions without priorities.
+    final aPriority = codeActionPriorities[a] ?? 0;
+    final bPriority = codeActionPriorities[b] ?? 0;
+    if (aPriority != bPriority) {
+      return bPriority - aPriority;
+    }
+    return a.title.compareTo(b.title);
+  };
+
   CodeActionHandler(LspAnalysisServer server) : super(server);
 
   @override
@@ -145,12 +169,12 @@
   /// version of each document being modified so it's important to call this
   /// immediately after computing edits to ensure the document is not modified
   /// before the version number is read.
-  CodeAction _createAssistAction(Assist assist) {
+  CodeAction _createAssistAction(SourceChange change) {
     return CodeAction(
-      title: assist.change.message,
-      kind: toCodeActionKind(assist.change.id, CodeActionKind.Refactor),
+      title: change.message,
+      kind: toCodeActionKind(change.id, CodeActionKind.Refactor),
       diagnostics: const [],
-      edit: createWorkspaceEdit(server, assist.change),
+      edit: createWorkspaceEdit(server, change),
     );
   }
 
@@ -158,12 +182,12 @@
   /// version of each document being modified so it's important to call this
   /// immediately after computing edits to ensure the document is not modified
   /// before the version number is read.
-  CodeAction _createFixAction(Fix fix, Diagnostic diagnostic) {
+  CodeAction _createFixAction(SourceChange change, Diagnostic diagnostic) {
     return CodeAction(
-      title: fix.change.message,
-      kind: toCodeActionKind(fix.change.id, CodeActionKind.QuickFix),
+      title: change.message,
+      kind: toCodeActionKind(change.id, CodeActionKind.QuickFix),
       diagnostics: [diagnostic],
-      edit: createWorkspaceEdit(server, fix.change),
+      edit: createWorkspaceEdit(server, change),
     );
   }
 
@@ -220,6 +244,7 @@
   Future<List<Either2<Command, CodeAction>>> _getAssistActions(
     bool Function(CodeActionKind?) shouldIncludeKind,
     bool supportsLiteralCodeActions,
+    String path,
     Range range,
     int offset,
     int length,
@@ -234,13 +259,28 @@
         length,
       );
       final processor = AssistProcessor(context);
-      final assists = await processor.compute();
-      assists.sort(Assist.SORT_BY_RELEVANCE);
+      final serverFuture = processor.compute();
+      final pluginFuture = _getPluginAssistChanges(path, offset, length);
 
-      final assistActions =
-          _dedupeActions(assists.map(_createAssistAction), range.start);
+      final assists = await serverFuture;
+      final pluginChanges = await pluginFuture;
 
-      return assistActions
+      final codeActions = <CodeAction>[];
+      codeActions.addAll(assists.map((assist) {
+        final action = _createAssistAction(assist.change);
+        codeActionPriorities[action] = assist.kind.priority;
+        return action;
+      }));
+      codeActions.addAll(pluginChanges.map((change) {
+        final action = _createAssistAction(change.change);
+        codeActionPriorities[action] = change.priority;
+        return action;
+      }));
+
+      final dedupedCodeActions = _dedupeActions(codeActions, range.start);
+      dedupedCodeActions.sort(_codeActionComparator);
+
+      return dedupedCodeActions
           .where((action) => shouldIncludeKind(action.kind))
           .map((action) => Either2<Command, CodeAction>.t2(action))
           .toList();
@@ -266,11 +306,11 @@
     final results = await Future.wait([
       _getSourceActions(shouldIncludeKind, supportsLiterals,
           supportsWorkspaceApplyEdit, path),
-      _getAssistActions(
-          shouldIncludeKind, supportsLiterals, range, offset, length, unit),
+      _getAssistActions(shouldIncludeKind, supportsLiterals, path, range,
+          offset, length, unit),
       _getRefactorActions(
           shouldIncludeKind, supportsLiterals, path, offset, length, unit),
-      _getFixActions(shouldIncludeKind, supportsLiterals,
+      _getFixActions(shouldIncludeKind, supportsLiterals, path, offset,
           supportedDiagnosticTags, range, unit),
     ]);
     final flatResults = results.expand((x) => x).toList();
@@ -281,22 +321,23 @@
   Future<List<Either2<Command, CodeAction>>> _getFixActions(
     bool Function(CodeActionKind?) shouldIncludeKind,
     bool supportsLiteralCodeActions,
+    String path,
+    int offset,
     Set<DiagnosticTag> supportedDiagnosticTags,
     Range range,
     ResolvedUnitResult unit,
   ) async {
+    final clientSupportsCodeDescription =
+        server.clientCapabilities?.diagnosticCodeDescription ?? false;
+    // TODO(dantup): We may be missing fixes for pubspec, analysis_options,
+    //   android manifests (see _computeServerErrorFixes in EditDomainHandler).
     final lineInfo = unit.lineInfo;
     final codeActions = <CodeAction>[];
     final fixContributor = DartFixContributor();
 
-    try {
-      final errorCodeCounts = <ErrorCode, int>{};
-      // Count the errors by code so we know whether to include a fix-all.
-      for (final error in unit.errors) {
-        errorCodeCounts[error.errorCode] =
-            (errorCodeCounts[error.errorCode] ?? 0) + 1;
-      }
+    final pluginFuture = _getPluginFixActions(unit, offset);
 
+    try {
       for (final error in unit.errors) {
         // Server lineNumber is one-based so subtract one.
         var errorLine = lineInfo.getLocation(error.offset).lineNumber - 1;
@@ -309,28 +350,50 @@
           var tracker = server.declarationsTracker!;
           return TopLevelDeclarationsProvider(tracker).get(
             unit.session.analysisContext,
-            unit.path!,
+            unit.path,
             name,
           );
         }, extensionCache: server.getExtensionCacheFor(unit));
         final fixes = await fixContributor.computeFixes(context);
         if (fixes.isNotEmpty) {
-          fixes.sort(Fix.SORT_BY_RELEVANCE);
-
           final diagnostic = toDiagnostic(
             unit,
             error,
             supportedTags: supportedDiagnosticTags,
-            clientSupportsCodeDescription:
-                server.clientCapabilities?.diagnosticCodeDescription ?? false,
+            clientSupportsCodeDescription: clientSupportsCodeDescription,
           );
           codeActions.addAll(
-            fixes.map((fix) => _createFixAction(fix, diagnostic)),
+            fixes.map((fix) {
+              final action = _createFixAction(fix.change, diagnostic);
+              codeActionPriorities[action] = fix.kind.priority;
+              return action;
+            }),
           );
         }
       }
 
+      Diagnostic pluginErrorToDiagnostic(AnalysisError error) {
+        return pluginToDiagnostic(
+          (_) => lineInfo,
+          error,
+          supportedTags: supportedDiagnosticTags,
+          clientSupportsCodeDescription: clientSupportsCodeDescription,
+        );
+      }
+
+      final pluginFixes = await pluginFuture;
+      final pluginFixActions = pluginFixes.expand(
+        (fix) => fix.fixes.map((fixChange) {
+          final action = _createFixAction(
+              fixChange.change, pluginErrorToDiagnostic(fix.error));
+          codeActionPriorities[action] = fixChange.priority;
+          return action;
+        }),
+      );
+      codeActions.addAll(pluginFixActions);
+
       final dedupedActions = _dedupeActions(codeActions, range.start);
+      dedupedActions.sort(_codeActionComparator);
 
       return dedupedActions
           .where((action) => shouldIncludeKind(action.kind))
@@ -344,6 +407,61 @@
     }
   }
 
+  Future<Iterable<plugin.PrioritizedSourceChange>> _getPluginAssistChanges(
+      String path, int offset, int length) async {
+    final requestParams = plugin.EditGetAssistsParams(path, offset, length);
+    final driver = server.getAnalysisDriver(path);
+
+    Map<PluginInfo, Future<plugin.Response>> pluginFutures;
+    if (driver == null) {
+      pluginFutures = <PluginInfo, Future<plugin.Response>>{};
+    } else {
+      pluginFutures = server.pluginManager.broadcastRequest(
+        requestParams,
+        contextRoot: driver.analysisContext!.contextRoot,
+      );
+    }
+
+    final pluginChanges = <plugin.PrioritizedSourceChange>[];
+    final responses =
+        await waitForResponses(pluginFutures, requestParameters: requestParams);
+
+    for (final response in responses) {
+      final result = plugin.EditGetAssistsResult.fromResponse(response);
+      pluginChanges.addAll(result.assists);
+    }
+
+    return pluginChanges;
+  }
+
+  Future<Iterable<plugin.AnalysisErrorFixes>> _getPluginFixActions(
+      ResolvedUnitResult unit, int offset) async {
+    final file = unit.path;
+    final requestParams = plugin.EditGetFixesParams(file, offset);
+    final driver = server.getAnalysisDriver(file);
+
+    Map<PluginInfo, Future<plugin.Response>> pluginFutures;
+    if (driver == null) {
+      pluginFutures = <PluginInfo, Future<plugin.Response>>{};
+    } else {
+      pluginFutures = server.pluginManager.broadcastRequest(
+        requestParams,
+        contextRoot: driver.analysisContext!.contextRoot,
+      );
+    }
+
+    final pluginFixes = <plugin.AnalysisErrorFixes>[];
+    final responses =
+        await waitForResponses(pluginFutures, requestParameters: requestParams);
+
+    for (final response in responses) {
+      final result = plugin.EditGetFixesResult.fromResponse(response);
+      pluginFixes.addAll(result.fixes);
+    }
+
+    return pluginFixes;
+  }
+
   Future<List<Either2<Command, CodeAction>>> _getRefactorActions(
     bool Function(CodeActionKind) shouldIncludeKind,
     bool supportsLiteralCodeActions,
@@ -428,6 +546,28 @@
         }
       }
 
+      // Converts/Rewrites
+      if (shouldIncludeKind(CodeActionKind.RefactorRewrite)) {
+        final node = NodeLocator(offset).searchWithin(unit.unit);
+        final element = server.getElementOfNode(node);
+        // Getter to Method
+        if (element is PropertyAccessorElement) {
+          refactorActions.add(createRefactor(
+              CodeActionKind.RefactorRewrite,
+              'Convert Getter to Method',
+              RefactoringKind.CONVERT_GETTER_TO_METHOD));
+        }
+
+        // Method to Getter
+        if (element is ExecutableElement &&
+            element is! PropertyAccessorElement) {
+          refactorActions.add(createRefactor(
+              CodeActionKind.RefactorRewrite,
+              'Convert Method to Getter',
+              RefactoringKind.CONVERT_METHOD_TO_GETTER));
+        }
+      }
+
       return refactorActions;
     } on InconsistentAnalysisException {
       // If an InconsistentAnalysisException occurs, it's likely the user modified
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index ccf8bb2..2ab3d5d 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -205,7 +205,7 @@
   ) async {
     final performance = CompletionPerformance();
     performance.path = unit.path;
-    performance.setContentsAndOffset(unit.content!, offset);
+    performance.setContentsAndOffset(unit.content, offset);
     server.performanceStats.completion.add(performance);
 
     return await performance.runRequestOperation((perf) async {
@@ -261,7 +261,7 @@
         /// insert dupes.
         final completeFunctionCalls = _hasExistingArgList(target.entity)
             ? false
-            : server.clientConfiguration.completeFunctionCalls;
+            : server.clientConfiguration.global.completeFunctionCalls;
 
         final results = serverSuggestions.map(
           (item) {
@@ -292,7 +292,7 @@
               // depending on how the spec is updated.
               // https://github.com/microsoft/vscode-languageserver-node/issues/673
               includeCommitCharacters:
-                  server.clientConfiguration.previewCommitCharacters,
+                  server.clientConfiguration.global.previewCommitCharacters,
               completeFunctionCalls: completeFunctionCalls,
             );
           },
@@ -374,7 +374,7 @@
                   importingUris.first == '${library.uri}';
             }).map((item) => declarationToCompletionItem(
                       capabilities,
-                      unit.path!,
+                      unit.path,
                       offset,
                       includedSet,
                       library,
@@ -390,8 +390,8 @@
                       // this should be removed (or made conditional based on a capability)
                       // depending on how the spec is updated.
                       // https://github.com/microsoft/vscode-languageserver-node/issues/673
-                      includeCommitCharacters:
-                          server.clientConfiguration.previewCommitCharacters,
+                      includeCommitCharacters: server
+                          .clientConfiguration.global.previewCommitCharacters,
                       completeFunctionCalls: completeFunctionCalls,
                     ));
             results.addAll(setResults);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
index 1463107..30935d6 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
@@ -111,7 +111,7 @@
 
         analyzer.LibraryElement requestedLibraryElement;
         {
-          final result = await session.getLibraryByUri2(library.uriStr);
+          final result = await session.getLibraryByUri(library.uriStr);
           if (result is LibraryElementResult) {
             requestedLibraryElement = result.element;
           } else {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
index ff213a4..ae96228 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_document_highlights.dart
@@ -34,7 +34,7 @@
 
     return offset.mapResult((requestedOffset) {
       final collector = OccurrencesCollectorImpl();
-      addDartOccurrences(collector, unit.result.unit!);
+      addDartOccurrences(collector, unit.result.unit);
 
       // Find an occurrence that has an instance that spans the position.
       for (final occurrence in collector.allOccurrences) {
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
index 1ed3a71..3148284 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_on_type.dart
@@ -32,8 +32,8 @@
       return success(null);
     }
 
-    return generateEditsForFormatting(
-        result, server.clientConfiguration.lineLength);
+    final lineLength = server.clientConfiguration.forResource(path).lineLength;
+    return generateEditsForFormatting(result, lineLength);
   }
 
   @override
@@ -43,12 +43,15 @@
       return success(null);
     }
 
-    if (!server.clientConfiguration.enableSdkFormatter) {
-      return error(ServerErrorCodes.FeatureDisabled,
-          'Formatter was disabled by client settings');
-    }
-
     final path = pathOfDoc(params.textDocument);
-    return path.mapResult((path) => formatFile(path));
+    return path.mapResult((path) {
+      if (!server.clientConfiguration.forResource(path).enableSdkFormatter) {
+        // Because we now support formatting for just some WorkspaceFolders
+        // we should silently do nothing for those that are disabled.
+        return success(null);
+      }
+
+      return formatFile(path);
+    });
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
index d6f7247..f92433a 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_format_range.dart
@@ -32,9 +32,8 @@
       return success(null);
     }
 
-    return generateEditsForFormatting(
-        result, server.clientConfiguration.lineLength,
-        range: range);
+    final lineLength = server.clientConfiguration.forResource(path).lineLength;
+    return generateEditsForFormatting(result, lineLength, range: range);
   }
 
   @override
@@ -44,12 +43,14 @@
       return success(null);
     }
 
-    if (!server.clientConfiguration.enableSdkFormatter) {
-      return error(ServerErrorCodes.FeatureDisabled,
-          'Formatter was disabled by client settings');
-    }
-
     final path = pathOfDoc(params.textDocument);
-    return path.mapResult((path) => formatRange(path, params.range));
+    return path.mapResult((path) {
+      if (!server.clientConfiguration.forResource(path).enableSdkFormatter) {
+        // Because we now support formatting for just some WorkspaceFolders
+        // we should silently do nothing for those that are disabled.
+        return success(null);
+      }
+      return formatRange(path, params.range);
+    });
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
index 75b7a41..23a7cad 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_formatting.dart
@@ -32,8 +32,8 @@
       return success(null);
     }
 
-    return generateEditsForFormatting(
-        result, server.clientConfiguration.lineLength);
+    final lineLength = server.clientConfiguration.forResource(path).lineLength;
+    return generateEditsForFormatting(result, lineLength);
   }
 
   @override
@@ -43,12 +43,14 @@
       return success(null);
     }
 
-    if (!server.clientConfiguration.enableSdkFormatter) {
-      return error(ServerErrorCodes.FeatureDisabled,
-          'Formatter was disabled by client settings');
-    }
-
     final path = pathOfDoc(params.textDocument);
-    return path.mapResult((path) => formatFile(path));
+    return path.mapResult((path) {
+      if (!server.clientConfiguration.forResource(path).enableSdkFormatter) {
+        // Because we now support formatting for just some WorkspaceFolders
+        // we should silently do nothing for those that are disabled.
+        return success(null);
+      }
+      return formatFile(path);
+    });
   }
 }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
index c533db2..1195c9b 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_hover.dart
@@ -83,10 +83,6 @@
 
   ErrorOr<Hover?> _getHover(ResolvedUnitResult unit, int offset) {
     final compilationUnit = unit.unit;
-    if (compilationUnit == null) {
-      return success(null);
-    }
-
     final computer = DartUnitHoverComputer(
         server.getDartdocDirectiveInfoFor(unit), compilationUnit, offset);
     final hover = computer.compute();
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
index d842bbb..b0e3ca3 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialized.dart
@@ -28,10 +28,8 @@
       server,
     );
 
-    await server.fetchClientConfigurationAndPerformDynamicRegistration();
-
     if (!server.initializationOptions.onlyAnalyzeProjectsWithOpenFiles) {
-      server.updateWorkspaceFolders(openWorkspacePaths, const []);
+      await server.updateWorkspaceFolders(openWorkspacePaths, const []);
     }
 
     return success(null);
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
index b302227..93c78da 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_references.dart
@@ -83,7 +83,7 @@
         convert(results, toLocation).whereNotNull().toList();
 
     final compilationUnit = unit.unit;
-    if (compilationUnit != null && params.context.includeDeclaration == true) {
+    if (params.context.includeDeclaration == true) {
       // Also include the definition for the symbol at this location.
       referenceResults.addAll(_getDeclarations(compilationUnit, offset));
     }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
index 34f4193..25a78ca 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_signature_help.dart
@@ -62,7 +62,7 @@
       // signature help for that.
       final typeArgsSignature = _tryGetTypeArgsSignatureHelp(
         dartDocInfo,
-        unit.result.unit!,
+        unit.result.unit,
         offset,
         autoTriggered,
         formats,
@@ -72,7 +72,7 @@
       }
 
       final computer =
-          DartUnitSignatureComputer(dartDocInfo, unit.result.unit!, offset);
+          DartUnitSignatureComputer(dartDocInfo, unit.result.unit, offset);
       if (!computer.offsetIsValid) {
         return success(null); // No error, just no valid hover.
       }
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 ab57310..2dcd219 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -35,6 +35,7 @@
 import 'package:analysis_server/src/services/completion/completion_performance.dart'
     show CompletionPerformance;
 import 'package:analysis_server/src/services/refactoring/refactoring.dart';
+import 'package:analysis_server/src/utilities/process.dart';
 import 'package:analyzer/dart/analysis/context_locator.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/error/error.dart';
@@ -126,6 +127,7 @@
     CrashReportingAttachmentsBuilder crashReportingAttachmentsBuilder,
     InstrumentationService instrumentationService, {
     http.Client? httpClient,
+    ProcessRunner? processRunner,
     DiagnosticServer? diagnosticServer,
     // Disable to avoid using this in unit tests.
     bool enableBazelWatcher = false,
@@ -137,6 +139,7 @@
           baseResourceProvider,
           instrumentationService,
           httpClient,
+          processRunner,
           LspNotificationManager(channel, baseResourceProvider.pathContext),
           enableBazelWatcher: enableBazelWatcher,
         ) {
@@ -184,10 +187,10 @@
       RefactoringWorkspace(driverMap.values, searchEngine);
 
   void addPriorityFile(String filePath) {
-    // When a pubspec is opened, trigger package name caching for completion.
-    if (!pubPackageService.isRunning &&
-        file_paths.isPubspecYaml(resourceProvider.pathContext, filePath)) {
-      pubPackageService.beginPackageNamePreload();
+    // When pubspecs are opened, trigger pre-loading of pub package names and
+    // versions.
+    if (file_paths.isPubspecYaml(resourceProvider.pathContext, filePath)) {
+      pubPackageService.beginCachePreloads([filePath]);
     }
 
     final didAdd = priorityFiles.add(filePath);
@@ -205,33 +208,49 @@
   /// register/unregister requests for any supported/enabled dynamic registrations.
   Future<void> fetchClientConfigurationAndPerformDynamicRegistration() async {
     if (clientCapabilities?.configuration ?? false) {
+      // Take a copy of workspace folders because we need to match up the
+      // responses to the request by index and it's possible _workspaceFolders
+      // will change after we sent the request but before we get the response.
+      final folders = _workspaceFolders.toList();
+
       // Fetch all configuration we care about from the client. This is just
       // "dart" for now, but in future this may be extended to include
       // others (for example "flutter").
       final response = await sendRequest(
           Method.workspace_configuration,
           ConfigurationParams(items: [
+            // Dart settings for each workspace folder.
+            for (final folder in folders)
+              ConfigurationItem(
+                scopeUri: Uri.file(folder).toString(),
+                section: 'dart',
+              ),
+            // Global Dart settings. This comes last to simplify matching up the
+            // indexes in the results (folder[i] is the i'th item).
             ConfigurationItem(section: 'dart'),
           ]));
 
       final result = response.result;
 
-      // Expect the result to be a single list (to match the single
-      // ConfigurationItem we requested above) and that it should be
-      // a standard map of settings.
+      // Expect the result to be a list with 1 + folders.length items to
+      // match the request above, and each should be a standard map of settings.
       // If the above code is extended to support multiple sets of config
-      // this will need tweaking to handle each group appropriately.
+      // this will need tweaking to handle the item for each section.
       if (result != null &&
           result is List<dynamic> &&
-          result.length == 1 &&
-          result.first is Map<String, dynamic>) {
-        final newConfig = result.first;
-        final refreshRoots =
-            clientConfiguration.affectsAnalysisRoots(newConfig);
+          result.length == 1 + folders.length) {
+        // Config is stored as a map keyed by the workspace folder, and a key of
+        // null for the global config
+        final workspaceFolderConfig = {
+          for (var i = 0; i < folders.length; i++)
+            folders[i]: result[i] as Map<String, Object?>? ?? {},
+        };
+        final newGlobalConfig = result.last as Map<String, Object?>? ?? {};
 
-        clientConfiguration.replace(newConfig);
+        final oldGlobalConfig = clientConfiguration.global;
+        clientConfiguration.replace(newGlobalConfig, workspaceFolderConfig);
 
-        if (refreshRoots) {
+        if (clientConfiguration.affectsAnalysisRoots(oldGlobalConfig)) {
           _refreshAnalysisRoots();
         }
       }
@@ -638,14 +657,16 @@
     sendServerErrorNotification('Socket error', error, stack);
   }
 
-  void updateWorkspaceFolders(
-      List<String> addedPaths, List<String> removedPaths) {
+  Future<void> updateWorkspaceFolders(
+      List<String> addedPaths, List<String> removedPaths) async {
     // TODO(dantup): This is currently case-sensitive!
 
     _workspaceFolders
       ..addAll(addedPaths)
       ..removeAll(removedPaths);
 
+    await fetchClientConfigurationAndPerformDynamicRegistration();
+
     _refreshAnalysisRoots();
   }
 
@@ -699,7 +720,7 @@
         ? _workspaceFolders.toSet()
         : _getRootsForOpenFiles();
 
-    final excludedPaths = clientConfiguration.analysisExcludedFolders
+    final excludedPaths = clientConfiguration.global.analysisExcludedFolders
         .expand((excludePath) => resourceProvider.pathContext
                 .isAbsolute(excludePath)
             ? [excludePath]
@@ -825,42 +846,8 @@
     }
 
     analysisDriver.results.listen((result) {
-      var path = result.path;
-      if (path == null) {
-        // This shouldn't occur - result.path is marked with a TODO to become
-        // non-nullable.
-        return;
-      }
-      filesToFlush.add(path);
-      if (analysisServer.isAnalyzed(path)) {
-        final serverErrors = protocol.doAnalysisError_listFromEngine(result);
-        recordAnalysisErrors(path, serverErrors);
-      }
-      analysisServer.getDocumentationCacheFor(result)?.cacheFromResult(result);
-      analysisServer.getExtensionCacheFor(result)?.cacheFromResult(result);
-      final unit = result.unit;
-      if (unit != null) {
-        if (analysisServer.shouldSendClosingLabelsFor(path)) {
-          final labels = DartUnitClosingLabelsComputer(result.lineInfo, unit)
-              .compute()
-              .map((l) => toClosingLabel(result.lineInfo, l))
-              .toList();
-
-          analysisServer.publishClosingLabels(path, labels);
-        }
-        if (analysisServer.shouldSendOutlineFor(path)) {
-          final outline = DartUnitOutlineComputer(
-            result,
-            withBasicFlutter: true,
-          ).compute();
-          final lspOutline = toOutline(result.lineInfo, outline);
-          analysisServer.publishOutline(path, lspOutline);
-        }
-        if (analysisServer.shouldSendFlutterOutlineFor(path)) {
-          final outline = FlutterOutlineComputer(result).compute();
-          final lspOutline = toFlutterOutline(result.lineInfo, outline);
-          analysisServer.publishFlutterOutline(path, lspOutline);
-        }
+      if (result is FileResult) {
+        _handleFileResult(result);
       }
     });
     analysisDriver.exceptions.listen(analysisServer.logExceptionResult);
@@ -868,6 +855,18 @@
   }
 
   @override
+  void pubspecChanged(String pubspecPath) {
+    analysisServer.pubPackageService.fetchPackageVersionsViaPubOutdated(
+        pubspecPath,
+        pubspecWasModified: true);
+  }
+
+  @override
+  void pubspecRemoved(String pubspecPath) {
+    analysisServer.pubPackageService.flushPackageCaches(pubspecPath);
+  }
+
+  @override
   void recordAnalysisErrors(String path, List<protocol.AnalysisError> errors) {
     final errorsToSend = errors.where(_shouldSendError).toList();
     filesToFlush.add(path);
@@ -875,7 +874,53 @@
         .recordAnalysisErrors(NotificationManager.serverId, path, errorsToSend);
   }
 
+  void _handleFileResult(FileResult result) {
+    var path = result.path;
+    filesToFlush.add(path);
+
+    if (result is AnalysisResultWithErrors) {
+      if (analysisServer.isAnalyzed(path)) {
+        final serverErrors = protocol.doAnalysisError_listFromEngine(result);
+        recordAnalysisErrors(path, serverErrors);
+      }
+    }
+
+    if (result is ResolvedUnitResult) {
+      _handleResolvedUnitResult(result);
+    }
+  }
+
+  void _handleResolvedUnitResult(ResolvedUnitResult result) {
+    var path = result.path;
+
+    analysisServer.getDocumentationCacheFor(result)?.cacheFromResult(result);
+    analysisServer.getExtensionCacheFor(result)?.cacheFromResult(result);
+
+    final unit = result.unit;
+    if (analysisServer.shouldSendClosingLabelsFor(path)) {
+      final labels = DartUnitClosingLabelsComputer(result.lineInfo, unit)
+          .compute()
+          .map((l) => toClosingLabel(result.lineInfo, l))
+          .toList();
+
+      analysisServer.publishClosingLabels(path, labels);
+    }
+    if (analysisServer.shouldSendOutlineFor(path)) {
+      final outline = DartUnitOutlineComputer(
+        result,
+        withBasicFlutter: true,
+      ).compute();
+      final lspOutline = toOutline(result.lineInfo, outline);
+      analysisServer.publishOutline(path, lspOutline);
+    }
+    if (analysisServer.shouldSendFlutterOutlineFor(path)) {
+      final outline = FlutterOutlineComputer(result).compute();
+      final lspOutline = toFlutterOutline(result.lineInfo, outline);
+      analysisServer.publishFlutterOutline(path, lspOutline);
+    }
+  }
+
   bool _shouldSendError(protocol.AnalysisError error) =>
       error.code != ErrorType.TODO.name.toLowerCase() ||
-      analysisServer.clientConfiguration.showTodos;
+      analysisServer.clientConfiguration.global.showTodos;
 }
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 429920f..da9bb2a 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -49,6 +49,15 @@
   ],
 };
 
+/// Pattern for docComplete text on completion items that can be upgraded to
+/// the "detail" field so that it can be shown more prominently by clients.
+///
+/// This is typically used for labels like _latest compatible_ and _latest_ in
+/// the pubspec version items. These go into docComplete so that they appear
+/// reasonably for non-LSP clients where there is no equivalent of the detail
+/// field.
+final _upgradableDocCompletePattern = RegExp(r'^_([\w ]{0,20})_$');
+
 lsp.Either2<String, lsp.MarkupContent> asStringOrMarkupContent(
     Set<lsp.MarkupKind>? preferredFormats, String content) {
   return preferredFormats == null
@@ -866,19 +875,30 @@
         range: toRange(lineInfo, label.offset, label.length),
         label: label.label);
 
-lsp.CodeActionKind toCodeActionKind(String? id, lsp.CodeActionKind fallback) {
+/// Converts [id] to a [CodeActionKind] using [fallbackOrPrefix] as a fallback
+/// or a prefix if the ID is not already a fix/refactor.
+lsp.CodeActionKind toCodeActionKind(
+    String? id, lsp.CodeActionKind fallbackOrPrefix) {
   if (id == null) {
-    return fallback;
+    return fallbackOrPrefix;
   }
   // Dart fixes and assists start with "dart.assist." and "dart.fix." but in LSP
   // we want to use the predefined prefixes for CodeActions.
-  final newId = id
+  var newId = id
       .replaceAll('dart.assist', lsp.CodeActionKind.Refactor.toString())
       .replaceAll('dart.fix', lsp.CodeActionKind.QuickFix.toString())
       .replaceAll(
           'analysisOptions.assist', lsp.CodeActionKind.Refactor.toString())
       .replaceAll(
           'analysisOptions.fix', lsp.CodeActionKind.QuickFix.toString());
+
+  // If the ID does not start with either of the kinds above, prefix it as
+  // it will be an unqualified ID from a plugin.
+  if (!newId.startsWith(lsp.CodeActionKind.Refactor.toString()) &&
+      !newId.startsWith(lsp.CodeActionKind.QuickFix.toString())) {
+    newId = '$fallbackOrPrefix.$newId';
+  }
+
   return lsp.CodeActionKind(newId);
 }
 
@@ -956,7 +976,21 @@
   final insertText = insertTextInfo.first;
   final insertTextFormat = insertTextInfo.last;
   final isMultilineCompletion = insertText.contains('\n');
-  final cleanedDoc = cleanDartdoc(suggestion.docComplete);
+
+  var cleanedDoc = cleanDartdoc(suggestion.docComplete);
+  var detail = getCompletionDetail(suggestion, completionKind,
+      supportsCompletionDeprecatedFlag || supportsDeprecatedTag);
+
+  // To improve the display of some items (like pubspec version numbers),
+  // short labels in the format `_foo_` in docComplete are "upgraded" to the
+  // detail field.
+  final labelMatch = cleanedDoc != null
+      ? _upgradableDocCompletePattern.firstMatch(cleanedDoc)
+      : null;
+  if (labelMatch != null) {
+    cleanedDoc = null;
+    detail = labelMatch.group(1);
+  }
 
   // Because we potentially send thousands of these items, we should minimise
   // the generated JSON as much as possible - for example using nulls in place
@@ -971,8 +1005,7 @@
     commitCharacters:
         includeCommitCharacters ? dartCompletionCommitCharacters : null,
     data: resolutionData,
-    detail: getCompletionDetail(suggestion, completionKind,
-        supportsCompletionDeprecatedFlag || supportsDeprecatedTag),
+    detail: detail,
     documentation: cleanedDoc != null
         ? asStringOrMarkupContent(formats, cleanedDoc)
         : null,
diff --git a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
index ca0b352..89f26d4 100644
--- a/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
+++ b/pkg/analysis_server/lib/src/lsp/server_capabilities_computer.dart
@@ -136,9 +136,10 @@
       LspClientCapabilities clientCapabilities) {
     final codeActionLiteralSupport = clientCapabilities.literalCodeActions;
     final renameOptionsSupport = clientCapabilities.renameValidation;
-    final enableFormatter = _server.clientConfiguration.enableSdkFormatter;
+    final enableFormatter =
+        _server.clientConfiguration.global.enableSdkFormatter;
     final previewCommitCharacters =
-        _server.clientConfiguration.previewCommitCharacters;
+        _server.clientConfiguration.global.previewCommitCharacters;
 
     final dynamicRegistrations =
         ClientDynamicRegistrations(clientCapabilities.raw);
@@ -321,9 +322,10 @@
 
     final registrations = <Registration>[];
 
-    final enableFormatter = _server.clientConfiguration.enableSdkFormatter;
+    final enableFormatter =
+        _server.clientConfiguration.global.enableSdkFormatter;
     final previewCommitCharacters =
-        _server.clientConfiguration.previewCommitCharacters;
+        _server.clientConfiguration.global.previewCommitCharacters;
 
     /// Helper for creating registrations with IDs.
     void register(bool condition, Method method, [ToJsonable? options]) {
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 05538df..94f0005 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -94,7 +94,7 @@
     AnalysisServer server, ResolvedUnitResult resolvedUnit) {
   _sendNotification(server, () {
     protocol.FileKind fileKind;
-    var unit = resolvedUnit.unit!;
+    var unit = resolvedUnit.unit;
     if (unit.directives.any((d) => d is PartOfDirective)) {
       fileKind = protocol.FileKind.PART;
     } else {
@@ -112,7 +112,7 @@
 
     // send notification
     var params = protocol.AnalysisOutlineParams(
-        resolvedUnit.path!, fileKind, outline,
+        resolvedUnit.path, fileKind, outline,
         libraryName: libraryName);
     server.sendNotification(params.toNotification());
   });
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index c03f74b..7ad36bd 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -27,7 +27,7 @@
 /// Returns a list of AnalysisErrors corresponding to the given list of Engine
 /// errors.
 List<AnalysisError> doAnalysisError_listFromEngine(
-    engine.ResolvedUnitResult result) {
+    engine.AnalysisResultWithErrors result) {
   return mapEngineErrors(result, result.errors, newAnalysisError_fromEngine);
 }
 
@@ -79,9 +79,10 @@
 
 /// Translates engine errors through the ErrorProcessor.
 List<T> mapEngineErrors<T>(
-    engine.ResolvedUnitResult result,
+    engine.AnalysisResultWithErrors result,
     List<engine.AnalysisError> errors,
-    T Function(engine.ResolvedUnitResult result, engine.AnalysisError error,
+    T Function(
+            engine.AnalysisResultWithErrors result, engine.AnalysisError error,
             [engine.ErrorSeverity errorSeverity])
         constructor) {
   var analysisOptions = result.session.analysisContext.analysisOptions;
@@ -106,7 +107,7 @@
 ///
 /// If an [errorSeverity] is specified, it will override the one in [error].
 AnalysisError newAnalysisError_fromEngine(
-    engine.ResolvedUnitResult result, engine.AnalysisError error,
+    engine.AnalysisResultWithErrors result, engine.AnalysisError error,
     [engine.ErrorSeverity? errorSeverity]) {
   var errorCode = error.errorCode;
   // prepare location
@@ -125,8 +126,8 @@
     var endLine = endLocation.lineNumber;
     var endColumn = endLocation.columnNumber;
 
-    location = Location(
-        file, offset, length, startLine, startColumn, endLine, endColumn);
+    location = Location(file, offset, length, startLine, startColumn,
+        endLine: endLine, endColumn: endColumn);
   }
 
   // Default to the error's severity if none is specified.
@@ -155,7 +156,7 @@
 
 /// Create a DiagnosticMessage based on an [engine.DiagnosticMessage].
 DiagnosticMessage newDiagnosticMessage(
-    engine.ResolvedUnitResult result, engine.DiagnosticMessage message) {
+    engine.AnalysisResultWithErrors result, engine.DiagnosticMessage message) {
   var file = message.filePath;
   var offset = message.offset;
   var length = message.length;
@@ -170,8 +171,8 @@
 
   return DiagnosticMessage(
       message.messageText(includeUrl: true),
-      Location(
-          file, offset, length, startLine, startColumn, endLine, endColumn));
+      Location(file, offset, length, startLine, startColumn,
+          endLine: endLine, endColumn: endColumn));
 }
 
 /// Create a Location based on an [engine.Element].
@@ -316,5 +317,6 @@
     //  should be able to throw an exception. Try removing the try statement.
   }
   return Location(unitElement.source.fullName, range.offset, range.length,
-      startLine, startColumn, endLine, endColumn);
+      startLine, startColumn,
+      endLine: endLine, endColumn: endColumn);
 }
diff --git a/pkg/analysis_server/lib/src/services/completion/completion_core.dart b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
index 2c71a1e..d6fe971 100644
--- a/pkg/analysis_server/lib/src/services/completion/completion_core.dart
+++ b/pkg/analysis_server/lib/src/services/completion/completion_core.dart
@@ -44,7 +44,7 @@
   ResourceProvider get resourceProvider => result.session.resourceProvider;
 
   @override
-  Source get source => result.unit!.declaredElement!.source;
+  Source get source => result.unit.declaredElement!.source;
 
   @override
   String? get sourceContents => result.content;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index fce6916..b71fa3e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -100,7 +100,7 @@
   }) async {
     request.checkAborted();
     var pathContext = request.resourceProvider.pathContext;
-    if (!file_paths.isDart(pathContext, request.result.path!)) {
+    if (!file_paths.isDart(pathContext, request.result.path)) {
       return const <CompletionSuggestion>[];
     }
 
@@ -458,7 +458,7 @@
     return performance.run(
       'build DartCompletionRequest',
       (_) {
-        var unit = request.result.unit!;
+        var unit = request.result.unit;
         var libSource = unit.declaredElement!.library.source;
         var objectType = request.result.typeProvider.objectType;
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/documentation_cache.dart b/pkg/analysis_server/lib/src/services/completion/dart/documentation_cache.dart
index 4457f2e..0ca62d6 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/documentation_cache.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/documentation_cache.dart
@@ -29,7 +29,7 @@
 
   /// Fill the cache with data from the [result].
   void cacheFromResult(ResolvedUnitResult result) {
-    var compilationUnit = result.unit?.declaredElement;
+    var compilationUnit = result.unit.declaredElement;
     if (compilationUnit != null) {
       documentationCache.remove(_keyForUnit(compilationUnit));
       _cacheFromElement(compilationUnit);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_cache.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_cache.dart
index 96decc0..38481dc 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_cache.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_cache.dart
@@ -21,7 +21,7 @@
 
   /// Fill the cache with data from the [result].
   void cacheFromResult(ResolvedUnitResult result) {
-    var element = result.unit?.declaredElement;
+    var element = result.unit.declaredElement;
     if (element != null) {
       _cacheFromElement(element);
       for (var library in result.libraryElement.importedLibraries) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
index c767698..f14d554 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
@@ -158,7 +158,7 @@
       return;
     }
 
-    var libraryUnits = request.result.unit?.declaredElement?.library.units;
+    var libraryUnits = request.result.unit.declaredElement?.library.units;
     if (libraryUnits == null) {
       return;
     }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 467c954..9bcd314 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -704,7 +704,7 @@
       ExecutableElement element, bool invokeSuper) async {
     var displayTextBuffer = StringBuffer();
     var builder = ChangeBuilder(session: request.result.session);
-    await builder.addDartFileEdit(request.result.path!, (builder) {
+    await builder.addDartFileEdit(request.result.path, (builder) {
       builder.addReplacement(range.node(targetId), (builder) {
         builder.writeOverride(
           element,
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
index d045443..26a1a94 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -158,7 +158,8 @@
     bool isDeprecated = false}) {
   var name = id.name;
   // TODO(danrubel) use lineInfo to determine startLine and startColumn
-  var location = Location(source.fullName, id.offset, id.length, 0, 0, 0, 0);
+  var location = Location(source.fullName, id.offset, id.length, 0, 0,
+      endLine: 0, endColumn: 0);
   var flags = protocol.Element.makeFlags(
       isAbstract: isAbstract,
       isDeprecated: isDeprecated,
@@ -194,7 +195,7 @@
 }
 
 String getRequestLineIndent(DartCompletionRequest request) {
-  var content = request.result.content!;
+  var content = request.result.content;
   var lineStartOffset = request.offset;
   var notWhitespaceOffset = request.offset;
   for (; lineStartOffset > 0; lineStartOffset--) {
diff --git a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
index 8aa88e2..988a42d 100644
--- a/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/postfix/postfix_completion.dart
@@ -264,7 +264,7 @@
 
   String get eol => utils.endOfLine;
 
-  String get file => completionContext.resolveResult.path!;
+  String get file => completionContext.resolveResult.path;
 
   String get key => completionContext.key;
 
diff --git a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
index 9bd0039..e337213 100644
--- a/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
+++ b/pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart
@@ -120,7 +120,7 @@
 
   String get eol => utils.endOfLine;
 
-  String get file => statementContext.resolveResult.path!;
+  String get file => statementContext.resolveResult.path;
 
   LineInfo get lineInfo => statementContext.resolveResult.lineInfo;
 
@@ -128,7 +128,7 @@
 
   Source get source => unitElement.source;
 
-  CompilationUnit get unit => statementContext.resolveResult.unit!;
+  CompilationUnit get unit => statementContext.resolveResult.unit;
 
   CompilationUnitElement get unitElement => unit.declaredElement!;
 
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
index 7f60edd..bd175b9 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart
@@ -30,6 +30,7 @@
         AnalyzerOptions.chromeOsManifestChecks: EmptyProducer(),
       }),
       AnalyzerOptions.plugins: EmptyProducer(),
+      AnalyzerOptions.propagateLinterExceptions: EmptyProducer(),
       AnalyzerOptions.strong_mode: MapProducer({
         AnalyzerOptions.declarationCasts: EmptyProducer(),
         AnalyzerOptions.implicitCasts: EmptyProducer(),
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart b/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
index 960346f..5d7f681 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/producer.dart
@@ -176,9 +176,11 @@
   const Producer();
 
   /// A utility method used to create a suggestion for the [identifier].
-  CompletionSuggestion identifier(String identifier, {int relevance = 1000}) =>
+  CompletionSuggestion identifier(String identifier,
+          {int relevance = 1000, String? docComplete}) =>
       CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER, relevance,
-          identifier, identifier.length, 0, false, false);
+          identifier, identifier.length, 0, false, false,
+          docComplete: docComplete);
 
   /// A utility method used to create a suggestion for the package [packageName].
   CompletionSuggestion packageName(String packageName,
diff --git a/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart b/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
index 724bb6f..a34d791 100644
--- a/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
+++ b/pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart
@@ -37,18 +37,25 @@
   @override
   Iterable<CompletionSuggestion> suggestions(
       YamlCompletionRequest request) sync* {
-    // TOOD(dantup): Consider supporting async completion requests so this
-    // could call packageDetails() (with a short timeout, and pub retries
-    // disabled). A user that explicitly invokes completion in the location
-    // of a version may be prepared to wait a short period for a web request
-    // to get completion versions (this is also the only way for non-LSP
-    // clients to get them, since there are no resolve calls).
+    final versions = request.pubPackageService
+        ?.cachedPubOutdatedVersions(request.filePath, package);
+    final resolvable = versions?.resolvableVersion;
+    var latest = versions?.latestVersion;
+
+    // If we didn't get a latest version from the "pub outdated" results, we can
+    // use the result from the Pub API if we've called it (this will usually
+    // only be the case for LSP where a resolve() call was sent).
     //
-    // Supporting this will require making the completion async further up.
-    final details = request.pubPackageService?.cachedPackageDetails(package);
-    final version = details?.latestVersion;
-    if (version != null) {
-      yield identifier('^$version');
+    // This allows us (in some cases) to still show version numbers even if the
+    // package was newly added to pubspec and not saved, so not yet in the
+    // "pub outdated" results.
+    latest ??= request.pubPackageService?.cachedPubApiLatestVersion(package);
+
+    if (resolvable != null && resolvable != latest) {
+      yield identifier('^$resolvable', docComplete: '_latest compatible_');
+    }
+    if (latest != null) {
+      yield identifier('^$latest', docComplete: '_latest_');
     }
   }
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/base_processor.dart b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
index 543d8c9..fb8a04f 100644
--- a/pkg/analysis_server/lib/src/services/correction/base_processor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/base_processor.dart
@@ -33,7 +33,7 @@
     this.selectionLength = 0,
     required this.resolvedResult,
     required this.workspace,
-  })  : file = resolvedResult.path!,
+  })  : file = resolvedResult.path,
         session = resolvedResult.session,
         sessionHelper = AnalysisSessionHelper(resolvedResult.session),
         typeProvider = resolvedResult.typeProvider,
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 b43cfbc..7313659 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
@@ -172,7 +172,7 @@
             file_paths.isGenerated(path)) {
           continue;
         }
-        var library = await context.currentSession.getResolvedLibrary2(path);
+        var library = await context.currentSession.getResolvedLibrary(path);
         if (library is ResolvedLibraryResult) {
           await _fixErrorsInLibrary(library);
         }
@@ -182,6 +182,22 @@
     return builder;
   }
 
+  /// Return a change builder that has been used to create fixes for the
+  /// diagnostics in [file] in the given [context].
+  Future<ChangeBuilder> fixErrorsForFile(
+      AnalysisContext context, String path) async {
+    var pathContext = context.contextRoot.resourceProvider.pathContext;
+
+    if (file_paths.isDart(pathContext, path) && !file_paths.isGenerated(path)) {
+      var library = await context.currentSession.getResolvedLibrary(path);
+      if (library is ResolvedLibraryResult) {
+        await _fixErrorsInLibrary(library);
+      }
+    }
+
+    return builder;
+  }
+
   /// Return a change builder that has been used to create all fixes for a
   /// specific diagnostic code in the given [unit].
   Future<ChangeBuilder> fixOfTypeInUnit(
@@ -269,7 +285,7 @@
   /// library associated with the analysis [result].
   Future<void> _fixErrorsInLibrary(ResolvedLibraryResult result) async {
     var analysisOptions = result.session.analysisContext.analysisOptions;
-    for (var unitResult in result.units!) {
+    for (var unitResult in result.units) {
       var overrideSet = _readOverrideSet(unitResult);
       for (var error in unitResult.errors) {
         var processor = ErrorProcessor.getProcessor(analysisOptions, error);
@@ -336,7 +352,7 @@
       await compute(producer);
       var newHash = computeChangeHash();
       if (newHash != oldHash) {
-        changeMap.add(result.path!, code);
+        changeMap.add(result.path, code);
       }
     }
 
@@ -401,7 +417,7 @@
     if (useConfigFiles) {
       var provider = result.session.resourceProvider;
       var context = provider.pathContext;
-      var dartFileName = result.path!;
+      var dartFileName = result.path;
       var configFileName = '${context.withoutExtension(dartFileName)}.config';
       var configFile = provider.getFile(configFileName);
       try {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
index bc10e17..14485d2 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
@@ -249,12 +249,12 @@
     this.overrideSet,
     this.selectionOffset = -1,
     this.selectionLength = 0,
-  })  : file = resolvedResult.path!,
+  })  : file = resolvedResult.path,
         session = resolvedResult.session,
         sessionHelper = AnalysisSessionHelper(resolvedResult.session),
         typeProvider = resolvedResult.typeProvider,
         selectionEnd = selectionOffset + selectionLength,
-        unit = resolvedResult.unit!,
+        unit = resolvedResult.unit,
         utils = CorrectionUtils(resolvedResult);
 
   /// Return `true` if the lint with the given [name] is enabled.
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_async_body.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_async_body.dart
index 1ccaff4..8a6b2c8 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_into_async_body.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_into_async_body.dart
@@ -17,8 +17,9 @@
     var body = getEnclosingFunctionBody();
     if (body == null ||
         body is EmptyFunctionBody ||
-        body.isAsynchronous ||
-        body.isGenerator) {
+        // Do not offer a correction if there is an `async`, `async*`, `sync*`,
+        // or the fictional `sync` keyword.
+        body.keyword != null) {
       return;
     }
 
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart b/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart
index 0f22239..c841c0f 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/convert_part_of_to_uri.dart
@@ -27,7 +27,7 @@
     }
 
     var libraryPath = resolvedResult.libraryElement.source.fullName;
-    var partPath = resolvedResult.path!;
+    var partPath = resolvedResult.path;
     var relativePath = relative(libraryPath, from: dirname(partPath));
     var uri = Uri.file(relativePath).toString();
     var replacementRange = range.node(libraryName);
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart b/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart
index 2f320ef..9009561 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/create_method.dart
@@ -154,7 +154,7 @@
       // use different utils
       var targetPath = targetClassElement.source.fullName;
       var targetResolveResult =
-          await resolvedResult.session.getResolvedUnit2(targetPath);
+          await resolvedResult.session.getResolvedUnit(targetPath);
       if (targetResolveResult is! ResolvedUnitResult) {
         return;
       }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
index 1b02c88..318a934 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_wrap.dart
@@ -39,7 +39,7 @@
   Iterable<CorrectionProducer> _wrapMultipleWidgets() sync* {
     var selectionRange = SourceRange(selectionOffset, selectionLength);
     var analyzer = SelectionAnalyzer(selectionRange);
-    resolvedResult.unit!.accept(analyzer);
+    resolvedResult.unit.accept(analyzer);
 
     var widgetExpressions = <Expression>[];
     if (analyzer.hasSelectedNodes) {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart b/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
index 69137bf..00b0dd7d 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/import_library.dart
@@ -450,7 +450,7 @@
 
   @override
   Future<void> compute(ChangeBuilder builder) async {
-    var result = await sessionHelper.session.getLibraryByUri2(uri.toString());
+    var result = await sessionHelper.session.getLibraryByUri(uri.toString());
     if (result is LibraryElementResult) {
       var library = result.element;
       if (library
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/organize_imports.dart b/pkg/analysis_server/lib/src/services/correction/dart/organize_imports.dart
index caca5ec..d5cf7c0 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/organize_imports.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/organize_imports.dart
@@ -25,7 +25,7 @@
   @override
   Future<void> compute(ChangeBuilder builder) async {
     var organizer =
-        ImportOrganizer(resolvedResult.content!, unit, resolvedResult.errors);
+        ImportOrganizer(resolvedResult.content, unit, resolvedResult.errors);
     // todo (pq): consider restructuring organizer to allow a passed-in change
     //  builder
     for (var edit in organizer.organize()) {
diff --git a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
index 9f1c68a..9a156c4 100644
--- a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
@@ -52,7 +52,7 @@
 
   /// Analyze the selection, compute [status] and nodes.
   void analyze() {
-    resolveResult.unit!.accept(this);
+    resolveResult.unit.accept(this);
   }
 
   /// Records fatal error with given message and [Location].
@@ -73,7 +73,7 @@
     {
       var selectionStart = selection.offset;
       var selectionEnd = selection.end;
-      var commentRanges = getCommentRanges(resolveResult.unit!);
+      var commentRanges = getCommentRanges(resolveResult.unit);
       for (var commentRange in commentRanges) {
         if (commentRange.contains(selectionStart)) {
           invalidSelection('Selection begins inside a comment.');
@@ -208,9 +208,9 @@
 
   /// Returns `true` if there are [Token]s in the given [SourceRange].
   bool _hasTokens(SourceRange range) {
-    var fullText = resolveResult.content!;
+    var fullText = resolveResult.content;
     var rangeText = fullText.substring(range.offset, range.end);
-    return _getTokens(rangeText, resolveResult.unit!.featureSet).isNotEmpty;
+    return _getTokens(rangeText, resolveResult.unit.featureSet).isNotEmpty;
   }
 
   /// Returns `true` if [nodes] contains [node].
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 7259632..7fc3b9f 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -37,7 +37,7 @@
     LibraryElement targetLibrary, Set<Source> libraries) async {
   var libraryPath = targetLibrary.source.fullName;
 
-  var resolveResult = await session.getResolvedUnit2(libraryPath);
+  var resolveResult = await session.getResolvedUnit(libraryPath);
   if (resolveResult is! ResolvedUnitResult) {
     return;
   }
@@ -537,9 +537,9 @@
   String? _endOfLine;
 
   CorrectionUtils(ResolvedUnitResult result)
-      : unit = result.unit!,
+      : unit = result.unit,
         _library = result.libraryElement,
-        _buffer = result.content!;
+        _buffer = result.content;
 
   /// Returns the EOL to use for this [CompilationUnit].
   String get endOfLine {
@@ -860,14 +860,13 @@
   /// used by the generated source, but not imported.
   String? getTypeSource(DartType type, Set<Source> librariesToImport,
       {StringBuffer? parametersBuffer}) {
-    var aliasElement = type.aliasElement;
-    var aliasArguments = type.aliasArguments;
-    if (aliasElement != null && aliasArguments != null) {
+    var alias = type.alias;
+    if (alias != null) {
       return _getTypeCodeElementArguments(
         librariesToImport: librariesToImport,
-        element: aliasElement,
+        element: alias.element,
         isNullable: type.nullabilitySuffix == NullabilitySuffix.question,
-        typeArguments: aliasArguments,
+        typeArguments: alias.typeArguments,
       );
     }
 
diff --git a/pkg/analysis_server/lib/src/services/flutter/property.dart b/pkg/analysis_server/lib/src/services/flutter/property.dart
index 11af175..2a6586d 100644
--- a/pkg/analysis_server/lib/src/services/flutter/property.dart
+++ b/pkg/analysis_server/lib/src/services/flutter/property.dart
@@ -118,7 +118,7 @@
       );
     }
 
-    await builder.addDartFileEdit(resolvedUnit.path!, (builder) {
+    await builder.addDartFileEdit(resolvedUnit.path, (builder) {
       _changeCode(builder, (builder) {
         var expression = value.expression;
         if (expression != null) {
@@ -155,7 +155,7 @@
       }
 
       var beginOffset = argumentExpression.offset;
-      await builder.addDartFileEdit(resolvedUnit.path!, (builder) {
+      await builder.addDartFileEdit(resolvedUnit.path, (builder) {
         builder.addDeletion(
           SourceRange(beginOffset, endOffset - beginOffset),
         );
@@ -559,7 +559,7 @@
 
     var builder = ChangeBuilder(session: property.resolvedUnit.session);
 
-    await builder.addDartFileEdit(property.resolvedUnit.path!, (builder) {
+    await builder.addDartFileEdit(property.resolvedUnit.path, (builder) {
       property._changeCode(builder, (builder) {
         if (leftCode == rightCode && topCode == bottomCode) {
           builder.writeReference(classEdgeInsets);
@@ -659,7 +659,7 @@
 
   String? _expressionCode(Expression? expression) {
     if (expression != null) {
-      var content = property.resolvedUnit.content!;
+      var content = property.resolvedUnit.content;
       return content.substring(expression.offset, expression.end);
     }
     return null;
diff --git a/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart b/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
index f38a7cc..77da5dda 100644
--- a/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
+++ b/pkg/analysis_server/lib/src/services/flutter/widget_descriptions.dart
@@ -336,7 +336,7 @@
 
     String? valueExpressionCode;
     if (valueExpression != null) {
-      valueExpressionCode = resolvedUnit.content!.substring(
+      valueExpressionCode = resolvedUnit.content.substring(
         valueExpression.offset,
         valueExpression.end,
       );
diff --git a/pkg/analysis_server/lib/src/services/pub/pub_command.dart b/pkg/analysis_server/lib/src/services/pub/pub_command.dart
new file mode 100644
index 0000000..a649d65
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/pub/pub_command.dart
@@ -0,0 +1,149 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// 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 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:analysis_server/src/utilities/process.dart';
+import 'package:analyzer/instrumentation/service.dart';
+import 'package:path/path.dart' as path;
+
+/// A class for interacting with the `pub` command.
+///
+/// `pub` commands will be queued and not run concurrently.
+class PubCommand {
+  static const String _pubEnvironmentKey = 'PUB_ENVIRONMENT';
+  final InstrumentationService _instrumentationService;
+  late final ProcessRunner _processRunner;
+  late final String _pubPath;
+  late final String _pubEnvironmentValue;
+
+  /// Tracks the last queued command to avoid overlapping because pub does not
+  /// do its own locking when accessing the cache.
+  ///
+  /// https://github.com/dart-lang/pub/issues/1178
+  ///
+  /// This does not prevent running concurrently with commands spawned by other
+  /// tools (such as the IDE).
+  var _lastQueuedCommand = Future<void>.value();
+
+  PubCommand(this._instrumentationService, this._processRunner) {
+    _pubPath = path.join(
+      path.dirname(Platform.resolvedExecutable),
+      Platform.isWindows ? 'pub.bat' : 'pub',
+    );
+
+    // When calling the `pub` command, we must add an identifier to the
+    // PUB_ENVIRONMENT environment variable (joined with colons).
+    const _pubEnvString = 'analysis_server.pub_api';
+    final existingPubEnv = Platform.environment[_pubEnvironmentKey];
+    _pubEnvironmentValue = [
+      if (existingPubEnv?.isNotEmpty ?? false) existingPubEnv,
+      _pubEnvString,
+    ].join(':');
+  }
+
+  /// Runs `pub outdated --show-all` and returns the results.
+  ///
+  /// If any error occurs executing the command, returns an empty list.
+  Future<List<PubOutdatedPackageDetails>> outdatedVersions(
+      String pubspecPath) async {
+    final packageDirectory = path.dirname(pubspecPath);
+    final result = await _runPubJsonCommand(
+        ['outdated', '--show-all', '--json'],
+        workingDirectory: packageDirectory);
+
+    if (result == null) {
+      return [];
+    }
+
+    final packages =
+        (result['packages'] as List<dynamic>?)?.cast<Map<String, Object?>>();
+    if (packages == null) {
+      return [];
+    }
+
+    return packages
+        .map(
+          (json) => PubOutdatedPackageDetails(
+            json['package'] as String,
+            currentVersion: _version(json, 'current'),
+            latestVersion: _version(json, 'latest'),
+            resolvableVersion: _version(json, 'resolvable'),
+            upgradableVersion: _version(json, 'upgradable'),
+          ),
+        )
+        .toList();
+  }
+
+  /// Runs a pub command and decodes JSON from `stdout`.
+  ///
+  /// Returns null if:
+  ///   - exit code is non-zero
+  ///   - returned text cannot be decoded as JSON
+  Future<Map<String, Object?>?> _runPubJsonCommand(List<String> args,
+      {required String workingDirectory}) async {
+    // Atomically replace the lastQueuedCommand future with our own to ensure
+    // only one command waits on any previous commands future.
+    final completer = Completer<void>();
+    final lastCommand = _lastQueuedCommand;
+    _lastQueuedCommand = completer.future;
+    // And wait for that previous command to finish.
+    await lastCommand.catchError((_) {});
+
+    try {
+      final command = [_pubPath, ...args];
+
+      _instrumentationService.logInfo('Running pub command $command');
+      final result = await _processRunner.run(_pubPath, args,
+          workingDirectory: workingDirectory,
+          environment: {_pubEnvironmentKey: _pubEnvironmentValue});
+
+      if (result.exitCode != 0) {
+        _instrumentationService.logError(
+            'pub command returned ${result.exitCode} exit code: ${result.stderr}.');
+        return null;
+      }
+
+      try {
+        final results = jsonDecode(result.stdout);
+        _instrumentationService.logInfo('pub command completed successfully');
+        return results;
+      } catch (e) {
+        _instrumentationService
+            .logError('pub command returned invalid JSON: $e.');
+        return null;
+      }
+    } catch (e) {
+      _instrumentationService.logError('pub command failed to run: $e.');
+      return null;
+    } finally {
+      completer.complete();
+    }
+  }
+
+  String? _version(Map<String, Object?> json, String type) {
+    final versionType = json[type] as Map<String, Object?>?;
+    final version =
+        versionType != null ? versionType['version'] as String? : null;
+    return version;
+  }
+}
+
+class PubOutdatedPackageDetails {
+  final String packageName;
+  final String? currentVersion;
+  final String? latestVersion;
+  final String? resolvableVersion;
+  final String? upgradableVersion;
+
+  PubOutdatedPackageDetails(
+    this.packageName, {
+    required this.currentVersion,
+    required this.latestVersion,
+    required this.resolvableVersion,
+    required this.upgradableVersion,
+  });
+}
diff --git a/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart b/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart
index d0990db..4b6ef3a8 100644
--- a/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart
+++ b/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart
@@ -6,10 +6,11 @@
 import 'dart:convert';
 
 import 'package:analysis_server/src/services/pub/pub_api.dart';
+import 'package:analysis_server/src/services/pub/pub_command.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/instrumentation/service.dart';
 import 'package:meta/meta.dart';
+import 'package:path/path.dart' as path;
 
 /// Information about Pub packages that can be converted to/from JSON and
 /// cached to disk.
@@ -130,16 +131,26 @@
 
 /// A service for providing Pub package information.
 ///
-/// Uses a [PubApi] to communicate with Pub and caches to disk using [cacheResourceProvider].
+/// Uses a [PubApi] to communicate with the Pub API and a [PubCommand] to
+/// interact with the local `pub` command.
+///
+/// Expensive results are cached to disk using [resourceProvider].
 class PubPackageService {
   final InstrumentationService _instrumentationService;
   final PubApi _api;
+
+  /// A wrapper over the "pub" command line too.
+  ///
+  /// This can be null when not running on a real file system because it may
+  /// try to interact with folders that don't really exist.
+  final PubCommand? _command;
+
   Timer? _nextPackageNameListRequestTimer;
   Timer? _nextWriteDiskCacheTimer;
 
-  /// [ResourceProvider] used for caching. This should generally be a
-  /// [PhysicalResourceProvider] outside of tests.
-  final ResourceProvider cacheResourceProvider;
+  /// [ResourceProvider] used for accessing the disk for caches and checking
+  /// project types. This will be a [PhysicalResourceProvider] outside of tests.
+  final ResourceProvider resourceProvider;
 
   /// The current cache of package information. Initially `null`, but
   /// overwritten after first read of cache from disk or fetch from the API.
@@ -148,25 +159,50 @@
 
   int _packageDetailsRequestsInFlight = 0;
 
-  PubPackageService(
-      this._instrumentationService, this.cacheResourceProvider, this._api);
+  /// A cache of version numbers from running the "pub outdated" command used
+  /// for completion in pubspec.yaml.
+  final _pubspecPackageVersions =
+      <String, Map<String, PubOutdatedPackageDetails>>{};
 
-  /// Gets the last set of package results or an empty List if no results.
+  PubPackageService(this._instrumentationService, this.resourceProvider,
+      this._api, this._command);
+
+  /// Gets the last set of package results from the Pub API or an empty List if
+  /// no results.
+  ///
+  /// This data is used for completion of package names in pubspec.yaml
+  /// and for clients that support lazy resolution of completion items may also
+  /// include their descriptions and/or version numbers.
   List<PubPackage> get cachedPackages =>
       packageCache?.packages.values.toList() ?? [];
 
-  bool get isRunning => _nextPackageNameListRequestTimer != null;
+  @visibleForTesting
+  bool get isPackageNamesTimerRunning =>
+      _nextPackageNameListRequestTimer != null;
 
   @visibleForTesting
   File get packageCacheFile {
-    final cacheFolder = cacheResourceProvider
+    final cacheFolder = resourceProvider
         .getStateLocation('.pub-package-details-cache')!
       ..create();
     return cacheFolder.getChildAssumingFile('packages.json');
   }
 
-  /// Begin a request to pre-load the package name list.
+  /// Begins preloading caches for package names and pub versions.
+  void beginCachePreloads(List<String> pubspecs) {
+    beginPackageNamePreload();
+    for (final pubspec in pubspecs) {
+      fetchPackageVersionsViaPubOutdated(pubspec, pubspecWasModified: false);
+    }
+  }
+
+  /// Begin a timer to pre-load and update the package name list if one has not
+  /// already been started.
   void beginPackageNamePreload() {
+    if (isPackageNamesTimerRunning) {
+      return;
+    }
+
     // If first time, try to read from disk.
     var cache = packageCache;
     if (cache == null) {
@@ -179,11 +215,69 @@
         Timer(cache.cacheTimeRemaining, _fetchFromServer);
   }
 
-  /// Gets the cached package details for package [packageName].
+  /// Gets the latest cached package version fetched from the Pub API for the
+  /// package [packageName].
+  String? cachedPubApiLatestVersion(String packageName) =>
+      packageCache?.packages[packageName]?.latestVersion;
+
+  /// Gets the package versions cached using "pub outdated" for the package
+  /// [packageName] for the project using [pubspecPath].
   ///
-  /// Returns null if no package details are cached.
-  PubPackage? cachedPackageDetails(String packageName) =>
-      packageCache?.packages[packageName];
+  /// Versions in here might only be available for packages that are in the
+  /// pubspec on disk. Newly-added packages in the overlay might not be
+  /// available.
+  PubOutdatedPackageDetails? cachedPubOutdatedVersions(
+      String pubspecPath, String packageName) {
+    final pubspecCache = _pubspecPackageVersions[pubspecPath];
+    return pubspecCache != null ? pubspecCache[packageName] : null;
+  }
+
+  /// Begin a request to pre-load package versions using the "pub outdated"
+  /// command.
+  ///
+  /// If [pubspecWasModified] is true, the command will always be run. Otherwise it
+  /// will only be run if data is not already cached.
+  Future<void> fetchPackageVersionsViaPubOutdated(String pubspecPath,
+      {required bool pubspecWasModified}) async {
+    final pubCommand = _command;
+    if (pubCommand == null) {
+      return;
+    }
+
+    // If we already have a cache for the file and it was not modified (only
+    // opened) we do not need to re-run the command.
+    if (!pubspecWasModified &&
+        _pubspecPackageVersions.containsKey(pubspecPath)) {
+      return;
+    }
+
+    // Check if this pubspec is inside a DEPS-managed folder, and if so
+    // just cache an empty set of results since Pub is not managing
+    // dependencies.
+    if (_hasAncestorDEPSFile(pubspecPath)) {
+      _pubspecPackageVersions.putIfAbsent(pubspecPath, () => {});
+      return;
+    }
+
+    final results = await pubCommand.outdatedVersions(pubspecPath);
+    final cache = _pubspecPackageVersions.putIfAbsent(pubspecPath, () => {});
+    for (final package in results) {
+      // We use the versions from the "pub outdated" results but only cache them
+      // in-memory for this specific pubspec, as the resolved version may be
+      // restricted by constraints/dependencies in the pubspec. The "pub"
+      // command does caching of the JSON versions to make "pub outdated" fast.
+      cache[package.packageName] = package;
+    }
+  }
+
+  /// Clears package caches for [pubspecPath].
+  ///
+  /// Does not remove other caches that are not pubspec-specific (for example
+  /// the latest version pulled directly from the Pub API independant of
+  /// pubspec).
+  Future<void> flushPackageCaches(String pubspecPath) async {
+    _pubspecPackageVersions.remove(pubspecPath);
+  }
 
   /// Gets package details for package [packageName].
   ///
@@ -267,6 +361,19 @@
     }
   }
 
+  /// Checks whether there is a DEPS file in any folder walking up from the
+  /// pubspec at [pubspecPath].
+  bool _hasAncestorDEPSFile(String pubspecPath) {
+    var folder = path.dirname(pubspecPath);
+    do {
+      if (resourceProvider.getFile(path.join(folder, 'DEPS')).exists) {
+        return true;
+      }
+      folder = path.dirname(folder);
+    } while (folder != path.dirname(folder));
+    return false;
+  }
+
   /// Writes the package cache to disk after
   /// [PackageDetailsCache._writeCacheDebounceDuration] has elapsed, restarting
   /// the timer each time this method is called.
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
index 2432c5b..7d361dc 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_local.dart
@@ -61,12 +61,12 @@
     utils = CorrectionUtils(resolveResult);
   }
 
-  String get file => resolveResult.path!;
+  String get file => resolveResult.path;
 
   @override
   String get refactoringName => 'Extract Local Variable';
 
-  CompilationUnit get unit => resolveResult.unit!;
+  CompilationUnit get unit => resolveResult.unit;
 
   CompilationUnitElement get unitElement => unit.declaredElement!;
 
@@ -231,7 +231,7 @@
       return RefactoringStatus.fatal(
           'The selection offset must be greater than zero.');
     }
-    if (selectionOffset + selectionLength >= resolveResult.content!.length) {
+    if (selectionOffset + selectionLength >= resolveResult.content.length) {
       return RefactoringStatus.fatal(
           'The selection end offset must be less then the length of the file.');
     }
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
index a2c9a19..ebb50c0 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_method.dart
@@ -297,7 +297,7 @@
       // add replace edit
       var edit = newSourceEdit_range(range, invocationSource);
       doSourceChange_addElementEdit(
-          change, resolveResult.unit!.declaredElement!, edit);
+          change, resolveResult.unit.declaredElement!, edit);
     }
     // add method declaration
     {
@@ -378,7 +378,7 @@
         var offset = _parentMember!.end;
         var edit = SourceEdit(offset, 0, '$eol$eol$prefix$declarationSource');
         doSourceChange_addElementEdit(
-            change, resolveResult.unit!.declaredElement!, edit);
+            change, resolveResult.unit.declaredElement!, edit);
       }
     }
     // done
@@ -450,7 +450,7 @@
       return RefactoringStatus.fatal(
           'The selection offset must be greater than zero.');
     }
-    if (selectionOffset + selectionLength >= resolveResult.content!.length) {
+    if (selectionOffset + selectionLength >= resolveResult.content.length) {
       return RefactoringStatus.fatal(
           'The selection end offset must be less then the length of the file.');
     }
@@ -658,12 +658,11 @@
     var originalSource = utils.getText(range.offset, range.length);
     var pattern = _SourcePattern();
     var replaceEdits = <SourceEdit>[];
-    resolveResult.unit!
-        .accept(_GetSourcePatternVisitor(range, pattern, replaceEdits));
+    resolveResult.unit.accept(_GetSourcePatternVisitor(range, pattern, replaceEdits));
     replaceEdits = replaceEdits.reversed.toList();
     var source = SourceEdit.applySequence(originalSource, replaceEdits);
     pattern.normalizedSource =
-        _getNormalizedSource(source, resolveResult.unit!.featureSet);
+        _getNormalizedSource(source, resolveResult.unit.featureSet);
     return pattern;
   }
 
@@ -706,7 +705,7 @@
     var result = RefactoringStatus();
     var assignedUsedVariables = <VariableElement>[];
 
-    var unit = resolveResult.unit!;
+    var unit = resolveResult.unit;
     _visibleRangeMap = VisibleRangesComputer.forNode(unit);
     unit.accept(
       _InitializeParametersVisitor(this, assignedUsedVariables),
diff --git a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
index 36304e9..6fe4778 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/extract_widget.dart
@@ -85,7 +85,7 @@
   }
 
   FeatureSet get _featureSet {
-    return resolveResult.unit!.featureSet;
+    return resolveResult.unit.featureSet;
   }
 
   Flutter get _flutter => Flutter.instance;
@@ -144,7 +144,7 @@
   Future<SourceChange> createChange() async {
     var builder =
         ChangeBuilder(session: sessionHelper.session, eol: utils.endOfLine);
-    await builder.addDartFileEdit(resolveResult.path!, (builder) {
+    await builder.addDartFileEdit(resolveResult.path, (builder) {
       final expression = _expression;
       final statements = _statements;
       if (expression != null) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
index c7577b6..e0f3df71 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_local.dart
@@ -114,7 +114,7 @@
   @override
   Future<SourceChange> createChange() {
     var change = SourceChange(refactoringName);
-    var unitElement = resolveResult.unit!.declaredElement!;
+    var unitElement = resolveResult.unit.declaredElement!;
     var state = _initialState!;
     // remove declaration
     {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
index 1cff243..f3e4b67 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/inline_method.dart
@@ -363,7 +363,7 @@
     _methodNode = methodNode;
 
     var resolvedUnit = declaration.resolvedUnit!;
-    _methodUnit = resolvedUnit.unit!;
+    _methodUnit = resolvedUnit.unit;
     _methodUtils = CorrectionUtils(resolvedUnit);
 
     if (methodNode is MethodDeclaration) {
diff --git a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
index b8535bd..f768861 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/move_file.dart
@@ -71,7 +71,7 @@
   @override
   Future<SourceChange> createChange() async {
     var changeBuilder = ChangeBuilder(session: resolvedUnit.session);
-    var element = resolvedUnit.unit!.declaredElement;
+    var element = resolvedUnit.unit.declaredElement;
     if (element == null) {
       return changeBuilder.sourceChange;
     }
@@ -85,21 +85,21 @@
     if (element == libraryElement.definingCompilationUnit) {
       // Handle part-of directives in this library
       var libraryResult = await driver.currentSession
-          .getResolvedLibraryByElement2(libraryElement);
+          .getResolvedLibraryByElement(libraryElement);
       if (libraryResult is! ResolvedLibraryResult) {
         return changeBuilder.sourceChange;
       }
-      var definingUnitResult = libraryResult.units!.first;
-      for (var result in libraryResult.units!) {
+      var definingUnitResult = libraryResult.units.first;
+      for (var result in libraryResult.units) {
         if (result.isPart) {
-          var partOfs = result.unit!.directives
+          var partOfs = result.unit.directives
               .whereType<PartOfDirective>()
               .map((e) => e.uri)
               .whereNotNull()
               .where((uri) => _isRelativeUri(uri.stringValue));
           if (partOfs.isNotEmpty) {
             await changeBuilder.addDartFileEdit(
-                result.unit!.declaredElement!.source.fullName, (builder) {
+                result.unit.declaredElement!.source.fullName, (builder) {
               partOfs.forEach((uri) {
                 var newLocation =
                     pathContext.join(newDir, pathos.basename(newFile));
@@ -113,9 +113,8 @@
       }
 
       if (newDir != oldDir) {
-        await changeBuilder.addDartFileEdit(definingUnitResult.path!,
-            (builder) {
-          for (var directive in definingUnitResult.unit!.directives) {
+        await changeBuilder.addDartFileEdit(definingUnitResult.path, (builder) {
+          for (var directive in definingUnitResult.unit.directives) {
             if (directive is UriBasedDirective) {
               _updateUriReference(builder, directive, oldDir, newDir);
             }
@@ -124,7 +123,7 @@
       }
     } else if (newDir != oldDir) {
       // Otherwise, we need to update any relative part-of references.
-      var partOfs = resolvedUnit.unit!.directives
+      var partOfs = resolvedUnit.unit.directives
           .whereType<PartOfDirective>()
           .map((e) => e.uri)
           .whereNotNull()
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
index 422d944..91654f8 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_class_member.dart
@@ -334,9 +334,6 @@
         }
 
         var unit = result.unit;
-        if (unit == null) {
-          return const [];
-        }
 
         var collector = _LocalElementsCollector(name);
         unit.accept(collector);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart
index 5367235..f0b65ab 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_extension_member.dart
@@ -165,9 +165,6 @@
         }
 
         var unit = result.unit;
-        if (unit == null) {
-          return const [];
-        }
 
         var collector = _LocalElementsCollector(name);
         unit.accept(collector);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
index 2dfbd42..4042b04 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename_import.dart
@@ -108,7 +108,7 @@
   ImportDirective? _findNode() {
     var library = element.library;
     var path = library.source.fullName;
-    var unitResult = session.getParsedUnit2(path);
+    var unitResult = session.getParsedUnit(path);
     if (unitResult is! ParsedUnitResult) {
       return null;
     }
@@ -122,7 +122,7 @@
   /// it. Otherwise return `null`.
   SimpleIdentifier? _getInterpolationIdentifier(SourceReference reference) {
     var source = reference.element.source!;
-    var unitResult = session.getParsedUnit2(source.fullName);
+    var unitResult = session.getParsedUnit(source.fullName);
     if (unitResult is! ParsedUnitResult) {
       return null;
     }
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index 610be65..999bc4d 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -246,7 +246,7 @@
     var result = await driver.getResult2(filePath);
     if (result is ResolvedUnitResult) {
       var writer = AstWriter(buf);
-      result.unit!.accept(writer);
+      result.unit.accept(writer);
     } else {
       p(
           'An AST could not be produced for the file '
@@ -836,7 +836,7 @@
     var result = await driver.getResult2(filePath);
     CompilationUnitElement? compilationUnitElement;
     if (result is ResolvedUnitResult) {
-      compilationUnitElement = result.unit?.declaredElement;
+      compilationUnitElement = result.unit.declaredElement;
     }
     if (compilationUnitElement != null) {
       var writer = ElementWriter(buf);
diff --git a/pkg/analysis_server/lib/src/utilities/mocks.dart b/pkg/analysis_server/lib/src/utilities/mocks.dart
index 5022dcd..9c581cd 100644
--- a/pkg/analysis_server/lib/src/utilities/mocks.dart
+++ b/pkg/analysis_server/lib/src/utilities/mocks.dart
@@ -146,6 +146,8 @@
   plugin.AnalysisUpdateContentParams? analysisUpdateContentParams;
   plugin.RequestParams? broadcastedRequest;
   Map<PluginInfo, Future<plugin.Response>>? broadcastResults;
+  Map<PluginInfo, Future<plugin.Response>>? Function(plugin.RequestParams)?
+      handleRequest;
 
   @override
   List<PluginInfo> plugins = [];
@@ -192,7 +194,9 @@
       plugin.RequestParams params,
       {analyzer.ContextRoot? contextRoot}) {
     broadcastedRequest = params;
-    return broadcastResults ?? <PluginInfo, Future<plugin.Response>>{};
+    return handleRequest?.call(params) ??
+        broadcastResults ??
+        <PluginInfo, Future<plugin.Response>>{};
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/utilities/process.dart b/pkg/analysis_server/lib/src/utilities/process.dart
new file mode 100644
index 0000000..70ea179
--- /dev/null
+++ b/pkg/analysis_server/lib/src/utilities/process.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// 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 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+/// An abstraction over [Process] from 'dart:io' to allow mocking in tests.
+class ProcessRunner {
+  Future<ProcessResult> run(
+    String executable,
+    List<String> arguments, {
+    String? workingDirectory,
+    Map<String, String>? environment,
+    bool includeParentEnvironment = true,
+    bool runInShell = false,
+    Encoding? stdoutEncoding = systemEncoding,
+    Encoding? stderrEncoding = systemEncoding,
+  }) async {
+    return Process.run(
+      executable,
+      arguments,
+      workingDirectory: workingDirectory,
+      environment: environment,
+      includeParentEnvironment: includeParentEnvironment,
+      runInShell: runInShell,
+      stdoutEncoding: stdoutEncoding,
+      stderrEncoding: stderrEncoding,
+    );
+  }
+}
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index f628981..fb9d441 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -90,7 +90,7 @@
     var analysisContext = contextFor(testPackageRootPath);
     var files = analysisContext.contextRoot.analyzedFiles().toList();
     for (var path in files) {
-      await analysisContext.currentSession.getResolvedUnit2(path);
+      await analysisContext.currentSession.getResolvedUnit(path);
     }
   }
 
@@ -172,7 +172,7 @@
   Future<ResolvedUnitResult> resolveFile(String path) async {
     path = convertPath(path);
     var session = contextFor(path).currentSession;
-    return await session.getResolvedUnit2(path) as ResolvedUnitResult;
+    return await session.getResolvedUnit(path) as ResolvedUnitResult;
   }
 
   @mustCallSuper
diff --git a/pkg/analysis_server/test/abstract_single_unit.dart b/pkg/analysis_server/test/abstract_single_unit.dart
index e479d9c..b18416c 100644
--- a/pkg/analysis_server/test/abstract_single_unit.dart
+++ b/pkg/analysis_server/test/abstract_single_unit.dart
@@ -70,10 +70,10 @@
   }
 
   Future<void> resolveTestFile() async {
-    var result = await session.getResolvedUnit2(testFile) as ResolvedUnitResult;
+    var result = await session.getResolvedUnit(testFile) as ResolvedUnitResult;
     testAnalysisResult = result;
-    testCode = result.content!;
-    testUnit = result.unit!;
+    testCode = result.content;
+    testUnit = result.unit;
     if (verifyNoTestUnitErrors) {
       expect(result.errors.where((AnalysisError error) {
         return error.errorCode != HintCode.DEAD_CODE &&
diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart
index 53ba68b..ff64169 100644
--- a/pkg/analysis_server/test/edit/fixes_test.dart
+++ b/pkg/analysis_server/test/edit/fixes_test.dart
@@ -73,7 +73,7 @@
     var fixes = plugin.AnalysisErrorFixes(AnalysisError(
         AnalysisErrorSeverity.ERROR,
         AnalysisErrorType.HINT,
-        Location('', 0, 0, 0, 0, 0, 0),
+        Location('', 0, 0, 0, 0, endLine: 0, endColumn: 0),
         'message',
         'code'));
     var result = plugin.EditGetFixesResult(<plugin.AnalysisErrorFixes>[fixes]);
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 3c0e282..3c3eecb 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -1104,15 +1104,16 @@
 ///   "length": int
 ///   "startLine": int
 ///   "startColumn": int
-///   "endLine": int
-///   "endColumn": int
+///   "endLine": optional int
+///   "endColumn": optional int
 /// }
 final Matcher isLocation = LazyMatcher(() => MatchesJsonObject('Location', {
       'file': isFilePath,
       'offset': isInt,
       'length': isInt,
       'startLine': isInt,
-      'startColumn': isInt,
+      'startColumn': isInt
+    }, optionalFields: {
       'endLine': isInt,
       'endColumn': isInt
     }));
diff --git a/pkg/analysis_server/test/lsp/client_configuration_test.dart b/pkg/analysis_server/test/lsp/client_configuration_test.dart
new file mode 100644
index 0000000..86788dc
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/client_configuration_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// 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:analysis_server/src/lsp/client_configuration.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ClientConfigurationTest);
+  });
+}
+
+@reflectiveTest
+class ClientConfigurationTest with ResourceProviderMixin {
+  void test_folderConfig() {
+    final folder = convertPath('/home/test');
+    final file = convertPath('/home/test/file.dart');
+    final config = LspClientConfiguration();
+    config.replace(
+      {'lineLength': 100},
+      {
+        folder: {'lineLength': 200}
+      },
+    );
+    expect(config.forResource(file).lineLength, equals(200));
+  }
+
+  void test_folderConfig_globalFallback() {
+    final file = convertPath('/home/test/file.dart');
+    final config = LspClientConfiguration();
+    config.replace({'lineLength': 100}, {});
+    // Should fall back to the global config.
+    expect(config.forResource(file).lineLength, equals(100));
+  }
+
+  void test_folderConfig_nested() {
+    final folderOne = convertPath('/one');
+    final folderTwo = convertPath('/one/two');
+    final folderThree = convertPath('/one/two/three');
+    final file = convertPath('/one/two/three/file.dart');
+    final config = LspClientConfiguration();
+    config.replace(
+      {'lineLength': 50},
+      {
+        folderOne: {'lineLength': 100},
+        folderThree: {'lineLength': 300},
+        folderTwo: {'lineLength': 200},
+      },
+    );
+    // Should use the inner-most folder (folderThree).
+    expect(config.forResource(file).lineLength, equals(300));
+  }
+
+  void test_globalConfig() {
+    final config = LspClientConfiguration();
+    config.replace({'lineLength': 100}, {});
+    expect(config.global.lineLength, equals(100));
+  }
+}
diff --git a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
index 67323f9..2797109 100644
--- a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
@@ -7,6 +7,8 @@
 import 'package:analysis_server/lsp_protocol/protocol_custom_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
 import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:collection/collection.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -166,6 +168,87 @@
     expect(codeActions, isEmpty);
   }
 
+  Future<void> test_plugin() async {
+    // This code should get an assist to replace 'foo' with 'bar'.'
+    const content = '[[foo]]';
+    const expectedContent = 'bar';
+
+    final pluginResult = plugin.EditGetAssistsResult([
+      plugin.PrioritizedSourceChange(
+        0,
+        plugin.SourceChange(
+          "Change 'foo' to 'bar'",
+          edits: [
+            plugin.SourceFileEdit(mainFilePath, 0,
+                edits: [plugin.SourceEdit(0, 3, 'bar')])
+          ],
+          id: 'fooToBar',
+        ),
+      )
+    ]);
+    configureTestPlugin(
+      handler: (request) =>
+          request is plugin.EditGetAssistsParams ? pluginResult : null,
+    );
+
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+    );
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final assist = findEditAction(codeActions,
+        CodeActionKind('refactor.fooToBar'), "Change 'foo' to 'bar'")!;
+
+    final edit = assist.edit!;
+    expect(edit.changes, isNotNull);
+
+    // Ensure applying the changes will give us the expected content.
+    final contents = {
+      mainFilePath: withoutMarkers(content),
+    };
+    applyChanges(contents, edit.changes!);
+    expect(contents[mainFilePath], equals(expectedContent));
+  }
+
+  Future<void> test_plugin_sortsWithServer() async {
+    // Produces a server assist of "Convert to single quoted string" (with a
+    // priority of 30).
+    const content = 'import "[[dart:async]]";';
+
+    // Provide two plugin results that should sort either side of the server assist.
+    final pluginResult = plugin.EditGetAssistsResult([
+      plugin.PrioritizedSourceChange(10, plugin.SourceChange('Low')),
+      plugin.PrioritizedSourceChange(100, plugin.SourceChange('High')),
+    ]);
+    configureTestPlugin(
+      handler: (request) =>
+          request is plugin.EditGetAssistsParams ? pluginResult : null,
+    );
+
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+    );
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeActionTitles = codeActions.map((action) =>
+        action.map((command) => command.title, (action) => action.title));
+
+    expect(
+      codeActionTitles,
+      containsAllInOrder([
+        'High',
+        'Convert to single quoted string',
+        'Low',
+      ]),
+    );
+  }
+
   Future<void> test_snippetTextEdits_supported() async {
     // This tests experimental support for including Snippets in TextEdits.
     // https://github.com/rust-analyzer/rust-analyzer/blob/b35559a2460e7f0b2b79a7029db0c5d4e0acdb44/docs/dev/lsp-extensions.md#snippet-textedit
diff --git a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
index 2a9184a..925b13b 100644
--- a/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_fixes_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
+import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
 import 'package:linter/src/rules.dart';
 import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
@@ -350,6 +352,111 @@
     final codeActions = await getCodeActions(otherFileUri.toString());
     expect(codeActions, isEmpty);
   }
+
+  Future<void> test_plugin() async {
+    // This code should get a fix to replace 'foo' with 'bar'.'
+    const content = '[[foo]]';
+    const expectedContent = 'bar';
+
+    final pluginResult = plugin.EditGetFixesResult([
+      plugin.AnalysisErrorFixes(
+        plugin.AnalysisError(
+          plugin.AnalysisErrorSeverity.ERROR,
+          plugin.AnalysisErrorType.HINT,
+          plugin.Location(mainFilePath, 0, 3, 0, 0),
+          "Do not use 'foo'",
+          'do_not_use_foo',
+        ),
+        fixes: [
+          plugin.PrioritizedSourceChange(
+            0,
+            plugin.SourceChange(
+              "Change 'foo' to 'bar'",
+              edits: [
+                plugin.SourceFileEdit(mainFilePath, 0,
+                    edits: [plugin.SourceEdit(0, 3, 'bar')])
+              ],
+              id: 'fooToBar',
+            ),
+          )
+        ],
+      )
+    ]);
+    configureTestPlugin(
+      handler: (request) =>
+          request is plugin.EditGetFixesParams ? pluginResult : null,
+    );
+
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
+    );
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final assist = findEditAction(codeActions,
+        CodeActionKind('quickfix.fooToBar'), "Change 'foo' to 'bar'")!;
+
+    final edit = assist.edit!;
+    expect(edit.changes, isNotNull);
+
+    // Ensure applying the changes will give us the expected content.
+    final contents = {
+      mainFilePath: withoutMarkers(content),
+    };
+    applyChanges(contents, edit.changes!);
+    expect(contents[mainFilePath], equals(expectedContent));
+  }
+
+  Future<void> test_plugin_sortsWithServer() async {
+    // Produces a server fix for removing unused import with a default
+    // priority of 50.
+    const content = '''
+[[import]] 'dart:convert';
+''';
+
+    // Provide two plugin results that should sort either side of the server fix.
+    final pluginResult = plugin.EditGetFixesResult([
+      plugin.AnalysisErrorFixes(
+        plugin.AnalysisError(
+          plugin.AnalysisErrorSeverity.ERROR,
+          plugin.AnalysisErrorType.HINT,
+          plugin.Location(mainFilePath, 0, 3, 0, 0),
+          'Dummy error',
+          'dummy',
+        ),
+        fixes: [
+          plugin.PrioritizedSourceChange(10, plugin.SourceChange('Low')),
+          plugin.PrioritizedSourceChange(100, plugin.SourceChange('High')),
+        ],
+      )
+    ]);
+    configureTestPlugin(
+      handler: (request) =>
+          request is plugin.EditGetFixesParams ? pluginResult : null,
+    );
+
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.QuickFix]),
+    );
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final codeActionTitles = codeActions.map((action) =>
+        action.map((command) => command.title, (action) => action.title));
+
+    expect(
+      codeActionTitles,
+      containsAllInOrder([
+        'High',
+        'Remove unused import',
+        'Low',
+      ]),
+    );
+  }
 }
 
 @reflectiveTest
diff --git a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
index 5ebc918..e8921f7 100644
--- a/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_refactor_test.dart
@@ -20,10 +20,76 @@
     defineReflectiveTests(ExtractVariableRefactorCodeActionsTest);
     defineReflectiveTests(InlineLocalVariableRefactorCodeActionsTest);
     defineReflectiveTests(InlineMethodRefactorCodeActionsTest);
+    defineReflectiveTests(ConvertGetterToMethodCodeActionsTest);
+    defineReflectiveTests(ConvertMethodToGetterCodeActionsTest);
   });
 }
 
 @reflectiveTest
+class ConvertGetterToMethodCodeActionsTest extends AbstractCodeActionsTest {
+  final refactorTitle = 'Convert Getter to Method';
+
+  Future<void> test_refactor() async {
+    const content = '''
+int get ^test => 42;
+main() {
+  var a = test;
+  var b = test;
+}
+''';
+    const expectedContent = '''
+int test() => 42;
+main() {
+  var a = test();
+  var b = test();
+}
+''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        position: positionFromMarker(content));
+    final codeAction =
+        findCommand(codeActions, Commands.performRefactor, refactorTitle)!;
+
+    await verifyCodeActionEdits(
+        codeAction, withoutMarkers(content), expectedContent);
+  }
+}
+
+@reflectiveTest
+class ConvertMethodToGetterCodeActionsTest extends AbstractCodeActionsTest {
+  final refactorTitle = 'Convert Method to Getter';
+
+  Future<void> test_refactor() async {
+    const content = '''
+int ^test() => 42;
+main() {
+  var a = test();
+  var b = test();
+}
+''';
+    const expectedContent = '''
+int get test => 42;
+main() {
+  var a = test;
+  var b = test;
+}
+''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        position: positionFromMarker(content));
+    final codeAction =
+        findCommand(codeActions, Commands.performRefactor, refactorTitle)!;
+
+    await verifyCodeActionEdits(
+        codeAction, withoutMarkers(content), expectedContent);
+  }
+}
+
+@reflectiveTest
 class ExtractMethodRefactorCodeActionsTest extends AbstractCodeActionsTest {
   final extractMethodTitle = 'Extract Method';
 
@@ -176,7 +242,12 @@
 }
     ''';
     newFile(mainFilePath, content: withoutMarkers(content));
-    await initialize();
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+        emptyTextDocumentClientCapabilities,
+        [CodeActionKind.Empty], // Support everything (empty prefix matches all)
+      ),
+    );
 
     final ofKind = (CodeActionKind kind) => getCodeActions(
           mainFileUri.toString(),
@@ -184,13 +255,31 @@
           kinds: [kind],
         );
 
-    // The code above will return a RefactorExtract that should be included
-    // by both Refactor and RefactorExtract, but not RefactorExtractFoo or
-    // RefactorRewrite
-    expect(await ofKind(CodeActionKind.Refactor), isNotEmpty);
-    expect(await ofKind(CodeActionKind.RefactorExtract), isNotEmpty);
-    expect(await ofKind(CodeActionKind('refactor.extract.foo')), isEmpty);
-    expect(await ofKind(CodeActionKind.RefactorRewrite), isEmpty);
+    // Helper that requests CodeActions for [kind] and ensures all results
+    // returned have either an equal kind, or a kind that is prefixed with the
+    // requested kind followed by a dot.
+    Future<void> checkResults(CodeActionKind kind) async {
+      final results = await ofKind(kind);
+      for (final result in results) {
+        final resultKind = result.map(
+          (cmd) => throw 'Expected CodeAction, got Command: ${cmd.title}',
+          (action) => action.kind,
+        );
+        expect(
+          '$resultKind',
+          anyOf([
+            equals('$kind'),
+            startsWith('$kind.'),
+          ]),
+        );
+      }
+    }
+
+    // Check a few of each that will produces multiple matches and no matches.
+    await checkResults(CodeActionKind.Refactor);
+    await checkResults(CodeActionKind.RefactorExtract);
+    await checkResults(CodeActionKind('refactor.extract.foo'));
+    await checkResults(CodeActionKind.RefactorRewrite);
   }
 
   Future<void> test_generatesNames() async {
diff --git a/pkg/analysis_server/test/lsp/completion.dart b/pkg/analysis_server/test/lsp/completion.dart
index 75c85b1..6d70a26 100644
--- a/pkg/analysis_server/test/lsp/completion.dart
+++ b/pkg/analysis_server/test/lsp/completion.dart
@@ -8,6 +8,9 @@
 import 'server_abstract.dart';
 
 mixin CompletionTestMixin on AbstractLspAnalysisServerTest {
+  /// The last set of completion results fetched.
+  List<CompletionItem> completionResults = [];
+
   int sortTextSorter(CompletionItem item1, CompletionItem item2) =>
       (item1.sortText ?? item1.label).compareTo(item2.sortText ?? item2.label);
 
@@ -40,23 +43,24 @@
     if (openCloseFile) {
       await openFile(fileUri, withoutMarkers(content));
     }
-    final res = await getCompletion(fileUri, positionFromMarker(content));
+    completionResults =
+        await getCompletion(fileUri, positionFromMarker(content));
     if (openCloseFile) {
       await closeFile(fileUri);
     }
 
     // Sort the completions by sortText and filter to those we expect, so the ordering
     // can be compared.
-    final sortedResults = res
+    final sortedResults = completionResults
         .where((r) => expectCompletions.contains(r.label))
         .toList()
-          ..sort(sortTextSorter);
+      ..sort(sortTextSorter);
 
     expect(sortedResults.map((item) => item.label), equals(expectCompletions));
 
     // Check the edits apply correctly.
     if (applyEditsFor != null) {
-      var item = res.singleWhere((c) => c.label == applyEditsFor);
+      var item = completionResults.singleWhere((c) => c.label == applyEditsFor);
       final insertFormat = item.insertTextFormat;
 
       if (resolve) {
diff --git a/pkg/analysis_server/test/lsp/completion_yaml_test.dart b/pkg/analysis_server/test/lsp/completion_yaml_test.dart
index 9d26755..52bf479 100644
--- a/pkg/analysis_server/test/lsp/completion_yaml_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_yaml_test.dart
@@ -2,6 +2,8 @@
 // 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 'dart:io';
+
 import 'package:analysis_server/src/services/pub/pub_api.dart';
 import 'package:http/http.dart';
 import 'package:linter/src/rules.dart';
@@ -367,7 +369,7 @@
     );
   }
 
-  Future<void> test_package_version() async {
+  Future<void> test_package_versions_fromApi() async {
     httpClient.sendHandler = (BaseRequest request) async {
       if (request.url.path.startsWith(PubApi.packageNameListPath)) {
         return Response(samplePackageList, 200);
@@ -418,6 +420,163 @@
     );
   }
 
+  Future<void> test_package_versions_fromPubOutdated() async {
+    final json = r'''
+    {
+      "packages": [
+        {
+          "package":    "one",
+          "latest":     { "version": "3.2.1" },
+          "resolvable": { "version": "1.2.4" }
+        }
+      ]
+    }
+    ''';
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, json, '');
+
+    final content = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+  one: ^''';
+
+    final expected = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+  one: ^1.2.4''';
+
+    await initialize();
+    await openFile(pubspecFileUri, withoutMarkers(content));
+    await pumpEventQueue(times: 500);
+
+    await verifyCompletions(
+      pubspecFileUri,
+      content,
+      expectCompletions: ['^1.2.4', '^3.2.1'],
+      applyEditsFor: '^1.2.4',
+      expectedContent: expected,
+      openCloseFile: false,
+    );
+  }
+
+  Future<void> test_package_versions_fromPubOutdated_afterChange() async {
+    final initialJson = r'''
+    {
+      "packages": [
+        {
+          "package":    "one",
+          "latest":     { "version": "3.2.1" },
+          "resolvable": { "version": "1.2.3" }
+        }
+      ]
+    }
+    ''';
+    final updatedJson = r'''
+    {
+      "packages": [
+        {
+          "package":    "one",
+          "latest":     { "version": "2.1.0" },
+          "resolvable": { "version": "2.3.4" }
+        }
+      ]
+    }
+    ''';
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, initialJson, '');
+
+    final content = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+  one: ^''';
+
+    final expected = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+  one: ^2.3.4''';
+
+    newFile(pubspecFilePath, content: content);
+    await initialize();
+    await openFile(pubspecFileUri, withoutMarkers(content));
+    await pumpEventQueue(times: 500);
+
+    // Modify the underlying file which should trigger an update of the
+    // cached data.
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, updatedJson, '');
+    modifyFile(pubspecFilePath, '$content# trailing comment');
+    await pumpEventQueue(times: 500);
+
+    await verifyCompletions(
+      pubspecFileUri,
+      content,
+      expectCompletions: ['^2.3.4', '^2.1.0'],
+      applyEditsFor: '^2.3.4',
+      expectedContent: expected,
+      openCloseFile: false,
+    );
+
+    // Also veryify the detail fields were populated as expected.
+    expect(
+      completionResults.singleWhere((c) => c.label == '^2.3.4').detail,
+      equals('latest compatible'),
+    );
+    expect(
+      completionResults.singleWhere((c) => c.label == '^2.1.0').detail,
+      equals('latest'),
+    );
+  }
+
+  Future<void> test_package_versions_fromPubOutdated_afterDelete() async {
+    final initialJson = r'''
+    {
+      "packages": [
+        {
+          "package":    "one",
+          "latest":     { "version": "3.2.1" },
+          "resolvable": { "version": "1.2.3" }
+        }
+      ]
+    }
+    ''';
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, initialJson, '');
+
+    final content = '''
+name: foo
+version: 1.0.0
+
+dependencies:
+  one: ^''';
+
+    newFile(pubspecFilePath, content: content);
+    await initialize();
+    await openFile(pubspecFileUri, withoutMarkers(content));
+    await pumpEventQueue(times: 500);
+
+    // Delete the underlying file which should trigger eviction of the cache.
+    deleteFile(pubspecFilePath);
+    await pumpEventQueue(times: 500);
+
+    await verifyCompletions(
+      pubspecFileUri,
+      content,
+      expectCompletions: [],
+      openCloseFile: false,
+    );
+
+    // There should have been no version numbers.
+    expect(completionResults, isEmpty);
+  }
+
   Future<void> test_topLevel() async {
     final content = '''
 version: 1.0.0
diff --git a/pkg/analysis_server/test/lsp/diagnostic_test.dart b/pkg/analysis_server/test/lsp/diagnostic_test.dart
index 0f7ecf1..96c7f5a 100644
--- a/pkg/analysis_server/test/lsp/diagnostic_test.dart
+++ b/pkg/analysis_server/test/lsp/diagnostic_test.dart
@@ -30,12 +30,15 @@
     final pluginError = plugin.AnalysisError(
       plugin.AnalysisErrorSeverity.ERROR,
       plugin.AnalysisErrorType.STATIC_TYPE_WARNING,
-      plugin.Location(pluginAnalyzedFilePath, 0, 6, 0, 0, 0, 6),
+      plugin.Location(pluginAnalyzedFilePath, 0, 6, 0, 0,
+          endLine: 0, endColumn: 6),
       'Test error from plugin',
       'ERR1',
       contextMessages: [
-        plugin.DiagnosticMessage('Related error',
-            plugin.Location(pluginAnalyzedFilePath, 31, 4, 1, 12, 1, 16))
+        plugin.DiagnosticMessage(
+            'Related error',
+            plugin.Location(pluginAnalyzedFilePath, 31, 4, 1, 12,
+                endLine: 1, endColumn: 16))
       ],
     );
     final pluginResult =
@@ -317,7 +320,7 @@
     final pluginError = plugin.AnalysisError(
       plugin.AnalysisErrorSeverity.ERROR,
       plugin.AnalysisErrorType.STATIC_TYPE_WARNING,
-      plugin.Location(mainFilePath, 0, 1, 0, 0, 0, 1),
+      plugin.Location(mainFilePath, 0, 1, 0, 0, endLine: 0, endColumn: 1),
       pluginErrorMessage,
       'ERR1',
     );
diff --git a/pkg/analysis_server/test/lsp/format_test.dart b/pkg/analysis_server/test/lsp/format_test.dart
index 741a740..5ba380f 100644
--- a/pkg/analysis_server/test/lsp/format_test.dart
+++ b/pkg/analysis_server/test/lsp/format_test.dart
@@ -309,6 +309,97 @@
     await expectFormattedContents(mainFileUri, contents, expectedLongLines);
   }
 
+  Future<void> test_lineLength_outsideWorkspaceFolders() async {
+    const contents = '''
+main() {
+  print('123456789 ''123456789 ''123456789 ');
+}
+''';
+    const expectedContents = '''
+main() {
+  print(
+      '123456789 '
+      '123456789 '
+      '123456789 ');
+}
+''';
+
+    await provideConfig(
+      () => initialize(
+        // Use empty roots so the test file is not inside any known
+        // WorkspaceFolder.
+        allowEmptyRootUri: true,
+        workspaceCapabilities: withDidChangeConfigurationDynamicRegistration(
+            withConfigurationSupport(emptyWorkspaceClientCapabilities)),
+      ),
+      // Global config (this should be used).
+      {'lineLength': 10},
+    );
+    await openFile(mainFileUri, contents);
+    await expectFormattedContents(mainFileUri, contents, expectedContents);
+  }
+
+  Future<void> test_lineLength_workspaceFolderSpecified() async {
+    const contents = '''
+main() {
+  print('123456789 ''123456789 ''123456789 ');
+}
+''';
+    const expectedContents = '''
+main() {
+  print(
+      '123456789 '
+      '123456789 '
+      '123456789 ');
+}
+''';
+
+    await provideConfig(
+      () => initialize(
+          workspaceCapabilities: withDidChangeConfigurationDynamicRegistration(
+              withConfigurationSupport(emptyWorkspaceClientCapabilities))),
+      // Global config.
+      {'lineLength': 200},
+      folderConfig: {
+        // WorkspaceFolder config for this project (this should be used).
+        projectFolderPath: {'lineLength': 10},
+      },
+    );
+    await openFile(mainFileUri, contents);
+    await expectFormattedContents(mainFileUri, contents, expectedContents);
+  }
+
+  Future<void> test_lineLength_workspaceFolderUnspecified() async {
+    const contents = '''
+main() {
+  print('123456789 ''123456789 ''123456789 ');
+}
+''';
+    const expectedContents = '''
+main() {
+  print(
+      '123456789 '
+      '123456789 '
+      '123456789 ');
+}
+''';
+
+    await provideConfig(
+      () => initialize(
+          workspaceCapabilities: withDidChangeConfigurationDynamicRegistration(
+              withConfigurationSupport(emptyWorkspaceClientCapabilities))),
+      // Global config (this should be used).
+      {'lineLength': 10},
+      folderConfig: {
+        // WorkspaceFolder config for this project that doesn't specific
+        // lineLength.
+        projectFolderPath: {'someOtherValue': 'foo'},
+      },
+    );
+    await openFile(mainFileUri, contents);
+    await expectFormattedContents(mainFileUri, contents, expectedContents);
+  }
+
   Future<void> test_minimalEdits_addWhitespace() async {
     // Check we only get one edit to add the required whitespace and not
     // an entire document replacement.
diff --git a/pkg/analysis_server/test/lsp/pub_package_service_test.dart b/pkg/analysis_server/test/lsp/pub_package_service_test.dart
index b00f285..c22a0f5 100644
--- a/pkg/analysis_server/test/lsp/pub_package_service_test.dart
+++ b/pkg/analysis_server/test/lsp/pub_package_service_test.dart
@@ -2,10 +2,16 @@
 // 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 'dart:io';
+
 import 'package:analysis_server/src/services/pub/pub_api.dart';
+import 'package:analysis_server/src/services/pub/pub_command.dart';
 import 'package:analysis_server/src/services/pub/pub_package_service.dart';
 import 'package:analyzer/instrumentation/service.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:collection/collection.dart';
 import 'package:http/http.dart';
+import 'package:path/path.dart' as path;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -15,6 +21,7 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(PubApiTest);
+    defineReflectiveTests(PubCommandTest);
     defineReflectiveTests(PubPackageServiceTest);
   });
 }
@@ -78,6 +85,168 @@
 }
 
 @reflectiveTest
+class PubCommandTest with ResourceProviderMixin {
+  late MockProcessRunner processRunner;
+  late PubCommand pubCommand;
+  late String pubspecPath, pubspec2Path;
+
+  void setUp() {
+    pubspecPath = convertPath('/home/project/pubspec.yaml');
+    pubspec2Path = convertPath('/home/project2/pubspec.yaml');
+    processRunner = MockProcessRunner();
+    pubCommand = PubCommand(InstrumentationService.NULL_SERVICE, processRunner);
+  }
+
+  Future<void> test_doesNotRunConcurrently() async {
+    var isRunning = false;
+    processRunner.runHandler = (executable, args, {dir, env}) async {
+      expect(isRunning, isFalse,
+          reason: 'pub commands should not run concurrently');
+      isRunning = true;
+      await pumpEventQueue(times: 500);
+      isRunning = false;
+      return ProcessResult(0, 0, '', '');
+    };
+    await Future.wait([
+      pubCommand.outdatedVersions(pubspecPath),
+      pubCommand.outdatedVersions(pubspecPath),
+    ]);
+  }
+
+  Future<void> test_outdated_args() async {
+    processRunner.runHandler = (executable, args, {dir, env}) {
+      var expectedPubPath = path.join(
+        path.dirname(Platform.resolvedExecutable),
+        Platform.isWindows ? 'pub.bat' : 'pub',
+      );
+      expect(executable, equals(expectedPubPath));
+      expect(
+          args,
+          equals([
+            'outdated',
+            '--show-all',
+            '--json',
+          ]));
+      expect(dir, equals(convertPath('/home/project')));
+      expect(
+          env!['PUB_ENVIRONMENT'],
+          anyOf(equals('analysis_server.pub_api'),
+              endsWith(':analysis_server.pub_api')));
+      return ProcessResult(0, 0, '', '');
+    };
+    await pubCommand.outdatedVersions(pubspecPath);
+  }
+
+  Future<void> test_outdated_invalidJson() async {
+    processRunner.runHandler = (String executable, List<String> args,
+            {dir, env}) =>
+        ProcessResult(1, 0, 'NOT VALID JSON', '');
+    final result = await pubCommand.outdatedVersions(pubspecPath);
+    expect(result, isEmpty);
+  }
+
+  Future<void> test_outdated_missingFields() async {
+    final validJson = r'''
+    {
+      "packages": [
+        {
+          "package":    "foo",
+          "current":    { "version": "1.0.0" },
+          "upgradable": { "version": "2.0.0" },
+          "resolvable": { }
+        }
+      ]
+    }
+    ''';
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, validJson, '');
+    final result = await pubCommand.outdatedVersions(pubspecPath);
+    expect(result, hasLength(1));
+    final package = result.first;
+    expect(package.packageName, equals('foo'));
+    expect(package.currentVersion, equals('1.0.0'));
+    expect(package.upgradableVersion, equals('2.0.0'));
+    expect(package.resolvableVersion, isNull);
+    expect(package.latestVersion, isNull);
+  }
+
+  Future<void> test_outdated_multiplePubspecs() async {
+    final pubspecJson1 = r'''
+    {
+      "packages": [
+        {
+          "package":    "foo",
+          "resolvable": { "version": "1.1.1" }
+        }
+      ]
+    }
+    ''';
+    final pubspecJson2 = r'''
+    {
+      "packages": [
+        {
+          "package":    "foo",
+          "resolvable": { "version": "2.2.2" }
+        }
+      ]
+    }
+    ''';
+
+    processRunner.runHandler = (executable, args, {dir, env}) {
+      // Return different json based on the directory we were invoked in.
+      final json =
+          dir == path.dirname(pubspecPath) ? pubspecJson1 : pubspecJson2;
+      return ProcessResult(1, 0, json, '');
+    };
+    final result1 = await pubCommand.outdatedVersions(pubspecPath);
+    final result2 = await pubCommand.outdatedVersions(pubspec2Path);
+    expect(result1.first.resolvableVersion, equals('1.1.1'));
+    expect(result2.first.resolvableVersion, equals('2.2.2'));
+  }
+
+  Future<void> test_outdated_nonZeroExitCode() async {
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 123, '{}', '');
+    final result = await pubCommand.outdatedVersions(pubspecPath);
+    expect(result, isEmpty);
+  }
+
+  Future<void> test_validJson() async {
+    final validJson = r'''
+    {
+      "packages": [
+        {
+          "package":    "foo",
+          "current":    { "version": "1.0.0" },
+          "upgradable": { "version": "2.0.0" },
+          "resolvable": { "version": "3.0.0" },
+          "latest":     { "version": "4.0.0" }
+        },
+        {
+          "package":    "bar",
+          "current":    { "version": "1.0.0" },
+          "upgradable": { "version": "2.0.0" },
+          "resolvable": { "version": "3.0.0" },
+          "latest":     { "version": "4.0.0" }
+        }
+      ]
+    }
+    ''';
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, validJson, '');
+    final result = await pubCommand.outdatedVersions(pubspecPath);
+    expect(result, hasLength(2));
+    result.forEachIndexed((index, package) {
+      expect(package.packageName, equals(index == 0 ? 'foo' : 'bar'));
+      expect(package.currentVersion, equals('1.0.0'));
+      expect(package.upgradableVersion, equals('2.0.0'));
+      expect(package.resolvableVersion, equals('3.0.0'));
+      expect(package.latestVersion, equals('4.0.0'));
+    });
+  }
+}
+
+@reflectiveTest
 class PubPackageServiceTest extends AbstractLspAnalysisServerTest {
   /// A sample API response for package names. This should match the JSON served
   /// at https://pub.dev/api/package-name-completion-data.
@@ -194,13 +363,13 @@
   Future<void> test_packageCache_initializesOnPubspecOpen() async {
     await initialize();
 
-    expect(server.pubPackageService.isRunning, isFalse);
+    expect(server.pubPackageService.isPackageNamesTimerRunning, isFalse);
     expect(server.pubPackageService.packageCache, isNull);
     expectPackages([]);
     await openFile(pubspecFileUri, '');
     await pumpEventQueue();
 
-    expect(server.pubPackageService.isRunning, isTrue);
+    expect(server.pubPackageService.isPackageNamesTimerRunning, isTrue);
     expect(server.pubPackageService.packageCache, isNotNull);
     expectPackages([]);
   }
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index ad2d20b..2e49ae5 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -48,6 +48,7 @@
   late MockLspServerChannel channel;
   late TestPluginManager pluginManager;
   late LspAnalysisServer server;
+  late MockProcessRunner processRunner;
   late MockHttpClient httpClient;
 
   /// The number of context builds that had already occurred the last time
@@ -62,12 +63,25 @@
   DiscoveredPluginInfo configureTestPlugin({
     plugin.ResponseResult? respondWith,
     plugin.Notification? notification,
+    plugin.ResponseResult? Function(plugin.RequestParams)? handler,
     Duration respondAfter = Duration.zero,
   }) {
     final info = DiscoveredPluginInfo('a', 'b', 'c', server.notificationManager,
         server.instrumentationService);
     pluginManager.plugins.add(info);
 
+    if (handler != null) {
+      pluginManager.handleRequest = (request) {
+        final response = handler(request);
+        return response == null
+            ? null
+            : <PluginInfo, Future<plugin.Response>>{
+                info: Future.delayed(respondAfter)
+                    .then((_) => response.toResponse('-', 1))
+              };
+      };
+    }
+
     if (respondWith != null) {
       pluginManager.broadcastResults = <PluginInfo, Future<plugin.Response>>{
         info: Future.delayed(respondAfter)
@@ -151,6 +165,7 @@
 
   void setUp() {
     httpClient = MockHttpClient();
+    processRunner = MockProcessRunner();
     channel = MockLspServerChannel(debugPrintCommunication);
     // Create an SDK in the mock file system.
     MockSdk(resourceProvider: resourceProvider);
@@ -162,7 +177,8 @@
         DartSdkManager(convertPath('/sdk')),
         CrashReportingAttachmentsBuilder.empty,
         InstrumentationService.NULL_SERVICE,
-        httpClient: httpClient);
+        httpClient: httpClient,
+        processRunner: processRunner);
     server.pluginManager = pluginManager;
 
     projectFolderPath = convertPath('/home/test');
@@ -1458,14 +1474,34 @@
 
   /// Calls the supplied function and responds to any `workspace/configuration`
   /// request with the supplied config.
-  Future<ResponseMessage> provideConfig(Future<ResponseMessage> Function() f,
-      FutureOr<Map<String, dynamic>> config) {
+  Future<ResponseMessage> provideConfig(
+    Future<ResponseMessage> Function() f,
+    FutureOr<Map<String, Object?>> globalConfig, {
+    FutureOr<Map<String, Map<String, Object?>>>? folderConfig,
+  }) {
     return handleExpectedRequest<ResponseMessage, ConfigurationParams,
-        List<Map<String, dynamic>>>(
+        List<Map<String, Object?>>>(
       Method.workspace_configuration,
       ConfigurationParams.fromJson,
       f,
-      handler: (configurationParams) async => [await config],
+      handler: (configurationParams) async {
+        // We must respond to the request for config with items that match the
+        // request. For any item in the request without a folder, we will return
+        // the global config. For any item in the request with a folder we will
+        // return the config for that item in the map, or fall back to the global
+        // config if it does not exist.
+        final global = await globalConfig;
+        final folders = await folderConfig;
+        return configurationParams.items.map(
+          (requestedConfig) {
+            final uri = requestedConfig.scopeUri;
+            final path = uri != null ? Uri.parse(uri).toFilePath() : null;
+            // Use the config the test provided for this path, or fall back to
+            // global.
+            return (folders != null ? folders[path] : null) ?? global;
+          },
+        ).toList();
+      },
     );
   }
 
diff --git a/pkg/analysis_server/test/lsp/test_all.dart b/pkg/analysis_server/test/lsp/test_all.dart
index fbdd56c..752d3f1 100644
--- a/pkg/analysis_server/test/lsp/test_all.dart
+++ b/pkg/analysis_server/test/lsp/test_all.dart
@@ -8,6 +8,7 @@
 import 'analyzer_status_test.dart' as analyzer_status;
 import 'cancel_request_test.dart' as cancel_request;
 import 'change_workspace_folders_test.dart' as change_workspace_folders;
+import 'client_configuration_test.dart' as client_configuration;
 import 'closing_labels_test.dart' as closing_labels;
 import 'code_actions_assists_test.dart' as code_actions_assists;
 import 'code_actions_fixes_test.dart' as code_actions_fixes;
@@ -48,6 +49,7 @@
     analyzer_status.main();
     cancel_request.main();
     change_workspace_folders.main();
+    client_configuration.main();
     closing_labels.main();
     code_actions_assists.main();
     code_actions_fixes.main();
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index d6cfa2c..e1f3ecd 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -3,9 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
 
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/utilities/process.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:http/http.dart' as http;
 import 'package:test/test.dart';
@@ -47,6 +50,32 @@
   }
 }
 
+class MockProcessRunner implements ProcessRunner {
+  FutureOr<ProcessResult> Function(String executable, List<String> arguments,
+          {String? dir, Map<String, String>? env})? runHandler =
+      (executable, arguments, {dir, env}) => throw UnimplementedError();
+
+  @override
+  dynamic noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
+
+  @override
+  Future<ProcessResult> run(
+    String executable,
+    List<String> arguments, {
+    String? workingDirectory,
+    Map<String, String>? environment,
+    bool includeParentEnvironment = true,
+    bool runInShell = false,
+    Encoding? stdoutEncoding = systemEncoding,
+    Encoding? stderrEncoding = systemEncoding,
+  }) async {
+    return runHandler!(executable, arguments,
+        dir: workingDirectory, env: environment);
+  }
+}
+
 class MockSource implements Source {
   @override
   final String fullName;
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 49cae54..ac31994 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -361,7 +361,7 @@
   Map<String, FileResult> fileResults = {};
 
   void addFileResult(FileResult result) {
-    fileResults[result.path!] = result;
+    fileResults[result.path] = result;
   }
 
   @override
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index 0a651c2..546faf8 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -536,7 +536,7 @@
       DartCompletionRequest request);
 
   Future computeSuggestions({int times = 200}) async {
-    result = await session.getResolvedUnit2(testFile) as ResolvedUnitResult;
+    result = await session.getResolvedUnit(testFile) as ResolvedUnitResult;
     var baseRequest = CompletionRequestImpl(
         result, completionOffset, CompletionPerformance());
 
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
index 4dd13ee..257fb5b 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
@@ -50,7 +50,7 @@
 
     // Build the request
     var baseRequest = CompletionRequestImpl(
-        await session.getResolvedUnit2(testFile) as ResolvedUnitResult,
+        await session.getResolvedUnit(testFile) as ResolvedUnitResult,
         completionOffset,
         CompletionPerformance());
     await baseRequest.performance.runRequestOperation((performance) async {
diff --git a/pkg/analysis_server/test/services/correction/organize_directives_test.dart b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
index a147a80..7696ad5 100644
--- a/pkg/analysis_server/test/services/correction/organize_directives_test.dart
+++ b/pkg/analysis_server/test/services/correction/organize_directives_test.dart
@@ -582,8 +582,8 @@
 
   Future<void> _computeUnitAndErrors(String code) async {
     addTestSource(code);
-    var result = await session.getResolvedUnit2(testFile) as ResolvedUnitResult;
-    testUnit = result.unit!;
+    var result = await session.getResolvedUnit(testFile) as ResolvedUnitResult;
+    testUnit = result.unit;
     testErrors = result.errors;
   }
 }
diff --git a/pkg/analysis_server/test/services/correction/sort_members_test.dart b/pkg/analysis_server/test/services/correction/sort_members_test.dart
index a766800..e434168 100644
--- a/pkg/analysis_server/test/services/correction/sort_members_test.dart
+++ b/pkg/analysis_server/test/services/correction/sort_members_test.dart
@@ -925,7 +925,7 @@
 
   Future<void> _parseTestUnit(String code) async {
     addTestSource(code);
-    var result = session.getParsedUnit2(testFile) as ParsedUnitResult;
+    var result = session.getParsedUnit(testFile) as ParsedUnitResult;
     testUnit = result.unit;
   }
 }
diff --git a/pkg/analysis_server/test/services/correction/status_test.dart b/pkg/analysis_server/test/services/correction/status_test.dart
index 41c0eec..055c0e4 100644
--- a/pkg/analysis_server/test/services/correction/status_test.dart
+++ b/pkg/analysis_server/test/services/correction/status_test.dart
@@ -98,7 +98,7 @@
   }
 
   void test_addFatalError_withLocation() {
-    var location = Location('/test.dart', 1, 2, 3, 4, 5, 6);
+    var location = Location('/test.dart', 1, 2, 3, 4, endLine: 5, endColumn: 6);
     var refactoringStatus = RefactoringStatus();
     // initial state
     expect(refactoringStatus.severity, null);
@@ -210,7 +210,7 @@
   }
 
   void test_newError() {
-    var location = Location('/test.dart', 1, 2, 3, 4, 5, 6);
+    var location = Location('/test.dart', 1, 2, 3, 4, endLine: 5, endColumn: 6);
     var refactoringStatus = RefactoringStatus.error('msg', location);
     var problem = refactoringStatus.problem!;
     var problemLocation = problem.location!;
diff --git a/pkg/analysis_server/test/services/refactoring/move_file_test.dart b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
index ad4b7ef..5094b24 100644
--- a/pkg/analysis_server/test/services/refactoring/move_file_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
@@ -67,7 +67,7 @@
     // testAnalysisResult manually here, the path is referenced through the
     // referenced File object to run on Windows:
     testAnalysisResult =
-        await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+        await session.getResolvedUnit(file.path) as ResolvedUnitResult;
 
     _createRefactoring('/home/test/lib/222/new_name.dart', oldFile: file.path);
     await _assertSuccessfulRefactoring();
@@ -90,7 +90,7 @@
     // testAnalysisResult manually here, the path is referenced through the
     // referenced File object to run on Windows:
     testAnalysisResult =
-        await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+        await session.getResolvedUnit(file.path) as ResolvedUnitResult;
 
     _createRefactoring('/home/test0/test1/test3/lib/111/name.dart',
         oldFile: file.path);
@@ -114,7 +114,7 @@
     // testAnalysisResult manually here, the path is referenced through the
     // referenced File object to run on Windows:
     testAnalysisResult =
-        await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+        await session.getResolvedUnit(file.path) as ResolvedUnitResult;
 
     _createRefactoring('/home/test0/test1/test2/test3/lib/111/name.dart',
         oldFile: file.path);
@@ -138,7 +138,7 @@
     // testAnalysisResult manually here, the path is referenced through the
     // referenced File object to run on Windows:
     testAnalysisResult =
-        await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+        await session.getResolvedUnit(file.path) as ResolvedUnitResult;
 
     _createRefactoring('/home/test0/test1/lib/111/name.dart',
         oldFile: file.path);
@@ -160,7 +160,7 @@
     // testAnalysisResult manually here, the path is referenced through the
     // referenced File object to run on Windows:
     testAnalysisResult =
-        await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+        await session.getResolvedUnit(file.path) as ResolvedUnitResult;
 
     _createRefactoring('/home/test/lib/222/new_name.dart', oldFile: file.path);
     await _assertSuccessfulRefactoring();
@@ -181,7 +181,7 @@
     // testAnalysisResult manually here, the path is referenced through the
     // referenced File object to run on Windows:
     testAnalysisResult =
-        await session.getResolvedUnit2(file.path) as ResolvedUnitResult;
+        await session.getResolvedUnit(file.path) as ResolvedUnitResult;
 
     _createRefactoring('/home/test/lib/new_name.dart', oldFile: file.path);
     await _assertSuccessfulRefactoring();
diff --git a/pkg/analysis_server/test/services/search/search_engine_test.dart b/pkg/analysis_server/test/services/search/search_engine_test.dart
index 99aa552..512db98 100644
--- a/pkg/analysis_server/test/services/search/search_engine_test.dart
+++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -41,8 +41,8 @@
     result = await resolveFile(path);
     expect(result.state, ResultState.VALID);
 
-    findNode = FindNode(result.content!, result.unit!);
-    findElement = FindElement(result.unit!);
+    findNode = FindNode(result.content, result.unit);
+    findElement = FindElement(result.unit);
   }
 
   /// Put the [code] into the test file, and resolve it.
diff --git a/pkg/analysis_server/test/src/cider/completion_test.dart b/pkg/analysis_server/test/src/cider/completion_test.dart
index b83e4ef..7a50af7 100644
--- a/pkg/analysis_server/test/src/cider/completion_test.dart
+++ b/pkg/analysis_server/test/src/cider/completion_test.dart
@@ -806,7 +806,7 @@
   /// for completion we don't resolve unnecessary node.
   void _configureToCheckNotResolved({required Set<String> identifiers}) {
     _testResolvedUnit = (resolvedUnitResult) {
-      var unit = resolvedUnitResult.unit!;
+      var unit = resolvedUnitResult.unit;
       unit.accept(
         FunctionAstVisitor(
           simpleIdentifier: (node) {
diff --git a/pkg/analysis_server/test/src/cider/fixes_test.dart b/pkg/analysis_server/test/src/cider/fixes_test.dart
index fa71e62..4e57e14 100644
--- a/pkg/analysis_server/test/src/cider/fixes_test.dart
+++ b/pkg/analysis_server/test/src/cider/fixes_test.dart
@@ -48,7 +48,7 @@
 ''');
 
     // The file was resolved only once, even though we have 2 errors.
-    expect(fileResolver.testView!.resolvedFiles, [convertPath(testPath)]);
+    expect(fileResolver.testView!.resolvedLibraries, [convertPath(testPath)]);
   }
 
   Future<void> test_createMethod() async {
diff --git a/pkg/analysis_server/test/src/cider/rename_test.dart b/pkg/analysis_server/test/src/cider/rename_test.dart
index 31c96d5..028aaea 100644
--- a/pkg/analysis_server/test/src/cider/rename_test.dart
+++ b/pkg/analysis_server/test/src/cider/rename_test.dart
@@ -107,6 +107,65 @@
     expect(refactor.refactoringElement.offset, _correctionContext.offset);
   }
 
+  void test_checkName_function() {
+    var result = _checkName(r'''
+int ^foo() => 2;
+''', 'bar');
+
+    expect(result, isNotNull);
+    expect(result?.status.problems.length, 0);
+    expect(result?.oldName, 'foo');
+  }
+
+  void test_checkName_local() {
+    var result = _checkName(r'''
+void foo() {
+  var ^a = 0; var b = a + 1;
+}
+''', 'bar');
+
+    expect(result, isNotNull);
+    expect(result?.status.problems.length, 0);
+    expect(result?.oldName, 'a');
+  }
+
+  void test_checkName_local_invalid() {
+    var result = _checkName(r'''
+void foo() {
+  var ^a = 0; var b = a + 1;
+}
+''', 'Aa');
+
+    expect(result, isNotNull);
+    expect(result?.status.problems.length, 1);
+    expect(result?.oldName, 'a');
+  }
+
+  void test_checkName_parameter() {
+    var result = _checkName(r'''
+void foo(String ^a) {
+  var b = a + 1;
+}
+''', 'bar');
+
+    expect(result, isNotNull);
+    expect(result?.status.problems.length, 0);
+    expect(result?.oldName, 'a');
+  }
+
+  CheckNameResponse? _checkName(String content, String newName) {
+    _updateFile(content);
+
+    return CiderRenameComputer(
+      fileResolver,
+    ).checkNewName(
+      convertPath(testPath),
+      _correctionContext.line,
+      _correctionContext.character,
+      newName,
+    );
+  }
+
   CanRenameResponse? _compute(String content) {
     _updateFile(content);
 
diff --git a/pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart b/pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart
index 37057d0..83a9954 100644
--- a/pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/closing_labels_computer_test.dart
@@ -398,8 +398,8 @@
   Future<List<ClosingLabel>> _computeElements(String sourceContent) async {
     newFile(sourcePath, content: sourceContent);
     var result =
-        await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
-    var computer = DartUnitClosingLabelsComputer(result.lineInfo, result.unit!);
+        await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
+    var computer = DartUnitClosingLabelsComputer(result.lineInfo, result.unit);
     return computer.compute();
   }
 }
diff --git a/pkg/analysis_server/test/src/computer/folding_computer_test.dart b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
index 62e7ad9..f63607d 100644
--- a/pkg/analysis_server/test/src/computer/folding_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/folding_computer_test.dart
@@ -582,8 +582,8 @@
   Future<List<FoldingRegion>> _computeRegions(String sourceContent) async {
     newFile(sourcePath, content: sourceContent);
     var result =
-        await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
-    var computer = DartUnitFoldingComputer(result.lineInfo, result.unit!);
+        await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
+    var computer = DartUnitFoldingComputer(result.lineInfo, result.unit);
     return computer.compute();
   }
 }
diff --git a/pkg/analysis_server/test/src/computer/highlights_computer_test.dart b/pkg/analysis_server/test/src/computer/highlights_computer_test.dart
index 2012268..46a6c44 100644
--- a/pkg/analysis_server/test/src/computer/highlights_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/highlights_computer_test.dart
@@ -114,7 +114,7 @@
     this.content = content;
     newFile(sourcePath, content: content);
     var result =
-        await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
+        await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
 
     if (hasErrors) {
       expect(result.errors, isNotEmpty);
@@ -122,7 +122,7 @@
       expect(result.errors, isEmpty);
     }
 
-    var computer = DartUnitHighlightsComputer(result.unit!);
+    var computer = DartUnitHighlightsComputer(result.unit);
     highlights = computer.compute();
   }
 }
diff --git a/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart b/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart
index ebdde35..fed52b7 100644
--- a/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/import_elements_computer_test.dart
@@ -50,7 +50,7 @@
   Future<void> createBuilder(String content) async {
     originalContent = content;
     newFile(path, content: content);
-    var result = await session.getResolvedUnit2(path) as ResolvedUnitResult;
+    var result = await session.getResolvedUnit(path) as ResolvedUnitResult;
     computer = ImportElementsComputer(resourceProvider, result);
   }
 
diff --git a/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart b/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart
index 2cd24c1..a63d9bc 100644
--- a/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/imported_elements_computer_test.dart
@@ -471,9 +471,9 @@
     // TODO(brianwilkerson) Automatically extract the selection from the content.
     newFile(sourcePath, content: content);
     var result =
-        await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
+        await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
     var computer = ImportedElementsComputer(
-        result.unit!, content.indexOf(selection), selection.length);
+        result.unit, content.indexOf(selection), selection.length);
     importedElements = computer.compute();
   }
 }
diff --git a/pkg/analysis_server/test/src/computer/outline_computer_test.dart b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
index 6db141d..a005ff2 100644
--- a/pkg/analysis_server/test/src/computer/outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/outline_computer_test.dart
@@ -32,7 +32,7 @@
     testCode = code;
     newFile(testPath, content: code);
     var resolveResult =
-        await session.getResolvedUnit2(testPath) as ResolvedUnitResult;
+        await session.getResolvedUnit(testPath) as ResolvedUnitResult;
     return DartUnitOutlineComputer(
       resolveResult,
       withBasicFlutter: true,
diff --git a/pkg/analysis_server/test/src/computer/selection_range_computer_test.dart b/pkg/analysis_server/test/src/computer/selection_range_computer_test.dart
index cbb6cf8..27e9e7f 100644
--- a/pkg/analysis_server/test/src/computer/selection_range_computer_test.dart
+++ b/pkg/analysis_server/test/src/computer/selection_range_computer_test.dart
@@ -194,8 +194,8 @@
       String sourceContent, int offset) async {
     newFile(sourcePath, content: sourceContent);
     var result =
-        await session.getResolvedUnit2(sourcePath) as ResolvedUnitResult;
-    var computer = DartSelectionRangeComputer(result.unit!, offset);
+        await session.getResolvedUnit(sourcePath) as ResolvedUnitResult;
+    var computer = DartSelectionRangeComputer(result.unit, offset);
     return computer.compute();
   }
 
diff --git a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
index f186301..c224c12 100644
--- a/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
+++ b/pkg/analysis_server/test/src/flutter/flutter_outline_computer_test.dart
@@ -517,7 +517,7 @@
     testCode = code;
     newFile(testPath, content: code);
     resolveResult =
-        await session.getResolvedUnit2(testPath) as ResolvedUnitResult;
+        await session.getResolvedUnit(testPath) as ResolvedUnitResult;
     computer = FlutterOutlineComputer(resolveResult);
     return computer.compute();
   }
diff --git a/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart b/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
index 631dcac..4ad6049 100644
--- a/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
+++ b/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
@@ -79,7 +79,8 @@
   Element element(int stringIndex, int intIndex, {ElementKind? kind}) =>
       Element(kind ?? ElementKind.CLASS, strings[stringIndex++], intIndex++,
           location: Location(fileName(stringIndex++), intIndex++, intIndex++,
-              intIndex++, intIndex++, intIndex++, intIndex++),
+              intIndex++, intIndex++,
+              endLine: intIndex++, endColumn: intIndex++),
           parameters: strings[stringIndex++],
           returnType: strings[stringIndex++],
           typeParameters: strings[stringIndex++]);
@@ -99,8 +100,8 @@
       intIndex++,
       intIndex++,
       intIndex++,
-      intIndex++,
-      intIndex++);
+      endLine: intIndex++,
+      endColumn: intIndex++);
 
   /// On return, increment [stringIndex] by 5 and [intIndex] by 7.
   Occurrences occurrences(int stringIndex, int intIndex) {
diff --git a/pkg/analysis_server/test/src/plugin/result_merger_test.dart b/pkg/analysis_server/test/src/plugin/result_merger_test.dart
index 934e335..9affdc3 100644
--- a/pkg/analysis_server/test/src/plugin/result_merger_test.dart
+++ b/pkg/analysis_server/test/src/plugin/result_merger_test.dart
@@ -29,7 +29,8 @@
     AnalysisError createError(int offset) {
       var severity = AnalysisErrorSeverity.ERROR;
       var type = AnalysisErrorType.HINT;
-      var location = Location('test.dart', offset, 2, 3, 4, 5, 6);
+      var location =
+          Location('test.dart', offset, 2, 3, 4, endLine: 5, endColumn: 6);
       return AnalysisError(severity, type, location, '', '');
     }
 
@@ -68,7 +69,8 @@
     AnalysisError createError(int offset) {
       var severity = AnalysisErrorSeverity.ERROR;
       var type = AnalysisErrorType.HINT;
-      var location = Location('test.dart', offset, 2, 3, 4, 5, 6);
+      var location =
+          Location('test.dart', offset, 2, 3, 4, endLine: 5, endColumn: 6);
       return AnalysisError(severity, type, location, '', '');
     }
 
@@ -265,7 +267,7 @@
 
   void test_mergeOutline() {
     Element element(ElementKind kind, int offset) {
-      var location = Location('', offset, 0, 0, 0, 0, 0);
+      var location = Location('', offset, 0, 0, 0, endLine: 0, endColumn: 0);
       return Element(kind, '', 0, location: location);
     }
 
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
index 4f4923f..4eab94d 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
@@ -2,8 +2,11 @@
 // 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 'dart:io';
+
 import 'package:analysis_server/src/services/completion/yaml/pubspec_generator.dart';
 import 'package:analysis_server/src/services/pub/pub_api.dart';
+import 'package:analysis_server/src/services/pub/pub_command.dart';
 import 'package:analysis_server/src/services/pub/pub_package_service.dart';
 import 'package:analyzer/instrumentation/service.dart';
 import 'package:http/http.dart';
@@ -22,6 +25,7 @@
 @reflectiveTest
 class PubspecGeneratorTest extends YamlGeneratorTest {
   late MockHttpClient httpClient;
+  late MockProcessRunner processRunner;
 
   late PubPackageService pubPackageService;
 
@@ -34,10 +38,12 @@
 
   void setUp() {
     httpClient = MockHttpClient();
+    processRunner = MockProcessRunner();
     pubPackageService = PubPackageService(
         InstrumentationService.NULL_SERVICE,
         resourceProvider,
-        PubApi(InstrumentationService.NULL_SERVICE, httpClient, null));
+        PubApi(InstrumentationService.NULL_SERVICE, httpClient, null),
+        PubCommand(InstrumentationService.NULL_SERVICE, processRunner));
   }
 
   void tearDown() {
@@ -339,4 +345,46 @@
 ''');
     assertSuggestion('two: ');
   }
+
+  void test_packageVersion() async {
+    final json = r'''
+    {
+      "packages": [
+        {
+          "package":    "one",
+          "latest":     { "version": "3.2.1" },
+          "resolvable": { "version": "1.2.4" }
+        }
+      ]
+    }
+    ''';
+    processRunner.runHandler =
+        (executable, args, {dir, env}) => ProcessResult(1, 0, json, '');
+
+    pubPackageService.beginCachePreloads([convertPath('/home/test/$fileName')]);
+    await pumpEventQueue(times: 500);
+
+    getCompletions('''
+dependencies:
+  one: ^
+''');
+    assertSuggestion('^1.2.4');
+    assertSuggestion('^3.2.1');
+  }
+
+  /// Ensure in a repo with a DEPS file like the SDK, we do not run pub
+  /// processes to cache the version numbers.
+  void test_packageVersion_withDEPSfile() async {
+    var didRun = false;
+    processRunner.runHandler = (executable, args, {dir, env}) {
+      didRun = true;
+      return ProcessResult(1, 0, '', '');
+    };
+
+    newFile('/home/DEPS');
+    pubPackageService.beginCachePreloads([convertPath('/home/test/$fileName')]);
+    await pumpEventQueue(times: 500);
+
+    expect(didRun, isFalse);
+  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart
index 0120636..fc933c1 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart
@@ -136,6 +136,17 @@
 ''');
   }
 
+  Future<void> test_sync() async {
+    // This code is erroneous; the test ensures there is no error thrown when
+    // computing assists.
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode('''
+Iterable<String> f() sync {}
+''');
+    await assertNoAssistAt('{}');
+  }
+
+
   Future<void> test_syncStar() async {
     await resolveTestCode('''
 Iterable<String> f() sync* {}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
index 5103661..f6ccc74 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/code_template_test.dart
@@ -72,7 +72,7 @@
 }
 void g(int x, int y) {}
 ''');
-    var unit = testAnalysisResult.unit!;
+    var unit = testAnalysisResult.unit;
     var function = unit.declarations[0] as FunctionDeclaration;
     var body = function.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart
index e2c4988..4022696 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart
@@ -6,7 +6,6 @@
 import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_manager.dart';
 import 'package:analysis_server/src/services/correction/fix_internal.dart';
-import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -441,7 +440,7 @@
   Future<void> test_rename_removed() async {
     setPackageContent('''
 class C {
-  C.new([C c]);
+  C.updated([C c]);
 }
 ''');
     addPackageDataFile('''
@@ -455,7 +454,7 @@
     inClass: 'C'
   changes:
     - kind: 'rename'
-      newName: 'new'
+      newName: 'updated'
 ''');
     await resolveTestCode('''
 import '$importUri';
@@ -463,7 +462,7 @@
 ''');
     await assertHasFix('''
 import '$importUri';
-C c() => C.new(C.new());
+C c() => C.updated(C.updated());
 ''');
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_manager_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_manager_test.dart
index d182ab1..42d762b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_manager_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_manager_test.dart
@@ -36,7 +36,7 @@
     var testFile = convertPath('/home/test/lib/test.dart');
     addSource(testFile, '');
     var result = await session.getResolvedLibraryValid(testFile);
-    var sets = manager.forLibrary(result.element!);
+    var sets = manager.forLibrary(result.element);
     expect(sets, hasLength(2));
   }
 
@@ -47,7 +47,7 @@
     var testFile = convertPath('/home/test/lib/test.dart');
     addSource(testFile, '');
     var result = await session.getResolvedLibraryValid(testFile);
-    var sets = manager.forLibrary(result.element!);
+    var sets = manager.forLibrary(result.element);
     expect(sets, hasLength(0));
   }
 
@@ -70,6 +70,6 @@
 
 extension on AnalysisSession {
   Future<ResolvedLibraryResult> getResolvedLibraryValid(String path) async {
-    return await getResolvedLibrary2(path) as ResolvedLibraryResult;
+    return await getResolvedLibrary(path) as ResolvedLibraryResult;
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
index 366f8d1..00f2730 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -262,7 +262,7 @@
 
   Future<void> addUnimportedFile(String filePath, String content) async {
     addSource(filePath, content);
-    var result = await session.getResolvedUnit2(convertPath(filePath));
+    var result = await session.getResolvedUnit(convertPath(filePath));
     extensionCache.cacheFromResult(result as ResolvedUnitResult);
   }
 
diff --git a/pkg/analysis_server/test/src/services/flutter/widget_description.dart b/pkg/analysis_server/test/src/services/flutter/widget_description.dart
index 8cdbfff..33f47ad 100644
--- a/pkg/analysis_server/test/src/services/flutter/widget_description.dart
+++ b/pkg/analysis_server/test/src/services/flutter/widget_description.dart
@@ -24,7 +24,7 @@
     expect(fileEdit.file, testAnalysisResult.path);
 
     var actual = SourceEdit.applySequence(
-      testAnalysisResult.content!,
+      testAnalysisResult.content,
       fileEdit.edits,
     );
     expect(actual, expected);
@@ -50,7 +50,7 @@
 
   Future<protocol.FlutterGetWidgetDescriptionResult?> getDescription(
       String search) async {
-    var content = testAnalysisResult.content!;
+    var content = testAnalysisResult.content;
 
     var offset = content.indexOf(search);
     if (offset == -1) {
diff --git a/pkg/analysis_server/test/stress/completion/completion_runner.dart b/pkg/analysis_server/test/stress/completion/completion_runner.dart
index 542d8fe..16d1e81 100644
--- a/pkg/analysis_server/test/stress/completion/completion_runner.dart
+++ b/pkg/analysis_server/test/stress/completion/completion_runner.dart
@@ -80,11 +80,11 @@
         }
         fileCount++;
         output.write('.');
-        var result = await context.currentSession.getResolvedUnit2(path)
+        var result = await context.currentSession.getResolvedUnit(path)
             as ResolvedUnitResult;
-        var content = result.content!;
+        var content = result.content;
         var lineInfo = result.lineInfo;
-        var identifiers = _identifiersIn(result.unit!);
+        var identifiers = _identifiersIn(result.unit);
 
         for (var identifier in identifiers) {
           identifierCount++;
@@ -94,7 +94,7 @@
                 content.substring(identifier.end);
             resourceProvider.setOverlay(path,
                 content: modifiedContent, modificationStamp: stamp++);
-            result = await context.currentSession.getResolvedUnit2(path)
+            result = await context.currentSession.getResolvedUnit(path)
                 as ResolvedUnitResult;
           }
 
diff --git a/pkg/analysis_server/test/test_all.dart b/pkg/analysis_server/test/test_all.dart
index 4c5a33f..3e5769c 100644
--- a/pkg/analysis_server/test/test_all.dart
+++ b/pkg/analysis_server/test/test_all.dart
@@ -26,6 +26,7 @@
 import 'socket_server_test.dart' as socket_server;
 import 'src/test_all.dart' as src;
 import 'tool/test_all.dart' as tool;
+import 'verify_no_solo_test.dart' as verify_no_solo;
 import 'verify_sorted_test.dart' as verify_sorted;
 import 'verify_tests_test.dart' as verify_tests;
 
@@ -52,6 +53,7 @@
     socket_server.main();
     src.main();
     tool.main();
+    verify_no_solo.main();
     verify_sorted.main();
     verify_tests.main();
     defineReflectiveSuite(() {
diff --git a/pkg/analysis_server/test/verify_no_solo_test.dart b/pkg/analysis_server/test/verify_no_solo_test.dart
new file mode 100644
index 0000000..150c731
--- /dev/null
+++ b/pkg/analysis_server/test/verify_no_solo_test.dart
@@ -0,0 +1,109 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// 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/dart/analysis/analysis_context_collection.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/session.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/physical_file_system.dart';
+import 'package:analyzer_utilities/package_root.dart';
+import 'package:test/test.dart';
+
+void main() {
+  group('analysis_server', () {
+    buildTests(packagePath: 'analysis_server');
+  });
+
+  group('analyzer', () {
+    buildTests(packagePath: 'analyzer');
+  });
+
+  group('analyzer_cli', () {
+    buildTests(packagePath: 'analyzer_cli');
+  });
+
+  group('analyzer_plugin', () {
+    buildTests(packagePath: 'analyzer_plugin');
+  });
+}
+
+void buildTests({required String packagePath}) {
+  var provider = PhysicalResourceProvider.INSTANCE;
+  var pkgRootPath = provider.pathContext.normalize(packageRoot);
+
+  var testsPath = _toPlatformPath(pkgRootPath, '$packagePath/test');
+
+  var collection = AnalysisContextCollection(
+    includedPaths: <String>[testsPath],
+    resourceProvider: provider,
+  );
+  var contexts = collection.contexts;
+  if (contexts.length != 1) {
+    fail('The directory $testsPath contains multiple analysis contexts.');
+  }
+
+  test('no @soloTest', () {
+    var failures = <String>[];
+    buildTestsIn(contexts[0].currentSession, testsPath,
+        provider.getFolder(testsPath), failures);
+
+    if (failures.isNotEmpty) {
+      fail('@soloTest annotation found in:\n${failures.join('\n')}');
+    }
+  });
+}
+
+void buildTestsIn(AnalysisSession session, String testDirPath, Folder directory,
+    List<String> failures) {
+  var pathContext = session.resourceProvider.pathContext;
+  var children = directory.getChildren();
+  children.sort((first, second) => first.shortName.compareTo(second.shortName));
+  for (var child in children) {
+    if (child is Folder) {
+      buildTestsIn(session, testDirPath, child, failures);
+    } else if (child is File && child.shortName.endsWith('_test.dart')) {
+      var path = child.path;
+      var relativePath = pathContext.relative(path, from: testDirPath);
+
+      var result = session.getParsedUnit(path);
+      if (result is! ParsedUnitResult) {
+        fail('Could not parse $path');
+      }
+      var unit = result.unit;
+      var errors = result.errors;
+      if (errors.isNotEmpty) {
+        fail('Errors found when parsing $path');
+      }
+      var tracker = SoloTestTracker();
+      unit.accept(tracker);
+      if (tracker.found) {
+        failures.add(relativePath);
+      }
+    }
+  }
+}
+
+String _toPlatformPath(String pathPath, String relativePosixPath) {
+  var pathContext = PhysicalResourceProvider.INSTANCE.pathContext;
+  return pathContext.joinAll([
+    pathPath,
+    ...relativePosixPath.split('/'),
+  ]);
+}
+
+/// A [RecursiveAstVisitor] that tracks whether any node is annotated with
+/// an annotation named 'soloTest'.
+class SoloTestTracker extends RecursiveAstVisitor<void> {
+  bool found = false;
+
+  @override
+  void visitAnnotation(Annotation node) {
+    if (node.name.name == 'soloTest') {
+      found = true;
+    }
+    super.visitAnnotation(node);
+  }
+}
diff --git a/pkg/analysis_server/test/verify_sorted_test.dart b/pkg/analysis_server/test/verify_sorted_test.dart
index 9cf62ed..dc12ccc 100644
--- a/pkg/analysis_server/test/verify_sorted_test.dart
+++ b/pkg/analysis_server/test/verify_sorted_test.dart
@@ -134,7 +134,7 @@
       }
       var relativePath = pathContext.relative(path, from: testDirPath);
       test(relativePath, () {
-        var result = session.getParsedUnit2(path);
+        var result = session.getParsedUnit(path);
         if (result is! ParsedUnitResult) {
           fail('Could not parse $path');
         }
diff --git a/pkg/analysis_server/tool/code_completion/code_metrics.dart b/pkg/analysis_server/tool/code_completion/code_metrics.dart
index 5ff17b9..565a9fd 100644
--- a/pkg/analysis_server/tool/code_completion/code_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/code_metrics.dart
@@ -1394,7 +1394,7 @@
       if (file_paths.isDart(pathContext, filePath)) {
         try {
           var resolvedUnitResult =
-              await context.currentSession.getResolvedUnit2(filePath);
+              await context.currentSession.getResolvedUnit(filePath);
           //
           // Check for errors that cause the file to be skipped.
           //
@@ -1411,7 +1411,7 @@
             continue;
           }
 
-          resolvedUnitResult.unit!.accept(collector);
+          resolvedUnitResult.unit.accept(collector);
         } catch (exception) {
           print('Exception caught analyzing: "$filePath"');
           print(exception.toString());
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index d32c961..46638b1 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -1293,7 +1293,7 @@
     for (var filePath in context.contextRoot.analyzedFiles()) {
       if (file_paths.isDart(pathContext, filePath)) {
         try {
-          var result = await context.currentSession.getResolvedUnit2(filePath)
+          var result = await context.currentSession.getResolvedUnit(filePath)
               as ResolvedUnitResult;
 
           var analysisError = getFirstErrorOrNull(result);
@@ -1315,11 +1315,11 @@
     }
     for (var result in results) {
       _resolvedUnitResult = result;
-      var filePath = result.path!;
+      var filePath = result.path;
       // Use the ExpectedCompletionsVisitor to compute the set of expected
       // completions for this CompilationUnit.
       final visitor = ExpectedCompletionsVisitor(filePath);
-      _resolvedUnitResult.unit!.accept(visitor);
+      _resolvedUnitResult.unit.accept(visitor);
 
       for (var expectedCompletion in visitor.expectedCompletions) {
         var resolvedUnitResult = _resolvedUnitResult;
@@ -1328,14 +1328,14 @@
         // have the context reanalyze the file
         if (options.overlay != CompletionMetricsOptions.OVERLAY_NONE) {
           var overlayContents = _getOverlayContents(
-              _resolvedUnitResult.content!, expectedCompletion);
+              _resolvedUnitResult.content, expectedCompletion);
 
           _provider.setOverlay(filePath,
               content: overlayContents,
               modificationStamp: overlayModificationStamp++);
           context.driver.changeFile(filePath);
           resolvedUnitResult = await context.currentSession
-              .getResolvedUnit2(filePath) as ResolvedUnitResult;
+              .getResolvedUnit(filePath) as ResolvedUnitResult;
         }
 
         // As this point the completion suggestions are computed,
diff --git a/pkg/analysis_server/tool/code_completion/flutter_metrics.dart b/pkg/analysis_server/tool/code_completion/flutter_metrics.dart
index ee267a5..edab701 100644
--- a/pkg/analysis_server/tool/code_completion/flutter_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/flutter_metrics.dart
@@ -207,7 +207,7 @@
       if (file_paths.isDart(pathContext, filePath)) {
         try {
           var resolvedUnitResult =
-              await context.currentSession.getResolvedUnit2(filePath);
+              await context.currentSession.getResolvedUnit(filePath);
           //
           // Check for errors that cause the file to be skipped.
           //
@@ -224,7 +224,7 @@
             continue;
           }
 
-          resolvedUnitResult.unit!.accept(collector);
+          resolvedUnitResult.unit.accept(collector);
         } catch (exception, stackTrace) {
           print('');
           print('Exception caught analyzing: "$filePath"');
diff --git a/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart b/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart
index 6b0b3c1..8494fb4 100644
--- a/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart
+++ b/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart
@@ -184,7 +184,7 @@
       if (file_paths.isDart(pathContext, filePath)) {
         try {
           var resolvedUnitResult =
-              await context.currentSession.getResolvedUnit2(filePath);
+              await context.currentSession.getResolvedUnit(filePath);
           //
           // Check for errors that cause the file to be skipped.
           //
@@ -208,7 +208,7 @@
             continue;
           }
 
-          resolvedUnitResult.unit!.accept(collector);
+          resolvedUnitResult.unit.accept(collector);
         } catch (exception, stacktrace) {
           print('Exception caught analyzing: "$filePath"');
           print(exception);
diff --git a/pkg/analysis_server/tool/code_completion/relevance_metrics.dart b/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
index 0975c8a..8a24e94 100644
--- a/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/relevance_metrics.dart
@@ -1940,7 +1940,7 @@
       if (file_paths.isDart(pathContext, filePath)) {
         try {
           var resolvedUnitResult =
-              await context.currentSession.getResolvedUnit2(filePath);
+              await context.currentSession.getResolvedUnit(filePath);
           //
           // Check for errors that cause the file to be skipped.
           //
@@ -1964,7 +1964,7 @@
             continue;
           }
 
-          resolvedUnitResult.unit!.accept(collector);
+          resolvedUnitResult.unit.accept(collector);
         } catch (exception, stacktrace) {
           print('Exception caught analyzing: "$filePath"');
           print(exception);
diff --git a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart b/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
index 52b219e..3e2af94 100644
--- a/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
+++ b/pkg/analysis_server/tool/code_completion/relevance_table_generator.dart
@@ -317,7 +317,7 @@
 
   /// Initialize this collector prior to visiting the unit in the [result].
   void initializeFrom(ResolvedUnitResult result) {
-    unit = result.unit!;
+    unit = result.unit;
   }
 
   @override
@@ -1459,7 +1459,7 @@
       if (file_paths.isDart(pathContext, filePath)) {
         try {
           var resolvedUnitResult =
-              await context.currentSession.getResolvedUnit2(filePath);
+              await context.currentSession.getResolvedUnit(filePath);
           //
           // Check for errors that cause the file to be skipped.
           //
@@ -1484,7 +1484,7 @@
           }
 
           collector.initializeFrom(resolvedUnitResult);
-          resolvedUnitResult.unit!.accept(collector);
+          resolvedUnitResult.unit.accept(collector);
         } catch (exception, stacktrace) {
           print('Exception caught analyzing: "$filePath"');
           print(exception);
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index 5376013..bac9b69 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -94,8 +94,8 @@
 | textDocument/codeAction (organiseImports) | ✅ | ✅ | | ✅ | ✅ |
 | textDocument/codeAction (fixAll) | ✅ | ✅ | | ✅ | ✅ |
 | textDocument/codeAction (refactors) | ✅ | ✅ | | ✅ | ✅ |
-| textDocument/codeAction (assists) | ✅ | ✅ | | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `Refactor`
-| textDocument/codeAction (fixes) | ✅ | ✅ | | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `QuickFix`
+| textDocument/codeAction (assists) | ✅ | ✅ | ✅ | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `Refactor`
+| textDocument/codeAction (fixes) | ✅ | ✅ | ✅ | ✅ | ✅ | Only if the client advertises `codeActionLiteralSupport` with `QuickFix`
 | textDocument/codeLens | | | | | |
 | codeLens/resolve | | | | | |
 | textDocument/documentLink | | | | | |
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/Location.java b/pkg/analysis_server/tool/spec/generated/java/types/Location.java
index 1df7d78..13e14bd 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/Location.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/Location.java
@@ -63,17 +63,17 @@
   /**
    * The one-based index of the line containing the character immediately following the range.
    */
-  private final int endLine;
+  private final Integer endLine;
 
   /**
    * The one-based index of the column containing the character immediately following the range.
    */
-  private final int endColumn;
+  private final Integer endColumn;
 
   /**
    * Constructor for {@link Location}.
    */
-  public Location(String file, int offset, int length, int startLine, int startColumn, int endLine, int endColumn) {
+  public Location(String file, int offset, int length, int startLine, int startColumn, Integer endLine, Integer endColumn) {
     this.file = file;
     this.offset = offset;
     this.length = length;
@@ -93,8 +93,8 @@
         other.length == length &&
         other.startLine == startLine &&
         other.startColumn == startColumn &&
-        other.endLine == endLine &&
-        other.endColumn == endColumn;
+        ObjectUtilities.equals(other.endLine, endLine) &&
+        ObjectUtilities.equals(other.endColumn, endColumn);
     }
     return false;
   }
@@ -105,8 +105,8 @@
     int length = jsonObject.get("length").getAsInt();
     int startLine = jsonObject.get("startLine").getAsInt();
     int startColumn = jsonObject.get("startColumn").getAsInt();
-    int endLine = jsonObject.get("endLine").getAsInt();
-    int endColumn = jsonObject.get("endColumn").getAsInt();
+    Integer endLine = jsonObject.get("endLine") == null ? null : jsonObject.get("endLine").getAsInt();
+    Integer endColumn = jsonObject.get("endColumn") == null ? null : jsonObject.get("endColumn").getAsInt();
     return new Location(file, offset, length, startLine, startColumn, endLine, endColumn);
   }
 
@@ -125,14 +125,14 @@
   /**
    * The one-based index of the column containing the character immediately following the range.
    */
-  public int getEndColumn() {
+  public Integer getEndColumn() {
     return endColumn;
   }
 
   /**
    * The one-based index of the line containing the character immediately following the range.
    */
-  public int getEndLine() {
+  public Integer getEndLine() {
     return endLine;
   }
 
@@ -191,8 +191,12 @@
     jsonObject.addProperty("length", length);
     jsonObject.addProperty("startLine", startLine);
     jsonObject.addProperty("startColumn", startColumn);
-    jsonObject.addProperty("endLine", endLine);
-    jsonObject.addProperty("endColumn", endColumn);
+    if (endLine != null) {
+      jsonObject.addProperty("endLine", endLine);
+    }
+    if (endColumn != null) {
+      jsonObject.addProperty("endColumn", endColumn);
+    }
     return jsonObject;
   }
 
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
index dfbd44c..76b7a2c 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
@@ -2884,8 +2884,8 @@
 ///   "length": int
 ///   "startLine": int
 ///   "startColumn": int
-///   "endLine": int
-///   "endColumn": int
+///   "endLine": optional int
+///   "endColumn": optional int
 /// }
 ///
 /// Clients may not extend, implement or mix-in this class.
@@ -2909,14 +2909,15 @@
 
   /// The one-based index of the line containing the character immediately
   /// following the range.
-  int endLine;
+  int? endLine;
 
   /// The one-based index of the column containing the character immediately
   /// following the range.
-  int endColumn;
+  int? endColumn;
 
-  Location(this.file, this.offset, this.length, this.startLine,
-      this.startColumn, this.endLine, this.endColumn);
+  Location(
+      this.file, this.offset, this.length, this.startLine, this.startColumn,
+      {this.endLine, this.endColumn});
 
   factory Location.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -2954,21 +2955,17 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, 'startColumn');
       }
-      int endLine;
+      int? endLine;
       if (json.containsKey('endLine')) {
         endLine = jsonDecoder.decodeInt(jsonPath + '.endLine', json['endLine']);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'endLine');
       }
-      int endColumn;
+      int? endColumn;
       if (json.containsKey('endColumn')) {
         endColumn =
             jsonDecoder.decodeInt(jsonPath + '.endColumn', json['endColumn']);
-      } else {
-        throw jsonDecoder.mismatch(jsonPath, 'endColumn');
       }
-      return Location(
-          file, offset, length, startLine, startColumn, endLine, endColumn);
+      return Location(file, offset, length, startLine, startColumn,
+          endLine: endLine, endColumn: endColumn);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'Location', json);
     }
@@ -2982,8 +2979,14 @@
     result['length'] = length;
     result['startLine'] = startLine;
     result['startColumn'] = startColumn;
-    result['endLine'] = endLine;
-    result['endColumn'] = endColumn;
+    var endLine = this.endLine;
+    if (endLine != null) {
+      result['endLine'] = endLine;
+    }
+    var endColumn = this.endColumn;
+    if (endColumn != null) {
+      result['endColumn'] = endColumn;
+    }
     return result;
   }
 
diff --git a/pkg/analysis_server_client/test/verify_sorted_test.dart b/pkg/analysis_server_client/test/verify_sorted_test.dart
index dfa4c4a..f4f4c57 100644
--- a/pkg/analysis_server_client/test/verify_sorted_test.dart
+++ b/pkg/analysis_server_client/test/verify_sorted_test.dart
@@ -55,7 +55,7 @@
       }
       var relativePath = pathContext.relative(path, from: testDirPath);
       test(relativePath, () {
-        var result = session.getParsedUnit2(path);
+        var result = session.getParsedUnit(path);
         if (result is! ParsedUnitResult) {
           fail('Could not parse $path');
         }
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index 6ccdf32..337ad88 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,20 @@
+## 2.1.0-dev
+* Changed `AnalysisResult.path` to be non-nullable.
+* Changed `ParsedLibraryResult.units` to be non-nullable.
+* Changed `ResolvedLibraryResult.element` to be non-nullable.
+* Changed `ResolvedLibraryResult.units` to be non-nullable.
+* Changed `ResolvedUnitResult.content` to be non-nullable.
+* Changed `ResolvedUnitResult.unit` to be non-nullable.
+* Deprecated and renamed `AnalysisSession.getXyz2()` into `getXyz()`.
+* Changed `AnalysisDriver.results` to `Stream<Object>`.
+  It used to always produce `ResolvedUnitResult`s, but sometimes its
+  `content` and `unit` were `null`, when the result actually had only errors.
+  Now it produces either `ResolvedUnitResult`, or `ErrorsResult`, or
+  some other results that might be added in the future.
+* Added `DartType.alias` with information about instantiated type alias.
+  The type alias element and arguments are present or absent together.
+* Deprecated `DartType.aliasElement` and `DartType.aliasArguments`.
+
 ## 2.0.0
 * Removed deprecated `Scope.lookup2()`.
 * Removed deprecated setters in API of AST.
diff --git a/pkg/analyzer/doc/tutorial/ast.md b/pkg/analyzer/doc/tutorial/ast.md
index 3e9e3fa..ed449d8 100644
--- a/pkg/analyzer/doc/tutorial/ast.md
+++ b/pkg/analyzer/doc/tutorial/ast.md
@@ -55,7 +55,7 @@
 
 ```dart
 void processFile(AnalysisSession session, String path) {
-  var result = session.getParsedUnit2(path);
+  var result = session.getParsedUnit(path);
   if (result is ParsedUnitResult) {
     CompilationUnit unit = result.unit;
   }
@@ -67,7 +67,7 @@
 
 ```dart
 void processFile(AnalysisSession session, String path) async {
-  var result = await session.getResolvedUnit2(path);
+  var result = await session.getResolvedUnit(path);
   if (result is ResolvedUnitResult) {
     CompilationUnit unit = result.unit;
   }
diff --git a/pkg/analyzer/doc/tutorial/element.md b/pkg/analyzer/doc/tutorial/element.md
index 6c5509f..912d65b 100644
--- a/pkg/analyzer/doc/tutorial/element.md
+++ b/pkg/analyzer/doc/tutorial/element.md
@@ -46,7 +46,7 @@
 
 ```dart
 void analyzeSingleFile(AnalysisSession session, String path) async {
-  var result = await session.getUnitElement2(path);
+  var result = await session.getUnitElement(path);
   if (result is UnitElementResult) {
     CompilationUnitElement element = result.element;
   }
diff --git a/pkg/analyzer/example/analyze.dart b/pkg/analyzer/example/analyze.dart
index a94f27e..72acdf5 100644
--- a/pkg/analyzer/example/analyze.dart
+++ b/pkg/analyzer/example/analyze.dart
@@ -32,7 +32,7 @@
         continue;
       }
 
-      final errorsResult = await context.currentSession.getErrors2(filePath);
+      final errorsResult = await context.currentSession.getErrors(filePath);
       if (errorsResult is ErrorsResult) {
         for (final error in errorsResult.errors) {
           if (error.errorCode.type != ErrorType.TODO) {
diff --git a/pkg/analyzer/lib/dart/analysis/results.dart b/pkg/analyzer/lib/dart/analysis/results.dart
index 287c470..13500ba 100644
--- a/pkg/analyzer/lib/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/dart/analysis/results.dart
@@ -17,9 +17,7 @@
 abstract class AnalysisResult {
   /// The absolute and normalized path of the file that was analyzed.
   /// If [state] is not [ResultState.VALID], throws [StateError].
-  ///
-  /// TODO(migration): should not be nullable
-  String? get path;
+  String get path;
 
   /// Return the session used to compute this result.
   /// If [state] is not [ResultState.VALID], throws [StateError].
@@ -164,9 +162,7 @@
 abstract class ParsedLibraryResult
     implements SomeParsedLibraryResult, AnalysisResult {
   /// The parsed units of the library.
-  ///
-  /// TODO(migration): should not be null, probably empty list
-  List<ParsedUnitResult>? get units;
+  List<ParsedUnitResult> get units;
 
   /// Return the declaration of the [element], or `null` if the [element]
   /// is synthetic. Throw [ArgumentError] if the [element] is not defined in
@@ -214,13 +210,13 @@
 abstract class ResolvedLibraryResult
     implements SomeResolvedLibraryResult, AnalysisResult {
   /// The element representing this library.
-  LibraryElement? get element;
+  LibraryElement get element;
 
   /// The type provider used when resolving the library.
   TypeProvider get typeProvider;
 
   /// The resolved units of the library.
-  List<ResolvedUnitResult>? get units;
+  List<ResolvedUnitResult> get units;
 
   /// Return the declaration of the [element], or `null` if the [element]
   /// is synthetic. Throw [ArgumentError] if the [element] is not defined in
@@ -235,7 +231,7 @@
 abstract class ResolvedUnitResult
     implements SomeResolvedUnitResult, AnalysisResultWithErrors {
   /// The content of the file that was scanned, parsed and resolved.
-  String? get content;
+  String get content;
 
   /// Return `true` if the file exists.
   bool get exists;
@@ -250,7 +246,7 @@
   TypeSystem get typeSystem;
 
   /// The fully resolved compilation unit for the [content].
-  CompilationUnit? get unit;
+  CompilationUnit get unit;
 }
 
 /// An indication of whether an analysis result is valid, and if not why.
diff --git a/pkg/analyzer/lib/dart/analysis/session.dart b/pkg/analyzer/lib/dart/analysis/session.dart
index 680ba37..ade0e8e 100644
--- a/pkg/analyzer/lib/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/dart/analysis/session.dart
@@ -35,47 +35,105 @@
   ///
   /// If the file cannot be analyzed by this session, then the result will have
   /// a result state indicating the nature of the problem.
+  Future<SomeErrorsResult> getErrors(String path);
+
+  /// Return a future that will complete with information about the errors
+  /// contained in the file with the given absolute, normalized [path].
+  ///
+  /// If the file cannot be analyzed by this session, then the result will have
+  /// a result state indicating the nature of the problem.
+  @Deprecated('Use getErrors() instead')
   Future<SomeErrorsResult> getErrors2(String path);
 
   /// Return information about the file at the given absolute, normalized
   /// [path].
+  SomeFileResult getFile(String path);
+
+  /// Return information about the file at the given absolute, normalized
+  /// [path].
+  @Deprecated('Use getFile() instead')
   SomeFileResult getFile2(String path);
 
   /// Return a future that will complete with information about the library
   /// element representing the library with the given [uri].
+  Future<SomeLibraryElementResult> getLibraryByUri(String uri);
+
+  /// Return a future that will complete with information about the library
+  /// element representing the library with the given [uri].
+  @Deprecated('Use getLibraryByUri() instead')
   Future<SomeLibraryElementResult> getLibraryByUri2(String uri);
 
   /// Return information about the results of parsing units of the library file
   /// with the given absolute, normalized [path].
+  SomeParsedLibraryResult getParsedLibrary(String path);
+
+  /// Return information about the results of parsing units of the library file
+  /// with the given absolute, normalized [path].
+  @Deprecated('Use getParsedLibrary() instead')
   SomeParsedLibraryResult getParsedLibrary2(String path);
 
   /// Return information about the results of parsing units of the library file
   /// with the given library [element].
+  SomeParsedLibraryResult getParsedLibraryByElement(LibraryElement element);
+
+  /// Return information about the results of parsing units of the library file
+  /// with the given library [element].
+  @Deprecated('Use getParsedLibraryByElement() instead')
   SomeParsedLibraryResult getParsedLibraryByElement2(LibraryElement element);
 
   /// Return information about the results of parsing the file with the given
   /// absolute, normalized [path].
+  SomeParsedUnitResult getParsedUnit(String path);
+
+  /// Return information about the results of parsing the file with the given
+  /// absolute, normalized [path].
+  @Deprecated('Use getParsedUnit() instead')
   SomeParsedUnitResult getParsedUnit2(String path);
 
   /// Return a future that will complete with information about the results of
   /// resolving all of the files in the library with the given absolute,
   /// normalized [path].
+  Future<SomeResolvedLibraryResult> getResolvedLibrary(String path);
+
+  /// Return a future that will complete with information about the results of
+  /// resolving all of the files in the library with the given absolute,
+  /// normalized [path].
+  @Deprecated('Use getResolvedLibrary() instead')
   Future<SomeResolvedLibraryResult> getResolvedLibrary2(String path);
 
   /// Return a future that will complete with information about the results of
   /// resolving all of the files in the library with the library [element].
   ///
   /// Throw [ArgumentError] if the [element] was not produced by this session.
+  Future<SomeResolvedLibraryResult> getResolvedLibraryByElement(
+      LibraryElement element);
+
+  /// Return a future that will complete with information about the results of
+  /// resolving all of the files in the library with the library [element].
+  ///
+  /// Throw [ArgumentError] if the [element] was not produced by this session.
+  @Deprecated('Use getResolvedLibraryByElement() instead')
   Future<SomeResolvedLibraryResult> getResolvedLibraryByElement2(
       LibraryElement element);
 
   /// Return a future that will complete with information about the results of
   /// resolving the file with the given absolute, normalized [path].
+  Future<SomeResolvedUnitResult> getResolvedUnit(String path);
+
+  /// Return a future that will complete with information about the results of
+  /// resolving the file with the given absolute, normalized [path].
+  @Deprecated('Use getResolvedUnit() instead')
   Future<SomeResolvedUnitResult> getResolvedUnit2(String path);
 
   /// Return a future that will complete with information about the results of
   /// building the element model for the file with the given absolute,
   /// normalized [path].
+  Future<SomeUnitElementResult> getUnitElement(String path);
+
+  /// Return a future that will complete with information about the results of
+  /// building the element model for the file with the given absolute,
+  /// normalized [path].
+  @Deprecated('Use getUnitElement() instead')
   Future<SomeUnitElementResult> getUnitElement2(String path);
 }
 
diff --git a/pkg/analyzer/lib/dart/analysis/utilities.dart b/pkg/analyzer/lib/dart/analysis/utilities.dart
index 3fd296d..8cee120 100644
--- a/pkg/analyzer/lib/dart/analysis/utilities.dart
+++ b/pkg/analyzer/lib/dart/analysis/utilities.dart
@@ -115,7 +115,7 @@
     {required String path, ResourceProvider? resourceProvider}) async {
   AnalysisContext context =
       _createAnalysisContext(path: path, resourceProvider: resourceProvider);
-  return await context.currentSession.getResolvedUnit2(path);
+  return await context.currentSession.getResolvedUnit(path);
 }
 
 /// Return a newly create analysis context in which the file at the given [path]
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index ab82e26..2df5ebb 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -1061,7 +1061,7 @@
 /// [PostfixExpression] when the operator is an increment operator.
 ///
 /// Clients may not extend, implement or mix-in this class.
-abstract class CompoundAssignmentExpression {
+abstract class CompoundAssignmentExpression implements Expression {
   /// The element that is used to read the value.
   ///
   /// If this node is not a compound assignment, this element is `null`.
@@ -2471,7 +2471,7 @@
 
   /// Return `true` if the given [name] is visible only within the library in
   /// which it is declared.
-  static bool isPrivateName(String name) => name.startsWith('_');
+  static bool isPrivateName(String name) => name.isNotEmpty && name[0] == "_";
 }
 
 /// The basic structure of an if element.
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index 44efa9f..5e9079a 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -28,12 +28,19 @@
 ///
 /// Clients may not extend, implement or mix-in this class.
 abstract class DartType {
+  /// If this type is an instantiation of a type alias, information about
+  /// the alias element, and the type arguments.
+  /// Otherwise return `null`.
+  InstantiatedTypeAliasElement? get alias;
+
   /// If this type is an instantiation of a type alias, return the type
   /// arguments used for the instantiation. Otherwise return `null`.
+  @Deprecated('Use alias instead')
   List<DartType>? get aliasArguments;
 
   /// If this type is an instantiation of a type alias, return it.
   /// Otherwise return `null`.
+  @Deprecated('Use alias instead')
   TypeAliasElement? get aliasElement;
 
   /// Return the name of this type as it should appear when presented to users
@@ -245,6 +252,17 @@
   FunctionType instantiate(List<DartType> argumentTypes);
 }
 
+/// Information about an instantiated [TypeAliasElement] and the type
+/// arguments with which it is instantiated.
+abstract class InstantiatedTypeAliasElement {
+  /// The alias element that is instantiated to produce a [DartType].
+  TypeAliasElement get element;
+
+  /// The type arguments with which the [element] was instantiated.
+  /// This list will be empty if the [element] is not generic.
+  List<DartType> get typeArguments;
+}
+
 /// The type introduced by either a class or an interface, or a reference to
 /// such a type.
 ///
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 6a6fa5a..0a2b2c8 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -146,6 +146,7 @@
   CompileTimeErrorCode.DEFAULT_VALUE_ON_REQUIRED_PARAMETER,
   CompileTimeErrorCode.DEFERRED_IMPORT_OF_EXTENSION,
   CompileTimeErrorCode.DEFINITELY_UNASSIGNED_LATE_LOCAL_VARIABLE,
+  CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION,
   CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_DEFAULT,
   CompileTimeErrorCode.DUPLICATE_CONSTRUCTOR_NAME,
   CompileTimeErrorCode.DUPLICATE_DEFINITION,
@@ -454,6 +455,7 @@
   CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_OPERATOR_MINUS,
   CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
   CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
+  CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION,
   CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
   CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_EXTENSION,
   CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
@@ -469,6 +471,7 @@
   FfiCode.EMPTY_STRUCT,
   FfiCode.EXTRA_ANNOTATION_ON_STRUCT_FIELD,
   FfiCode.EXTRA_SIZE_ANNOTATION_CARRAY,
+  FfiCode.FFI_NATIVE_ONLY_STATIC,
   FfiCode.FIELD_IN_STRUCT_WITH_INITIALIZER,
   FfiCode.FIELD_INITIALIZER_IN_STRUCT,
   FfiCode.FIELD_MUST_BE_EXTERNAL_IN_STRUCT,
diff --git a/pkg/analyzer/lib/src/context/builder.dart b/pkg/analyzer/lib/src/context/builder.dart
index 9bb60eb..ec0aaa7 100644
--- a/pkg/analyzer/lib/src/context/builder.dart
+++ b/pkg/analyzer/lib/src/context/builder.dart
@@ -5,387 +5,9 @@
 import 'dart:collection';
 import 'dart:core';
 
-import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
-import 'package:analyzer/src/context/context_root.dart';
-import 'package:analyzer/src/context/packages.dart';
-import 'package:analyzer/src/dart/analysis/byte_store.dart';
-import 'package:analyzer/src/dart/analysis/driver.dart'
-    show AnalysisDriver, AnalysisDriverScheduler;
-import 'package:analyzer/src/dart/analysis/file_content_cache.dart';
-import 'package:analyzer/src/dart/analysis/performance_logger.dart';
-import 'package:analyzer/src/dart/sdk/sdk.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/hint/sdk_constraint_extractor.dart';
-import 'package:analyzer/src/summary/package_bundle_reader.dart';
-import 'package:analyzer/src/summary/summary_sdk.dart';
-import 'package:analyzer/src/task/options.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 {
-  /// The [ResourceProvider] by which paths are converted into [Resource]s.
-  final ResourceProvider resourceProvider;
-
-  /// The manager used to manage the DartSdk's that have been created so that
-  /// they can be shared across contexts.
-  final DartSdkManager sdkManager;
-
-  /// The options used by the context builder.
-  final ContextBuilderOptions builderOptions;
-
-  /// The scheduler used by any analysis drivers created through this interface.
-  late final AnalysisDriverScheduler analysisDriverScheduler;
-
-  /// The performance log used by any analysis drivers created through this
-  /// interface.
-  late final PerformanceLog performanceLog;
-
-  /// If `true`, additional analysis data useful for testing is stored.
-  bool retainDataForTesting = false;
-
-  /// The byte store used by any analysis drivers created through this interface.
-  late final ByteStore byteStore;
-
-  /// Whether any analysis driver created through this interface should support
-  /// indexing and search.
-  bool enableIndex = false;
-
-  /// Sometimes `BUILD` files are not preserved, and other files are created
-  /// instead. But looking for them is expensive, so we want to avoid this
-  /// in cases when `BUILD` files are always available.
-  bool lookForBazelBuildFileSubstitutes = true;
-
-  /// Initialize a newly created builder to be ready to build a context rooted in
-  /// the directory with the given [rootDirectoryPath].
-  ContextBuilder(this.resourceProvider, this.sdkManager,
-      {ContextBuilderOptions? options})
-      : builderOptions = options ?? ContextBuilderOptions();
-
-  /// Return an analysis driver that is configured correctly to analyze code in
-  /// the directory with the given [path].
-  AnalysisDriver buildDriver(
-    ContextRoot contextRoot,
-    Workspace workspace, {
-    void Function(AnalysisOptionsImpl)? updateAnalysisOptions,
-    FileContentCache? fileContentCache,
-  }) {
-    String path = contextRoot.root;
-
-    var options = getAnalysisOptions(path, workspace, contextRoot: contextRoot);
-
-    if (updateAnalysisOptions != null) {
-      updateAnalysisOptions(options);
-    }
-    //_processAnalysisOptions(context, optionMap);
-
-    SummaryDataStore? summaryData;
-    var librarySummaryPaths = builderOptions.librarySummaryPaths;
-    if (librarySummaryPaths != null) {
-      summaryData = SummaryDataStore(librarySummaryPaths);
-    }
-
-    final sf =
-        createSourceFactoryFromWorkspace(workspace, summaryData: summaryData);
-
-    AnalysisDriver driver = AnalysisDriver.tmp1(
-      scheduler: analysisDriverScheduler,
-      logger: performanceLog,
-      resourceProvider: resourceProvider,
-      byteStore: byteStore,
-      sourceFactory: sf,
-      analysisOptions: options,
-      packages: createPackageMap(
-        resourceProvider: resourceProvider,
-        options: builderOptions,
-        rootPath: path,
-      ),
-      enableIndex: enableIndex,
-      externalSummaries: summaryData,
-      retainDataForTesting: retainDataForTesting,
-      fileContentCache: fileContentCache,
-    );
-
-    declareVariablesInDriver(driver);
-    return driver;
-  }
-
-//  void _processAnalysisOptions(
-//      AnalysisContext context, Map<String, YamlNode> optionMap) {
-//    List<OptionsProcessor> optionsProcessors =
-//        AnalysisEngine.instance.optionsPlugin.optionsProcessors;
-//    try {
-//      optionsProcessors.forEach(
-//          (OptionsProcessor p) => p.optionsProcessed(context, optionMap));
-//
-//      // Fill in lint rule defaults in case lints are enabled and rules are
-//      // not specified in an options file.
-//      if (context.analysisOptions.lint && !containsLintRuleEntry(optionMap)) {
-//        setLints(context, linterPlugin.contributedRules);
-//      }
-//
-//      // Ask engine to further process options.
-//      if (optionMap != null) {
-//        configureContextOptions(context, optionMap);
-//      }
-//    } on Exception catch (e) {
-//      optionsProcessors.forEach((OptionsProcessor p) => p.onError(e));
-//    }
-//  }
-
-  SourceFactory createSourceFactory(String rootPath, Workspace workspace,
-      {SummaryDataStore? summaryData}) {
-    DartSdk sdk = findSdk(workspace);
-    if (summaryData != null && sdk is SummaryBasedDartSdk) {
-      summaryData.addBundle(null, sdk.bundle);
-    }
-    return workspace.createSourceFactory(sdk, summaryData);
-  }
-
-  SourceFactory createSourceFactoryFromWorkspace(Workspace workspace,
-      {SummaryDataStore? summaryData}) {
-    DartSdk sdk = findSdk(workspace);
-    if (summaryData != null && sdk is SummaryBasedDartSdk) {
-      summaryData.addBundle(null, sdk.bundle);
-    }
-    return workspace.createSourceFactory(sdk, summaryData);
-  }
-
-  /// Add any [declaredVariables] to the list of declared variables used by the
-  /// given analysis [driver].
-  void declareVariablesInDriver(AnalysisDriver driver) {
-    var variables = builderOptions.declaredVariables;
-    if (variables.isNotEmpty) {
-      driver.declaredVariables = DeclaredVariables.fromMap(variables);
-      driver.configure();
-    }
-  }
-
-  /// Return the SDK that should be used to analyze code. Use the given
-  /// [workspace] to locate the SDK.
-  DartSdk findSdk(Workspace? workspace) {
-    String? summaryPath = builderOptions.dartSdkSummaryPath;
-    if (summaryPath != null) {
-      return SummaryBasedDartSdk(summaryPath, true,
-          resourceProvider: resourceProvider);
-    }
-
-    DartSdk folderSdk;
-    {
-      String sdkPath = sdkManager.defaultSdkDirectory;
-      SdkDescription description = SdkDescription(sdkPath);
-      folderSdk = sdkManager.getSdk(description, () {
-        return FolderBasedDartSdk(
-          resourceProvider,
-          resourceProvider.getFolder(sdkPath),
-        );
-      });
-    }
-
-    if (workspace != null) {
-      var partialSourceFactory = workspace.createSourceFactory(null, null);
-      var embedderYamlSource = partialSourceFactory.forUri(
-        'package:sky_engine/_embedder.yaml',
-      );
-      if (embedderYamlSource != null) {
-        var embedderYamlPath = embedderYamlSource.fullName;
-        var libFolder = resourceProvider.getFile(embedderYamlPath).parent2;
-        EmbedderYamlLocator locator =
-            EmbedderYamlLocator.forLibFolder(libFolder);
-        Map<Folder, YamlMap> embedderMap = locator.embedderYamls;
-        if (embedderMap.isNotEmpty) {
-          EmbedderSdk embedderSdk = EmbedderSdk(
-            resourceProvider,
-            embedderMap,
-            languageVersion: folderSdk.languageVersion,
-          );
-          return embedderSdk;
-        }
-      }
-    }
-
-    return folderSdk;
-  }
-
-  /// Return the analysis options that should be used to analyze code in the
-  /// directory with the given [path]. Use [verbosePrint] to echo verbose
-  /// information about the analysis options selection process.
-  AnalysisOptionsImpl getAnalysisOptions(String path, Workspace workspace,
-      {void Function(String text)? verbosePrint, ContextRoot? contextRoot}) {
-    void verbose(String text) {
-      if (verbosePrint != null) {
-        verbosePrint(text);
-      }
-    }
-
-    SourceFactory sourceFactory = workspace.createSourceFactory(null, null);
-    AnalysisOptionsProvider optionsProvider =
-        AnalysisOptionsProvider(sourceFactory);
-
-    AnalysisOptionsImpl options = AnalysisOptionsImpl();
-
-    var optionsPath = builderOptions.defaultAnalysisOptionsFilePath;
-    if (optionsPath != null) {
-      var optionsFile = resourceProvider.getFile(optionsPath);
-      try {
-        contextRoot?.optionsFilePath = optionsFile.path;
-        var optionsMap = optionsProvider.getOptionsFromFile(optionsFile);
-        applyToAnalysisOptions(options, optionsMap);
-        verbose('Loaded analysis options from ${optionsFile.path}');
-      } catch (e) {
-        // Ignore exceptions thrown while trying to load the options file.
-        verbose('Exception: $e\n  when loading ${optionsFile.path}');
-      }
-    } else {
-      verbose('Using default analysis options');
-    }
-
-    var pubspecFile = _findPubspecFile(path);
-    if (pubspecFile != null) {
-      var extractor = SdkConstraintExtractor(pubspecFile);
-      var sdkVersionConstraint = extractor.constraint();
-      if (sdkVersionConstraint != null) {
-        options.sdkVersionConstraint = sdkVersionConstraint;
-      }
-    }
-
-    return options;
-  }
-
-  /// Return the `pubspec.yaml` file that should be used when analyzing code in
-  /// the directory with the given [path], possibly `null`.
-  File? _findPubspecFile(String path) {
-    var folder = resourceProvider.getFolder(path);
-    for (var current in folder.withAncestors) {
-      var file = current.getChildAssumingFile('pubspec.yaml');
-      if (file.exists) {
-        return file;
-      }
-    }
-  }
-
-  /// 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].
-class ContextBuilderOptions {
-  /// The file path of the file containing the summary of the SDK that should be
-  /// used to "analyze" the SDK. This option should only be specified by
-  /// command-line tools such as 'dartanalyzer' or 'ddc'.
-  String? dartSdkSummaryPath;
-
-  /// 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`
-  /// if the normal lookup mechanism should be used.
-  String? defaultAnalysisOptionsFilePath;
-
-  /// A table mapping variable names to values for the declared variables.
-  Map<String, String> declaredVariables = {};
-
-  /// The file path of the .packages file that should be used in place of any
-  /// file found using the normal (Package Specification DEP) lookup mechanism,
-  /// or `null` if the normal lookup mechanism should be used.
-  String? defaultPackageFilePath;
-
-  /// A list of the paths of summary files that are to be used, or `null` if no
-  /// summary information is available.
-  List<String>? librarySummaryPaths;
-
-  /// Initialize a newly created set of options
-  ContextBuilderOptions();
-}
-
 /// Given a package map, check in each package's lib directory for the existence
 /// of an `_embedder.yaml` file. If the file contains a top level YamlMap, it
 /// will be added to the [embedderYamls] map.
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index 0ca758d..3e2f98b 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -7,9 +7,9 @@
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/src/context/builder.dart' as old
-    show ContextBuilder, ContextBuilderOptions;
-import 'package:analyzer/src/context/context_root.dart' as old;
+import 'package:analyzer/src/analysis_options/analysis_options_provider.dart';
+import 'package:analyzer/src/context/builder.dart' show EmbedderYamlLocator;
+import 'package:analyzer/src/context/packages.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart'
     show ByteStore, MemoryByteStore;
 import 'package:analyzer/src/dart/analysis/driver.dart'
@@ -18,8 +18,15 @@
 import 'package:analyzer/src/dart/analysis/file_content_cache.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart'
     show PerformanceLog;
+import 'package:analyzer/src/dart/sdk/sdk.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
-import 'package:analyzer/src/generated/sdk.dart' show DartSdkManager;
+import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/hint/sdk_constraint_extractor.dart';
+import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/summary/summary_sdk.dart';
+import 'package:analyzer/src/task/options.dart';
+import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:cli_util/cli_util.dart';
 
 /// An implementation of a context builder.
@@ -57,46 +64,57 @@
     byteStore ??= MemoryByteStore();
     performanceLog ??= PerformanceLog(StringBuffer());
 
-    DartSdkManager sdkManager = DartSdkManager(sdkPath);
-
     if (scheduler == null) {
       scheduler = AnalysisDriverScheduler(performanceLog);
       scheduler.start();
     }
 
-    // TODO(brianwilkerson) Move the required implementation from the old
-    // ContextBuilder to this class and remove the old class.
-    old.ContextBuilderOptions options = old.ContextBuilderOptions();
-    if (declaredVariables != null) {
-      options.declaredVariables = _toMap(declaredVariables);
-    }
-    if (sdkSummaryPath != null) {
-      options.dartSdkSummaryPath = sdkSummaryPath;
-    }
+    SummaryDataStore? summaryData;
     if (librarySummaryPaths != null) {
-      options.librarySummaryPaths = librarySummaryPaths;
+      summaryData = SummaryDataStore(librarySummaryPaths);
     }
-    options.defaultAnalysisOptionsFilePath = contextRoot.optionsFile?.path;
-    options.defaultPackageFilePath = contextRoot.packagesFile?.path;
 
-    old.ContextBuilder builder =
-        old.ContextBuilder(resourceProvider, sdkManager, options: options);
-    builder.analysisDriverScheduler = scheduler;
-    builder.byteStore = byteStore;
-    builder.enableIndex = enableIndex;
-    builder.performanceLog = performanceLog;
-    builder.retainDataForTesting = retainDataForTesting;
-
-    old.ContextRoot oldContextRoot = old.ContextRoot(
-        contextRoot.root.path, contextRoot.excludedPaths.toList(),
-        pathContext: resourceProvider.pathContext);
-    AnalysisDriver driver = builder.buildDriver(
-      oldContextRoot,
-      contextRoot.workspace,
-      fileContentCache: fileContentCache,
-      updateAnalysisOptions: updateAnalysisOptions,
+    var workspace = contextRoot.workspace;
+    var sdk = _createSdk(
+      workspace: workspace,
+      sdkPath: sdkPath,
+      sdkSummaryPath: sdkSummaryPath,
     );
 
+    // TODO(scheglov) Ensure that "librarySummaryPaths" not null only
+    // when "sdkSummaryPath" is not null.
+    if (sdk is SummaryBasedDartSdk) {
+      summaryData?.addBundle(null, sdk.bundle);
+    }
+
+    var sourceFactory = workspace.createSourceFactory(sdk, summaryData);
+
+    var options = _getAnalysisOptions(contextRoot, sourceFactory);
+    if (updateAnalysisOptions != null) {
+      updateAnalysisOptions(options);
+    }
+
+    var driver = AnalysisDriver.tmp1(
+      scheduler: scheduler,
+      logger: performanceLog,
+      resourceProvider: resourceProvider,
+      byteStore: byteStore,
+      sourceFactory: sourceFactory,
+      analysisOptions: options,
+      packages: _createPackageMap(
+        contextRoot: contextRoot,
+      ),
+      enableIndex: enableIndex,
+      externalSummaries: summaryData,
+      retainDataForTesting: retainDataForTesting,
+      fileContentCache: fileContentCache,
+    );
+
+    if (declaredVariables != null) {
+      driver.declaredVariables = declaredVariables;
+      driver.configure();
+    }
+
     // AnalysisDriver reports results into streams.
     // We need to drain these streams to avoid memory leak.
     if (drainStreams) {
@@ -111,13 +129,103 @@
     return context;
   }
 
-  /// Convert the [declaredVariables] into a map for use with the old context
-  /// builder.
-  Map<String, String> _toMap(DeclaredVariables declaredVariables) {
-    Map<String, String> map = <String, String>{};
-    for (String name in declaredVariables.variableNames) {
-      map[name] = declaredVariables.get(name)!;
+  /// Return [Packages] to analyze the [contextRoot].
+  ///
+  /// TODO(scheglov) Get [Packages] from [Workspace]?
+  Packages _createPackageMap({
+    required ContextRoot contextRoot,
+  }) {
+    var configFile = contextRoot.packagesFile;
+    if (configFile != null) {
+      return parsePackagesFile(resourceProvider, configFile);
+    } else {
+      return Packages.empty;
     }
-    return map;
+  }
+
+  /// Return the SDK that that should be used to analyze code.
+  DartSdk _createSdk({
+    required Workspace workspace,
+    String? sdkPath,
+    String? sdkSummaryPath,
+  }) {
+    if (sdkSummaryPath != null) {
+      return SummaryBasedDartSdk(sdkSummaryPath, true,
+          resourceProvider: resourceProvider);
+    }
+
+    var folderSdk = FolderBasedDartSdk(
+      resourceProvider,
+      resourceProvider.getFolder(sdkPath!),
+    );
+
+    {
+      // TODO(scheglov) We already had partial SourceFactory in ContextLocatorImpl.
+      var partialSourceFactory = workspace.createSourceFactory(null, null);
+      var embedderYamlSource = partialSourceFactory.forUri(
+        'package:sky_engine/_embedder.yaml',
+      );
+      if (embedderYamlSource != null) {
+        var embedderYamlPath = embedderYamlSource.fullName;
+        var libFolder = resourceProvider.getFile(embedderYamlPath).parent2;
+        var locator = EmbedderYamlLocator.forLibFolder(libFolder);
+        var embedderMap = locator.embedderYamls;
+        if (embedderMap.isNotEmpty) {
+          return EmbedderSdk(
+            resourceProvider,
+            embedderMap,
+            languageVersion: folderSdk.languageVersion,
+          );
+        }
+      }
+    }
+
+    return folderSdk;
+  }
+
+  /// Return the `pubspec.yaml` file that should be used when analyzing code in
+  /// the [contextRoot], possibly `null`.
+  ///
+  /// TODO(scheglov) Get it from [Workspace]?
+  File? _findPubspecFile(ContextRoot contextRoot) {
+    for (var current in contextRoot.root.withAncestors) {
+      var file = current.getChildAssumingFile('pubspec.yaml');
+      if (file.exists) {
+        return file;
+      }
+    }
+  }
+
+  /// Return the analysis options that should be used to analyze code in the
+  /// [contextRoot].
+  ///
+  /// TODO(scheglov) We have already loaded it once in [ContextLocatorImpl].
+  AnalysisOptionsImpl _getAnalysisOptions(
+    ContextRoot contextRoot,
+    SourceFactory sourceFactory,
+  ) {
+    var options = AnalysisOptionsImpl();
+
+    var optionsFile = contextRoot.optionsFile;
+    if (optionsFile != null) {
+      try {
+        var provider = AnalysisOptionsProvider(sourceFactory);
+        var optionsMap = provider.getOptionsFromFile(optionsFile);
+        applyToAnalysisOptions(options, optionsMap);
+      } catch (e) {
+        // ignore
+      }
+    }
+
+    var pubspecFile = _findPubspecFile(contextRoot);
+    if (pubspecFile != null) {
+      var extractor = SdkConstraintExtractor(pubspecFile);
+      var sdkVersionConstraint = extractor.constraint();
+      if (sdkVersionConstraint != null) {
+        options.sdkVersionConstraint = sdkVersionConstraint;
+      }
+    }
+
+    return options;
   }
 }
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/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 79bc69f..ed78b2e 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/dart/analysis/analysis_context.dart' as api;
 import 'package:analyzer/dart/analysis/declared_variables.dart';
 import 'package:analyzer/dart/analysis/results.dart';
-import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
@@ -81,7 +80,7 @@
 /// TODO(scheglov) Clean up the list of implicitly analyzed files.
 class AnalysisDriver implements AnalysisDriverGeneric {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 161;
+  static const int DATA_VERSION = 167;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
@@ -201,10 +200,10 @@
   final _partsToAnalyze = <String>{};
 
   /// The controller for the [results] stream.
-  final _resultController = StreamController<ResolvedUnitResult>();
+  final _resultController = StreamController<Object>();
 
   /// The stream that will be written to when analysis results are produced.
-  late final Stream<ResolvedUnitResult> _onResults;
+  late final Stream<Object> _onResults;
 
   /// Resolution signatures of the most recently produced results for files.
   final Map<String, String> _lastProducedSignatures = {};
@@ -383,6 +382,13 @@
   /// an analysis result is produced for every added file prior to the next time
   /// the analysis state transitions to "idle".
   ///
+  /// [ResolvedUnitResult]s are produced for:
+  /// 1. Files requested using [getResult2].
+  /// 2. Files passed to [addFile] which are also in [priorityFiles].
+  ///
+  /// [ErrorsResult]s are produced for:
+  /// 1. Files passed to [addFile] which are not in [priorityFiles].
+  ///
   /// At least one analysis result is produced for every file passed to
   /// [addFile] or [changeFile] prior to the next time the analysis state
   /// transitions to "idle", unless the file is later removed from analysis
@@ -394,7 +400,7 @@
   ///
   /// Results might be produced even for files that have never been added
   /// using [addFile], for example when [getResult2] was called for a file.
-  Stream<ResolvedUnitResult> get results => _onResults;
+  Stream<Object> get results => _onResults;
 
   /// Return the search support for the driver.
   Search get search => _search;
@@ -463,7 +469,6 @@
         _unitElementRequestedParts.isNotEmpty) {
       return AnalysisDriverPriority.general;
     }
-    clearLibraryContext();
     return AnalysisDriverPriority.nothing;
   }
 
@@ -994,11 +999,11 @@
         }
         // Notify the completers.
         _requestedFiles.remove(path)!.forEach((completer) {
-          completer.complete(result);
+          completer.complete(result.unitResult!);
         });
         // Remove from to be analyzed and produce it now.
         _fileTracker.fileWasAnalyzed(path);
-        _resultController.add(result);
+        _resultController.add(result.unitResult!);
       } catch (exception, stackTrace) {
         _reportException(path, exception, stackTrace);
         _fileTracker.fileWasAnalyzed(path);
@@ -1123,7 +1128,7 @@
             if (result == null) {
               _partsToAnalyze.add(path);
             } else {
-              _resultController.add(result);
+              _resultController.add(result.unitResult!);
             }
           } catch (exception, stackTrace) {
             _reportException(path, exception, stackTrace);
@@ -1144,12 +1149,12 @@
             withUnit: false, skipIfSameSignature: true);
         if (result == null) {
           _partsToAnalyze.add(path);
-        } else if (result == AnalysisResult._UNCHANGED) {
+        } else if (result.isUnchangedErrors) {
           // We found that the set of errors is the same as we produced the
           // last time, so we don't need to produce it again now.
         } else {
-          _resultController.add(result);
-          _lastProducedSignatures[result.path!] = result._signature;
+          _resultController.add(result.errorsResult!);
+          _lastProducedSignatures[path] = result._signature;
         }
       } catch (exception, stackTrace) {
         _reportException(path, exception, stackTrace);
@@ -1168,11 +1173,11 @@
             withUnit: true, asIsIfPartWithoutLibrary: true)!;
         // Notify the completers.
         _requestedParts.remove(path)!.forEach((completer) {
-          completer.complete(result);
+          completer.complete(result.unitResult!);
         });
         // Remove from to be analyzed and produce it now.
         _partsToAnalyze.remove(path);
-        _resultController.add(result);
+        _resultController.add(result.unitResult!);
       } catch (exception, stackTrace) {
         _reportException(path, exception, stackTrace);
         _partsToAnalyze.remove(path);
@@ -1189,10 +1194,16 @@
       String path = _partsToAnalyze.first;
       _partsToAnalyze.remove(path);
       try {
-        var result = _computeAnalysisResult(path,
-            withUnit: _priorityFiles.contains(path),
-            asIsIfPartWithoutLibrary: true)!;
-        _resultController.add(result);
+        var withUnit = _priorityFiles.contains(path);
+        if (withUnit) {
+          var result = _computeAnalysisResult(path,
+              withUnit: true, asIsIfPartWithoutLibrary: true)!;
+          _resultController.add(result.unitResult!);
+        } else {
+          var result = _computeAnalysisResult(path,
+              withUnit: false, asIsIfPartWithoutLibrary: true)!;
+          _resultController.add(result.errorsResult!);
+        }
       } catch (exception, stackTrace) {
         _reportException(path, exception, stackTrace);
         _clearLibraryContextAfterException();
@@ -1294,8 +1305,9 @@
   /// Return the cached or newly computed analysis result of the file with the
   /// given [path].
   ///
-  /// The result will have the fully resolved unit and will always be newly
-  /// compute only if [withUnit] is `true`.
+  /// The [withUnit] flag control which result will be returned.
+  /// When `true`, [AnalysisResult.unitResult] will be set.
+  /// Otherwise [AnalysisResult.errorsResult] will be set.
   ///
   /// Return `null` if the file is a part of an unknown library, so cannot be
   /// analyzed yet. But [asIsIfPartWithoutLibrary] is `true`, then the file is
@@ -1305,7 +1317,7 @@
   /// the resolved signature of the file in its library is the same as the one
   /// that was the most recently produced to the client.
   AnalysisResult? _computeAnalysisResult(String path,
-      {bool withUnit = false,
+      {required bool withUnit,
       bool asIsIfPartWithoutLibrary = false,
       bool skipIfSameSignature = false}) {
     FileState file = _fsState.getFileForPath(path);
@@ -1328,7 +1340,7 @@
     if (skipIfSameSignature) {
       assert(!withUnit);
       if (_lastProducedSignatures[path] == signature) {
-        return AnalysisResult._UNCHANGED;
+        return AnalysisResult.unchangedErrors(signature);
       }
     }
 
@@ -1388,7 +1400,7 @@
             content: withUnit ? file.content : null,
             resolvedUnit: withUnit ? resolvedUnit : null);
         if (withUnit && _priorityFiles.contains(path)) {
-          _priorityResults[path] = result;
+          _priorityResults[path] = result.unitResult!;
         }
         return result;
       } catch (exception, stackTrace) {
@@ -1410,8 +1422,7 @@
       return null;
     }
 
-    return ErrorsResultImpl(currentSession, path, analysisResult.uri,
-        analysisResult.lineInfo, analysisResult.isPart, analysisResult.errors);
+    return analysisResult.errorsResult;
   }
 
   AnalysisDriverUnitIndex _computeIndex(String path) {
@@ -1660,7 +1671,9 @@
     var unit = AnalysisDriverResolvedUnit.fromBuffer(bytes);
     List<AnalysisError> errors = _getErrorsFromSerialized(file, unit.errors);
     _updateHasErrorOrWarningFlag(file, errors);
-    return AnalysisResult(
+    var index = unit.index!;
+    if (content != null && resolvedUnit != null) {
+      var resolvedUnitResult = ResolvedUnitResultImpl(
         currentSession,
         file.path,
         file.uri,
@@ -1668,10 +1681,21 @@
         content,
         file.lineInfo,
         file.isPart,
-        signature,
         resolvedUnit,
         errors,
-        unit.index);
+      );
+      return AnalysisResult.unit(signature, resolvedUnitResult, index);
+    } else {
+      var errorsResult = ErrorsResultImpl(
+        currentSession,
+        file.path,
+        file.uri,
+        file.lineInfo,
+        file.isPart,
+        errors,
+      );
+      return AnalysisResult.errors(signature, errorsResult, index);
+    }
   }
 
   /// Return [AnalysisError]s for the given [serialized] errors.
@@ -1720,21 +1744,19 @@
   AnalysisResult _newMissingDartLibraryResult(
       FileState file, String missingUri) {
     // TODO(scheglov) Find a better way to report this.
-    return AnalysisResult(
-        currentSession,
-        file.path,
-        file.uri,
-        file.exists,
-        null,
-        file.lineInfo,
-        file.isPart,
-        'missing',
-        null,
-        [
-          AnalysisError(file.source, 0, 0,
-              CompileTimeErrorCode.MISSING_DART_LIBRARY, [missingUri])
-        ],
-        null);
+    var errorsResult = ErrorsResultImpl(
+      currentSession,
+      file.path,
+      file.uri,
+      file.lineInfo,
+      file.isPart,
+      [
+        AnalysisError(file.source, 0, 0,
+            CompileTimeErrorCode.MISSING_DART_LIBRARY, [missingUri])
+      ],
+    );
+    return AnalysisResult.errors(
+        'missing', errorsResult, AnalysisDriverUnitIndexBuilder());
   }
 
   void _reportException(String path, Object exception, StackTrace stackTrace) {
@@ -2115,38 +2137,50 @@
 
 /// The result of analyzing of a single file.
 ///
-/// These results are self-consistent, i.e. [content], [lineInfo], the
-/// resolved [unit] correspond to each other. All referenced elements, even
+/// These results are self-consistent, i.e. the file content, line info, the
+/// resolved unit correspond to each other. All referenced elements, even
 /// external ones, are also self-consistent. But none of the results is
 /// guaranteed to be consistent with the state of the files.
 ///
 /// Every result is independent, and is not guaranteed to be consistent with
 /// any previously returned result, even inside of the same library.
-class AnalysisResult extends ResolvedUnitResultImpl {
-  static final _UNCHANGED = _UnchangedAnalysisResult();
-
+class AnalysisResult {
   /// The signature of the result based on the content of the file, and the
   /// transitive closure of files imported and exported by the library of
   /// the requested file.
   final String _signature;
 
+  final bool isUnchangedErrors;
+
+  /// Is not `null` if this result is a result with errors.
+  /// Otherwise is `null`, and usually [unitResult] is set.
+  final ErrorsResultImpl? errorsResult;
+
+  /// Is not `null` if this result is a result with a resolved unit.
+  /// Otherwise is `null`, and usually [errorsResult] is set.
+  final ResolvedUnitResultImpl? unitResult;
+
   /// The index of the unit.
   final AnalysisDriverUnitIndex? _index;
 
-  AnalysisResult(
-      AnalysisSession session,
-      String path,
-      Uri uri,
-      bool exists,
-      String? content,
-      LineInfo lineInfo,
-      bool isPart,
-      this._signature,
-      CompilationUnit? unit,
-      List<AnalysisError> errors,
-      this._index)
-      : super(session, path, uri, exists, content, lineInfo, isPart, unit,
-            errors);
+  AnalysisResult.errors(
+      this._signature, this.errorsResult, AnalysisDriverUnitIndex index)
+      : isUnchangedErrors = false,
+        unitResult = null,
+        _index = index;
+
+  AnalysisResult.unchangedErrors(this._signature)
+      : isUnchangedErrors = true,
+        errorsResult = null,
+        unitResult = null,
+        _index = null;
+
+  AnalysisResult.unit(this._signature, ResolvedUnitResultImpl unitResult,
+      AnalysisDriverUnitIndex index)
+      : isUnchangedErrors = false,
+        errorsResult = null,
+        unitResult = unitResult,
+        _index = index;
 }
 
 /// An object that watches for the creation and removal of analysis drivers.
@@ -2488,8 +2522,3 @@
     return true;
   }
 }
-
-class _UnchangedAnalysisResult implements AnalysisResult {
-  @override
-  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 40b742f..b21980f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -414,12 +414,8 @@
   /// Read the file content and ensure that all of the file properties are
   /// consistent with the read content, including API signature.
   ///
-  /// If [allowCached] is `true`, don't read the content of the file if it
-  /// is already cached (in another [FileSystemState], because otherwise we
-  /// would not create this new instance of [FileState] and refresh it).
-  ///
   /// Return `true` if the API signature changed since the last refresh.
-  bool refresh({bool allowCached = false}) {
+  bool refresh() {
     counterFileStateRefresh++;
 
     var timerWasRunning = timerFileStateRefresh.isRunning;
@@ -429,10 +425,6 @@
 
     _invalidateCurrentUnresolvedData();
 
-    if (!allowCached) {
-      _fsState.markFileForReading(path);
-    }
-
     {
       var rawFileState = _fsState._fileContentCache.get(path);
       _content = rawFileState.content;
@@ -862,7 +854,7 @@
       _uriToFile[uri] = file;
       _addFileWithPath(path, file);
       _pathToCanonicalFile[path] = file;
-      file.refresh(allowCached: true);
+      file.refresh();
     }
     return file;
   }
@@ -908,7 +900,7 @@
           packageLanguageVersion);
       _uriToFile[uri] = file;
       _addFileWithPath(path, file);
-      file.refresh(allowCached: true);
+      file.refresh();
     }
     return Either2.t1(file);
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index e10f9be..af4dab4 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -332,7 +332,6 @@
 
     var enableTiming = _analysisOptions.enableTiming;
     var nodeRegistry = NodeLintRegistry(enableTiming);
-    var visitors = <AstVisitor>[];
 
     var context = LinterContextImpl(
       allUnits,
@@ -354,14 +353,9 @@
 
     // Run lints that handle specific node types.
     unit.accept(LinterVisitor(
-        nodeRegistry, ExceptionHandlingDelegatingAstVisitor.logException));
-
-    // Run visitor based lints.
-    if (visitors.isNotEmpty) {
-      AstVisitor visitor = ExceptionHandlingDelegatingAstVisitor(
-          visitors, ExceptionHandlingDelegatingAstVisitor.logException);
-      unit.accept(visitor);
-    }
+        nodeRegistry,
+        LinterExceptionHandler(_analysisOptions.propagateLinterExceptions)
+            .logException));
   }
 
   void _computeVerifyErrors(FileState file, CompilationUnit unit) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/results.dart b/pkg/analyzer/lib/src/dart/analysis/results.dart
index bcd371c..9db2ec6 100644
--- a/pkg/analyzer/lib/src/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/results.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type_provider.dart';
-import 'package:analyzer/dart/element/type_system.dart';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
@@ -18,7 +17,7 @@
   final AnalysisSession session;
 
   @override
-  final String? path;
+  final String path;
 
   @override
   final Uri uri;
@@ -74,130 +73,17 @@
   LibraryElementResultImpl(this.element);
 }
 
-/// The implementation of [AnalysisResult] when not [ResultState.VALID].
-class NotValidAnalysisResultImpl implements AnalysisResult {
-  @override
-  final ResultState state;
-
-  NotValidAnalysisResultImpl(this.state);
-
-  @override
-  String? get path {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  AnalysisSession get session {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  Uri get uri {
-    throw StateError('This result is not valid');
-  }
-}
-
-/// The implementation of [ErrorsResult] when not [ResultState.VALID].
-class NotValidErrorsResultImpl extends NotValidFileResultImpl
-    implements ErrorsResult {
-  NotValidErrorsResultImpl(ResultState state) : super(state);
-
-  @override
-  List<AnalysisError> get errors {
-    throw StateError('This result is not valid');
-  }
-}
-
-/// The implementation of [FileResult] when not [ResultState.VALID].
-class NotValidFileResultImpl extends NotValidAnalysisResultImpl
-    implements FileResult {
-  NotValidFileResultImpl(ResultState state) : super(state);
-
-  @override
-  bool get isPart {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  LineInfo get lineInfo {
-    throw StateError('This result is not valid');
-  }
-}
-
-/// The implementation of [ResolvedUnitResult] when not [ResultState.VALID].
-class NotValidResolvedUnitResultImpl extends NotValidFileResultImpl
-    implements ResolvedUnitResult {
-  NotValidResolvedUnitResultImpl(ResultState state) : super(state);
-
-  @override
-  String? get content {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  List<AnalysisError> get errors {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  bool get exists {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  LibraryElement get libraryElement {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  TypeProvider get typeProvider {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  TypeSystem get typeSystem {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  CompilationUnit? get unit {
-    throw StateError('This result is not valid');
-  }
-}
-
-/// The implementation of [UnitElementResult] when not [ResultState.VALID].
-class NotValidUnitElementResultImpl extends NotValidAnalysisResultImpl
-    implements UnitElementResult {
-  NotValidUnitElementResultImpl(ResultState state) : super(state);
-
-  @override
-  CompilationUnitElement get element {
-    throw StateError('This result is not valid');
-  }
-
-  @override
-  String get signature {
-    throw StateError('This result is not valid');
-  }
-}
-
 class ParsedLibraryResultImpl extends AnalysisResultImpl
     implements ParsedLibraryResult {
   @override
-  final List<ParsedUnitResult>? units;
+  final List<ParsedUnitResult> units;
 
   ParsedLibraryResultImpl(
-      AnalysisSession session, String? path, Uri uri, this.units)
+      AnalysisSession session, String path, Uri uri, this.units)
       : super(session, path, uri);
 
-  ParsedLibraryResultImpl.external(AnalysisSession session, Uri uri)
-      : this(session, null, uri, null);
-
   @override
   ResultState get state {
-    if (path == null) {
-      return ResultState.NOT_A_FILE;
-    }
     return ResultState.VALID;
   }
 
@@ -215,7 +101,7 @@
     }
 
     var elementPath = element.source!.fullName;
-    var unitResult = units!.firstWhere(
+    var unitResult = units.firstWhere(
       (r) => r.path == elementPath,
       orElse: () {
         var elementStr = element.getDisplayString(withNullability: true);
@@ -273,28 +159,22 @@
 class ResolvedLibraryResultImpl extends AnalysisResultImpl
     implements ResolvedLibraryResult {
   @override
-  final LibraryElement? element;
+  final LibraryElement element;
 
   @override
-  final List<ResolvedUnitResult>? units;
+  final List<ResolvedUnitResult> units;
 
   ResolvedLibraryResultImpl(
-      AnalysisSession session, String? path, Uri uri, this.element, this.units)
+      AnalysisSession session, String path, Uri uri, this.element, this.units)
       : super(session, path, uri);
 
-  ResolvedLibraryResultImpl.external(AnalysisSession session, Uri uri)
-      : this(session, null, uri, null, null);
-
   @override
   ResultState get state {
-    if (path == null) {
-      return ResultState.NOT_A_FILE;
-    }
     return ResultState.VALID;
   }
 
   @override
-  TypeProvider get typeProvider => element!.typeProvider;
+  TypeProvider get typeProvider => element.typeProvider;
 
   @override
   ElementDeclarationResult? getElementDeclaration(Element element) {
@@ -310,7 +190,7 @@
     }
 
     var elementPath = element.source!.fullName;
-    var unitResult = units!.firstWhere(
+    var unitResult = units.firstWhere(
       (r) => r.path == elementPath,
       orElse: () {
         var elementStr = element.getDisplayString(withNullability: true);
@@ -319,18 +199,13 @@
         buffer.writeln(' is not defined in this library.');
         // TODO(scheglov) https://github.com/dart-lang/sdk/issues/45430
         buffer.writeln('elementPath: $elementPath');
-        buffer.writeln('unitPaths: ${units!.map((e) => e.path).toList()}');
+        buffer.writeln('unitPaths: ${units.map((e) => e.path).toList()}');
         throw ArgumentError('$buffer');
       },
     );
 
-    var unit = unitResult.unit;
-    if (unit == null) {
-      throw StateError('The result has no unit');
-    }
-
     var locator = _DeclarationByElementLocator(element);
-    unit.accept(locator);
+    unitResult.unit.accept(locator);
     var declaration = locator.result;
 
     if (declaration == null) {
@@ -347,10 +222,10 @@
   final bool exists;
 
   @override
-  final String? content;
+  final String content;
 
   @override
-  final CompilationUnit? unit;
+  final CompilationUnit unit;
 
   @override
   final List<AnalysisError> errors;
@@ -369,10 +244,6 @@
 
   @override
   LibraryElement get libraryElement {
-    final unit = this.unit;
-    if (unit == null) {
-      throw StateError('The result has no unit');
-    }
     return unit.declaredElement!.library;
   }
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 20df7ad..8d7a200 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -381,7 +381,7 @@
       var unitResult = await _driver.getResult2(unitPath);
       if (unitResult is ResolvedUnitResult) {
         var visitor = _ImportElementReferencesVisitor(element, unitElement);
-        unitResult.unit!.accept(visitor);
+        unitResult.unit.accept(visitor);
         results.addAll(visitor.results);
       }
     }
@@ -400,7 +400,7 @@
       String unitPath = unitElement.source.fullName;
       var unitResult = await _driver.getResult2(unitPath);
       if (unitResult is ResolvedUnitResult) {
-        CompilationUnit unit = unitResult.unit!;
+        CompilationUnit unit = unitResult.unit;
         for (Directive directive in unit.directives) {
           if (directive is PartOfDirective && directive.element == element) {
             results.add(
@@ -433,9 +433,6 @@
       return const <SearchResult>[];
     }
     var unit = unitResult.unit;
-    if (unit == null) {
-      return const <SearchResult>[];
-    }
 
     // Prepare the node.
     var node = NodeLocator(element.nameOffset).searchWithin(unit);
@@ -487,7 +484,7 @@
       var unitResult = await _driver.getResult2(unitPath);
       if (unitResult is ResolvedUnitResult) {
         var visitor = _LocalReferencesVisitor(element, unitElement);
-        unitResult.unit!.accept(visitor);
+        unitResult.unit.accept(visitor);
         results.addAll(visitor.results);
       }
     }
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 288882e..5bc5a9c 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -55,31 +55,55 @@
   driver.AnalysisDriver getDriver() => _driver;
 
   @override
-  Future<SomeErrorsResult> getErrors2(String path) {
+  Future<SomeErrorsResult> getErrors(String path) {
     _checkConsistency();
     return _driver.getErrors2(path);
   }
 
+  @Deprecated('Use getErrors() instead')
   @override
-  SomeFileResult getFile2(String path) {
+  Future<SomeErrorsResult> getErrors2(String path) {
+    return getErrors(path);
+  }
+
+  @override
+  SomeFileResult getFile(String path) {
     _checkConsistency();
     return _driver.getFileSync2(path);
   }
 
+  @Deprecated('Use getFile() instead')
   @override
-  Future<SomeLibraryElementResult> getLibraryByUri2(String uri) {
+  SomeFileResult getFile2(String path) {
+    return getFile(path);
+  }
+
+  @override
+  Future<SomeLibraryElementResult> getLibraryByUri(String uri) {
     _checkConsistency();
     return _driver.getLibraryByUri2(uri);
   }
 
+  @Deprecated('Use getLibraryByUri() instead')
   @override
-  SomeParsedLibraryResult getParsedLibrary2(String path) {
+  Future<SomeLibraryElementResult> getLibraryByUri2(String uri) {
+    return getLibraryByUri(uri);
+  }
+
+  @override
+  SomeParsedLibraryResult getParsedLibrary(String path) {
     _checkConsistency();
     return _driver.getParsedLibrary2(path);
   }
 
+  @Deprecated('Use getParsedLibrary() instead')
   @override
-  SomeParsedLibraryResult getParsedLibraryByElement2(LibraryElement element) {
+  SomeParsedLibraryResult getParsedLibrary2(String path) {
+    return getParsedLibrary(path);
+  }
+
+  @override
+  SomeParsedLibraryResult getParsedLibraryByElement(LibraryElement element) {
     _checkConsistency();
 
     if (element.session != this) {
@@ -89,20 +113,38 @@
     return _driver.getParsedLibraryByUri2(element.source.uri);
   }
 
+  @Deprecated('Use getParsedLibraryByElement() instead')
   @override
-  SomeParsedUnitResult getParsedUnit2(String path) {
+  SomeParsedLibraryResult getParsedLibraryByElement2(LibraryElement element) {
+    return getParsedLibraryByElement(element);
+  }
+
+  @override
+  SomeParsedUnitResult getParsedUnit(String path) {
     _checkConsistency();
     return _driver.parseFileSync2(path);
   }
 
+  @Deprecated('Use getParsedUnit() instead')
   @override
-  Future<SomeResolvedLibraryResult> getResolvedLibrary2(String path) {
+  SomeParsedUnitResult getParsedUnit2(String path) {
+    return getParsedUnit(path);
+  }
+
+  @override
+  Future<SomeResolvedLibraryResult> getResolvedLibrary(String path) {
     _checkConsistency();
     return _driver.getResolvedLibrary2(path);
   }
 
+  @Deprecated('Use getResolvedLibrary() instead')
   @override
-  Future<SomeResolvedLibraryResult> getResolvedLibraryByElement2(
+  Future<SomeResolvedLibraryResult> getResolvedLibrary2(String path) {
+    return getResolvedLibrary(path);
+  }
+
+  @override
+  Future<SomeResolvedLibraryResult> getResolvedLibraryByElement(
     LibraryElement element,
   ) {
     _checkConsistency();
@@ -116,18 +158,38 @@
     return _driver.getResolvedLibraryByUri2(element.source.uri);
   }
 
+  @Deprecated('Use getResolvedLibraryByElement() instead')
   @override
-  Future<SomeResolvedUnitResult> getResolvedUnit2(String path) {
+  Future<SomeResolvedLibraryResult> getResolvedLibraryByElement2(
+    LibraryElement element,
+  ) {
+    return getResolvedLibraryByElement(element);
+  }
+
+  @override
+  Future<SomeResolvedUnitResult> getResolvedUnit(String path) {
     _checkConsistency();
     return _driver.getResult2(path);
   }
 
+  @Deprecated('Use getResolvedUnit() instead')
   @override
-  Future<SomeUnitElementResult> getUnitElement2(String path) {
+  Future<SomeResolvedUnitResult> getResolvedUnit2(String path) {
+    return getResolvedUnit(path);
+  }
+
+  @override
+  Future<SomeUnitElementResult> getUnitElement(String path) {
     _checkConsistency();
     return _driver.getUnitElement2(path);
   }
 
+  @Deprecated('Use getUnitElement() instead')
+  @override
+  Future<SomeUnitElementResult> getUnitElement2(String path) {
+    return getUnitElement(path);
+  }
+
   /// Check to see that results from this session will be consistent, and throw
   /// an [InconsistentAnalysisException] if they might not be.
   void _checkConsistency() {
diff --git a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
index 020af5d..a7bc83a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session_helper.dart
@@ -22,7 +22,7 @@
   /// from the library with the given [libraryUri], or `null` if the library
   /// does not export a class with such name.
   Future<ClassElement?> getClass(String libraryUri, String className) async {
-    var libraryResult = await session.getLibraryByUri2(libraryUri);
+    var libraryResult = await session.getLibraryByUri(libraryUri);
     if (libraryResult is LibraryElementResult) {
       var element = libraryResult.element.exportNamespace.get(className);
       if (element is ClassElement) {
@@ -50,7 +50,7 @@
     }
 
     var unitPath = element.source!.fullName;
-    return resolvedLibrary.units!.singleWhere((resolvedUnit) {
+    return resolvedLibrary.units.singleWhere((resolvedUnit) {
       return resolvedUnit.path == unitPath;
     });
   }
@@ -60,7 +60,7 @@
   /// library does not export a top-level accessor with such name.
   Future<PropertyAccessorElement?> getTopLevelPropertyAccessor(
       String uri, String name) async {
-    var libraryResult = await session.getLibraryByUri2(uri);
+    var libraryResult = await session.getLibraryByUri(uri);
     if (libraryResult is LibraryElementResult) {
       var element = libraryResult.element.exportNamespace.get(name);
       if (element is PropertyAccessorElement) {
@@ -74,7 +74,7 @@
   Future<ResolvedLibraryResult?> _getResolvedLibrary(String path) async {
     var result = _resolvedLibraries[path];
     if (result == null) {
-      var some = await session.getResolvedLibrary2(path);
+      var some = await session.getResolvedLibrary(path);
       if (some is ResolvedLibraryResult) {
         result = _resolvedLibraries[path] = some;
       }
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 874c8f5..9256fa8 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -5892,8 +5892,7 @@
 
     final parent = this.parent;
     if (parent is CompoundAssignmentExpression) {
-      var assignment = parent as CompoundAssignmentExpression;
-      element = assignment.writeElement ?? assignment.readElement;
+      element = parent.writeElement ?? parent.readElement;
     }
 
     if (element is ExecutableElement) {
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 605628f..4387e37 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -1302,38 +1302,19 @@
   }
 }
 
-/// A [DelegatingAstVisitor] that will additionally catch all exceptions from
-/// the delegates without stopping the visiting. A function must be provided
-/// that will be invoked for each such exception.
+/// Class capable of handling exceptions generated during linting.
 ///
 /// Clients may not extend, implement or mix-in this class.
-class ExceptionHandlingDelegatingAstVisitor<T> extends DelegatingAstVisitor<T> {
-  /// The function that will be executed for each exception that is thrown by
-  /// one of the visit methods on the delegate.
-  final ExceptionInDelegateHandler handler;
+class LinterExceptionHandler {
+  /// Indicates whether linter exceptions should be propagated to the caller (by
+  /// re-throwing them)
+  final bool propagateLinterExceptions;
 
-  /// Initialize a newly created visitor to use each of the given delegate
-  /// visitors to visit the nodes of an AST structure.
-  ExceptionHandlingDelegatingAstVisitor(
-      Iterable<AstVisitor<T>> delegates, this.handler)
-      : super(delegates);
+  LinterExceptionHandler(this.propagateLinterExceptions);
 
-  @override
-  T? visitNode(AstNode node) {
-    delegates.forEach((delegate) {
-      try {
-        node.accept(delegate);
-      } catch (exception, stackTrace) {
-        handler(node, delegate, exception, stackTrace);
-      }
-    });
-    node.visitChildren(this);
-    return null;
-  }
-
-  /// A function that can be used with instances of this class to log and then
-  /// ignore any exceptions that are thrown by any of the delegates.
-  static void logException(
+  /// A method that can be passed to the `LinterVisitor` constructor to handle
+  /// exceptions that occur during linting.
+  void logException(
       AstNode node, Object visitor, dynamic exception, StackTrace stackTrace) {
     StringBuffer buffer = StringBuffer();
     buffer.write('Exception while using a ${visitor.runtimeType} to visit a ');
@@ -1351,6 +1332,9 @@
     // TODO(39284): should this exception be silent?
     AnalysisEngine.instance.instrumentationService.logException(
         SilentException(buffer.toString(), exception, stackTrace));
+    if (propagateLinterExceptions) {
+      throw exception;
+    }
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 2bdca7a..549e1bc 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:collection';
+import 'dart:typed_data';
 
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/session.dart';
@@ -14,6 +15,7 @@
 import 'package:analyzer/dart/element/scope.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/session.dart';
 import 'package:analyzer/src/dart/ast/ast_factory.dart';
@@ -610,6 +612,42 @@
   @override
   bool get isDartCoreObject => !isMixin && supertype == null;
 
+  bool get isEnumLike {
+    // Must be a concrete class.
+    if (isAbstract || isMixin) {
+      return false;
+    }
+
+    // With only private non-factory constructors.
+    for (var constructor in constructors) {
+      if (constructor.isPublic || constructor.isFactory) {
+        return false;
+      }
+    }
+
+    // With 2+ static const fields with the type of this class.
+    var numberOfElements = 0;
+    for (var field in fields) {
+      if (field.isStatic && field.isConst && field.type == thisType) {
+        numberOfElements++;
+      }
+    }
+    if (numberOfElements < 2) {
+      return false;
+    }
+
+    // No subclasses in the library.
+    for (var unit in library.units) {
+      for (var class_ in unit.classes) {
+        if (class_.supertype?.element == this) {
+          return false;
+        }
+      }
+    }
+
+    return true;
+  }
+
   @override
   bool get isMixinApplication {
     return hasModifier(Modifier.MIXIN_APPLICATION);
@@ -910,6 +948,10 @@
 
   static ConstructorElement? getNamedConstructorFromList(
       String name, List<ConstructorElement> constructors) {
+    if (name == 'new') {
+      // An unnamed constructor declared with `C.new(` is modeled as unnamed.
+      name = '';
+    }
     for (ConstructorElement element in constructors) {
       if (element.name == name) {
         return element;
@@ -1367,7 +1409,7 @@
 /// A concrete implementation of a [ConstructorElement].
 class ConstructorElementImpl extends ExecutableElementImpl
     with ConstructorElementMixin
-    implements ConstructorElement {
+    implements ConstructorElement, HasMacroGenerationData {
   /// The constructor to which this constructor is redirecting.
   ConstructorElement? _redirectedConstructor;
 
@@ -1376,6 +1418,9 @@
   List<ConstructorInitializer> _constantInitializers = const [];
 
   @override
+  MacroGenerationData? macro;
+
+  @override
   int? periodOffset;
 
   @override
@@ -2010,9 +2055,6 @@
   /// The length of the element's code, or `null` if the element is synthetic.
   int? _codeLength;
 
-  /// The language version for the library.
-  LibraryLanguageVersion? _languageVersion;
-
   /// Initialize a newly created element to have the given [name] at the given
   /// [_nameOffset].
   ElementImpl(String? name, this._nameOffset, {this.reference}) {
@@ -3435,6 +3477,13 @@
   }
 }
 
+/// This interface is implemented by [Element]s that can be added by macros.
+abstract class HasMacroGenerationData {
+  /// If this element was added by a macro, the code of a declaration that
+  /// was produced by the macro.
+  MacroGenerationData? macro;
+}
+
 /// A concrete implementation of a [HideElementCombinator].
 class HideElementCombinatorImpl implements HideElementCombinator {
   @override
@@ -3575,6 +3624,9 @@
   @override
   final AnalysisSession session;
 
+  /// The language version for the library.
+  LibraryLanguageVersion? _languageVersion;
+
   bool hasTypeProviderSystemSet = false;
 
   @override
@@ -3958,6 +4010,64 @@
     return getTypeFromParts(className, _definingCompilationUnit, _parts);
   }
 
+  /// Indicates whether it is unnecessary to report an undefined identifier
+  /// error for an identifier reference with the given [name] and optional
+  /// [prefix].
+  ///
+  /// This method is intended to reduce spurious errors in circumstances where
+  /// an undefined identifier occurs as the result of a missing (most likely
+  /// code generated) file.  It will only return `true` in a circumstance where
+  /// the current library is guaranteed to have at least one other error (due to
+  /// a missing part or import), so there is no risk that ignoring the undefined
+  /// identifier would cause an invalid program to be treated as valid.
+  bool shouldIgnoreUndefined({
+    required String? prefix,
+    required String name,
+  }) {
+    for (var importElement in imports) {
+      if (importElement.prefix?.name == prefix &&
+          importElement.importedLibrary?.isSynthetic != false) {
+        var showCombinators = importElement.combinators
+            .whereType<ShowElementCombinator>()
+            .toList();
+        if (prefix != null && showCombinators.isEmpty) {
+          return true;
+        }
+        for (var combinator in showCombinators) {
+          if (combinator.shownNames.contains(name)) {
+            return true;
+          }
+        }
+      }
+    }
+
+    if (prefix == null && name.startsWith(r'_$')) {
+      for (var partElement in parts) {
+        if (partElement.isSynthetic && isGeneratedSource(partElement.source)) {
+          return true;
+        }
+      }
+    }
+
+    return false;
+  }
+
+  /// Convenience wrapper around [shouldIgnoreUndefined] that calls it for a
+  /// given (possibly prefixed) identifier [node].
+  bool shouldIgnoreUndefinedIdentifier(Identifier node) {
+    if (node is PrefixedIdentifier) {
+      return shouldIgnoreUndefined(
+        prefix: node.prefix.name,
+        name: node.identifier.name,
+      );
+    }
+
+    return shouldIgnoreUndefined(
+      prefix: null,
+      name: (node as SimpleIdentifier).name,
+    );
+  }
+
   @override
   T toLegacyElementIfOptOut<T extends Element>(T element) {
     if (isNonNullableByDefault) return element;
@@ -4049,8 +4159,36 @@
       visitor.visitLocalVariableElement(this);
 }
 
+/// Information about a macro-produced [Element].
+class MacroGenerationData {
+  /// The sequential id of this macro-produced element, for an element created
+  /// for a declaration that was macro-generated later this value is greater.
+  ///
+  /// This is different from [ElementImpl.id], which is also incrementing,
+  /// but shows the order in which elements were built from declarations,
+  /// not the order of declarations, and we process all field declarations
+  /// before method declarations.
+  final int id;
+
+  /// The code that was produced by the macro. It is used to compose full
+  /// code of a unit to display to the user, so that new declarations are
+  /// added to the unit or existing classes.
+  ///
+  /// When a class is generated, its code might have some members, or might
+  /// be empty, and new elements might be macro-generated into it.
+  final String code;
+
+  /// When we build elements from macro-produced code, we remember informative
+  /// data, such as offsets - to store it into bytes. This field is set to
+  /// an empty list when reading from bytes.
+  final Uint8List informative;
+
+  MacroGenerationData(this.id, this.code, this.informative);
+}
+
 /// A concrete implementation of a [MethodElement].
-class MethodElementImpl extends ExecutableElementImpl implements MethodElement {
+class MethodElementImpl extends ExecutableElementImpl
+    implements MethodElement, HasMacroGenerationData {
   /// Is `true` if this method is `operator==`, and there is no explicit
   /// type specified for its formal parameter, in this method or in any
   /// overridden methods other than the one declared in `Object`.
@@ -4060,6 +4198,9 @@
   /// this variable is not a subject of type inference, or there was no error.
   TopLevelInferenceError? typeInferenceError;
 
+  @override
+  MacroGenerationData? macro;
+
   /// Initialize a newly created method element to have the given [name] at the
   /// given [offset].
   MethodElementImpl(String name, int offset) : super(name, offset);
@@ -4863,11 +5004,14 @@
 
 /// A concrete implementation of a [PropertyAccessorElement].
 class PropertyAccessorElementImpl extends ExecutableElementImpl
-    implements PropertyAccessorElement {
+    implements PropertyAccessorElement, HasMacroGenerationData {
   /// The variable associated with this accessor.
   @override
   late PropertyInducingElement variable;
 
+  @override
+  MacroGenerationData? macro;
+
   /// Initialize a newly created property accessor element to have the given
   /// [name] and [offset].
   PropertyAccessorElementImpl(String name, int offset) : super(name, offset);
@@ -5423,23 +5567,29 @@
         parameters: type.parameters,
         returnType: type.returnType,
         nullabilitySuffix: resultNullability,
-        aliasElement: this,
-        aliasArguments: typeArguments,
+        alias: InstantiatedTypeAliasElementImpl(
+          element: this,
+          typeArguments: typeArguments,
+        ),
       );
     } else if (type is InterfaceType) {
       return InterfaceTypeImpl(
         element: type.element,
         typeArguments: type.typeArguments,
         nullabilitySuffix: resultNullability,
-        aliasElement: this,
-        aliasArguments: typeArguments,
+        alias: InstantiatedTypeAliasElementImpl(
+          element: this,
+          typeArguments: typeArguments,
+        ),
       );
     } else if (type is TypeParameterType) {
       return TypeParameterTypeImpl(
         element: type.element,
         nullabilitySuffix: resultNullability,
-        aliasElement: this,
-        aliasArguments: typeArguments,
+        alias: InstantiatedTypeAliasElementImpl(
+          element: this,
+          typeArguments: typeArguments,
+        ),
       );
     } else {
       return (type as TypeImpl).withNullability(resultNullability);
diff --git a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
index b05ab3d..f4077d4 100644
--- a/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
+++ b/pkg/analyzer/lib/src/dart/element/generic_inferrer.dart
@@ -583,7 +583,7 @@
           if (typeElement != null && typeElement.hasOptionalTypeArgs) {
             return;
           }
-          var typeAliasElement = type.aliasElement;
+          var typeAliasElement = type.alias?.element;
           if (typeAliasElement != null &&
               typeAliasElement.hasOptionalTypeArgs) {
             return;
diff --git a/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart b/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart
index 5709733..2db9a85 100644
--- a/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/replace_top_bottom_visitor.dart
@@ -53,8 +53,9 @@
       }
     }
 
-    if (type.aliasElement != null) {
-      return _typeAliasInstantiation(type, variance);
+    var alias = type.alias;
+    if (alias != null) {
+      return _instantiatedTypeAlias(type, alias, variance);
     } else if (type is InterfaceType) {
       return _interfaceType(type, variance);
     } else if (type is FunctionType) {
@@ -83,6 +84,34 @@
     );
   }
 
+  DartType _instantiatedTypeAlias(
+    DartType type,
+    InstantiatedTypeAliasElement alias,
+    Variance variance,
+  ) {
+    var aliasElement = alias.element;
+    var aliasArguments = alias.typeArguments;
+
+    var typeParameters = aliasElement.typeParameters;
+    assert(typeParameters.length == aliasArguments.length);
+
+    var newTypeArguments = <DartType>[];
+    for (var i = 0; i < typeParameters.length; i++) {
+      var typeParameter = typeParameters[i] as TypeParameterElementImpl;
+      newTypeArguments.add(
+        process(
+          aliasArguments[i],
+          typeParameter.variance.combine(variance),
+        ),
+      );
+    }
+
+    return aliasElement.instantiate(
+      typeArguments: newTypeArguments,
+      nullabilitySuffix: type.nullabilitySuffix,
+    );
+  }
+
   DartType _interfaceType(InterfaceType type, Variance variance) {
     var typeParameters = type.element.typeParameters;
     if (typeParameters.isEmpty) {
@@ -105,30 +134,6 @@
     );
   }
 
-  DartType _typeAliasInstantiation(DartType type, Variance variance) {
-    var aliasElement = type.aliasElement!;
-    var aliasArguments = type.aliasArguments!;
-
-    var typeParameters = aliasElement.typeParameters;
-    assert(typeParameters.length == aliasArguments.length);
-
-    var newTypeArguments = <DartType>[];
-    for (var i = 0; i < typeParameters.length; i++) {
-      var typeParameter = typeParameters[i] as TypeParameterElementImpl;
-      newTypeArguments.add(
-        process(
-          aliasArguments[i],
-          typeParameter.variance.combine(variance),
-        ),
-      );
-    }
-
-    return aliasElement.instantiate(
-      typeArguments: newTypeArguments,
-      nullabilitySuffix: type.nullabilitySuffix,
-    );
-  }
-
   /// Runs an instance of the visitor on the given [type] and returns the
   /// resulting type.  If the type contains no instances of Top or Bottom, the
   /// original type object is returned to avoid unnecessary allocation.
diff --git a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
index c1c1a79..638ad0f 100644
--- a/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/element/replacement_visitor.dart
@@ -29,13 +29,14 @@
 
   DartType? createFunctionType({
     required FunctionType type,
-    required List<DartType>? newAliasArguments,
+    required InstantiatedTypeAliasElement? newAlias,
     required List<TypeParameterElement>? newTypeParameters,
     required List<ParameterElement>? newParameters,
     required DartType? newReturnType,
     required NullabilitySuffix? newNullability,
   }) {
-    if (newNullability == null &&
+    if (newAlias == null &&
+        newNullability == null &&
         newReturnType == null &&
         newParameters == null) {
       return null;
@@ -46,8 +47,7 @@
       parameters: newParameters ?? type.parameters,
       returnType: newReturnType ?? type.returnType,
       nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
-      aliasElement: type.aliasElement,
-      aliasArguments: newAliasArguments ?? type.aliasArguments,
+      alias: newAlias ?? type.alias,
     );
   }
 
@@ -74,11 +74,11 @@
 
   DartType? createInterfaceType({
     required InterfaceType type,
-    required List<DartType>? newAliasArguments,
+    required InstantiatedTypeAliasElement? newAlias,
     required List<DartType>? newTypeArguments,
     required NullabilitySuffix? newNullability,
   }) {
-    if (newAliasArguments == null &&
+    if (newAlias == null &&
         newTypeArguments == null &&
         newNullability == null) {
       return null;
@@ -88,8 +88,7 @@
       element: type.element,
       typeArguments: newTypeArguments ?? type.typeArguments,
       nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
-      aliasElement: type.aliasElement,
-      aliasArguments: newAliasArguments ?? type.aliasArguments,
+      alias: newAlias ?? type.alias,
     );
   }
 
@@ -136,8 +135,7 @@
       element: type.element,
       nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
       promotedBound: newPromotedBound ?? promotedBound,
-      aliasElement: type.aliasElement,
-      aliasArguments: type.aliasArguments,
+      alias: type.alias,
     );
   }
 
@@ -152,8 +150,7 @@
     return TypeParameterTypeImpl(
       element: type.element,
       nullabilitySuffix: newNullability,
-      aliasElement: type.aliasElement,
-      aliasArguments: type.aliasArguments,
+      alias: type.alias,
     );
   }
 
@@ -215,16 +212,24 @@
 
     var newReturnType = visitType(node.returnType);
 
-    List<DartType>? newAliasArguments;
-    var aliasArguments = node.aliasArguments;
-    if (aliasArguments != null) {
+    InstantiatedTypeAliasElement? newAlias;
+    var alias = node.alias;
+    if (alias != null) {
+      List<DartType>? newArguments;
+      var aliasArguments = alias.typeArguments;
       for (var i = 0; i < aliasArguments.length; i++) {
         var substitution = aliasArguments[i].accept(this);
         if (substitution != null) {
-          newAliasArguments ??= aliasArguments.toList(growable: false);
-          newAliasArguments[i] = substitution;
+          newArguments ??= aliasArguments.toList(growable: false);
+          newArguments[i] = substitution;
         }
       }
+      if (newArguments != null) {
+        newAlias = InstantiatedTypeAliasElementImpl(
+          element: alias.element,
+          typeArguments: newArguments,
+        );
+      }
     }
 
     changeVariance();
@@ -253,7 +258,7 @@
 
     return createFunctionType(
       type: node,
-      newAliasArguments: newAliasArguments,
+      newAlias: newAlias,
       newTypeParameters: newTypeParameters,
       newParameters: newParameters,
       newReturnType: newReturnType,
@@ -351,13 +356,20 @@
   DartType? visitInterfaceType(InterfaceType type) {
     var newNullability = visitNullability(type);
 
-    var aliasElement = type.aliasElement;
-    var newAliasArguments = aliasElement != null
-        ? _typeArguments(
-            aliasElement.typeParameters,
-            type.aliasArguments,
-          )
-        : null;
+    InstantiatedTypeAliasElement? newAlias;
+    var alias = type.alias;
+    if (alias != null) {
+      var newArguments = _typeArguments(
+        alias.element.typeParameters,
+        alias.typeArguments,
+      );
+      if (newArguments != null) {
+        newAlias = InstantiatedTypeAliasElementImpl(
+          element: alias.element,
+          typeArguments: newArguments,
+        );
+      }
+    }
 
     var newTypeArguments = _typeArguments(
       type.element.typeParameters,
@@ -366,7 +378,7 @@
 
     return createInterfaceType(
       type: type,
-      newAliasArguments: newAliasArguments,
+      newAlias: newAlias,
       newTypeArguments: newTypeArguments,
       newNullability: newNullability,
     );
@@ -453,12 +465,8 @@
 
   List<DartType>? _typeArguments(
     List<TypeParameterElement> parameters,
-    List<DartType>? arguments,
+    List<DartType> arguments,
   ) {
-    if (arguments == null) {
-      return null;
-    }
-
     if (arguments.length != parameters.length) {
       return null;
     }
diff --git a/pkg/analyzer/lib/src/dart/element/scope.dart b/pkg/analyzer/lib/src/dart/element/scope.dart
index 1f15606..4df2190 100644
--- a/pkg/analyzer/lib/src/dart/element/scope.dart
+++ b/pkg/analyzer/lib/src/dart/element/scope.dart
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/scope.dart';
-import 'package:analyzer/src/context/source.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart' as impl;
 
@@ -104,38 +103,6 @@
     _element.units.forEach(_addUnitElements);
   }
 
-  bool shouldIgnoreUndefined({
-    required String? prefix,
-    required String name,
-  }) {
-    for (var importElement in _element.imports) {
-      if (importElement.prefix?.name == prefix &&
-          importElement.importedLibrary?.isSynthetic != false) {
-        var showCombinators = importElement.combinators
-            .whereType<ShowElementCombinator>()
-            .toList();
-        if (prefix != null && showCombinators.isEmpty) {
-          return true;
-        }
-        for (var combinator in showCombinators) {
-          if (combinator.shownNames.contains(name)) {
-            return true;
-          }
-        }
-      }
-    }
-
-    if (prefix == null && name.startsWith(r'_$')) {
-      for (var partElement in _element.parts) {
-        if (partElement.isSynthetic && isGeneratedSource(partElement.source)) {
-          return true;
-        }
-      }
-    }
-
-    return false;
-  }
-
   void _addExtension(ExtensionElement element) {
     _addGetter(element);
     if (!extensions.contains(element)) {
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index a123137..846f845 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -109,13 +109,12 @@
     required List<ParameterElement> parameters,
     required DartType returnType,
     required NullabilitySuffix nullabilitySuffix,
-    TypeAliasElement? aliasElement,
-    List<DartType>? aliasArguments,
+    InstantiatedTypeAliasElement? alias,
   })  : typeFormals = typeFormals,
         parameters = _sortNamedParameters(parameters),
         returnType = returnType,
         nullabilitySuffix = nullabilitySuffix,
-        super(null, aliasElement: aliasElement, aliasArguments: aliasArguments);
+        super(null, alias: alias);
 
   @override
   int get hashCode {
@@ -297,8 +296,7 @@
       parameters: parameters,
       returnType: returnType,
       nullabilitySuffix: nullabilitySuffix,
-      aliasElement: aliasElement,
-      aliasArguments: aliasArguments,
+      alias: alias,
     );
   }
 
@@ -610,6 +608,19 @@
   }
 }
 
+class InstantiatedTypeAliasElementImpl implements InstantiatedTypeAliasElement {
+  @override
+  final TypeAliasElement element;
+
+  @override
+  final List<DartType> typeArguments;
+
+  InstantiatedTypeAliasElementImpl({
+    required this.element,
+    required this.typeArguments,
+  });
+}
+
 /// A concrete implementation of an [InterfaceType].
 class InterfaceTypeImpl extends TypeImpl implements InterfaceType {
   @override
@@ -631,12 +642,10 @@
     required ClassElement element,
     required this.typeArguments,
     required this.nullabilitySuffix,
-    TypeAliasElement? aliasElement,
-    List<DartType>? aliasArguments,
+    InstantiatedTypeAliasElement? alias,
   }) : super(
           element,
-          aliasElement: aliasElement,
-          aliasArguments: aliasArguments,
+          alias: alias,
         );
 
   @override
@@ -1615,19 +1624,26 @@
 /// representing the declared type of elements in the element model.
 abstract class TypeImpl implements DartType {
   @override
-  final List<DartType>? aliasArguments;
-
-  @override
-  final TypeAliasElement? aliasElement;
+  InstantiatedTypeAliasElement? alias;
 
   /// The element representing the declaration of this type, or `null` if the
   /// type has not, or cannot, be associated with an element.
   final Element? _element;
 
   /// Initialize a newly created type to be declared by the given [element].
-  TypeImpl(this._element, {this.aliasElement, this.aliasArguments})
-      : assert(aliasElement == null && aliasArguments == null ||
-            aliasElement != null && aliasArguments != null);
+  TypeImpl(this._element, {this.alias});
+
+  @Deprecated('Use alias instead')
+  @override
+  List<DartType>? get aliasArguments {
+    return alias?.typeArguments;
+  }
+
+  @Deprecated('Use alias instead')
+  @override
+  TypeAliasElement? get aliasElement {
+    return alias?.element;
+  }
 
   @deprecated
   @override
@@ -1774,12 +1790,10 @@
     required TypeParameterElement element,
     required this.nullabilitySuffix,
     this.promotedBound,
-    TypeAliasElement? aliasElement,
-    List<DartType>? aliasArguments,
+    InstantiatedTypeAliasElement? alias,
   }) : super(
           element,
-          aliasElement: aliasElement,
-          aliasArguments: aliasArguments,
+          alias: alias,
         );
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/element/type_algebra.dart b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
index 326f73a..9057b2c 100644
--- a/pkg/analyzer/lib/src/dart/element/type_algebra.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_algebra.dart
@@ -444,9 +444,13 @@
 
     var returnType = type.returnType.accept(inner);
 
-    var aliasArguments = type.aliasArguments;
-    var newAliasArguments =
-        aliasArguments != null ? _mapList(aliasArguments) : null;
+    var alias = type.alias;
+    var newAlias = alias != null
+        ? InstantiatedTypeAliasElementImpl(
+            element: alias.element,
+            typeArguments: _mapList(alias.typeArguments),
+          )
+        : null;
 
     if (useCounter == before) return type;
 
@@ -455,8 +459,7 @@
       parameters: parameters,
       returnType: returnType,
       nullabilitySuffix: type.nullabilitySuffix,
-      aliasElement: type.aliasElement,
-      aliasArguments: newAliasArguments,
+      alias: newAlias,
     );
   }
 
diff --git a/pkg/analyzer/lib/src/dart/element/type_demotion.dart b/pkg/analyzer/lib/src/dart/element/type_demotion.dart
index 4b1cc1a..4839abe 100644
--- a/pkg/analyzer/lib/src/dart/element/type_demotion.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_demotion.dart
@@ -38,8 +38,7 @@
         return TypeParameterTypeImpl(
           element: type.element,
           nullabilitySuffix: newNullability ?? type.nullabilitySuffix,
-          aliasElement: type.aliasElement,
-          aliasArguments: type.aliasArguments,
+          alias: type.alias,
         );
       }
     }
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index a299c7d..711f2ab 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -628,7 +628,7 @@
             appendParameters(type.returnType);
             type.parameters.map((p) => p.type).forEach(appendParameters);
             // TODO(scheglov) https://github.com/dart-lang/sdk/issues/44218
-            type.aliasArguments?.forEach(appendParameters);
+            type.alias?.typeArguments.forEach(appendParameters);
           } else if (type is InterfaceType) {
             type.typeArguments.forEach(appendParameters);
           }
diff --git a/pkg/analyzer/lib/src/dart/error/ffi_code.dart b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
index 639a3f3..d8600d8 100644
--- a/pkg/analyzer/lib/src/dart/error/ffi_code.dart
+++ b/pkg/analyzer/lib/src/dart/error/ffi_code.dart
@@ -69,6 +69,14 @@
   /**
    * No parameters.
    */
+  static const FfiCode FFI_NATIVE_ONLY_STATIC = FfiCode(
+      name: 'FFI_NATIVE_ONLY_STATIC',
+      message: "FfiNative annotations can only be used on static functions.",
+      correction: "Change the method to static.");
+
+  /**
+   * No parameters.
+   */
   static const FfiCode FIELD_IN_STRUCT_WITH_INITIALIZER = FfiCode(
       name: 'FIELD_IN_STRUCT_WITH_INITIALIZER',
       message:
diff --git a/pkg/analyzer/lib/src/dart/micro/analysis_context.dart b/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
index 4d79d83..ef663ca 100644
--- a/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
+++ b/pkg/analyzer/lib/src/dart/micro/analysis_context.dart
@@ -181,18 +181,18 @@
   }
 
   @override
-  Future<SomeLibraryElementResult> getLibraryByUri2(String uriStr) async {
+  Future<SomeLibraryElementResult> getLibraryByUri(String uriStr) async {
     var element = analysisContext.fileResolver.getLibraryByUri(uriStr: uriStr);
     return LibraryElementResultImpl(element);
   }
 
   @override
-  Future<SomeResolvedLibraryResult> getResolvedLibrary2(String path) async {
+  Future<SomeResolvedLibraryResult> getResolvedLibrary(String path) async {
     return analysisContext.fileResolver.resolveLibrary(path: path);
   }
 
   @override
-  Future<SomeResolvedUnitResult> getResolvedUnit2(String path) async {
+  Future<SomeResolvedUnitResult> getResolvedUnit(String path) async {
     return analysisContext.fileResolver.resolve(path: path);
   }
 
diff --git a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
index 2d5a144..327af6e 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_analyzer.dart
@@ -332,7 +332,6 @@
     ErrorReporter errorReporter = _getErrorReporter(file);
 
     var nodeRegistry = NodeLintRegistry(_analysisOptions.enableTiming);
-    var visitors = <AstVisitor>[];
     final workspacePackage = _getPackage(currentUnit.unit);
     var context = LinterContextImpl(
         allUnits,
@@ -350,14 +349,9 @@
 
     // Run lints that handle specific node types.
     unit.accept(LinterVisitor(
-        nodeRegistry, ExceptionHandlingDelegatingAstVisitor.logException));
-
-    // Run visitor based lints.
-    if (visitors.isNotEmpty) {
-      AstVisitor visitor = ExceptionHandlingDelegatingAstVisitor(
-          visitors, ExceptionHandlingDelegatingAstVisitor.logException);
-      unit.accept(visitor);
-    }
+        nodeRegistry,
+        LinterExceptionHandler(_analysisOptions.propagateLinterExceptions)
+            .logException));
   }
 
   void _computeVerifyErrors(FileState file, CompilationUnit unit) {
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 2608588..d52742b 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -39,6 +39,7 @@
 import 'package:analyzer/src/util/performance/operation_performance.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:collection/collection.dart';
+import 'package:meta/meta.dart';
 import 'package:yaml/yaml.dart';
 
 const M = 1024 * 1024 /*1 MiB*/;
@@ -109,7 +110,8 @@
   /// It is used to allow assists and fixes without resolving the same file
   /// multiple times, as we compute more than one assist, or fixes when there
   /// are more than one error on a line.
-  final Map<String, ResolvedLibraryResult> _cachedResults = {};
+  @visibleForTesting
+  final Map<String, ResolvedLibraryResult> cachedResults = {};
 
   FileResolver(
     PerformanceLog logger,
@@ -164,7 +166,7 @@
     }
 
     // Forget all results, anything is potentially affected.
-    _cachedResults.clear();
+    cachedResults.clear();
 
     // Remove this file and all files that transitively depend on it.
     var removedFiles = <FileState>[];
@@ -208,7 +210,7 @@
       result.forEach((filePath) {
         var resolved = resolve(path: filePath);
         var collector = ReferencesCollector(element);
-        resolved.unit?.accept(collector);
+        resolved.unit.accept(collector);
         var offsets = collector.offsets;
         if (offsets.isNotEmpty) {
           references.add(CiderSearchMatch(filePath, offsets));
@@ -445,24 +447,16 @@
         }
       }
 
-      var libraryUnit = resolveLibrary(
+      var libraryResult = resolveLibrary(
         completionLine: completionLine,
         completionColumn: completionColumn,
         path: libraryFile.path,
-        completionPath: path,
+        completionPath: completionLine != null ? path : null,
         performance: performance,
       );
-      var result = libraryUnit.units!
-          .firstWhereOrNull((element) => element.path == path);
-      // TODO(scheglov) Fix and remove.
-      if (result == null) {
-        throw StateError('''
-libraryFile.path: ${libraryFile.path}
-path: $path
-units: ${libraryUnit.units!.map((e) => '(${e.uri} = ${e.path})').toList()}
-''');
-      }
-      return result;
+      return libraryResult.units.firstWhere(
+        (unitResult) => unitResult.path == path,
+      );
     });
   }
 
@@ -478,7 +472,7 @@
 
     performance ??= OperationPerformanceImpl('<default>');
 
-    var cachedResult = _cachedResults[path];
+    var cachedResult = cachedResults[path];
     if (cachedResult != null) {
       return cachedResult;
     }
@@ -513,7 +507,7 @@
         );
       });
 
-      testView?.addResolvedFile(path);
+      testView?.addResolvedLibrary(path);
 
       late Map<FileState, UnitAnalysisResult> results;
 
@@ -570,7 +564,11 @@
       var libraryUnit = resolvedUnits.first;
       var result = ResolvedLibraryResultImpl(contextObjects!.analysisSession,
           path, libraryUnit.uri, libraryUnit.libraryElement, resolvedUnits);
-      _cachedResults[path] = result;
+
+      if (completionPath == null) {
+        cachedResults[path] = result;
+      }
+
       return result;
     });
   }
@@ -764,13 +762,13 @@
 }
 
 class FileResolverTestView {
-  /// The paths of files which were resolved.
+  /// The paths of libraries which were resolved.
   ///
-  /// The file path is added every time when it is resolved.
-  final List<String> resolvedFiles = [];
+  /// The library path is added every time when it is resolved.
+  final List<String> resolvedLibraries = [];
 
-  void addResolvedFile(String path) {
-    resolvedFiles.add(path);
+  void addResolvedLibrary(String path) {
+    resolvedLibraries.add(path);
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
index 84260a2..76697c1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
@@ -25,13 +26,17 @@
   /// The resolver driving this participant.
   final ResolverVisitor _resolver;
 
+  /// Helper for extension method resolution.
+  final ExtensionMemberResolver _extensionResolver;
+
   final bool _isNonNullableByDefault;
 
   /// The type representing the type 'type'.
   final InterfaceType _typeType;
 
   FunctionReferenceResolver(this._resolver, this._isNonNullableByDefault)
-      : _typeType = _resolver.typeProvider.typeType;
+      : _extensionResolver = _resolver.extensionResolver,
+        _typeType = _resolver.typeProvider.typeType;
 
   ErrorReporter get _errorReporter => _resolver.errorReporter;
 
@@ -43,192 +48,44 @@
     node.typeArguments?.accept(_resolver);
 
     if (function is SimpleIdentifierImpl) {
-      var element = _resolver.nameScope.lookup(function.name).getter;
-
-      // Classes and type aliases are checked first so as to include a
-      // PropertyAccess parent check, which does not need to be done for
-      // functions.
-      if (element is ClassElement || element is TypeAliasElement) {
-        // A type-instantiated constructor tearoff like `C<int>.name` or
-        // `prefix.C<int>.name` is initially represented as a [PropertyAccess]
-        // with a [FunctionReference] target.
-        if (node.parent is PropertyAccess) {
-          _resolveConstructorReference(node);
-          return;
-        } else if (element is ClassElement) {
-          function.staticElement = element;
-          _resolveDirectTypeLiteral(node, function, element);
-          return;
-        } else if (element is TypeAliasElement) {
-          function.staticElement = element;
-          _resolveTypeAlias(node: node, element: element, typeAlias: function);
-          return;
-        }
-      } else if (element is ExecutableElement) {
-        function.staticElement = element;
-        _resolve(node: node, name: element.name, rawType: element.type);
-        return;
-      } else if (element is VariableElement) {
-        var functionType = element.type;
-        if (functionType is FunctionType) {
-          function.accept(_resolver);
-          _resolve(node: node, name: element.name ?? '', rawType: functionType);
-          return;
-        }
-      }
-    }
-
-    // TODO(srawlins): Handle `function` being a [SuperExpression].
-
-    if (function is PrefixedIdentifierImpl) {
-      var prefixElement =
-          _resolver.nameScope.lookup(function.prefix.name).getter;
-      function.prefix.staticElement = prefixElement;
-      if (prefixElement is PrefixElement) {
-        var functionName = function.identifier.name;
-        var functionElement = prefixElement.scope.lookup(functionName).getter;
-        if (functionElement == null) {
-          _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME,
-            function.identifier,
-            [function.identifier.name, function.prefix.name],
-          );
-          function.staticType = DynamicTypeImpl.instance;
-          node.staticType = DynamicTypeImpl.instance;
-          return;
-        } else {
-          functionElement = _resolver.toLegacyElement(functionElement);
-          _resolveReceiverPrefix(
-              node, prefixElement, function, functionElement);
-          return;
-        }
-      } else if (prefixElement is VariableElement) {
-        function.prefix.staticType = prefixElement.type;
-      } else if (prefixElement is PropertyAccessorElement) {
-        function.prefix.staticType = prefixElement.returnType;
-      }
-
-      var methodElement = _resolveTypeProperty(
-        receiver: function.prefix,
-        receiverElement: prefixElement,
-        name: function.identifier,
-        nameErrorEntity: function,
-      );
-
-      if (methodElement is MethodElement) {
-        function.identifier.staticElement = methodElement;
-        function.staticType = methodElement.type;
-        _resolve(
-          node: node,
-          name: function.identifier.name,
-          rawType: methodElement.type,
-        );
-        return;
-      }
-
-      // TODO(srawlins): Need to report cases where [methodElement] is not
-      // generic. The 'test_instanceGetter_explicitReceiver' test case needs to
-      // be updated to handle this.
+      _resolveSimpleIdentifierFunction(node, function);
+    } else if (function is PrefixedIdentifierImpl) {
+      _resolvePrefixedIdentifierFunction(node, function);
+    } else if (function is PropertyAccessImpl) {
+      _resolvePropertyAccessFunction(node, function);
+    } else {
+      // TODO(srawlins): Handle `function` being a [SuperExpression].
 
       function.accept(_resolver);
-      node.staticType = DynamicTypeImpl.instance;
-      return;
+      _resolveDisallowedExpression(node, node.function.staticType);
     }
-
-    if (function is PropertyAccessImpl) {
-      function.accept(_resolver);
-      var target = function.target;
-      DartType targetType;
-      if (target is SuperExpressionImpl) {
-        targetType = target.typeOrThrow;
-      } else if (target is ThisExpressionImpl) {
-        targetType = target.typeOrThrow;
-      } else if (target is SimpleIdentifierImpl) {
-        var targetElement = _resolver.nameScope.lookup(target.name).getter;
-        if (targetElement is VariableElement) {
-          targetType = targetElement.type;
-        } else if (targetElement is PropertyAccessorElement) {
-          targetType = targetElement.returnType;
-        } else {
-          // TODO(srawlins): Can we get here?
-          node.staticType = DynamicTypeImpl.instance;
-          return;
-        }
-      } else if (target is PrefixedIdentifierImpl) {
-        var prefixElement =
-            _resolver.nameScope.lookup(target.prefix.name).getter;
-        if (prefixElement is PrefixElement) {
-          var prefixName = target.identifier.name;
-          var targetElement = prefixElement.scope.lookup(prefixName).getter;
-
-          var methodElement = _resolveTypeProperty(
-            receiver: target,
-            receiverElement: targetElement,
-            name: function.propertyName,
-            nameErrorEntity: function,
-          );
-
-          if (methodElement == null) {
-            // TODO(srawlins): Can we get here?
-            node.staticType = DynamicTypeImpl.instance;
-            return;
-          } else {
-            _resolveReceiverPrefix(node, prefixElement, target, methodElement);
-            return;
-          }
-        } else {
-          // TODO(srawlins): Can we get here?
-          node.staticType = DynamicTypeImpl.instance;
-          return;
-        }
-      } else {
-        // TODO(srawlins): Can we get here?
-        node.staticType = DynamicTypeImpl.instance;
-        return;
-      }
-
-      var propertyElement = _resolver.typePropertyResolver
-          .resolve(
-            receiver: function.realTarget,
-            receiverType: targetType,
-            name: function.propertyName.name,
-            propertyErrorEntity: function.propertyName,
-            nameErrorEntity: function,
-          )
-          .getter;
-
-      var functionType = function.typeOrThrow;
-      if (functionType is FunctionType && propertyElement != null) {
-        _resolve(
-          node: node,
-          name: propertyElement.name,
-          rawType: functionType,
-        );
-        return;
-      }
-
-      // TODO(srawlins): Handle type variables bound to function type, like
-      // `T extends void Function<U>(U)`.
-    }
-
-    // TODO(srawlins): Enumerate and handle all cases that fall through to
-    // here; ultimately it should just be a case of "unknown identifier."
-    function.accept(_resolver);
-    node.staticType = DynamicTypeImpl.instance;
   }
 
   List<DartType> _checkTypeArguments(
     TypeArgumentList typeArgumentList,
-    String name,
+    String? name,
     List<TypeParameterElement> typeParameters,
     CompileTimeErrorCode errorCode,
   ) {
     if (typeArgumentList.arguments.length != typeParameters.length) {
-      _errorReporter.reportErrorForNode(
-        errorCode,
-        typeArgumentList,
-        [name, typeParameters.length, typeArgumentList.arguments.length],
-      );
+      if (name == null &&
+          errorCode ==
+              CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION) {
+        errorCode = CompileTimeErrorCode
+            .WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION;
+        _errorReporter.reportErrorForNode(
+          errorCode,
+          typeArgumentList,
+          [typeParameters.length, typeArgumentList.arguments.length],
+        );
+      } else {
+        assert(name != null);
+        _errorReporter.reportErrorForNode(
+          errorCode,
+          typeArgumentList,
+          [name, typeParameters.length, typeArgumentList.arguments.length],
+        );
+      }
       return List.filled(typeParameters.length, DynamicTypeImpl.instance);
     } else {
       return typeArgumentList.arguments
@@ -237,22 +94,68 @@
     }
   }
 
+  void _reportInvalidAccessToStaticMember(
+    SimpleIdentifier nameNode,
+    ExecutableElement element, {
+    required bool implicitReceiver,
+  }) {
+    if (_resolver.enclosingExtension != null) {
+      _resolver.errorReporter.reportErrorForNode(
+        CompileTimeErrorCode
+            .UNQUALIFIED_REFERENCE_TO_STATIC_MEMBER_OF_EXTENDED_TYPE,
+        nameNode,
+        [element.enclosingElement.displayName],
+      );
+    } else if (implicitReceiver) {
+      _resolver.errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER,
+        nameNode,
+        [element.enclosingElement.displayName],
+      );
+    } else {
+      _resolver.errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER,
+        nameNode,
+        [
+          nameNode.name,
+          element.kind.displayName,
+          element.enclosingElement.displayName,
+        ],
+      );
+    }
+  }
+
   /// Resolves [node]'s static type, as an instantiated function type, and type
   /// argument types, using [rawType] as the uninstantiated function type.
   void _resolve({
     required FunctionReferenceImpl node,
-    required String name,
-    required FunctionType rawType,
+    required DartType? rawType,
+    String? name,
   }) {
-    var typeArguments = _checkTypeArguments(
-      // `node.typeArguments`, coming from the parser, is never null.
-      node.typeArguments!, name, rawType.typeFormals,
-      CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
-    );
+    if (rawType == null) {
+      node.staticType = DynamicTypeImpl.instance;
+    }
 
-    var invokeType = rawType.instantiate(typeArguments);
-    node.typeArgumentTypes = typeArguments;
-    node.staticType = invokeType;
+    if (rawType is TypeParameterTypeImpl) {
+      // If the type of the function is a type parameter, the tearoff is
+      // disallowed, reported in [_resolveDisallowedExpression]. Use the type
+      // parameter's bound here in an attempt to assign the intended types.
+      rawType = rawType.element.bound;
+    }
+
+    if (rawType is FunctionType) {
+      var typeArguments = _checkTypeArguments(
+        // `node.typeArguments`, coming from the parser, is never null.
+        node.typeArguments!, name, rawType.typeFormals,
+        CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION,
+      );
+
+      var invokeType = rawType.instantiate(typeArguments);
+      node.typeArgumentTypes = typeArguments;
+      node.staticType = invokeType;
+    } else {
+      node.staticType = DynamicTypeImpl.instance;
+    }
   }
 
   void _resolveConstructorReference(FunctionReferenceImpl node) {
@@ -277,14 +180,220 @@
     _resolveTypeLiteral(node: node, instantiatedType: type, name: name);
   }
 
+  /// Resolves [node] as a type instantiation on an illegal expression.
+  ///
+  /// This function attempts to give [node] a static type, to continue working
+  /// with what the user may be intending.
+  void _resolveDisallowedExpression(
+      FunctionReferenceImpl node, DartType? rawType) {
+    _errorReporter.reportErrorForNode(
+      CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION,
+      node.function,
+      [],
+    );
+    _resolve(node: node, rawType: rawType);
+  }
+
+  void _resolveExtensionOverride(
+    FunctionReferenceImpl node,
+    PropertyAccessImpl function,
+    ExtensionOverride override,
+  ) {
+    var propertyName = function.propertyName;
+    var result =
+        _extensionResolver.getOverrideMember(override, propertyName.name);
+    var member = _resolver.toLegacyElement(result.getter);
+
+    if (member == null) {
+      node.staticType = DynamicTypeImpl.instance;
+      return;
+    }
+
+    if (member.isStatic) {
+      _resolver.errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.EXTENSION_OVERRIDE_ACCESS_TO_STATIC_MEMBER,
+        function.propertyName,
+      );
+      // Continue to resolve type.
+    }
+
+    if (function.isCascaded) {
+      _resolver.errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.EXTENSION_OVERRIDE_WITH_CASCADE,
+        override.extensionName,
+      );
+      // Continue to resolve type.
+    }
+
+    if (member is PropertyAccessorElement) {
+      function.accept(_resolver);
+      _resolveDisallowedExpression(node, member.returnType);
+      return;
+    }
+
+    _resolve(node: node, rawType: member.type, name: propertyName.name);
+  }
+
+  void _resolvePrefixedIdentifierFunction(
+      FunctionReferenceImpl node, PrefixedIdentifierImpl function) {
+    var prefixElement = _resolver.nameScope.lookup(function.prefix.name).getter;
+
+    if (prefixElement == null) {
+      _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
+        function.prefix,
+        [function.name],
+      );
+      function.staticType = DynamicTypeImpl.instance;
+      node.staticType = DynamicTypeImpl.instance;
+      return;
+    }
+
+    function.prefix.staticElement = prefixElement;
+    if (prefixElement is PrefixElement) {
+      var functionName = function.identifier.name;
+      var functionElement = prefixElement.scope.lookup(functionName).getter;
+      if (functionElement == null) {
+        _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME,
+          function.identifier,
+          [function.identifier.name, function.prefix.name],
+        );
+        function.staticType = DynamicTypeImpl.instance;
+        node.staticType = DynamicTypeImpl.instance;
+        return;
+      } else {
+        functionElement = _resolver.toLegacyElement(functionElement);
+        _resolveReceiverPrefix(node, prefixElement, function, functionElement);
+        return;
+      }
+    }
+
+    DartType? prefixType;
+    if (prefixElement is VariableElement) {
+      prefixType = prefixElement.type;
+    } else if (prefixElement is PropertyAccessorElement) {
+      prefixType = prefixElement.returnType;
+    }
+
+    function.prefix.staticType = prefixType;
+    if (prefixType != null && prefixType.isDynamic) {
+      // TODO(srawlins): Report error. See spec text: "We do not allow dynamic
+      // explicit instantiation."
+      node.staticType = DynamicTypeImpl.instance;
+      return;
+    }
+
+    var methodElement = _resolveTypeProperty(
+      receiver: function.prefix,
+      receiverElement: prefixElement,
+      name: function.identifier,
+      nameErrorEntity: function,
+    );
+
+    if (methodElement is MethodElement) {
+      function.identifier.staticElement = methodElement;
+      function.staticType = methodElement.type;
+      _resolve(
+        node: node,
+        rawType: methodElement.type,
+        name: function.identifier.name,
+      );
+      return;
+    }
+
+    if (methodElement is PropertyAccessorElement) {
+      function.accept(_resolver);
+      _resolveDisallowedExpression(node, methodElement.returnType);
+      return;
+    }
+
+    function.accept(_resolver);
+    node.staticType = DynamicTypeImpl.instance;
+  }
+
+  void _resolvePropertyAccessFunction(
+      FunctionReferenceImpl node, PropertyAccessImpl function) {
+    function.accept(_resolver);
+    var target = function.realTarget;
+
+    DartType targetType;
+    if (target is SuperExpressionImpl) {
+      targetType = target.typeOrThrow;
+    } else if (target is ThisExpressionImpl) {
+      targetType = target.typeOrThrow;
+    } else if (target is SimpleIdentifierImpl) {
+      var targetElement = _resolver.nameScope.lookup(target.name).getter;
+      if (targetElement is VariableElement) {
+        targetType = targetElement.type;
+      } else if (targetElement is PropertyAccessorElement) {
+        targetType = targetElement.returnType;
+      } else {
+        // TODO(srawlins): Can we get here?
+        node.staticType = DynamicTypeImpl.instance;
+        return;
+      }
+    } else if (target is PrefixedIdentifierImpl) {
+      var prefixElement = _resolver.nameScope.lookup(target.prefix.name).getter;
+      if (prefixElement is PrefixElement) {
+        var prefixName = target.identifier.name;
+        var targetElement = prefixElement.scope.lookup(prefixName).getter;
+
+        var methodElement = _resolveTypeProperty(
+          receiver: target,
+          receiverElement: targetElement,
+          name: function.propertyName,
+          nameErrorEntity: function,
+        );
+
+        if (methodElement == null) {
+          // TODO(srawlins): Can we get here?
+          node.staticType = DynamicTypeImpl.instance;
+          return;
+        } else {
+          _resolveReceiverPrefix(node, prefixElement, target, methodElement);
+          return;
+        }
+      } else {
+        // TODO(srawlins): Can we get here?
+        node.staticType = DynamicTypeImpl.instance;
+        return;
+      }
+    } else if (target is ExtensionOverrideImpl) {
+      _resolveExtensionOverride(node, function, target);
+      return;
+    } else {
+      targetType = target.typeOrThrow;
+    }
+
+    var propertyElement = _resolver.typePropertyResolver
+        .resolve(
+          receiver: function.realTarget,
+          receiverType: targetType,
+          name: function.propertyName.name,
+          propertyErrorEntity: function.propertyName,
+          nameErrorEntity: function,
+        )
+        .getter;
+
+    if (propertyElement is TypeParameterElement) {
+      _resolveDisallowedExpression(node, propertyElement!.type);
+      return;
+    }
+
+    _resolve(
+      node: node,
+      rawType: function.staticType,
+      name: propertyElement?.name,
+    );
+  }
+
   void _resolveReceiverPrefix(
     FunctionReferenceImpl node,
     PrefixElement prefixElement,
     PrefixedIdentifier prefix,
     Element element,
   ) {
-    // TODO(srawlins): Handle `loadLibrary`, as in `p.loadLibrary<int>;`.
-
     if (element is MultiplyDefinedElement) {
       MultiplyDefinedElement multiply = element;
       element = multiply.conflictingElements[0];
@@ -315,8 +424,8 @@
       node.function.accept(_resolver);
       _resolve(
         node: node,
-        name: element.name,
         rawType: node.function.typeOrThrow as FunctionType,
+        name: element.name,
       );
       return;
     }
@@ -326,6 +435,118 @@
     node.staticType = DynamicTypeImpl.instance;
   }
 
+  void _resolveSimpleIdentifierFunction(
+      FunctionReferenceImpl node, SimpleIdentifierImpl function) {
+    var element = _resolver.nameScope.lookup(function.name).getter;
+
+    if (element == null) {
+      DartType receiverType;
+      var enclosingClass = _resolver.enclosingClass;
+      if (enclosingClass != null) {
+        receiverType = enclosingClass.thisType;
+      } else {
+        var enclosingExtension = _resolver.enclosingExtension;
+        if (enclosingExtension != null) {
+          receiverType = enclosingExtension.extendedType;
+        } else {
+          _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
+            function,
+            [function.name],
+          );
+          function.staticType = DynamicTypeImpl.instance;
+          node.staticType = DynamicTypeImpl.instance;
+          return;
+        }
+      }
+
+      var result = _resolver.typePropertyResolver.resolve(
+        receiver: null,
+        receiverType: receiverType,
+        name: function.name,
+        propertyErrorEntity: function,
+        nameErrorEntity: function,
+      );
+
+      var method = result.getter;
+      if (method != null) {
+        if (method.isStatic) {
+          _reportInvalidAccessToStaticMember(function, method,
+              implicitReceiver: true);
+          // Continue to assign types.
+        }
+
+        if (method is PropertyAccessorElement) {
+          _resolveDisallowedExpression(node, method.returnType);
+          return;
+        }
+
+        function.staticElement = method;
+        function.staticType = method.type;
+        _resolve(node: node, rawType: method.type, name: function.name);
+        return;
+      } else {
+        _resolver.errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.UNDEFINED_METHOD,
+          function,
+          [function.name, enclosingClass],
+        );
+        function.staticType = DynamicTypeImpl.instance;
+        node.staticType = DynamicTypeImpl.instance;
+        return;
+      }
+    }
+
+    // Classes and type aliases are checked first so as to include a
+    // PropertyAccess parent check, which does not need to be done for
+    // functions.
+    if (element is ClassElement || element is TypeAliasElement) {
+      // A type-instantiated constructor tearoff like `C<int>.name` or
+      // `prefix.C<int>.name` is initially represented as a [PropertyAccess]
+      // with a [FunctionReference] target.
+      if (node.parent is PropertyAccess) {
+        _resolveConstructorReference(node);
+        return;
+      } else if (element is ClassElement) {
+        function.staticElement = element;
+        _resolveDirectTypeLiteral(node, function, element);
+        return;
+      } else if (element is TypeAliasElement) {
+        function.staticElement = element;
+        _resolveTypeAlias(node: node, element: element, typeAlias: function);
+        return;
+      }
+    } else if (element is MethodElement) {
+      function.staticElement = element;
+      function.staticType = element.type;
+      _resolve(node: node, rawType: element.type, name: element.name);
+      return;
+    } else if (element is FunctionElement) {
+      function.staticElement = element;
+      function.staticType = element.type;
+      _resolve(node: node, rawType: element.type, name: element.name);
+      return;
+    } else if (element is PropertyAccessorElement) {
+      function.staticElement = element;
+      function.staticType = element.returnType;
+      _resolveDisallowedExpression(node, element.returnType);
+      return;
+    } else if (element is ExecutableElement) {
+      function.staticElement = element;
+      function.staticType = element.type;
+      _resolveDisallowedExpression(node, element.type);
+      return;
+    } else if (element is VariableElement) {
+      function.staticElement = element;
+      function.staticType = element.type;
+      _resolveDisallowedExpression(node, element.type);
+      return;
+    } else {
+      _resolveDisallowedExpression(node, DynamicTypeImpl.instance);
+      return;
+    }
+  }
+
   /// Returns the element that represents the property named [propertyName] on
   /// [classElement].
   ExecutableElement? _resolveStaticElement(
@@ -410,7 +631,7 @@
           'Unexpected receiverElement type: ${receiverElement.runtimeType}');
       return null;
     }
-    return _resolver.typePropertyResolver
+    var methodElement = _resolver.typePropertyResolver
         .resolve(
           receiver: receiver,
           receiverType: receiverType,
@@ -419,5 +640,10 @@
           nameErrorEntity: nameErrorEntity,
         )
         .getter;
+    if (methodElement != null && methodElement.isStatic) {
+      _reportInvalidAccessToStaticMember(name, methodElement,
+          implicitReceiver: false);
+    }
+    return methodElement;
   }
 }
diff --git a/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
new file mode 100644
index 0000000..cf4574c
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/instance_creation_expression_resolver.dart
@@ -0,0 +1,152 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// 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/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+/// A resolver for [InstanceCreationExpression] nodes.
+///
+/// This resolver is responsible for rewriting a given
+/// [InstanceCreationExpression] as a [MethodInvocation] if the parsed
+/// [ConstructorName]'s `type` resolves to a [FunctionReference] or
+/// [ConstructorReference], instead of a [TypeName].
+class InstanceCreationExpressionResolver {
+  /// The resolver driving this participant.
+  final ResolverVisitor _resolver;
+
+  InstanceCreationExpressionResolver(this._resolver);
+
+  void resolve(InstanceCreationExpressionImpl node) {
+    // The parser can parse certain code as [InstanceCreationExpression] when it
+    // might be an invocation of a method on a [FunctionReference] or
+    // [ConstructorReference]. In such a case, it is this resolver's
+    // responsibility to rewrite. For example, given:
+    //
+    //     a.m<int>.apply();
+    //
+    // the parser will give an InstanceCreationExpression (`a.m<int>.apply()`)
+    // with a name of `a.m<int>.apply` (ConstructorName) with a type of
+    // `a.m<int>` (TypeName with a name of `a.m` (PrefixedIdentifier) and
+    // typeArguments of `<int>`) and a name of `apply` (SimpleIdentifier). If
+    // `a.m<int>` is actually a function reference, then the
+    // InstanceCreationExpression needs to be rewritten as a MethodInvocation
+    // with a target of `a.m<int>` (a FunctionReference) and a name of `apply`.
+    if (node.keyword == null) {
+      var typeNameTypeArguments = node.constructorName.type.typeArguments;
+      if (typeNameTypeArguments != null) {
+        // This could be a method call on a function reference or a constructor
+        // reference.
+        _resolveWithTypeNameWithTypeArguments(node, typeNameTypeArguments);
+        return;
+      }
+    }
+
+    _resolveInstanceCreationExpression(node);
+  }
+
+  void _inferArgumentTypes(covariant InstanceCreationExpressionImpl node) {
+    var constructorName = node.constructorName;
+    var typeName = constructorName.type;
+    var typeArguments = typeName.typeArguments;
+    var elementToInfer = _resolver.inferenceHelper.constructorElementToInfer(
+      constructorName: constructorName,
+      definingLibrary: _resolver.definingLibrary,
+    );
+    FunctionType? inferred;
+
+    // If the constructor is generic, we'll have a ConstructorMember that
+    // substitutes in type arguments (possibly `dynamic`) from earlier in
+    // resolution.
+    //
+    // Otherwise we'll have a ConstructorElement, and we can skip inference
+    // because there's nothing to infer in a non-generic type.
+    if (elementToInfer != null) {
+      // TODO(leafp): Currently, we may re-infer types here, since we
+      // sometimes resolve multiple times.  We should really check that we
+      // have not already inferred something.  However, the obvious ways to
+      // check this don't work, since we may have been instantiated
+      // to bounds in an earlier phase, and we *do* want to do inference
+      // in that case.
+
+      // Get back to the uninstantiated generic constructor.
+      // TODO(jmesserly): should we store this earlier in resolution?
+      // Or look it up, instead of jumping backwards through the Member?
+      var rawElement = elementToInfer.element;
+      var constructorType = elementToInfer.asType;
+
+      inferred = _resolver.inferenceHelper.inferArgumentTypesForGeneric(
+          node, constructorType, typeArguments,
+          isConst: node.isConst, errorNode: node.constructorName);
+
+      if (inferred != null) {
+        var arguments = node.argumentList;
+        InferenceContext.setType(arguments, inferred);
+        // Fix up the parameter elements based on inferred method.
+        arguments.correspondingStaticParameters =
+            ResolverVisitor.resolveArgumentsToParameters(
+                arguments, inferred.parameters, null);
+
+        constructorName.type.type = inferred.returnType;
+
+        // Update the static element as well. This is used in some cases, such
+        // as computing constant values. It is stored in two places.
+        var constructorElement = ConstructorMember.from(
+          rawElement,
+          inferred.returnType as InterfaceType,
+        );
+        constructorName.staticElement = constructorElement;
+      }
+    }
+
+    if (inferred == null) {
+      var constructorElement = constructorName.staticElement;
+      if (constructorElement != null) {
+        var type = constructorElement.type;
+        type = _resolver.toLegacyTypeIfOptOut(type) as FunctionType;
+        InferenceContext.setType(node.argumentList, type);
+      }
+    }
+  }
+
+  void _resolveInstanceCreationExpression(InstanceCreationExpressionImpl node) {
+    var whyNotPromotedList = <WhyNotPromotedGetter>[];
+    node.constructorName.accept(_resolver);
+    _inferArgumentTypes(node);
+    _resolver.visitArgumentList(node.argumentList,
+        whyNotPromotedList: whyNotPromotedList);
+    node.accept(_resolver.elementResolver);
+    node.accept(_resolver.typeAnalyzer);
+    _resolver.checkForArgumentTypesNotAssignableInList(
+        node.argumentList, whyNotPromotedList);
+  }
+
+  /// Resolve [node] which has a [TypeName] with type arguments (given as
+  /// [typeNameTypeArguments]).
+  ///
+  /// The instance creation expression may actually be a method call on a
+  /// type-instantiated function reference or constructor reference.
+  void _resolveWithTypeNameWithTypeArguments(
+    InstanceCreationExpressionImpl node,
+    TypeArgumentListImpl typeNameTypeArguments,
+  ) {
+    var typeNameName = node.constructorName.type.name;
+    if (typeNameName is SimpleIdentifierImpl) {
+      // TODO(srawlins): Lookup the name and potentially rewrite `node` as a
+      // [MethodInvocation].
+      _resolveInstanceCreationExpression(node);
+      return;
+    } else if (typeNameName is PrefixedIdentifierImpl) {
+      // TODO(srawlins): Lookup the name and potentially rewrite `node` as a
+      // [MethodInvocation].
+      _resolveInstanceCreationExpression(node);
+    } else {
+      assert(
+          false, 'Unexpected typeNameName type: ${typeNameName.runtimeType}');
+      _resolveInstanceCreationExpression(node);
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart b/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
index 94c39d7..7be20ef 100644
--- a/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/legacy_type_asserter.dart
@@ -144,7 +144,7 @@
       return;
     }
 
-    type.aliasArguments?.forEach(_assertLegacyType);
+    type.alias?.typeArguments.forEach(_assertLegacyType);
 
     if (type is TypeParameterType) {
       _assertLegacyType(type.bound);
diff --git a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
index 7485e6e..5c7a513 100644
--- a/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/method_invocation_resolver.dart
@@ -10,12 +10,12 @@
 import 'package:analyzer/src/dart/ast/ast_factory.dart';
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/migratable_ast_info_provider.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -42,7 +42,7 @@
   final InheritanceManager3 _inheritance;
 
   /// The element for the library containing the compilation unit being visited.
-  final LibraryElement _definingLibrary;
+  final LibraryElementImpl _definingLibrary;
 
   /// The URI of [_definingLibrary].
   final Uri _definingLibraryUri;
@@ -271,7 +271,7 @@
   }) {
     _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
 
-    if (nameScope.shouldIgnoreUndefined2(prefix: prefix, name: name)) {
+    if (_definingLibrary.shouldIgnoreUndefined(prefix: prefix, name: name)) {
       return;
     }
 
@@ -282,19 +282,6 @@
     );
   }
 
-  void _reportUndefinedMethod(
-      MethodInvocationImpl node,
-      String name,
-      ClassElement typeReference,
-      List<WhyNotPromotedGetter> whyNotPromotedList) {
-    _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
-    _resolver.errorReporter.reportErrorForNode(
-      CompileTimeErrorCode.UNDEFINED_METHOD,
-      node.methodName,
-      [name, typeReference.displayName],
-    );
-  }
-
   void _reportUseOfVoidType(MethodInvocationImpl node, AstNode errorNode,
       List<WhyNotPromotedGetter> whyNotPromotedList) {
     _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
@@ -779,7 +766,26 @@
       return;
     }
 
-    _reportUndefinedMethod(node, name, receiver, whyNotPromotedList);
+    _setDynamicResolution(node, whyNotPromotedList: whyNotPromotedList);
+    if (nameNode.name == 'new') {
+      // Attempting to invoke the unnamed constructor via `C.new(`.
+      if (_resolver.isConstructorTearoffsEnabled) {
+        _resolver.errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT,
+          nameNode,
+          [receiver.displayName],
+        );
+      } else {
+        // [ParserErrorCode.EXPERIMENT_NOT_ENABLED] is reported by the parser.
+        // Do not report extra errors.
+      }
+    } else {
+      _resolver.errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.UNDEFINED_METHOD,
+        node.methodName,
+        [name, receiver.displayName],
+      );
+    }
   }
 
   /// If the given [type] is a type parameter, replace with its bound.
diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
index e2d5336..10c9f96 100644
--- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
@@ -13,7 +13,6 @@
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/extension_member_resolver.dart';
 import 'package:analyzer/src/dart/resolver/resolution_result.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/error/assignment_verifier.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
@@ -590,7 +589,7 @@
 
     if (hasRead && readElement == null || hasWrite && writeElement == null) {
       if (!forAnnotation &&
-          !_resolver.nameScope.shouldIgnoreUndefined2(
+          !_resolver.definingLibrary.shouldIgnoreUndefined(
             prefix: target.name,
             name: identifier.name,
           )) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 6a03d38..f08fb8d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -56,6 +56,7 @@
 /// 3. Resolve all [TypeName]s - set elements and types.
 /// 4. Resolve all [GenericFunctionType]s - set their types.
 class ResolutionVisitor extends RecursiveAstVisitor<void> {
+  LibraryElementImpl _libraryElement;
   final TypeProvider _typeProvider;
   final CompilationUnitElementImpl _unitElement;
   final bool _isNonNullableByDefault;
@@ -102,13 +103,14 @@
     );
 
     var typeNameResolver = TypeNameResolver(
-      libraryElement.typeSystem,
+      libraryElement,
       typeProvider,
       isNonNullableByDefault,
       errorReporter,
     );
 
     return ResolutionVisitor._(
+      libraryElement,
       typeProvider,
       unitElement,
       isNonNullableByDefault,
@@ -122,6 +124,7 @@
   }
 
   ResolutionVisitor._(
+    this._libraryElement,
     this._typeProvider,
     this._unitElement,
     this._isNonNullableByDefault,
@@ -1211,7 +1214,7 @@
     // If the type is not an InterfaceType, then visitTypeName() sets the type
     // to be a DynamicTypeImpl
     Identifier name = typeName.name;
-    if (!_nameScope.shouldIgnoreUndefined(name)) {
+    if (!_libraryElement.shouldIgnoreUndefinedIdentifier(name)) {
       _errorReporter.reportErrorForNode(errorCode, name, [name.name]);
     }
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index 95850f3..845c8e1 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -352,35 +352,6 @@
 }
 
 extension ScopeExtension on Scope {
-  /// Return `true` if the fact that the given [node] is not defined should be
-  /// ignored (from the perspective of error reporting).
-  bool shouldIgnoreUndefined(Identifier node) {
-    if (node is PrefixedIdentifier) {
-      return shouldIgnoreUndefined2(
-        prefix: node.prefix.name,
-        name: node.identifier.name,
-      );
-    }
-
-    return shouldIgnoreUndefined2(
-      prefix: null,
-      name: (node as SimpleIdentifier).name,
-    );
-  }
-
-  /// Return `true` if the fact that the identifier with the given [prefix]
-  /// (might be `null`) and [name] is not defined should be ignored (from the
-  /// perspective of error reporting).
-  bool shouldIgnoreUndefined2({
-    required String? prefix,
-    required String name,
-  }) {
-    return _enclosingLibraryScope.shouldIgnoreUndefined(
-      prefix: prefix,
-      name: name,
-    );
-  }
-
   List<ExtensionElement> get extensions {
     return _enclosingLibraryScope.extensions;
   }
diff --git a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
index a3e5943..4c872f9 100644
--- a/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/simple_identifier_resolver.dart
@@ -14,7 +14,6 @@
 import 'package:analyzer/src/dart/resolver/flow_analysis_visitor.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
 import 'package:analyzer/src/dart/resolver/property_element_resolver.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 
@@ -203,7 +202,8 @@
           CompileTimeErrorCode.UNDEFINED_IDENTIFIER_AWAIT,
           node,
         );
-      } else if (!_resolver.nameScope.shouldIgnoreUndefined(node)) {
+      } else if (!_resolver.definingLibrary
+          .shouldIgnoreUndefinedIdentifier(node)) {
         _errorReporter.reportErrorForNode(
           CompileTimeErrorCode.UNDEFINED_IDENTIFIER,
           node,
diff --git a/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
index 4acea06..3f3c167 100644
--- a/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/type_name_resolver.dart
@@ -16,7 +16,6 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/type_system.dart';
-import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/diagnostic/diagnostic_factory.dart';
 import 'package:analyzer/src/error/codes.dart';
 
@@ -24,6 +23,7 @@
 ///
 /// The client must set [nameScope] before calling [resolveTypeName].
 class TypeNameResolver {
+  final LibraryElementImpl _libraryElement;
   final TypeSystemImpl typeSystem;
   final DartType dynamicType;
   final bool isNonNullableByDefault;
@@ -56,9 +56,10 @@
   /// If [resolveTypeName] reported an error, this flag is set to `true`.
   bool hasErrorReported = false;
 
-  TypeNameResolver(this.typeSystem, TypeProvider typeProvider,
+  TypeNameResolver(this._libraryElement, TypeProvider typeProvider,
       this.isNonNullableByDefault, this.errorReporter)
-      : dynamicType = typeProvider.dynamicType;
+      : typeSystem = _libraryElement.typeSystem,
+        dynamicType = typeProvider.dynamicType;
 
   bool get _genericMetadataIsEnabled =>
       enclosingClass!.library.featureSet.isEnabled(Feature.generic_metadata);
@@ -285,7 +286,7 @@
   void _resolveToElement(TypeNameImpl node, Element? element) {
     if (element == null) {
       node.type = dynamicType;
-      if (!nameScope.shouldIgnoreUndefined(node.name)) {
+      if (!_libraryElement.shouldIgnoreUndefinedIdentifier(node.name)) {
         _ErrorHelper(errorReporter).reportNullOrNonTypeElement(node, null);
       }
       return;
diff --git a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
index ee009b4..e781de9 100644
--- a/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/typed_literal_resolver.dart
@@ -37,7 +37,7 @@
       TypeSystemImpl typeSystem, TypeProviderImpl typeProvider,
       {MigratableAstInfoProvider migratableAstInfoProvider =
           const MigratableAstInfoProvider()}) {
-    var library = resolver.definingLibrary as LibraryElementImpl;
+    var library = resolver.definingLibrary;
     var analysisOptions = library.context.analysisOptions;
     var analysisOptionsImpl = analysisOptions as AnalysisOptionsImpl;
     return TypedLiteralResolver._(
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index a1d8739..bfa745d 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -755,7 +755,7 @@
       // not report synthetic `dynamic` in place of an unresolved type.
       if ((type.element == _nullType.element ||
               (type.isDynamic && name == 'dynamic')) &&
-          type.aliasElement == null) {
+          type.alias == null) {
         _errorReporter.reportErrorForNode(
             HintCode.UNNECESSARY_QUESTION_MARK, node, [name]);
       }
@@ -1048,7 +1048,7 @@
           ...element.typeParameters.map((tp) => tp.bound),
         ];
         for (var type in signatureTypes) {
-          var aliasElement = type?.aliasElement;
+          var aliasElement = type?.alias?.element;
           if (aliasElement != null && aliasElement.hasInternal) {
             _errorReporter.reportErrorForNode(
                 HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT_INDIRECTLY,
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index a5fdaf2..fb2881f 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -10505,6 +10505,18 @@
   /**
    * No parameters.
    */
+  static const CompileTimeErrorCode DISALLOWED_TYPE_INSTANTIATION_EXPRESSION =
+      CompileTimeErrorCode(
+          'DISALLOWED_TYPE_INSTANTIATION_EXPRESSION',
+          'Only a generic type, generic function, generic instance method, or '
+              'generic constructor can be type instantiated.',
+          correction:
+              'Try instantiating the type(s) of a generic type, generic '
+              'function, generic instance method, or generic constructor.');
+
+  /**
+   * No parameters.
+   */
   // #### Description
   //
   // The analyzer produces this diagnostic when the static type of the
@@ -14632,6 +14644,22 @@
 
   /**
    * Parameters:
+   * 0: the number of type parameters that were declared
+   * 1: the number of type arguments provided
+   */
+  static const CompileTimeErrorCode
+      WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION = CompileTimeErrorCode(
+          'WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION',
+          "This function is declared with {0} type parameters, "
+              "but {1} type arguments were given.",
+          correction:
+              "Try adjusting the number of type arguments to match the number "
+              "of type parameters.",
+          hasPublishedDocs: true,
+          uniqueName: 'WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION');
+
+  /**
+   * Parameters:
    * 0: the name of the class being instantiated
    * 1: the name of the constructor being invoked
    */
diff --git a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
index e4a6930..55d66ce 100644
--- a/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
+++ b/pkg/analyzer/lib/src/error/type_arguments_verifier.dart
@@ -210,10 +210,10 @@
 
     List<TypeParameterElement> typeParameters;
     List<DartType> typeArguments;
-    var aliasElement = type.aliasElement;
-    if (aliasElement != null) {
-      typeParameters = aliasElement.typeParameters;
-      typeArguments = type.aliasArguments!;
+    var alias = type.alias;
+    if (alias != null) {
+      typeParameters = alias.element.typeParameters;
+      typeArguments = alias.typeArguments;
     } else if (type is InterfaceType) {
       typeParameters = type.element.typeParameters;
       typeArguments = type.typeArguments;
@@ -277,8 +277,9 @@
 
     // Prepare type arguments for checking for super-bounded.
     type = _typeSystem.replaceTopAndBottom(type);
-    if (type.aliasElement != null) {
-      typeArguments = type.aliasArguments!;
+    alias = type.alias;
+    if (alias != null) {
+      typeArguments = alias.typeArguments;
     } else if (type is InterfaceType) {
       typeArguments = type.typeArguments;
     } else {
@@ -422,9 +423,9 @@
   bool _isMissingTypeArguments(AstNode node, DartType type, Element? element,
       Expression? inferenceContextNode) {
     List<DartType> typeArguments;
-    var aliasElement = type.aliasElement;
-    if (aliasElement != null) {
-      typeArguments = type.aliasArguments!;
+    var alias = type.alias;
+    if (alias != null) {
+      typeArguments = alias.typeArguments;
     } else if (type is InterfaceType) {
       typeArguments = type.typeArguments;
     } else {
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index cc5fc13..2a378e1 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -498,7 +498,8 @@
     var declaration = node.thisOrAncestorOfType<ClassDeclaration>();
     var superclassName = declaration?.extendsClause?.superclass.name;
     if (superclassName != null &&
-        _resolver.nameScope.shouldIgnoreUndefined(superclassName)) {
+        _resolver.definingLibrary
+            .shouldIgnoreUndefinedIdentifier(superclassName)) {
       return;
     }
     var argumentList = node.argumentList;
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 7f04b64..c678842 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -281,6 +281,10 @@
   /// This option is experimental and subject to change.
   bool implicitDynamic = true;
 
+  /// Indicates whether linter exceptions should be propagated to the caller (by
+  /// re-throwing them)
+  bool propagateLinterExceptions = false;
+
   /// A flag indicating whether inference failures are allowed, off by default.
   ///
   /// This option is experimental and subject to change.
@@ -319,6 +323,7 @@
     if (options is AnalysisOptionsImpl) {
       implicitCasts = options.implicitCasts;
       implicitDynamic = options.implicitDynamic;
+      propagateLinterExceptions = options.propagateLinterExceptions;
       strictInference = options.strictInference;
       strictRawTypes = options.strictRawTypes;
     }
@@ -382,6 +387,7 @@
       // Append boolean flags.
       buffer.addBool(implicitCasts);
       buffer.addBool(implicitDynamic);
+      buffer.addBool(propagateLinterExceptions);
       buffer.addBool(strictInference);
       buffer.addBool(strictRawTypes);
       buffer.addBool(useFastaParser);
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index b4880fb..3ad6c31 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -518,8 +518,9 @@
     _withEnclosingExecutable(element, () {
       _checkForInvalidModifierOnBody(
           node.body, CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR);
-      _checkForConstConstructorWithNonFinalField(node, element);
-      _checkForConstConstructorWithNonConstSuper(node);
+      if (!_checkForConstConstructorWithNonConstSuper(node)) {
+        _checkForConstConstructorWithNonFinalField(node, element);
+      }
       _constructorFieldsVerifier.verify(node);
       _checkForRedirectingConstructorErrorCodes(node);
       _checkForMultipleSuperInitializers(node);
@@ -1851,23 +1852,40 @@
   /// are no invocations of non-'const' super constructors, and that there are
   /// no instance variables mixed in.
   ///
+  /// Return `true` if an error is reported here, and the caller should stop
+  /// checking the constructor for constant-related errors.
+  ///
   /// See [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER], and
   /// [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD].
-  void _checkForConstConstructorWithNonConstSuper(
+  bool _checkForConstConstructorWithNonConstSuper(
       ConstructorDeclaration constructor) {
     if (!_enclosingExecutable.isConstConstructor) {
-      return;
+      return false;
     }
     // OK, const factory, checked elsewhere
     if (constructor.factoryKeyword != null) {
-      return;
+      return false;
     }
 
     // check for mixins
     var instanceFields = <FieldElement>[];
     for (var mixin in _enclosingClass!.mixins) {
-      instanceFields.addAll(mixin.element.fields
-          .where((field) => !field.isStatic && !field.isSynthetic));
+      instanceFields.addAll(mixin.element.fields.where((field) {
+        if (field.isStatic) {
+          return false;
+        }
+        if (field.isSynthetic) {
+          return false;
+        }
+        // From the abstract and external fields specification:
+        // > An abstract instance variable declaration D is treated as an
+        // > abstract getter declaration and possibly an abstract setter
+        // > declaration. The setter is included if and only if D is non-final.
+        if (field.isAbstract && field.isFinal) {
+          return false;
+        }
+        return true;
+      }));
     }
     if (instanceFields.length == 1) {
       var field = instanceFields.single;
@@ -1875,7 +1893,7 @@
           CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
           constructor.returnType,
           ["'${field.enclosingElement.name}.${field.name}'"]);
-      return;
+      return true;
     } else if (instanceFields.length > 1) {
       var fieldNames = instanceFields
           .map((field) => "'${field.enclosingElement.name}.${field.name}'")
@@ -1884,7 +1902,7 @@
           CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELDS,
           constructor.returnType,
           [fieldNames]);
-      return;
+      return true;
     }
 
     // try to find and check super constructor invocation
@@ -1892,26 +1910,26 @@
       if (initializer is SuperConstructorInvocation) {
         var element = initializer.staticElement;
         if (element == null || element.isConst) {
-          return;
+          return false;
         }
         errorReporter.reportErrorForNode(
             CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
             initializer,
             [element.enclosingElement.displayName]);
-        return;
+        return true;
       }
     }
     // no explicit super constructor invocation, check default constructor
     var supertype = _enclosingClass!.supertype;
     if (supertype == null) {
-      return;
+      return false;
     }
     if (supertype.isDartCoreObject) {
-      return;
+      return false;
     }
     var unnamedConstructor = supertype.element.unnamedConstructor;
     if (unnamedConstructor == null || unnamedConstructor.isConst) {
-      return;
+      return false;
     }
 
     // default constructor is not 'const', report problem
@@ -1919,6 +1937,7 @@
         CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER,
         constructor.returnType,
         [supertype]);
+    return true;
   }
 
   /// Verify that if the given [constructor] declaration is 'const' then there
@@ -1935,10 +1954,6 @@
     if (!classElement.hasNonFinalField) {
       return;
     }
-    // TODO(brianwilkerson) Stop generating
-    //  CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD when either
-    //  CONST_CONSTRUCTOR_WITH_NON_CONST_SUPER or
-    //  CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD is also generated.
     errorReporter.reportErrorForName(
         CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
         constructor);
diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
index 8382b13..576627a 100644
--- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
@@ -23,6 +23,7 @@
   static const _dartFfiLibraryName = 'dart.ffi';
   static const _isLeafParamName = 'isLeaf';
   static const _opaqueClassName = 'Opaque';
+  static const _ffiNativeName = 'FfiNative';
 
   static const List<String> _primitiveIntegerNativeTypes = [
     'Int8',
@@ -76,8 +77,8 @@
           inCompound = true;
           compound = node;
           if (node.declaredElement!.isEmptyStruct) {
-            _errorReporter
-                .reportErrorForNode(FfiCode.EMPTY_STRUCT, node, [node.name]);
+            _errorReporter.reportErrorForNode(
+                FfiCode.EMPTY_STRUCT, node.name, [node.name.name]);
           }
           if (className == _structClassName) {
             _validatePackedAnnotation(node.metadata);
@@ -155,6 +156,12 @@
   }
 
   @override
+  void visitFunctionDeclaration(FunctionDeclaration node) {
+    _checkFfiNative(node);
+    super.visitFunctionDeclaration(node);
+  }
+
+  @override
   void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     var element = node.staticElement;
     if (element is MethodElement) {
@@ -196,6 +203,12 @@
   }
 
   @override
+  void visitMethodDeclaration(MethodDeclaration node) {
+    _checkFfiNative(node);
+    super.visitMethodDeclaration(node);
+  }
+
+  @override
   void visitMethodInvocation(MethodInvocation node) {
     var element = node.methodName.staticElement;
     if (element is MethodElement) {
@@ -256,6 +269,38 @@
     super.visitPropertyAccess(node);
   }
 
+  void _checkFfiNative(Declaration node) {
+    NodeList<Annotation> annotations = node.metadata;
+    if (annotations.isEmpty) {
+      return;
+    }
+
+    for (Annotation annotation in annotations) {
+      if (annotation.name.name == _ffiNativeName) {
+        // All FFI Natives must be static.
+        final isStatic = (node is FunctionDeclaration) ||
+            ((node is MethodDeclaration) && node.isStatic);
+        if (!isStatic) {
+          _errorReporter.reportErrorForNode(
+              FfiCode.FFI_NATIVE_ONLY_STATIC, node);
+        }
+        // Leaf call FFI Natives can't use Handles.
+        ArgumentList? argumentList = annotation.arguments;
+        if (argumentList != null) {
+          NodeList<Expression> arguments = argumentList.arguments;
+          TypeArgumentList? typeArgumentList = annotation.typeArguments;
+          if (typeArgumentList != null) {
+            NodeList<TypeAnnotation> typeArguments = typeArgumentList.arguments;
+            if (typeArguments.isNotEmpty && typeArguments[0].type != null) {
+              _validateFfiLeafCallUsesNoHandles(
+                  arguments, typeArguments[0].type!, node);
+            }
+          }
+        }
+      }
+    }
+  }
+
   /// Returns `true` if [nativeType] is a C type that has a size.
   bool _isSized(DartType nativeType) {
     switch (_primitiveNativeType(nativeType)) {
@@ -499,7 +544,8 @@
         _errorReporter.reportErrorForNode(
             FfiCode.MUST_BE_A_SUBTYPE, node, [TPrime, F, 'asFunction']);
       }
-      _validateFfiLeafCallUsesNoHandles(node, TPrime, node);
+      _validateFfiLeafCallUsesNoHandles(
+          node.argumentList.arguments, TPrime, node);
     }
     _validateIsLeafIsConst(node);
   }
@@ -592,8 +638,7 @@
   }
 
   void _validateFfiLeafCallUsesNoHandles(
-      MethodInvocation node, DartType nativeType, AstNode errorNode) {
-    final args = node.argumentList.arguments;
+      NodeList<Expression> args, DartType nativeType, AstNode errorNode) {
     if (args.isNotEmpty) {
       for (final arg in args) {
         if (arg is NamedExpression) {
@@ -670,6 +715,8 @@
       } else if (declaredType.isCompoundSubtype) {
         final clazz = (declaredType as InterfaceType).element;
         if (clazz.isEmptyStruct) {
+          // TODO(brianwilkerson) There are no tests for this branch. Ensure
+          //  that the diagnostic is correct and add tests.
           _errorReporter
               .reportErrorForNode(FfiCode.EMPTY_STRUCT, node, [clazz.name]);
         }
@@ -705,8 +752,13 @@
 
     final DartType T = node.typeArgumentTypes![0];
     if (!_isValidFfiNativeFunctionType(T)) {
-      _errorReporter.reportErrorForNode(
-          FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, node, [T, 'fromFunction']);
+      AstNode errorNode = node.methodName;
+      var typeArgument = node.typeArguments?.arguments[0];
+      if (typeArgument != null) {
+        errorNode = typeArgument;
+      }
+      _errorReporter.reportErrorForNode(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE,
+          errorNode, [T, 'fromFunction']);
       return;
     }
 
@@ -765,7 +817,7 @@
   /// `DynamicLibrary.lookupFunction<S, F>()`.
   void _validateLookupFunction(MethodInvocation node) {
     final typeArguments = node.typeArguments?.arguments;
-    if (typeArguments?.length != 2) {
+    if (typeArguments == null || typeArguments.length != 2) {
       // There are other diagnostics reported against the invocation and the
       // diagnostics generated below might be inaccurate, so don't report them.
       return;
@@ -775,18 +827,19 @@
     final DartType S = argTypes[0];
     final DartType F = argTypes[1];
     if (!_isValidFfiNativeFunctionType(S)) {
-      final AstNode errorNode = typeArguments![0];
+      final AstNode errorNode = typeArguments[0];
       _errorReporter.reportErrorForNode(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE,
           errorNode, [S, 'lookupFunction']);
       return;
     }
     if (!_validateCompatibleFunctionTypes(F, S)) {
-      final AstNode errorNode = typeArguments![1];
+      final AstNode errorNode = typeArguments[1];
       _errorReporter.reportErrorForNode(
           FfiCode.MUST_BE_A_SUBTYPE, errorNode, [S, F, 'lookupFunction']);
     }
     _validateIsLeafIsConst(node);
-    _validateFfiLeafCallUsesNoHandles(node, S, typeArguments![0]);
+    _validateFfiLeafCallUsesNoHandles(
+        node.argumentList.arguments, S, typeArguments[0]);
   }
 
   /// Validate that none of the [annotations] are from `dart:ffi`.
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 112f2e7..6a09580 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -21,8 +21,7 @@
 import 'package:analyzer/src/dart/ast/extensions.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/dart/element/member.dart'
-    show ConstructorMember, Member;
+import 'package:analyzer/src/dart/element/member.dart' show Member;
 import 'package:analyzer/src/dart/element/nullability_eliminator.dart';
 import 'package:analyzer/src/dart/element/scope.dart';
 import 'package:analyzer/src/dart/element/type.dart';
@@ -38,6 +37,7 @@
 import 'package:analyzer/src/dart/resolver/function_expression_invocation_resolver.dart';
 import 'package:analyzer/src/dart/resolver/function_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/function_reference_resolver.dart';
+import 'package:analyzer/src/dart/resolver/instance_creation_expression_resolver.dart';
 import 'package:analyzer/src/dart/resolver/invocation_inference_helper.dart';
 import 'package:analyzer/src/dart/resolver/lexical_lookup.dart';
 import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
@@ -210,10 +210,6 @@
   @override
   final TypeSystemImpl typeSystem;
 
-  /// The element representing the function containing the current node, or
-  /// `null` if the current node is not contained in a function.
-  ExecutableElement? _enclosingFunction;
-
   /// The helper for tracking if the current location has access to `this`.
   final ThisAccessTracker _thisAccessTracker = ThisAccessTracker.unit();
 
@@ -253,6 +249,9 @@
 
   late final FunctionReferenceResolver _functionReferenceResolver;
 
+  late final InstanceCreationExpressionResolver
+      _instanceCreationExpressionResolver;
+
   /// Initialize a newly created visitor to resolve the nodes in an AST node.
   ///
   /// The [definingLibrary] is the element for the library containing the node
@@ -269,7 +268,7 @@
   /// breaking change).
   ResolverVisitor(
       InheritanceManager3 inheritanceManager,
-      LibraryElement definingLibrary,
+      LibraryElementImpl definingLibrary,
       Source source,
       TypeProvider typeProvider,
       AnalysisErrorListener errorListener,
@@ -280,7 +279,7 @@
             inheritanceManager,
             definingLibrary,
             source,
-            definingLibrary.typeSystem as TypeSystemImpl,
+            definingLibrary.typeSystem,
             typeProvider,
             errorListener,
             featureSet ??
@@ -292,7 +291,7 @@
 
   ResolverVisitor._(
       this.inheritance,
-      LibraryElement definingLibrary,
+      LibraryElementImpl definingLibrary,
       Source source,
       this.typeSystem,
       TypeProvider typeProvider,
@@ -373,13 +372,12 @@
     typeAnalyzer = StaticTypeAnalyzer(this, migrationResolutionHooks);
     _functionReferenceResolver =
         FunctionReferenceResolver(this, _isNonNullableByDefault);
+    _instanceCreationExpressionResolver =
+        InstanceCreationExpressionResolver(this);
   }
 
-  /// Return the element representing the function containing the current node,
-  /// or `null` if the current node is not contained in a function.
-  ///
-  /// @return the element representing the function containing the current node
-  ExecutableElement? get enclosingFunction => _enclosingFunction;
+  bool get isConstructorTearoffsEnabled =>
+      _featureSet.isEnabled(Feature.constructor_tearoffs);
 
   /// Return the object providing promoted or declared types of variables.
   LocalVariableTypeProvider get localVariableTypeProvider {
@@ -1218,13 +1216,10 @@
 
   @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
-    var outerFunction = _enclosingFunction;
-    _enclosingFunction = node.declaredElement;
-
     flowAnalysis!.topLevelDeclaration_enter(node, node.parameters);
     flowAnalysis!.executableDeclaration_enter(node, node.parameters, false);
 
-    var returnType = _enclosingFunction!.type.returnType;
+    var returnType = node.declaredElement!.type.returnType;
     InferenceContext.setType(node.body, returnType);
 
     super.visitConstructorDeclaration(node);
@@ -1240,8 +1235,6 @@
     flowAnalysis!.executableDeclaration_exit(node.body, false);
     flowAnalysis!.topLevelDeclaration_exit();
     nullSafetyDeadCodeVerifier.flowEnd(node);
-
-    _enclosingFunction = outerFunction;
   }
 
   @override
@@ -1442,9 +1435,6 @@
 
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
-    var outerFunction = _enclosingFunction;
-    _enclosingFunction = node.declaredElement;
-
     bool isLocal = node.parent is FunctionDeclarationStatement;
 
     if (isLocal) {
@@ -1459,7 +1449,7 @@
       isLocal,
     );
 
-    var functionType = _enclosingFunction!.type;
+    var functionType = node.declaredElement!.type;
     InferenceContext.setType(node.functionExpression, functionType);
 
     super.visitFunctionDeclaration(node);
@@ -1484,7 +1474,6 @@
     }
     nullSafetyDeadCodeVerifier.flowEnd(node);
 
-    _enclosingFunction = outerFunction;
     node.accept(elementResolver);
     // Note: no need to call the typeAnalyzer since it does not override
     // visitFunctionDeclaration
@@ -1498,6 +1487,8 @@
 
   @override
   void visitFunctionExpression(covariant FunctionExpressionImpl node) {
+    // Note: we have to update _enclosingFunction because we don't make use of
+    // super.visitFunctionExpression.
     var outerFunction = _enclosingFunction;
     _enclosingFunction = node.declaredElement;
 
@@ -1677,15 +1668,7 @@
   @override
   void visitInstanceCreationExpression(
       covariant InstanceCreationExpressionImpl node) {
-    var whyNotPromotedList = <Map<DartType, NonPromotionReason> Function()>[];
-    node.constructorName.accept(this);
-    _inferArgumentTypesForInstanceCreate(node);
-    visitArgumentList(node.argumentList,
-        whyNotPromotedList: whyNotPromotedList);
-    node.accept(elementResolver);
-    node.accept(typeAnalyzer);
-    checkForArgumentTypesNotAssignableInList(
-        node.argumentList, whyNotPromotedList);
+    _instanceCreationExpressionResolver.resolve(node);
   }
 
   @override
@@ -1715,13 +1698,10 @@
 
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
-    var outerFunction = _enclosingFunction;
-    _enclosingFunction = node.declaredElement;
-
     flowAnalysis!.topLevelDeclaration_enter(node, node.parameters);
     flowAnalysis!.executableDeclaration_enter(node, node.parameters, false);
 
-    DartType returnType = _enclosingFunction!.returnType;
+    DartType returnType = node.declaredElement!.returnType;
     InferenceContext.setType(node.body, returnType);
 
     super.visitMethodDeclaration(node);
@@ -1737,7 +1717,6 @@
     flowAnalysis!.topLevelDeclaration_exit();
     nullSafetyDeadCodeVerifier.flowEnd(node);
 
-    _enclosingFunction = outerFunction;
     node.accept(elementResolver);
     // Note: no need to call the typeAnalyzer since it does not override
     // visitMethodDeclaration.
@@ -2176,72 +2155,6 @@
     return typeProvider.futureOrType(type);
   }
 
-  void _inferArgumentTypesForInstanceCreate(
-      covariant InstanceCreationExpressionImpl node) {
-    var constructorName = node.constructorName;
-
-    var typeName = constructorName.type;
-    var typeArguments = typeName.typeArguments;
-
-    var elementToInfer = inferenceHelper.constructorElementToInfer(
-      constructorName: constructorName,
-      definingLibrary: definingLibrary,
-    );
-
-    FunctionType? inferred;
-    // If the constructor is generic, we'll have a ConstructorMember that
-    // substitutes in type arguments (possibly `dynamic`) from earlier in
-    // resolution.
-    //
-    // Otherwise we'll have a ConstructorElement, and we can skip inference
-    // because there's nothing to infer in a non-generic type.
-    if (elementToInfer != null) {
-      // TODO(leafp): Currently, we may re-infer types here, since we
-      // sometimes resolve multiple times.  We should really check that we
-      // have not already inferred something.  However, the obvious ways to
-      // check this don't work, since we may have been instantiated
-      // to bounds in an earlier phase, and we *do* want to do inference
-      // in that case.
-
-      // Get back to the uninstantiated generic constructor.
-      // TODO(jmesserly): should we store this earlier in resolution?
-      // Or look it up, instead of jumping backwards through the Member?
-      var rawElement = elementToInfer.element;
-      var constructorType = elementToInfer.asType;
-
-      inferred = inferenceHelper.inferArgumentTypesForGeneric(
-          node, constructorType, typeArguments,
-          isConst: node.isConst, errorNode: node.constructorName);
-
-      if (inferred != null) {
-        var arguments = node.argumentList;
-        InferenceContext.setType(arguments, inferred);
-        // Fix up the parameter elements based on inferred method.
-        arguments.correspondingStaticParameters =
-            resolveArgumentsToParameters(arguments, inferred.parameters, null);
-
-        constructorName.type.type = inferred.returnType;
-
-        // Update the static element as well. This is used in some cases, such
-        // as computing constant values. It is stored in two places.
-        var constructorElement = ConstructorMember.from(
-          rawElement,
-          inferred.returnType as InterfaceType,
-        );
-        constructorName.staticElement = constructorElement;
-      }
-    }
-
-    if (inferred == null) {
-      var constructorElement = constructorName.staticElement;
-      if (constructorElement != null) {
-        var type = constructorElement.type;
-        type = toLegacyTypeIfOptOut(type) as FunctionType;
-        InferenceContext.setType(node.argumentList, type);
-      }
-    }
-  }
-
   /// Continues resolution of a [FunctionExpressionInvocation] that was created
   /// from a rewritten [MethodInvocation]. The target function is already
   /// resolved.
@@ -2387,7 +2300,7 @@
 
   ResolverVisitorForMigration(
       InheritanceManager3 inheritanceManager,
-      LibraryElement definingLibrary,
+      LibraryElementImpl definingLibrary,
       Source source,
       TypeProvider typeProvider,
       AnalysisErrorListener errorListener,
@@ -2457,7 +2370,7 @@
   static const _nameScopeProperty = 'nameScope';
 
   /// The element for the library containing the compilation unit being visited.
-  final LibraryElement definingLibrary;
+  final LibraryElementImpl definingLibrary;
 
   /// The source representing the compilation unit being visited.
   final Source source;
@@ -2487,6 +2400,10 @@
   /// visited, or `null` if we are not in the scope of an extension.
   ExtensionElement? enclosingExtension;
 
+  /// The element representing the function containing the current node, or
+  /// `null` if the current node is not contained in a function.
+  ExecutableElement? _enclosingFunction;
+
   /// Initialize a newly created visitor to resolve the nodes in a compilation
   /// unit.
   ///
@@ -2511,6 +2428,12 @@
         ),
         nameScope = nameScope ?? LibraryScope(definingLibrary);
 
+  /// Return the element representing the function containing the current node,
+  /// or `null` if the current node is not contained in a function.
+  ///
+  /// @return the element representing the function containing the current node
+  ExecutableElement? get enclosingFunction => _enclosingFunction;
+
   /// Return the implicit label scope in which the current node is being
   /// resolved.
   ImplicitLabelScope get implicitLabelScope => _implicitLabelScope;
@@ -2644,6 +2567,8 @@
 
   @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
+    var outerFunction = _enclosingFunction;
+    _enclosingFunction = node.declaredElement;
     Scope outerScope = nameScope;
     try {
       ConstructorElement element = node.declaredElement!;
@@ -2673,6 +2598,7 @@
       visitConstructorDeclarationInScope(node);
     } finally {
       nameScope = outerScope;
+      _enclosingFunction = outerFunction;
     }
   }
 
@@ -2851,6 +2777,9 @@
 
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
+    var outerFunction = _enclosingFunction;
+    _enclosingFunction = node.declaredElement;
+
     node.metadata.accept(this);
     Scope outerScope = nameScope;
     try {
@@ -2862,6 +2791,7 @@
       visitFunctionDeclarationInScope(node);
     } finally {
       nameScope = outerScope;
+      _enclosingFunction = outerFunction;
     }
   }
 
@@ -2882,6 +2812,8 @@
       return;
     }
 
+    var outerFunction = _enclosingFunction;
+    _enclosingFunction = node.declaredElement;
     Scope outerScope = nameScope;
     try {
       ExecutableElement element = node.declaredElement!;
@@ -2892,6 +2824,7 @@
       super.visitFunctionExpression(node);
     } finally {
       nameScope = outerScope;
+      _enclosingFunction = outerFunction;
     }
   }
 
@@ -3018,6 +2951,9 @@
 
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
+    var outerFunction = _enclosingFunction;
+    _enclosingFunction = node.declaredElement;
+
     node.metadata.accept(this);
     Scope outerScope = nameScope;
     try {
@@ -3029,6 +2965,7 @@
       visitMethodDeclarationInScope(node);
     } finally {
       nameScope = outerScope;
+      _enclosingFunction = outerFunction;
     }
   }
 
@@ -3214,10 +3151,6 @@
 /// Instances of the class `VariableResolverVisitor` are used to resolve
 /// [SimpleIdentifier]s to local variables and formal parameters.
 class VariableResolverVisitor extends ScopedVisitor {
-  /// The method or function that we are currently visiting, or `null` if we are
-  /// not inside a method or function.
-  ExecutableElement? _enclosingFunction;
-
   /// The container with information about local variables.
   final LocalVariableInfo _localVariableInfo = LocalVariableInfo();
 
@@ -3234,7 +3167,7 @@
   /// [nameScope] is the scope used to resolve identifiers in the node that will
   /// first be visited.  If `null` or unspecified, a new [LibraryScope] will be
   /// created based on [definingLibrary] and [typeProvider].
-  VariableResolverVisitor(LibraryElement definingLibrary, Source source,
+  VariableResolverVisitor(LibraryElementImpl definingLibrary, Source source,
       TypeProvider typeProvider, AnalysisErrorListener errorListener,
       {Scope? nameScope})
       : super(definingLibrary, source, typeProvider as TypeProviderImpl,
@@ -3243,14 +3176,8 @@
 
   @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
-    var outerFunction = _enclosingFunction;
-    try {
-      (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
-      _enclosingFunction = node.declaredElement;
-      super.visitConstructorDeclaration(node);
-    } finally {
-      _enclosingFunction = outerFunction;
-    }
+    (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
+    super.visitConstructorDeclaration(node);
   }
 
   @override
@@ -3258,28 +3185,16 @@
 
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
-    var outerFunction = _enclosingFunction;
-    try {
-      (node.functionExpression.body as FunctionBodyImpl).localVariableInfo =
-          _localVariableInfo;
-      _enclosingFunction = node.declaredElement;
-      super.visitFunctionDeclaration(node);
-    } finally {
-      _enclosingFunction = outerFunction;
-    }
+    (node.functionExpression.body as FunctionBodyImpl).localVariableInfo =
+        _localVariableInfo;
+    super.visitFunctionDeclaration(node);
   }
 
   @override
   void visitFunctionExpression(FunctionExpression node) {
     if (node.parent is! FunctionDeclaration) {
-      var outerFunction = _enclosingFunction;
-      try {
-        (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
-        _enclosingFunction = node.declaredElement;
-        super.visitFunctionExpression(node);
-      } finally {
-        _enclosingFunction = outerFunction;
-      }
+      (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
+      super.visitFunctionExpression(node);
     } else {
       super.visitFunctionExpression(node);
     }
@@ -3290,14 +3205,8 @@
 
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
-    var outerFunction = _enclosingFunction;
-    try {
-      (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
-      _enclosingFunction = node.declaredElement;
-      super.visitMethodDeclaration(node);
-    } finally {
-      _enclosingFunction = outerFunction;
-    }
+    (node.body as FunctionBodyImpl).localVariableInfo = _localVariableInfo;
+    super.visitMethodDeclaration(node);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/generated/testing/element_factory.dart b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
index 6045950..ed9b4f8 100644
--- a/pkg/analyzer/lib/src/generated/testing/element_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/element_factory.dart
@@ -106,9 +106,11 @@
   static ConstructorElementImpl constructorElement(
       ClassElement definingClass, String? name, bool isConst,
       [List<DartType> argumentTypes = const []]) {
-    ConstructorElementImpl constructor = name == null
-        ? ConstructorElementImpl("", -1)
-        : ConstructorElementImpl(name, 0);
+    var offset = name == null ? -1 : 0;
+    // An unnamed constructor declared with `C.new(` is modeled as unnamed.
+    var constructor = name == null || name == 'new'
+        ? ConstructorElementImpl('', offset)
+        : ConstructorElementImpl(name, offset);
     if (name != null) {
       if (name.isEmpty) {
         constructor.nameEnd = definingClass.name.length;
diff --git a/pkg/analyzer/lib/src/lint/linter_visitor.dart b/pkg/analyzer/lib/src/lint/linter_visitor.dart
index df3f994..0794a4c 100644
--- a/pkg/analyzer/lib/src/lint/linter_visitor.dart
+++ b/pkg/analyzer/lib/src/lint/linter_visitor.dart
@@ -4,6 +4,7 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/lint/linter.dart';
 import 'package:analyzer/src/services/lint.dart';
 
@@ -16,7 +17,9 @@
   final NodeLintRegistry registry;
   final LintRuleExceptionHandler exceptionHandler;
 
-  LinterVisitor(this.registry, this.exceptionHandler);
+  LinterVisitor(this.registry, [LintRuleExceptionHandler? exceptionHandler])
+      : exceptionHandler =
+            exceptionHandler ?? LinterExceptionHandler(true).logException;
 
   @override
   void visitAdjacentStrings(AdjacentStrings node) {
diff --git a/pkg/analyzer/lib/src/macro/api/code.dart b/pkg/analyzer/lib/src/macro/api/code.dart
new file mode 100644
index 0000000..a3fed07
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/api/code.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+/// Combines [parts] into a [String].
+/// Must only contain [Code] or [String] instances.
+String _combineParts(List<Object> parts) {
+  var buffer = StringBuffer();
+
+  void write(Object part) {
+    if (part is String) {
+      buffer.write(part);
+    } else if (part is Code) {
+      buffer.write(part.code);
+    } else if (part is Iterable<Object>) {
+      part.forEach(write);
+    } else {
+      throw UnsupportedError(
+        'Only String, Code, and List(s) of them are '
+        'allowed but got ${part.runtimeType}',
+      );
+    }
+  }
+
+  write(parts);
+  return buffer.toString();
+}
+
+/// The representation of a piece of code.
+abstract class Code {
+  String get code;
+
+  @override
+  String toString() => code;
+}
+
+/// A piece of code representing a syntactically valid declaration.
+class Declaration extends Code {
+  @override
+  final String code;
+
+  Declaration(this.code);
+
+  /// Creates a [Declaration] from [parts], which must be of type [Code],
+  /// [String], or [Iterable]s of them.
+  factory Declaration.fromParts(List<Object> parts) =>
+      Declaration(_combineParts(parts));
+}
+
+/// A piece of code that can't be parsed into a valid language construct in its
+/// current form. No validation or parsing is performed.
+class Fragment extends Code {
+  @override
+  final String code;
+
+  Fragment(this.code);
+
+  /// Creates a [Fragment] from [parts], which must be of type [Code],
+  /// [String], or [Iterable]s of them.
+  factory Fragment.fromParts(List<Object> parts) =>
+      Fragment(_combineParts(parts));
+}
diff --git a/pkg/analyzer/lib/src/macro/api/macro.dart b/pkg/analyzer/lib/src/macro/api/macro.dart
new file mode 100644
index 0000000..78eb6c0
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/api/macro.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// 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/dart/ast/ast.dart' as ast;
+import 'package:analyzer/src/macro/api/code.dart';
+
+/// The api used by [DeclarationMacro]s to contribute new declarations to the
+/// current class.
+///
+/// Note that this is available to macros that run directly on classes, as well
+/// as macros that run on any members of a class.
+abstract class ClassDeclarationBuilder implements DeclarationBuilder {
+  /// Adds a new declaration to the surrounding class.
+  void addToClass(Declaration declaration);
+}
+
+/// The interface for [DeclarationMacro]s that can be applied to classes.
+abstract class ClassDeclarationMacro implements DeclarationMacro {
+  void visitClassDeclaration(
+      ast.ClassDeclaration declaration, ClassDeclarationBuilder builder);
+}
+
+/// The api used by [DeclarationMacro]s to contribute new declarations to the
+/// current library.
+abstract class DeclarationBuilder {
+  /// Adds a new regular declaration to the surrounding library.
+  ///
+  /// Note that type declarations are not supported.
+  void addToLibrary(Declaration declaration);
+
+  /// Return the [Code] of the [node].
+  Code typeAnnotationCode(ast.TypeAnnotation node);
+}
+
+/// The marker interface for macros that are allowed to contribute new
+/// declarations to the program, including both top level and class level
+/// declarations.
+///
+/// These macros run after [TypeMacro] macros, but before [DefinitionMacro]
+/// macros.
+///
+/// These macros can resolve type annotations to specific declarations, and
+/// inspect type hierarchies, but they cannot inspect the declarations on those
+/// type annotations, since new declarations could still be added in this phase.
+abstract class DeclarationMacro implements Macro {}
+
+/// The marker interface for macros that are only allowed to implement or wrap
+/// existing declarations in the program. They cannot introduce any new
+/// declarations that are visible to the program, but are allowed to add
+/// declarations that only they can see.
+///
+/// These macros run after all other types of macros.
+///
+/// These macros can fully reflect on the program since the static shape is
+/// fully defined by the time they run.
+abstract class DefinitionMacro implements Macro {}
+
+/// The interface for [DeclarationMacro]s that can be applied to fields.
+abstract class FieldDeclarationMacro implements DeclarationMacro {
+  void visitFieldDeclaration(
+    ast.FieldDeclaration declaration,
+    ClassDeclarationBuilder builder,
+  );
+}
+
+/// The marker interface for all types of macros.
+abstract class Macro {}
+
+/// The marker interface for macros that are allowed to contribute new type
+/// declarations into the program.
+///
+/// These macros run before all other types of macros.
+///
+/// In exchange for the power to add new type declarations, these macros have
+/// limited introspections capabilities, since new types can be added in this
+/// phase you cannot follow type references back to their declarations.
+abstract class TypeMacro implements Macro {}
diff --git a/pkg/analyzer/lib/src/macro/builders/data_class.dart b/pkg/analyzer/lib/src/macro/builders/data_class.dart
new file mode 100644
index 0000000..664f5d8
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/builders/data_class.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// 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/dart/ast/ast.dart' as ast;
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/macro/api/code.dart';
+import 'package:analyzer/src/macro/api/macro.dart';
+
+class AutoConstructorMacro implements ClassDeclarationMacro {
+  const AutoConstructorMacro();
+
+  @override
+  void visitClassDeclaration(
+    ast.ClassDeclaration node,
+    ClassDeclarationBuilder builder,
+  ) {
+    // TODO(scheglov) Should we provide the element as a parameter?
+    var classElement = node.declaredElement!;
+    var typeSystem = classElement.library.typeSystem;
+
+    if (classElement.unnamedConstructor != null) {
+      throw ArgumentError(
+        'Cannot generate a constructor because one already exists',
+      );
+    }
+
+    var fieldsCode = classElement.fields.map((field) {
+      var isNullable = typeSystem.isNullable(field.type);
+      var requiredKeyword = isNullable ? '' : 'required ';
+      return '${requiredKeyword}this.${field.name}';
+    }).join(', ');
+
+    // TODO(scheglov) super constructor
+
+    builder.addToClass(
+      Declaration('${classElement.name}({$fieldsCode});'),
+    );
+  }
+}
+
+class HashCodeMacro implements ClassDeclarationMacro {
+  const HashCodeMacro();
+
+  @override
+  void visitClassDeclaration(
+    ast.ClassDeclaration node,
+    ClassDeclarationBuilder builder,
+  ) {
+    var expression = node.declaredElement!.allFields
+        .map((e) => '${e.name}.hashCode')
+        .join(' ^ ');
+    builder.addToClass(
+      Declaration('''
+@override
+int get hashCode => $expression;'''),
+    );
+  }
+}
+
+class ToStringMacro implements ClassDeclarationMacro {
+  const ToStringMacro();
+
+  @override
+  void visitClassDeclaration(
+    ast.ClassDeclaration node,
+    ClassDeclarationBuilder builder,
+  ) {
+    var classElement = node.declaredElement!;
+    var fieldsCode = classElement.allFields.map((field) {
+      var name = field.name;
+      return '$name: \$$name';
+    }).join(', ');
+    builder.addToClass(
+      Declaration('''
+@override
+String toString() => '${classElement.name}($fieldsCode)';'''),
+    );
+  }
+}
+
+extension on ClassElement {
+  Iterable<FieldElement> get allFields sync* {
+    for (ClassElement? class_ = this; class_ != null;) {
+      yield* class_.fields.where((e) => !e.isSynthetic);
+      class_ = class_.supertype?.element;
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/macro/builders/observable.dart b/pkg/analyzer/lib/src/macro/builders/observable.dart
new file mode 100644
index 0000000..6857d34
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/builders/observable.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// 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/dart/ast/ast.dart' as ast;
+import 'package:analyzer/src/macro/api/code.dart';
+import 'package:analyzer/src/macro/api/macro.dart';
+
+class ObservableMacro implements FieldDeclarationMacro {
+  const ObservableMacro();
+
+  @override
+  void visitFieldDeclaration(
+    ast.FieldDeclaration node,
+    ClassDeclarationBuilder builder,
+  ) {
+    var typeNode = node.fields.type;
+    if (typeNode == null) {
+      throw ArgumentError('@observable can only annotate typed fields.');
+    }
+    var typeCode = builder.typeAnnotationCode(typeNode);
+
+    var fields = node.fields.variables;
+    for (var field in fields) {
+      var name = field.name.name;
+      if (!name.startsWith('_')) {
+        throw ArgumentError(
+          '@observable can only annotate private fields, and it will create '
+          'public getters and setters for them, but the public field '
+          '$name was annotated.',
+        );
+      }
+      var publicName = name.substring(1);
+
+      var getter = Declaration(
+        '$typeCode get $publicName => $name;',
+      );
+      builder.addToClass(getter);
+
+      var setter = Declaration('''
+set $publicName($typeCode val) {
+  print('Setting $publicName to \${val}');
+  $name = val;
+}''');
+      builder.addToClass(setter);
+    }
+  }
+}
diff --git a/pkg/analyzer/lib/src/macro/impl/macro.dart b/pkg/analyzer/lib/src/macro/impl/macro.dart
new file mode 100644
index 0000000..73e10f7
--- /dev/null
+++ b/pkg/analyzer/lib/src/macro/impl/macro.dart
@@ -0,0 +1,108 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// 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 'dart:typed_data';
+
+import 'package:analyzer/dart/analysis/utilities.dart';
+import 'package:analyzer/dart/ast/ast.dart' as ast;
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/ast.dart' as ast;
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/macro/api/code.dart';
+import 'package:analyzer/src/macro/api/macro.dart';
+import 'package:analyzer/src/summary2/informative_data.dart';
+
+class ClassDeclarationBuilderImpl extends DeclarationBuilderImpl
+    implements ClassDeclarationBuilder {
+  final DeclarationCollector _collector;
+  final ast.ClassDeclarationImpl node;
+
+  ClassDeclarationBuilderImpl(this._collector, this.node);
+
+  @override
+  void addToClass(Declaration declaration) {
+    var declarationCode = declaration.code.trim();
+
+    // TODO(scheglov) feature set
+    // TODO(scheglov) throw if errors?
+    var parseResult = parseString(
+      content: 'class ${node.name.name} { $declarationCode }',
+    );
+    var parsedDeclarations = parseResult.unit.declarations;
+    var parsedClass = parsedDeclarations.single as ast.ClassDeclaration;
+    var parsedMember = parsedClass.members.single;
+    _rebaseOffsets(parsedMember);
+
+    node.members.add(parsedMember);
+    _collector._add(parsedMember, declaration);
+  }
+
+  /// We parsed [node] in the context of some synthetic code string, its
+  /// current offsets only have meaning relative to the begin offset of the
+  /// [node]. So, we update offsets accordingly.
+  static void _rebaseOffsets(ast.AstNode node) {
+    var baseOffset = node.offset;
+    for (Token? t = node.beginToken;
+        t != null && t != node.endToken;
+        t = t.next) {
+      t.offset -= baseOffset;
+    }
+  }
+}
+
+class DeclarationBuilderImpl implements DeclarationBuilder {
+  @override
+  void addToLibrary(Declaration declaration) {
+    // TODO: implement addToLibrary
+  }
+
+  @override
+  Code typeAnnotationCode(ast.TypeAnnotation node) {
+    return Fragment(node.toSource());
+  }
+}
+
+class DeclarationCollector {
+  final Map<ast.AstNode, _CollectedDeclaration> _declarations = {};
+  int _nextId = 0;
+
+  /// Elements for nodes in [_declarations] were built.
+  /// Move information from [_CollectedDeclaration] into elements.
+  void updateElements() {
+    for (var entry in _declarations.entries) {
+      var node = entry.key;
+      if (node is ast.Declaration) {
+        var element = node.declaredElement;
+        if (element is HasMacroGenerationData) {
+          var collectedDeclaration = entry.value;
+          (element as HasMacroGenerationData).macro = MacroGenerationData(
+            collectedDeclaration.id,
+            collectedDeclaration.declaration.code,
+            collectedDeclaration.informative,
+          );
+        }
+      }
+    }
+  }
+
+  void _add(ast.AstNode node, Declaration declaration) {
+    _declarations[node] = _CollectedDeclaration(
+      _nextId++,
+      declaration,
+      writeDeclarationInformative(node),
+    );
+  }
+}
+
+class _CollectedDeclaration {
+  final int id;
+  final Declaration declaration;
+  final Uint8List informative;
+
+  _CollectedDeclaration(
+    this.id,
+    this.declaration,
+    this.informative,
+  );
+}
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index cccbbb3..51a33b6 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -493,12 +493,24 @@
       offset: resolutionOffset,
     );
 
-    InformativeDataApplier(_elementFactory, _unitsInformativeBytes)
-        .applyTo(libraryElement);
+    _declareDartCoreDynamicNever();
+
+    InformativeDataApplier(_elementFactory).applyTo(
+      _unitsInformativeBytes,
+      libraryElement,
+    );
 
     return libraryElement;
   }
 
+  /// These elements are implicitly declared in `dart:core`.
+  void _declareDartCoreDynamicNever() {
+    if (_reference.name == 'dart:core') {
+      _reference.getChild('dynamic').element = DynamicElementImpl.instance;
+      _reference.getChild('Never').element = NeverElementImpl.instance;
+    }
+  }
+
   ClassElementImpl _readClassElement(
     CompilationUnitElementImpl unitElement,
     Reference unitReference,
@@ -580,6 +592,7 @@
       element.setLinkedData(reference, linkedData);
       ConstructorElementFlags.read(_reader, element);
       element.parameters = _readParameters(element, reference);
+      _readMacro(element, element);
       return element;
     });
   }
@@ -840,6 +853,20 @@
     return LibraryLanguageVersion(package: package, override: override);
   }
 
+  void _readMacro(Element element, HasMacroGenerationData hasMacro) {
+    if (_reader.readBool()) {
+      hasMacro.macro = MacroGenerationData(
+        _reader.readUInt30(),
+        _reader.readStringUtf8(),
+        Uint8List(0),
+      );
+      InformativeDataApplier(_elementFactory).applyToDeclaration(
+        element,
+        _reader.readUint8List(),
+      );
+    }
+  }
+
   List<MethodElementImpl> _readMethods(
     CompilationUnitElementImpl unitElement,
     ElementImpl enclosingElement,
@@ -863,6 +890,7 @@
       element.typeParameters = _readTypeParameters();
       element.parameters = _readParameters(element, reference);
       element.typeInferenceError = _readTopLevelInferenceError();
+      _readMacro(element, element);
       return element;
     });
   }
@@ -989,6 +1017,7 @@
     element.setLinkedData(reference, linkedData);
 
     element.parameters = _readParameters(element, reference);
+    _readMacro(element, element);
     return element;
   }
 
@@ -1525,23 +1554,29 @@
           parameters: type.parameters,
           returnType: type.returnType,
           nullabilitySuffix: type.nullabilitySuffix,
-          aliasElement: aliasElement,
-          aliasArguments: aliasArguments,
+          alias: InstantiatedTypeAliasElementImpl(
+            element: aliasElement,
+            typeArguments: aliasArguments,
+          ),
         );
       } else if (type is InterfaceType) {
         return InterfaceTypeImpl(
           element: type.element,
           typeArguments: type.typeArguments,
           nullabilitySuffix: type.nullabilitySuffix,
-          aliasElement: aliasElement,
-          aliasArguments: aliasArguments,
+          alias: InstantiatedTypeAliasElementImpl(
+            element: aliasElement,
+            typeArguments: aliasArguments,
+          ),
         );
       } else if (type is TypeParameterType) {
         return TypeParameterTypeImpl(
           element: type.element,
           nullabilitySuffix: type.nullabilitySuffix,
-          aliasElement: aliasElement,
-          aliasArguments: aliasArguments,
+          alias: InstantiatedTypeAliasElementImpl(
+            element: aliasElement,
+            typeArguments: aliasArguments,
+          ),
         );
       } else if (type is VoidType) {
         // TODO(scheglov) add support for `void` aliasing
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index 528b9d2..5fd0bf8 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -164,6 +164,7 @@
     _resolutionSink.localElements.declareAll(element.parameters);
     try {
       _writeList(element.parameters, _writeParameterElement);
+      _writeMacro(element.macro);
       if (element.isConst || element.isFactory) {
         _resolutionSink.writeElement(element.redirectedConstructor);
         _resolutionSink._writeNodeList(element.constantInitializers);
@@ -280,6 +281,15 @@
     }
   }
 
+  void _writeMacro(MacroGenerationData? macro) {
+    _sink.writeBool(macro != null);
+    if (macro != null) {
+      _sink.writeUInt30(macro.id);
+      _sink.writeStringUtf8(macro.code);
+      _sink.writeUint8List(macro.informative);
+    }
+  }
+
   void _writeMethodElement(MethodElement element) {
     element as MethodElementImpl;
     _sink.writeUInt30(_resolutionSink.offset);
@@ -293,6 +303,8 @@
       _sink._writeTopLevelInferenceError(element.typeInferenceError);
       _resolutionSink.writeType(element.returnType);
     });
+
+    _writeMacro(element.macro);
   }
 
   void _writeMixinElement(ClassElement element) {
@@ -367,7 +379,9 @@
 
     _resolutionSink._writeAnnotationList(element.metadata);
     _resolutionSink.writeType(element.returnType);
+
     _writeList(element.parameters, _writeParameterElement);
+    _writeMacro(element.macro);
   }
 
   void _writeReferences(List<Reference> references) {
@@ -706,10 +720,10 @@
   }
 
   void _writeTypeAliasElementArguments(DartType type) {
-    var aliasElement = type.aliasElement;
-    _writeElement(aliasElement);
-    if (aliasElement != null) {
-      _writeTypeList(type.aliasArguments!);
+    var alias = type.alias;
+    _writeElement(alias?.element);
+    if (alias != null) {
+      _writeTypeList(alias.typeArguments);
     }
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index 3737f6e..b5b366b 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -89,6 +89,19 @@
     }
   }
 
+  /// Build elements for [members] and add into the [element].
+  void buildMacroClassMembers(
+    ClassElementImpl element,
+    List<ClassMember> members,
+  ) {
+    var holder = _buildClassMembers(element, members);
+
+    element.accessors.addAll(holder.propertyAccessors);
+    element.constructors.addAll(holder.constructors);
+    element.fields.addAll(holder.properties.whereType<FieldElementImpl>());
+    element.methods.addAll(holder.methods);
+  }
+
   @override
   void visitClassDeclaration(covariant ClassDeclarationImpl node) {
     var nameNode = node.name;
@@ -159,6 +172,10 @@
   ) {
     var nameNode = node.name ?? node.returnType;
     var name = node.name?.name ?? '';
+    if (name == 'new') {
+      // An unnamed constructor declared with `C.new(` is modeled as unnamed.
+      name = '';
+    }
     var nameOffset = nameNode.offset;
 
     var element = ConstructorElementImpl(name, nameOffset);
@@ -868,7 +885,7 @@
   }
 
   _EnclosingContext _buildClassMembers(
-      ElementImpl element, NodeList<ClassMember> members) {
+      ElementImpl element, List<ClassMember> members) {
     var hasConstConstructor = members.any((e) {
       return e is ConstructorDeclaration && e.constKeyword != null;
     });
@@ -884,29 +901,9 @@
     var element = node.declaredElement as ClassElementImpl;
     var holder = _buildClassMembers(element, node.members);
     element.accessors = holder.propertyAccessors;
+    element.constructors = holder.constructors;
     element.fields = holder.properties.whereType<FieldElement>().toList();
     element.methods = holder.methods;
-
-    var constructors = holder.constructors;
-    if (constructors.isEmpty) {
-      var containerRef = element.reference!.getChild('@constructor');
-      constructors = [
-        ConstructorElementImpl('', -1)
-          ..isSynthetic = true
-          ..reference = containerRef.getChild(''),
-      ];
-    }
-    element.constructors = constructors;
-
-    // We have all fields and constructors.
-    // Now we can resolve field formal parameters.
-    for (var constructor in constructors) {
-      for (var parameter in constructor.parameters) {
-        if (parameter is FieldFormalParameterElementImpl) {
-          parameter.field = element.getField(parameter.name);
-        }
-      }
-    }
   }
 
   void _buildExecutableElementChildren({
diff --git a/pkg/analyzer/lib/src/summary2/element_flags.dart b/pkg/analyzer/lib/src/summary2/element_flags.dart
index e808000..529a06f 100644
--- a/pkg/analyzer/lib/src/summary2/element_flags.dart
+++ b/pkg/analyzer/lib/src/summary2/element_flags.dart
@@ -8,8 +8,8 @@
 
 class ClassElementFlags {
   static const int _isAbstract = 1 << 0;
-  static const int _isMixinApplication = 1 << 1;
-  static const int _isSimplyBounded = 1 << 2;
+  static const int _isMixinApplication = 1 << 2;
+  static const int _isSimplyBounded = 1 << 3;
 
   static void read(SummaryDataReader reader, ClassElementImpl element) {
     var byte = reader.readByte();
@@ -60,8 +60,8 @@
   static const int _isCovariant = 1 << 5;
   static const int _isExternal = 1 << 6;
   static const int _isFinal = 1 << 7;
-  static const int _isLate = 1 << 8;
-  static const int _isStatic = 1 << 9;
+  static const int _isLate = 1 << 9;
+  static const int _isStatic = 1 << 10;
 
   static void read(SummaryDataReader reader, FieldElementImpl element) {
     var byte = reader.readUInt30();
@@ -161,8 +161,8 @@
   static const int _isAbstract = 1 << 1;
   static const int _isAsynchronous = 1 << 2;
   static const int _isExternal = 1 << 3;
-  static const int _isGenerator = 1 << 4;
-  static const int _isStatic = 1 << 5;
+  static const int _isGenerator = 1 << 5;
+  static const int _isStatic = 1 << 6;
 
   static void read(SummaryDataReader reader, MethodElementImpl element) {
     var byte = reader.readByte();
@@ -217,8 +217,8 @@
   static const int _isAbstract = 1 << 3;
   static const int _isAsynchronous = 1 << 4;
   static const int _isExternal = 1 << 5;
-  static const int _isGenerator = 1 << 6;
-  static const int _isStatic = 1 << 7;
+  static const int _isGenerator = 1 << 7;
+  static const int _isStatic = 1 << 8;
 
   static void read(
     SummaryDataReader reader,
diff --git a/pkg/analyzer/lib/src/summary2/function_type_builder.dart b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
index f59a117..4ab0f6a 100644
--- a/pkg/analyzer/lib/src/summary2/function_type_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
@@ -190,7 +190,7 @@
       } else if (isNNBD) {
         nullabilitySuffix = NullabilitySuffix.none;
       } else {
-        nullabilitySuffix = NullabilitySuffix.question;
+        nullabilitySuffix = NullabilitySuffix.star;
       }
 
       return FunctionTypeBuilder(
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index 1dd1e5f..f14a0f2 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -19,6 +19,15 @@
 import 'package:analyzer/src/util/comment.dart';
 import 'package:collection/collection.dart';
 
+/// Write the informative data (mostly offsets) of the given [node].
+/// Throw [UnimplementedError] if [node] is not supported.
+Uint8List writeDeclarationInformative(AstNode node) {
+  var byteSink = ByteSink();
+  var sink = BufferedSink(byteSink);
+  _InformativeDataWriter(sink).writeDeclaration(node);
+  return sink.flushAndTake();
+}
+
 Uint8List writeUnitInformative(CompilationUnit unit) {
   var byteSink = ByteSink();
   var sink = BufferedSink(byteSink);
@@ -55,14 +64,13 @@
 
 class InformativeDataApplier {
   final LinkedElementFactory _elementFactory;
-  final Map<Uri, Uint8List> _unitsInformativeBytes2;
 
-  InformativeDataApplier(
-    this._elementFactory,
-    this._unitsInformativeBytes2,
-  );
+  InformativeDataApplier(this._elementFactory);
 
-  void applyTo(LibraryElementImpl libraryElement) {
+  void applyTo(
+    Map<Uri, Uint8List> unitsInformativeBytes,
+    LibraryElementImpl libraryElement,
+  ) {
     if (_elementFactory.isApplyingInformativeData) {
       throw StateError('Unexpected recursion.');
     }
@@ -72,7 +80,7 @@
     for (var i = 0; i < unitElements.length; i++) {
       var unitElement = unitElements[i] as CompilationUnitElementImpl;
       var unitUri = unitElement.source.uri;
-      var unitInfoBytes = _unitsInformativeBytes2[unitUri];
+      var unitInfoBytes = unitsInformativeBytes[unitUri];
       if (unitInfoBytes != null) {
         var unitReader = SummaryDataReader(unitInfoBytes);
         var unitInfo = _InfoUnit(unitReader);
@@ -140,35 +148,49 @@
     _elementFactory.isApplyingInformativeData = false;
   }
 
+  /// Read informative data from [bytes], and apply it to [element].
+  /// The data and the [element] must correspond to each other.
+  void applyToDeclaration(Element element, Uint8List bytes) {
+    if (_elementFactory.isApplyingInformativeData) {
+      throw StateError('Unexpected recursion.');
+    }
+    _elementFactory.isApplyingInformativeData = true;
+
+    var reader = SummaryDataReader(bytes);
+
+    var kindIndex = reader.readByte();
+    var kind = _DeclarationKind.values[kindIndex];
+
+    if (kind == _DeclarationKind.constructorDeclaration &&
+        element is ConstructorElement) {
+      var info = _InfoConstructorDeclaration(reader);
+      _applyToConstructor(element, info);
+    } else if (kind == _DeclarationKind.methodDeclaration &&
+        element is MethodElement) {
+      var info = _InfoMethodDeclaration(reader);
+      _applyToMethod(element, info);
+    } else if (kind == _DeclarationKind.methodDeclaration &&
+        element is PropertyAccessorElement) {
+      var info = _InfoMethodDeclaration(reader);
+      _applyToPropertyAccessor(element, info);
+    } else {
+      throw UnimplementedError(
+        'Unsupported kind: $kind, '
+        'or element: ${element.runtimeType}',
+      );
+    }
+
+    _elementFactory.isApplyingInformativeData = false;
+  }
+
   void _applyToAccessors(
     List<PropertyAccessorElement> elementList,
     List<_InfoMethodDeclaration> infoList,
   ) {
-    forCorrespondingPairs<PropertyAccessorElement, _InfoMethodDeclaration>(
+    forCorrespondingPairs(
       elementList.notSynthetic,
       infoList,
-      (element, info) {
-        element as PropertyAccessorElementImpl;
-        element.setCodeRange(info.codeOffset, info.codeLength);
-        element.nameOffset = info.nameOffset;
-        element.documentationComment = info.documentationComment;
-        _applyToFormalParameters(
-          element.parameters_unresolved,
-          info.parameters,
-        );
-
-        var linkedData = element.linkedData;
-        if (linkedData is PropertyAccessorElementLinkedData) {
-          linkedData.applyConstantOffsets = ApplyConstantOffsets(
-            info.constantOffsets,
-            (applier) {
-              applier.applyToMetadata(element);
-              applier.applyToTypeParameters(element.typeParameters);
-              applier.applyToFormalParameters(element.parameters);
-            },
-          );
-        }
-      },
+      _applyToPropertyAccessor,
     );
   }
 
@@ -240,6 +262,32 @@
     );
   }
 
+  void _applyToConstructor(
+    ConstructorElement element,
+    _InfoConstructorDeclaration info,
+  ) {
+    element as ConstructorElementImpl;
+    element.setCodeRange(info.codeOffset, info.codeLength);
+    element.periodOffset = info.periodOffset;
+    element.nameOffset = info.nameOffset;
+    element.nameEnd = info.nameEnd;
+    element.documentationComment = info.documentationComment;
+    _applyToFormalParameters(
+      element.parameters_unresolved,
+      info.parameters,
+    );
+
+    var linkedData = element.linkedData as ConstructorElementLinkedData;
+    linkedData.applyConstantOffsets = ApplyConstantOffsets(
+      info.constantOffsets,
+      (applier) {
+        applier.applyToMetadata(element);
+        applier.applyToFormalParameters(element.parameters);
+        applier.applyToConstructorInitializers(element);
+      },
+    );
+  }
+
   void _applyToConstructors(
     List<ConstructorElement> elementList,
     List<_InfoConstructorDeclaration> infoList,
@@ -247,28 +295,7 @@
     forCorrespondingPairs<ConstructorElement, _InfoConstructorDeclaration>(
       elementList,
       infoList,
-      (element, info) {
-        element as ConstructorElementImpl;
-        element.setCodeRange(info.codeOffset, info.codeLength);
-        element.periodOffset = info.periodOffset;
-        element.nameOffset = info.nameOffset;
-        element.nameEnd = info.nameEnd;
-        element.documentationComment = info.documentationComment;
-        _applyToFormalParameters(
-          element.parameters_unresolved,
-          info.parameters,
-        );
-
-        var linkedData = element.linkedData as ConstructorElementLinkedData;
-        linkedData.applyConstantOffsets = ApplyConstantOffsets(
-          info.constantOffsets,
-          (applier) {
-            applier.applyToMetadata(element);
-            applier.applyToFormalParameters(element.parameters);
-            applier.applyToConstructorInitializers(element);
-          },
-        );
-      },
+      _applyToConstructor,
     );
   }
 
@@ -499,6 +526,31 @@
     );
   }
 
+  void _applyToMethod(MethodElement element, _InfoMethodDeclaration info) {
+    element as MethodElementImpl;
+    element.setCodeRange(info.codeOffset, info.codeLength);
+    element.nameOffset = info.nameOffset;
+    element.documentationComment = info.documentationComment;
+    _applyToTypeParameters(
+      element.typeParameters_unresolved,
+      info.typeParameters,
+    );
+    _applyToFormalParameters(
+      element.parameters_unresolved,
+      info.parameters,
+    );
+
+    var linkedData = element.linkedData as MethodElementLinkedData;
+    linkedData.applyConstantOffsets = ApplyConstantOffsets(
+      info.constantOffsets,
+      (applier) {
+        applier.applyToMetadata(element);
+        applier.applyToTypeParameters(element.typeParameters);
+        applier.applyToFormalParameters(element.parameters);
+      },
+    );
+  }
+
   void _applyToMethods(
     List<MethodElement> elementList,
     List<_InfoMethodDeclaration> infoList,
@@ -506,30 +558,7 @@
     forCorrespondingPairs<MethodElement, _InfoMethodDeclaration>(
       elementList,
       infoList,
-      (element, info) {
-        element as MethodElementImpl;
-        element.setCodeRange(info.codeOffset, info.codeLength);
-        element.nameOffset = info.nameOffset;
-        element.documentationComment = info.documentationComment;
-        _applyToTypeParameters(
-          element.typeParameters_unresolved,
-          info.typeParameters,
-        );
-        _applyToFormalParameters(
-          element.parameters_unresolved,
-          info.parameters,
-        );
-
-        var linkedData = element.linkedData as MethodElementLinkedData;
-        linkedData.applyConstantOffsets = ApplyConstantOffsets(
-          info.constantOffsets,
-          (applier) {
-            applier.applyToMetadata(element);
-            applier.applyToTypeParameters(element.typeParameters);
-            applier.applyToFormalParameters(element.parameters);
-          },
-        );
-      },
+      _applyToMethod,
     );
   }
 
@@ -560,6 +589,32 @@
     );
   }
 
+  void _applyToPropertyAccessor(
+    PropertyAccessorElement element,
+    _InfoMethodDeclaration info,
+  ) {
+    element as PropertyAccessorElementImpl;
+    element.setCodeRange(info.codeOffset, info.codeLength);
+    element.nameOffset = info.nameOffset;
+    element.documentationComment = info.documentationComment;
+    _applyToFormalParameters(
+      element.parameters_unresolved,
+      info.parameters,
+    );
+
+    var linkedData = element.linkedData;
+    if (linkedData is PropertyAccessorElementLinkedData) {
+      linkedData.applyConstantOffsets = ApplyConstantOffsets(
+        info.constantOffsets,
+        (applier) {
+          applier.applyToMetadata(element);
+          applier.applyToTypeParameters(element.typeParameters);
+          applier.applyToFormalParameters(element.parameters);
+        },
+      );
+    }
+  }
+
   void _applyToTopLevelVariable(
     TopLevelVariableElement element,
     _InfoTopLevelVariable info,
@@ -629,6 +684,11 @@
   }
 }
 
+enum _DeclarationKind {
+  constructorDeclaration,
+  methodDeclaration,
+}
+
 class _InfoClassDeclaration {
   final int codeOffset;
   final int codeLength;
@@ -1289,6 +1349,18 @@
     );
   }
 
+  void writeDeclaration(AstNode node) {
+    if (node is ConstructorDeclaration) {
+      sink.addByte(_DeclarationKind.constructorDeclaration.index);
+      _writeConstructor(node);
+    } else if (node is MethodDeclaration) {
+      sink.addByte(_DeclarationKind.methodDeclaration.index);
+      _writeMethod(node);
+    } else {
+      throw UnimplementedError('(${node.runtimeType}) $node');
+    }
+  }
+
   int _codeOffsetForVariable(VariableDeclaration node) {
     var codeOffset = node.offset;
     var variableList = node.parent as VariableDeclarationList;
@@ -1305,22 +1377,24 @@
     });
   }
 
+  void _writeConstructor(ConstructorDeclaration node) {
+    sink.writeUInt30(node.offset);
+    sink.writeUInt30(node.length);
+    sink.writeOptionalUInt30(node.period?.offset);
+    var nameNode = node.name ?? node.returnType;
+    sink.writeUInt30(nameNode.offset);
+    sink.writeUInt30(nameNode.end);
+    _writeDocumentationComment(node);
+    _writeFormalParameters(node.parameters);
+    _writeOffsets(
+      metadata: node.metadata,
+      formalParameters: node.parameters,
+      constructorInitializers: node.initializers,
+    );
+  }
+
   void _writeConstructors(List<ClassMember> members) {
-    sink.writeList2<ConstructorDeclaration>(members, (node) {
-      sink.writeUInt30(node.offset);
-      sink.writeUInt30(node.length);
-      sink.writeOptionalUInt30(node.period?.offset);
-      var nameNode = node.name ?? node.returnType;
-      sink.writeUInt30(nameNode.offset);
-      sink.writeUInt30(nameNode.end);
-      _writeDocumentationComment(node);
-      _writeFormalParameters(node.parameters);
-      _writeOffsets(
-        metadata: node.metadata,
-        formalParameters: node.parameters,
-        constructorInitializers: node.initializers,
-      );
-    });
+    sink.writeList2<ConstructorDeclaration>(members, _writeConstructor);
   }
 
   void _writeDocumentationComment(AnnotatedNode node) {
@@ -1383,19 +1457,7 @@
           .whereType<MethodDeclaration>()
           .where((e) => e.isGetter || e.isSetter)
           .toList(),
-      (node) {
-        sink.writeUInt30(node.offset);
-        sink.writeUInt30(node.length);
-        sink.writeUInt30(node.name.offset);
-        _writeDocumentationComment(node);
-        _writeTypeParameters(node.typeParameters);
-        _writeFormalParameters(node.parameters);
-        _writeOffsets(
-          metadata: node.metadata,
-          typeParameters: node.typeParameters,
-          formalParameters: node.parameters,
-        );
-      },
+      _writeMethod,
     );
   }
 
@@ -1420,25 +1482,27 @@
     );
   }
 
+  void _writeMethod(MethodDeclaration node) {
+    sink.writeUInt30(node.offset);
+    sink.writeUInt30(node.length);
+    sink.writeUInt30(node.name.offset);
+    _writeDocumentationComment(node);
+    _writeTypeParameters(node.typeParameters);
+    _writeFormalParameters(node.parameters);
+    _writeOffsets(
+      metadata: node.metadata,
+      typeParameters: node.typeParameters,
+      formalParameters: node.parameters,
+    );
+  }
+
   void _writeMethods(List<ClassMember> members) {
     sink.writeList<MethodDeclaration>(
       members
           .whereType<MethodDeclaration>()
           .where((e) => !(e.isGetter || e.isSetter))
           .toList(),
-      (node) {
-        sink.writeUInt30(node.offset);
-        sink.writeUInt30(node.length);
-        sink.writeUInt30(node.name.offset);
-        _writeDocumentationComment(node);
-        _writeTypeParameters(node.typeParameters);
-        _writeFormalParameters(node.parameters);
-        _writeOffsets(
-          metadata: node.metadata,
-          typeParameters: node.typeParameters,
-          formalParameters: node.parameters,
-        );
-      },
+      _writeMethod,
     );
   }
 
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 2c1a0b3..c1eb205 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -2,13 +2,15 @@
 // 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/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart' as ast;
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/ast/ast.dart' as ast;
 import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
+import 'package:analyzer/src/macro/builders/data_class.dart' as macro;
+import 'package:analyzer/src/macro/builders/observable.dart' as macro;
+import 'package:analyzer/src/macro/impl/macro.dart' as macro;
 import 'package:analyzer/src/summary2/combinator.dart';
 import 'package:analyzer/src/summary2/constructor_initializer_resolver.dart';
 import 'package:analyzer/src/summary2/default_value_resolver.dart';
@@ -111,10 +113,7 @@
       }
       elementBuilder.buildDeclarationElements(linkingUnit.node);
     }
-    if ('$uri' == 'dart:core') {
-      localScope.declare('dynamic', reference.getChild('dynamic'));
-      localScope.declare('Never', reference.getChild('Never'));
-    }
+    _declareDartCoreDynamicNever();
   }
 
   void buildEnumChildren() {
@@ -145,6 +144,38 @@
     }
   }
 
+  /// We don't create default constructors during building elements from AST,
+  /// there might be macros that will add one later. So, this method is
+  /// invoked after all macros that affect element models.
+  void processClassConstructors() {
+    // TODO(scheglov) We probably don't need constructors for mixins.
+    var classes = element.topLevelElements
+        .whereType<ClassElementImpl>()
+        .where((e) => !e.isMixinApplication)
+        .toList();
+
+    for (var element in classes) {
+      if (element.constructors.isEmpty) {
+        var containerRef = element.reference!.getChild('@constructor');
+        element.constructors = [
+          ConstructorElementImpl('', -1)
+            ..isSynthetic = true
+            ..reference = containerRef.getChild(''),
+        ];
+      }
+
+      // We have all fields and constructors.
+      // Now we can resolve field formal parameters.
+      for (var constructor in element.constructors) {
+        for (var parameter in constructor.parameters) {
+          if (parameter is FieldFormalParameterElementImpl) {
+            parameter.field = element.getField(parameter.name);
+          }
+        }
+      }
+    }
+  }
+
   void resolveConstructors() {
     ConstructorInitializerResolver(linker, element).resolve();
   }
@@ -162,18 +193,99 @@
 
   void resolveTypes(NodesToBuildType nodesToBuildType) {
     for (var linkingUnit in units) {
-      var resolver = ReferenceResolver(
-        linker,
-        nodesToBuildType,
-        linker.elementFactory,
-        element,
-        linkingUnit.reference,
-        linkingUnit.node.featureSet.isEnabled(Feature.non_nullable),
-      );
+      var resolver = ReferenceResolver(linker, nodesToBuildType, element);
       linkingUnit.node.accept(resolver);
     }
   }
 
+  /// Run built-in declaration macros.
+  void runDeclarationMacros() {
+    bool hasMacroAnnotation(ast.AnnotatedNode node, String name) {
+      for (var annotation in node.metadata) {
+        var nameNode = annotation.name;
+        if (nameNode is ast.SimpleIdentifier &&
+            annotation.arguments == null &&
+            annotation.constructorName == null &&
+            nameNode.name == name) {
+          var nameElement = element.scope.lookup(name).getter;
+          return nameElement != null &&
+              nameElement.library?.name == 'analyzer.macro.annotations';
+        }
+      }
+      return false;
+    }
+
+    /// Build types for type annotations in new [nodes].
+    void resolveTypeAnnotations(
+      List<ast.AstNode> nodes, {
+      ClassElementImpl? classElement,
+    }) {
+      var nodesToBuildType = NodesToBuildType();
+      var resolver = ReferenceResolver(linker, nodesToBuildType, element);
+      if (classElement != null) {
+        resolver.enterScopeClassElement(classElement);
+      }
+      for (var node in nodes) {
+        node.accept(resolver);
+      }
+      TypesBuilder(linker).build(nodesToBuildType);
+    }
+
+    var collector = macro.DeclarationCollector();
+    for (var linkingUnit in units) {
+      for (var declaration in linkingUnit.node.declarations) {
+        if (declaration is ast.ClassDeclarationImpl) {
+          var members = declaration.members.toList();
+          var classBuilder = macro.ClassDeclarationBuilderImpl(
+            collector,
+            declaration,
+          );
+          if (hasMacroAnnotation(declaration, 'autoConstructor')) {
+            macro.AutoConstructorMacro().visitClassDeclaration(
+              declaration,
+              classBuilder,
+            );
+          }
+          if (hasMacroAnnotation(declaration, 'hashCode')) {
+            macro.HashCodeMacro().visitClassDeclaration(
+              declaration,
+              classBuilder,
+            );
+          }
+          if (hasMacroAnnotation(declaration, 'toString')) {
+            macro.ToStringMacro().visitClassDeclaration(
+              declaration,
+              classBuilder,
+            );
+          }
+          for (var member in members) {
+            if (member is ast.FieldDeclarationImpl) {
+              if (hasMacroAnnotation(member, 'observable')) {
+                macro.ObservableMacro().visitFieldDeclaration(
+                  member,
+                  classBuilder,
+                );
+              }
+            }
+          }
+
+          var newMembers = declaration.members.sublist(members.length);
+          if (newMembers.isNotEmpty) {
+            var elementBuilder = ElementBuilder(
+              libraryBuilder: this,
+              unitReference: linkingUnit.reference,
+              unitElement: linkingUnit.element,
+            );
+            var classElement = declaration.declaredElement as ClassElementImpl;
+            elementBuilder.buildMacroClassMembers(classElement, newMembers);
+            resolveTypeAnnotations(newMembers, classElement: classElement);
+          }
+        }
+      }
+    }
+    collector.updateElements();
+  }
+
   void storeExportScope() {
     exports = exportScope.map.values.toList();
     linker.elementFactory.setExportsOfLibrary('$uri', exports);
@@ -195,6 +307,19 @@
     }
   }
 
+  /// These elements are implicitly declared in `dart:core`.
+  void _declareDartCoreDynamicNever() {
+    if (reference.name == 'dart:core') {
+      var dynamicRef = reference.getChild('dynamic');
+      dynamicRef.element = DynamicElementImpl.instance;
+      localScope.declare('dynamic', dynamicRef);
+
+      var neverRef = reference.getChild('Never');
+      neverRef.element = NeverElementImpl.instance;
+      localScope.declare('Never', neverRef);
+    }
+  }
+
   static void build(Linker linker, LinkInputLibrary inputLibrary) {
     var elementFactory = linker.elementFactory;
 
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index f0b0174..7a33308 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -93,6 +93,7 @@
     _createTypeSystem();
     _buildEnumChildren();
     _resolveTypes();
+    _runDeclarationMacros();
     _performTopLevelInference();
     _resolveConstructors();
     _resolveConstantInitializers();
@@ -213,6 +214,13 @@
     TypesBuilder(this).build(nodesToBuildType);
   }
 
+  void _runDeclarationMacros() {
+    for (var library in builders.values) {
+      library.runDeclarationMacros();
+      library.processClassConstructors();
+    }
+  }
+
   void _writeLibraries() {
     var bundleWriter = BundleWriter(
       elementFactory.dynamicRef,
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index a449b97..e83e492 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -27,7 +27,6 @@
   ) {
     ArgumentError.checkNotNull(analysisContext, 'analysisContext');
     ArgumentError.checkNotNull(analysisSession, 'analysisSession');
-    _declareDartCoreDynamicNever();
   }
 
   Reference get dynamicRef {
@@ -182,10 +181,22 @@
   /// that the client can re-add the bundle, this time read from bytes.
   void removeBundle(Set<String> uriStrSet) {
     removeLibraries(uriStrSet);
+  }
 
-    // This is the bundle with dart:core and dart:async, based on full ASTs.
-    // To link them, the linker set the type provider. We are removing these
-    // libraries, and we should also remove the type provider.
+  /// Remove libraries with the specified URIs from the reference tree, and
+  /// any session level caches.
+  void removeLibraries(Set<String> uriStrSet) {
+    for (var uriStr in uriStrSet) {
+      _exportsOfLibrary.remove(uriStr);
+      libraryReaders.remove(uriStr);
+      rootReference.removeChild(uriStr);
+    }
+
+    analysisSession.classHierarchy.removeOfLibraries(uriStrSet);
+    analysisSession.inheritanceManager.removeOfLibraries(uriStrSet);
+
+    // If we discard `dart:core` and `dart:async`, we should also discard
+    // the type provider.
     if (uriStrSet.contains('dart:core')) {
       if (!uriStrSet.contains('dart:async')) {
         throw StateError(
@@ -200,23 +211,9 @@
         );
       }
       analysisContext.clearTypeProvider();
-      _declareDartCoreDynamicNever();
     }
   }
 
-  /// Remove libraries with the specified URIs from the reference tree, and
-  /// any session level caches.
-  void removeLibraries(Set<String> uriStrSet) {
-    for (var uriStr in uriStrSet) {
-      _exportsOfLibrary.remove(uriStr);
-      libraryReaders.remove(uriStr);
-      rootReference.removeChild(uriStr);
-    }
-
-    analysisSession.classHierarchy.removeOfLibraries(uriStrSet);
-    analysisSession.inheritanceManager.removeOfLibraries(uriStrSet);
-  }
-
   /// Set exports of the library with [uriStr], after building exports during
   /// linking, or after reading a linked bundle.
   void setExportsOfLibrary(String uriStr, List<Reference> exports) {
@@ -242,10 +239,4 @@
 
     libraryElement.createLoadLibraryFunction();
   }
-
-  void _declareDartCoreDynamicNever() {
-    var dartCoreRef = rootReference.getChild('dart:core');
-    dartCoreRef.getChild('dynamic').element = DynamicElementImpl.instance;
-    dartCoreRef.getChild('Never').element = NeverElementImpl.instance;
-  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/reference.dart b/pkg/analyzer/lib/src/summary2/reference.dart
index a2cf17b..23c3836 100644
--- a/pkg/analyzer/lib/src/summary2/reference.dart
+++ b/pkg/analyzer/lib/src/summary2/reference.dart
@@ -2,7 +2,6 @@
 // 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/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/summary2/scope.dart';
 
@@ -32,14 +31,6 @@
   /// The simple name of the reference in its [parent].
   final String name;
 
-  /// The node accessor, used to read nodes lazily.
-  /// Or `null` if a named container.
-  ReferenceNodeAccessor? nodeAccessor;
-
-  /// The corresponding [AstNode], or `null` if a named container.
-  /// TODO(scheglov) remove it
-  AstNode? node;
-
   /// The corresponding [Element], or `null` if a named container.
   Element? element;
 
@@ -62,30 +53,14 @@
     return const [];
   }
 
-  bool get isClass => parent != null && parent!.name == '@class';
-
-  bool get isConstructor => parent != null && parent!.name == '@constructor';
-
-  bool get isDynamic => name == 'dynamic' && parent?.name == 'dart:core';
-
-  bool get isEnum => parent != null && parent!.name == '@enum';
-
-  bool get isGetter => parent != null && parent!.name == '@getter';
-
   bool get isLibrary => parent != null && parent!.isRoot;
 
-  bool get isParameter => parent != null && parent!.name == '@parameter';
-
   bool get isPrefix => parent != null && parent!.name == '@prefix';
 
   bool get isRoot => parent == null;
 
   bool get isSetter => parent != null && parent!.name == '@setter';
 
-  bool get isTypeAlias => parent != null && parent!.name == '@typeAlias';
-
-  bool get isUnit => parent != null && parent!.name == '@unit';
-
   /// Return the child with the given name, or `null` if does not exist.
   Reference? operator [](String name) {
     return _children != null ? _children![name] : null;
@@ -97,21 +72,6 @@
     return map[name] ??= Reference._(this, name);
   }
 
-  /// If the reference has element, and it is for the [node], return `true`.
-  ///
-  /// The element might be not `null`, but the node is different in case of
-  /// duplicate declarations.
-  bool hasElementFor(AstNode node) {
-    if (element != null && this.node == node) {
-      return true;
-    } else {
-      if (this.node == null) {
-        this.node = node;
-      }
-      return false;
-    }
-  }
-
   void removeChild(String name) {
     _children!.remove(name);
   }
@@ -119,13 +79,3 @@
   @override
   String toString() => parent == null ? 'root' : '$parent::$name';
 }
-
-abstract class ReferenceNodeAccessor {
-  /// Return the node that corresponds to this [Reference], read it if not yet.
-  AstNode get node;
-
-  /// Fill [Reference.nodeAccessor] for children.
-  ///
-  /// TODO(scheglov) only class reader has a meaningful implementation.
-  void readIndex();
-}
diff --git a/pkg/analyzer/lib/src/summary2/reference_resolver.dart b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
index ea3f216..1cba245 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -14,10 +14,8 @@
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/summary2/function_type_builder.dart';
 import 'package:analyzer/src/summary2/link.dart';
-import 'package:analyzer/src/summary2/linked_element_factory.dart';
 import 'package:analyzer/src/summary2/linking_node_scope.dart';
 import 'package:analyzer/src/summary2/named_type_builder.dart';
-import 'package:analyzer/src/summary2/reference.dart';
 import 'package:analyzer/src/summary2/types_builder.dart';
 
 /// Recursive visitor of [LinkedNode]s that resolves explicit type annotations
@@ -33,8 +31,6 @@
   final Linker linker;
   final TypeSystemImpl _typeSystem;
   final NodesToBuildType nodesToBuildType;
-  final LinkedElementFactory elementFactory;
-  final Reference unitReference;
 
   /// Indicates whether the library is opted into NNBD.
   final bool isNNBD;
@@ -44,12 +40,14 @@
   ReferenceResolver(
     this.linker,
     this.nodesToBuildType,
-    this.elementFactory,
     LibraryElementImpl libraryElement,
-    this.unitReference,
-    this.isNNBD,
   )   : _typeSystem = libraryElement.typeSystem,
-        scope = libraryElement.scope;
+        scope = libraryElement.scope,
+        isNNBD = libraryElement.isNonNullableByDefault;
+
+  void enterScopeClassElement(ClassElementImpl element) {
+    scope = TypeParameterScope(scope, element.typeParameters);
+  }
 
   @override
   void visitBlockFunctionBody(BlockFunctionBody node) {}
@@ -59,9 +57,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as ClassElementImpl;
-    element.accessors; // create elements
-    element.constructors; // create elements
-    element.methods; // create elements
 
     scope = TypeParameterScope(scope, element.typeParameters);
 
@@ -108,7 +103,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as ConstructorElementImpl;
-    element.parameters; // create elements
 
     scope = TypeParameterScope(scope, element.typeParameters);
     LinkingNodeContext(node, scope);
@@ -164,7 +158,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as FieldFormalParameterElementImpl;
-    element.parameters; // create elements
 
     scope = TypeParameterScope(scope, element.typeParameters);
 
@@ -186,7 +179,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as ExecutableElementImpl;
-    element.parameters; // create elements
 
     scope = TypeParameterScope(outerScope, element.typeParameters);
     LinkingNodeContext(node, scope);
@@ -214,9 +206,6 @@
 
     node.returnType?.accept(this);
     node.typeParameters?.accept(this);
-
-    var function = element.aliasedElement as GenericFunctionTypeElementImpl;
-    function.parameters; // create elements
     node.parameters.accept(this);
 
     nodesToBuildType.addDeclaration(node);
@@ -229,7 +218,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as ParameterElementImpl;
-    element.parameters; // create elements
 
     scope = TypeParameterScope(scope, element.typeParameters);
 
@@ -293,7 +281,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as ExecutableElementImpl;
-    element.parameters; // create elements
 
     scope = TypeParameterScope(scope, element.typeParameters);
     LinkingNodeContext(node, scope);
@@ -311,9 +298,6 @@
     var outerScope = scope;
 
     var element = node.declaredElement as MixinElementImpl;
-    element.accessors; // create elements
-    element.constructors; // create elements
-    element.methods; // create elements
 
     scope = TypeParameterScope(scope, element.typeParameters);
 
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index 28b4452..2efaaa1 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -151,6 +151,8 @@
   /// Ways to say `include`.
   static const List<String> includeSynonyms = ['include', 'true'];
 
+  static const String propagateLinterExceptions = 'propagate-linter-exceptions';
+
   /// Ways to say `true` or `false`.
   static const List<String> trueOrFalse = ['true', 'false'];
 
@@ -163,6 +165,7 @@
     language,
     optionalChecks,
     plugins,
+    propagateLinterExceptions,
     strong_mode,
   ];
 
@@ -805,6 +808,9 @@
       if (feature == AnalyzerOptions.implicitDynamic) {
         options.implicitDynamic = boolValue;
       }
+      if (feature == AnalyzerOptions.propagateLinterExceptions) {
+        options.propagateLinterExceptions = boolValue;
+      }
     }
   }
 
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 3aa1807..b20ece0 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -748,6 +748,12 @@
 
   external T operator [](int index);
 }
+
+class FfiNative<T> {
+  final String nativeName;
+  final bool isLeaf;
+  const FfiNative(this.nativeName, {this.isLeaf: false});
+}
 ''',
   )
 ]);
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;
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index d52b622..4afb0cc 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 2.0.0
+version: 2.1.0-dev
 description: This package provides a library that performs static analysis of Dart code.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
 
diff --git a/pkg/analyzer/test/error/error_reporter_test.dart b/pkg/analyzer/test/error/error_reporter_test.dart
index dba624a..7b32e98 100644
--- a/pkg/analyzer/test/error/error_reporter_test.dart
+++ b/pkg/analyzer/test/error/error_reporter_test.dart
@@ -166,7 +166,7 @@
     var fa = findNode.topLevelVariableDeclaration('fa');
     var fb = findNode.topLevelVariableDeclaration('fb');
 
-    var source = result.unit!.declaredElement!.source;
+    var source = result.unit.declaredElement!.source;
     var reporter = ErrorReporter(
       listener,
       source,
@@ -201,7 +201,7 @@
     var ba = findNode.topLevelVariableDeclaration('ba');
     var bb = findNode.topLevelVariableDeclaration('bb');
 
-    var source = result.unit!.declaredElement!.source;
+    var source = result.unit.declaredElement!.source;
     var reporter = ErrorReporter(
       listener,
       source,
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index f4a4079..f97d66a 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -497,7 +497,7 @@
 
     var expression = findNode.variableDeclaration('x =').initializer!;
 
-    var file = getFile(result.path!);
+    var file = getFile(result.path);
     var evaluator = ConstantEvaluator(
       file.createSource(result.uri),
       result.libraryElement as LibraryElementImpl,
diff --git a/pkg/analyzer/test/generated/function_reference_parser_test.dart b/pkg/analyzer/test/generated/function_reference_parser_test.dart
index 13d0d82..c7cc214 100644
--- a/pkg/analyzer/test/generated/function_reference_parser_test.dart
+++ b/pkg/analyzer/test/generated/function_reference_parser_test.dart
@@ -300,6 +300,59 @@
             as MethodInvocation);
   }
 
+  void test_functionReference_after_indexExpression() {
+    // Note: this is not legal Dart, but it's important that we do error
+    // recovery and don't crash the parser.
+    var functionReference =
+        parseExpression('x[0]<a, b>', featureSet: constructorTearoffs)
+            as FunctionReference;
+    expect(functionReference.function, TypeMatcher<IndexExpression>());
+    var typeArgs = functionReference.typeArguments!.arguments;
+    expect(typeArgs, hasLength(2));
+    expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+    expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+  }
+
+  void test_functionReference_after_indexExpression_bang() {
+    // Note: this is not legal Dart, but it's important that we do error
+    // recovery and don't crash the parser.
+    var functionReference =
+        parseExpression('x[0]!<a, b>', featureSet: constructorTearoffs)
+            as FunctionReference;
+    expect(functionReference.function, TypeMatcher<PostfixExpression>());
+    var typeArgs = functionReference.typeArguments!.arguments;
+    expect(typeArgs, hasLength(2));
+    expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+    expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+  }
+
+  void test_functionReference_after_indexExpression_functionCall() {
+    // Note: this is not legal Dart, but it's important that we do error
+    // recovery and don't crash the parser.
+    var functionReference =
+        parseExpression('x[0]()<a, b>', featureSet: constructorTearoffs)
+            as FunctionReference;
+    expect(functionReference.function,
+        TypeMatcher<FunctionExpressionInvocation>());
+    var typeArgs = functionReference.typeArguments!.arguments;
+    expect(typeArgs, hasLength(2));
+    expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+    expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+  }
+
+  void test_functionReference_after_indexExpression_nullAware() {
+    // Note: this is not legal Dart, but it's important that we do error
+    // recovery and don't crash the parser.
+    var functionReference =
+        parseExpression('x?[0]<a, b>', featureSet: constructorTearoffs)
+            as FunctionReference;
+    expect(functionReference.function, TypeMatcher<IndexExpression>());
+    var typeArgs = functionReference.typeArguments!.arguments;
+    expect(typeArgs, hasLength(2));
+    expect(((typeArgs[0] as TypeName).name as SimpleIdentifier).name, 'a');
+    expect(((typeArgs[1] as TypeName).name as SimpleIdentifier).name, 'b');
+  }
+