Version 2.15.0-145.0.dev

Merge commit '5e0f4c24c554352fd1da953bf64532c207a04ef3' into 'dev'
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index 2fb02e1..eaad3c1 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -28,7 +28,7 @@
     }
     expect(
       typeArguments.map(
-          (arg) => arg.toTypeValue()!.getDisplayString(withNullability: false)),
+          (arg) => arg.toTypeValue()!.getDisplayString(withNullability: true)),
       equals(typeArgumentNames),
     );
   }
@@ -226,100 +226,6 @@
     await _assertValueBool(false, "'a' == 'b'");
   }
 
-  test_functionReference_explicitTypeArgs_badBound() async {
-    var result = await _getExpressionValue("foo<String>", context: '''
-void foo<T extends num>(T a) {}
-''');
-    expect(result.isValid, isTrue);
-    DartObject value = result.value!;
-    assertType(value.type, 'void Function(String)');
-    assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
-    assertTypeArguments(value, ['String']);
-  }
-
-  test_functionReference_explicitTypeArgs_differentElements() async {
-    var result = await _getExpressionValue("(b ? foo : bar)<int>", context: '''
-const b = true;
-void foo<T>(String a, T b) {}
-void bar<T>(T a, String b) {}
-''');
-    expect(result.isValid, isTrue);
-    DartObject value = result.value!;
-    assertType(value.type, 'void Function(String, int)');
-    assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
-    assertTypeArguments(value, ['int']);
-  }
-
-  test_functionReference_explicitTypeArgs_identifier() async {
-    // TODO(srawlins): Add test where the type argument is a type variable.
-    var result = await _getExpressionValue("foo<int>", context: '''
-void foo<T>(T a) {}
-''');
-    expect(result.isValid, isTrue);
-    var value = result.value!;
-    assertType(value.type, 'void Function(int)');
-    assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
-    assertTypeArguments(value, ['int']);
-  }
-
-  test_functionReference_explicitTypeArgs_nonIdentifier() async {
-    var result = await _getExpressionValue("(b ? foo : bar)<int>", context: '''
-const b = true;
-void foo<T>(T a) {}
-void bar<T>(T a) {}
-''');
-    expect(result.isValid, isTrue);
-    var value = result.value!;
-    assertType(value.type, 'void Function(int)');
-    assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
-    assertTypeArguments(value, ['int']);
-  }
-
-  test_functionReference_explicitTypeArgs_notAType() async {
-    var result = await _getExpressionValue("foo<true>", context: '''
-void foo<T>(T a) {}
-''');
-    expect(result.isValid, isFalse);
-  }
-
-  test_functionReference_explicitTypeArgs_tooFew() async {
-    var result = await _getExpressionValue("foo<int>", context: '''
-void foo<T, U>(T a) {}
-''');
-    expect(result.isValid, isFalse);
-  }
-
-  test_functionReference_explicitTypeArgs_tooMany() async {
-    var result = await _getExpressionValue("foo<int, int>", context: '''
-void foo<T>(T a) {}
-''');
-    expect(result.isValid, isFalse);
-  }
-
-  test_functionReference_uninstantiated_identifier() async {
-    var result = await _getExpressionValue("foo", context: '''
-void foo<T>(T a) {}
-''');
-    expect(result.isValid, isTrue);
-    DartObject value = result.value!;
-    assertType(value.type, 'void Function<T>(T)');
-    assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
-    assertTypeArguments(value, null);
-  }
-
-  test_functionReference_uninstantiated_nonIdentifier() async {
-    var result = await _getExpressionValue("b ? foo : bar", context: '''
-const b = true;
-void foo<T>(T a) {}
-void bar<T>(T a) {}
-''');
-    expect(result.isValid, isTrue);
-    DartObject value = result.value!;
-    assertType(value.type, 'void Function<T>(T)');
-    assertElement(value.toFunctionValue(), findElement.topFunction('foo'));
-    assertTypeArguments(value, null);
-  }
-
   test_greaterThan_int_int() async {
     await _assertValueBool(false, "2 > 3");
   }
@@ -328,51 +234,6 @@
     await _assertValueBool(false, "2 >= 3");
   }
 
