Report MAIN_HAS_MORE_THAN_TWO_REQUIRED_POSITIONAL_PARAMETERS and MAIN_HAS_REQUIRED_NAMED_PARAMETER.

Bug: https://github.com/dart-lang/sdk/issues/43559
Change-Id: If74634187d411c0b008133b59c1c3e23e87319c3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/166309
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Konstantin Shcheglov 2020-10-08 00:05:16 +00:00 committed by commit-bot@chromium.org
parent 4d7714174e
commit 103465c90c
7 changed files with 195 additions and 1 deletions

View file

@ -260,6 +260,8 @@ const List<ErrorCode> errorCodeValues = [
CompileTimeErrorCode.LATE_FINAL_FIELD_WITH_CONST_CONSTRUCTOR,
CompileTimeErrorCode.LATE_FINAL_LOCAL_ALREADY_ASSIGNED,
CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE,
CompileTimeErrorCode.MAIN_HAS_REQUIRED_NAMED_PARAMETERS,
CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS,
CompileTimeErrorCode.MAIN_IS_NOT_FUNCTION,
CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP,
CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,

View file

@ -5460,6 +5460,22 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
"The element type '{0}' can't be assigned to the list type '{1}'.",
hasPublishedDocs: true);
static const CompileTimeErrorCode
MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS = CompileTimeErrorCode(
'MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS',
"The function 'main' can't have more than two required positional parameters.",
correction: "Try using a different name for the function, "
"or removing extra parameters.",
);
static const CompileTimeErrorCode MAIN_HAS_REQUIRED_NAMED_PARAMETERS =
CompileTimeErrorCode(
'MAIN_HAS_REQUIRED_NAMED_PARAMETERS',
"The function 'main' can't have any required named parameters.",
correction: "Try using a different name for the function, "
"or removing the 'required' modifier.",
);
static const CompileTimeErrorCode MAIN_IS_NOT_FUNCTION = CompileTimeErrorCode(
'MAIN_IS_NOT_FUNCTION',
"The declaration named 'main' must be a function.",

View file

@ -3127,6 +3127,24 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
);
return;
}
var parameters = (element as FunctionElement).parameters;
var requiredPositional =
parameters.where((e) => e.isRequiredPositional).toList();
if (requiredPositional.length > 2) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS,
nameNode,
);
}
if (parameters.any((e) => e.isRequiredNamed)) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.MAIN_HAS_REQUIRED_NAMED_PARAMETERS,
nameNode,
);
}
}
void _checkForMapTypeNotAssignable(SetOrMapLiteral literal) {

View file

@ -322,7 +322,7 @@ main(int? a, int b) {
test_parameter_interfaceType_generic() async {
await assertNoErrorsInCode('''
main(List<int?>? a, List<int>? b, List<int?> c, List<int> d) {
void f(List<int?>? a, List<int>? b, List<int?> c, List<int> d) {
}
''');

View file

@ -0,0 +1,41 @@
// Copyright (c) 2020, 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 '../dart/resolution/context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(MainHasRequiredNamedParametersTest);
defineReflectiveTests(MainHasRequiredNamedParametersWithNullSafetyTest);
});
}
@reflectiveTest
class MainHasRequiredNamedParametersTest extends PubPackageResolutionTest
with MainHasRequiredNamedParametersTestCases {}
mixin MainHasRequiredNamedParametersTestCases on PubPackageResolutionTest {
test_namedOptional() async {
await resolveTestCode('''
void main({int a = 0}) {}
''');
assertNoErrorsInResult();
}
}
@reflectiveTest
class MainHasRequiredNamedParametersWithNullSafetyTest
extends PubPackageResolutionTest
with WithNullSafetyMixin, MainHasRequiredNamedParametersTestCases {
test_namedRequired() async {
await assertErrorsInCode('''
void main({required List<String> a}) {}
''', [
error(CompileTimeErrorCode.MAIN_HAS_REQUIRED_NAMED_PARAMETERS, 5, 4),
]);
}
}

View file

@ -0,0 +1,111 @@
// Copyright (c) 2020, 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 '../dart/resolution/context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(MainHasTooManyRequiredPositionalParametersTest);
defineReflectiveTests(
MainHasTooManyRequiredPositionalParametersWithNullSafetyTest,
);
});
}
@reflectiveTest
class MainHasTooManyRequiredPositionalParametersTest
extends PubPackageResolutionTest
with MainHasTooManyRequiredPositionalParametersTestCases {}
mixin MainHasTooManyRequiredPositionalParametersTestCases
on PubPackageResolutionTest {
test_namedOptional_1() async {
await resolveTestCode('''
void main({int a = 0}) {}
''');
assertNoErrorsInResult();
}
test_positionalOptional_1() async {
await resolveTestCode('''
void main([int a = 0]) {}
''');
assertNoErrorsInResult();
}
test_positionalRequired_0() async {
await resolveTestCode('''
void main() {}
''');
assertNoErrorsInResult();
}
test_positionalRequired_1() async {
await resolveTestCode('''
void main(args) {}
''');
assertNoErrorsInResult();
}
test_positionalRequired_2() async {
await resolveTestCode('''
void main(args, int a) {}
''');
assertNoErrorsInResult();
}
test_positionalRequired_2_positionalOptional_1() async {
await resolveTestCode('''
void main(args, int a, [int b = 0]) {}
''');
assertNoErrorsInResult();
}
test_positionalRequired_3() async {
await resolveTestCode('''
void main(args, int a, int b) {}
''');
assertErrorsInResult(expectedErrorsByNullability(nullable: [
error(
CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS,
5,
4),
], legacy: []));
}
test_positionalRequired_3_namedOptional_1() async {
await resolveTestCode('''
void main(args, int a, int b, {int c = 0}) {}
''');
assertErrorsInResult(expectedErrorsByNullability(nullable: [
error(
CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS,
5,
4),
], legacy: []));
}
}
@reflectiveTest
class MainHasTooManyRequiredPositionalParametersWithNullSafetyTest
extends PubPackageResolutionTest
with
WithNullSafetyMixin,
MainHasTooManyRequiredPositionalParametersTestCases {
test_positionalRequired_3_namedRequired_1() async {
await resolveTestCode('''
void main(args, int a, int b, {required int c}) {}
''');
assertErrorsInResult(expectedErrorsByNullability(nullable: [
error(CompileTimeErrorCode.MAIN_HAS_REQUIRED_NAMED_PARAMETERS, 5, 4),
error(
CompileTimeErrorCode.MAIN_HAS_TOO_MANY_REQUIRED_POSITIONAL_PARAMETERS,
5,
4),
], legacy: []));
}
}

View file

@ -344,6 +344,10 @@ import 'late_final_local_already_assigned_test.dart'
as late_final_local_already_assigned;
import 'list_element_type_not_assignable_test.dart'
as list_element_type_not_assignable;
import 'main_has_required_named_parameters_test.dart'
as main_has_required_named_parameters;
import 'main_has_too_many_required_positional_parameters_test.dart'
as main_has_too_many_required_positional_parameters;
import 'main_is_not_function_test.dart' as main_is_not_function;
import 'map_entry_not_in_map_test.dart' as map_entry_not_in_map;
import 'map_key_type_not_assignable_test.dart' as map_key_type_not_assignable;
@ -873,6 +877,8 @@ main() {
late_final_field_with_const_constructor.main();
late_final_local_already_assigned.main();
list_element_type_not_assignable.main();
main_has_required_named_parameters.main();
main_has_too_many_required_positional_parameters.main();
main_is_not_function.main();
map_entry_not_in_map.main();
map_key_type_not_assignable.main();