Version 2.18.0-227.0.dev

Merge commit '0c72795f692faa01e148126761d9524d19da9bb3' into 'dev'
diff --git a/pkg/analysis_server/lib/src/cider/completion.dart b/pkg/analysis_server/lib/src/cider/completion.dart
index 86e6d59..e9a515d 100644
--- a/pkg/analysis_server/lib/src/cider/completion.dart
+++ b/pkg/analysis_server/lib/src/cider/completion.dart
@@ -7,9 +7,9 @@
 import 'package:analysis_server/src/services/completion/dart/fuzzy_filter_sort.dart';
 import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
 import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
-import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/element/element.dart' show LibraryElement;
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
+import 'package:analyzer/src/dart/analysis/results.dart';
 import 'package:analyzer/src/dart/micro/resolve_file.dart';
 import 'package:analyzer/src/util/performance/operation_performance.dart';
 import 'package:meta/meta.dart';
@@ -51,13 +51,14 @@
     required String path,
     required int line,
     required int column,
-    @visibleForTesting void Function(ResolvedUnitResult)? testResolvedUnit,
+    @visibleForTesting
+        void Function(ResolvedForCompletionResultImpl)? testResolvedUnit,
   }) async {
     return _performanceRoot.runAsync('completion', (performance) async {
-      var resolvedUnit = await performance.runAsync(
+      final resolvedUnit = await performance.runAsync(
         'resolution',
         (performance) async {
-          return _fileResolver.resolve2(
+          return _fileResolver.resolveForCompletion(
             completionLine: line,
             completionColumn: column,
             path: path,
@@ -70,12 +71,21 @@
         testResolvedUnit(resolvedUnit);
       }
 
+      final analysisSession = resolvedUnit.analysisSession;
+      final enclosingNode = resolvedUnit.parsedUnit;
+
       var lineInfo = resolvedUnit.lineInfo;
       var offset = lineInfo.getOffsetOfLine(line) + column;
 
-      _dartCompletionRequest = DartCompletionRequest.forResolvedUnit(
-        resolvedUnit: resolvedUnit,
+      _dartCompletionRequest = DartCompletionRequest(
+        analysisSession: analysisSession,
+        filePath: resolvedUnit.path,
+        fileContent: resolvedUnit.content,
+        unitElement: resolvedUnit.unitElement,
+        enclosingNode: enclosingNode,
         offset: offset,
+        dartdocDirectiveInfo: null,
+        documentationCache: null,
       );
 
       var suggestions = await performance.runAsync(
diff --git a/pkg/analysis_server/test/src/cider/completion_test.dart b/pkg/analysis_server/test/src/cider/completion_test.dart
index 2fd1095..c43ddad 100644
--- a/pkg/analysis_server/test/src/cider/completion_test.dart
+++ b/pkg/analysis_server/test/src/cider/completion_test.dart
@@ -3,8 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/cider/completion.dart';
-import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer/src/dart/analysis/results.dart';
 import 'package:analyzer/src/test_utilities/function_ast_visitor.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     show CompletionSuggestion, CompletionSuggestionKind, ElementKind;
@@ -24,7 +24,7 @@
   final CiderCompletionCache _completionCache = CiderCompletionCache();
 
   late CiderCompletionComputer _computer;
-  void Function(ResolvedUnitResult)? _testResolvedUnit;
+  void Function(ResolvedForCompletionResultImpl)? _testResolvedUnit;
 
   late CiderCompletionResult _completionResult;
   late List<CompletionSuggestion> _suggestions;
@@ -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.parsedUnit;
       unit.accept(
         FunctionAstVisitor(
           simpleIdentifier: (node) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
index ade3b53..af049b8 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
@@ -378,10 +378,12 @@
     Workspace? workspace;
     workspace = BazelWorkspace.find(resourceProvider, rootPath,
         lookForBuildFileSubstitutes: false);
-    workspace ??= GnWorkspace.find(resourceProvider, rootPath);
-    workspace ??=
-        PackageBuildWorkspace.find(resourceProvider, packages, rootPath);
-    workspace ??= PubWorkspace.find(resourceProvider, packages, rootPath);
+    workspace = _mostSpecificWorkspace(
+        workspace, GnWorkspace.find(resourceProvider, rootPath));
+    workspace = _mostSpecificWorkspace(workspace,
+        PackageBuildWorkspace.find(resourceProvider, packages, rootPath));
+    workspace = _mostSpecificWorkspace(
+        workspace, PubWorkspace.find(resourceProvider, packages, rootPath));
     workspace ??= BasicWorkspace.find(resourceProvider, packages, rootPath);
     return workspace;
   }
@@ -555,6 +557,20 @@
 
     return true;
   }
+
+  /// Pick a workspace with the most specific root. If the root of [first] is
+  /// non-null and is within the root of [second], return [second]. If any of
+  /// [first] and [second] is null, return the other one. If the roots aren't
+  /// within each other, return [first].
+  static Workspace? _mostSpecificWorkspace(
+      Workspace? first, Workspace? second) {
+    if (first == null) return second;
+    if (second == null) return first;
+    if (isWithin(first.root, second.root)) {
+      return second;
+    }
+    return first;
+  }
 }
 
 /// The packages [file] found for the [parent].
diff --git a/pkg/analyzer/lib/src/dart/analysis/results.dart b/pkg/analyzer/lib/src/dart/analysis/results.dart
index 81dcce5..223e40d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/results.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/results.dart
@@ -177,6 +177,8 @@
     required this.unitElement,
     required this.resolvedNodes,
   });
+
+  LibraryElement get libraryElement => unitElement.enclosingElement;
 }
 
 class ResolvedLibraryResultImpl extends AnalysisResultImpl
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index a2bca9a..2303065 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -5730,6 +5730,22 @@
     return super.name!;
   }
 
+  /// Instantiates this type alias with its type parameters as arguments.
+  DartType get rawType {
+    final List<DartType> typeArguments;
+    if (typeParameters.isNotEmpty) {
+      typeArguments = typeParameters.map<DartType>((t) {
+        return t.instantiate(nullabilitySuffix: _noneOrStarSuffix);
+      }).toList();
+    } else {
+      typeArguments = const <DartType>[];
+    }
+    return instantiate(
+      typeArguments: typeArguments,
+      nullabilitySuffix: _noneOrStarSuffix,
+    );
+  }
+
   @override
   List<TypeParameterElement> get typeParameters {
     linkedData?.read(this);
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index 5208c75..9fc03c6 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -321,7 +321,11 @@
     if (mixinElement.isMixin) {
       candidates = mixinElement.superclassConstraints;
     } else {
-      candidates = [mixinElement.supertype!];
+      final supertype = mixinElement.supertype;
+      if (supertype == null) {
+        return const [];
+      }
+      candidates = [supertype];
       candidates.addAll(mixinElement.mixins);
       if (mixinElement.isMixinApplication) {
         candidates.removeLast();
@@ -1220,16 +1224,15 @@
     return (type as TypeImpl).withNullability(NullabilitySuffix.question);
   }
 
-  /// Attempts to find the appropriate substitution for the [mixinElement]
-  /// type parameters that can be applied to [srcTypes] to make it equal to
-  /// [destTypes].  If no such substitution can be found, `null` is returned.
+  /// Attempts to find the appropriate substitution for the [typeParameters]
+  /// that can be applied to [srcTypes] to make it equal to [destTypes].
+  /// If no such substitution can be found, `null` is returned.
   List<DartType>? matchSupertypeConstraints(
-    ClassElement mixinElement,
+    List<TypeParameterElement> typeParameters,
     List<DartType> srcTypes,
     List<DartType> destTypes, {
     required bool genericMetadataIsEnabled,
   }) {
-    var typeParameters = mixinElement.typeParameters;
     var inferrer = GenericInferrer(this, typeParameters,
         genericMetadataIsEnabled: genericMetadataIsEnabled);
     for (int i = 0; i < srcTypes.length; i++) {
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index cb41ad2..8283d1d 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -19,12 +19,12 @@
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/dart/analysis/feature_set_provider.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
+import 'package:analyzer/src/dart/analysis/library_analyzer.dart';
 import 'package:analyzer/src/dart/analysis/library_context.dart';
 import 'package:analyzer/src/dart/analysis/performance_logger.dart';
 import 'package:analyzer/src/dart/analysis/results.dart';
 import 'package:analyzer/src/dart/analysis/search.dart';
 import 'package:analyzer/src/dart/micro/analysis_context.dart';
-import 'package:analyzer/src/dart/micro/library_analyzer.dart';
 import 'package:analyzer/src/dart/micro/utils.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/source.dart';
@@ -511,10 +511,7 @@
     releaseAndClearRemovedIds();
   }
 
-  /// The [completionLine] and [completionColumn] are zero based.
   Future<ResolvedUnitResult> resolve2({
-    int? completionLine,
-    int? completionColumn,
     required String path,
     OperationPerformanceImpl? performance,
   }) async {
@@ -529,23 +526,11 @@
       );
       var file = fileContext.file;
 
-      // // If we have a `part of` directive, we want to analyze this library.
-      // // But the library must include the file, so have its element.
-      // var libraryFile = file;
-      // var partOfLibrary = file.partOfLibrary;
-      // if (partOfLibrary != null) {
-      //   if (partOfLibrary.files().ofLibrary.contains(file)) {
-      //     libraryFile = partOfLibrary;
-      //   }
-      // }
       final libraryKind = file.kind.library ?? file.kind.asLibrary;
       final libraryFile = libraryKind.file;
 
       var libraryResult = await resolveLibrary2(
-        completionLine: completionLine,
-        completionColumn: completionColumn,
         path: libraryFile.path,
-        completionPath: completionLine != null ? path : null,
         performance: performance,
       );
       return libraryResult.units.firstWhere(
@@ -555,10 +540,74 @@
   }
 
   /// The [completionLine] and [completionColumn] are zero based.
+  Future<ResolvedForCompletionResultImpl> resolveForCompletion({
+    required int completionLine,
+    required int completionColumn,
+    required String path,
+    OperationPerformanceImpl? performance,
+  }) async {
+    _throwIfNotAbsoluteNormalizedPath(path);
+
+    performance ??= OperationPerformanceImpl('<default>');
+
+    return logger.runAsync('Resolve $path', () async {
+      final fileContext = getFileContext(
+        path: path,
+        performance: performance!,
+      );
+      final file = fileContext.file;
+      final libraryKind = file.kind.library ?? file.kind.asLibrary;
+
+      final lineOffset = file.lineInfo.getOffsetOfLine(completionLine);
+      final completionOffset = lineOffset + completionColumn;
+
+      await performance.runAsync('libraryContext', (performance) async {
+        await libraryContext!.load(
+          targetLibrary: libraryKind,
+          performance: performance,
+        );
+      });
+
+      final unitElement = libraryContext!.computeUnitElement(libraryKind, file);
+
+      return logger.run('Compute analysis results', () {
+        final elementFactory = libraryContext!.elementFactory;
+        final analysisSession = elementFactory.analysisSession;
+
+        var libraryAnalyzer = LibraryAnalyzer(
+          fileContext.analysisOptions,
+          contextObjects!.declaredVariables,
+          sourceFactory,
+          elementFactory.libraryOfUri2(libraryKind.file.uri),
+          analysisSession.inheritanceManager,
+          libraryKind,
+        );
+
+        final analysisResult = performance!.run('analyze', (performance) {
+          return libraryAnalyzer.analyzeForCompletion(
+            file: file,
+            offset: completionOffset,
+            unitElement: unitElement,
+            performance: performance,
+          );
+        });
+
+        return ResolvedForCompletionResultImpl(
+          analysisSession: analysisSession,
+          path: path,
+          uri: file.uri,
+          exists: file.exists,
+          content: file.content,
+          lineInfo: file.lineInfo,
+          parsedUnit: analysisResult.parsedUnit,
+          unitElement: unitElement,
+          resolvedNodes: analysisResult.resolvedNodes,
+        );
+      });
+    });
+  }
+
   Future<ResolvedLibraryResult> resolveLibrary2({
-    int? completionLine,
-    int? completionColumn,
-    String? completionPath,
     required String path,
     OperationPerformanceImpl? performance,
   }) async {
@@ -577,24 +626,7 @@
         performance: performance!,
       );
       var file = fileContext.file;
-
-      // // If we have a `part of` directive, we want to analyze this library.
-      // // But the library must include the file, so have its element.
-      // var libraryFile = file;
-      // var partOfLibrary = file.partOfLibrary;
-      // if (partOfLibrary != null) {
-      //   if (partOfLibrary.files().ofLibrary.contains(file)) {
-      //     libraryFile = partOfLibrary;
-      //   }
-      // }
       final libraryKind = file.kind.library ?? file.kind.asLibrary;
-      final libraryFile = libraryKind.file;
-
-      int? completionOffset;
-      if (completionLine != null && completionColumn != null) {
-        var lineOffset = file.lineInfo.getOffsetOfLine(completionLine);
-        completionOffset = lineOffset + completionColumn;
-      }
 
       await performance.runAsync('libraryContext', (performance) async {
         await libraryContext!.load(
@@ -605,31 +637,24 @@
 
       testData?.addResolvedLibrary(path);
 
-      late Map<FileState, UnitAnalysisResult> results;
+      late List<UnitAnalysisResult> results;
 
       logger.run('Compute analysis results', () {
         var libraryAnalyzer = LibraryAnalyzer(
           fileContext.analysisOptions,
           contextObjects!.declaredVariables,
           sourceFactory,
-          (_) => true, // _isLibraryUri
-          libraryContext!.analysisContext,
-          libraryContext!.elementFactory,
-          contextObjects!.inheritanceManager,
-          libraryFile,
-          (file) => file.getContent(),
+          libraryContext!.elementFactory.libraryOfUri2(libraryKind.file.uri),
+          libraryContext!.elementFactory.analysisSession.inheritanceManager,
+          libraryKind,
         );
 
         results = performance!.run('analyze', (performance) {
-          return libraryAnalyzer.analyze(
-            completionPath: completionOffset != null ? completionPath : null,
-            completionOffset: completionOffset,
-            performance: performance,
-          );
+          return libraryAnalyzer.analyze();
         });
       });
 
-      var resolvedUnits = results.values.map((fileResult) {
+      var resolvedUnits = results.map((fileResult) {
         var file = fileResult.file;
         return ResolvedUnitResultImpl(
           contextObjects!.analysisSession,
@@ -648,9 +673,7 @@
       var result = ResolvedLibraryResultImpl(contextObjects!.analysisSession,
           libraryUnit.libraryElement, resolvedUnits);
 
-      if (completionPath == null) {
-        cachedResults[path] = result;
-      }
+      cachedResults[path] = result;
 
       return result;
     });
diff --git a/pkg/analyzer/lib/src/summary2/types_builder.dart b/pkg/analyzer/lib/src/summary2/types_builder.dart
index 1fd8625..64d6087 100644
--- a/pkg/analyzer/lib/src/summary2/types_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/types_builder.dart
@@ -383,14 +383,6 @@
     interfacesMerger.addWithSupertypes(element.supertype);
   }
 
-  NullabilitySuffix get _noneOrStarSuffix {
-    return _nonNullableEnabled
-        ? NullabilitySuffix.none
-        : NullabilitySuffix.star;
-  }
-
-  bool get _nonNullableEnabled => featureSet.isEnabled(Feature.non_nullable);
-
   void perform(WithClause? withClause) {
     if (withClause == null) return;
 
@@ -438,19 +430,46 @@
       return mixinType;
     }
 
-    var mixinElement = mixinType.element;
-    if (mixinElement.typeParameters.isEmpty) {
-      return mixinType;
+    List<TypeParameterElement>? typeParameters;
+    List<InterfaceType>? supertypeConstraints;
+    InterfaceType Function(List<DartType> typeArguments)? instantiate;
+    final mixinElement = mixinNode.name.staticElement;
+    if (mixinElement is ClassElement) {
+      typeParameters = mixinElement.typeParameters;
+      if (typeParameters.isNotEmpty) {
+        supertypeConstraints = typeSystem
+            .gatherMixinSupertypeConstraintsForInference(mixinElement);
+        instantiate = (typeArguments) {
+          return mixinElement.instantiate(
+            typeArguments: typeArguments,
+            nullabilitySuffix: mixinType.nullabilitySuffix,
+          );
+        };
+      }
+    } else if (mixinElement is TypeAliasElementImpl) {
+      typeParameters = mixinElement.typeParameters;
+      if (typeParameters.isNotEmpty) {
+        final rawType = mixinElement.rawType;
+        if (rawType is InterfaceType) {
+          supertypeConstraints = rawType.superclassConstraints;
+          instantiate = (typeArguments) {
+            return mixinElement.instantiate(
+              typeArguments: typeArguments,
+              nullabilitySuffix: mixinType.nullabilitySuffix,
+            ) as InterfaceType;
+          };
+        }
+      }
     }
 
-    var mixinSupertypeConstraints =
-        typeSystem.gatherMixinSupertypeConstraintsForInference(mixinElement);
-    if (mixinSupertypeConstraints.isEmpty) {
+    if (typeParameters == null ||
+        supertypeConstraints == null ||
+        instantiate == null) {
       return mixinType;
     }
 
     var matchingInterfaceTypes = _findInterfaceTypesForConstraints(
-      mixinSupertypeConstraints,
+      supertypeConstraints,
       interfacesMerger.typeList,
     );
 
@@ -468,22 +487,18 @@
     // mixinSupertypeConstraints to find the correct set of type
     // parameters to apply to the mixin.
     var inferredTypeArguments = typeSystem.matchSupertypeConstraints(
-      mixinElement,
-      mixinSupertypeConstraints,
+      typeParameters,
+      supertypeConstraints,
       matchingInterfaceTypes,
-      genericMetadataIsEnabled:
-          mixinElement.library.featureSet.isEnabled(Feature.generic_metadata),
+      genericMetadataIsEnabled: featureSet.isEnabled(Feature.generic_metadata),
     );
-    if (inferredTypeArguments != null) {
-      var inferredMixin = mixinElement.instantiate(
-        typeArguments: inferredTypeArguments,
-        nullabilitySuffix: _noneOrStarSuffix,
-      );
-      mixinType = inferredMixin;
-      mixinNode.type = inferredMixin;
+    if (inferredTypeArguments == null) {
+      return mixinType;
     }
 
-    return mixinType;
+    final inferredType = instantiate(inferredTypeArguments);
+    mixinNode.type = inferredType;
+    return inferredType;
   }
 
   InterfaceType _interfaceType(DartType type) {
diff --git a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
index 9f757d0..70b8c34 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
@@ -290,6 +290,35 @@
     expect(outerRoot.packagesFile, outerPackagesFile);
   }
 
+  void
+      test_locateRoots_multiple_dirAndNestedDir_outerIsBazel_innerConfigurationFiles() {
+    var outerRootFolder = newFolder('/outer');
+    newFile('$outerRootFolder/WORKSPACE', '');
+    newBazelBuildFile('$outerRootFolder', '');
+    var innerRootFolder = newFolder('/outer/examples/inner');
+    var innerOptionsFile = newAnalysisOptionsYamlFile('$innerRootFolder', '');
+    var innerPackagesFile = newPackageConfigJsonFile('$innerRootFolder', '');
+    newPubspecYamlFile('$innerRootFolder', '');
+
+    var roots = contextLocator.locateRoots(
+      includedPaths: [outerRootFolder.path, innerRootFolder.path],
+    );
+    expect(roots, hasLength(2));
+
+    var outerRoot = findRoot(roots, outerRootFolder);
+    expect(outerRoot.includedPaths, unorderedEquals([outerRootFolder.path]));
+    expect(outerRoot.excludedPaths, unorderedEquals([innerRootFolder.path]));
+    expect(outerRoot.optionsFile, isNull);
+    expect(outerRoot.packagesFile, isNull);
+
+    var innerRoot = findRoot(roots, innerRootFolder);
+    expect(innerRoot.workspace.root, equals(innerRootFolder.path));
+    expect(innerRoot.includedPaths, unorderedEquals([innerRootFolder.path]));
+    expect(innerRoot.excludedPaths, isEmpty);
+    expect(innerRoot.optionsFile, innerOptionsFile);
+    expect(innerRoot.packagesFile, innerPackagesFile);
+  }
+
   void test_locateRoots_multiple_dirAndNestedFile_excludedByOptions() {
     var rootPath = convertPath('/home/test');
     var rootFolder = newFolder(rootPath);
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index b284a45..8b247dd 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -3322,32 +3322,6 @@
     expect(result, isNot(same(result1)));
   }
 
-  test_resolveFile_dontCache_whenForCompletion() async {
-    final a = newFile('/workspace/dart/test/lib/a.dart', r'''
-part 'b.dart';
-''');
-
-    final b = newFile('/workspace/dart/test/lib/b.dart', r'''
-part of 'a.dart';
-''');
-
-    // No resolved files yet.
-    _assertResolvedFiles([]);
-
-    await fileResolver.resolve2(
-      path: b.path,
-      completionLine: 0,
-      completionColumn: 0,
-    );
-
-    // The library was resolved.
-    _assertResolvedFiles([a]);
-
-    // The completion location was set, so not units are resolved.
-    // So, the result should not be cached.
-    expect(fileResolver.cachedResults, isEmpty);
-  }
-
   test_resolveLibrary() async {
     var aPath = convertPath('/workspace/dart/test/lib/a.dart');
     newFile(aPath, r'''
diff --git a/pkg/analyzer/test/src/summary/elements_test.dart b/pkg/analyzer/test/src/summary/elements_test.dart
index 7101cab..dc9ab8f 100644
--- a/pkg/analyzer/test/src/summary/elements_test.dart
+++ b/pkg/analyzer/test/src/summary/elements_test.dart
@@ -31080,6 +31080,116 @@
 ''');
   }
 
+  test_mixin_inference_viaTypeAlias() async {
+    var library = await buildLibrary(r'''
+mixin M<T, U> on S<T> {}
+
+typedef M2<T2> = M<T2, int>;
+
+class S<T3> {}
+
+class X extends S<String> with M2 {}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    classes
+      class S @62
+        typeParameters
+          covariant T3 @64
+            defaultType: dynamic
+        constructors
+          synthetic @-1
+      class X @78
+        supertype: S<String>
+        mixins
+          M<String, int>
+            alias: self::@typeAlias::M2
+              typeArguments
+                String
+        constructors
+          synthetic @-1
+            superConstructor: ConstructorMember
+              base: self::@class::S::@constructor::•
+              substitution: {T3: String}
+    mixins
+      mixin M @6
+        typeParameters
+          covariant T @8
+            defaultType: dynamic
+          covariant U @11
+            defaultType: dynamic
+        superclassConstraints
+          S<T>
+    typeAliases
+      M2 @34
+        typeParameters
+          covariant T2 @37
+            defaultType: dynamic
+        aliasedType: M<T2, int>
+''');
+  }
+
+  test_mixin_inference_viaTypeAlias2() async {
+    var library = await buildLibrary(r'''
+mixin M<T, U> on S<T> {}
+
+typedef M2<T2> = M<T2, int>;
+
+typedef M3<T3> = M2<T3>;
+
+class S<T4> {}
+
+class X extends S<String> with M3 {}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    classes
+      class S @88
+        typeParameters
+          covariant T4 @90
+            defaultType: dynamic
+        constructors
+          synthetic @-1
+      class X @104
+        supertype: S<String>
+        mixins
+          M<String, int>
+            alias: self::@typeAlias::M3
+              typeArguments
+                String
+        constructors
+          synthetic @-1
+            superConstructor: ConstructorMember
+              base: self::@class::S::@constructor::•
+              substitution: {T4: String}
+    mixins
+      mixin M @6
+        typeParameters
+          covariant T @8
+            defaultType: dynamic
+          covariant U @11
+            defaultType: dynamic
+        superclassConstraints
+          S<T>
+    typeAliases
+      M2 @34
+        typeParameters
+          covariant T2 @37
+            defaultType: dynamic
+        aliasedType: M<T2, int>
+      M3 @64
+        typeParameters
+          covariant T3 @67
+            defaultType: dynamic
+        aliasedType: M<T3, int>
+          alias: self::@typeAlias::M2
+            typeArguments
+              T3
+''');
+  }
+
   test_mixin_method_invokesSuperSelf() async {
     var library = await buildLibrary(r'''
 mixin M on A {
diff --git a/pkg/test_runner/lib/bot_results.dart b/pkg/test_runner/lib/bot_results.dart
index 1bad14e..6b0a850 100644
--- a/pkg/test_runner/lib/bot_results.dart
+++ b/pkg/test_runner/lib/bot_results.dart
@@ -24,35 +24,37 @@
   final bool matches;
   final String name;
   final String outcome;
-  final bool changed;
-  final String commitHash;
+  final bool? changed;
+  final String? commitHash;
   final bool flaked; // From optional flakiness_data argument to constructor.
-  final bool isFlaky; // From results.json after it is extended.
-  final String previousOutcome;
+  final bool? isFlaky; // From results.json after it is extended.
+  final String? previousOutcome;
 
   Result(
-      this.configuration,
-      this.name,
-      this.outcome,
-      this.expectation,
-      this.matches,
-      this.changed,
-      this.commitHash,
-      this.isFlaky,
-      this.previousOutcome,
-      [this.flaked = false]);
+    this.configuration,
+    this.name,
+    this.outcome,
+    this.expectation,
+    this.matches,
+    this.changed,
+    this.commitHash,
+    this.isFlaky,
+    this.previousOutcome, {
+    this.flaked = false,
+  });
 
-  Result.fromMap(Map<String, dynamic> map,
-      [Map<String, dynamic>? flakinessData])
-      : configuration = map["configuration"] as String,
+  Result.fromMap(
+    Map<String, dynamic> map, [
+    Map<String, dynamic>? flakinessData,
+  ])  : configuration = map["configuration"] as String,
         name = map["name"] as String,
         outcome = map["result"] as String,
         expectation = map["expected"] as String,
         matches = map["matches"] as bool,
-        changed = map["changed"] as bool,
-        commitHash = map["commit_hash"] as String,
-        isFlaky = map["flaky"] as bool,
-        previousOutcome = map["previous_result"] as String,
+        changed = map["changed"] as bool?,
+        commitHash = map["commit_hash"] as String?,
+        isFlaky = map["flaky"] as bool?,
+        previousOutcome = map["previous_result"] as String?,
         flaked = flakinessData != null &&
             (flakinessData["active"] ?? true) == true &&
             (flakinessData["outcomes"] as List).contains(map["result"]);
diff --git a/pkg/test_runner/test/compare_results/compare_results_test.dart b/pkg/test_runner/test/compare_results/compare_results_test.dart
index 2a8b174..c655ddf 100644
--- a/pkg/test_runner/test/compare_results/compare_results_test.dart
+++ b/pkg/test_runner/test/compare_results/compare_results_test.dart
@@ -198,6 +198,16 @@
     bool flaked = false,
     bool isFlaky = false,
     String previousOutcome = 'Pass'}) {
-  return Result(configuration, name, outcome, expectation, matches, changed,
-      commitHash, isFlaky, previousOutcome, flaked);
+  return Result(
+    configuration,
+    name,
+    outcome,
+    expectation,
+    matches,
+    changed,
+    commitHash,
+    isFlaky,
+    previousOutcome,
+    flaked: flaked,
+  );
 }
diff --git a/tools/VERSION b/tools/VERSION
index 67be777..234f0fe 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 226
+PRERELEASE 227
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/compare_results.dart b/tools/bots/compare_results.dart
index 1e2bad3..5ca9f1f 100755
--- a/tools/bots/compare_results.dart
+++ b/tools/bots/compare_results.dart
@@ -7,8 +7,6 @@
 // The output contains additional details in the verbose mode. There is a human
 // readable mode that explains the results and how they changed.
 
-// @dart = 2.9
-
 import '../../pkg/test_runner/bin/compare_results.dart' as compare_results;
 
 main(List<String> args) {
diff --git a/tools/bots/extend_results.dart b/tools/bots/extend_results.dart
index 6b03623..98fcec8 100644
--- a/tools/bots/extend_results.dart
+++ b/tools/bots/extend_results.dart
@@ -5,8 +5,6 @@
 // Add fields with data about the test run and the commit tested, and
 // with the result on the last build tested, to the test results file.
 
-// @dart = 2.9
-
 import 'dart:convert';
 import 'dart:io';
 
@@ -38,10 +36,10 @@
     }
   });
   for (final String key in results.keys) {
-    final Map<String, dynamic> result = results[key];
-    final Map<String, dynamic> priorResult = priorResults[key];
-    final Map<String, dynamic> flaky = flakes[key];
-    final Map<String, dynamic> priorFlaky = priorFlakes[key];
+    final Map<String, dynamic> result = results[key]!;
+    final Map<String, dynamic>? priorResult = priorResults[key];
+    final Map<String, dynamic>? flaky = flakes[key];
+    final Map<String, dynamic>? priorFlaky = priorFlakes[key];
     result['commit_hash'] = commitHash;
     result['commit_time'] = commitTime;
     result['build_number'] = buildNumber;
diff --git a/tools/bots/update_blamelists.dart b/tools/bots/update_blamelists.dart
index 0776afc..7956090 100644
--- a/tools/bots/update_blamelists.dart
+++ b/tools/bots/update_blamelists.dart
@@ -6,8 +6,6 @@
 // of active, non-approved failures which include the commit of the current
 // bisection build.
 
-// @dart = 2.9
-
 import 'dart:io';
 
 import 'package:args/args.dart';
@@ -20,7 +18,7 @@
 
 const maxAttempts = 20;
 
-FirestoreDatabase database;
+late FirestoreDatabase database;
 
 class ResultRecord {
   final Map data;
@@ -77,7 +75,7 @@
 
 /// Compute if the record should be updated based on the outcomes in the
 /// result record and the new test result.
-bool shouldUpdateRecord(ResultRecord resultRecord, Result testResult) {
+bool shouldUpdateRecord(ResultRecord resultRecord, Result? testResult) {
   if (testResult == null || !testResult.matches) {
     return false;
   }
@@ -97,8 +95,8 @@
   return true;
 }
 
-void updateBlameLists(
-    String configuration, String commit, Map<String, Map> testResults) async {
+void updateBlameLists(String configuration, String commit,
+    Map<String, Map<String, dynamic>> testResults) async {
   int commitIndex = await getCommitIndex(commit);
   var query = unapprovedActiveFailuresQuery(configuration);
   bool needsRetry;
@@ -127,7 +125,7 @@
       print('Found result record: $configuration:${result.name}: '
           '${result.previousResult} -> ${result.result} '
           'in ${result.blamelistStartIndex}..${result.blamelistEndIndex} '
-          'to update with ${testResult.outcome} at $commitIndex.');
+          'to update with ${testResult?.outcome} at $commitIndex.');
       // We found a result representation for this test and configuration whose
       // blamelist includes this results' commit but whose outcome is different
       // then the outcome in the provided test results.
@@ -176,7 +174,7 @@
   }
   // Pick an arbitrary result entry to find configuration and commit hash.
   var firstResult = Result.fromMap(results.values.first);
-  var commit = firstResult.commitHash;
+  var commit = firstResult.commitHash!;
   var configuration = firstResult.configuration;
   var project = options['staging'] ? 'dart-ci-staging' : 'dart-ci';
   database = FirestoreDatabase(
diff --git a/tools/bots/update_flakiness.dart b/tools/bots/update_flakiness.dart
index 92667a5..a112fed 100755
--- a/tools/bots/update_flakiness.dart
+++ b/tools/bots/update_flakiness.dart
@@ -5,8 +5,6 @@
 
 // Update the flakiness data with a set of fresh results.
 
-// @dart = 2.9
-
 import 'dart:convert';
 import 'dart:io';
 
@@ -43,7 +41,7 @@
 
   final resultsForInactiveFlakiness = {
     for (final flakyTest in data.keys)
-      if (data[flakyTest]['active'] == false) flakyTest: <String>{}
+      if (data[flakyTest]!['active'] == false) flakyTest: <String>{}
   };
   // Incrementally update the flakiness data with each observed result.
   for (final path in parameters) {
@@ -99,11 +97,11 @@
       options['output'] != null ? File(options['output']).openWrite() : stdout;
   final keys = data.keys.toList()..sort();
   for (final key in keys) {
-    final testData = data[key];
+    final testData = data[key]!;
     if (testData['outcomes'].length < 2) continue;
     // Reactivate inactive flaky results that are flaky again.
     if (testData['active'] == false) {
-      if (resultsForInactiveFlakiness[key].length > 1) {
+      if (resultsForInactiveFlakiness[key]!.length > 1) {
         testData['active'] = true;
         testData['reactivation_count'] =
             (testData['reactivation_count'] ?? 0) + 1;
diff --git a/tools/generate_experimental_flags.dart b/tools/generate_experimental_flags.dart
index 3ae2858..f096ae9 100644
--- a/tools/generate_experimental_flags.dart
+++ b/tools/generate_experimental_flags.dart
@@ -2,14 +2,13 @@
 // 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.
 
-// @dart = 2.9
-
 import 'dart:io' show File, Platform;
+
 import 'package:yaml/yaml.dart' show YamlMap, loadYaml;
 
 void main() {
   YamlMap yaml = loadYaml(File.fromUri(computeYamlFile()).readAsStringSync());
-  final currentVersion = getAsVersionNumber(yaml['current-version']);
+  final currentVersion = getAsVersionNumber(yaml['current-version'])!;
   final enumNames = StringBuffer();
   final featureValues = StringBuffer();
   final featureNames = StringBuffer();
@@ -108,7 +107,7 @@
   return Platform.script.resolve("../runtime/vm/experimental_features.h");
 }
 
-List<num> getAsVersionNumber(dynamic value) {
+List<num>? getAsVersionNumber(dynamic value) {
   if (value == null) return null;
   final version = List.of("$value".split(".").map(int.parse));
   while (version.length < 3) {
diff --git a/tools/test.dart b/tools/test.dart
index fece115..e85bebd 100755
--- a/tools/test.dart
+++ b/tools/test.dart
@@ -3,8 +3,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.
 
-// @dart = 2.9
-
 import 'package:test_runner/test_runner.dart';
 
 void main(List<String> args) {