[cfe] Add Extensions to the parser in the CFE type tests

Change-Id: I796fcab752da42c77414170b661dfe5c42e30aec
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196492
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
diff --git a/pkg/front_end/test/fasta/types/kernel_type_parser_test.dart b/pkg/front_end/test/fasta/types/kernel_type_parser_test.dart
index 6b31ffd..8ccfba3 100644
--- a/pkg/front_end/test/fasta/types/kernel_type_parser_test.dart
+++ b/pkg/front_end/test/fasta/types/kernel_type_parser_test.dart
@@ -34,6 +34,10 @@
 class Sub extends Super;
 class FBound<T extends FBound<T>>;
 class MixinApplication extends Object with FBound<MixinApplication>;
+class ExtendedClass;
+class ExtendedGenericClass<X>;
+extension Extension on ExtendedClass;
+extension GenericExtension<Y> on ExtendedGenericClass<Y>;
 """;
 
 const String expectedSdk = """
@@ -81,6 +85,14 @@
 }
 class MixinApplication = self::Object with self::FBound<self::MixinApplication> {
 }
+class ExtendedClass extends self::Object {
+}
+class ExtendedGenericClass<X extends self::Object? = dynamic> extends self::Object {
+}
+extension Extension on self::ExtendedClass {
+}
+extension GenericExtension<Y extends self::Object? = dynamic> on self::ExtendedGenericClass<Y%> {
+}
 """;
 
 Component parseSdk(Uri uri, TypeParserEnvironment environment) {
diff --git a/pkg/kernel/lib/testing/type_parser.dart b/pkg/kernel/lib/testing/type_parser.dart
index 4b935b4e..45ffeab 100644
--- a/pkg/kernel/lib/testing/type_parser.dart
+++ b/pkg/kernel/lib/testing/type_parser.dart
@@ -123,6 +123,32 @@
   }
 }
 
+class ParsedExtension extends ParsedDeclaration {
+  final List<ParsedTypeVariable> typeVariables;
+  final ParsedInterfaceType onType;
+
+  ParsedExtension(String name, this.typeVariables, this.onType) : super(name);
+
+  String toString() {
+    StringBuffer sb = new StringBuffer();
+    sb.write("extension ");
+    sb.write(name);
+    if (typeVariables.isNotEmpty) {
+      sb.write("<");
+      sb.writeAll(typeVariables, ", ");
+      sb.write(">");
+    }
+    sb.write(" on ");
+    sb.write(onType);
+    sb.write(";");
+    return "$sb";
+  }
+
+  R accept<R, A>(Visitor<R, A> visitor, [A a]) {
+    return visitor.visitExtension(this, a);
+  }
+}
+
 class ParsedTypedef extends ParsedDeclaration {
   final List<ParsedTypeVariable> typeVariables;
 
@@ -347,6 +373,7 @@
   ParsedType parseType() {
     if (optional("class")) return parseClass();
     if (optional("typedef")) return parseTypedef();
+    if (optional("extension")) return parseExtension();
     List<ParsedType> results = <ParsedType>[];
     do {
       ParsedType type;
@@ -494,6 +521,16 @@
         name, typeVariables, supertype, mixedInType, interfaces, callableType);
   }
 
+  ParsedExtension parseExtension() {
+    expect("extension");
+    String name = parseName();
+    List<ParsedTypeVariable> typeVariables = parseTypeVariablesOpt();
+    expect("on");
+    ParsedType onType = parseType();
+    expect(";");
+    return new ParsedExtension(name, typeVariables, onType);
+  }
+
   /// This parses a general typedef on this form:
   ///
   ///     typedef <name> <type-variables-opt> <type> ;
@@ -628,6 +665,10 @@
     return DefaultAction.perform<R, A>(this, node, a);
   }
 
+  R visitExtension(ParsedExtension node, A a) {
+    return DefaultAction.perform<R, A>(this, node, a);
+  }
+
   R visitTypedef(ParsedTypedef node, A a) {
     return DefaultAction.perform<R, A>(this, node, a);
   }
diff --git a/pkg/kernel/lib/testing/type_parser_environment.dart b/pkg/kernel/lib/testing/type_parser_environment.dart
index fcc984c..262ae20 100644
--- a/pkg/kernel/lib/testing/type_parser_environment.dart
+++ b/pkg/kernel/lib/testing/type_parser_environment.dart
@@ -4,30 +4,7 @@
 
 // @dart = 2.9
 
-import "package:kernel/ast.dart"
-    show
-        Class,
-        Component,
-        DartType,
-        DynamicType,
-        FunctionType,
-        FutureOrType,
-        InterfaceType,
-        InvalidType,
-        Library,
-        NamedType,
-        NeverType,
-        Node,
-        NullType,
-        Nullability,
-        Supertype,
-        TreeNode,
-        TypeParameter,
-        TypeParameterType,
-        Typedef,
-        TypedefType,
-        VoidType,
-        setParents;
+import "package:kernel/ast.dart" hide Visitor;
 
 import 'package:kernel/core_types.dart' show CoreTypes;
 
@@ -78,6 +55,13 @@
           new Class(fileUri: fileUri, name: name)
             ..typeParameters.addAll(new List<TypeParameter>.filled(
                 type.typeVariables.length, null)));
+    } else if (type is ParsedExtension) {
+      String name = type.name;
+      environment._registerDeclaration(
+          name,
+          new Extension(fileUri: fileUri, name: name)
+            ..typeParameters.addAll(new List<TypeParameter>.filled(
+                type.typeVariables.length, null)));
     }
   }
   for (ParsedType type in types) {
@@ -86,6 +70,8 @@
       library.addClass(node);
     } else if (node is Typedef) {
       library.addTypedef(node);
+    } else if (node is Extension) {
+      library.addExtension(node);
     } else {
       throw "Unsupported: $node";
     }
@@ -381,6 +367,26 @@
     return cls;
   }
 
+  Extension visitExtension(
+      ParsedExtension node, TypeParserEnvironment environment) {
+    String name = node.name;
+    Extension ext = environment.lookupDeclaration(name);
+    ParameterEnvironment parameterEnvironment =
+        computeTypeParameterEnvironment(node.typeVariables, environment);
+    List<TypeParameter> parameters = parameterEnvironment.parameters;
+    setParents(parameters, ext);
+    ext.typeParameters
+      ..clear()
+      ..addAll(parameters);
+    {
+      TypeParserEnvironment environment = parameterEnvironment.environment;
+      InterfaceType onType =
+          node.onType?.accept<Node, TypeParserEnvironment>(this, environment);
+      ext.onType = onType;
+    }
+    return ext;
+  }
+
   Typedef visitTypedef(ParsedTypedef node, TypeParserEnvironment environment) {
     String name = node.name;
     Typedef def = environment._registerDeclaration(