|
| 1 | +// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file |
| 2 | +// for details. All rights reserved. Use of this source code is governed by a |
| 3 | +// BSD-style license that can be found in the LICENSE file. |
| 4 | + |
| 5 | +import 'package:analyzer/dart/element/type.dart'; |
| 6 | +import 'package:analyzer/src/dart/element/type.dart'; |
| 7 | +import 'package:nnbd_migration/src/decorated_type.dart'; |
| 8 | +import 'package:nnbd_migration/src/nullability_node.dart'; |
| 9 | + |
| 10 | +/// This class transforms ordinary [DartType]s into their corresponding |
| 11 | +/// [DecoratedType]s, assuming the [DartType]s come from code that has already |
| 12 | +/// been migrated to NNBD. |
| 13 | +class AlreadyMigratedCodeDecorator { |
| 14 | + final NullabilityGraph _graph; |
| 15 | + |
| 16 | + AlreadyMigratedCodeDecorator(this._graph); |
| 17 | + |
| 18 | + /// Transforms [type], which should have come from code that has already been |
| 19 | + /// migrated to NNBD, into the corresponding [DecoratedType]. |
| 20 | + DecoratedType decorate(DartType type) { |
| 21 | + if (type.isVoid || type.isDynamic) { |
| 22 | + return DecoratedType(type, _graph.always); |
| 23 | + } |
| 24 | + var nullabilitySuffix = (type as TypeImpl).nullabilitySuffix; |
| 25 | + if (nullabilitySuffix == NullabilitySuffix.question) { |
| 26 | + // TODO(paulberry): add support for depending on already-migrated packages |
| 27 | + // containing nullable types. |
| 28 | + throw UnimplementedError( |
| 29 | + 'Migration depends on an already-migrated nullable type'); |
| 30 | + } else { |
| 31 | + // Currently, all types passed to this method have nullability suffix `star` |
| 32 | + // because (a) we don't yet have a migrated SDK, and (b) we haven't added |
| 33 | + // support to the migrator for analyzing packages that have already been |
| 34 | + // migrated with NNBD enabled. |
| 35 | + // TODO(paulberry): fix this assertion when things change. |
| 36 | + assert(nullabilitySuffix == NullabilitySuffix.star); |
| 37 | + } |
| 38 | + if (type is FunctionType) { |
| 39 | + var positionalParameters = <DecoratedType>[]; |
| 40 | + var namedParameters = <String, DecoratedType>{}; |
| 41 | + for (var parameter in type.parameters) { |
| 42 | + if (parameter.isPositional) { |
| 43 | + positionalParameters.add(decorate(parameter.type)); |
| 44 | + } else { |
| 45 | + namedParameters[parameter.name] = decorate(parameter.type); |
| 46 | + } |
| 47 | + } |
| 48 | + return DecoratedType(type, _graph.never, |
| 49 | + returnType: decorate(type.returnType), |
| 50 | + namedParameters: namedParameters, |
| 51 | + positionalParameters: positionalParameters); |
| 52 | + } else if (type is InterfaceType) { |
| 53 | + if (type.typeParameters.isNotEmpty) { |
| 54 | + // TODO(paulberry) |
| 55 | + throw UnimplementedError('Decorating ${type.displayName}'); |
| 56 | + } |
| 57 | + return DecoratedType(type, _graph.never); |
| 58 | + } else if (type is TypeParameterType) { |
| 59 | + return DecoratedType(type, _graph.never); |
| 60 | + } else { |
| 61 | + // TODO(paulberry) |
| 62 | + throw UnimplementedError( |
| 63 | + 'Unable to decorate already-migrated type $type'); |
| 64 | + } |
| 65 | + } |
| 66 | +} |
0 commit comments