// Copyright (c) 2020, 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:analyzer/src/generated/utilities_general.dart'; /// Data structure representing a part of a type. When a fix has multiple /// reasons (due to a complex type having different nullabilities at different /// locations), this data structure allows us to tell which part of the type /// is associated with each reason. abstract class FixReasonTarget { /// Fix reason target representing the full type, rather than a part of it. static const FixReasonTarget root = _FixReasonTarget_Root(); const FixReasonTarget._(); /// Gets a fix reason target representing the type's return type. FixReasonTarget get returnType => _FixReasonTarget_ReturnType(this); /// Returns a description of the fix reason target that's suitable for /// appending to a description of a nullability trace. /// /// For example, `root.returnType.suffix` returns ` for return type`. This /// can be attached to a string like `nullability reason` to form /// `nullability reason for return type`. String get suffix => _describe('for'); /// Gets a fix reason target representing the type's yielded type. This /// represents the type argument of `Future` or `FutureOr`, or in the case /// where `await` is applied to a non-future type, the type itself. FixReasonTarget get yieldedType => _FixReasonTarget_YieldedType(this); /// Gets a fix reason target representing one of the type's named parameters. FixReasonTarget namedParameter(String name) => _FixReasonTarget_NamedParameter(this, name); /// Gets a fix reason target representing one of the type's positional /// parameters. FixReasonTarget positionalParameter(int i) => _FixReasonTarget_PositionalParameter(this, i); /// Gets a fix reason target representing one of the type's type arguments. FixReasonTarget typeArgument(int i) => _FixReasonTarget_TypeArgument(this, i); String _describe(String preposition); } /// Fix reason target representing a named parameter of a function type. class _FixReasonTarget_NamedParameter extends _FixReasonTarget_Part { final String name; _FixReasonTarget_NamedParameter(FixReasonTarget inner, this.name) : super(inner); @override int get hashCode => JenkinsSmiHash.hash3(2, inner.hashCode, name.hashCode); @override bool operator ==(Object other) => other is _FixReasonTarget_NamedParameter && inner == other.inner && name == other.name; @override String _describe(String preposition) => ' $preposition parameter $name${inner._describe('of')}'; } /// Fix reason target representing a type that forms part of a larger type (e.g. /// the `int` part of `List`). abstract class _FixReasonTarget_Part extends FixReasonTarget { final FixReasonTarget inner; _FixReasonTarget_Part(this.inner) : super._(); } /// Fix reason target representing a positional parameter of a function type. class _FixReasonTarget_PositionalParameter extends _FixReasonTarget_Part { final int index; _FixReasonTarget_PositionalParameter(FixReasonTarget inner, this.index) : super(inner); @override int get hashCode => JenkinsSmiHash.hash3(1, inner.hashCode, index); @override bool operator ==(Object other) => other is _FixReasonTarget_PositionalParameter && inner == other.inner && index == other.index; @override String _describe(String preposition) => ' $preposition parameter $index${inner._describe('of')}'; } /// Fix reason target representing the return type of a function type. class _FixReasonTarget_ReturnType extends _FixReasonTarget_Part { _FixReasonTarget_ReturnType(FixReasonTarget inner) : super(inner); @override int get hashCode => JenkinsSmiHash.hash2(3, inner.hashCode); @override bool operator ==(Object other) => other is _FixReasonTarget_ReturnType && inner == other.inner; @override String _describe(String preposition) => ' $preposition return type${inner._describe('of')}'; } /// Fix reason target representing the root of the type in question. class _FixReasonTarget_Root extends FixReasonTarget { const _FixReasonTarget_Root() : super._(); @override int get hashCode => 0; @override bool operator ==(Object other) => other is _FixReasonTarget_Root; @override String _describe(String preposition) => ''; } /// Fix reason target representing a type argument of an interface type. class _FixReasonTarget_TypeArgument extends _FixReasonTarget_Part { final int index; _FixReasonTarget_TypeArgument(FixReasonTarget inner, this.index) : super(inner); @override int get hashCode => JenkinsSmiHash.hash3(5, inner.hashCode, index); @override bool operator ==(Object other) => other is _FixReasonTarget_TypeArgument && inner == other.inner && index == other.index; @override String _describe(String preposition) => ' $preposition type argument $index${inner._describe('of')}'; } /// Fix reason target representing the type argument of `Future` or `FutureOr`, /// or in the case where `await` is applied to a non-future type, the type /// itself. /// /// This allows the migration tool to describe a type correspondence that exists /// in a subtype check involving `FutureOr`, for example if the user tries to /// assign `List` to `FutureOr>`, then the migration tool /// determines that it needs to change `*` into `?`. To make this determination /// it has to form a correspondence between the type argument of the source type /// and the type argument of the type argument of the destination type. To /// explain to the user which part of the two types is involved in the /// correspondence, we need an ambiguous way of referring to either "type /// argument of type argument of" or simply "type argument". The solution is to /// describe the fix reason target as "type argument of yielded type". class _FixReasonTarget_YieldedType extends _FixReasonTarget_Part { _FixReasonTarget_YieldedType(FixReasonTarget inner) : super(inner); @override int get hashCode => JenkinsSmiHash.hash2(4, inner.hashCode); @override bool operator ==(Object other) => other is _FixReasonTarget_YieldedType && inner == other.inner; @override String _describe(String preposition) => ' $preposition yielded type${inner._describe('from')}'; }