Add the class NonNullableTypeProvider to access SDK classes in opted-in context

Change-Id: Id0cd7c8cd6f93701a5e603753b10a27236292d41
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/102202
Reviewed-by: Mike Fairhurst <mfairhurst@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index edb112e..f66ceb7 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -3402,6 +3402,23 @@
   }
 }
 
+/// A type provider that returns non-nullable versions of the SDK types.
+class NonNullableTypeProvider extends TypeProviderImpl {
+  NonNullableTypeProvider(
+      LibraryElement coreLibrary, LibraryElement asyncLibrary)
+      : super(coreLibrary, asyncLibrary);
+
+  @override
+  InterfaceType _getType(Namespace namespace, String typeName) {
+    InterfaceType type = super._getType(namespace, typeName);
+    if (type == null) {
+      return null;
+    }
+    return (type as TypeImpl).withNullability(NullabilitySuffix.none)
+        as InterfaceType;
+  }
+}
+
 /// Instances of the class `OverrideVerifier` visit all of the declarations in a
 /// compilation unit to verify that if they have an override annotation it is
 /// being used correctly.
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 5a190a0..3ec7c06 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -44,6 +44,7 @@
     defineReflectiveTests(ErrorResolverTest);
     defineReflectiveTests(LibraryImportScopeTest);
     defineReflectiveTests(LibraryScopeTest);
+    defineReflectiveTests(NonNullableTypeProviderTest);
     defineReflectiveTests(PrefixedNamespaceTest);
     defineReflectiveTests(ScopeTest);
     defineReflectiveTests(StrictModeTest);
@@ -333,6 +334,129 @@
 }
 
 @reflectiveTest
+class NonNullableTypeProviderTest extends EngineTestCase {
+  void assertNonNullable(InterfaceType type) {
+    expect((type as TypeImpl).nullabilitySuffix, NullabilitySuffix.none);
+  }
+
+  void test_creation() {
+    //
+    // Create a mock library element with the types expected to be in dart:core.
+    // We cannot use either ElementFactory or TestTypeProvider (which uses
+    // ElementFactory) because we side-effect the elements in ways that would
+    // break other tests.
+    //
+    InterfaceType objectType = _classElement("Object", null).type;
+    InterfaceType boolType = _classElement("bool", objectType).type;
+    InterfaceType numType = _classElement("num", objectType).type;
+    InterfaceType deprecatedType = _classElement('Deprecated', objectType).type;
+    InterfaceType doubleType = _classElement("double", numType).type;
+    InterfaceType functionType = _classElement("Function", objectType).type;
+    InterfaceType futureType = _classElement("Future", objectType, ["T"]).type;
+    InterfaceType futureOrType =
+        _classElement("FutureOr", objectType, ["T"]).type;
+    InterfaceType intType = _classElement("int", numType).type;
+    InterfaceType iterableType =
+        _classElement("Iterable", objectType, ["T"]).type;
+    InterfaceType listType = _classElement("List", objectType, ["E"]).type;
+    InterfaceType mapType = _classElement("Map", objectType, ["K", "V"]).type;
+    InterfaceType nullType = _classElement('Null', objectType).type;
+    InterfaceType setType = _classElement("Set", objectType, ["E"]).type;
+    InterfaceType stackTraceType = _classElement("StackTrace", objectType).type;
+    InterfaceType streamType = _classElement("Stream", objectType, ["T"]).type;
+    InterfaceType stringType = _classElement("String", objectType).type;
+    InterfaceType symbolType = _classElement("Symbol", objectType).type;
+    InterfaceType typeType = _classElement("Type", objectType).type;
+    CompilationUnitElementImpl coreUnit = new CompilationUnitElementImpl();
+    coreUnit.types = <ClassElement>[
+      boolType.element,
+      deprecatedType.element,
+      doubleType.element,
+      functionType.element,
+      intType.element,
+      iterableType.element,
+      listType.element,
+      mapType.element,
+      nullType.element,
+      numType.element,
+      setType.element,
+      objectType.element,
+      stackTraceType.element,
+      stringType.element,
+      symbolType.element,
+      typeType.element
+    ];
+    coreUnit.source = new TestSource('dart:core');
+    coreUnit.librarySource = coreUnit.source;
+    CompilationUnitElementImpl asyncUnit = new CompilationUnitElementImpl();
+    asyncUnit.types = <ClassElement>[
+      futureType.element,
+      futureOrType.element,
+      streamType.element
+    ];
+    asyncUnit.source = new TestSource('dart:async');
+    asyncUnit.librarySource = asyncUnit.source;
+    LibraryElementImpl coreLibrary = new LibraryElementImpl.forNode(
+        null, null, AstTestFactory.libraryIdentifier2(["dart.core"]));
+    coreLibrary.definingCompilationUnit = coreUnit;
+    LibraryElementImpl asyncLibrary = new LibraryElementImpl.forNode(
+        null, null, AstTestFactory.libraryIdentifier2(["dart.async"]));
+    asyncLibrary.definingCompilationUnit = asyncUnit;
+    //
+    // Create a type provider and ensure that it can return the expected types.
+    //
+    TypeProvider provider =
+        new NonNullableTypeProvider(coreLibrary, asyncLibrary);
+    assertNonNullable(provider.boolType);
+    expect(provider.bottomType, isNotNull);
+    assertNonNullable(provider.deprecatedType);
+    assertNonNullable(provider.doubleType);
+    expect(provider.dynamicType, isNotNull);
+    assertNonNullable(provider.functionType);
+    assertNonNullable(provider.futureType);
+    assertNonNullable(provider.futureOrType);
+    assertNonNullable(provider.intType);
+    assertNonNullable(provider.listType);
+    assertNonNullable(provider.mapType);
+    expect(provider.neverType, isNotNull);
+    assertNonNullable(provider.nullType);
+    assertNonNullable(provider.numType);
+    assertNonNullable(provider.objectType);
+    assertNonNullable(provider.stackTraceType);
+    assertNonNullable(provider.streamType);
+    assertNonNullable(provider.stringType);
+    assertNonNullable(provider.symbolType);
+    assertNonNullable(provider.typeType);
+  }
+
+  ClassElement _classElement(String typeName, InterfaceType superclassType,
+      [List<String> parameterNames]) {
+    ClassElementImpl element =
+        new ClassElementImpl.forNode(AstTestFactory.identifier3(typeName));
+    element.supertype = superclassType;
+    if (parameterNames != null) {
+      int count = parameterNames.length;
+      if (count > 0) {
+        List<TypeParameterElementImpl> typeParameters =
+            new List<TypeParameterElementImpl>(count);
+        List<TypeParameterTypeImpl> typeArguments =
+            new List<TypeParameterTypeImpl>(count);
+        for (int i = 0; i < count; i++) {
+          TypeParameterElementImpl typeParameter =
+              new TypeParameterElementImpl.forNode(
+                  AstTestFactory.identifier3(parameterNames[i]));
+          typeParameters[i] = typeParameter;
+          typeArguments[i] = new TypeParameterTypeImpl(typeParameter);
+          typeParameter.type = typeArguments[i];
+        }
+        element.typeParameters = typeParameters;
+      }
+    }
+    return element;
+  }
+}
+
+@reflectiveTest
 class PrefixedNamespaceTest extends DriverResolutionTest {
   void test_lookup_missing() {
     ClassElement element = ElementFactory.classElement2('A');