-  test_identical_functionReference_explicitTypeArgs_differentElements() async {
-    var result =
-        await _getExpressionValue("identical(foo<int>, bar<int>)", context: '''
-void foo<T>(T a) {}
-void bar<T>(T a) {}
-''');
-    expect(result.isValid, isTrue);
-    DartObject value = result.value!;
-    assertType(value.type, 'bool');
-    expect(value.toBoolValue(), false);
-  }
-
-  test_identical_functionReference_explicitTypeArgs_differentTypeArgs() async {
-    var result = await _getExpressionValue("identical(foo<int>, foo<String>)",
-        context: '''
-void foo<T>(T a) {}
-''');
-    expect(result.isValid, isTrue);
-    DartObject value = result.value!;
-    assertType(value.type, 'bool');
-    expect(value.toBoolValue(), false);
-  }
-
-  test_identical_functionReference_explicitTypeArgs_sameElement() async {
-    var result =
-        await _getExpressionValue("identical(foo<int>, foo<int>)", context: '''
-void foo<T>(T a) {}
-''');
-    expect(result.isValid, isTrue);
-    DartObject value = result.value!;
-    assertType(value.type, 'bool');
-    expect(value.toBoolValue(), true);
-  }
-
-  test_identical_functionReference_onlyOneHasTypeArgs() async {
-    var result =
-        await _getExpressionValue("identical(foo<int>, foo)", context: '''
-void foo<T>(T a) {}
-''');
-    expect(result.isValid, isTrue);
-    DartObject value = result.value!;
-    assertType(value.type, 'bool');
-    expect(value.toBoolValue(), false);
-  }
-
   @failingTest
   test_identifier_class() async {
     var result = await _getExpressionValue("?");
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index 69b5497..7b42573 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -3,6 +3,7 @@
 // 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';
 import 'package:analyzer/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -120,6 +121,62 @@
     );
   }
 
