[CFE] Error in outline and recover from type parameter in static field in class

Change-Id: I7127a6acd85c3133912d70abb28285989aeeae61
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/138809
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/fasta/builder/field_builder.dart b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
index 97b2ede..df4c39b 100644
--- a/pkg/front_end/lib/src/fasta/builder/field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/field_builder.dart
@@ -252,7 +252,7 @@
 
   void build(SourceLibraryBuilder libraryBuilder) {
     if (type != null) {
-      fieldType = type.build(libraryBuilder);
+      fieldType = type.build(libraryBuilder, null, isStatic);
     }
     _fieldEncoding.build(libraryBuilder, this);
   }
diff --git a/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
index 8d18032..7675648 100644
--- a/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/fixed_type_builder.dart
@@ -28,7 +28,10 @@
     return buffer;
   }
 
-  DartType build(LibraryBuilder library, [TypedefType origin]) => type;
+  DartType build(LibraryBuilder library,
+      [TypedefType origin, bool notInstanceContext]) {
+    return type;
+  }
 
   Supertype buildSupertype(
       LibraryBuilder library, int charOffset, Uri fileUri) {
diff --git a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
index c1aa78c1..521e537 100644
--- a/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/function_type_builder.dart
@@ -71,7 +71,8 @@
     return buffer;
   }
 
