Skip to content

Commit c3669f7

Browse files
bwilkersoncommit-bot@chromium.org
authored andcommitted
Add a diagnostic for missing arguments associated with required named parameters
Change-Id: I78a46a41ae1c361da0995bb851414e19ef375477 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/100632 Commit-Queue: Brian Wilkerson <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]>
1 parent f3b6028 commit c3669f7

File tree

5 files changed

+236
-44
lines changed

5 files changed

+236
-44
lines changed

pkg/analyzer/lib/dart/ast/resolution_map.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import 'package:analyzer/dart/element/type.dart';
1010
/// AST to elements and types in the element model.
1111
///
1212
/// Clients should not extend, implement or mix-in this class.
13+
// TODO(brianwilkerson) This was added for unifying with the front_end, and is
14+
// no longer needed. It should be removed.
1315
abstract class ResolutionMap {
1416
/// Return the best element available for the function being invoked at
1517
/// [node]. If resolution was able to find a better element based on type

pkg/analyzer/lib/error/error.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ const List<ErrorCode> errorCodeValues = const [
190190
CompileTimeErrorCode.MISSING_CONST_IN_SET_LITERAL,
191191
CompileTimeErrorCode.MISSING_DART_LIBRARY,
192192
CompileTimeErrorCode.MISSING_DEFAULT_VALUE_FOR_PARAMETER,
193+
CompileTimeErrorCode.MISSING_REQUIRED_PARAM,
193194
CompileTimeErrorCode.MIXIN_APPLICATION_CONCRETE_SUPER_INVOKED_MEMBER_TYPE,
194195
CompileTimeErrorCode.MIXIN_APPLICATION_NOT_IMPLEMENTED_INTERFACE,
195196
CompileTimeErrorCode.MIXIN_APPLICATION_NO_CONCRETE_SUPER_INVOKED_MEMBER,

pkg/analyzer/lib/src/error/codes.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,6 +1707,18 @@ class CompileTimeErrorCode extends ErrorCode {
17071707
correction:
17081708
"Try adding either a default value or the 'required' modifier.");
17091709

1710+
/**
1711+
* It is an error if a named parameter that is marked as being required is
1712+
* not bound to an argument at a call site.
1713+
*
1714+
* Parameters:
1715+
* 0: the name of the parameter
1716+
*/
1717+
static const CompileTimeErrorCode MISSING_REQUIRED_PARAM =
1718+
const CompileTimeErrorCode(
1719+
'MISSING_REQUIRED_PARAM', "The parameter '{0}' is required.",
1720+
correction: "Try adding the required argument.");
1721+
17101722
/**
17111723
* It's a compile-time error to apply a mixin containing super-invocations to
17121724
* a class that doesn't have a concrete implementation of the super-invoked

pkg/analyzer/lib/src/generated/error_verifier.dart

Lines changed: 49 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,8 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
840840
}
841841
_checkForImplicitDynamicInvoke(node);
842842
_checkForNullableDereference(node.function);
843+
_checkForMissingRequiredParam(
844+
node.staticInvokeType, node.argumentList, node);
843845
super.visitFunctionExpressionInvocation(node);
844846
}
845847

@@ -947,6 +949,8 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
947949
_checkForConstOrNewWithAbstractClass(node, typeName, type);
948950
_checkForConstOrNewWithEnum(node, typeName, type);
949951
_checkForConstOrNewWithMixin(node, typeName, type);
952+
_checkForMissingRequiredParam(
953+
node.staticElement?.type, node.argumentList, node.constructorName);
950954
if (_isInConstInstanceCreation) {
951955
_checkForConstWithNonConst(node);
952956
_checkForConstWithUndefinedConstructor(
@@ -1046,6 +1050,8 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
10461050
}
10471051
_checkTypeArguments(node);
10481052
_checkForImplicitDynamicInvoke(node);
1053+
_checkForMissingRequiredParam(
1054+
node.staticInvokeType, node.argumentList, node.methodName);
10491055
if (node.operator?.type != TokenType.QUESTION_PERIOD &&
10501056
methodName.name != 'toString' &&
10511057
methodName.name != 'noSuchMethod') {
@@ -1165,6 +1171,11 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
11651171
@override
11661172
void visitRedirectingConstructorInvocation(
11671173
RedirectingConstructorInvocation node) {
1174+
DartType type =
1175+
resolutionMap.staticElementForConstructorReference(node)?.type;
1176+
if (type != null) {
1177+
_checkForMissingRequiredParam(type, node.argumentList, node);
1178+
}
11681179
_isInConstructorInitializer = true;
11691180
try {
11701181
super.visitRedirectingConstructorInvocation(node);
@@ -1259,6 +1270,11 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
12591270

12601271
@override
12611272
void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
1273+
DartType type =
1274+
resolutionMap.staticElementForConstructorReference(node)?.type;
1275+
if (type != null) {
1276+
_checkForMissingRequiredParam(type, node.argumentList, node);
1277+
}
12621278
_isInConstructorInitializer = true;
12631279
try {
12641280
super.visitSuperConstructorInvocation(node);
@@ -4101,6 +4117,24 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
41014117
}
41024118
}
41034119

4120+
void _checkForMissingRequiredParam(
4121+
DartType type, ArgumentList argumentList, AstNode node) {
4122+
if (type is FunctionType) {
4123+
for (ParameterElement parameter in type.parameters) {
4124+
if (parameter.isRequiredNamed) {
4125+
String parameterName = parameter.name;
4126+
if (!RequiredConstantsComputer._containsNamedExpression(
4127+
argumentList, parameterName)) {
4128+
_errorReporter.reportErrorForNode(
4129+
CompileTimeErrorCode.MISSING_REQUIRED_PARAM,
4130+
node,
4131+
[parameterName]);
4132+
}
4133+
}
4134+
}
4135+
}
4136+
}
4137+
41044138
/**
41054139
* Verify that the given function [body] does not contain return statements
41064140
* that both have and do not have return values.
@@ -5955,14 +5989,14 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
59555989
return result;
59565990
}
59575991

5958-
// Find a method which is overridden by [node] and which is annotated with
5959-
// `@mustCallSuper`.
5960-
//
5961-
// As per the definition of `mustCallSuper` [1], every method which overrides
5962-
// a method annotated with `@mustCallSuper` is implicitly annotated with
5963-
// `@mustCallSuper`.
5964-
//
5965-
// [1] https://pub.dartlang.org/documentation/meta/latest/meta/mustCallSuper-constant.html
5992+
/// Find a method which is overridden by [node] and which is annotated with
5993+
/// `@mustCallSuper`.
5994+
///
5995+
/// As per the definition of `mustCallSuper` [1], every method which overrides
5996+
/// a method annotated with `@mustCallSuper` is implicitly annotated with
5997+
/// `@mustCallSuper`.
5998+
///
5999+
/// [1] https://pub.dartlang.org/documentation/meta/latest/meta/mustCallSuper-constant.html
59666000
MethodElement _findOverriddenMemberThatMustCallSuper(MethodDeclaration node) {
59676001
Element member = node.declaredElement;
59686002
ClassElement classElement = member.enclosingElement;
@@ -6108,7 +6142,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
61086142
return setterParameters[0].type;
61096143
}
61106144

6111-
// Returns whether [node] overrides a concrete method.
6145+
/// Returns whether [node] overrides a concrete method.
61126146
bool _hasConcreteSuperMethod(MethodDeclaration node) {
61136147
ClassElement classElement = node.declaredElement.enclosingElement;
61146148
String name = node.declaredElement.name;
@@ -6499,7 +6533,7 @@ class RequiredConstantsComputer extends RecursiveAstVisitor {
64996533
DartType type, ArgumentList argumentList, AstNode node) {
65006534
if (type is FunctionType) {
65016535
for (ParameterElement parameter in type.parameters) {
6502-
if (parameter.isNamed) {
6536+
if (parameter.isOptionalNamed) {
65036537
ElementAnnotationImpl annotation = _getRequiredAnnotation(parameter);
65046538
if (annotation != null) {
65056539
String parameterName = parameter.name;
@@ -6514,7 +6548,11 @@ class RequiredConstantsComputer extends RecursiveAstVisitor {
65146548
}
65156549
}
65166550

6517-
bool _containsNamedExpression(ArgumentList args, String name) {
6551+
ElementAnnotationImpl _getRequiredAnnotation(ParameterElement param) => param
6552+
.metadata
6553+
.firstWhere((ElementAnnotation e) => e.isRequired, orElse: () => null);
6554+
6555+
static bool _containsNamedExpression(ArgumentList args, String name) {
65186556
NodeList<Expression> arguments = args.arguments;
65196557
for (int i = arguments.length - 1; i >= 0; i--) {
65206558
Expression expression = arguments[i];
@@ -6526,10 +6564,6 @@ class RequiredConstantsComputer extends RecursiveAstVisitor {
65266564
}
65276565
return false;
65286566
}
6529-
6530-
ElementAnnotationImpl _getRequiredAnnotation(ParameterElement param) => param
6531-
.metadata
6532-
.firstWhere((ElementAnnotation e) => e.isRequired, orElse: () => null);
65336567
}
65346568

65356569
class _HasTypedefSelfReferenceVisitor extends GeneralizingElementVisitor<void> {

0 commit comments

Comments
 (0)