Skip to content

Commit 48093f5

Browse files
Dan Rubelcommit-bot@chromium.org
Dan Rubel
authored andcommitted
Revert "Add support for parsing simple nullable types"
This reverts commit c5fd11b. Reason for revert: Conditional expression lookahead may modify the token stream Original change's description: > Add support for parsing simple nullable types > > ... as part of adding NNBD as outlined in > dart-lang/language#110 > > This only supports parsing simple nullable types > such as int? and List<int>? while subsequent CLs > will add support for parsing more complex types. > > Change-Id: I144858946cb115755af437299899c2631105bf8c > Reviewed-on: https://dart-review.googlesource.com/c/87501 > Reviewed-by: Brian Wilkerson <[email protected]> > Commit-Queue: Dan Rubel <[email protected]> [email protected],[email protected] Change-Id: Ie1f47e7384ff51159aa2ebeb21561455b8e6287f No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/87620 Reviewed-by: Dan Rubel <[email protected]> Commit-Queue: Dan Rubel <[email protected]>
1 parent c7e7cbd commit 48093f5

File tree

4 files changed

+36
-288
lines changed

4 files changed

+36
-288
lines changed

pkg/front_end/lib/src/fasta/parser/parser.dart

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4489,7 +4489,11 @@ class Parser {
44894489
Token name = beforeName.next;
44904490
if (name.isIdentifier) {
44914491
TypeParamOrArgInfo typeParam = computeTypeParamOrArg(name);
4492-
Token next = typeParam.skip(name).next;
4492+
Token next = name;
4493+
if (typeParam != noTypeParamOrArg) {
4494+
next = typeParam.skip(next);
4495+
}
4496+
next = next.next;
44934497
if (optional('(', next)) {
44944498
if (looksLikeFunctionBody(next.endGroup.next)) {
44954499
return parseFunctionLiteral(
@@ -4869,10 +4873,8 @@ class Parser {
48694873
if (optional('!', token.next)) {
48704874
not = token = token.next;
48714875
}
4872-
TypeInfo typeInfo = computeType(token, true);
4873-
if (typeInfo.isConditionalExpressionStart(token, this)) {
4874-
typeInfo = typeInfo.asNonNullable;
4875-
}
4876+
// Ignore trailing `?` if there is one as it may be part of an expression
4877+
TypeInfo typeInfo = computeType(token, true).asNonNullableType();
48764878
token = typeInfo.ensureTypeNotVoid(token, this);
48774879
listener.handleIsOperator(operator, not);
48784880
return skipChainedAsIsOperators(token);
@@ -4886,10 +4888,8 @@ class Parser {
48864888
Token parseAsOperatorRest(Token token) {
48874889
Token operator = token = token.next;
48884890
assert(optional('as', operator));
4889-
TypeInfo typeInfo = computeType(token, true);
4890-
if (typeInfo.isConditionalExpressionStart(token, this)) {
4891-
typeInfo = typeInfo.asNonNullable;
4892-
}
4891+
// Ignore trailing `?` if there is one as it may be part of an expression
4892+
TypeInfo typeInfo = computeType(token, true).asNonNullableType();
48934893
token = typeInfo.ensureTypeNotVoid(token, this);
48944894
listener.handleAsOperator(operator);
48954895
return skipChainedAsIsOperators(token);
@@ -4908,11 +4908,7 @@ class Parser {
49084908
if (optional('!', next.next)) {
49094909
next = next.next;
49104910
}
4911-
TypeInfo typeInfo = computeType(next, true);
4912-
if (typeInfo.isConditionalExpressionStart(next, this)) {
4913-
typeInfo = typeInfo.asNonNullable;
4914-
}
4915-
token = typeInfo.skipType(next);
4911+
token = computeType(next, true).skipType(next);
49164912
next = token.next;
49174913
value = next.stringValue;
49184914
}
@@ -5033,10 +5029,6 @@ class Parser {
50335029
TypeInfo typeInfo,
50345030
bool onlyParseVariableDeclarationStart = false]) {
50355031
typeInfo ??= computeType(beforeType, false);
5036-
if (typeInfo.isConditionalExpressionStart(beforeType, this)) {
5037-
typeInfo = noType;
5038-
}
5039-
50405032
Token token = typeInfo.skipType(beforeType);
50415033
Token next = token.next;
50425034

pkg/front_end/lib/src/fasta/parser/type_info.dart

Lines changed: 9 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ import 'util.dart' show isOneOf, optional;
1919
abstract class TypeInfo {
2020
/// Return type info representing the receiver without the trailing `?`
2121
/// or the receiver if the receiver does not represent a nullable type.
22-
TypeInfo get asNonNullable;
22+
TypeInfo asNonNullableType();
2323

2424
/// Return `true` if the tokens comprising the type represented by the
2525
/// receiver could be interpreted as a valid standalone expression.
26-
/// For example, `A` or `A.b` could be interpreted as type references
27-
/// or expressions, while `A<T>` only looks like a type reference.
26+
/// For example, `A` or `A.b` could be interpreted as a type references
27+
/// or as expressions, while `A<T>` only looks like a type reference.
2828
bool get couldBeExpression;
2929

3030
/// Call this function when the token after [token] must be a type (not void).
@@ -41,13 +41,6 @@ abstract class TypeInfo {
4141
/// in valid code or during recovery.
4242
Token ensureTypeOrVoid(Token token, Parser parser);
4343

44-
/// Return `true` if the tokens comprising the type represented by the
45-
/// receiver are the start of a conditional expression.
46-
/// For example, `A?` or `A.b?` could be the start of a conditional expression
47-
/// and require arbitrary look ahead to determine if it is,
48-
/// while `A<T>?` cannot be the start of a conditional expression.
49-
bool isConditionalExpressionStart(Token token, Parser parser);
50-
5144
/// Call this function to parse an optional type (not void) after [token].
5245
/// This function will call the appropriate event methods on the [Parser]'s
5346
/// listener to handle the type. This may modify the token stream
@@ -206,19 +199,13 @@ TypeInfo computeType(final Token token, bool required,
206199
// We've seen identifier `<` identifier `>`
207200
next = typeParamOrArg.skip(next).next;
208201
if (!isGeneralizedFunctionType(next)) {
209-
if (optional('?', next) && typeParamOrArg == simpleTypeArgument1) {
210-
if (required || looksLikeName(next.next)) {
211-
// identifier `<` identifier `>` `?` identifier
212-
return simpleNullableTypeWith1Argument;
213-
}
202+
if (required || looksLikeName(next)) {
203+
// identifier `<` identifier `>` identifier
204+
return typeParamOrArg.typeInfo;
214205
} else {
215-
if (required || looksLikeName(next)) {
216-
// identifier `<` identifier `>` identifier
217-
return typeParamOrArg.typeInfo;
218-
}
206+
// identifier `<` identifier `>` non-identifier
207+
return noType;
219208
}
220-
// identifier `<` identifier `>` non-identifier
221-
return noType;
222209
}
223210
}
224211
// TODO(danrubel): Consider adding a const for
@@ -268,21 +255,7 @@ TypeInfo computeType(final Token token, bool required,
268255
.computeIdentifierGFT(required);
269256
}
270257

271-
if (optional('?', next)) {
272-
if (required) {
273-
// identifier `?`
274-
return simpleNullableType;
275-
} else {
276-
next = next.next;
277-
if (isGeneralizedFunctionType(next)) {
278-
// identifier `?` Function `(`
279-
return simpleNullableType;
280-
} else if (looksLikeName(next)) {
281-
// identifier `?` identifier `=`
282-
return simpleNullableType;
283-
}
284-
}
285-
} else if (required || looksLikeName(next)) {
258+
if (required || looksLikeName(next)) {
286259
// identifier identifier
287260
return simpleType;
288261
}

pkg/front_end/lib/src/fasta/parser/type_info_impl.dart

Lines changed: 14 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ import 'util.dart'
3838
/// when there is a single identifier as the type reference.
3939
const TypeInfo simpleType = const SimpleType();
4040

41-
/// [SimpleNullableType] is a specialized [TypeInfo] returned by [computeType]
42-
/// when there is a single identifier followed by `?` as the type reference.
43-
const TypeInfo simpleNullableType = const SimpleNullableType();
44-
4541
/// [PrefixedType] is a specialized [TypeInfo] returned by [computeType]
4642
/// when the type reference is of the form: identifier `.` identifier.
4743
const TypeInfo prefixedType = const PrefixedType();
@@ -64,12 +60,6 @@ const TypeInfo simpleTypeWith1ArgumentGtEq =
6460
const TypeInfo simpleTypeWith1ArgumentGtGt =
6561
const SimpleTypeWith1Argument(simpleTypeArgument1GtGt);
6662

67-
/// [SimpleNullableTypeWith1Argument] is a specialized [TypeInfo] returned by
68-
/// [computeType] when the type reference is of the form:
69-
/// identifier `<` identifier `>` `?`.
70-
const TypeInfo simpleNullableTypeWith1Argument =
71-
const SimpleNullableTypeWith1Argument();
72-
7363
/// [SimpleTypeArgument1] is a specialized [TypeParamOrArgInfo] returned by
7464
/// [computeTypeParamOrArg] when the type reference is of the form:
7565
/// `<` identifier `>`.
@@ -92,10 +82,10 @@ class NoType implements TypeInfo {
9282
const NoType();
9383

9484
@override
95-
TypeInfo get asNonNullable => this;
85+
bool get couldBeExpression => false;
9686

9787
@override
98-
bool get couldBeExpression => false;
88+
TypeInfo asNonNullableType() => this;
9989

10090
@override
10191
Token ensureTypeNotVoid(Token token, Parser parser) {
@@ -109,9 +99,6 @@ class NoType implements TypeInfo {
10999
Token ensureTypeOrVoid(Token token, Parser parser) =>
110100
ensureTypeNotVoid(token, parser);
111101

112-
@override
113-
bool isConditionalExpressionStart(Token token, Parser parser) => false;
114-
115102
@override
116103
Token parseTypeNotVoid(Token token, Parser parser) =>
117104
parseType(token, parser);
@@ -133,10 +120,10 @@ class PrefixedType implements TypeInfo {
133120
const PrefixedType();
134121

135122
@override
136-
TypeInfo get asNonNullable => this;
123+
bool get couldBeExpression => true;
137124

138125
@override
139-
bool get couldBeExpression => true;
126+
TypeInfo asNonNullableType() => this;
140127

141128
@override
142129
Token ensureTypeNotVoid(Token token, Parser parser) =>
@@ -146,9 +133,6 @@ class PrefixedType implements TypeInfo {
146133
Token ensureTypeOrVoid(Token token, Parser parser) =>
147134
parseType(token, parser);
148135

149-
@override
150-
bool isConditionalExpressionStart(Token token, Parser parser) => false;
151-
152136
@override
153137
Token parseTypeNotVoid(Token token, Parser parser) =>
154138
parseType(token, parser);
@@ -180,44 +164,17 @@ class PrefixedType implements TypeInfo {
180164
}
181165
}
182166

183-
/// See documentation on the [simpleNullableTypeWith1Argument] const.
184-
class SimpleNullableTypeWith1Argument extends SimpleTypeWith1Argument {
185-
const SimpleNullableTypeWith1Argument() : super(simpleTypeArgument1);
186-
187-
@override
188-
TypeInfo get asNonNullable => simpleTypeWith1Argument;
189-
190-
@override
191-
bool isConditionalExpressionStart(Token token, Parser parser) =>
192-
isConditionalThenExpression(skipType(token), parser);
193-
194-
@override
195-
Token parseTypeRest(Token start, Token token, Parser parser) {
196-
token = token.next;
197-
assert(optional('?', token));
198-
parser.listener.handleType(start, token);
199-
return token;
200-
}
201-
202-
@override
203-
Token skipType(Token token) {
204-
token = super.skipType(token).next;
205-
assert(optional('?', token));
206-
return token;
207-
}
208-
}
209-
210167
/// See documentation on the [simpleTypeWith1Argument] const.
211168
class SimpleTypeWith1Argument implements TypeInfo {
212169
final TypeParamOrArgInfo typeArg;
213170

214171
const SimpleTypeWith1Argument(this.typeArg);
215172

216173
@override
217-
TypeInfo get asNonNullable => this;
174+
bool get couldBeExpression => false;
218175

219176
@override
220-
bool get couldBeExpression => false;
177+
TypeInfo asNonNullableType() => this;
221178

222179
@override
223180
Token ensureTypeNotVoid(Token token, Parser parser) =>
@@ -227,9 +184,6 @@ class SimpleTypeWith1Argument implements TypeInfo {
227184
Token ensureTypeOrVoid(Token token, Parser parser) =>
228185
parseType(token, parser);
229186

230-
@override
231-
bool isConditionalExpressionStart(Token token, Parser parser) => false;
232-
233187
@override
234188
Token parseTypeNotVoid(Token token, Parser parser) =>
235189
parseType(token, parser);
@@ -256,40 +210,15 @@ class SimpleTypeWith1Argument implements TypeInfo {
256210
}
257211
}
258212

259-
/// See documentation on the [simpleNullableType] const.
260-
class SimpleNullableType extends SimpleType {
261-
const SimpleNullableType();
262-
263-
@override
264-
TypeInfo get asNonNullable => simpleType;
265-
266-
@override
267-
bool isConditionalExpressionStart(Token token, Parser parser) =>
268-
isConditionalThenExpression(skipType(token), parser);
269-
270-
@override
271-
Token parseTypeRest(Token start, Parser parser) {
272-
Token token = start.next;
273-
assert(optional('?', token));
274-
parser.listener.handleType(start, token);
275-
return token;
276-
}
277-
278-
@override
279-
Token skipType(Token token) {
280-
return token.next.next;
281-
}
282-
}
283-
284213
/// See documentation on the [simpleType] const.
285214
class SimpleType implements TypeInfo {
286215
const SimpleType();
287216

288217
@override
289-
TypeInfo get asNonNullable => this;
218+
bool get couldBeExpression => true;
290219

291220
@override
292-
bool get couldBeExpression => true;
221+
TypeInfo asNonNullableType() => this;
293222

294223
@override
295224
Token ensureTypeNotVoid(Token token, Parser parser) =>
@@ -299,9 +228,6 @@ class SimpleType implements TypeInfo {
299228
Token ensureTypeOrVoid(Token token, Parser parser) =>
300229
parseType(token, parser);
301230

302-
@override
303-
bool isConditionalExpressionStart(Token token, Parser parser) => false;
304-
305231
@override
306232
Token parseTypeNotVoid(Token token, Parser parser) =>
307233
parseType(token, parser);
@@ -331,10 +257,10 @@ class VoidType implements TypeInfo {
331257
const VoidType();
332258

333259
@override
334-
TypeInfo get asNonNullable => this;
260+
bool get couldBeExpression => false;
335261

336262
@override
337-
bool get couldBeExpression => false;
263+
TypeInfo asNonNullableType() => this;
338264

339265
@override
340266
Token ensureTypeNotVoid(Token token, Parser parser) {
@@ -347,9 +273,6 @@ class VoidType implements TypeInfo {
347273
Token ensureTypeOrVoid(Token token, Parser parser) =>
348274
parseType(token, parser);
349275

350-
@override
351-
bool isConditionalExpressionStart(Token token, Parser parser) => false;
352-
353276
@override
354277
Token parseTypeNotVoid(Token token, Parser parser) =>
355278
ensureTypeNotVoid(token, parser);
@@ -414,12 +337,12 @@ class ComplexTypeInfo implements TypeInfo {
414337
: this.start = beforeStart.next;
415338

416339
@override
417-
TypeInfo get asNonNullable {
418-
return this;
419-
}
340+
bool get couldBeExpression => false;
420341

421342
@override
422-
bool get couldBeExpression => false;
343+
TypeInfo asNonNullableType() {
344+
return this;
345+
}
423346

424347
@override
425348
Token ensureTypeNotVoid(Token token, Parser parser) =>
@@ -429,12 +352,6 @@ class ComplexTypeInfo implements TypeInfo {
429352
Token ensureTypeOrVoid(Token token, Parser parser) =>
430353
parseType(token, parser);
431354

432-
@override
433-
bool isConditionalExpressionStart(Token token, Parser parser) {
434-
//return isConditionalThenExpression(token.next.next, parser);
435-
return false;
436-
}
437-
438355
@override
439356
Token parseTypeNotVoid(Token token, Parser parser) =>
440357
parseType(token, parser);
@@ -1144,16 +1061,3 @@ Token splitCloser(Token closer) {
11441061
}
11451062
return null;
11461063
}
1147-
1148-
/// Return `true` if the tokens after [token]
1149-
/// represent a valid expression followed by a `:`.
1150-
bool isConditionalThenExpression(Token token, Parser parser) {
1151-
// TODO(danrubel): Consider adding checks for simple situations
1152-
// before resorting to heavy weight lookahead.
1153-
1154-
final originalListener = parser.listener;
1155-
parser.listener = new ForwardingListener();
1156-
token = parser.parseExpression(token);
1157-
parser.listener = originalListener;
1158-
return optional(':', token.next);
1159-
}

0 commit comments

Comments
 (0)