+  test_identical_functionReference_explicitTypeArgs_differentElements() async {
+    await resolveTestCode('''
+void foo<T>(T a) {}
+void bar<T>(T a) {}
+const g = identical(foo<int>, bar<int>);
+''');
+    expect(
+      _evaluateConstant('g'),
+      _boolValue(false),
+    );
+  }
+
+  test_identical_functionReference_explicitTypeArgs_differentTypeArgs() async {
+    await resolveTestCode('''
+void foo<T>(T a) {}
+const g = identical(foo<int>, foo<String>);
+''');
+    expect(
+      _evaluateConstant('g'),
+      _boolValue(false),
+    );
+  }
+
+  test_identical_functionReference_explicitTypeArgs_onlyOneHasTypeArgs() async {
+    await resolveTestCode('''
+void foo<T>(T a) {}
+const g = identical(foo<int>, foo);
+''');
+    expect(
+      _evaluateConstant('g'),
+      _boolValue(false),
+    );
+  }
+
+  test_identical_functionReference_explicitTypeArgs_sameElement() async {
+    await resolveTestCode('''
+void foo<T>(T a) {}
+const g = identical(foo<int>, foo<int>);
+''');
+    expect(
+      _evaluateConstant('g'),
+      _boolValue(true),
+    );
+  }
+
+  test_identical_functionReference_uninstantiated_sameElement() async {
+    await resolveTestCode('''
+void foo<T>(T a) {}
+const g = identical(foo, foo);
+''');
+    expect(
+      _evaluateConstant('g'),
+      _boolValue(true),
+    );
+  }
+
   test_visitAsExpression_potentialConstType() async {
     await assertNoErrorsInCode('''
 const num three = 3;
@@ -223,6 +280,128 @@
     expect(result.toIntValue(), 0xFF);
   }
 
+  test_visitFunctionReference_explicitTypeArgs_complexExpression() async {
+    await resolveTestCode('''
+const b = true;
+void foo<T>(T a) {}
+void bar<T>(T a) {}
+const g = (b ? foo : bar)<int>;
+''');
+    var result = _evaluateConstant('g');
+    assertType(result.type, 'void Function(int)');
+    assertElement(result.toFunctionValue(), findElement.topFunction('foo'));
+    _assertTypeArguments(result, ['int']);
+  }
+
+  test_visitFunctionReference_explicitTypeArgs_complexExpression_differentTypes() async {
+    await resolveTestCode('''
+const b = true;
+void foo<T>(String a, T b) {}
+void bar<T>(T a, String b) {}
+const g = (b ? foo : bar)<int>;
+''');
+    var result = _evaluateConstant('g');
+    assertType(result.type, 'void Function(String, int)');
+    assertElement(result.toFunctionValue(), findElement.topFunction('foo'));
+    _assertTypeArguments(result, ['int']);
+  }
+
+  test_visitFunctionReference_explicitTypeArgs_functionName_constantType() async {
+    await resolveTestCode('''
+void f<T>(T a) {}
+const g = f<int>;
+''');
+    var result = _evaluateConstant('g');
+    assertType(result.type, 'void Function(int)');
+    assertElement(result.toFunctionValue(), findElement.topFunction('f'));
+    _assertTypeArguments(result, ['int']);
+  }
+
+  test_visitFunctionReference_explicitTypeArgs_functionName_notMatchingBound() async {
+    await resolveTestCode('''
+void f<T extends num>(T a) {}
+const g = f<String>;
+''');
+    var result = _evaluateConstant('g');
+    assertType(result.type, 'void Function(String)');
+    assertElement(result.toFunctionValue(), findElement.topFunction('f'));
+    _assertTypeArguments(result, ['String']);
+  }
+
+  test_visitFunctionReference_functionName_explicitTypeArgs_notType() async {
+    await resolveTestCode('''
+void foo<T>(T a) {}
+const g = foo<true>;
+''');
+    var result = _evaluateConstantOrNull('g', errorCodes: [
+      CompileTimeErrorCode.CONST_EVAL_TYPE_NUM,
+      CompileTimeErrorCode.INVALID_CONSTANT,
+    ]);
+    expect(result, isNull);
+  }
+
+  test_visitFunctionReference_functionName_explicitTypeArgs_tooFew() async {
+    await resolveTestCode('''
+void foo<T, U>(T a, U b) {}
+const g = foo<int>;
+''');
+    var result = _evaluateConstantOrNull('g');
+    // The wrong number of arguments is reported elsewhere. Here, the result is
+    // simply `null`.
+    expect(result, isNull);
+  }
+
+  test_visitFunctionReference_functionName_explicitTypeArgs_tooMany() async {
+    await resolveTestCode('''
+void foo<T>(T a) {}
+const g = foo<int, String>;
+''');
+    var result = _evaluateConstantOrNull('g');
+    // The wrong number of arguments is reported elsewhere. Here, the result is
+    // simply `null`.
+    expect(result, isNull);
+  }
+
+  test_visitFunctionReference_functionName_explicitTypeArgs_typeParameter() async {
+    await resolveTestCode('''
+void f<T>(T a) {}
+
+class C<U> {
+  void m() {
+    static const g = f<U>;
+  }
+}
+''');
+    var result = _evaluateConstantLocal('g')!;
+    assertType(result.type, 'void Function(U)');
+    assertElement(result.toFunctionValue(), findElement.topFunction('f'));
+    _assertTypeArguments(result, ['U']);
+  }
+
+  test_visitFunctionReference_uninstantiated_complexExpression() async {
+    await resolveTestCode('''
+const b = true;
+void foo<T>(T a) {}
+void bar<T>(T a) {}
+const g = b ? foo : bar;
+''');
+    var result = _evaluateConstant('g');
+    assertType(result.type, 'void Function<T>(T)');
+    assertElement(result.toFunctionValue(), findElement.topFunction('foo'));
+    _assertTypeArguments(result, null);
+  }
+
+  test_visitFunctionReference_uninstantiated_functionName() async {
+    await resolveTestCode('''
+void f<T>(T a) {}
+const g = f;
+''');
+    var result = _evaluateConstant('g');
+    assertType(result.type, 'void Function<T>(T)');
+    assertElement(result.toFunctionValue(), findElement.topFunction('f'));
+    _assertTypeArguments(result, null);
+  }
+
   test_visitSimpleIdentifier_className() async {
     await resolveTestCode('''
 const a = C;
@@ -1320,6 +1499,19 @@
 }
 
 class ConstantVisitorTestSupport extends PubPackageResolutionTest {
+  void _assertTypeArguments(DartObject value, List<String>? typeArgumentNames) {
+    var typeArguments = (value as DartObjectImpl).typeArguments;
+    if (typeArguments == null) {
+      expect(typeArguments, typeArgumentNames);
+      return;
+    }
+    expect(
+      typeArguments.map(
+          (arg) => arg.toTypeValue()!.getDisplayString(withNullability: true)),
+      equals(typeArgumentNames),
+    );
+  }
+
   DartObjectImpl _evaluateConstant(
     String name, {
     List<ErrorCode>? errorCodes,
@@ -1334,6 +1526,21 @@
     )!;
   }
 
+  DartObjectImpl? _evaluateConstantLocal(
+    String name, {
+    List<ErrorCode>? errorCodes,
+    Map<String, String> declaredVariables = const {},
+    Map<String, DartObjectImpl>? lexicalEnvironment,
+  }) {
+    var expression = findNode.variableDeclaration(name).initializer!;
+    return _evaluateExpression(
+      expression,
+      errorCodes: errorCodes,
+      declaredVariables: declaredVariables,
+      lexicalEnvironment: lexicalEnvironment,
+    );
+  }
+
   DartObjectImpl? _evaluateConstantOrNull(
     String name, {
     List<ErrorCode>? errorCodes,
@@ -1341,7 +1548,20 @@
     Map<String, DartObjectImpl>? lexicalEnvironment,
   }) {
     var expression = findNode.topVariableDeclarationByName(name).initializer!;
+    return _evaluateExpression(
+      expression,
+      errorCodes: errorCodes,
+      declaredVariables: declaredVariables,
+      lexicalEnvironment: lexicalEnvironment,
+    );
+  }
 
+  DartObjectImpl? _evaluateExpression(
+    Expression expression, {
+    List<ErrorCode>? errorCodes,
+    Map<String, String> declaredVariables = const {},
+    Map<String, DartObjectImpl>? lexicalEnvironment,
+  }) {
     var unit = this.result.unit;
     var source = unit.declaredElement!.source;
     var errorListener = GatheringErrorListener();
@@ -1351,7 +1571,7 @@
       isNonNullableByDefault: false,
     );
 
-    DartObjectImpl? result = expression.accept(
+    var result = expression.accept(
       ConstantVisitor(
         ConstantEvaluationEngine(
           declaredVariables: DeclaredVariables.fromMap(declaredVariables),
diff --git a/tools/VERSION b/tools/VERSION
index fe63169..bf47595 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 144
+PRERELEASE 145
 PRERELEASE_PATCH 0
\ No newline at end of file