-  FunctionType build(LibraryBuilder library, [TypedefType origin]) {
+  FunctionType build(LibraryBuilder library,
+      [TypedefType origin, bool notInstanceContext]) {
     DartType builtReturnType =
         returnType?.build(library) ?? const DynamicType();
     List<DartType> positionalParameters = <DartType>[];
diff --git a/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart b/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart
index 4387c8e..1991aed 100644
--- a/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/mixin_application_builder.dart
@@ -43,7 +43,8 @@
   }
 
   @override
-  InterfaceType build(LibraryBuilder library, [TypedefType origin]) {
+  InterfaceType build(LibraryBuilder library,
+      [TypedefType origin, bool notInstanceContext]) {
     int charOffset = -1; // TODO(ahe): Provide these.
     Uri fileUri = null; // TODO(ahe): Provide these.
     return unsupported("build", charOffset, fileUri);
diff --git a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
index 46e5327..d4601f5 100644
--- a/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
@@ -6,18 +6,31 @@
 
 import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;
 
-import 'package:kernel/ast.dart' show DartType, Supertype, TypedefType;
+import 'package:kernel/ast.dart'
+    show
+        Class,
+        DartType,
+        Extension,
+        InvalidType,
+        Supertype,
+        TreeNode,
+        TypeParameter,
+        TypedefType;
 
 import '../fasta_codes.dart'
     show
-        Message,
-        Template,
-        noLength,
-        templateMissingExplicitTypeArguments,
-        messageNotATypeContext,
         LocatedMessage,
+        Message,
+        Severity,
+        Template,
+        messageNotATypeContext,
+        messageTypeVariableInStaticContext,
+        noLength,
         templateExtendingRestricted,
+        templateMissingExplicitTypeArguments,
         templateNotAType,
+        templateSupertypeIsIllegal,
+        templateSupertypeIsTypeVariable,
         templateTypeArgumentMismatch,
         templateTypeArgumentsOnTypeVariable,
         templateTypeNotFound;
@@ -50,14 +63,18 @@
 
   final NullabilityBuilder nullabilityBuilder;
 
+  final Uri fileUri;
+  final int charOffset;
+
   @override
   TypeDeclarationBuilder declaration;
 
-  NamedTypeBuilder(this.name, this.nullabilityBuilder, this.arguments);
+  NamedTypeBuilder(this.name, this.nullabilityBuilder, this.arguments,
+      [this.fileUri, this.charOffset]);
 
   NamedTypeBuilder.fromTypeDeclarationBuilder(
       this.declaration, this.nullabilityBuilder,
-      [this.arguments])
+      [this.arguments, this.fileUri, this.charOffset])
       : this.name = declaration.name;
 
   @override
@@ -218,8 +235,23 @@
   }
 
   // TODO(johnniwinther): Store [origin] on the built type.
-  DartType build(LibraryBuilder library, [TypedefType origin]) {
+  DartType build(LibraryBuilder library,
+      [TypedefType origin, bool notInstanceContext]) {
     assert(declaration != null, "Declaration has not been resolved on $this.");
+    if (notInstanceContext == true && declaration.isTypeVariable) {
+      TypeVariableBuilder typeParameterBuilder = declaration;
+      TypeParameter typeParameter = typeParameterBuilder.parameter;
+      if (typeParameter.parent is Class || typeParameter.parent is Extension) {
+        messageTypeVariableInStaticContext;
+        library.addProblem(
+            messageTypeVariableInStaticContext,
+            charOffset ?? TreeNode.noOffset,
+            noLength,
+            fileUri ?? library.fileUri);
+        return const InvalidType();
+      }
+    }
+
     return declaration.buildType(library, nullabilityBuilder, arguments);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/type_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_builder.dart
index d3e7c8e..01d5a33 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_builder.dart
@@ -55,7 +55,8 @@
 
   String get fullNameForErrors => "${printOn(new StringBuffer())}";
 
-  DartType build(LibraryBuilder library, [TypedefType origin]);
+  DartType build(LibraryBuilder library,
+      [TypedefType origin, bool notInstanceContext]);
 
   Supertype buildSupertype(LibraryBuilder library, int charOffset, Uri fileUri);
 
diff --git a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
index c34ef54..277e05c 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart
@@ -127,7 +127,8 @@
   }
 
   TypeBuilder asTypeBuilder() {
-    return new NamedTypeBuilder(name, const NullabilityBuilder.omitted(), null)
+    return new NamedTypeBuilder(
+        name, const NullabilityBuilder.omitted(), null, fileUri, charOffset)
       ..bind(this);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 82b8342..7cadadf 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -3090,8 +3090,12 @@
         libraryBuilder.addProblem(
             message, offset, lengthOfSpan(beginToken, suffix), uri);
         push(new UnresolvedType(
-            new NamedTypeBuilder(name,
-                libraryBuilder.nullableBuilderIfTrue(isMarkedAsNullable), null)
+            new NamedTypeBuilder(
+                name,
+                libraryBuilder.nullableBuilderIfTrue(isMarkedAsNullable),
+                null,
+                uri,
+                offset)
               ..bind(new InvalidTypeDeclarationBuilder(
                   name,
                   message.withLocation(
@@ -3180,7 +3184,8 @@
     int offset = offsetForToken(token);
     // "void" is always nullable.
     push(new UnresolvedType(
-        new NamedTypeBuilder("void", const NullabilityBuilder.nullable(), null)
+        new NamedTypeBuilder(
+            "void", const NullabilityBuilder.nullable(), null, uri, offset)
           ..bind(new VoidTypeBuilder(const VoidType(), libraryBuilder, offset)),
         offset,
         uri));
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 33555b8..b2a1e9e 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -1865,7 +1865,11 @@
                     builder.name, via.join("', '"));
             addProblem(message, builder.charOffset, builder.name.length);
             builder.bound = new NamedTypeBuilder(
-                builder.name, const NullabilityBuilder.omitted(), null)
+                builder.name,
+                const NullabilityBuilder.omitted(),
+                null,
+                uri,
+                builder.charOffset)
               ..bind(new InvalidTypeDeclarationBuilder(
                   builder.name,
                   message.withLocation(
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 618f8c2..8f4d344 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -1262,7 +1262,9 @@
   TypeBuilder addNamedType(Object name, NullabilityBuilder nullabilityBuilder,
       List<TypeBuilder> arguments, int charOffset) {
     return addType(
-        new NamedTypeBuilder(name, nullabilityBuilder, arguments), charOffset);
+        new NamedTypeBuilder(
+            name, nullabilityBuilder, arguments, fileUri, charOffset),
+        charOffset);
   }
 
   TypeBuilder addMixinApplication(
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart
index 4ff87d7..9a01ce1 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart
@@ -19,6 +19,7 @@
   static void foo12(void Function(U) b) { return null; }
   // old syntax: variable named "b" of type "U" of a function called 'Function'.
   static void foo13(void Function(U b)) { return null; }
+  static U foo14 = null;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.outline.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.outline.expect
index b8ae066..5db43ea 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.outline.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.outline.expect
@@ -30,10 +30,15 @@
 //   static void foo13(void Function(U b)) { return null; }
 //               ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:22:10: Error: Type variables can't be used in static members.
+//   static U foo14 = null;
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
 class Foo<U extends core::Object* = dynamic> extends core::Object {
+  static field invalid-type foo14;
   synthetic constructor •() → self::Foo<self::Foo::U*>*
     ;
   static method foo1() → dynamic
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.expect
index ff33285..966ed95 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.expect
@@ -30,6 +30,10 @@
 //   static void foo13(void Function(U b)) { return null; }
 //               ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:22:10: Error: Type variables can't be used in static members.
+//   static U foo14 = null;
+//          ^
+//
 // pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:7:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
 //                    ^
@@ -78,6 +82,7 @@
 import "dart:core" as core;
 
 class Foo<U extends core::Object* = dynamic> extends core::Object {
+  static field invalid-type foo14 = null;
   synthetic constructor •() → self::Foo<self::Foo::U*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.transformed.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.transformed.expect
index ff33285..966ed95 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart.strong.transformed.expect
@@ -30,6 +30,10 @@
 //   static void foo13(void Function(U b)) { return null; }
 //               ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:22:10: Error: Type variables can't be used in static members.
+//   static U foo14 = null;
+//          ^
+//
 // pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_class.dart:7:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
 //                    ^
@@ -78,6 +82,7 @@
 import "dart:core" as core;
 
 class Foo<U extends core::Object* = dynamic> extends core::Object {
+  static field invalid-type foo14 = null;
   synthetic constructor •() → self::Foo<self::Foo::U*>*
     : super core::Object::•()
     ;
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart
index 2cbab2d..7c56bec 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart
@@ -19,6 +19,7 @@
   static void foo12(void Function(U) b) { return null; }
   // old syntax: variable named "b" of type "U" of a function called 'Function'.
   static void foo13(void Function(U b)) { return null; }
+  static U foo14 = null;
 }
 
 main() {}
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.outline.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.outline.expect
index b74feb4..ef530f4 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.outline.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.outline.expect
@@ -30,6 +30,10 @@
 //   static void foo13(void Function(U b)) { return null; }
 //               ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:22:10: Error: Type variables can't be used in static members.
+//   static U foo14 = null;
+//          ^
+//
 import self as self;
 import "dart:core" as core;
 
@@ -43,7 +47,9 @@
   static method foo11 = self::Foo|foo11;
   static method foo12 = self::Foo|foo12;
   static method foo13 = self::Foo|foo13;
+  static field foo14 = self::Foo|foo14;
 }
+static field invalid-type Foo|foo14;
 static method Foo|foo1() → dynamic
   ;
 static method Foo|foo2(dynamic x) → void
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.expect
index 8c2c382..e6a1aa9 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.expect
@@ -30,6 +30,10 @@
 //   static void foo13(void Function(U b)) { return null; }
 //               ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:22:10: Error: Type variables can't be used in static members.
+//   static U foo14 = null;
+//          ^
+//
 // pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:7:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
 //                    ^
@@ -87,7 +91,9 @@
   static method foo11 = self::Foo|foo11;
   static method foo12 = self::Foo|foo12;
   static method foo13 = self::Foo|foo13;
+  static field foo14 = self::Foo|foo14;
 }
+static field invalid-type Foo|foo14 = null;
 static method Foo|foo1() → dynamic {
   return null;
 }
diff --git a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.transformed.expect b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.transformed.expect
index 8c2c382..e6a1aa9 100644
--- a/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart.strong.transformed.expect
@@ -30,6 +30,10 @@
 //   static void foo13(void Function(U b)) { return null; }
 //               ^
 //
+// pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:22:10: Error: Type variables can't be used in static members.
+//   static U foo14 = null;
+//          ^
+//
 // pkg/front_end/testcases/general/type_parameter_usage_in_static_method_in_extension.dart:7:20: Error: Type variables can't be used in static members.
 //   static void foo2(U x) { return null; }
 //                    ^
@@ -87,7 +91,9 @@
   static method foo11 = self::Foo|foo11;
   static method foo12 = self::Foo|foo12;
   static method foo13 = self::Foo|foo13;
+  static field foo14 = self::Foo|foo14;
 }
+static field invalid-type Foo|foo14 = null;
 static method Foo|foo1() → dynamic {
   return null;
 }