blob: b7fa3e58975d14e55df49b67b731d513df6049dc [file] [log] [blame]
// Copyright (c) 2019, 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.md file.
import '../ast.dart' hide MapEntry;
import '../core_types.dart';
import 'replacement_visitor.dart';
/// Returns legacy erasure of [type], that is, the type in which all nnbd
/// nullabilities have been replaced with legacy nullability, and all required
/// named parameters are not required.
DartType legacyErasure(CoreTypes coreTypes, DartType type) {
return rawLegacyErasure(coreTypes, type) ?? type;
}
/// Returns legacy erasure of [type], that is, the type in which all nnbd
/// nullabilities have been replaced with legacy nullability, and all required
/// named parameters are not required.
///
/// Returns `null` if the type wasn't changed.
DartType rawLegacyErasure(CoreTypes coreTypes, DartType type) {
return type.accept(new _LegacyErasure(coreTypes));
}
/// Returns legacy erasure of [supertype], that is, the type in which all nnbd
/// nullabilities have been replaced with legacy nullability, and all required
/// named parameters are not required.
Supertype legacyErasureSupertype(CoreTypes coreTypes, Supertype supertype) {
if (supertype.typeArguments.isEmpty) {
return supertype;
}
List<DartType> newTypeArguments;
for (int i = 0; i < supertype.typeArguments.length; i++) {
DartType typeArgument = supertype.typeArguments[i];
DartType newTypeArgument =
typeArgument.accept(new _LegacyErasure(coreTypes));
if (newTypeArgument != null) {
newTypeArguments ??= supertype.typeArguments.toList(growable: false);
newTypeArguments[i] = newTypeArgument;
}
}
if (newTypeArguments != null) {
return new Supertype(supertype.classNode, newTypeArguments);
}
return supertype;
}
/// Visitor that replaces all nnbd nullabilities with legacy nullabilities and
/// all required named parameters with optional named parameters.
///
/// The visitor returns `null` if the type wasn't changed.
class _LegacyErasure extends ReplacementVisitor {
final CoreTypes coreTypes;
_LegacyErasure(this.coreTypes);
Nullability visitNullability(DartType node) {
if (node.nullability != Nullability.legacy) {
return Nullability.legacy;
}
return null;
}
@override
NamedType createNamedType(NamedType node, DartType newType) {
if (node.isRequired || newType != null) {
return new NamedType(node.name, newType ?? node.type, isRequired: false);
}
return null;
}
@override
DartType visitInterfaceType(InterfaceType node) {
if (node.classNode == coreTypes.nullClass) return null;
return super.visitInterfaceType(node);
}
@override
DartType visitNeverType(NeverType node) => coreTypes.nullType;
}