| // 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:kernel/type_algebra.dart'; | |
| import '../ast.dart'; | |
| import 'replacement_visitor.dart'; | |
| /// Replaces all occurrences of [TypedefType] in [type] with the corresponding | |
| /// unaliased type. | |
| /// | |
| /// If [legacyEraseAliases] is `true`, the unaliased types will be legacy | |
| /// erased. This used when the [TypedefType] was used in a legacy library. | |
| DartType unalias(DartType type) { | |
| return rawUnalias(type) ?? type; | |
| } | |
| /// Replaces all occurrences of [TypedefType] in [types] with the corresponding | |
| /// unaliased types. | |
| /// | |
| /// If [legacyEraseAliases] is `true`, the unaliased types will be legacy | |
| /// erased. This used when the [TypedefType] was used in a legacy library. | |
| List<DartType>? unaliasTypes(List<DartType>? types) { | |
| if (types == null) return null; | |
| return rawUnaliasTypes(types) ?? types; | |
| } | |
| /// Replaces all occurrences of [TypedefType] in [type] with the corresponding | |
| /// unaliased type, or returns `null` if no [TypedefType]s were found. | |
| /// | |
| /// If [legacyEraseAliases] is `true`, the unaliased types will be legacy | |
| /// erased. This used when the [TypedefType] was used in a legacy library. | |
| DartType? rawUnalias(DartType type) { | |
| return type.accept1(const _Unalias(), Variance.covariant); | |
| } | |
| /// Replaces all occurrences of [TypedefType] in [types] with the corresponding | |
| /// unaliased types, or returns `null` if no [TypedefType]s were found. | |
| /// | |
| /// If [legacyEraseAliases] is `true`, the unaliased types will be legacy | |
| /// erased. This used when the [TypedefType] was used in a legacy library. | |
| DartTypeList? rawUnaliasTypes(List<DartType> types) { | |
| DartTypeList? newTypes; | |
| for (int i = 0; i < types.length; i++) { | |
| DartType typeArgument = types[i]; | |
| DartType? newTypeArgument = rawUnalias(typeArgument); | |
| if (newTypeArgument != null) { | |
| newTypes ??= DartTypeList.from(types); | |
| newTypes[i] = newTypeArgument; | |
| } | |
| } | |
| return newTypes; | |
| } | |
| /// Visitor that replaces all occurrences of [TypedefType] with the | |
| /// corresponding unaliased type, or returns `null` if no type was replaced. | |
| /// | |
| /// If [legacyEraseAliases] is `true`, the unaliased types will be legacy | |
| /// erased. This used when the [TypedefType] was used in a legacy library. | |
| class _Unalias extends ReplacementVisitor { | |
| const new(); | |
| @override | |
| DartType visitTypedefType(TypedefType node, Variance variance) { | |
| DartType result; | |
| if (node.typeArguments.isNotEmpty) { | |
| DartTypeList? newTypeArguments = null; | |
| for (int i = 0; i < node.typeArguments.length; i++) { | |
| DartType? substitution = node.typeArguments[i].accept1(this, variance); | |
| if (substitution != null) { | |
| newTypeArguments ??= DartTypeList.from(node.typeArguments); | |
| newTypeArguments[i] = substitution; | |
| } | |
| } | |
| if (newTypeArguments != null) { | |
| result = new TypedefType( | |
| node.typedefNode, | |
| node.nullability, | |
| newTypeArguments, | |
| ).unalias; | |
| } else { | |
| result = node.unalias; | |
| } | |
| } else { | |
| result = node.unalias; | |
| } | |
| result = result.withDeclaredNullability( | |
| uniteNullabilities(node.declaredNullability, result.declaredNullability), | |
| ); | |
| return result; | |
| } | |
| } |