add asNonNullable() to existing type infos

This adds code to ignore trailing `?` in `as` and `is` expressions
because the trailing `?` may be part of the larger expression.
At the moment, this change is a no-op, but will become active
when a subsequent CL lands support for nullable types as part of
https://github.com/dart-lang/language/issues/110

Change-Id: I829d6aee0f11957ca9b5e143000005031649449f
Reviewed-on: https://dart-review.googlesource.com/c/86960
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 480d68d..9e1f015 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -4875,7 +4875,9 @@
     if (optional('!', token.next)) {
       not = token = token.next;
     }
-    token = computeType(token, true).ensureTypeNotVoid(token, this);
+    // Ignore trailing `?` if there is one as it may be part of an expression
+    TypeInfo typeInfo = computeType(token, true).asNonNullableType();
+    token = typeInfo.ensureTypeNotVoid(token, this);
     listener.handleIsOperator(operator, not);
     return skipChainedAsIsOperators(token);
   }
@@ -4888,7 +4890,9 @@
   Token parseAsOperatorRest(Token token) {
     Token operator = token = token.next;
     assert(optional('as', operator));
-    token = computeType(token, true).ensureTypeNotVoid(token, this);
+    // Ignore trailing `?` if there is one as it may be part of an expression
+    TypeInfo typeInfo = computeType(token, true).asNonNullableType();
+    token = typeInfo.ensureTypeNotVoid(token, this);
     listener.handleAsOperator(operator);
     return skipChainedAsIsOperators(token);
   }
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 585fedf3..5e9f636 100644
--- a/pkg/front_end/lib/src/fasta/parser/type_info.dart
+++ b/pkg/front_end/lib/src/fasta/parser/type_info.dart
@@ -17,6 +17,10 @@
 /// [TypeInfo] provides information collected by [computeType]
 /// about a particular type reference.
 abstract class TypeInfo {
+  /// Return type info representing the receiver without the trailing `?`
+  /// or the receiver if the receiver does not represent a nullable type.
+  TypeInfo asNonNullableType();
+
   /// Return `true` if the tokens comprising the type represented by the
   /// receiver could be interpreted as a valid standalone expression.
   /// For example, `A` or `A.b` could be interpreted as a type references
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 6ec0d20..8a29317 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
@@ -85,6 +85,9 @@
   bool get couldBeExpression => false;
 
   @override
+  TypeInfo asNonNullableType() => this;
+
+  @override
   Token ensureTypeNotVoid(Token token, Parser parser) {
     parser.reportRecoverableErrorWithToken(
         token.next, fasta.templateExpectedType);
@@ -120,6 +123,9 @@
   bool get couldBeExpression => true;
 
   @override
+  TypeInfo asNonNullableType() => this;
+
+  @override
   Token ensureTypeNotVoid(Token token, Parser parser) =>
       parseType(token, parser);
 
@@ -168,6 +174,9 @@
   bool get couldBeExpression => false;
 
   @override
+  TypeInfo asNonNullableType() => this;
+
+  @override
   Token ensureTypeNotVoid(Token token, Parser parser) =>
       parseType(token, parser);
 
@@ -209,6 +218,9 @@
   bool get couldBeExpression => true;
 
   @override
+  TypeInfo asNonNullableType() => this;
+
+  @override
   Token ensureTypeNotVoid(Token token, Parser parser) =>
       parseType(token, parser);
 
@@ -248,6 +260,9 @@
   bool get couldBeExpression => false;
 
   @override
+  TypeInfo asNonNullableType() => this;
+
+  @override
   Token ensureTypeNotVoid(Token token, Parser parser) {
     // Report an error, then parse `void` as if it were a type name.
     parser.reportRecoverableError(token.next, fasta.messageInvalidVoid);
@@ -325,6 +340,11 @@
   bool get couldBeExpression => false;
 
   @override
+  TypeInfo asNonNullableType() {
+    return this;
+  }
+
+  @override
   Token ensureTypeNotVoid(Token token, Parser parser) =>
       parseType(token, parser);