forward "required" modifier to parser listeners
... and have each report an error by default
Change-Id: If818a7bb207becbed95a97890632a1803917d285
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99720
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 22634cd..8d57aea 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -169,11 +169,12 @@
}
@override
- void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
- Token varFinalOrConst) {
+ void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+ Token covariantToken, Token varFinalOrConst) {
push(new _Modifiers()
..covariantKeyword = covariantToken
- ..finalConstOrVarKeyword = varFinalOrConst);
+ ..finalConstOrVarKeyword = varFinalOrConst
+ ..requiredToken = requiredToken);
}
@override
@@ -791,6 +792,9 @@
_Modifiers modifiers = pop();
Token keyword = modifiers?.finalConstOrVarKeyword;
Token covariantKeyword = modifiers?.covariantKeyword;
+ Token requiredKeyword = modifiers?.requiredToken;
+ // TODO(danrubel): handle required token
+ reportNonNullableModifierError(requiredKeyword);
List<Annotation> metadata = pop();
Comment comment = _findComment(metadata,
thisKeyword ?? typeOrFunctionTypedParameter?.beginToken ?? nameToken);
@@ -3291,34 +3295,7 @@
Token finalConstOrVarKeyword;
Token staticKeyword;
Token covariantKeyword;
-
- _Modifiers([List<Token> modifierTokens]) {
- // No need to check the order and uniqueness of the modifiers, or that
- // disallowed modifiers are not used; the parser should do that.
- // TODO(paulberry,ahe): implement the necessary logic in the parser.
- if (modifierTokens != null) {
- for (var token in modifierTokens) {
- var s = token.lexeme;
- if (identical('abstract', s)) {
- abstractKeyword = token;
- } else if (identical('const', s)) {
- finalConstOrVarKeyword = token;
- } else if (identical('external', s)) {
- externalKeyword = token;
- } else if (identical('final', s)) {
- finalConstOrVarKeyword = token;
- } else if (identical('static', s)) {
- staticKeyword = token;
- } else if (identical('var', s)) {
- finalConstOrVarKeyword = token;
- } else if (identical('covariant', s)) {
- covariantKeyword = token;
- } else {
- unhandled("$s", "modifier", token.charOffset, null);
- }
- }
- }
- }
+ Token requiredToken;
/// Return the token that is lexically first.
Token get beginToken {
@@ -3328,7 +3305,8 @@
externalKeyword,
finalConstOrVarKeyword,
staticKeyword,
- covariantKeyword
+ covariantKeyword,
+ requiredToken,
]) {
if (firstToken == null) {
firstToken = token;
diff --git a/pkg/analyzer/test/generated/parser_fasta_listener.dart b/pkg/analyzer/test/generated/parser_fasta_listener.dart
index 45b0b61..bab6fa6 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -244,9 +244,10 @@
}
@override
- void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
- Token varFinalOrConst) {
- super.beginFormalParameter(token, kind, covariantToken, varFinalOrConst);
+ void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+ Token covariantToken, Token varFinalOrConst) {
+ super.beginFormalParameter(
+ token, kind, requiredToken, covariantToken, varFinalOrConst);
begin('FormalParameter');
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 0430c9d..a74cb99 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -2862,8 +2862,10 @@
}
@override
- void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
- Token varFinalOrConst) {
+ void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+ Token covariantToken, Token varFinalOrConst) {
+ // TODO(danrubel): handle required token
+ reportNonNullableModifierError(requiredToken);
push((covariantToken != null ? covariantMask : 0) |
Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme));
}
diff --git a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
index b63af14..02f42fc 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -172,10 +172,10 @@
}
@override
- void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
- Token varFinalOrConst) {
+ void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+ Token covariantToken, Token varFinalOrConst) {
listener?.beginFormalParameter(
- token, kind, covariantToken, varFinalOrConst);
+ token, kind, requiredToken, covariantToken, varFinalOrConst);
}
@override
@@ -1471,6 +1471,11 @@
}
@override
+ void reportNonNullableModifierError(Token modifierToken) {
+ listener?.reportNonNullableModifierError(modifierToken);
+ }
+
+ @override
set suppressParseErrors(bool value) {
listener?.suppressParseErrors = value;
}
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index 9cc581a..78c1ee5 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -272,8 +272,8 @@
logEvent("FactoryMethod");
}
- void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
- Token varFinalOrConst) {}
+ void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+ Token covariantToken, Token varFinalOrConst) {}
void endFormalParameter(Token thisKeyword, Token periodAfterThis,
Token nameToken, FormalParameterKind kind, MemberKind memberKind) {
@@ -968,6 +968,17 @@
}
// TODO(danrubel): Remove this once all listeners have been updated
+ // to properly handle nullable types
+ void reportNonNullableModifierError(Token modifierToken) {
+ if (modifierToken != null) {
+ handleRecoverableError(
+ templateExperimentNotEnabled.withArguments('non-nullable'),
+ modifierToken,
+ modifierToken);
+ }
+ }
+
+ // TODO(danrubel): Remove this once all listeners have been updated
// to properly handle non-null assert expressions
void reportNonNullAssertExpressionNotEnabled(Token bang) {
handleRecoverableError(
diff --git a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
index 0a40ae5..8d8a225 100644
--- a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
@@ -4,6 +4,7 @@
import '../../scanner/token.dart' show Token;
import '../messages.dart' as fasta;
+import 'formal_parameter_kind.dart';
import 'member_kind.dart' show MemberKind;
import 'parser.dart' show Parser;
import 'util.dart' show optional;
@@ -117,9 +118,13 @@
}
/// Parse modifiers for formal parameters.
- Token parseFormalParameterModifiers(Token token, MemberKind memberKind) {
+ Token parseFormalParameterModifiers(
+ Token token, FormalParameterKind parameterKind, MemberKind memberKind) {
token = parseModifiers(token);
+ if (parameterKind != FormalParameterKind.optionalNamed) {
+ reportExtraneousModifier(requiredToken);
+ }
if (memberKind == MemberKind.StaticMethod ||
memberKind == MemberKind.TopLevelMethod) {
reportExtraneousModifier(this.covariantToken);
@@ -136,7 +141,6 @@
reportExtraneousModifier(abstractToken);
reportExtraneousModifier(externalToken);
reportExtraneousModifier(lateToken);
- reportExtraneousModifier(requiredToken);
reportExtraneousModifier(staticToken);
return token;
}
@@ -248,8 +252,7 @@
constToken = next;
if (afterFactory) {
- parser.reportRecoverableError(next,
- fasta.templateModifierOutOfOrder.withArguments('const', 'factory'));
+ reportModifierOutOfOrder(next, 'factory');
}
return next;
}
@@ -368,6 +371,16 @@
assert(optional('required', next));
if (requiredToken == null) {
requiredToken = next;
+
+ if (constToken != null) {
+ reportModifierOutOfOrder(requiredToken, constToken.lexeme);
+ } else if (covariantToken != null) {
+ reportModifierOutOfOrder(requiredToken, covariantToken.lexeme);
+ } else if (finalToken != null) {
+ reportModifierOutOfOrder(requiredToken, finalToken.lexeme);
+ } else if (varToken != null) {
+ reportModifierOutOfOrder(requiredToken, varToken.lexeme);
+ }
return next;
}
@@ -437,4 +450,11 @@
token, fasta.templateExtraneousModifier);
}
}
+
+ void reportModifierOutOfOrder(Token modifier, String beforeModifier) {
+ parser.reportRecoverableError(
+ modifier,
+ fasta.templateModifierOutOfOrder
+ .withArguments(modifier.lexeme, beforeModifier));
+ }
}
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index ce21d39..95d7361 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -1417,7 +1417,8 @@
..requiredToken = requiredToken
..varFinalOrConst = varFinalOrConst;
- token = context.parseFormalParameterModifiers(token, memberKind);
+ token = context.parseFormalParameterModifiers(
+ token, parameterKind, memberKind);
next = token.next;
covariantToken = context.covariantToken;
@@ -1431,7 +1432,7 @@
}
listener.beginFormalParameter(
- start, memberKind, covariantToken, varFinalOrConst);
+ start, memberKind, requiredToken, covariantToken, varFinalOrConst);
// Type is required in a generalized function type, but optional otherwise.
final Token beforeType = token;
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 0f4d72f..2958f48 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -1017,8 +1017,10 @@
}
@override
- void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
- Token varFinalOrConst) {
+ void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+ Token covariantToken, Token varFinalOrConst) {
+ // TODO(danrubel): handle required token
+ reportNonNullableModifierError(requiredToken);
push((covariantToken != null ? covariantMask : 0) |
Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme));
}
diff --git a/pkg/front_end/test/fasta/parser/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index 5c37a69..d095d9a 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -2768,8 +2768,9 @@
}
@override
- void beginFormalParameter(Token token, MemberKind kind, Token covariantToken,
- Token varFinalOrConst) {
+ void beginFormalParameter(Token token, MemberKind kind, Token requiredToken,
+ Token covariantToken, Token varFinalOrConst) {
+ // TODO(danrubel): Update tests to include required and covariant
calls.add('beginFormalParameter $token $kind');
}