diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart index 4bc6cdca1a0..80eebe3b492 100644 --- a/pkg/analyzer/lib/src/generated/resolver.dart +++ b/pkg/analyzer/lib/src/generated/resolver.dart @@ -1045,20 +1045,16 @@ class ResolverVisitor extends ResolverBase with ErrorDetectionHelpers { var callerType = InferenceContext.getContext(node); NodeList arguments = node.arguments; if (callerType is FunctionType) { - Map namedParameterTypes = - callerType.namedParameterTypes; - List normalParameterTypes = callerType.normalParameterTypes; - List optionalParameterTypes = callerType.optionalParameterTypes; - int normalCount = normalParameterTypes.length; - int optionalCount = optionalParameterTypes.length; + var parameters = callerType.parameters; + + var namedParameters = {}; + for (var i = 0; i < parameters.length; i++) { + var parameter = parameters[i]; + if (parameter.isNamed) { + namedParameters[parameter.name] = parameter; + } + } - Iterable positional = - arguments.takeWhile((l) => l is! NamedExpression); - Iterable required = positional.take(normalCount); - Iterable optional = - positional.skip(normalCount).take(optionalCount); - Iterable named = - arguments.skipWhile((l) => l is! NamedExpression); var parent = node.parent; DartType? targetType; Element? methodElement; @@ -1072,28 +1068,29 @@ class ResolverVisitor extends ResolverBase with ErrorDetectionHelpers { //TODO(leafp): Consider using the parameter elements here instead. //TODO(leafp): Make sure that the parameter elements are getting // setup correctly with inference. - int index = 0; - for (Expression argument in required) { - var parameterType = normalParameterTypes[index++]; - if (targetType != null) { - InferenceContext.setType( - argument, - typeSystem.refineNumericInvocationContext( - targetType, methodElement, invocationContext, parameterType)); - } else { - InferenceContext.setType(argument, parameterType); - } - } - index = 0; - for (Expression argument in optional) { - InferenceContext.setType(argument, optionalParameterTypes[index++]); - } - - for (Expression argument in named) { + var positionalParameterIndex = 0; + for (var i = 0; i < arguments.length; i++) { + var argument = arguments[i]; + ParameterElement? parameter; if (argument is NamedExpression) { - var type = namedParameterTypes[argument.name.label.name]; - if (type != null) { - InferenceContext.setType(argument, type); + parameter = namedParameters[argument.name.label.name]; + } else { + while (positionalParameterIndex < parameters.length) { + parameter = parameters[positionalParameterIndex++]; + if (!parameter.isNamed) { + break; + } + } + } + if (parameter != null) { + var parameterType = parameter.type; + if (targetType != null) { + InferenceContext.setType( + argument, + typeSystem.refineNumericInvocationContext(targetType, + methodElement, invocationContext, parameterType)); + } else { + InferenceContext.setType(argument, parameterType); } } } diff --git a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart index feac8048cda..51758009053 100644 --- a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart @@ -305,42 +305,48 @@ main() { test_namedArgument_anywhere() async { await assertNoErrorsInCode(''' -class A { - A(int a, double b, {bool? c, bool? d}); +class A {} +class B {} +class C {} +class D {} + +class X { + X(A a, B b, {C? c, D? d}); } +T g1() => throw 0; +T g2() => throw 0; +T g3() => throw 0; +T g4() => throw 0; + void f() { - A(0, c: true, 1.2, d: true); + X(g1(), c: g3(), g2(), d: g4()); } '''); assertInstanceCreation( - findNode.instanceCreation('A(0'), - findElement.class_('A'), - 'A', + findNode.instanceCreation('X(g'), + findElement.class_('X'), + 'X', ); - assertParameterElement( - findNode.integerLiteral('0'), - findElement.parameter('a'), - ); + var g1 = findNode.methodInvocation('g1()'); + assertType(g1, 'A'); + assertParameterElement(g1, findElement.parameter('a')); - assertParameterElement( - findNode.doubleLiteral('1.2'), - findElement.parameter('b'), - ); + var g2 = findNode.methodInvocation('g2()'); + assertType(g2, 'B'); + assertParameterElement(g2, findElement.parameter('b')); - assertParameterElement( - findNode.namedExpression('c: true'), - findElement.parameter('c'), - ); - assertNamedParameterRef('c: true', 'c'); + var named_g3 = findNode.namedExpression('c: g3()'); + assertType(named_g3.expression, 'C?'); + assertParameterElement(named_g3, findElement.parameter('c')); + assertNamedParameterRef('c:', 'c'); - assertParameterElement( - findNode.namedExpression('d: true'), - findElement.parameter('d'), - ); - assertNamedParameterRef('d: true', 'd'); + var named_g4 = findNode.namedExpression('d: g4()'); + assertType(named_g4.expression, 'D?'); + assertParameterElement(named_g4, findElement.parameter('d')); + assertNamedParameterRef('d:', 'd'); } test_typeAlias_generic_class_generic_named_infer_all() async { diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart index 32d8c5dbc65..c564c0c55d6 100644 --- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart +++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart @@ -2865,40 +2865,46 @@ void f(T a) { test_namedArgument_anywhere() async { await assertNoErrorsInCode(''' -void foo(int a, double b, {bool? c, bool? d}) {} +class A {} +class B {} +class C {} +class D {} + +void foo(A a, B b, {C? c, D? d}) {} + +T g1() => throw 0; +T g2() => throw 0; +T g3() => throw 0; +T g4() => throw 0; void f() { - foo(0, c: true, 1.2, d: true); + foo(g1(), c: g3(), g2(), d: g4()); } '''); assertMethodInvocation( - findNode.methodInvocation('foo(0'), + findNode.methodInvocation('foo(g'), findElement.topFunction('foo'), - 'void Function(int, double, {bool? c, bool? d})', + 'void Function(A, B, {C? c, D? d})', ); - assertParameterElement( - findNode.integerLiteral('0'), - findElement.parameter('a'), - ); + var g1 = findNode.methodInvocation('g1()'); + assertType(g1, 'A'); + assertParameterElement(g1, findElement.parameter('a')); - assertParameterElement( - findNode.doubleLiteral('1.2'), - findElement.parameter('b'), - ); + var g2 = findNode.methodInvocation('g2()'); + assertType(g2, 'B'); + assertParameterElement(g2, findElement.parameter('b')); - assertParameterElement( - findNode.namedExpression('c: true'), - findElement.parameter('c'), - ); - assertNamedParameterRef('c: true', 'c'); + var named_g3 = findNode.namedExpression('c: g3()'); + assertType(named_g3.expression, 'C?'); + assertParameterElement(named_g3, findElement.parameter('c')); + assertNamedParameterRef('c:', 'c'); - assertParameterElement( - findNode.namedExpression('d: true'), - findElement.parameter('d'), - ); - assertNamedParameterRef('d: true', 'd'); + var named_g4 = findNode.namedExpression('d: g4()'); + assertType(named_g4.expression, 'D?'); + assertParameterElement(named_g4, findElement.parameter('d')); + assertNamedParameterRef('d:', 'd'); } test_nullShorting_cascade_firstMethodInvocation() async {