Revert support for simple nullable type return value in generalized function type
This reverts commit 11d081d115c1884ba3af2629839fc8ac66227589
Reason for revert: Breaks parsing less common conditionals (e.g. b ? c = true : g();)
Original change's description:
> Add support for simple nullable type return value in generalized function type
>
> This only supports nullable return values of the form
>
> <identifier> '?' 'Function' '(' ...
>
> This is an increment CL in the ongoing effort to add nullable type support
> as outlined in https://github.com/dart-lang/language/issues/110
Change-Id: I99bce29619d4e448193e3c81fa86a982791b1f77
Reviewed-on: https://dart-review.googlesource.com/c/87283
Reviewed-by: Dan Rubel <danrubel@google.com>
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index b1dd26d..8b8b575 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -2013,46 +2013,6 @@
expect(elseExpression, new TypeMatcher<SimpleIdentifier>());
}
- void test_conditionalExpression_precedence_nullableTypeWithTypeArg1_is() {
- Expression expression = parseExpression('x is String<S> ? (x + y) : z');
- expect(expression, isNotNull);
- expect(expression, new TypeMatcher<ConditionalExpression>());
- ConditionalExpression conditional = expression;
- Expression condition = conditional.condition;
- expect(condition, new TypeMatcher<IsExpression>());
- Expression thenExpression = conditional.thenExpression;
- expect(thenExpression, new TypeMatcher<ParenthesizedExpression>());
- Expression elseExpression = conditional.elseExpression;
- expect(elseExpression, new TypeMatcher<SimpleIdentifier>());
- }
-
- void test_conditionalExpression_precedence_nullableTypeWithTypeArg1GFT_is() {
- Expression expression =
- parseExpression('x is String<S> Function() ? (x + y) : z');
- expect(expression, isNotNull);
- expect(expression, new TypeMatcher<ConditionalExpression>());
- ConditionalExpression conditional = expression;
- Expression condition = conditional.condition;
- expect(condition, new TypeMatcher<IsExpression>());
- Expression thenExpression = conditional.thenExpression;
- expect(thenExpression, new TypeMatcher<ParenthesizedExpression>());
- Expression elseExpression = conditional.elseExpression;
- expect(elseExpression, new TypeMatcher<SimpleIdentifier>());
- }
-
- void test_conditionalExpression_precedence_nullableTypeWithTypeArg2_is() {
- Expression expression = parseExpression('x is String<S,T> ? (x + y) : z');
- expect(expression, isNotNull);
- expect(expression, new TypeMatcher<ConditionalExpression>());
- ConditionalExpression conditional = expression;
- Expression condition = conditional.condition;
- expect(condition, new TypeMatcher<IsExpression>());
- Expression thenExpression = conditional.thenExpression;
- expect(thenExpression, new TypeMatcher<ParenthesizedExpression>());
- Expression elseExpression = conditional.elseExpression;
- expect(elseExpression, new TypeMatcher<SimpleIdentifier>());
- }
-
void test_constructor_initializer_withParenthesizedExpression() {
CompilationUnit unit = parseCompilationUnit(r'''
class C {
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info.dart b/pkg/front_end/lib/src/fasta/parser/type_info.dart
index 5e27b8c..4dc7e66 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info.dart
@@ -187,7 +187,7 @@
if (isGeneralizedFunctionType(next)) {
// `Function` ...
return new ComplexTypeInfo(token, noTypeParamOrArg)
- .computeNoTypeGFT(token, required);
+ .computeNoTypeGFT(required);
}
// We've seen an identifier.
@@ -262,17 +262,20 @@
}
if (optional('?', next)) {
- next = next.next;
- if (isGeneralizedFunctionType(next)) {
- // identifier `?` Function `(`
- return new ComplexTypeInfo(token, noTypeParamOrArg)
- .computeIdentifierQuestionGFT(required);
- } else if (required ||
- (looksLikeName(next) &&
- isOneOfOrEof(
- next.next, const [';', ',', '=', '>', '>=', '>>', '>>>']))) {
+ if (required) {
// identifier `?`
return simpleNullableType;
+ } else {
+ next = next.next;
+ if (isGeneralizedFunctionType(next)) {
+ // identifier `?` Function `(`
+ return simpleNullableType;
+ } else if (looksLikeName(next) &&
+ isOneOfOrEof(
+ next.next, const [';', ',', '=', '>', '>=', '>>', '>>>'])) {
+ // identifier `?` identifier `=`
+ return simpleNullableType;
+ }
}
} else if (required || looksLikeName(next)) {
// identifier identifier
diff --git a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
index 41df19b..2b87c5b 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info_impl.dart
@@ -376,9 +376,6 @@
/// Type arguments were seen during analysis.
final TypeParamOrArgInfo typeArguments;
- /// The token before the trailing question mark or `null` if none.
- Token beforeQuestionMark;
-
/// The last token in the type reference.
Token end;
@@ -393,18 +390,12 @@
ComplexTypeInfo(Token beforeStart, this.typeArguments)
: this.start = beforeStart.next;
- ComplexTypeInfo._nonNullable(this.start, this.typeArguments, this.end,
- this.typeVariableStarters, this.gftHasReturnType);
-
@override
bool get couldBeExpression => false;
@override
TypeInfo asNonNullableType() {
- return beforeQuestionMark == null
- ? this
- : new ComplexTypeInfo._nonNullable(start, typeArguments,
- beforeQuestionMark, typeVariableStarters, gftHasReturnType);
+ return this;
}
@override
@@ -461,15 +452,7 @@
}
}
token = typeArguments.parseArguments(token, parser);
- Token questionMark = token.next;
- if (optional('?', questionMark) &&
- (typeVariableEndGroups.isNotEmpty || beforeQuestionMark != null)) {
- // Only consume the `?` if it is part of the complex type
- token = questionMark;
- } else {
- questionMark = null;
- }
- parser.listener.handleType(typeRefOrPrefix, questionMark);
+ parser.listener.handleType(typeRefOrPrefix, null);
}
}
@@ -509,11 +492,10 @@
/// Given `Function` non-identifier, compute the type
/// and return the receiver or one of the [TypeInfo] constants.
- TypeInfo computeNoTypeGFT(Token beforeStart, bool required) {
+ TypeInfo computeNoTypeGFT(bool required) {
assert(optional('Function', start));
- assert(beforeStart.next == start);
- computeRest(beforeStart, required);
+ computeRest(start, required);
if (gftHasReturnType == null) {
return required ? simpleType : noType;
}
@@ -527,7 +509,7 @@
assert(optional('void', start));
assert(optional('Function', start.next));
- computeRest(start, required);
+ computeRest(start.next, required);
if (gftHasReturnType == null) {
return voidType;
}
@@ -541,7 +523,7 @@
assert(isValidTypeReference(start));
assert(optional('Function', start.next));
- computeRest(start, required);
+ computeRest(start.next, required);
if (gftHasReturnType == null) {
return simpleType;
}
@@ -549,28 +531,13 @@
return this;
}
- /// Given identifier `?` `Function` non-identifier, compute the type
- /// and return the receiver or one of the [TypeInfo] constants.
- TypeInfo computeIdentifierQuestionGFT(bool required) {
- assert(isValidTypeReference(start));
- assert(optional('?', start.next));
- assert(optional('Function', start.next.next));
-
- computeRest(start, required);
- if (gftHasReturnType == null) {
- return simpleNullableType;
- }
- assert(end != null);
- return this;
- }
-
/// Given a builtin, return the receiver so that parseType will report
/// an error for the builtin used as a type.
TypeInfo computeBuiltinOrVarAsType(bool required) {
assert(start.type.isBuiltIn || optional('var', start));
end = typeArguments.skip(start);
- computeRest(end, required);
+ computeRest(end.next, required);
assert(end != null);
return this;
}
@@ -583,7 +550,7 @@
assert(typeArguments != noTypeParamOrArg);
end = typeArguments.skip(start);
- computeRest(end, required);
+ computeRest(end.next, required);
if (!required && !looksLikeName(end.next) && gftHasReturnType == null) {
return noType;
@@ -607,7 +574,7 @@
}
end = typeArguments.skip(token);
- computeRest(end, required);
+ computeRest(end.next, required);
if (!required && !looksLikeName(end.next) && gftHasReturnType == null) {
return noType;
}
@@ -616,11 +583,6 @@
}
void computeRest(Token token, bool required) {
- if (optional('?', token.next)) {
- beforeQuestionMark = token;
- end = token = token.next;
- }
- token = token.next;
while (optional('Function', token)) {
Token typeVariableStart = token;
// TODO(danrubel): Consider caching TypeParamOrArgInfo
@@ -641,14 +603,9 @@
assert(optional(')', token));
gftHasReturnType ??= typeVariableStart != start;
typeVariableStarters = typeVariableStarters.prepend(typeVariableStart);
- beforeQuestionMark = null;
end = token;
token = token.next;
}
- if (optional('?', token)) {
- beforeQuestionMark = end;
- end = token;
- }
}
}
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 64675bb..7b9b003 100644
--- a/pkg/front_end/test/fasta/parser/type_info_test.dart
+++ b/pkg/front_end/test/fasta/parser/type_info_test.dart
@@ -800,19 +800,6 @@
]);
}
- void test_computeType_identifierComplex_questionMark() {
- expectComplexInfo('C? Function()', required: true, expectedCalls: [
- 'handleNoTypeVariables (',
- 'beginFunctionType C',
- 'handleIdentifier C typeReference',
- 'handleNoTypeArguments ?',
- 'handleType C ?',
- 'beginFormalParameters ( MemberKind.GeneralizedFunctionType',
- 'endFormalParameters 0 ( ) MemberKind.GeneralizedFunctionType',
- 'endFunctionType Function null',
- ]);
- }
-
void test_computeType_identifierTypeArg() {
expectComplexInfo('C<void>', required: true, expectedCalls: [
'handleIdentifier C typeReference',