Consolidate common code between the two type schema environment tests.
Change-Id: I014f6024372e57577026f0a1f2dda905899c3b00
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/241200
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Chloe Stefantsova <cstefantsova@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart
index ea04c62..dadd9ee 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_nnbd_test.dart
@@ -2,16 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:front_end/src/fasta/type_inference/type_constraint_gatherer.dart';
-import 'package:front_end/src/fasta/type_inference/type_schema.dart';
-import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart';
import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
-import 'package:kernel/class_hierarchy.dart';
-import 'package:kernel/testing/type_parser_environment.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'type_schema_environment_test_base.dart';
+
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(TypeSchemaEnvironmentTest);
@@ -19,47 +15,9 @@
}
@reflectiveTest
-class TypeSchemaEnvironmentTest {
- late Env typeParserEnvironment;
- late TypeSchemaEnvironment typeSchemaEnvironment;
-
- final Map<String, DartType Function()> additionalTypes = {
- "UNKNOWN": () => new UnknownType(),
- };
-
- late Library _coreLibrary;
- late Library _testLibrary;
-
- Library get coreLibrary => _coreLibrary;
- Library get testLibrary => _testLibrary;
-
- Component get component => typeParserEnvironment.component;
- CoreTypes get coreTypes => typeParserEnvironment.coreTypes;
-
- void parseTestLibrary(String testLibraryText) {
- typeParserEnvironment =
- new Env(testLibraryText, isNonNullableByDefault: true);
- typeSchemaEnvironment = new TypeSchemaEnvironment(
- coreTypes, new ClassHierarchy(component, coreTypes));
- assert(
- typeParserEnvironment.component.libraries.length == 2,
- "The tests are supposed to have exactly two libraries: "
- "the core library and the test library.");
- Library firstLibrary = typeParserEnvironment.component.libraries.first;
- Library secondLibrary = typeParserEnvironment.component.libraries.last;
- if (firstLibrary.importUri.isScheme("dart") &&
- firstLibrary.importUri.path == "core") {
- _coreLibrary = firstLibrary;
- _testLibrary = secondLibrary;
- } else {
- assert(
- secondLibrary.importUri.isScheme("dart") &&
- secondLibrary.importUri.path == "core",
- "One of the libraries is expected to be 'dart:core'.");
- _coreLibrary == secondLibrary;
- _testLibrary = firstLibrary;
- }
- }
+class TypeSchemaEnvironmentTest extends TypeSchemaEnvironmentTestBase {
+ @override
+ bool get isNonNullableByDefault => true;
void test_addLowerBound() {
parseTestLibrary("""
@@ -1503,68 +1461,6 @@
checkIsSubtype("Pair<A*, Null>*", "Pair<UNKNOWN, UNKNOWN>*");
}
- void checkConstraintSolving(String constraint, String expected,
- {required bool grounded}) {
- expect(
- typeSchemaEnvironment.solveTypeConstraint(
- parseConstraint(constraint),
- coreTypes.objectNullableRawType,
- new NeverType.internal(Nullability.nonNullable),
- grounded: grounded),
- parseType(expected));
- }
-
- void checkConstraintUpperBound(
- {required String constraint, required String bound}) {
- expect(parseConstraint(constraint).upper, parseType(bound));
- }
-
- void checkConstraintLowerBound(
- {required String constraint, required String bound}) {
- expect(parseConstraint(constraint).lower, parseType(bound));
- }
-
- void checkTypeSatisfiesConstraint(String type, String constraint) {
- expect(
- typeSchemaEnvironment.typeSatisfiesConstraint(
- parseType(type), parseConstraint(constraint)),
- isTrue);
- }
-
- void checkTypeDoesntSatisfyConstraint(String type, String constraint) {
- expect(
- typeSchemaEnvironment.typeSatisfiesConstraint(
- parseType(type), parseConstraint(constraint)),
- isFalse);
- }
-
- void checkIsSubtype(String subtype, String supertype) {
- expect(
- typeSchemaEnvironment
- .performNullabilityAwareSubtypeCheck(
- parseType(subtype), parseType(supertype))
- .isSubtypeWhenUsingNullabilities(),
- isTrue);
- }
-
- void checkIsLegacySubtype(String subtype, String supertype) {
- expect(
- typeSchemaEnvironment
- .performNullabilityAwareSubtypeCheck(
- parseType(subtype), parseType(supertype))
- .isSubtypeWhenIgnoringNullabilities(),
- isTrue);
- }
-
- void checkIsNotSubtype(String subtype, String supertype) {
- expect(
- typeSchemaEnvironment
- .performNullabilityAwareSubtypeCheck(
- parseType(subtype), parseType(supertype))
- .isSubtypeWhenIgnoringNullabilities(),
- isFalse);
- }
-
void checkUpperBound(
{required String type1,
required String type2,
@@ -1588,150 +1484,4 @@
parseType(upperBound));
});
}
-
- void checkLowerBound(
- {required String type1,
- required String type2,
- required String lowerBound,
- String? typeParameters}) {
- typeParserEnvironment.withTypeParameters(typeParameters,
- (List<TypeParameter> typeParameterNodes) {
- expect(
- typeSchemaEnvironment.getStandardLowerBound(
- parseType(type1), parseType(type2), testLibrary),
- parseType(lowerBound));
- });
- }
-
- void checkInference(
- {required String typeParametersToInfer,
- required String functionType,
- String? actualParameterTypes,
- String? returnContextType,
- String? inferredTypesFromDownwardPhase,
- required String expectedTypes}) {
- typeParserEnvironment.withTypeParameters(typeParametersToInfer,
- (List<TypeParameter> typeParameterNodesToInfer) {
- FunctionType functionTypeNode = parseType(functionType) as FunctionType;
- DartType? returnContextTypeNode =
- returnContextType == null ? null : parseType(returnContextType);
- List<DartType>? actualTypeNodes = actualParameterTypes == null
- ? null
- : parseTypes(actualParameterTypes);
- List<DartType> expectedTypeNodes = parseTypes(expectedTypes);
- DartType declaredReturnTypeNode = functionTypeNode.returnType;
- List<DartType>? formalTypeNodes = actualParameterTypes == null
- ? null
- : functionTypeNode.positionalParameters;
-
- List<DartType> inferredTypeNodes;
- if (inferredTypesFromDownwardPhase == null) {
- inferredTypeNodes = new List<DartType>.generate(
- typeParameterNodesToInfer.length, (_) => new UnknownType());
- } else {
- inferredTypeNodes = parseTypes(inferredTypesFromDownwardPhase);
- }
-
- TypeConstraintGatherer gatherer =
- typeSchemaEnvironment.setupGenericTypeInference(
- declaredReturnTypeNode,
- typeParameterNodesToInfer,
- returnContextTypeNode,
- testLibrary);
- if (formalTypeNodes == null) {
- typeSchemaEnvironment.downwardsInfer(gatherer,
- typeParameterNodesToInfer, inferredTypeNodes, testLibrary);
- } else {
- gatherer.constrainArguments(formalTypeNodes, actualTypeNodes!);
- typeSchemaEnvironment.upwardsInfer(gatherer, typeParameterNodesToInfer,
- inferredTypeNodes, testLibrary);
- }
-
- assert(
- inferredTypeNodes.length == expectedTypeNodes.length,
- "The numbers of expected types and type parameters to infer "
- "mismatch.");
- for (int i = 0; i < inferredTypeNodes.length; ++i) {
- expect(inferredTypeNodes[i], expectedTypeNodes[i]);
- }
- });
- }
-
- void checkInferenceFromConstraints(
- {required String typeParameter,
- required String constraints,
- String? inferredTypeFromDownwardPhase,
- required bool downwardsInferPhase,
- required String expected}) {
- assert(inferredTypeFromDownwardPhase == null || !downwardsInferPhase);
-
- typeParserEnvironment.withTypeParameters(typeParameter,
- (List<TypeParameter> typeParameterNodes) {
- assert(typeParameterNodes.length == 1);
-
- TypeConstraint typeConstraint = parseConstraint(constraints);
- DartType expectedTypeNode = parseType(expected);
- TypeParameter typeParameterNode = typeParameterNodes.single;
- List<DartType> inferredTypeNodes = <DartType>[
- inferredTypeFromDownwardPhase == null
- ? new UnknownType()
- : parseType(inferredTypeFromDownwardPhase)
- ];
-
- typeSchemaEnvironment.inferTypeFromConstraints(
- {typeParameterNode: typeConstraint},
- [typeParameterNode],
- inferredTypeNodes,
- testLibrary,
- downwardsInferPhase: downwardsInferPhase);
-
- expect(inferredTypeNodes.single, expectedTypeNode);
- });
- }
-
- /// Parses a string like "<: T <: S >: R" into a [TypeConstraint].
- ///
- /// The [constraint] string is assumed to be a sequence of bounds added to the
- /// constraint. Each element of the sequence is either "<: T" or ":> T",
- /// where the former adds an upper bound and the latter adds a lower bound.
- /// The bounds are added to the constraint in the order they are mentioned in
- /// the [constraint] string, from left to right.
- TypeConstraint parseConstraint(String constraint) {
- TypeConstraint result = new TypeConstraint();
- List<String> upperBoundSegments = constraint.split("<:");
- bool firstUpperBoundSegment = true;
- for (String upperBoundSegment in upperBoundSegments) {
- if (firstUpperBoundSegment) {
- firstUpperBoundSegment = false;
- if (upperBoundSegment.isEmpty) {
- continue;
- }
- }
- List<String> lowerBoundSegments = upperBoundSegment.split(":>");
- bool firstLowerBoundSegment = true;
- for (String segment in lowerBoundSegments) {
- if (firstLowerBoundSegment) {
- firstLowerBoundSegment = false;
- if (segment.isNotEmpty) {
- typeSchemaEnvironment.addUpperBound(
- result, parseType(segment), testLibrary);
- }
- } else {
- typeSchemaEnvironment.addLowerBound(
- result, parseType(segment), testLibrary);
- }
- }
- }
- return result;
- }
-
- DartType parseType(String type) {
- return typeParserEnvironment.parseType(type,
- additionalTypes: additionalTypes);
- }
-
- List<DartType> parseTypes(String types) {
- return typeParserEnvironment.parseTypes(types,
- additionalTypes: additionalTypes);
- }
}
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
index f603242..d45112f 100644
--- a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test.dart
@@ -2,16 +2,12 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-import 'package:front_end/src/fasta/type_inference/type_constraint_gatherer.dart';
-import 'package:front_end/src/fasta/type_inference/type_schema.dart';
-import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart';
import 'package:kernel/ast.dart';
-import 'package:kernel/core_types.dart';
-import 'package:kernel/class_hierarchy.dart';
-import 'package:kernel/testing/type_parser_environment.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import 'type_schema_environment_test_base.dart';
+
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(TypeSchemaEnvironmentTest);
@@ -19,47 +15,9 @@
}
@reflectiveTest
-class TypeSchemaEnvironmentTest {
- late Env typeParserEnvironment;
- late TypeSchemaEnvironment typeSchemaEnvironment;
-
- final Map<String, DartType Function()> additionalTypes = {
- "UNKNOWN": () => new UnknownType(),
- };
-
- late Library _coreLibrary;
- late Library _testLibrary;
-
- Library get coreLibrary => _coreLibrary;
- Library get testLibrary => _testLibrary;
-
- Component get component => typeParserEnvironment.component;
- CoreTypes get coreTypes => typeParserEnvironment.coreTypes;
-
- void parseTestLibrary(String testLibraryText) {
- typeParserEnvironment =
- new Env(testLibraryText, isNonNullableByDefault: false);
- typeSchemaEnvironment = new TypeSchemaEnvironment(
- coreTypes, new ClassHierarchy(component, coreTypes));
- assert(
- typeParserEnvironment.component.libraries.length == 2,
- "The tests are supposed to have exactly two libraries: "
- "the core library and the test library.");
- Library firstLibrary = typeParserEnvironment.component.libraries.first;
- Library secondLibrary = typeParserEnvironment.component.libraries.last;
- if (firstLibrary.importUri.isScheme("dart") &&
- firstLibrary.importUri.path == "core") {
- _coreLibrary = firstLibrary;
- _testLibrary = secondLibrary;
- } else {
- assert(
- secondLibrary.importUri.isScheme("dart") &&
- secondLibrary.importUri.path == "core",
- "One of the libraries is expected to be 'dart:core'.");
- _coreLibrary == secondLibrary;
- _testLibrary = firstLibrary;
- }
- }
+class TypeSchemaEnvironmentTest extends TypeSchemaEnvironmentTestBase {
+ @override
+ bool get isNonNullableByDefault => false;
void test_addLowerBound() {
parseTestLibrary("class A; class B extends A; class C extends A;");
@@ -585,66 +543,6 @@
checkIsLegacySubtype("Map<A*, A*>*", "Map<UNKNOWN, UNKNOWN>*");
}
- void checkConstraintSolving(String constraint, String expected,
- {required bool grounded}) {
- expect(
- typeSchemaEnvironment.solveTypeConstraint(
- parseConstraint(constraint), new DynamicType(), new NullType(),
- grounded: grounded),
- parseType(expected));
- }
-
- void checkConstraintUpperBound(
- {required String constraint, required String bound}) {
- expect(parseConstraint(constraint).upper, parseType(bound));
- }
-
- void checkConstraintLowerBound(
- {required String constraint, required String bound}) {
- expect(parseConstraint(constraint).lower, parseType(bound));
- }
-
- void checkTypeSatisfiesConstraint(String type, String constraint) {
- expect(
- typeSchemaEnvironment.typeSatisfiesConstraint(
- parseType(type), parseConstraint(constraint)),
- isTrue);
- }
-
- void checkTypeDoesntSatisfyConstraint(String type, String constraint) {
- expect(
- typeSchemaEnvironment.typeSatisfiesConstraint(
- parseType(type), parseConstraint(constraint)),
- isFalse);
- }
-
- void checkIsSubtype(String subtype, String supertype) {
- expect(
- typeSchemaEnvironment
- .performNullabilityAwareSubtypeCheck(
- parseType(subtype), parseType(supertype))
- .isSubtypeWhenUsingNullabilities(),
- isTrue);
- }
-
- void checkIsLegacySubtype(String subtype, String supertype) {
- expect(
- typeSchemaEnvironment
- .performNullabilityAwareSubtypeCheck(
- parseType(subtype), parseType(supertype))
- .isSubtypeWhenIgnoringNullabilities(),
- isTrue);
- }
-
- void checkIsNotSubtype(String subtype, String supertype) {
- expect(
- typeSchemaEnvironment
- .performNullabilityAwareSubtypeCheck(
- parseType(subtype), parseType(supertype))
- .isSubtypeWhenIgnoringNullabilities(),
- isFalse);
- }
-
void checkUpperBound(
{required String type1,
required String type2,
@@ -658,150 +556,4 @@
parseType(upperBound));
});
}
-
- void checkLowerBound(
- {required String type1,
- required String type2,
- required String lowerBound,
- String? typeParameters}) {
- typeParserEnvironment.withTypeParameters(typeParameters,
- (List<TypeParameter> typeParameterNodes) {
- expect(
- typeSchemaEnvironment.getStandardLowerBound(
- parseType(type1), parseType(type2), testLibrary),
- parseType(lowerBound));
- });
- }
-
- void checkInference(
- {required String typeParametersToInfer,
- required String functionType,
- String? actualParameterTypes,
- String? returnContextType,
- String? inferredTypesFromDownwardPhase,
- required String expectedTypes}) {
- typeParserEnvironment.withTypeParameters(typeParametersToInfer,
- (List<TypeParameter> typeParameterNodesToInfer) {
- FunctionType functionTypeNode = parseType(functionType) as FunctionType;
- DartType? returnContextTypeNode =
- returnContextType == null ? null : parseType(returnContextType);
- List<DartType>? actualTypeNodes = actualParameterTypes == null
- ? null
- : parseTypes(actualParameterTypes);
- List<DartType> expectedTypeNodes = parseTypes(expectedTypes);
- DartType declaredReturnTypeNode = functionTypeNode.returnType;
- List<DartType>? formalTypeNodes = actualParameterTypes == null
- ? null
- : functionTypeNode.positionalParameters;
-
- List<DartType> inferredTypeNodes;
- if (inferredTypesFromDownwardPhase == null) {
- inferredTypeNodes = new List<DartType>.generate(
- typeParameterNodesToInfer.length, (_) => new UnknownType());
- } else {
- inferredTypeNodes = parseTypes(inferredTypesFromDownwardPhase);
- }
-
- TypeConstraintGatherer gatherer =
- typeSchemaEnvironment.setupGenericTypeInference(
- declaredReturnTypeNode,
- typeParameterNodesToInfer,
- returnContextTypeNode,
- testLibrary);
- if (formalTypeNodes == null) {
- typeSchemaEnvironment.downwardsInfer(gatherer,
- typeParameterNodesToInfer, inferredTypeNodes, testLibrary);
- } else {
- gatherer.constrainArguments(formalTypeNodes, actualTypeNodes!);
- typeSchemaEnvironment.upwardsInfer(gatherer, typeParameterNodesToInfer,
- inferredTypeNodes, testLibrary);
- }
-
- assert(
- inferredTypeNodes.length == expectedTypeNodes.length,
- "The numbers of expected types and type parameters to infer "
- "mismatch.");
- for (int i = 0; i < inferredTypeNodes.length; ++i) {
- expect(inferredTypeNodes[i], expectedTypeNodes[i]);
- }
- });
- }
-
- void checkInferenceFromConstraints(
- {required String typeParameter,
- required String constraints,
- String? inferredTypeFromDownwardPhase,
- required bool downwardsInferPhase,
- required String expected}) {
- assert(inferredTypeFromDownwardPhase == null || !downwardsInferPhase);
-
- typeParserEnvironment.withTypeParameters(typeParameter,
- (List<TypeParameter> typeParameterNodes) {
- assert(typeParameterNodes.length == 1);
-
- TypeConstraint typeConstraint = parseConstraint(constraints);
- DartType expectedTypeNode = parseType(expected);
- TypeParameter typeParameterNode = typeParameterNodes.single;
- List<DartType> inferredTypeNodes = <DartType>[
- inferredTypeFromDownwardPhase == null
- ? new UnknownType()
- : parseType(inferredTypeFromDownwardPhase)
- ];
-
- typeSchemaEnvironment.inferTypeFromConstraints(
- {typeParameterNode: typeConstraint},
- [typeParameterNode],
- inferredTypeNodes,
- testLibrary,
- downwardsInferPhase: downwardsInferPhase);
-
- expect(inferredTypeNodes.single, expectedTypeNode);
- });
- }
-
- /// Parses a string like "<: T <: S >: R" into a [TypeConstraint].
- ///
- /// The [constraint] string is assumed to be a sequence of bounds added to the
- /// constraint. Each element of the sequence is either "<: T" or ":> T",
- /// where the former adds an upper bound and the latter adds a lower bound.
- /// The bounds are added to the constraint in the order they are mentioned in
- /// the [constraint] string, from left to right.
- TypeConstraint parseConstraint(String constraint) {
- TypeConstraint result = new TypeConstraint();
- List<String> upperBoundSegments = constraint.split("<:");
- bool firstUpperBoundSegment = true;
- for (String upperBoundSegment in upperBoundSegments) {
- if (firstUpperBoundSegment) {
- firstUpperBoundSegment = false;
- if (upperBoundSegment.isEmpty) {
- continue;
- }
- }
- List<String> lowerBoundSegments = upperBoundSegment.split(":>");
- bool firstLowerBoundSegment = true;
- for (String segment in lowerBoundSegments) {
- if (firstLowerBoundSegment) {
- firstLowerBoundSegment = false;
- if (segment.isNotEmpty) {
- typeSchemaEnvironment.addUpperBound(
- result, parseType(segment), testLibrary);
- }
- } else {
- typeSchemaEnvironment.addLowerBound(
- result, parseType(segment), testLibrary);
- }
- }
- }
- return result;
- }
-
- DartType parseType(String type) {
- return typeParserEnvironment.parseType(type,
- additionalTypes: additionalTypes);
- }
-
- List<DartType> parseTypes(String types) {
- return typeParserEnvironment.parseTypes(types,
- additionalTypes: additionalTypes);
- }
}
diff --git a/pkg/front_end/test/fasta/type_inference/type_schema_environment_test_base.dart b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test_base.dart
new file mode 100644
index 0000000..2e9bf18
--- /dev/null
+++ b/pkg/front_end/test/fasta/type_inference/type_schema_environment_test_base.dart
@@ -0,0 +1,269 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:front_end/src/fasta/type_inference/type_constraint_gatherer.dart';
+import 'package:front_end/src/fasta/type_inference/type_schema.dart';
+import 'package:front_end/src/fasta/type_inference/type_schema_environment.dart';
+import 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/class_hierarchy.dart';
+import 'package:kernel/testing/type_parser_environment.dart';
+import 'package:test/test.dart';
+
+abstract class TypeSchemaEnvironmentTestBase {
+ bool get isNonNullableByDefault;
+
+ late Env typeParserEnvironment;
+ late TypeSchemaEnvironment typeSchemaEnvironment;
+
+ final Map<String, DartType Function()> additionalTypes = {
+ "UNKNOWN": () => new UnknownType(),
+ };
+
+ late Library _coreLibrary;
+ late Library _testLibrary;
+
+ Library get coreLibrary => _coreLibrary;
+ Library get testLibrary => _testLibrary;
+
+ Component get component => typeParserEnvironment.component;
+ CoreTypes get coreTypes => typeParserEnvironment.coreTypes;
+
+ void parseTestLibrary(String testLibraryText) {
+ typeParserEnvironment = new Env(testLibraryText,
+ isNonNullableByDefault: isNonNullableByDefault);
+ typeSchemaEnvironment = new TypeSchemaEnvironment(
+ coreTypes, new ClassHierarchy(component, coreTypes));
+ assert(
+ typeParserEnvironment.component.libraries.length == 2,
+ "The tests are supposed to have exactly two libraries: "
+ "the core library and the test library.");
+ Library firstLibrary = typeParserEnvironment.component.libraries.first;
+ Library secondLibrary = typeParserEnvironment.component.libraries.last;
+ if (firstLibrary.importUri.isScheme("dart") &&
+ firstLibrary.importUri.path == "core") {
+ _coreLibrary = firstLibrary;
+ _testLibrary = secondLibrary;
+ } else {
+ assert(
+ secondLibrary.importUri.isScheme("dart") &&
+ secondLibrary.importUri.path == "core",
+ "One of the libraries is expected to be 'dart:core'.");
+ _coreLibrary == secondLibrary;
+ _testLibrary = firstLibrary;
+ }
+ }
+
+ void checkConstraintSolving(String constraint, String expected,
+ {required bool grounded}) {
+ expect(
+ typeSchemaEnvironment.solveTypeConstraint(
+ parseConstraint(constraint),
+ isNonNullableByDefault
+ ? coreTypes.objectNullableRawType
+ : new DynamicType(),
+ isNonNullableByDefault
+ ? new NeverType.internal(Nullability.nonNullable)
+ : new NullType(),
+ grounded: grounded),
+ parseType(expected));
+ }
+
+ void checkConstraintUpperBound(
+ {required String constraint, required String bound}) {
+ expect(parseConstraint(constraint).upper, parseType(bound));
+ }
+
+ void checkConstraintLowerBound(
+ {required String constraint, required String bound}) {
+ expect(parseConstraint(constraint).lower, parseType(bound));
+ }
+
+ void checkTypeSatisfiesConstraint(String type, String constraint) {
+ expect(
+ typeSchemaEnvironment.typeSatisfiesConstraint(
+ parseType(type), parseConstraint(constraint)),
+ isTrue);
+ }
+
+ void checkTypeDoesntSatisfyConstraint(String type, String constraint) {
+ expect(
+ typeSchemaEnvironment.typeSatisfiesConstraint(
+ parseType(type), parseConstraint(constraint)),
+ isFalse);
+ }
+
+ void checkIsSubtype(String subtype, String supertype) {
+ expect(
+ typeSchemaEnvironment
+ .performNullabilityAwareSubtypeCheck(
+ parseType(subtype), parseType(supertype))
+ .isSubtypeWhenUsingNullabilities(),
+ isTrue);
+ }
+
+ void checkIsLegacySubtype(String subtype, String supertype) {
+ expect(
+ typeSchemaEnvironment
+ .performNullabilityAwareSubtypeCheck(
+ parseType(subtype), parseType(supertype))
+ .isSubtypeWhenIgnoringNullabilities(),
+ isTrue);
+ }
+
+ void checkIsNotSubtype(String subtype, String supertype) {
+ expect(
+ typeSchemaEnvironment
+ .performNullabilityAwareSubtypeCheck(
+ parseType(subtype), parseType(supertype))
+ .isSubtypeWhenIgnoringNullabilities(),
+ isFalse);
+ }
+
+ void checkLowerBound(
+ {required String type1,
+ required String type2,
+ required String lowerBound,
+ String? typeParameters}) {
+ typeParserEnvironment.withTypeParameters(typeParameters,
+ (List<TypeParameter> typeParameterNodes) {
+ expect(
+ typeSchemaEnvironment.getStandardLowerBound(
+ parseType(type1), parseType(type2), testLibrary),
+ parseType(lowerBound));
+ });
+ }
+
+ void checkInference(
+ {required String typeParametersToInfer,
+ required String functionType,
+ String? actualParameterTypes,
+ String? returnContextType,
+ String? inferredTypesFromDownwardPhase,
+ required String expectedTypes}) {
+ typeParserEnvironment.withTypeParameters(typeParametersToInfer,
+ (List<TypeParameter> typeParameterNodesToInfer) {
+ FunctionType functionTypeNode = parseType(functionType) as FunctionType;
+ DartType? returnContextTypeNode =
+ returnContextType == null ? null : parseType(returnContextType);
+ List<DartType>? actualTypeNodes = actualParameterTypes == null
+ ? null
+ : parseTypes(actualParameterTypes);
+ List<DartType> expectedTypeNodes = parseTypes(expectedTypes);
+ DartType declaredReturnTypeNode = functionTypeNode.returnType;
+ List<DartType>? formalTypeNodes = actualParameterTypes == null
+ ? null
+ : functionTypeNode.positionalParameters;
+
+ List<DartType> inferredTypeNodes;
+ if (inferredTypesFromDownwardPhase == null) {
+ inferredTypeNodes = new List<DartType>.generate(
+ typeParameterNodesToInfer.length, (_) => new UnknownType());
+ } else {
+ inferredTypeNodes = parseTypes(inferredTypesFromDownwardPhase);
+ }
+
+ TypeConstraintGatherer gatherer =
+ typeSchemaEnvironment.setupGenericTypeInference(
+ declaredReturnTypeNode,
+ typeParameterNodesToInfer,
+ returnContextTypeNode,
+ testLibrary);
+ if (formalTypeNodes == null) {
+ typeSchemaEnvironment.downwardsInfer(gatherer,
+ typeParameterNodesToInfer, inferredTypeNodes, testLibrary);
+ } else {
+ gatherer.constrainArguments(formalTypeNodes, actualTypeNodes!);
+ typeSchemaEnvironment.upwardsInfer(gatherer, typeParameterNodesToInfer,
+ inferredTypeNodes, testLibrary);
+ }
+
+ assert(
+ inferredTypeNodes.length == expectedTypeNodes.length,
+ "The numbers of expected types and type parameters to infer "
+ "mismatch.");
+ for (int i = 0; i < inferredTypeNodes.length; ++i) {
+ expect(inferredTypeNodes[i], expectedTypeNodes[i]);
+ }
+ });
+ }
+
+ void checkInferenceFromConstraints(
+ {required String typeParameter,
+ required String constraints,
+ String? inferredTypeFromDownwardPhase,
+ required bool downwardsInferPhase,
+ required String expected}) {
+ assert(inferredTypeFromDownwardPhase == null || !downwardsInferPhase);
+
+ typeParserEnvironment.withTypeParameters(typeParameter,
+ (List<TypeParameter> typeParameterNodes) {
+ assert(typeParameterNodes.length == 1);
+
+ TypeConstraint typeConstraint = parseConstraint(constraints);
+ DartType expectedTypeNode = parseType(expected);
+ TypeParameter typeParameterNode = typeParameterNodes.single;
+ List<DartType> inferredTypeNodes = <DartType>[
+ inferredTypeFromDownwardPhase == null
+ ? new UnknownType()
+ : parseType(inferredTypeFromDownwardPhase)
+ ];
+
+ typeSchemaEnvironment.inferTypeFromConstraints(
+ {typeParameterNode: typeConstraint},
+ [typeParameterNode],
+ inferredTypeNodes,
+ testLibrary,
+ downwardsInferPhase: downwardsInferPhase);
+
+ expect(inferredTypeNodes.single, expectedTypeNode);
+ });
+ }
+
+ /// Parses a string like "<: T <: S >: R" into a [TypeConstraint].
+ ///
+ /// The [constraint] string is assumed to be a sequence of bounds added to the
+ /// constraint. Each element of the sequence is either "<: T" or ":> T",
+ /// where the former adds an upper bound and the latter adds a lower bound.
+ /// The bounds are added to the constraint in the order they are mentioned in
+ /// the [constraint] string, from left to right.
+ TypeConstraint parseConstraint(String constraint) {
+ TypeConstraint result = new TypeConstraint();
+ List<String> upperBoundSegments = constraint.split("<:");
+ bool firstUpperBoundSegment = true;
+ for (String upperBoundSegment in upperBoundSegments) {
+ if (firstUpperBoundSegment) {
+ firstUpperBoundSegment = false;
+ if (upperBoundSegment.isEmpty) {
+ continue;
+ }
+ }
+ List<String> lowerBoundSegments = upperBoundSegment.split(":>");
+ bool firstLowerBoundSegment = true;
+ for (String segment in lowerBoundSegments) {
+ if (firstLowerBoundSegment) {
+ firstLowerBoundSegment = false;
+ if (segment.isNotEmpty) {
+ typeSchemaEnvironment.addUpperBound(
+ result, parseType(segment), testLibrary);
+ }
+ } else {
+ typeSchemaEnvironment.addLowerBound(
+ result, parseType(segment), testLibrary);
+ }
+ }
+ }
+ return result;
+ }
+
+ DartType parseType(String type) {
+ return typeParserEnvironment.parseType(type,
+ additionalTypes: additionalTypes);
+ }
+
+ List<DartType> parseTypes(String types) {
+ return typeParserEnvironment.parseTypes(types,
+ additionalTypes: additionalTypes);
+ }
+}