| // 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_explicitReceiver_unknown() async { |
| await assertErrorsInCode(''' |
| bar() { |
| a.foo<int>; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 1), |
| ]); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertType(reference, 'dynamic'); |
| } |
| |
| test_explicitReceiver_unknown_multipleProperties() async { |
| await assertErrorsInCode(''' |
| bar() { |
| a.b.foo<int>; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_IDENTIFIER, 10, 1), |
| ]); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertType(reference, 'dynamic'); |
| } |
| |
| test_instanceGetter_explicitReceiver() async { |
| // This test is here to assert that the resolver does not throw, but in the |
| // future, an error should be reported here as well. |
| await assertNoErrorsInCode(''' |
| class A { |
| int foo = 0; |
| } |
| |
| bar(A a) { |
| a.foo<int>; |
| } |
| '''); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertType(reference, 'dynamic'); |
| } |
| |
| test_instanceMethod() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| void foo<T>(T a) {} |
| |
| bar() { |
| foo<int>; |
| } |
| } |
| '''); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.method('foo'), '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 reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.method('foo'), 'void Function(int)'); |
| } |
| |
| test_instanceMethod_explicitReceiver_otherExpression() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| void foo<T>(T a) {} |
| } |
| |
| void f(A? a, A b) { |
| (a ?? b).foo<int>; |
| } |
| '''); |
| |
| var reference = findNode.functionReference('(a ?? b).foo<int>;'); |
| assertType(reference, '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 reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.method('foo'), 'void Function(int)'); |
| } |
| |
| test_instanceMethod_explicitReceiver_super_noMethod() async { |
| await assertErrorsInCode(''' |
| class A { |
| bar() { |
| super.foo<int>; |
| } |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_SUPER_GETTER, 30, 3), |
| ]); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertType(reference, 'dynamic'); |
| } |
| |
| test_instanceMethod_explicitReceiver_super_noSuper() async { |
| await assertErrorsInCode(''' |
| bar() { |
| super.foo<int>; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, 10, 5), |
| ]); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertType(reference, 'dynamic'); |
| } |
| |
| test_instanceMethod_explicitReceiver_this() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| void foo<T>(T a) {} |
| |
| bar() { |
| this.foo<int>; |
| } |
| } |
| '''); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.method('foo'), 'void Function(int)'); |
| } |
| |
| test_instanceMethod_explicitReceiver_topLevelVariable() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| void foo<T>(T a) {} |
| } |
| var a = A(); |
| |
| void bar() { |
| a.foo<int>; |
| } |
| '''); |
| |
| assertIdentifierTopGetRef(findNode.simple('a.'), 'a'); |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.method('foo'), 'void Function(int)'); |
| } |
| |
| test_instanceMethod_explicitReceiver_topLevelVariable_prefix() async { |
| newFile('$testPackageLibPath/a.dart', content: ''' |
| class A { |
| void foo<T>(T a) {} |
| } |
| var a = A(); |
| '''); |
| await assertNoErrorsInCode(''' |
| import 'a.dart' as prefix; |
| |
| bar() { |
| prefix.a.foo<int>; |
| } |
| '''); |
| |
| assertImportPrefix( |
| findNode.simple('prefix.'), findElement.prefix('prefix')); |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, |
| findElement.importFind('package:test/a.dart').method('foo'), |
| 'void Function(int)'); |
| } |
| |
| test_instanceMethod_explicitReceiver_typeParameter() async { |
| await assertErrorsInCode(''' |
| bar<T>() { |
| T.foo<int>; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 15, 3), |
| ]); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertType(reference, 'dynamic'); |
| } |
| |
| test_instanceMethod_explicitReceiver_variable() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| void foo<T>(T a) {} |
| } |
| |
| bar(A a) { |
| a.foo<int>; |
| } |
| '''); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.method('foo'), 'void Function(int)'); |
| } |
| |
| @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/46635') |
| test_instanceMethod_explicitReceiver_variable_cascade() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| void foo<T>(T a) {} |
| } |
| |
| bar(A a) { |
| a..foo<int>; |
| } |
| '''); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.method('foo'), 'void Function(int)'); |
| } |
| |
| test_instanceMethod_inherited() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| void foo<T>(T a) {} |
| } |
| |
| class B extends A { |
| bar() { |
| foo<int>; |
| } |
| } |
| '''); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.method('foo'), 'void Function(int)'); |
| } |
| |
| test_localFunction() async { |
| await assertNoErrorsInCode(''' |
| void bar() { |
| void foo<T>(T a) {} |
| |
| foo<int>; |
| } |
| '''); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.localFunction('foo'), 'void Function(int)'); |
| } |
| |
| test_localVariable() async { |
| await assertErrorsInCode(''' |
| void bar(void Function<T>(T a) foo) { |
| foo<int>; |
| } |
| ''', [ |
| error( |
| CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 40, 3), |
| ]); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.parameter('foo'), 'void Function(int)'); |
| } |
| |
| test_localVariable_typeVariable() async { |
| await assertErrorsInCode(''' |
| void bar<T extends void Function<U>(U)>(T foo) { |
| foo<int>; |
| } |
| ''', [ |
| error( |
| CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 51, 3), |
| ]); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.parameter('foo'), 'void Function(int)'); |
| } |
| |
| test_nonGenericFunction() async { |
| await assertErrorsInCode(''' |
| class A { |
| void foo() {} |
| |
| bar() { |
| foo<int>; |
| } |
| } |
| ''', [ |
| error( |
| CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 44, 5), |
| ]); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.method('foo'), 'void Function()'); |
| } |
| |
| test_otherExpression() async { |
| await assertErrorsInCode(''' |
| void f(void Function<T>(T a) foo, void Function<T>(T a) bar) { |
| (1 == 2 ? foo : bar)<int>; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 65, |
| 20), |
| ]); |
| |
| var reference = findNode.functionReference('(1 == 2 ? foo : bar)<int>;'); |
| assertType(reference, 'void Function(int)'); |
| } |
| |
| test_otherExpression_wrongNumberOfTypeArguments() async { |
| await assertErrorsInCode(''' |
| void f(void Function<T>(T a) foo, void Function<T>(T a) bar) { |
| (1 == 2 ? foo : bar)<int, String>; |
| } |
| ''', [ |
| error(CompileTimeErrorCode.DISALLOWED_TYPE_INSTANTIATION_EXPRESSION, 65, |
| 20), |
| error( |
| CompileTimeErrorCode |
| .WRONG_NUMBER_OF_TYPE_ARGUMENTS_ANONYMOUS_FUNCTION, |
| 85, |
| 13), |
| ]); |
| |
| var reference = |
| findNode.functionReference('(1 == 2 ? foo : bar)<int, String>;'); |
| assertType(reference, 'void Function(dynamic)'); |
| } |
| |
| test_staticMethod() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| static void foo<T>(T a) {} |
| |
| bar() { |
| foo<int>; |
| } |
| } |
| '''); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.method('foo'), 'void Function(int)'); |
| } |
| |
| test_staticMethod_explicitReceiver() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| static void foo<T>(T a) {} |
| } |
| |
| bar() { |
| A.foo<int>; |
| } |
| '''); |
| |
| assertClassRef(findNode.simple('A.'), findElement.class_('A')); |
| var reference = findNode.functionReference('foo<int>;'); |
| assertElement(reference, findElement.method('foo')); |
| assertType(reference, 'void Function(int)'); |
| } |
| |
| 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>; |
| } |
| '''); |
| |
| assertImportPrefix(findNode.simple('a.A'), findElement.prefix('a')); |
| assertClassRef(findNode.simple('A.'), |
| findElement.importFind('package:test/a.dart').class_('A')); |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, |
| findElement.importFind('package:test/a.dart').method('foo'), |
| 'void Function(int)'); |
| } |
| |
| test_staticMethod_explicitReceiver_prefix_typeAlias() async { |
| newFile('$testPackageLibPath/a.dart', content: ''' |
| class A { |
| static void foo<T>(T a) {} |
| } |
| typedef TA = A; |
| '''); |
| await assertNoErrorsInCode(''' |
| import 'a.dart' as prefix; |
| |
| bar() { |
| prefix.TA.foo<int>; |
| } |
| '''); |
| |
| assertImportPrefix( |
| findNode.simple('prefix.'), findElement.prefix('prefix')); |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, |
| findElement.importFind('package:test/a.dart').method('foo'), |
| 'void Function(int)'); |
| } |
| |
| test_staticMethod_explicitReceiver_typeAlias() async { |
| await assertNoErrorsInCode(''' |
| class A { |
| static void foo<T>(T a) {} |
| } |
| typedef TA = A; |
| |
| bar() { |
| TA.foo<int>; |
| } |
| '''); |
| |
| assertTypeAliasRef(findNode.simple('TA.'), findElement.typeAlias('TA')); |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.method('foo'), 'void Function(int)'); |
| } |
| |
| test_staticMethod_explicitReciver_prefix() async { |
| newFile('$testPackageLibPath/a.dart', content: ''' |
| class A { |
| static void foo<T>(T a) {} |
| } |
| '''); |
| await assertNoErrorsInCode(''' |
| import 'a.dart' as prefix; |
| |
| bar() { |
| prefix.A.foo<int>; |
| } |
| '''); |
| |
| assertImportPrefix( |
| findNode.simple('prefix.'), findElement.prefix('prefix')); |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, |
| findElement.importFind('package:test/a.dart').method('foo'), |
| '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_FUNCTION, 58, 5), |
| ]); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference(reference, findElement.method('foo'), |
| '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_FUNCTION, 50, 10), |
| ]); |
| |
| var reference = findNode.functionReference('foo<int, int>;'); |
| assertFunctionReference( |
| reference, findElement.method('foo'), 'void Function(dynamic)'); |
| } |
| |
| test_topLevelFunction() async { |
| await assertNoErrorsInCode(''' |
| void foo<T>(T a) {} |
| |
| void bar() { |
| foo<int>; |
| } |
| '''); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, findElement.topFunction('foo'), '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>; |
| } |
| '''); |
| |
| assertImportPrefix(findNode.simple('a.f'), findElement.prefix('a')); |
| var reference = findNode.functionReference('foo<int>;'); |
| assertFunctionReference( |
| reference, |
| findElement.importFind('package:test/a.dart').topFunction('foo'), |
| 'void Function(int)', |
| ); |
| } |
| |
| test_typeAlias_function_unknownProperty() async { |
| await assertErrorsInCode(''' |
| typedef Cb = void Function(); |
| |
| var a = Cb.foo<int>; |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 42, 3), |
| ]); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertType(reference, 'dynamic'); |
| } |
| |
| test_typeAlias_typeVariable_unknownProperty() async { |
| await assertErrorsInCode(''' |
| typedef T<E> = E; |
| |
| var a = T.foo<int>; |
| ''', [ |
| error(CompileTimeErrorCode.UNDEFINED_GETTER, 29, 3), |
| ]); |
| |
| var reference = findNode.functionReference('foo<int>;'); |
| assertType(reference, 'dynamic'); |
| } |
| |
| 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), |
| ]); |
| } |
| } |