Skip to content

Commit 16e1a5b

Browse files
munificentCommit Queue
authored andcommitted
[private named parameters] Update compile errors
Change how the parser reports errors for named parameters that start with `_` in anticipation of supporting private named parameters. With "private named parameters" some private named parameters are errors and some aren't. It's still an error to have a private named parameter that doesn't refer to a field. This updates the error reporting to implement that. It also consolidates the error reporting into the parser. Prior to this CL, analyzer would discard the parser's private named parameter errors and then re-detect and report them itself. The errors you get now when the experiment is off are: * If the parameter doesn't refer to a field, you get the old error that you can't have a private named parameter. * If the parameter does refer to a field, you get an error telling you to enable the experiment. When the experiment ships, this changes to an error about updating the library's language version. And when the experiment is on: * If the parameter doesn't refer to a field, you get a new error that you can't have a private named parameter unless it refers to a field. * If the parameter does refer to a field, it reports no error. It doesn't actually support private named parameters that refer to fields yet. Let me know what I got wrong. It was a little tricky to figure out how it should behave when the experiment is off. One option is to have no user-visible changes in behavior at all when the experiment is off. So the feature is fully hidden behind the experiment. But most other code I saw seems to take an approach where if the feature is off, it acknowledges the existence of the feature but tells the user it's disabled. I went with this approach but I don't know if that's something we should only do when it's closer to shipping. Change-Id: I0fc4e9b06c8e7f0abc868e0f49d2b3e625c8dade Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/456540 Auto-Submit: Bob Nystrom <[email protected]> Reviewed-by: Konstantin Shcheglov <[email protected]> Reviewed-by: Phil Quitslund <[email protected]> Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Phil Quitslund <[email protected]>
1 parent 24e89ca commit 16e1a5b

File tree

36 files changed

+566
-106
lines changed

36 files changed

+566
-106
lines changed

pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2684,6 +2684,14 @@ const MessageCode codePrefixAfterCombinator = const MessageCode(
26842684
correctionMessage: """Try moving the prefix before the combinators.""",
26852685
);
26862686

