Version 2.12.0-261.0.dev

Merge commit '67e71d02c89333be1d9daad53109da051bb84ef8' into 'dev'
diff --git a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
index a0a5fe9..d2793e8 100644
--- a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
@@ -92,6 +92,9 @@
   if (kind == engine.ElementKind.TOP_LEVEL_VARIABLE) {
     return ElementKind.TOP_LEVEL_VARIABLE;
   }
+  if (kind == engine.ElementKind.TYPE_ALIAS) {
+    return ElementKind.TYPE_ALIAS;
+  }
   if (kind == engine.ElementKind.TYPE_PARAMETER) {
     return ElementKind.TYPE_PARAMETER;
   }
@@ -159,7 +162,9 @@
         closeOptionalString = ']';
       }
     }
-    if (parameter.hasRequired) {
+    if (parameter.isRequiredNamed) {
+      sb.write('required ');
+    } else if (parameter.hasRequired) {
       sb.write('@required ');
     }
     parameter.appendToWithoutDelimiters(sb, withNullability: false);
@@ -172,7 +177,7 @@
   List<engine.TypeParameterElement> typeParameters;
   if (element is engine.ClassElement) {
     typeParameters = element.typeParameters;
-  } else if (element is engine.FunctionTypeAliasElement) {
+  } else if (element is engine.TypeAliasElement) {
     typeParameters = element.typeParameters;
   }
   if (typeParameters == null || typeParameters.isEmpty) {
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index 0ad8a15..61b522c 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/dart/analysis/results.dart' as engine;
 import 'package:analyzer/dart/ast/ast.dart' as engine;
 import 'package:analyzer/dart/element/element.dart' as engine;
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/diagnostic/diagnostic.dart' as engine;
 import 'package:analyzer/error/error.dart' as engine;
 import 'package:analyzer/exception/exception.dart';
@@ -58,12 +59,12 @@
         ? type.getDisplayString(withNullability: false)
         : 'dynamic';
   } else if (element is engine.TypeAliasElement) {
-    var aliasedElement = element.aliasedElement;
-    if (aliasedElement is engine.GenericFunctionTypeElement) {
-      var returnType = aliasedElement.returnType;
+    var aliasedType = element.aliasedType;
+    if (aliasedType is FunctionType) {
+      var returnType = aliasedType.returnType;
       return returnType.getDisplayString(withNullability: false);
     } else {
-      return null;
+      return aliasedType.getDisplayString(withNullability: false);
     }
   } else {
     return null;
diff --git a/pkg/analysis_server/test/analysis/notification_navigation_test.dart b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
index 5dae7245..f7a70e9 100644
--- a/pkg/analysis_server/test/analysis/notification_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
@@ -19,7 +19,8 @@
   });
 }
 
