[cfe] Move ExtensionType into pkg/kernel/lib/ast.dart
Change-Id: I2e8231dad00accafb09d1ec88416242d3d5815a4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/190483 Commit-Queue: Dmitry Stefantsov <dmitryas@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
This commit is contained in:
committed by
commit-bot@chromium.org
parent
cf7e990233
commit
8ddc7465a8
@@ -207,6 +207,11 @@ class _FreeVariableVisitor implements ir.DartTypeVisitor<bool> {
|
||||
return visitList(node.typeArguments);
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitExtensionType(ir.ExtensionType node) {
|
||||
return visitList(node.typeArguments);
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitFutureOrType(ir.FutureOrType node) {
|
||||
return visit(node.typeArgument);
|
||||
|
||||
@@ -97,6 +97,12 @@ class TypeTextVisitor implements ir.DartTypeVisitor1<void, StringBuffer> {
|
||||
_writeTypeArguments(node.typeArguments, sb);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitExtensionType(ir.ExtensionType node, StringBuffer sb) {
|
||||
sb.write(node.extension.name);
|
||||
_writeTypeArguments(node.typeArguments, sb);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitFutureOrType(ir.FutureOrType node, StringBuffer sb) {
|
||||
sb.write('FutureOr<');
|
||||
|
||||
@@ -2745,6 +2745,10 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
|
||||
js_ast.Expression visitInterfaceType(InterfaceType type) =>
|
||||
_emitInterfaceType(type);
|
||||
|
||||
@override
|
||||
js_ast.Expression visitExtensionType(ExtensionType type) =>
|
||||
type.onType.accept(this);
|
||||
|
||||
@override
|
||||
js_ast.Expression visitFutureOrType(FutureOrType type) =>
|
||||
_normalizeFutureOr(type);
|
||||
|
||||
@@ -9,7 +9,6 @@ import 'package:kernel/core_types.dart';
|
||||
|
||||
import '../fasta_codes.dart'
|
||||
show templateInternalProblemNotFoundIn, templateTypeArgumentMismatch;
|
||||
import '../kernel/internal_ast.dart';
|
||||
import '../scope.dart';
|
||||
import '../source/source_library_builder.dart';
|
||||
import '../problems.dart';
|
||||
|
||||
@@ -21,13 +21,9 @@
|
||||
/// with the same kind of root node.
|
||||
|
||||
import 'package:kernel/ast.dart';
|
||||
import 'package:kernel/binary/ast_to_binary.dart';
|
||||
import 'package:kernel/core_types.dart';
|
||||
import 'package:kernel/src/assumptions.dart';
|
||||
import 'package:kernel/src/printer.dart';
|
||||
import 'package:kernel/src/text_util.dart';
|
||||
import 'package:kernel/text/ast_to_text.dart' show Precedence, Printer;
|
||||
import 'package:kernel/type_algebra.dart';
|
||||
import 'package:kernel/type_environment.dart';
|
||||
|
||||
import '../builder/type_alias_builder.dart';
|
||||
@@ -54,8 +50,6 @@ import '../type_inference/type_schema_environment.dart'
|
||||
|
||||
import 'inference_visitor.dart';
|
||||
|
||||
import 'type_labeler.dart';
|
||||
|
||||
/// Computes the return type of a (possibly factory) constructor.
|
||||
InterfaceType computeConstructorReturnType(
|
||||
Member constructor, CoreTypes coreTypes) {
|
||||
@@ -4232,170 +4226,3 @@ Expression clonePureExpression(Expression node) {
|
||||
}
|
||||
throw new UnsupportedError("Clone not supported for ${node.runtimeType}.");
|
||||
}
|
||||
|
||||
class ExtensionType extends DartType {
|
||||
final Reference extensionName;
|
||||
|
||||
@override
|
||||
final Nullability declaredNullability;
|
||||
|
||||
final List<DartType> typeArguments;
|
||||
|
||||
final DartType onType;
|
||||
|
||||
ExtensionType(Extension extensionNode, Nullability declaredNullability,
|
||||
[List<DartType> typeArguments])
|
||||
: this.byReference(extensionNode.reference, declaredNullability,
|
||||
typeArguments ?? _defaultTypeArguments(extensionNode));
|
||||
|
||||
ExtensionType.byReference(
|
||||
this.extensionName, this.declaredNullability, this.typeArguments)
|
||||
: assert(declaredNullability != null),
|
||||
onType = _computeOnType(extensionName, typeArguments);
|
||||
|
||||
Extension get extensionNode => extensionName.asExtension;
|
||||
|
||||
@override
|
||||
Nullability get nullability {
|
||||
return uniteNullabilities(
|
||||
declaredNullability, extensionNode.onType.nullability);
|
||||
}
|
||||
|
||||
static List<DartType> _defaultTypeArguments(Extension extensionNode) {
|
||||
if (extensionNode.typeParameters.length == 0) {
|
||||
// Avoid allocating a list in this very common case.
|
||||
return const <DartType>[];
|
||||
} else {
|
||||
return new List<DartType>.filled(
|
||||
extensionNode.typeParameters.length, const DynamicType());
|
||||
}
|
||||
}
|
||||
|
||||
static DartType _computeOnType(
|
||||
Reference extensionName, List<DartType> typeArguments) {
|
||||
Extension extensionNode = extensionName.asExtension;
|
||||
if (extensionNode.typeParameters.isEmpty) {
|
||||
return extensionNode.onType;
|
||||
} else {
|
||||
assert(extensionNode.typeParameters.length == typeArguments.length);
|
||||
return Substitution.fromPairs(extensionNode.typeParameters, typeArguments)
|
||||
.substituteType(extensionNode.onType);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
R accept<R>(DartTypeVisitor<R> v) {
|
||||
if (v is Printer) {
|
||||
// TODO(dmitryas): Move this guarded code into Printer.visitExtensionType
|
||||
// when it's available.
|
||||
Printer printer = v as Printer;
|
||||
printer.writeExtensionReferenceFromReference(extensionName);
|
||||
if (typeArguments.isNotEmpty) {
|
||||
printer.writeSymbol('<');
|
||||
printer.writeList(typeArguments, printer.writeType);
|
||||
printer.writeSymbol('>');
|
||||
printer.state = Printer.WORD;
|
||||
}
|
||||
printer.writeNullability(declaredNullability);
|
||||
// The following line is needed to supply the return value and make the
|
||||
// compiler happy. It should go away once ExtensionType is moved to
|
||||
// ast.dart.
|
||||
return null;
|
||||
} else if (v is BinaryPrinter) {
|
||||
// TODO(dmitryas): Remove the following line and implement
|
||||
// BinaryPrinter.visitExtensionType when it's available.
|
||||
return onType.accept(v);
|
||||
} else if (v is TypeLabeler) {
|
||||
// TODO(dmitryas): Move this guarded code into
|
||||
// TypeLabeler.visitExtensionType when it's available.
|
||||
TypeLabeler typeLabeler = v as TypeLabeler;
|
||||
typeLabeler.result.add(typeLabeler.nameForEntity(
|
||||
extensionNode,
|
||||
extensionNode.name,
|
||||
extensionNode.enclosingLibrary.importUri,
|
||||
extensionNode.enclosingLibrary.fileUri));
|
||||
if (typeArguments.isNotEmpty) {
|
||||
typeLabeler.result.add("<");
|
||||
bool first = true;
|
||||
for (DartType typeArg in typeArguments) {
|
||||
if (!first) typeLabeler.result.add(", ");
|
||||
typeArg.accept(typeLabeler);
|
||||
first = false;
|
||||
}
|
||||
typeLabeler.result.add(">");
|
||||
}
|
||||
typeLabeler.addNullability(declaredNullability);
|
||||
// The following line is needed to supply the return value and make the
|
||||
// compiler happy. It should go away once ExtensionType is moved to
|
||||
// ast.dart.
|
||||
return null;
|
||||
}
|
||||
// TODO(dmitryas): Change this to `v.visitExtensionType(this)` when
|
||||
// ExtensionType is moved to ast.dart.
|
||||
return v.defaultDartType(this);
|
||||
}
|
||||
|
||||
@override
|
||||
R accept1<R, A>(DartTypeVisitor1<R, A> v, A arg) {
|
||||
// TODO(dmitryas): Change this to `v.visitExtensionType(this, arg)` when
|
||||
// ExtensionType is moved to ast.dart.
|
||||
return v.defaultDartType(this, arg);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitChildren(Visitor v) {
|
||||
// TODO(dmitryas): Uncomment the following line when ExtensionType is moved
|
||||
// to ast.dart.
|
||||
//extensionNode.acceptReference(v);
|
||||
visitList(typeArguments, v);
|
||||
}
|
||||
|
||||
@override
|
||||
bool equals(Object other, Assumptions assumptions) {
|
||||
if (identical(this, other)) return true;
|
||||
if (other is ExtensionType) {
|
||||
if (nullability != other.nullability) return false;
|
||||
if (extensionName != other.extensionName) return false;
|
||||
if (typeArguments.length != other.typeArguments.length) return false;
|
||||
for (int i = 0; i < typeArguments.length; ++i) {
|
||||
if (!typeArguments[i].equals(other.typeArguments[i], assumptions)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
int hash = 0x3fffffff & extensionName.hashCode;
|
||||
for (int i = 0; i < typeArguments.length; ++i) {
|
||||
hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode));
|
||||
}
|
||||
int nullabilityHash = (0x33333333 >> nullability.index) ^ 0x33333333;
|
||||
hash = 0x3fffffff & (hash * 31 + (hash ^ nullabilityHash));
|
||||
return hash;
|
||||
}
|
||||
|
||||
@override
|
||||
ExtensionType withDeclaredNullability(Nullability declaredNullability) {
|
||||
return declaredNullability == this.declaredNullability
|
||||
? this
|
||||
: new ExtensionType.byReference(
|
||||
extensionName, declaredNullability, typeArguments);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "ExtensionType(${toStringInternal()})";
|
||||
}
|
||||
|
||||
@override
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
printer.writeExtensionName(extensionName);
|
||||
printer.writeTypeArguments(typeArguments);
|
||||
printer.write(nullabilityToString(declaredNullability));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ import 'package:kernel/visitor.dart';
|
||||
|
||||
import '../type_inference/type_schema.dart';
|
||||
|
||||
import 'internal_ast.dart';
|
||||
|
||||
/// Check if [type] contains [InvalidType] as its part.
|
||||
///
|
||||
/// The helper function is intended for stopping cascading errors because of
|
||||
@@ -59,6 +57,15 @@ class _InvalidTypeFinder implements DartTypeVisitor1<bool, Set<TypedefType>> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitExtensionType(
|
||||
ExtensionType node, Set<TypedefType> visitedTypedefs) {
|
||||
for (DartType typeArgument in node.typeArguments) {
|
||||
if (typeArgument.accept1(this, visitedTypedefs)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitFutureOrType(FutureOrType node, Set<TypedefType> visitedTypedefs) {
|
||||
return node.typeArgument.accept1(this, visitedTypedefs);
|
||||
|
||||
@@ -4,23 +4,7 @@
|
||||
|
||||
// @dart = 2.9
|
||||
|
||||
import 'package:kernel/ast.dart'
|
||||
show
|
||||
DartType,
|
||||
DartTypeVisitor,
|
||||
DynamicType,
|
||||
FunctionType,
|
||||
FutureOrType,
|
||||
InterfaceType,
|
||||
InvalidType,
|
||||
NamedType,
|
||||
NeverType,
|
||||
NullType,
|
||||
TypeParameter,
|
||||
TypeParameterType,
|
||||
TypedefType,
|
||||
Variance,
|
||||
VoidType;
|
||||
import 'package:kernel/ast.dart';
|
||||
|
||||
import 'package:kernel/type_algebra.dart' show containsTypeVariable;
|
||||
|
||||
@@ -1029,24 +1013,37 @@ class TypeVariableSearch implements DartTypeVisitor<bool> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitInvalidType(InvalidType node) => false;
|
||||
|
||||
@override
|
||||
bool visitDynamicType(DynamicType node) => false;
|
||||
|
||||
@override
|
||||
bool visitVoidType(VoidType node) => false;
|
||||
|
||||
@override
|
||||
bool visitNeverType(NeverType node) => false;
|
||||
|
||||
@override
|
||||
bool visitNullType(NullType node) => false;
|
||||
|
||||
@override
|
||||
bool visitInterfaceType(InterfaceType node) {
|
||||
return anyTypeVariables(node.typeArguments);
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitExtensionType(ExtensionType node) {
|
||||
return anyTypeVariables(node.typeArguments);
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitFutureOrType(FutureOrType node) {
|
||||
return node.typeArgument.accept(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitFunctionType(FunctionType node) {
|
||||
if (anyTypeVariables(node.positionalParameters)) return true;
|
||||
for (TypeParameter variable in node.typeParameters) {
|
||||
@@ -1058,8 +1055,10 @@ class TypeVariableSearch implements DartTypeVisitor<bool> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitTypeParameterType(TypeParameterType node) => true;
|
||||
|
||||
@override
|
||||
bool visitTypedefType(TypedefType node) {
|
||||
return anyTypeVariables(node.typeArguments);
|
||||
}
|
||||
|
||||
@@ -9,26 +9,7 @@ library fasta.type_builder_computer;
|
||||
import 'package:_fe_analyzer_shared/src/parser/parser.dart'
|
||||
show FormalParameterKind;
|
||||
|
||||
import 'package:kernel/ast.dart'
|
||||
show
|
||||
Class,
|
||||
DartType,
|
||||
DartTypeVisitor,
|
||||
DynamicType,
|
||||
FunctionType,
|
||||
FutureOrType,
|
||||
InterfaceType,
|
||||
InvalidType,
|
||||
Library,
|
||||
NamedType,
|
||||
NeverType,
|
||||
NullType,
|
||||
TreeNode,
|
||||
TypeParameter,
|
||||
TypeParameterType,
|
||||
Typedef,
|
||||
TypedefType,
|
||||
VoidType;
|
||||
import 'package:kernel/ast.dart';
|
||||
|
||||
import '../builder/class_builder.dart';
|
||||
import '../builder/dynamic_type_declaration_builder.dart';
|
||||
@@ -130,6 +111,11 @@ class TypeBuilderComputer implements DartTypeVisitor<TypeBuilder> {
|
||||
..bind(cls);
|
||||
}
|
||||
|
||||
@override
|
||||
TypeBuilder visitExtensionType(ExtensionType node) {
|
||||
throw "Not implemented";
|
||||
}
|
||||
|
||||
@override
|
||||
TypeBuilder visitFutureOrType(FutureOrType node) {
|
||||
TypeBuilder argument = node.typeArgument.accept(this);
|
||||
|
||||
@@ -6,43 +6,7 @@
|
||||
|
||||
import 'dart:convert' show json;
|
||||
|
||||
import 'package:kernel/ast.dart'
|
||||
show
|
||||
BoolConstant,
|
||||
Class,
|
||||
Constant,
|
||||
ConstantMapEntry,
|
||||
DartType,
|
||||
DoubleConstant,
|
||||
DynamicType,
|
||||
Field,
|
||||
FunctionType,
|
||||
FutureOrType,
|
||||
InvalidType,
|
||||
InstanceConstant,
|
||||
IntConstant,
|
||||
InterfaceType,
|
||||
Library,
|
||||
ListConstant,
|
||||
MapConstant,
|
||||
NeverType,
|
||||
NullConstant,
|
||||
NullType,
|
||||
Nullability,
|
||||
PartialInstantiationConstant,
|
||||
Procedure,
|
||||
SetConstant,
|
||||
StringConstant,
|
||||
SymbolConstant,
|
||||
TearOffConstant,
|
||||
TreeNode,
|
||||
Typedef,
|
||||
TypedefType,
|
||||
TypeLiteralConstant,
|
||||
TypeParameter,
|
||||
TypeParameterType,
|
||||
UnevaluatedConstant,
|
||||
VoidType;
|
||||
import 'package:kernel/ast.dart';
|
||||
|
||||
import 'package:kernel/visitor.dart' show ConstantVisitor, DartTypeVisitor;
|
||||
|
||||
@@ -286,6 +250,25 @@ class TypeLabeler implements DartTypeVisitor<void>, ConstantVisitor<void> {
|
||||
addNullability(node.declaredNullability);
|
||||
}
|
||||
|
||||
void visitExtensionType(ExtensionType node) {
|
||||
result.add(nameForEntity(
|
||||
node.extension,
|
||||
node.extension.name,
|
||||
node.extension.enclosingLibrary.importUri,
|
||||
node.extension.enclosingLibrary.fileUri));
|
||||
if (node.typeArguments.isNotEmpty) {
|
||||
result.add("<");
|
||||
bool first = true;
|
||||
for (DartType typeArg in node.typeArguments) {
|
||||
if (!first) result.add(", ");
|
||||
typeArg.accept(this);
|
||||
first = false;
|
||||
}
|
||||
result.add(">");
|
||||
}
|
||||
addNullability(node.declaredNullability);
|
||||
}
|
||||
|
||||
void defaultConstant(Constant node) {}
|
||||
|
||||
void visitNullConstant(NullConstant node) {
|
||||
|
||||
@@ -896,7 +896,7 @@ class TypeInferrerImpl implements TypeInferrer {
|
||||
Member targetTearoff;
|
||||
ProcedureKind targetKind;
|
||||
for (ExtensionMemberDescriptor descriptor
|
||||
in receiverType.extensionNode.members) {
|
||||
in receiverType.extension.members) {
|
||||
if (descriptor.name == name) {
|
||||
switch (descriptor.kind) {
|
||||
case ExtensionMemberKind.Method:
|
||||
|
||||
@@ -17,8 +17,6 @@ import 'package:kernel/type_environment.dart';
|
||||
import 'package:kernel/src/hierarchy_based_type_environment.dart'
|
||||
show HierarchyBasedTypeEnvironment;
|
||||
|
||||
import '../kernel/internal_ast.dart' show ExtensionType;
|
||||
|
||||
import 'standard_bounds.dart' show TypeSchemaStandardBounds;
|
||||
|
||||
import 'type_constraint_gatherer.dart' show TypeConstraintGatherer;
|
||||
@@ -373,7 +371,7 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
||||
if (coreTypes.isTop(supertype)) {
|
||||
return const IsSubtypeOf.always();
|
||||
} else if (supertype is ExtensionType &&
|
||||
subtype.extensionNode == supertype.extensionNode) {
|
||||
subtype.extension == supertype.extension) {
|
||||
assert(subtype.typeArguments.length == supertype.typeArguments.length);
|
||||
IsSubtypeOf result = const IsSubtypeOf.always();
|
||||
for (int i = 0; i < subtype.typeArguments.length; ++i) {
|
||||
@@ -399,7 +397,7 @@ class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
|
||||
if (coreTypes.isBottom(subtype)) {
|
||||
return const IsSubtypeOf.always();
|
||||
} else if (subtype is ExtensionType &&
|
||||
subtype.extensionNode == unwrappedSupertype.extensionNode) {
|
||||
subtype.extension == unwrappedSupertype.extension) {
|
||||
assert(subtype.typeArguments.length ==
|
||||
unwrappedSupertype.typeArguments.length);
|
||||
IsSubtypeOf result = const IsSubtypeOf.always();
|
||||
|
||||
@@ -570,6 +570,16 @@ class DartTypeToTextVisitor implements DartTypeVisitor<void> {
|
||||
}
|
||||
sb.write(nullabilityToText(node.nullability, typeRepresentation));
|
||||
}
|
||||
|
||||
void visitExtensionType(ExtensionType node) {
|
||||
sb.write(node.extension.name);
|
||||
if (node.typeArguments.isNotEmpty) {
|
||||
sb.write('<');
|
||||
visitList(node.typeArguments);
|
||||
sb.write('>');
|
||||
}
|
||||
sb.write(nullabilityToText(node.declaredNullability, typeRepresentation));
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if [type] is `Object` from `dart:core`.
|
||||
|
||||
@@ -345,6 +345,11 @@ class BenchMaker implements DartTypeVisitor1<void, StringBuffer> {
|
||||
throw "not implemented";
|
||||
}
|
||||
|
||||
@override
|
||||
void visitExtensionType(ExtensionType node, StringBuffer sb) {
|
||||
throw "not implemented";
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return <String, dynamic>{
|
||||
"classes": classes,
|
||||
|
||||
@@ -1466,6 +1466,8 @@ class Extension extends NamedNode implements FileUriNode {
|
||||
@override
|
||||
R accept1<R, A>(TreeVisitor1<R, A> v, A arg) => v.visitExtension(this, arg);
|
||||
|
||||
R acceptReference<R>(Visitor<R> v) => v.visitExtensionReference(this);
|
||||
|
||||
@override
|
||||
void visitChildren(Visitor v) {
|
||||
visitList(typeParameters, v);
|
||||
@@ -11150,6 +11152,123 @@ class FutureOrType extends DartType {
|
||||
}
|
||||
}
|
||||
|
||||
class ExtensionType extends DartType {
|
||||
final Reference extensionReference;
|
||||
|
||||
@override
|
||||
final Nullability declaredNullability;
|
||||
|
||||
final List<DartType> typeArguments;
|
||||
|
||||
final DartType onType;
|
||||
|
||||
ExtensionType(Extension extensionNode, Nullability declaredNullability,
|
||||
[List<DartType>? typeArguments])
|
||||
: this.byReference(extensionNode.reference, declaredNullability,
|
||||
typeArguments ?? _defaultTypeArguments(extensionNode));
|
||||
|
||||
ExtensionType.byReference(
|
||||
this.extensionReference, this.declaredNullability, this.typeArguments)
|
||||
// ignore: unnecessary_null_comparison
|
||||
: assert(declaredNullability != null),
|
||||
onType = _computeOnType(extensionReference, typeArguments);
|
||||
|
||||
Extension get extension => extensionReference.asExtension;
|
||||
|
||||
@override
|
||||
Nullability get nullability {
|
||||
return uniteNullabilities(
|
||||
declaredNullability, extension.onType.nullability);
|
||||
}
|
||||
|
||||
static List<DartType> _defaultTypeArguments(Extension extensionNode) {
|
||||
if (extensionNode.typeParameters.length == 0) {
|
||||
// Avoid allocating a list in this very common case.
|
||||
return const <DartType>[];
|
||||
} else {
|
||||
return new List<DartType>.filled(
|
||||
extensionNode.typeParameters.length, const DynamicType());
|
||||
}
|
||||
}
|
||||
|
||||
static DartType _computeOnType(
|
||||
Reference extensionName, List<DartType> typeArguments) {
|
||||
Extension extensionNode = extensionName.asExtension;
|
||||
if (extensionNode.typeParameters.isEmpty) {
|
||||
return extensionNode.onType;
|
||||
} else {
|
||||
assert(extensionNode.typeParameters.length == typeArguments.length);
|
||||
return Substitution.fromPairs(extensionNode.typeParameters, typeArguments)
|
||||
.substituteType(extensionNode.onType);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
R accept<R>(DartTypeVisitor<R> v) {
|
||||
return v.visitExtensionType(this);
|
||||
}
|
||||
|
||||
@override
|
||||
R accept1<R, A>(DartTypeVisitor1<R, A> v, A arg) {
|
||||
return v.visitExtensionType(this, arg);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitChildren(Visitor v) {
|
||||
extension.acceptReference(v);
|
||||
visitList(typeArguments, v);
|
||||
}
|
||||
|
||||
@override
|
||||
bool equals(Object other, Assumptions? assumptions) {
|
||||
if (identical(this, other)) return true;
|
||||
if (other is ExtensionType) {
|
||||
if (nullability != other.nullability) return false;
|
||||
if (extensionReference != other.extensionReference) return false;
|
||||
if (typeArguments.length != other.typeArguments.length) return false;
|
||||
for (int i = 0; i < typeArguments.length; ++i) {
|
||||
if (!typeArguments[i].equals(other.typeArguments[i], assumptions)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
int hash = 0x3fffffff & extensionReference.hashCode;
|
||||
for (int i = 0; i < typeArguments.length; ++i) {
|
||||
hash = 0x3fffffff & (hash * 31 + (hash ^ typeArguments[i].hashCode));
|
||||
}
|
||||
int nullabilityHash = (0x33333333 >> nullability.index) ^ 0x33333333;
|
||||
hash = 0x3fffffff & (hash * 31 + (hash ^ nullabilityHash));
|
||||
return hash;
|
||||
}
|
||||
|
||||
@override
|
||||
ExtensionType withDeclaredNullability(Nullability declaredNullability) {
|
||||
return declaredNullability == this.declaredNullability
|
||||
? this
|
||||
: new ExtensionType.byReference(
|
||||
extensionReference, declaredNullability, typeArguments);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "ExtensionType(${toStringInternal()})";
|
||||
}
|
||||
|
||||
@override
|
||||
void toTextInternal(AstPrinter printer) {
|
||||
printer.writeExtensionName(extensionReference);
|
||||
printer.writeTypeArguments(typeArguments);
|
||||
printer.write(nullabilityToString(declaredNullability));
|
||||
}
|
||||
}
|
||||
|
||||
/// A named parameter in [FunctionType].
|
||||
class NamedType extends Node implements Comparable<NamedType> {
|
||||
// Flag used for serialization if [isRequired].
|
||||
|
||||
@@ -2287,6 +2287,12 @@ class BinaryPrinter implements Visitor<void>, BinarySink {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitExtensionType(ExtensionType node) {
|
||||
// TODO(dmitryas): Serialize ExtensionType.
|
||||
node.onType.accept(this);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitFutureOrType(FutureOrType node) {
|
||||
// TODO(dmitryas): Remove special treatment of FutureOr when the VM supports
|
||||
@@ -2524,6 +2530,11 @@ class BinaryPrinter implements Visitor<void>, BinarySink {
|
||||
throw new UnsupportedError('serialization of Class references');
|
||||
}
|
||||
|
||||
@override
|
||||
void visitExtensionReference(Extension node) {
|
||||
throw new UnsupportedError('serialization of Class references');
|
||||
}
|
||||
|
||||
@override
|
||||
void visitConstructorReference(Constructor node) {
|
||||
throw new UnsupportedError('serialization of Constructor references');
|
||||
|
||||
@@ -738,6 +738,21 @@ class VarianceCalculator
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
int visitExtensionType(ExtensionType node,
|
||||
Map<TypeParameter, Map<DartType, int>> computedVariances) {
|
||||
int result = Variance.unrelated;
|
||||
for (int i = 0; i < node.typeArguments.length; ++i) {
|
||||
result = Variance.meet(
|
||||
result,
|
||||
Variance.combine(
|
||||
node.extension.typeParameters[i].variance,
|
||||
computeVariance(typeParameter, node.typeArguments[i],
|
||||
computedVariances: computedVariances)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
int visitFutureOrType(FutureOrType node,
|
||||
Map<TypeParameter, Map<DartType, int>> computedVariances) {
|
||||
|
||||
@@ -170,6 +170,32 @@ class DartTypeEquivalence implements DartTypeVisitor1<bool, DartType> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitExtensionType(ExtensionType node, DartType other) {
|
||||
// First, check Object*, Object?.
|
||||
if (equateTopTypes && coreTypes.isTop(node)) {
|
||||
return coreTypes.isTop(other);
|
||||
}
|
||||
|
||||
if (other is ExtensionType) {
|
||||
if (!_checkAndRegisterNullabilities(
|
||||
node.declaredNullability, other.declaredNullability)) {
|
||||
return false;
|
||||
}
|
||||
if (node.extension != other.extension) {
|
||||
return false;
|
||||
}
|
||||
assert(node.typeArguments.length == other.typeArguments.length);
|
||||
for (int i = 0; i < node.typeArguments.length; ++i) {
|
||||
if (!node.typeArguments[i].accept1(this, other.typeArguments[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitFutureOrType(FutureOrType node, DartType other) {
|
||||
// First, check FutureOr<dynamic>, FutureOr<Object?>, etc.
|
||||
|
||||
@@ -93,6 +93,12 @@ class FutureValueTypeVisitor implements DartTypeVisitor1<DartType, CoreTypes> {
|
||||
return coreTypes.objectNullableRawType;
|
||||
}
|
||||
|
||||
@override
|
||||
DartType visitExtensionType(DartType node, CoreTypes coreTypes) {
|
||||
// Otherwise, for all S, futureValueType(S) = Object?.
|
||||
return coreTypes.objectNullableRawType;
|
||||
}
|
||||
|
||||
@override
|
||||
DartType visitVoidType(DartType node, CoreTypes coreTypes) {
|
||||
// futureValueType(void) = void.
|
||||
|
||||
@@ -174,6 +174,41 @@ class MergeVisitor implements DartTypeVisitor1<DartType?, DartType> {
|
||||
return new InterfaceType(a.classNode, nullability, newTypeArguments);
|
||||
}
|
||||
|
||||
@override
|
||||
DartType? visitExtensionType(ExtensionType a, DartType b) {
|
||||
if (b is ExtensionType &&
|
||||
a.extension == b.extension &&
|
||||
a.typeArguments.length == b.typeArguments.length) {
|
||||
Nullability? nullability = mergeNullability(a.nullability, b.nullability);
|
||||
if (nullability != null) {
|
||||
return mergeExtensionTypes(a, b, nullability);
|
||||
}
|
||||
}
|
||||
if (b is InvalidType) {
|
||||
return b;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
DartType? mergeExtensionTypes(
|
||||
ExtensionType a, ExtensionType b, Nullability nullability) {
|
||||
assert(a.extension == b.extension);
|
||||
assert(a.typeArguments.length == b.typeArguments.length);
|
||||
if (a.typeArguments.isEmpty) {
|
||||
return new ExtensionType(a.extension, nullability);
|
||||
}
|
||||
List<DartType> newTypeArguments =
|
||||
new List<DartType>.filled(a.typeArguments.length, dummyDartType);
|
||||
for (int i = 0; i < a.typeArguments.length; i++) {
|
||||
DartType? newType = a.typeArguments[i].accept1(this, b.typeArguments[i]);
|
||||
if (newType == null) {
|
||||
return null;
|
||||
}
|
||||
newTypeArguments[i] = newType;
|
||||
}
|
||||
return new ExtensionType(a.extension, nullability, newTypeArguments);
|
||||
}
|
||||
|
||||
@override
|
||||
DartType? visitFutureOrType(FutureOrType a, DartType b) {
|
||||
if (b is FutureOrType) {
|
||||
|
||||
@@ -52,6 +52,14 @@ class _NonNullVisitor implements DartTypeVisitor<DartType?> {
|
||||
return node.withDeclaredNullability(Nullability.nonNullable);
|
||||
}
|
||||
|
||||
@override
|
||||
DartType? visitExtensionType(ExtensionType node) {
|
||||
if (node.declaredNullability == Nullability.nonNullable) {
|
||||
return null;
|
||||
}
|
||||
return node.withDeclaredNullability(Nullability.nonNullable);
|
||||
}
|
||||
|
||||
@override
|
||||
DartType? visitInvalidType(InvalidType node) => null;
|
||||
|
||||
|
||||
@@ -267,6 +267,36 @@ class ReplacementVisitor implements DartTypeVisitor1<DartType?, int> {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
DartType? visitExtensionType(ExtensionType node, int variance) {
|
||||
Nullability? newNullability = visitNullability(node);
|
||||
List<DartType>? newTypeArguments = null;
|
||||
for (int i = 0; i < node.typeArguments.length; i++) {
|
||||
DartType? substitution = node.typeArguments[i].accept1(
|
||||
this,
|
||||
Variance.combine(
|
||||
variance, node.extension.typeParameters[i].variance));
|
||||
if (substitution != null) {
|
||||
newTypeArguments ??= node.typeArguments.toList(growable: false);
|
||||
newTypeArguments[i] = substitution;
|
||||
}
|
||||
}
|
||||
return createExtensionType(node, newNullability, newTypeArguments);
|
||||
}
|
||||
|
||||
DartType? createExtensionType(ExtensionType node, Nullability? newNullability,
|
||||
List<DartType>? newTypeArguments) {
|
||||
if (newNullability == null && newTypeArguments == null) {
|
||||
// No nullability or type arguments needed to be substituted.
|
||||
return null;
|
||||
} else {
|
||||
return new ExtensionType(
|
||||
node.extension,
|
||||
newNullability ?? node.nullability,
|
||||
newTypeArguments ?? node.typeArguments);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
DartType? defaultDartType(DartType node, int variance) => null;
|
||||
}
|
||||
|
||||
@@ -2436,6 +2436,17 @@ class Printer extends Visitor<void> with VisitorVoidMixin {
|
||||
writeNullability(node.nullability);
|
||||
}
|
||||
|
||||
visitExtensionType(ExtensionType node) {
|
||||
writeExtensionReferenceFromReference(node.extensionReference);
|
||||
if (node.typeArguments.isNotEmpty) {
|
||||
writeSymbol('<');
|
||||
writeList(node.typeArguments, writeType);
|
||||
writeSymbol('>');
|
||||
state = Printer.WORD;
|
||||
}
|
||||
writeNullability(node.declaredNullability);
|
||||
}
|
||||
|
||||
visitFutureOrType(FutureOrType node) {
|
||||
writeWord('FutureOr');
|
||||
writeSymbol('<');
|
||||
|
||||
@@ -675,6 +675,10 @@ class _OccurrenceVisitor implements DartTypeVisitor<bool> {
|
||||
return node.typeArguments.any(visit);
|
||||
}
|
||||
|
||||
bool visitExtensionType(ExtensionType node) {
|
||||
return node.typeArguments.any(visit);
|
||||
}
|
||||
|
||||
bool visitFutureOrType(FutureOrType node) {
|
||||
return visit(node.typeArgument);
|
||||
}
|
||||
@@ -727,6 +731,10 @@ class _FreeFunctionTypeVariableVisitor implements DartTypeVisitor<bool> {
|
||||
return node.typeArguments.any(visit);
|
||||
}
|
||||
|
||||
bool visitExtensionType(ExtensionType node) {
|
||||
return node.typeArguments.any(visit);
|
||||
}
|
||||
|
||||
bool visitFutureOrType(FutureOrType node) {
|
||||
return visit(node.typeArgument);
|
||||
}
|
||||
@@ -782,6 +790,10 @@ class _FreeTypeVariableVisitor implements DartTypeVisitor<bool> {
|
||||
return node.typeArguments.any(visit);
|
||||
}
|
||||
|
||||
bool visitExtensionType(ExtensionType node) {
|
||||
return node.typeArguments.any(visit);
|
||||
}
|
||||
|
||||
bool visitFutureOrType(FutureOrType node) {
|
||||
return visit(node.typeArgument);
|
||||
}
|
||||
@@ -880,6 +892,11 @@ class _PrimitiveTypeVerifier implements DartTypeVisitor<bool> {
|
||||
return node.typeArguments.isEmpty;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitExtensionType(ExtensionType node) {
|
||||
return node.typeArguments.isEmpty;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitInvalidType(InvalidType node) {
|
||||
throw new UnsupportedError(
|
||||
@@ -949,6 +966,11 @@ class _NullabilityConstructorUnwrapper
|
||||
return node.withDeclaredNullability(Nullability.nonNullable);
|
||||
}
|
||||
|
||||
@override
|
||||
DartType visitExtensionType(ExtensionType node, CoreTypes coreTypes) {
|
||||
return node.withDeclaredNullability(Nullability.nonNullable);
|
||||
}
|
||||
|
||||
@override
|
||||
DartType visitInvalidType(InvalidType node, CoreTypes coreTypes) => node;
|
||||
|
||||
@@ -1162,6 +1184,13 @@ class _NullabilityMarkerDetector implements DartTypeVisitor<bool> {
|
||||
node.declaredNullability == Nullability.legacy;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitExtensionType(ExtensionType node) {
|
||||
assert(node.declaredNullability != Nullability.undetermined);
|
||||
return node.declaredNullability == Nullability.nullable ||
|
||||
node.declaredNullability == Nullability.legacy;
|
||||
}
|
||||
|
||||
@override
|
||||
bool visitInvalidType(InvalidType node) => false;
|
||||
|
||||
|
||||
@@ -529,6 +529,7 @@ abstract class DartTypeVisitor<R> {
|
||||
R visitTypedefType(TypedefType node) => defaultDartType(node);
|
||||
R visitNeverType(NeverType node) => defaultDartType(node);
|
||||
R visitNullType(NullType node) => defaultDartType(node);
|
||||
R visitExtensionType(ExtensionType node) => defaultDartType(node);
|
||||
}
|
||||
|
||||
abstract class DartTypeVisitor1<R, T> {
|
||||
@@ -545,6 +546,7 @@ abstract class DartTypeVisitor1<R, T> {
|
||||
R visitTypedefType(TypedefType node, T arg) => defaultDartType(node, arg);
|
||||
R visitNeverType(NeverType node, T arg) => defaultDartType(node, arg);
|
||||
R visitNullType(NullType node, T arg) => defaultDartType(node, arg);
|
||||
R visitExtensionType(ExtensionType node, T arg) => defaultDartType(node, arg);
|
||||
}
|
||||
|
||||
/// Visitor for [Constant] nodes.
|
||||
@@ -783,6 +785,7 @@ abstract class Visitor<R> extends TreeVisitor<R>
|
||||
R visitTypedefType(TypedefType node) => defaultDartType(node);
|
||||
R visitNeverType(NeverType node) => defaultDartType(node);
|
||||
R visitNullType(NullType node) => defaultDartType(node);
|
||||
R visitExtensionType(ExtensionType node) => defaultDartType(node);
|
||||
|
||||
// Constants
|
||||
R defaultConstant(Constant node) => defaultNode(node);
|
||||
@@ -807,6 +810,8 @@ abstract class Visitor<R> extends TreeVisitor<R>
|
||||
|
||||
R visitTypedefReference(Typedef node);
|
||||
|
||||
R visitExtensionReference(Extension node);
|
||||
|
||||
// Constant references
|
||||
R defaultConstantReference(Constant node);
|
||||
|
||||
@@ -905,6 +910,9 @@ mixin VisitorNullMixin<R> implements Visitor<R?> {
|
||||
@override
|
||||
R? visitTypedefReference(Typedef node) => null;
|
||||
|
||||
@override
|
||||
R? visitExtensionReference(Extension node) => null;
|
||||
|
||||
@override
|
||||
R? defaultConstantReference(Constant node) => null;
|
||||
|
||||
@@ -923,6 +931,9 @@ mixin VisitorVoidMixin implements Visitor<void> {
|
||||
@override
|
||||
void visitTypedefReference(Typedef node) {}
|
||||
|
||||
@override
|
||||
void visitExtensionReference(Extension node) {}
|
||||
|
||||
@override
|
||||
void defaultConstantReference(Constant node) {}
|
||||
|
||||
@@ -943,6 +954,9 @@ mixin VisitorDefaultValueMixin<R> implements Visitor<R> {
|
||||
@override
|
||||
R visitTypedefReference(Typedef node) => defaultValue;
|
||||
|
||||
@override
|
||||
R visitExtensionReference(Extension node) => defaultValue;
|
||||
|
||||
@override
|
||||
R defaultConstantReference(Constant node) => defaultValue;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user