2687+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2688+
const MessageCode codePrivateNamedNonFieldParameter = const MessageCode(
2689+
"PrivateNamedNonFieldParameter",
2690+
pseudoSharedCode: PseudoSharedCode.privateNamedNonFieldParameter,
2691+
problemMessage:
2692+
"""A named parameter that doesn't refer to an instance variable can't start with an underscore ('_').""",
2693+
);
2694+
26872695
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
26882696
const MessageCode codePrivateNamedParameter = const MessageCode(
26892697
"PrivateNamedParameter",
@@ -3203,6 +3211,7 @@ enum PseudoSharedCode {
32033211
nonSyncAbstractMethod,
32043212
nonSyncFactory,
32053213
positionalAfterNamedArgument,
3214+
privateNamedNonFieldParameter,
32063215
privateOptionalParameter,
32073216
returnInGenerator,
32083217
setOrMapLiteralTooManyTypeArguments,

pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,9 @@ class Parser {
328328
/// `true` if the 'declaring-constructors' feature is enabled.
329329
final bool _isDeclaringConstructorsFeatureEnabled;
330330

331+
/// `true` if the 'private-named-parameters' feature is enabled.
332+
final bool _isPrivateNamedParametersEnabled;
333+
331334
/// Indicates whether the last pattern parsed is allowed inside unary
332335
/// patterns. This is set by [parsePrimaryPattern] and [parsePattern].
333336
///
@@ -352,7 +355,9 @@ class Parser {
352355
_isEnhancedPartsFeatureEnabled = experimentalFeatures
353356
.isExperimentEnabled(ExperimentalFlag.enhancedParts),
354357
_isDeclaringConstructorsFeatureEnabled = experimentalFeatures
355-
.isExperimentEnabled(ExperimentalFlag.declaringConstructors);
358+
.isExperimentEnabled(ExperimentalFlag.declaringConstructors),
359+
_isPrivateNamedParametersEnabled = experimentalFeatures
360+
.isExperimentEnabled(ExperimentalFlag.privateNamedParameters);
356361

357362
/// Executes [callback]; however if `this` is the `TestParser` (from
358363
/// `pkg/front_end/test/parser_test_parser.dart`) then no output is printed
@@ -2300,7 +2305,29 @@ class Parser {
23002305
} else {
23012306
nameToken = token = ensureIdentifier(token, nameContext);
23022307
if (isNamedParameter && nameToken.lexeme.startsWith("_")) {
2303-
reportRecoverableError(nameToken, codes.codePrivateNamedParameter);
2308+
// TODO(rnystrom): Also handle declaring field parameters.
2309+
bool refersToField = thisKeyword != null;
2310+
2311+
if (_isPrivateNamedParametersEnabled) {
2312+
if (!refersToField) {
2313+
reportRecoverableError(
2314+
nameToken,
2315+
codes.codePrivateNamedNonFieldParameter,
2316+
);
2317+
}
2318+
} else {
2319+
if (!refersToField) {
2320+
reportRecoverableError(nameToken, codes.codePrivateNamedParameter);
2321+
} else {
2322+
// The user is using syntax that is now meaningful, but in a
2323+
// library where it isn't enabled, so report a more precise error.
2324+
reportExperimentNotEnabled(
2325+
ExperimentalFlag.privateNamedParameters,
2326+
nameToken,
2327+
nameToken,
2328+
);
2329+
}
2330+
}
23042331
}
23052332
}
23062333
if (endInlineFunctionType != null) {

pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,10 +1378,6 @@ CompileTimeErrorCode.PREFIX_SHADOWED_BY_LOCAL_DECLARATION:
13781378
status: noFix
13791379
CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION:
13801380
status: noFix
1381-
CompileTimeErrorCode.PRIVATE_OPTIONAL_PARAMETER:
1382-
status: needsFix
1383-
notes: |-
1384-
Remove the underscore
13851381
CompileTimeErrorCode.PRIVATE_SETTER:
13861382
status: noFix
13871383
CompileTimeErrorCode.READ_POTENTIALLY_UNASSIGNED_FINAL:
@@ -3221,6 +3217,12 @@ ParserErrorCode.PREFIX_AFTER_COMBINATOR:
32213217
status: needsFix
32223218
notes: |-
32233219
Move the prefix before the combinators.
3220+
ParserErrorCode.PRIVATE_OPTIONAL_PARAMETER:
3221+
status: needsFix
3222+
notes: |-
3223+
Remove the underscore
3224+
ParserErrorCode.PRIVATE_NAMED_NON_FIELD_PARAMETER:
3225+
status: needsEvaluation
32243226
ParserErrorCode.RECORD_LITERAL_ONE_POSITIONAL_NO_TRAILING_COMMA:
32253227
status: hasFix
32263228
ParserErrorCode.RECORD_TYPE_ONE_POSITIONAL_NO_TRAILING_COMMA:

pkg/analysis_server/test/src/services/correction/fix/remove_ignored_diagnostic_test.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,12 +165,12 @@ class C {
165165
Future<void> test_line_first_leading_and_eol() async {
166166
await resolveTestCode('''
167167
class C {
168-
// ignore: private_optional_parameter
168+
// ignore: private_named_non_field_parameter
169169
int f({required _a}) => null; // ignore: unused_local_variable, return_of_invalid_type
170170
}''');
171171
await assertHasFix('''
172172
class C {
173-
// ignore: private_optional_parameter
173+
// ignore: private_named_non_field_parameter
174174
int f({required _a}) => null; // ignore: return_of_invalid_type
175175
}''');
176176
}

pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2298,6 +2298,24 @@ class ParserErrorCode extends DiagnosticCodeWithExpectedTypes {
22982298
expectedTypes: [],
22992299
);
23002300

2301+
/// No parameters.
2302+
static const ParserErrorWithoutArguments
2303+
privateNamedNonFieldParameter = ParserErrorWithoutArguments(
2304+
'PRIVATE_NAMED_NON_FIELD_PARAMETER',
2305+
"Named parameters that don't refer to instance variables can't start with "
2306+
"underscore.",
2307+
expectedTypes: [],
2308+
);
2309+
2310+
/// No parameters.
2311+
static const ParserErrorWithoutArguments privateOptionalParameter =
2312+
ParserErrorWithoutArguments(
2313+
'PRIVATE_OPTIONAL_PARAMETER',
2314+
"Named parameters can't start with an underscore.",
2315+
hasPublishedDocs: true,
2316+
expectedTypes: [],
2317+
);
2318+
23012319
/// No parameters.
23022320
static const ParserErrorWithoutArguments
23032321
recordLiteralOnePositionalNoTrailingComma = ParserErrorWithoutArguments(

pkg/analyzer/lib/src/diagnostic/diagnostic_code_values.g.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,6 @@ const List<DiagnosticCode> diagnosticCodeValues = [
463463
CompileTimeErrorCode.prefixIdentifierNotFollowedByDot,
464464
CompileTimeErrorCode.prefixShadowedByLocalDeclaration,
465465
CompileTimeErrorCode.privateCollisionInMixinApplication,
466-
CompileTimeErrorCode.privateOptionalParameter,
467466
CompileTimeErrorCode.privateSetter,
468467
CompileTimeErrorCode.readPotentiallyUnassignedFinal,
469468
CompileTimeErrorCode.recordLiteralOnePositionalNoTrailingCommaByType,
@@ -875,6 +874,8 @@ const List<DiagnosticCode> diagnosticCodeValues = [
875874
ParserErrorCode.positionalAfterNamedArgument,
876875
ParserErrorCode.positionalParameterOutsideGroup,
877876
ParserErrorCode.prefixAfterCombinator,
877+
ParserErrorCode.privateNamedNonFieldParameter,
878+
ParserErrorCode.privateOptionalParameter,
878879
ParserErrorCode.recordLiteralOnePositionalNoTrailingComma,
879880
ParserErrorCode.recordTypeOnePositionalNoTrailingComma,
880881
ParserErrorCode.redirectingConstructorWithBody,

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

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6065,15 +6065,6 @@ class CompileTimeErrorCode extends DiagnosticCodeWithExpectedTypes {
60656065
],
60666066
);
60676067

6068-
/// No parameters.
6069-
static const CompileTimeErrorWithoutArguments privateOptionalParameter =
6070-
CompileTimeErrorWithoutArguments(
6071-
'PRIVATE_OPTIONAL_PARAMETER',
6072-
"Named parameters can't start with an underscore.",
6073-
hasPublishedDocs: true,
6074-
expectedTypes: [],
6075-
);
6076-
60776068
/// Parameters:
60786069
/// String p0: the name of the setter
60796070
static const CompileTimeErrorTemplate<

pkg/analyzer/lib/src/fasta/error_converter.dart

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,18 @@ class FastaErrorReporter {
333333
// Reported by [ErrorVerifier._checkForBuiltInIdentifierAsName].
334334
return;
335335
case PseudoSharedCode.privateOptionalParameter:
336-
// Reported by [ErrorVerifier._checkForPrivateOptionalParameter].
336+
diagnosticReporter?.atOffset(
337+
offset: offset,
338+
length: length,
339+
diagnosticCode: ParserErrorCode.privateOptionalParameter,
340+
);
341+
return;
342+
case PseudoSharedCode.privateNamedNonFieldParameter:
343+
diagnosticReporter?.atOffset(
344+
offset: offset,
345+
length: length,
346+
diagnosticCode: ParserErrorCode.privateNamedNonFieldParameter,
347+
);
337348
return;
338349
case PseudoSharedCode.nonSyncAbstractMethod:
339350
// Not reported but followed by a MISSING_FUNCTION_BODY error.

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

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -930,7 +930,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
930930
@override
931931
void visitFieldFormalParameter(FieldFormalParameter node) {
932932
_checkForValidField(node);
933-
_checkForPrivateOptionalParameter(node);
934933
_checkForFieldInitializingFormalRedirectingConstructor(node);
935934
_checkForTypeAnnotationDeferredClass(node.type);
936935
var fieldElement = node.declaredFragment?.element.field;
@@ -1456,7 +1455,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
14561455

14571456
@override
14581457
void visitSimpleFormalParameter(SimpleFormalParameter node) {
1459-
_checkForPrivateOptionalParameter(node);
14601458
_checkForTypeAnnotationDeferredClass(node.type);
14611459
super.visitSimpleFormalParameter(node);
14621460
}
@@ -4958,24 +4956,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void>
49584956
}
49594957
}
49604958

4961-
/// Check that the given named optional [parameter] does not begin with '_'.
4962-
void _checkForPrivateOptionalParameter(FormalParameter parameter) {
4963-
// should be named parameter
4964-
if (!parameter.isNamed) {
4965-
return;
4966-
}
4967-
// name should start with '_'
4968-
var name = parameter.name;
4969-
if (name == null || name.isSynthetic || !name.lexeme.startsWith('_')) {
4970-
return;
4971-
}
4972-
4973-
diagnosticReporter.atToken(
4974-
name,
4975-
CompileTimeErrorCode.privateOptionalParameter,
4976-
);
4977-
}
4978-
49794959
/// Check whether the given constructor [declaration] is the redirecting
49804960
/// generative constructor and references itself directly or indirectly. The
49814961
/// [constructorElement] is the constructor element.

pkg/analyzer/messages.yaml

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -13901,36 +13901,6 @@ CompileTimeErrorCode:
1390113901

1390213902
If you need both of the mixins, then rename the conflicting member in one
1390313903
of the two mixins.
13904-
PRIVATE_OPTIONAL_PARAMETER:
13905-
parameters: none
13906-
problemMessage: "Named parameters can't start with an underscore."
13907-
hasPublishedDocs: true
13908-
documentation: |-
13909-
#### Description
13910-
13911-
The analyzer produces this diagnostic when the name of a named parameter
13912-
starts with an underscore.
13913-
13914-
#### Example
13915-
13916-
The following code produces this diagnostic because the named parameter
13917-
`_x` starts with an underscore:
13918-
13919-
```dart
13920-
class C {
13921-
void m({int [!_x!] = 0}) {}
13922-
}
13923-
```
13924-
13925-
#### Common fixes
13926-
13927-
Rename the parameter so that it doesn't start with an underscore:
13928-
13929-
```dart
13930-
class C {
13931-
void m({int x = 0}) {}
13932-
}
13933-
```
1393413904
PRIVATE_SETTER:
1393513905
parameters:
1393613906
String p0: the name of the setter
@@ -21788,6 +21758,69 @@ ParserErrorCode:
2178821758
problemMessage: "Positional parameters must be enclosed in square brackets ('[' and ']')."
2178921759
correctionMessage: Try surrounding the positional parameters in square brackets.
2179021760
hasPublishedDocs: false
21761+
PRIVATE_OPTIONAL_PARAMETER:
21762+
parameters: none
21763+
problemMessage: "Named parameters can't start with an underscore."
21764+
hasPublishedDocs: true
21765+
documentation: |-
21766+
#### Description
21767+
21768+
The analyzer produces this diagnostic when the name of a named parameter
21769+
starts with an underscore.
21770+
21771+
#### Example
21772+
21773+
The following code produces this diagnostic because the named parameter
21774+
`_x` starts with an underscore:
21775+
21776+
```dart
21777+
class C {
21778+
void m({int [!_x!] = 0}) {}
21779+
}
21780+
```
21781+
21782+
#### Common fixes
21783+
21784+
Rename the parameter so that it doesn't start with an underscore:
21785+
21786+
```dart
21787+
class C {
21788+
void m({int x = 0}) {}
21789+
}
21790+
```
21791+
PRIVATE_NAMED_NON_FIELD_PARAMETER:
21792+
parameters: none
21793+
problemMessage: "Named parameters that don't refer to instance variables can't start with underscore."
21794+
hasPublishedDocs: false
21795+
documentation: |-
21796+
#### Description
21797+
21798+
The analyzer produces this diagnostic when the name of a named parameter
21799+
starts with an underscore and the parameter isn't an initializing formal
21800+
or field parameter.
21801+
21802+
#### Example
21803+
21804+
The following code produces this diagnostic because the named parameter
21805+
`_x` starts with an underscore:
21806+
21807+
```dart
21808+
class C {
21809+
C({int [!_x!] = 0});
21810+
}
21811+
```
21812+
21813+
#### Common fixes
21814+
21815+
Only use a private named parameter when it refers to a field:
21816+
21817+
```dart
21818+
class C {
21819+
final int _x;
21820+
C({this._x = 0});
21821+
int get x => _x;
21822+
}
21823+
```
2179121824
REPRESENTATION_FIELD_MODIFIER:
2179221825
parameters: none
2179321826
problemMessage: "Representation fields can't have modifiers."

0 commit comments

Comments
 (0)