-class AbstractNavigationTest extends AbstractAnalysisTest {
+class AbstractNavigationTest extends AbstractAnalysisTest
+    with WithNonFunctionTypeAliasesMixin {
   List<NavigationRegion> regions;
   List<NavigationTarget> targets;
   List<String> targetFiles;
@@ -956,6 +957,28 @@
     expect(testTarget.kind, ElementKind.CLASS);
   }
 
+  Future<void> test_targetElement_typedef_functionType() async {
+    addTestFile('''
+typedef A = void Function();
+
+void f(A a) {}
+''');
+    await prepareNavigation();
+    assertHasRegionTarget('A a', 'A =');
+    expect(testTarget.kind, ElementKind.TYPE_ALIAS);
+  }
+
+  Future<void> test_targetElement_typedef_interfaceType() async {
+    addTestFile('''
+typedef A = List<int>;
+
+void f(A a) {}
+''');
+    await prepareNavigation();
+    assertHasRegionTarget('A a', 'A =');
+    expect(testTarget.kind, ElementKind.TYPE_ALIAS);
+  }
+
   Future<void> test_type_dynamic() async {
     addTestFile('''
 main() {
diff --git a/pkg/analysis_server/test/plugin/protocol_dart_test.dart b/pkg/analysis_server/test/plugin/protocol_dart_test.dart
index aabef45..ccc74d0 100644
--- a/pkg/analysis_server/test/plugin/protocol_dart_test.dart
+++ b/pkg/analysis_server/test/plugin/protocol_dart_test.dart
@@ -9,87 +9,71 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../abstract_context.dart';
 import '../abstract_single_unit.dart';
 
 void main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(ElementTest);
+    defineReflectiveTests(ConvertElementNullableTest);
+    defineReflectiveTests(ConvertElementTest);
     defineReflectiveTests(ElementKindTest);
   });
 }
 
 @reflectiveTest
-class ElementKindTest {
-  void test_fromEngine() {
-    expect(convertElementKind(engine.ElementKind.CLASS), ElementKind.CLASS);
-    expect(convertElementKind(engine.ElementKind.COMPILATION_UNIT),
-        ElementKind.COMPILATION_UNIT);
-    expect(convertElementKind(engine.ElementKind.CONSTRUCTOR),
-        ElementKind.CONSTRUCTOR);
-    expect(convertElementKind(engine.ElementKind.FIELD), ElementKind.FIELD);
-    expect(
-        convertElementKind(engine.ElementKind.FUNCTION), ElementKind.FUNCTION);
-    expect(convertElementKind(engine.ElementKind.FUNCTION_TYPE_ALIAS),
-        ElementKind.FUNCTION_TYPE_ALIAS);
-    expect(convertElementKind(engine.ElementKind.GENERIC_FUNCTION_TYPE),
-        ElementKind.FUNCTION_TYPE_ALIAS);
-    expect(convertElementKind(engine.ElementKind.GETTER), ElementKind.GETTER);
-    expect(convertElementKind(engine.ElementKind.LABEL), ElementKind.LABEL);
-    expect(convertElementKind(engine.ElementKind.LIBRARY), ElementKind.LIBRARY);
-    expect(convertElementKind(engine.ElementKind.LOCAL_VARIABLE),
-        ElementKind.LOCAL_VARIABLE);
-    expect(convertElementKind(engine.ElementKind.METHOD), ElementKind.METHOD);
-    expect(convertElementKind(engine.ElementKind.PARAMETER),
-        ElementKind.PARAMETER);
-    expect(convertElementKind(engine.ElementKind.SETTER), ElementKind.SETTER);
-    expect(convertElementKind(engine.ElementKind.TOP_LEVEL_VARIABLE),
-        ElementKind.TOP_LEVEL_VARIABLE);
-    expect(convertElementKind(engine.ElementKind.TYPE_PARAMETER),
-        ElementKind.TYPE_PARAMETER);
+class ConvertElementNullableTest extends AbstractSingleUnitTest {
+  Future<void> test_CONSTRUCTOR_required_parameters_1() async {
+    writeTestPackageConfig(meta: true);
+    await resolveTestCode('''
+import 'package:meta/meta.dart';    
+class A {
+  const A.myConstructor(int a, {int b, @required int c});
+}''');
+
+    var engineElement = findElement.constructor('myConstructor');
+    // create notification Element
+    var element = convertElement(engineElement);
+    expect(element.parameters, '(int a, {@required int c, int b})');
   }
 
-  void test_string_constructor() {
-    expect(ElementKind(ElementKind.CLASS.name), ElementKind.CLASS);
-    expect(ElementKind(ElementKind.CLASS_TYPE_ALIAS.name),
-        ElementKind.CLASS_TYPE_ALIAS);
-    expect(ElementKind(ElementKind.COMPILATION_UNIT.name),
-        ElementKind.COMPILATION_UNIT);
-    expect(ElementKind(ElementKind.CONSTRUCTOR.name), ElementKind.CONSTRUCTOR);
-    expect(ElementKind(ElementKind.FIELD.name), ElementKind.FIELD);
-    expect(ElementKind(ElementKind.FUNCTION.name), ElementKind.FUNCTION);
-    expect(ElementKind(ElementKind.FUNCTION_TYPE_ALIAS.name),
-        ElementKind.FUNCTION_TYPE_ALIAS);
-    expect(ElementKind(ElementKind.GETTER.name), ElementKind.GETTER);
-    expect(ElementKind(ElementKind.LIBRARY.name), ElementKind.LIBRARY);
-    expect(ElementKind(ElementKind.LOCAL_VARIABLE.name),
-        ElementKind.LOCAL_VARIABLE);
-    expect(ElementKind(ElementKind.METHOD.name), ElementKind.METHOD);
-    expect(ElementKind(ElementKind.PARAMETER.name), ElementKind.PARAMETER);
-    expect(ElementKind(ElementKind.SETTER.name), ElementKind.SETTER);
-    expect(ElementKind(ElementKind.TOP_LEVEL_VARIABLE.name),
-        ElementKind.TOP_LEVEL_VARIABLE);
-    expect(ElementKind(ElementKind.TYPE_PARAMETER.name),
-        ElementKind.TYPE_PARAMETER);
-    expect(ElementKind(ElementKind.UNIT_TEST_TEST.name),
-        ElementKind.UNIT_TEST_TEST);
-    expect(ElementKind(ElementKind.UNIT_TEST_GROUP.name),
-        ElementKind.UNIT_TEST_GROUP);
-    expect(ElementKind(ElementKind.UNKNOWN.name), ElementKind.UNKNOWN);
-    expect(() {
-      ElementKind('no-such-kind');
-    }, throwsException);
+  /// Verify parameter re-ordering for required params
+  Future<void> test_CONSTRUCTOR_required_parameters_2() async {
+    writeTestPackageConfig(meta: true);
+    await resolveTestCode('''
+import 'package:meta/meta.dart';    
+class A {
+  const A.myConstructor(int a, {int b, @required int d, @required int c});
+}''');
+
+    var engineElement = findElement.constructor('myConstructor');
+    // create notification Element
+    var element = convertElement(engineElement);
+    expect(element.parameters,
+        '(int a, {@required int d, @required int c, int b})');
   }
 
-  void test_toString() {
-    expect(ElementKind.CLASS.toString(), 'ElementKind.CLASS');
-    expect(ElementKind.COMPILATION_UNIT.toString(),
-        'ElementKind.COMPILATION_UNIT');
+  /// Verify parameter re-ordering for required params
+  Future<void> test_CONSTRUCTOR_required_parameters_3() async {
+    writeTestPackageConfig(meta: true);
+    verifyNoTestUnitErrors = false;
+    await resolveTestCode('''
+import 'package:meta/meta.dart';    
+class A {
+  const A.myConstructor(int a, {int b, @required int d, @required int c, int a});
+}''');
+
+    var engineElement = findElement.constructor('myConstructor');
+    // create notification Element
+    var element = convertElement(engineElement);
+    expect(element.parameters,
+        '(int a, {@required int d, @required int c, int b, int a})');
   }
 }
 
 @reflectiveTest
-class ElementTest extends AbstractSingleUnitTest {
-  Future<void> test_fromElement_CLASS() async {
+class ConvertElementTest extends AbstractSingleUnitTest
+    with WithNonFunctionTypeAliasesMixin {
+  Future<void> test_CLASS() async {
     await resolveTestCode('''
 @deprecated
 abstract class _A {}
@@ -127,10 +111,10 @@
     }
   }
 
-  Future<void> test_fromElement_CONSTRUCTOR() async {
+  Future<void> test_CONSTRUCTOR() async {
     await resolveTestCode('''
 class A {
-  const A.myConstructor(int a, [String b]);
+  const A.myConstructor(int a, [String? b]);
 }''');
     var engineElement = findElement.constructor('myConstructor');
     // create notification Element
@@ -151,54 +135,54 @@
     expect(element.flags, Element.FLAG_CONST);
   }
 
-  Future<void> test_fromElement_CONSTRUCTOR_required_parameters_1() async {
+  Future<void> test_CONSTRUCTOR_required_parameters_1() async {
     writeTestPackageConfig(meta: true);
     await resolveTestCode('''
 import 'package:meta/meta.dart';    
 class A {
-  const A.myConstructor(int a, {int b, @required int c});
+  const A.myConstructor(int a, {int? b, required int c});
 }''');
 
     var engineElement = findElement.constructor('myConstructor');
     // create notification Element
     var element = convertElement(engineElement);
-    expect(element.parameters, '(int a, {@required int c, int b})');
+    expect(element.parameters, '(int a, {required int c, int b})');
   }
 
   /// Verify parameter re-ordering for required params
-  Future<void> test_fromElement_CONSTRUCTOR_required_parameters_2() async {
+  Future<void> test_CONSTRUCTOR_required_parameters_2() async {
     writeTestPackageConfig(meta: true);
     await resolveTestCode('''
 import 'package:meta/meta.dart';    
 class A {
-  const A.myConstructor(int a, {int b, @required int d, @required int c});
+  const A.myConstructor(int a, {int? b, required int d, required int c});
 }''');
 
     var engineElement = findElement.constructor('myConstructor');
     // create notification Element
     var element = convertElement(engineElement);
-    expect(element.parameters,
-        '(int a, {@required int d, @required int c, int b})');
+    expect(
+        element.parameters, '(int a, {required int d, required int c, int b})');
   }
 
   /// Verify parameter re-ordering for required params
-  Future<void> test_fromElement_CONSTRUCTOR_required_parameters_3() async {
+  Future<void> test_CONSTRUCTOR_required_parameters_3() async {
     writeTestPackageConfig(meta: true);
     verifyNoTestUnitErrors = false;
     await resolveTestCode('''
 import 'package:meta/meta.dart';    
 class A {
-  const A.myConstructor(int a, {int b, @required int d, @required int c, int a});
+  const A.myConstructor(int a, {int b, required int d, required int c, int a});
 }''');
 
     var engineElement = findElement.constructor('myConstructor');
     // create notification Element
     var element = convertElement(engineElement);
     expect(element.parameters,
-        '(int a, {@required int d, @required int c, int b, int a})');
+        '(int a, {required int d, required int c, int b, int a})');
   }
 
-  void test_fromElement_dynamic() {
+  void test_dynamic() {
     var engineElement = engine.DynamicElementImpl.instance;
     // create notification Element
     var element = convertElement(engineElement);
@@ -210,7 +194,7 @@
     expect(element.flags, 0);
   }
 
-  Future<void> test_fromElement_ENUM() async {
+  Future<void> test_ENUM() async {
     await resolveTestCode('''
 @deprecated
 enum _E1 { one, two }
@@ -248,7 +232,7 @@
     }
   }
 
-  Future<void> test_fromElement_ENUM_CONSTANT() async {
+  Future<void> test_ENUM_CONSTANT() async {
     await resolveTestCode('''
 @deprecated
 enum _E1 { one, two }
@@ -333,7 +317,7 @@
     }
   }
 
-  Future<void> test_fromElement_FIELD() async {
+  Future<void> test_FIELD() async {
     await resolveTestCode('''
 class A {
   static const myField = 42;
@@ -356,37 +340,14 @@
     expect(element.flags, Element.FLAG_CONST | Element.FLAG_STATIC);
   }
 
-  Future<void> test_fromElement_FUNCTION_TYPE_ALIAS() async {
-    await resolveTestCode('''
-typedef int F<T>(String x);
-''');
-    var engineElement = findElement.typeAlias('F');
-    // create notification Element
-    var element = convertElement(engineElement);
-    expect(element.kind, ElementKind.FUNCTION_TYPE_ALIAS);
-    expect(element.name, 'F');
-    expect(element.typeParameters, '<T>');
-    {
-      var location = element.location;
-      expect(location.file, testFile);
-      expect(location.offset, 12);
-      expect(location.length, 'F'.length);
-      expect(location.startLine, 1);
-      expect(location.startColumn, 13);
-    }
-    expect(element.parameters, '(String x)');
-    expect(element.returnType, 'int');
-    expect(element.flags, 0);
-  }
-
-  Future<void> test_fromElement_FUNCTION_TYPE_ALIAS_genericTypeAlias() async {
+  Future<void> test_FUNCTION_TYPE_ALIAS_functionType() async {
     await resolveTestCode('''
 typedef F<T> = int Function(String x);
 ''');
     var engineElement = findElement.typeAlias('F');
     // create notification Element
     var element = convertElement(engineElement);
-    expect(element.kind, ElementKind.FUNCTION_TYPE_ALIAS);
+    expect(element.kind, ElementKind.TYPE_ALIAS);
     expect(element.name, 'F');
     expect(element.typeParameters, '<T>');
     {
@@ -402,7 +363,53 @@
     expect(element.flags, 0);
   }
 
-  Future<void> test_fromElement_GETTER() async {
+  Future<void> test_FUNCTION_TYPE_ALIAS_interfaceType() async {
+    await resolveTestCode('''
+typedef F<T> = Map<int, T>;
+''');
+    var engineElement = findElement.typeAlias('F');
+    // create notification Element
+    var element = convertElement(engineElement);
+    expect(element.kind, ElementKind.TYPE_ALIAS);
+    expect(element.name, 'F');
+    expect(element.typeParameters, '<out T>');
+    {
+      var location = element.location;
+      expect(location.file, testFile);
+      expect(location.offset, 8);
+      expect(location.length, 'F'.length);
+      expect(location.startLine, 1);
+      expect(location.startColumn, 9);
+    }
+    expect(element.parameters, isNull);
+    expect(element.returnType, 'Map<int, T>');
+    expect(element.flags, 0);
+  }
+
+  Future<void> test_FUNCTION_TYPE_ALIAS_legacy() async {
+    await resolveTestCode('''
+typedef int F<T>(String x);
+''');
+    var engineElement = findElement.typeAlias('F');
+    // create notification Element
+    var element = convertElement(engineElement);
+    expect(element.kind, ElementKind.TYPE_ALIAS);
+    expect(element.name, 'F');
+    expect(element.typeParameters, '<T>');
+    {
+      var location = element.location;
+      expect(location.file, testFile);
+      expect(location.offset, 12);
+      expect(location.length, 'F'.length);
+      expect(location.startLine, 1);
+      expect(location.startColumn, 13);
+    }
+    expect(element.parameters, '(String x)');
+    expect(element.returnType, 'int');
+    expect(element.flags, 0);
+  }
+
+  Future<void> test_GETTER() async {
     verifyNoTestUnitErrors = false;
     await resolveTestCode('''
 class A {
@@ -426,7 +433,7 @@
     expect(element.flags, 0);
   }
 
-  Future<void> test_fromElement_LABEL() async {
+  Future<void> test_LABEL() async {
     await resolveTestCode('''
 main() {
 myLabel:
@@ -452,11 +459,11 @@
     expect(element.flags, 0);
   }
 
-  Future<void> test_fromElement_METHOD() async {
+  Future<void> test_METHOD() async {
     await resolveTestCode('''
 class A {
-  static List<String> myMethod(int a, {String b, int c}) {
-    return null;
+  static List<String> myMethod(int a, {String? b, int? c}) {
+    return [];
   }
 }''');
     var engineElement = findElement.method('myMethod');
@@ -477,7 +484,7 @@
     expect(element.flags, Element.FLAG_STATIC);
   }
 
-  Future<void> test_fromElement_MIXIN() async {
+  Future<void> test_MIXIN() async {
     await resolveTestCode('''
 mixin A {}
 ''');
@@ -501,7 +508,7 @@
     }
   }
 
-  Future<void> test_fromElement_SETTER() async {
+  Future<void> test_SETTER() async {
     await resolveTestCode('''
 class A {
   set mySetter(String x) {}
@@ -524,3 +531,74 @@
     expect(element.flags, 0);
   }
 }
+
+@reflectiveTest
+class ElementKindTest {
+  void test_fromEngine() {
+    expect(convertElementKind(engine.ElementKind.CLASS), ElementKind.CLASS);
+    expect(convertElementKind(engine.ElementKind.COMPILATION_UNIT),
+        ElementKind.COMPILATION_UNIT);
+    expect(convertElementKind(engine.ElementKind.CONSTRUCTOR),
+        ElementKind.CONSTRUCTOR);
+    expect(convertElementKind(engine.ElementKind.FIELD), ElementKind.FIELD);
+    expect(
+        convertElementKind(engine.ElementKind.FUNCTION), ElementKind.FUNCTION);
+    expect(convertElementKind(engine.ElementKind.FUNCTION_TYPE_ALIAS),
+        ElementKind.FUNCTION_TYPE_ALIAS);
+    expect(convertElementKind(engine.ElementKind.GENERIC_FUNCTION_TYPE),
+        ElementKind.FUNCTION_TYPE_ALIAS);
+    expect(convertElementKind(engine.ElementKind.GETTER), ElementKind.GETTER);
+    expect(convertElementKind(engine.ElementKind.LABEL), ElementKind.LABEL);
+    expect(convertElementKind(engine.ElementKind.LIBRARY), ElementKind.LIBRARY);
+    expect(convertElementKind(engine.ElementKind.LOCAL_VARIABLE),
+        ElementKind.LOCAL_VARIABLE);
+    expect(convertElementKind(engine.ElementKind.METHOD), ElementKind.METHOD);
+    expect(convertElementKind(engine.ElementKind.PARAMETER),
+        ElementKind.PARAMETER);
+    expect(convertElementKind(engine.ElementKind.SETTER), ElementKind.SETTER);
+    expect(convertElementKind(engine.ElementKind.TOP_LEVEL_VARIABLE),
+        ElementKind.TOP_LEVEL_VARIABLE);
+    expect(convertElementKind(engine.ElementKind.TYPE_ALIAS),
+        ElementKind.TYPE_ALIAS);
+    expect(convertElementKind(engine.ElementKind.TYPE_PARAMETER),
+        ElementKind.TYPE_PARAMETER);
+  }
+
+  void test_string_constructor() {
+    expect(ElementKind(ElementKind.CLASS.name), ElementKind.CLASS);
+    expect(ElementKind(ElementKind.CLASS_TYPE_ALIAS.name),
+        ElementKind.CLASS_TYPE_ALIAS);
+    expect(ElementKind(ElementKind.COMPILATION_UNIT.name),
+        ElementKind.COMPILATION_UNIT);
+    expect(ElementKind(ElementKind.CONSTRUCTOR.name), ElementKind.CONSTRUCTOR);
+    expect(ElementKind(ElementKind.FIELD.name), ElementKind.FIELD);
+    expect(ElementKind(ElementKind.FUNCTION.name), ElementKind.FUNCTION);
+    expect(ElementKind(ElementKind.FUNCTION_TYPE_ALIAS.name),
+        ElementKind.FUNCTION_TYPE_ALIAS);
+    expect(ElementKind(ElementKind.GETTER.name), ElementKind.GETTER);
+    expect(ElementKind(ElementKind.LIBRARY.name), ElementKind.LIBRARY);
+    expect(ElementKind(ElementKind.LOCAL_VARIABLE.name),
+        ElementKind.LOCAL_VARIABLE);
+    expect(ElementKind(ElementKind.METHOD.name), ElementKind.METHOD);
+    expect(ElementKind(ElementKind.PARAMETER.name), ElementKind.PARAMETER);
+    expect(ElementKind(ElementKind.SETTER.name), ElementKind.SETTER);
+    expect(ElementKind(ElementKind.TOP_LEVEL_VARIABLE.name),
+        ElementKind.TOP_LEVEL_VARIABLE);
+    expect(ElementKind(ElementKind.TYPE_PARAMETER.name),
+        ElementKind.TYPE_PARAMETER);
+    expect(ElementKind(ElementKind.UNIT_TEST_TEST.name),
+        ElementKind.UNIT_TEST_TEST);
+    expect(ElementKind(ElementKind.UNIT_TEST_GROUP.name),
+        ElementKind.UNIT_TEST_GROUP);
+    expect(ElementKind(ElementKind.UNKNOWN.name), ElementKind.UNKNOWN);
+    expect(() {
+      ElementKind('no-such-kind');
+    }, throwsException);
+  }
+
+  void test_toString() {
+    expect(ElementKind.CLASS.toString(), 'ElementKind.CLASS');
+    expect(ElementKind.COMPILATION_UNIT.toString(),
+        'ElementKind.COMPILATION_UNIT');
+  }
+}
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 0d5d964..b355d68 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -229,7 +229,6 @@
       engine.ElementKind.IMPORT: ElementKind.UNKNOWN,
       engine.ElementKind.NAME: ElementKind.UNKNOWN,
       engine.ElementKind.NEVER: ElementKind.UNKNOWN,
-      engine.ElementKind.TYPE_ALIAS: ElementKind.UNKNOWN,
       engine.ElementKind.UNIVERSE: ElementKind.UNKNOWN
     });
   }
diff --git a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
index bd4f5a5..92ab8c1 100644
--- a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
+++ b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/element/element.dart' as analyzer;
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/diagnostic/diagnostic.dart' as analyzer;
 import 'package:analyzer/error/error.dart' as analyzer;
 import 'package:analyzer/exception/exception.dart' as analyzer;
@@ -164,6 +165,8 @@
       return plugin.ElementKind.SETTER;
     } else if (kind == analyzer.ElementKind.TOP_LEVEL_VARIABLE) {
       return plugin.ElementKind.TOP_LEVEL_VARIABLE;
+    } else if (kind == analyzer.ElementKind.TYPE_ALIAS) {
+      return plugin.ElementKind.TYPE_ALIAS;
     } else if (kind == analyzer.ElementKind.TYPE_PARAMETER) {
       return plugin.ElementKind.TYPE_PARAMETER;
     }
@@ -281,12 +284,12 @@
           ? type.getDisplayString(withNullability: false)
           : 'dynamic';
     } else if (element is analyzer.TypeAliasElement) {
-      var aliasedElement = element.aliasedElement;
-      if (aliasedElement is analyzer.GenericFunctionTypeElement) {
-        var returnType = aliasedElement.returnType;
+      var aliasedType = element.aliasedType;
+      if (aliasedType is FunctionType) {
+        var returnType = aliasedType.returnType;
         return returnType.getDisplayString(withNullability: false);
       } else {
-        return null;
+        return aliasedType.getDisplayString(withNullability: false);
       }
     }
     return null;
diff --git a/pkg/analyzer_plugin/test/support/abstract_context.dart b/pkg/analyzer_plugin/test/support/abstract_context.dart
index b7c0d5a..e98a83e 100644
--- a/pkg/analyzer_plugin/test/support/abstract_context.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_context.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
 import 'package:analyzer/src/test_utilities/mock_packages.dart';
 import 'package:analyzer/src/test_utilities/mock_sdk.dart';
@@ -167,9 +168,25 @@
   }
 }
 
+mixin WithNonFunctionTypeAliasesMixin on AbstractContextTest {
+  @override
+  String get testPackageLanguageVersion => null;
+
+  @override
+  void setUp() {
+    super.setUp();
+
+    createAnalysisOptionsFile(
+      experiments: [
+        EnableString.nonfunction_type_aliases,
+      ],
+    );
+  }
+}
+
 mixin WithNullSafetyMixin on AbstractContextTest {
   @override
-  String get testPackageLanguageVersion => '2.12';
+  String get testPackageLanguageVersion => null;
 }
 
 /// Wraps the given [_ElementVisitorFunction] into an instance of
diff --git a/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart b/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart
index db1a6fc..ed2c434 100644
--- a/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart
+++ b/pkg/analyzer_plugin/test/utilities/analyzer_converter_test.dart
@@ -15,17 +15,45 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../support/abstract_context.dart';
 import '../support/abstract_single_unit.dart';
 
 void main() {
+  defineReflectiveTests(AnalyzerConverterNullableTest);
   defineReflectiveTests(AnalyzerConverterTest);
 }
 
 @reflectiveTest
-class AnalyzerConverterTest extends AbstractSingleUnitTest {
-  AnalyzerConverter converter = AnalyzerConverter();
-  analyzer.Source source;
+class AnalyzerConverterNullableTest extends _AnalyzerConverterTest {
+  Future<void> test_convertElement_method() async {
+    await resolveTestCode('''
+class A {
+  static List<String> myMethod(int a, {String b, int c}) {
+    return [];
+  }
+}''');
+    var engineElement = findElement.method('myMethod');
+    // create notification Element
+    var element = converter.convertElement(engineElement);
+    expect(element.kind, plugin.ElementKind.METHOD);
+    expect(element.name, 'myMethod');
+    {
+      var location = element.location;
+      expect(location.file, testFile);
+      expect(location.offset, 32);
+      expect(location.length, 'myGetter'.length);
+      expect(location.startLine, 2);
+      expect(location.startColumn, 23);
+    }
+    expect(element.parameters, '(int a, {String b, int c})');
+    expect(element.returnType, 'List<String>');
+    expect(element.flags, plugin.Element.FLAG_STATIC);
+  }
+}
 
+@reflectiveTest
+class AnalyzerConverterTest extends _AnalyzerConverterTest
+    with WithNonFunctionTypeAliasesMixin {
   /// Assert that the given [pluginError] matches the given [analyzerError].
   void assertError(
       plugin.AnalysisError pluginError, analyzer.AnalysisError analyzerError,
@@ -67,13 +95,6 @@
         contextMessages);
   }
 
-  @override
-  void setUp() {
-    super.setUp();
-    source = newFile('/foo/bar.dart').createSource();
-    testFile = convertPath('$testPackageRootPath/lib/test.dart');
-  }
-
   void test_convertAnalysisError_contextMessages() {
     var analyzerError = createError(13, contextMessage: 'here');
     var lineInfo = analyzer.LineInfo([0, 10, 20]);
@@ -239,7 +260,7 @@
   Future<void> test_convertElement_constructor() async {
     await resolveTestCode('''
 class A {
-  const A.myConstructor(int a, [String b]);
+  const A.myConstructor(int a, [String? b]);
 }''');
     var engineElement = findElement.constructor('myConstructor');
     // create notification Element
@@ -429,7 +450,7 @@
     var engineElement = findElement.typeAlias('F');
     // create notification Element
     var element = converter.convertElement(engineElement);
-    expect(element.kind, plugin.ElementKind.FUNCTION_TYPE_ALIAS);
+    expect(element.kind, plugin.ElementKind.TYPE_ALIAS);
     expect(element.name, 'F');
     expect(element.typeParameters, '<T>');
     {
@@ -445,29 +466,6 @@
     expect(element.flags, 0);
   }
 
-  Future<void> test_convertElement_genericTypeAlias_function() async {
-    await resolveTestCode('''
-typedef F<T> = int Function(String x);
-''');
-    var engineElement = findElement.typeAlias('F');
-    // create notification Element
-    var element = converter.convertElement(engineElement);
-    expect(element.kind, plugin.ElementKind.FUNCTION_TYPE_ALIAS);
-    expect(element.name, 'F');
-    expect(element.typeParameters, '<T>');
-    {
-      var location = element.location;
-      expect(location.file, testFile);
-      expect(location.offset, 8);
-      expect(location.length, 'F'.length);
-      expect(location.startLine, 1);
-      expect(location.startColumn, 9);
-    }
-    expect(element.parameters, '(String x)');
-    expect(element.returnType, 'int');
-    expect(element.flags, 0);
-  }
-
   Future<void> test_convertElement_getter() async {
     await resolveTestCode('''
 class A {
@@ -491,11 +489,37 @@
     expect(element.flags, 0);
   }
 
+  Future<void> test_convertElement_LABEL() async {
+    await resolveTestCode('''
+main() {
+myLabel:
+  while (true) {
+    break myLabel;
+  }
+}''');
+    var engineElement = findElement.label('myLabel');
+    // create notification Element
+    var element = converter.convertElement(engineElement);
+    expect(element.kind, plugin.ElementKind.LABEL);
+    expect(element.name, 'myLabel');
+    {
+      var location = element.location;
+      expect(location.file, testFile);
+      expect(location.offset, 9);
+      expect(location.length, 'myLabel'.length);
+      expect(location.startLine, 2);
+      expect(location.startColumn, 1);
+    }
+    expect(element.parameters, isNull);
+    expect(element.returnType, isNull);
+    expect(element.flags, 0);
+  }
+
   Future<void> test_convertElement_method() async {
     await resolveTestCode('''
 class A {
-  static List<String> myMethod(int a, {String b, int c}) {
-    return null;
+  static List<String> myMethod(int a, {String? b, int? c}) {
+    return [];
   }
 }''');
     var engineElement = findElement.method('myMethod');
@@ -539,6 +563,52 @@
     expect(element.flags, 0);
   }
 
+  Future<void> test_convertElement_typeAlias_functionType() async {
+    await resolveTestCode('''
+typedef F<T> = int Function(String x);
+''');
+    var engineElement = findElement.typeAlias('F');
+    // create notification Element
+    var element = converter.convertElement(engineElement);
+    expect(element.kind, plugin.ElementKind.TYPE_ALIAS);
+    expect(element.name, 'F');
+    expect(element.typeParameters, '<T>');
+    {
+      var location = element.location;
+      expect(location.file, testFile);
+      expect(location.offset, 8);
+      expect(location.length, 'F'.length);
+      expect(location.startLine, 1);
+      expect(location.startColumn, 9);
+    }
+    expect(element.parameters, '(String x)');
+    expect(element.returnType, 'int');
+    expect(element.flags, 0);
+  }
+
+  Future<void> test_convertElement_typeAlias_interfaceType() async {
+    await resolveTestCode('''
+typedef A<T> = Map<int, T>;
+''');
+    var engineElement = findElement.typeAlias('A');
+    // create notification Element
+    var element = converter.convertElement(engineElement);
+    expect(element.kind, plugin.ElementKind.TYPE_ALIAS);
+    expect(element.name, 'A');
+    expect(element.typeParameters, '<out T>');
+    {
+      var location = element.location;
+      expect(location.file, testFile);
+      expect(location.offset, 8);
+      expect(location.length, 'A'.length);
+      expect(location.startLine, 1);
+      expect(location.startColumn, 9);
+    }
+    expect(element.parameters, isNull);
+    expect(element.returnType, 'Map<int, T>');
+    expect(element.flags, 0);
+  }
+
   void test_convertElementKind() {
     expect(converter.convertElementKind(analyzer.ElementKind.CLASS),
         plugin.ElementKind.CLASS);
@@ -570,6 +640,8 @@
     expect(
         converter.convertElementKind(analyzer.ElementKind.TOP_LEVEL_VARIABLE),
         plugin.ElementKind.TOP_LEVEL_VARIABLE);
+    expect(converter.convertElementKind(analyzer.ElementKind.TYPE_ALIAS),
+        plugin.ElementKind.TYPE_ALIAS);
     expect(converter.convertElementKind(analyzer.ElementKind.TYPE_PARAMETER),
         plugin.ElementKind.TYPE_PARAMETER);
   }
@@ -588,30 +660,16 @@
       expect(converter.convertErrorType(type), isNotNull, reason: type.name);
     }
   }
+}
 
-  Future<void> test_fromElement_LABEL() async {
-    await resolveTestCode('''
-main() {
-myLabel:
-  while (true) {
-    break myLabel;
-  }
-}''');
-    var engineElement = findElement.label('myLabel');
-    // create notification Element
-    var element = converter.convertElement(engineElement);
-    expect(element.kind, plugin.ElementKind.LABEL);
-    expect(element.name, 'myLabel');
-    {
-      var location = element.location;
-      expect(location.file, testFile);
-      expect(location.offset, 9);
-      expect(location.length, 'myLabel'.length);
-      expect(location.startLine, 2);
-      expect(location.startColumn, 1);
-    }
-    expect(element.parameters, isNull);
-    expect(element.returnType, isNull);
-    expect(element.flags, 0);
+class _AnalyzerConverterTest extends AbstractSingleUnitTest {
+  AnalyzerConverter converter = AnalyzerConverter();
+  analyzer.Source source;
+
+  @override
+  void setUp() {
+    super.setUp();
+    source = newFile('/foo/bar.dart').createSource();
+    testFile = convertPath('$testPackageRootPath/lib/test.dart');
   }
 }
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 5590b0d..02feb06 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -3399,27 +3399,65 @@
 
   @override
   void visitBasicBlock(HBasicBlock block) {
-    if (block.predecessors.length == 0) {
+    final predecessors = block.predecessors;
+    final indegree = predecessors.length;
+    if (indegree == 0) {
       // Entry block.
       memorySet = new MemorySet(_closedWorld);
-    } else if (block.predecessors.length == 1 &&
-        block.predecessors[0].successors.length == 1) {
+    } else if (indegree == 1 && predecessors[0].successors.length == 1) {
       // No need to clone, there is no other successor for
-      // `block.predecessors[0]`, and this block has only one
-      // predecessor. Since we are not going to visit
-      // `block.predecessors[0]` again, we can just re-use its
-      // [memorySet].
-      memorySet = memories[block.predecessors[0].id];
-    } else if (block.predecessors.length == 1) {
-      // Clone the memorySet of the predecessor, because it is also used
-      // by other successors of it.
-      memorySet = memories[block.predecessors[0].id].clone();
+      // `block.predecessors[0]`, and this block has only one predecessor. Since
+      // we are not going to visit `block.predecessors[0]` again, we can just
+      // re-use its [memorySet].
+      memorySet = memories[predecessors[0].id];
+    } else if (indegree == 1) {
+      // Clone the memorySet of the predecessor, because it is also used by
+      // other successors of it.
+      memorySet = memories[predecessors[0].id].clone();
     } else {
       // Compute the intersection of all predecessors.
-      memorySet = memories[block.predecessors[0].id];
-      for (int i = 1; i < block.predecessors.length; i++) {
-        memorySet = memorySet.intersectionFor(
-            memories[block.predecessors[i].id], block, i);
+      //
+      // If a predecessor does not have a reachable exit, the kills on that path
+      // can be ignored. Since the usual case is conditional diamond flow with
+      // two predecessors, this is done by detecting a single non-dead
+      // predecessor and cloning the memory-set, but removing expressions that
+      // are not valid in the current block (invalid instructions would be in
+      // one arm of the diamond).
+
+      List<MemorySet> inputs = List.filled(indegree, null);
+      int firstLiveIndex = -1;
+      int otherLiveIndex = -1;
+      int firstDeadIndex = -1;
+      bool pendingBackEdge = false;
+
+      for (int i = 0; i < indegree; i++) {
+        final predecessor = predecessors[i];
+        final input = inputs[i] = memories[predecessor.id];
+        if (input == null) pendingBackEdge = true;
+        if (hasUnreachableExit(predecessor)) {
+          if (firstDeadIndex == -1) firstDeadIndex = i;
+        } else {
+          if (firstLiveIndex == -1) {
+            firstLiveIndex = i;
+          } else if (otherLiveIndex == -1) {
+            otherLiveIndex = i;
+          }
+        }
+      }
+
+      if (firstLiveIndex != -1 &&
+          otherLiveIndex == -1 &&
+          firstDeadIndex != -1 &&
+          !pendingBackEdge) {
+        // Single live input intersection.
+        memorySet = memories[predecessors[firstLiveIndex].id]
+            .cloneIfDominatesBlock(block);
+      } else {
+        // Standard intersection over all predecessors.
+        memorySet = inputs[0];
+        for (int i = 1; i < inputs.length; i++) {
+          memorySet = memorySet.intersectionFor(inputs[i], block, i);
+        }
       }
     }
 
@@ -4013,4 +4051,38 @@
     result.nonEscapingReceivers.addAll(nonEscapingReceivers);
     return result;
   }
+
+  /// Returns a copy of [this] memory set, removing any expressions that are not
+  /// valid in [block].
+  MemorySet cloneIfDominatesBlock(HBasicBlock block) {
+    bool instructionDominatesBlock(HInstruction instruction) {
+      return instruction != null && instruction.block.dominates(block);
+    }
+
+    MemorySet result = MemorySet(closedWorld);
+
+    fieldValues.forEach((element, values) {
+      values.forEach((receiver, value) {
+        if ((receiver == null || instructionDominatesBlock(receiver)) &&
+            instructionDominatesBlock(value)) {
+          result.registerFieldValue(element, receiver, value);
+        }
+      });
+    });
+
+    keyedValues.forEach((receiver, values) {
+      if (instructionDominatesBlock(receiver)) {
+        values.forEach((index, value) {
+          if (instructionDominatesBlock(index) &&
+              instructionDominatesBlock(value)) {
+            result.registerKeyedValue(receiver, index, value);
+          }
+        });
+      }
+    });
+
+    result.nonEscapingReceivers
+        .addAll(nonEscapingReceivers.where(instructionDominatesBlock));
+    return result;
+  }
 }
diff --git a/tools/VERSION b/tools/VERSION
index 1c187b9..a69e0df 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 12
 PATCH 0
-PRERELEASE 260
+PRERELEASE 261
 PRERELEASE_PATCH 0
\ No newline at end of file