mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 21:40:07 +00:00
Update fasta parser to report ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR
In addition to adding missing errors, this CL inlines modifier parsing as part of a multi step effort to parse modifiers once and provide better error recovery for class member and top level declarations. Change-Id: Ibea91a4a3e2073ed6079f0f44ff4bbbb4a98a614 Reviewed-on: https://dart-review.googlesource.com/35300 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Dan Rubel <danrubel@google.com>
This commit is contained in:
parent
7339e1ffe7
commit
6f6689889c
|
@ -235,6 +235,10 @@ class FastaErrorReporter {
|
||||||
errorReporter?.reportErrorForOffset(
|
errorReporter?.reportErrorForOffset(
|
||||||
StaticWarningCode.FINAL_NOT_INITIALIZED, offset, length, [name]);
|
StaticWarningCode.FINAL_NOT_INITIALIZED, offset, length, [name]);
|
||||||
return;
|
return;
|
||||||
|
case "FUNCTION_TYPED_PARAMETER_VAR":
|
||||||
|
errorReporter?.reportErrorForOffset(
|
||||||
|
ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, offset, length);
|
||||||
|
return;
|
||||||
case "GETTER_WITH_PARAMETERS":
|
case "GETTER_WITH_PARAMETERS":
|
||||||
errorReporter?.reportErrorForOffset(
|
errorReporter?.reportErrorForOffset(
|
||||||
ParserErrorCode.GETTER_WITH_PARAMETERS, offset, length);
|
ParserErrorCode.GETTER_WITH_PARAMETERS, offset, length);
|
||||||
|
|
|
@ -387,14 +387,6 @@ class ErrorParserTest_Fasta extends FastaParserTestCase
|
||||||
super.test_fieldInitializerOutsideConstructor();
|
super.test_fieldInitializerOutsideConstructor();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
@failingTest
|
|
||||||
void test_functionTypedParameter_final() {
|
|
||||||
// TODO(brianwilkerson) Wrong errors:
|
|
||||||
// Expected 1 errors of type ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, found 0
|
|
||||||
super.test_functionTypedParameter_final();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@failingTest
|
@failingTest
|
||||||
void test_functionTypedParameter_incomplete1() {
|
void test_functionTypedParameter_incomplete1() {
|
||||||
|
@ -415,14 +407,6 @@ class ErrorParserTest_Fasta extends FastaParserTestCase
|
||||||
super.test_functionTypedParameter_incomplete1();
|
super.test_functionTypedParameter_incomplete1();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
@failingTest
|
|
||||||
void test_functionTypedParameter_var() {
|
|
||||||
// TODO(brianwilkerson) Wrong errors:
|
|
||||||
// Expected 1 errors of type ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, found 0
|
|
||||||
super.test_functionTypedParameter_var();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@failingTest
|
@failingTest
|
||||||
void test_getterInFunction_block_noReturnType() {
|
void test_getterInFunction_block_noReturnType() {
|
||||||
|
@ -2129,36 +2113,6 @@ class FastaParserTestCase extends Object
|
||||||
@reflectiveTest
|
@reflectiveTest
|
||||||
class FormalParameterParserTest_Fasta extends FastaParserTestCase
|
class FormalParameterParserTest_Fasta extends FastaParserTestCase
|
||||||
with FormalParameterParserTestMixin {
|
with FormalParameterParserTestMixin {
|
||||||
@override
|
|
||||||
@failingTest
|
|
||||||
void test_parseNormalFormalParameter_field_const_noType() {
|
|
||||||
// TODO(brianwilkerson) Wrong errors:
|
|
||||||
// Expected 0 errors of type ParserErrorCode.EXTRANEOUS_MODIFIER, found 1 (1)
|
|
||||||
super.test_parseNormalFormalParameter_field_const_noType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@failingTest
|
|
||||||
void test_parseNormalFormalParameter_field_const_noType2() {
|
|
||||||
// TODO(danrubel): should not be generating an error
|
|
||||||
super.test_parseNormalFormalParameter_field_const_noType();
|
|
||||||
assertNoErrors();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
@failingTest
|
|
||||||
void test_parseNormalFormalParameter_field_const_type() {
|
|
||||||
// TODO(brianwilkerson) Wrong errors:
|
|
||||||
// Expected 0 errors of type ParserErrorCode.EXTRANEOUS_MODIFIER, found 1 (1)
|
|
||||||
super.test_parseNormalFormalParameter_field_const_type();
|
|
||||||
}
|
|
||||||
|
|
||||||
@failingTest
|
|
||||||
void test_parseNormalFormalParameter_field_const_type2() {
|
|
||||||
// TODO(danrubel): should not be generating an error
|
|
||||||
super.test_parseNormalFormalParameter_field_const_type();
|
|
||||||
assertNoErrors();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void test_parseNormalFormalParameter_function_noType_typeParameterComments() {
|
void test_parseNormalFormalParameter_function_noType_typeParameterComments() {
|
||||||
// Ignored: Fasta does not support the generic comment syntax.
|
// Ignored: Fasta does not support the generic comment syntax.
|
||||||
|
|
|
@ -3480,16 +3480,20 @@ class Foo {
|
||||||
void test_functionTypedParameter_const() {
|
void test_functionTypedParameter_const() {
|
||||||
parseCompilationUnit("void f(const x()) {}",
|
parseCompilationUnit("void f(const x()) {}",
|
||||||
errors: usingFastaParser
|
errors: usingFastaParser
|
||||||
? [expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 7, 5)]
|
? [
|
||||||
|
expectedError(ParserErrorCode.EXTRANEOUS_MODIFIER, 7, 5),
|
||||||
|
expectedError(
|
||||||
|
ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
|
||||||
|
]
|
||||||
: [
|
: [
|
||||||
expectedError(
|
expectedError(
|
||||||
ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 9)
|
ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_functionTypedParameter_final() {
|
void test_functionTypedParameter_final() {
|
||||||
parseCompilationUnit("void f(final x()) {}", errors: [
|
parseCompilationUnit("void f(final x()) {}", errors: [
|
||||||
expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 9)
|
expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 5)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3516,7 +3520,7 @@ class Foo {
|
||||||
|
|
||||||
void test_functionTypedParameter_var() {
|
void test_functionTypedParameter_var() {
|
||||||
parseCompilationUnit("void f(var x()) {}", errors: [
|
parseCompilationUnit("void f(var x()) {}", errors: [
|
||||||
expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 7)
|
expectedError(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 7, 3)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8815,8 +8819,9 @@ abstract class FormalParameterParserTestMixin
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_parseNormalFormalParameter_field_const_noType() {
|
void test_parseNormalFormalParameter_field_const_noType() {
|
||||||
NormalFormalParameter parameter =
|
NormalFormalParameter parameter = parseNormalFormalParameter('const this.a',
|
||||||
parseNormalFormalParameter('const this.a');
|
errorCodes:
|
||||||
|
usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
|
||||||
expect(parameter, isNotNull);
|
expect(parameter, isNotNull);
|
||||||
expect(parameter, new isInstanceOf<FieldFormalParameter>());
|
expect(parameter, new isInstanceOf<FieldFormalParameter>());
|
||||||
FieldFormalParameter fieldParameter = parameter;
|
FieldFormalParameter fieldParameter = parameter;
|
||||||
|
@ -8827,15 +8832,11 @@ abstract class FormalParameterParserTestMixin
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_parseNormalFormalParameter_field_const_type() {
|
void test_parseNormalFormalParameter_field_const_type() {
|
||||||
NormalFormalParameter parameter =
|
NormalFormalParameter parameter = parseNormalFormalParameter(
|
||||||
parseNormalFormalParameter('const A this.a');
|
'const A this.a',
|
||||||
|
errorCodes:
|
||||||
|
usingFastaParser ? [ParserErrorCode.EXTRANEOUS_MODIFIER] : []);
|
||||||
expect(parameter, isNotNull);
|
expect(parameter, isNotNull);
|
||||||
if (usingFastaParser) {
|
|
||||||
// TODO(danrubel): should not be generating an error
|
|
||||||
assertErrorsWithCodes([ParserErrorCode.EXTRANEOUS_MODIFIER]);
|
|
||||||
} else {
|
|
||||||
assertNoErrors();
|
|
||||||
}
|
|
||||||
expect(parameter, new isInstanceOf<FieldFormalParameter>());
|
expect(parameter, new isInstanceOf<FieldFormalParameter>());
|
||||||
FieldFormalParameter fieldParameter = parameter;
|
FieldFormalParameter fieldParameter = parameter;
|
||||||
expect(fieldParameter.keyword, isNotNull);
|
expect(fieldParameter.keyword, isNotNull);
|
||||||
|
|
|
@ -1486,40 +1486,12 @@ main() => foo(42);
|
||||||
MessageKind.FINAL_FUNCTION_TYPE_PARAMETER: const MessageTemplate(
|
MessageKind.FINAL_FUNCTION_TYPE_PARAMETER: const MessageTemplate(
|
||||||
MessageKind.FINAL_FUNCTION_TYPE_PARAMETER,
|
MessageKind.FINAL_FUNCTION_TYPE_PARAMETER,
|
||||||
"A function type parameter can't be declared final.",
|
"A function type parameter can't be declared final.",
|
||||||
howToFix: "Try removing 'final'.",
|
howToFix: "Try removing 'final'."),
|
||||||
examples: const [
|
|
||||||
"""
|
|
||||||
foo(final int x(int a)) {}
|
|
||||||
main() => foo((y) => 42);
|
|
||||||
""",
|
|
||||||
"""
|
|
||||||
foo({final int x(int a)}) {}
|
|
||||||
main() => foo((y) => 42);
|
|
||||||
""",
|
|
||||||
"""
|
|
||||||
foo([final int x(int a)]) {}
|
|
||||||
main() => foo((y) => 42);
|
|
||||||
"""
|
|
||||||
]),
|
|
||||||
|
|
||||||
MessageKind.VAR_FUNCTION_TYPE_PARAMETER: const MessageTemplate(
|
MessageKind.VAR_FUNCTION_TYPE_PARAMETER: const MessageTemplate(
|
||||||
MessageKind.VAR_FUNCTION_TYPE_PARAMETER,
|
MessageKind.VAR_FUNCTION_TYPE_PARAMETER,
|
||||||
"A function type parameter can't be declared with 'var'.",
|
"A function type parameter can't be declared with 'var'.",
|
||||||
howToFix: "Try removing 'var'.",
|
howToFix: "Try removing 'var'."),
|
||||||
examples: const [
|
|
||||||
"""
|
|
||||||
foo(var int x(int a)) {}
|
|
||||||
main() => foo((y) => 42);
|
|
||||||
""",
|
|
||||||
"""
|
|
||||||
foo({var int x(int a)}) {}
|
|
||||||
main() => foo((y) => 42);
|
|
||||||
""",
|
|
||||||
"""
|
|
||||||
foo([var int x(int a)]) {}
|
|
||||||
main() => foo((y) => 42);
|
|
||||||
"""
|
|
||||||
]),
|
|
||||||
|
|
||||||
MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE: const MessageTemplate(
|
MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE: const MessageTemplate(
|
||||||
MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
|
MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
|
||||||
|
|
|
@ -1934,6 +1934,19 @@ const MessageCode messageFunctionTypeDefaultValue = const MessageCode(
|
||||||
dart2jsCode: "*ignored*",
|
dart2jsCode: "*ignored*",
|
||||||
message: r"""Can't have a default value in a function type.""");
|
message: r"""Can't have a default value in a function type.""");
|
||||||
|
|
||||||
|
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||||
|
const Code<Null> codeFunctionTypedParameterVar =
|
||||||
|
messageFunctionTypedParameterVar;
|
||||||
|
|
||||||
|
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||||
|
const MessageCode messageFunctionTypedParameterVar = const MessageCode(
|
||||||
|
"FunctionTypedParameterVar",
|
||||||
|
analyzerCode: "FUNCTION_TYPED_PARAMETER_VAR",
|
||||||
|
dart2jsCode: "*fatal*",
|
||||||
|
message:
|
||||||
|
r"""Function-typed parameters can't specify 'const', 'final' or 'var' in place of a return type.""",
|
||||||
|
tip: r"""Try replacing the keyword with a return type.""");
|
||||||
|
|
||||||
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
|
||||||
const Code<Null> codeGeneratorReturnsValue = messageGeneratorReturnsValue;
|
const Code<Null> codeGeneratorReturnsValue = messageGeneratorReturnsValue;
|
||||||
|
|
||||||
|
|
|
@ -74,6 +74,22 @@ Token skipToLastModifier(Token token) {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeContinuation typeContinuationAfterVar(TypeContinuation typeContinuation) {
|
||||||
|
switch (typeContinuation ?? TypeContinuation.Required) {
|
||||||
|
case TypeContinuation.NormalFormalParameter:
|
||||||
|
return TypeContinuation.NormalFormalParameterAfterVar;
|
||||||
|
|
||||||
|
case TypeContinuation.OptionalPositionalFormalParameter:
|
||||||
|
return TypeContinuation.OptionalPositionalFormalParameterAfterVar;
|
||||||
|
|
||||||
|
case TypeContinuation.NamedFormalParameter:
|
||||||
|
return TypeContinuation.NamedFormalParameterAfterVar;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return TypeContinuation.OptionalAfterVar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TypeContinuation typeContinuationFromMemberKind(
|
TypeContinuation typeContinuationFromMemberKind(
|
||||||
bool isVarAllowed, MemberKind memberKind) =>
|
bool isVarAllowed, MemberKind memberKind) =>
|
||||||
(isVarAllowed || memberKind == MemberKind.GeneralizedFunctionType)
|
(isVarAllowed || memberKind == MemberKind.GeneralizedFunctionType)
|
||||||
|
@ -109,6 +125,7 @@ class ModifierContext {
|
||||||
memberKind != MemberKind.NonStaticField;
|
memberKind != MemberKind.NonStaticField;
|
||||||
|
|
||||||
Token parseOpt(Token token) {
|
Token parseOpt(Token token) {
|
||||||
|
assert(lastModifier != null);
|
||||||
if (token != lastModifier) {
|
if (token != lastModifier) {
|
||||||
if (optional('external', token.next)) {
|
if (optional('external', token.next)) {
|
||||||
token = parseExternalOpt(token);
|
token = parseExternalOpt(token);
|
||||||
|
@ -268,24 +285,7 @@ class ModifierContext {
|
||||||
next, fasta.templateExtraneousModifier);
|
next, fasta.templateExtraneousModifier);
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
switch (typeContinuation ?? TypeContinuation.Required) {
|
typeContinuation = typeContinuationAfterVar(typeContinuation);
|
||||||
case TypeContinuation.NormalFormalParameter:
|
|
||||||
typeContinuation = TypeContinuation.NormalFormalParameterAfterVar;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TypeContinuation.OptionalPositionalFormalParameter:
|
|
||||||
typeContinuation =
|
|
||||||
TypeContinuation.OptionalPositionalFormalParameterAfterVar;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TypeContinuation.NamedFormalParameter:
|
|
||||||
typeContinuation = TypeContinuation.NamedFormalParameterAfterVar;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
typeContinuation = TypeContinuation.OptionalAfterVar;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
varFinalOrConst ??= next;
|
varFinalOrConst ??= next;
|
||||||
modifierCount++;
|
modifierCount++;
|
||||||
return parser.parseModifier(token);
|
return parser.parseModifier(token);
|
||||||
|
@ -306,7 +306,7 @@ class ModifierRecoveryContext extends ModifierContext {
|
||||||
FormalParameterKind parameterKind,
|
FormalParameterKind parameterKind,
|
||||||
bool isVarAllowed,
|
bool isVarAllowed,
|
||||||
TypeContinuation typeContinuation,
|
TypeContinuation typeContinuation,
|
||||||
Token lastModifier)
|
[Token lastModifier])
|
||||||
: super(parser, memberKind, parameterKind, isVarAllowed, typeContinuation,
|
: super(parser, memberKind, parameterKind, isVarAllowed, typeContinuation,
|
||||||
lastModifier);
|
lastModifier);
|
||||||
|
|
||||||
|
@ -344,6 +344,52 @@ class ModifierRecoveryContext extends ModifierContext {
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token parseRecovery(Token token,
|
||||||
|
{Token covariantToken, Token varFinalOrConst}) {
|
||||||
|
if (covariantToken != null) {
|
||||||
|
this.covariantToken = covariantToken;
|
||||||
|
++modifierCount;
|
||||||
|
}
|
||||||
|
if (varFinalOrConst != null) {
|
||||||
|
++modifierCount;
|
||||||
|
if (optional('var', varFinalOrConst)) {
|
||||||
|
varToken = varFinalOrConst;
|
||||||
|
} else if (optional('final', varFinalOrConst)) {
|
||||||
|
finalToken = varFinalOrConst;
|
||||||
|
} else if (optional('const', varFinalOrConst)) {
|
||||||
|
constToken = varFinalOrConst;
|
||||||
|
} else {
|
||||||
|
throw "Internal error: Unexpected varFinalOrConst '$varFinalOrConst'.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process invalid and out-of-order modifiers
|
||||||
|
Token next = token.next;
|
||||||
|
while (isModifier(next)) {
|
||||||
|
final value = next.stringValue;
|
||||||
|
if (identical('abstract', value)) {
|
||||||
|
token = parseAbstract(token);
|
||||||
|
} else if (identical('const', value)) {
|
||||||
|
token = parseConst(token);
|
||||||
|
} else if (identical('covariant', value)) {
|
||||||
|
token = parseCovariantOpt(token);
|
||||||
|
} else if (identical('external', value)) {
|
||||||
|
token = parseExternalOpt(token);
|
||||||
|
} else if (identical('final', value)) {
|
||||||
|
token = parseFinal(token);
|
||||||
|
} else if (identical('static', value)) {
|
||||||
|
token = parseStaticOpt(token);
|
||||||
|
} else if (identical('var', value)) {
|
||||||
|
token = parseVar(token);
|
||||||
|
} else {
|
||||||
|
token = parseExtraneousModifier(token);
|
||||||
|
}
|
||||||
|
next = token.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
Token parseAbstract(Token token) {
|
Token parseAbstract(Token token) {
|
||||||
assert(optional('abstract', token.next));
|
assert(optional('abstract', token.next));
|
||||||
if (memberKind == MemberKind.NonStaticField ||
|
if (memberKind == MemberKind.NonStaticField ||
|
||||||
|
|
|
@ -79,10 +79,12 @@ import 'modifier_context.dart'
|
||||||
ClassMethodModifierContext,
|
ClassMethodModifierContext,
|
||||||
FactoryModifierContext,
|
FactoryModifierContext,
|
||||||
ModifierContext,
|
ModifierContext,
|
||||||
|
ModifierRecoveryContext,
|
||||||
TopLevelMethodModifierContext,
|
TopLevelMethodModifierContext,
|
||||||
isModifier,
|
isModifier,
|
||||||
parseModifiersOpt,
|
parseModifiersOpt,
|
||||||
skipToLastModifier,
|
skipToLastModifier,
|
||||||
|
typeContinuationAfterVar,
|
||||||
typeContinuationFromMemberKind;
|
typeContinuationFromMemberKind;
|
||||||
|
|
||||||
import 'recovery_listeners.dart'
|
import 'recovery_listeners.dart'
|
||||||
|
@ -1152,31 +1154,59 @@ class Parser {
|
||||||
/// ```
|
/// ```
|
||||||
Token parseFormalParameter(
|
Token parseFormalParameter(
|
||||||
Token token, FormalParameterKind parameterKind, MemberKind memberKind) {
|
Token token, FormalParameterKind parameterKind, MemberKind memberKind) {
|
||||||
|
assert(parameterKind != null);
|
||||||
token = parseMetadataStar(token);
|
token = parseMetadataStar(token);
|
||||||
Token next = token.next;
|
Token next = token.next;
|
||||||
listener.beginFormalParameter(next, memberKind);
|
listener.beginFormalParameter(next, memberKind);
|
||||||
|
|
||||||
TypeContinuation typeContinuation =
|
TypeContinuation typeContinuation =
|
||||||
typeContinuationFromFormalParameterKind(parameterKind);
|
typeContinuationFromFormalParameterKind(parameterKind);
|
||||||
|
Token varFinalOrConst;
|
||||||
if (isModifier(next)) {
|
if (isModifier(next)) {
|
||||||
ModifierContext modifierContext = parseModifiersOpt(
|
int modifierCount = 0;
|
||||||
this,
|
Token covariantToken;
|
||||||
token,
|
if (optional('covariant', next)) {
|
||||||
skipToLastModifier(token),
|
if (memberKind != MemberKind.StaticMethod &&
|
||||||
memberKind,
|
memberKind != MemberKind.TopLevelMethod) {
|
||||||
parameterKind,
|
covariantToken = token = parseModifier(token);
|
||||||
false,
|
++modifierCount;
|
||||||
typeContinuation);
|
next = token.next;
|
||||||
typeContinuation = modifierContext.typeContinuation;
|
}
|
||||||
memberKind = modifierContext.memberKind;
|
}
|
||||||
token = modifierContext.lastModifier;
|
|
||||||
modifierContext = null;
|
if (isModifier(next)) {
|
||||||
|
if (optional('var', next)) {
|
||||||
|
typeContinuation = typeContinuationAfterVar(typeContinuation);
|
||||||
|
varFinalOrConst = token = parseModifier(token);
|
||||||
|
++modifierCount;
|
||||||
|
next = token.next;
|
||||||
|
} else if (optional('final', next)) {
|
||||||
|
varFinalOrConst = token = parseModifier(token);
|
||||||
|
++modifierCount;
|
||||||
|
next = token.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isModifier(next)) {
|
||||||
|
// Recovery
|
||||||
|
ModifierRecoveryContext modifierContext = new ModifierRecoveryContext(
|
||||||
|
this, memberKind, parameterKind, false, typeContinuation);
|
||||||
|
token = modifierContext.parseRecovery(token,
|
||||||
|
covariantToken: covariantToken, varFinalOrConst: varFinalOrConst);
|
||||||
|
|
||||||
|
memberKind = modifierContext.memberKind;
|
||||||
|
typeContinuation = modifierContext.typeContinuation;
|
||||||
|
varFinalOrConst = modifierContext.varFinalOrConst;
|
||||||
|
modifierCount = modifierContext.modifierCount;
|
||||||
|
modifierContext = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
listener.handleModifiers(modifierCount);
|
||||||
} else {
|
} else {
|
||||||
listener.handleModifiers(0);
|
listener.handleModifiers(0);
|
||||||
typeContinuation ??= typeContinuationFromMemberKind(false, memberKind);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseType(token, typeContinuation, null, memberKind);
|
return parseType(
|
||||||
|
token, typeContinuation, null, memberKind, varFinalOrConst);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -2061,7 +2091,8 @@ class Parser {
|
||||||
Token parseType(Token token,
|
Token parseType(Token token,
|
||||||
[TypeContinuation continuation = TypeContinuation.Required,
|
[TypeContinuation continuation = TypeContinuation.Required,
|
||||||
IdentifierContext continuationContext,
|
IdentifierContext continuationContext,
|
||||||
MemberKind memberKind]) {
|
MemberKind memberKind,
|
||||||
|
Token varFinalOrConst]) {
|
||||||
/// True if we've seen the `var` keyword.
|
/// True if we've seen the `var` keyword.
|
||||||
bool hasVar = false;
|
bool hasVar = false;
|
||||||
|
|
||||||
|
@ -2580,12 +2611,20 @@ class Parser {
|
||||||
Token closer = closeBraceTokenFor(token);
|
Token closer = closeBraceTokenFor(token);
|
||||||
if (closer != null) {
|
if (closer != null) {
|
||||||
if (optional("(", closer.next)) {
|
if (optional("(", closer.next)) {
|
||||||
|
if (varFinalOrConst != null) {
|
||||||
|
reportRecoverableError(
|
||||||
|
varFinalOrConst, fasta.messageFunctionTypedParameterVar);
|
||||||
|
}
|
||||||
inlineFunctionTypeStart = beforeToken;
|
inlineFunctionTypeStart = beforeToken;
|
||||||
beforeToken = token;
|
beforeToken = token;
|
||||||
token = token.next;
|
token = token.next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (optional("(", token)) {
|
} else if (optional("(", token)) {
|
||||||
|
if (varFinalOrConst != null) {
|
||||||
|
reportRecoverableError(
|
||||||
|
varFinalOrConst, fasta.messageFunctionTypedParameterVar);
|
||||||
|
}
|
||||||
inlineFunctionTypeStart = beforeToken;
|
inlineFunctionTypeStart = beforeToken;
|
||||||
beforeToken = closeBraceTokenFor(token);
|
beforeToken = closeBraceTokenFor(token);
|
||||||
token = beforeToken.next;
|
token = beforeToken.next;
|
||||||
|
|
|
@ -278,6 +278,16 @@ MissingConstFinalVarOrType:
|
||||||
script:
|
script:
|
||||||
- "class C { static f; }"
|
- "class C { static f; }"
|
||||||
|
|
||||||
|
FunctionTypedParameterVar:
|
||||||
|
template: "Function-typed parameters can't specify 'const', 'final' or 'var' in place of a return type."
|
||||||
|
tip: "Try replacing the keyword with a return type."
|
||||||
|
analyzerCode: FUNCTION_TYPED_PARAMETER_VAR
|
||||||
|
dart2jsCode: "*fatal*"
|
||||||
|
script:
|
||||||
|
- "void f(const x()) {}"
|
||||||
|
- "void f(final x()) {}"
|
||||||
|
- "void f(var x()) {}"
|
||||||
|
|
||||||
AbstractClassMember:
|
AbstractClassMember:
|
||||||
template: "Members of classes can't be declared to be 'abstract'."
|
template: "Members of classes can't be declared to be 'abstract'."
|
||||||
tip: "Try removing the 'abstract' keyword. You can add the 'abstract' keyword before the class declaration."
|
tip: "Try removing the 'abstract' keyword. You can add the 'abstract' keyword before the class declaration."
|
||||||
|
|
|
@ -153,8 +153,6 @@ Language/Expressions/Type_Test/evaluation_t10: RuntimeError # Kernel Issue 28335
|
||||||
Language/Functions/External_Functions/not_connected_to_a_body_t01: RuntimeError # Dartk Issue 28565
|
Language/Functions/External_Functions/not_connected_to_a_body_t01: RuntimeError # Dartk Issue 28565
|
||||||
Language/Functions/Formal_Parameters/Optional_Formals/default_value_t01: MissingCompileTimeError
|
Language/Functions/Formal_Parameters/Optional_Formals/default_value_t01: MissingCompileTimeError
|
||||||
Language/Functions/Formal_Parameters/Optional_Formals/default_value_t02: MissingCompileTimeError
|
Language/Functions/Formal_Parameters/Optional_Formals/default_value_t02: MissingCompileTimeError
|
||||||
Language/Functions/Formal_Parameters/Required_Formals/syntax_t06: MissingCompileTimeError
|
|
||||||
Language/Functions/Formal_Parameters/Required_Formals/syntax_t07: MissingCompileTimeError
|
|
||||||
Language/Libraries_and_Scripts/Exports/reexport_t01: MissingCompileTimeError
|
Language/Libraries_and_Scripts/Exports/reexport_t01: MissingCompileTimeError
|
||||||
Language/Libraries_and_Scripts/Imports/deferred_import_t01: CompileTimeError # Deferred loading kernel issue 28335.
|
Language/Libraries_and_Scripts/Imports/deferred_import_t01: CompileTimeError # Deferred loading kernel issue 28335.
|
||||||
Language/Libraries_and_Scripts/Imports/deferred_import_t02: CompileTimeError # Deferred loading kernel issue 28335.
|
Language/Libraries_and_Scripts/Imports/deferred_import_t02: CompileTimeError # Deferred loading kernel issue 28335.
|
||||||
|
|
Loading…
Reference in a new issue