Version 2.14.0-236.0.dev
Merge commit 'b687e7e7570c7e27fdd83d5a844c1ca8f6447688' into 'dev'
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
new file mode 100644
index 0000000..b8c9a8a
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -0,0 +1,247 @@
+// 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/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/ast/extensions.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/dart/resolver/resolution_result.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+/// A resolver for [FunctionReference] nodes.
+///
+/// This resolver is responsible for writing a given [FunctionReference] as a
+/// [ConstructorReference] or as a [TypeLiteral], depending on how a function
+/// reference's `function` resolves.
+class FunctionReferenceResolver {
+ /// The resolver driving this participant.
+ final ResolverVisitor _resolver;
+
+ FunctionReferenceResolver(this._resolver);
+
+ ErrorReporter get _errorReporter => _resolver.errorReporter;
+
+ void resolve(FunctionReferenceImpl node) {
+ var function = node.function;
+ node.typeArguments?.accept(_resolver);
+
+ if (function is SimpleIdentifierImpl) {
+ var element = _resolver.nameScope.lookup(function.name).getter;
+ if (element is ExecutableElement) {
+ function.staticElement = element;
+ _resolve(node: node, rawType: element.type);
+ return;
+ } else if (element is VariableElement) {
+ var functionType = element.type;
+ if (functionType is FunctionType) {
+ function.accept(_resolver);
+ _resolve(node: node, rawType: functionType);
+ return;
+ }
+ }
+ }
+
+ // TODO(srawlins): Handle `function` being a [SuperExpression].
+
+ if (function is PrefixedIdentifierImpl) {
+ var prefixElement =
+ _resolver.nameScope.lookup(function.prefix.name).getter;
+ if (prefixElement is PrefixElement) {
+ var nameNode = function.identifier;
+ var name = nameNode.name;
+ _resolveReceiverPrefix(node, prefixElement, nameNode, name);
+ return;
+ }
+
+ if (prefixElement is ClassElement) {
+ // TODO(srawlins): Rewrite `node` as a [TypeLiteral], then resolve the
+ // [TypeLiteral] instead of `function`.
+ function.accept(_resolver);
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ } else if (prefixElement is TypeAliasElement) {
+ var aliasedType = prefixElement.aliasedType;
+ if (aliasedType is InterfaceType) {
+ // TODO(srawlins): Rewrite `node` as a [TypeLiteral], then resolve
+ // the [TypeLiteral] instead of `function`.
+ function.accept(_resolver);
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ }
+ } else if (prefixElement is ExtensionElement) {
+ // TODO(srawlins): Rewrite `node` as a [TypeLiteral], then resolve the
+ // [TypeLiteral] instead of `function`.
+ function.accept(_resolver);
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ }
+
+ ResolutionResult resolveTypeProperty(DartType prefixType) {
+ return _resolver.typePropertyResolver.resolve(
+ receiver: function.prefix,
+ receiverType: prefixType,
+ name: function.identifier.name,
+ propertyErrorEntity: function.identifier,
+ nameErrorEntity: function,
+ );
+ }
+
+ function.prefix.staticElement = prefixElement;
+ ExecutableElement? methodElement;
+ if (prefixElement is VariableElement) {
+ var prefixType = prefixElement.type;
+ function.prefix.staticType = prefixType;
+ methodElement = resolveTypeProperty(prefixType).getter;
+ } else if (prefixElement is PropertyAccessorElement) {
+ var prefixType = prefixElement.returnType;
+ function.prefix.staticType = prefixType;
+ methodElement = resolveTypeProperty(prefixType).getter;
+ }
+ if (methodElement is MethodElement) {
+ _resolveFunctionReferenceMethod(node: node, function: function);
+ return;
+ }
+
+ // TODO(srawlins): Check for [ConstructorElement] and rewrite to
+ // [ConstructorReference] before resolving.
+ function.accept(_resolver);
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ }
+
+ if (function is PropertyAccess) {
+ function.accept(_resolver);
+ DartType functionType = function.typeOrThrow;
+
+ if (functionType is FunctionType) {
+ _resolve(node: node, rawType: function.staticType as 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;
+ }
+
+ /// 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 FunctionType rawType,
+ }) {
+ // `node.typeArguments`, coming from the parser, is never null.
+ var typeArgumentList = node.typeArguments!;
+ var typeParameters = rawType.typeFormals;
+
+ List<DartType> typeArguments;
+ if (typeArgumentList.arguments.length != typeParameters.length) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS,
+ typeArgumentList,
+ [
+ rawType,
+ typeParameters.length,
+ typeArgumentList.arguments.length,
+ ],
+ );
+ typeArguments = List.filled(
+ typeParameters.length,
+ DynamicTypeImpl.instance,
+ );
+ } else {
+ typeArguments = typeArgumentList.arguments
+ .map((typeArgument) => typeArgument.typeOrThrow)
+ .toList();
+ }
+
+ var invokeType = rawType.instantiate(typeArguments);
+ node.typeArgumentTypes = typeArguments;
+ node.staticType = invokeType;
+
+ // TODO(srawlins): Verify that type arguments conform to bounds. This will
+ // probably be done later, not in this resolution phase.
+ }
+
+ void _resolveFunctionReferenceMethod({
+ required FunctionReferenceImpl node,
+ required PrefixedIdentifier function,
+ }) {
+ function.accept(_resolver);
+ var receiver = function.prefix;
+ var receiverType = receiver.staticType;
+ if (receiverType == null) {
+ // TODO(srawlins): Handle this situation; see
+ // `test_staticMethod_explicitReceiver` test case.
+ node.staticType = DynamicTypeImpl.instance;
+ return;
+ }
+ var nameNode = function.identifier;
+ var name = nameNode.name;
+ var result = _resolver.typePropertyResolver.resolve(
+ receiver: receiver,
+ receiverType: receiverType,
+ name: name,
+ propertyErrorEntity: nameNode,
+ nameErrorEntity: nameNode,
+ );
+
+ var target = result.getter;
+ if (target != null) {
+ // TODO(srawlins): Set static type on `nameNode`?
+
+ _resolve(
+ node: node,
+ rawType: function.staticType as FunctionType,
+ );
+ return;
+ }
+
+ // TODO(srawlins): Report unresolved identifier.
+ node.function.accept(_resolver);
+ node.staticType = DynamicTypeImpl.instance;
+ }
+
+ void _resolveReceiverPrefix(
+ FunctionReferenceImpl node,
+ PrefixElement prefix,
+ SimpleIdentifierImpl nameNode,
+ String name,
+ ) {
+ // TODO(srawlins): Handle `loadLibrary`, as in `p.loadLibrary<int>;`.
+
+ var element = prefix.scope.lookup(name).getter;
+ element = _resolver.toLegacyElement(element);
+ nameNode.staticElement = element;
+
+ if (element is MultiplyDefinedElement) {
+ MultiplyDefinedElement multiply = element;
+ element = multiply.conflictingElements[0];
+
+ // TODO(srawlins): Add a resolution test for this case.
+ }
+
+ if (element is ExecutableElement) {
+ var function = node.function;
+ function.accept(_resolver);
+ return _resolve(
+ node: node, rawType: function.typeOrThrow as FunctionType);
+ }
+
+ // TODO(srawlins): Handle prefixed constructor references and type literals.
+
+ // TODO(srawlins): Report undefined prefixed identifier.
+
+ node.function.accept(_resolver);
+ node.staticType = DynamicTypeImpl.instance;
+ }
+}
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 88b7c38..b6480b1 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -37,6 +37,7 @@
import 'package:analyzer/src/dart/resolver/for_resolver.dart';
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/invocation_inference_helper.dart';
import 'package:analyzer/src/dart/resolver/lexical_lookup.dart';
import 'package:analyzer/src/dart/resolver/method_invocation_resolver.dart';
@@ -263,6 +264,8 @@
/// TODO(scheglov) Stop cloning altogether.
bool shouldCloneAnnotations = true;
+ late final FunctionReferenceResolver _functionReferenceResolver;
+
/// Initialize a newly created visitor to resolve the nodes in an AST node.
///
/// The [definingLibrary] is the element for the library containing the node
@@ -381,6 +384,7 @@
migratableAstInfoProvider: _migratableAstInfoProvider);
inferenceContext = InferenceContext._(this);
typeAnalyzer = StaticTypeAnalyzer(this, migrationResolutionHooks);
+ _functionReferenceResolver = FunctionReferenceResolver(this);
}
/// Return the element representing the function containing the current node,
@@ -1538,6 +1542,11 @@
}
@override
+ void visitFunctionReference(FunctionReference node) {
+ _functionReferenceResolver.resolve(node as FunctionReferenceImpl);
+ }
+
+ @override
void visitFunctionTypeAlias(FunctionTypeAlias node) {
// Resolve the metadata in the library scope.
node.metadata.accept(this);
diff --git a/pkg/analyzer/lib/src/test_utilities/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index 11c7031e..0443c30 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -152,6 +152,10 @@
return _node(search, (n) => n is FunctionExpressionInvocation);
}
+ FunctionReference functionReference(String search) {
+ return _node(search, (n) => n is FunctionReference);
+ }
+
FunctionTypeAlias functionTypeAlias(String search) {
return _node(search, (n) => n is FunctionTypeAlias);
}
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index c6d8019..b545267 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -254,6 +254,7 @@
EnableString.generic_metadata,
EnableString.nonfunction_type_aliases,
EnableString.triple_shift,
+ EnableString.constructor_tearoffs,
];
/// The path that is not in [workspaceRootPath], contains external packages.
@@ -417,7 +418,7 @@
// TODO(https://github.com/dart-lang/sdk/issues/44666): This mixin is a no-op
// on PubPackageResolutionTest; remove its usage and remove it.
@override
- String? get testPackageLanguageVersion => '2.12';
+ String? get testPackageLanguageVersion => '2.14';
@override
bool get typeToStringWithNullability => true;
diff --git a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
new file mode 100644
index 0000000..4dba4a4
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
@@ -0,0 +1,306 @@
+// 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/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(FunctionReferenceResolutionTest);
+ });
+}
+
+@reflectiveTest
+class FunctionReferenceResolutionTest extends PubPackageResolutionTest {
+ test_instanceMethod() async {
+ await assertNoErrorsInCode('''
+class A {
+ void foo<T>(T a) {}
+
+ bar() {
+ foo<int>;
+ }
+}
+''');
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier, findElement.method('foo'));
+ assertType(identifier, 'void Function(int)');
+ }
+
+ test_instanceMethod_explicitReceiver_field() async {
+ await assertNoErrorsInCode('''
+class A {
+ void foo<T>(T a) {}
+}
+
+class B {
+ A a;
+ B(this.a);
+ bar() {
+ a.foo<int>;
+ }
+}
+''');
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier, findElement.method('foo'));
+ assertType(identifier, 'void Function(int)');
+ }
+
+ test_instanceMethod_explicitReceiver_super() async {
+ await assertNoErrorsInCode('''
+class A {
+ void foo<T>(T a) {}
+}
+class B extends A {
+ bar() {
+ super.foo<int>;
+ }
+}
+''');
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier, findElement.method('foo'));
+ assertType(identifier, 'void Function(int)');
+ }
+
+ test_instanceMethod_explicitReceiver_this() async {
+ await assertNoErrorsInCode('''
+class A {
+ void foo<T>(T a) {}
+
+ bar() {
+ this.foo<int>;
+ }
+}
+''');
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier, findElement.method('foo'));
+ assertType(identifier, 'void Function(int)');
+ }
+
+ test_instanceMethod_explicitReceiver_variable() async {
+ await assertNoErrorsInCode('''
+class A {
+ void foo<T>(T a) {}
+}
+
+class B {
+ bar(A a) {
+ a.foo<int>;
+ }
+}
+''');
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier, findElement.method('foo'));
+ assertType(identifier, 'void Function(int)');
+ }
+
+ test_localFunction() async {
+ await assertNoErrorsInCode('''
+void bar() {
+ void foo<T>(T a) {}
+
+ foo<int>;
+}
+''');
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier, findElement.localFunction('foo'));
+ assertType(identifier, 'void Function(int)');
+ }
+
+ test_localVariable() async {
+ await assertNoErrorsInCode('''
+void bar(void Function<T>(T a) foo) {
+ foo<int>;
+}
+''');
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier, findElement.parameter('foo'));
+ assertType(identifier, 'void Function(int)');
+ }
+
+ test_nonGenericFunction() async {
+ await assertErrorsInCode('''
+class A {
+ void foo() {}
+
+ bar() {
+ foo<int>;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 44, 5),
+ ]);
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier, findElement.method('foo'));
+ assertType(identifier, 'void Function()');
+ }
+
+ test_staticMethod() async {
+ await assertNoErrorsInCode('''
+class A {
+ static void foo<T>(T a) {}
+
+ bar() {
+ foo<int>;
+ }
+}
+''');
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier, findElement.method('foo'));
+ assertType(identifier, 'void Function(int)');
+ }
+
+ @FailingTest(reason: 'Unresolved TODO in FunctionReferenceResolver')
+ test_staticMethod_explicitReceiver() async {
+ await assertNoErrorsInCode('''
+class A {
+ static void foo<T>(T a) {}
+
+ bar() {
+ A.foo<int>;
+ }
+}
+''');
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier, findElement.method('foo'));
+ assertType(identifier, 'void Function(int)');
+ }
+
+ @FailingTest(reason: 'Unresolved TODO in FunctionReferenceResolver')
+ test_staticMethod_explicitReceiver_importPrefix() async {
+ newFile('$testPackageLibPath/a.dart', content: '''
+class A {
+ static void foo<T>(T a) {}
+}
+''');
+ await assertNoErrorsInCode('''
+import 'a.dart' as a;
+
+bar() {
+ a.A.foo<int>;
+}
+''');
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier, findElement.method('foo'));
+ assertType(identifier, 'void Function(int)');
+ }
+
+ test_tooFewTypeArguments() async {
+ await assertErrorsInCode('''
+class A {
+ void foo<T, U>(T a, U b) {}
+
+ bar() {
+ foo<int>;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 58, 5),
+ ]);
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier, findElement.method('foo'));
+ assertType(identifier, 'void Function(dynamic, dynamic)');
+ }
+
+ test_tooManyTypeArguments() async {
+ await assertErrorsInCode('''
+class A {
+ void foo<T>(T a) {}
+
+ bar() {
+ foo<int, int>;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 50, 10),
+ ]);
+
+ var identifier = findNode.functionReference('foo<int, int>;');
+ assertElement(identifier, findElement.method('foo'));
+ assertType(identifier, 'void Function(dynamic)');
+ }
+
+ test_topLevelFunction() async {
+ await assertNoErrorsInCode('''
+void foo<T>(T a) {}
+
+void bar() {
+ foo<int>;
+}
+''');
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier, findElement.topFunction('foo'));
+ assertType(identifier, 'void Function(int)');
+ }
+
+ test_topLevelFunction_importPrefix() async {
+ newFile('$testPackageLibPath/a.dart', content: '''
+void foo<T>(T arg) {}
+''');
+ await assertNoErrorsInCode('''
+import 'a.dart' as a;
+
+void bar() {
+ a.foo<int>;
+}
+''');
+
+ var identifier = findNode.functionReference('foo<int>;');
+ assertElement(identifier,
+ findElement.importFind('package:test/a.dart').topFunction('foo'));
+ assertType(identifier, 'void Function(int)');
+ }
+
+ test_unknownIdentifier() async {
+ await assertErrorsInCode('''
+void bar() {
+ foo<int>;
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 15, 3),
+ ]);
+ }
+
+ test_unknownIdentifier_explicitReceiver() async {
+ await assertErrorsInCode('''
+class A {}
+
+class B {
+ bar(A a) {
+ a.foo<int>;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_GETTER, 41, 3),
+ ]);
+ }
+
+ test_unknownIdentifier_importPrefix() async {
+ newFile('$testPackageLibPath/a.dart', content: '');
+ await assertErrorsInCode('''
+import 'a.dart' as a;
+
+void bar() {
+ a.foo<int>;
+}
+''', [
+ error(CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME, 40, 3),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index ca2b79e..2d2415b 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -875,6 +875,15 @@
return node.declaredElement;
} else if (node is FunctionExpressionInvocation) {
return node.staticElement;
+ } else if (node is FunctionReference) {
+ var function = node.function;
+ if (function is Identifier) {
+ return function.staticElement;
+ } else if (function is PropertyAccess) {
+ return function.propertyName.staticElement;
+ } else {
+ fail('Unsupported node: (${node.runtimeType}) $node');
+ }
} else if (node is Identifier) {
return node.staticElement;
} else if (node is IndexExpression) {
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index 7c87fe5..5b1355f 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -23,6 +23,7 @@
import 'function_declaration_test.dart' as function_declaration;
import 'function_expression_invocation_test.dart'
as function_expression_invocation;
+import 'function_reference_test.dart' as function_reference;
import 'function_type_alias_test.dart' as function_type_alias;
import 'generic_function_type_test.dart' as generic_function_type;
import 'generic_type_alias_test.dart' as generic_type_alias;
@@ -82,6 +83,7 @@
for_in.main();
function_declaration.main();
function_expression_invocation.main();
+ function_reference.main();
function_type_alias.main();
generic_function_type.main();
generic_type_alias.main();
diff --git a/pkg/analyzer/test/src/diagnostics/experiment_not_enabled_test.dart b/pkg/analyzer/test/src/diagnostics/experiment_not_enabled_test.dart
index c0ecd09..a305fc4 100644
--- a/pkg/analyzer/test/src/diagnostics/experiment_not_enabled_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/experiment_not_enabled_test.dart
@@ -17,6 +17,7 @@
class ExperimentNotEnabledTest extends PubPackageResolutionTest {
test_constructor_tearoffs_disabled_grammar() async {
await assertErrorsInCode('''
+// @dart = 2.12
class Foo<X> {
const Foo.bar();
int get baz => 0;
@@ -25,7 +26,7 @@
Foo<int>.bar.baz();
}
''', [
- error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 70, 5),
+ error(ParserErrorCode.EXPERIMENT_NOT_ENABLED, 86, 5),
]);
}
diff --git a/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart b/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
index 6754881..b610200 100644
--- a/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/wrong_number_of_type_arguments_test.dart
@@ -93,6 +93,26 @@
]);
}
+ test_functionReference_tooFew() async {
+ await assertErrorsInCode('''
+f(void Function<T, U>() foo) {
+ foo<int>;
+}
+''', [
+ error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 36, 5),
+ ]);
+ }
+
+ test_functionReference_tooMany() async {
+ await assertErrorsInCode('''
+f(void Function<T>() foo) {
+ foo<int, int>;
+}
+''', [
+ error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 33, 10),
+ ]);
+ }
+
test_metadata_1of0() async {
await assertErrorsInCode(r'''
class A {
diff --git a/tools/VERSION b/tools/VERSION
index 7671cdf..d15e618 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 235
+PRERELEASE 236
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/pub_integration_test.py b/tools/bots/pub_integration_test.py
index cef43cc..371ed1a 100755
--- a/tools/bots/pub_integration_test.py
+++ b/tools/bots/pub_integration_test.py
@@ -23,15 +23,21 @@
parser = optparse.OptionParser()
parser.add_option(
'--mode', action='store', dest='mode', type='string', default='release')
+ parser.add_option('--arch',
+ action='store',
+ dest='arch',
+ type='string',
+ default='x64')
(options, args) = parser.parse_args()
- out_dir_subfolder = 'DebugX64' if options.mode == 'debug' else 'ReleaseX64'
+ arch = 'XARM64' if options.arch == 'arm64' else 'X64'
+ mode = ('Debug' if options.mode == 'debug' else 'Release')
out_dir = 'xcodebuild' if sys.platform == 'darwin' else 'out'
extension = '' if not sys.platform == 'win32' else '.bat'
- pub = os.path.abspath(
- '%s/%s/dart-sdk/bin/pub%s' % (out_dir, out_dir_subfolder, extension))
+ pub = os.path.abspath('%s/%s%s/dart-sdk/bin/pub%s' %
+ (out_dir, mode, arch, extension))
print(pub)
working_dir = tempfile.mkdtemp()
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index b3e5e99..29fe236 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -3503,7 +3503,8 @@
"name": "pub integration tests",
"script": "tools/bots/pub_integration_test.py",
"arguments": [
- "--mode=release"
+ "--mode=release",
+ "--arch=arm64"
]
}
]