| // 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/dart/ast/ast.dart'; |
| import 'package:analyzer/dart/element/element.dart'; |
| import 'package:nnbd_migration/instrumentation.dart'; |
| |
| String _computeElementName(Element? element) { |
| List<String> parts = []; |
| while (element != null && element is! CompilationUnitElement) { |
| var name = element.name; |
| if (name == null || name.isEmpty) { |
| parts.add('<unnamed>'); |
| } else { |
| parts.add(name); |
| } |
| element = element.enclosingElement; |
| } |
| if (parts.isEmpty) { |
| assert(false, 'Could not compute a name for $element'); |
| return '<unknown>'; |
| } |
| return parts.reversed.join('.'); |
| } |
| |
| /// Data structure tracking information about which type in the user's source |
| /// code is referenced by a given nullability node. |
| abstract class NullabilityNodeTarget { |
| /// Creates a [NullabilityNodeTarget] referring to a particular element. |
| factory NullabilityNodeTarget.element(Element element) = |
| _NullabilityNodeTarget_Element; |
| |
| /// Creates a [NullabilityNodeTarget] with a simple text description. |
| factory NullabilityNodeTarget.text(String name) = _NullabilityNodeTarget_Text; |
| |
| /// Creates a new [NullabilityNodeTarget] representing the bound of a type |
| /// parameter. |
| factory NullabilityNodeTarget.typeParameterBound( |
| TypeParameterElement element) = _NullabilityNodeTarget_TypeParameterBound; |
| |
| NullabilityNodeTarget._(); |
| |
| /// The source code location associated with this target, if known. Otherwise |
| /// `null`. |
| CodeReference? get codeReference => null; |
| |
| /// Gets a short description of this nullability node target suitable for |
| /// displaying to the user, not including a code reference. |
| String get description; |
| |
| /// Same as [description], but if there is a [codeReference], it is included |
| /// after the description in parentheses. |
| String get displayName { |
| if (codeReference == null) return description; |
| return '$description (${codeReference!.shortName})'; |
| } |
| |
| NullabilityNodeTarget get supertype => _NullabilityNodeTarget_Supertype(this); |
| |
| /// Creates a new [NullabilityNodeTarget] representing a named function |
| /// parameter of this target. |
| NullabilityNodeTarget namedParameter(String name) => |
| _NullabilityNodeTarget_NamedParameter(this, name); |
| |
| /// Creates a new [NullabilityNodeTarget] representing a positional function |
| /// parameter of this target. |
| NullabilityNodeTarget positionalParameter(int index) => |
| _NullabilityNodeTarget_PositionalParameter(this, index); |
| |
| /// Creates a new [NullabilityNodeTarget] representing a function return type |
| /// of this target. |
| NullabilityNodeTarget returnType() => _NullabilityNodeTarget_ReturnType(this); |
| |
| /// Creates a new [NullabilityNodeTarget] representing a type argument of this |
| /// target. |
| NullabilityNodeTarget typeArgument(int index) => |
| _NullabilityNodeTarget_TypeArgument(this, index); |
| |
| /// Creates a new [NullabilityNodeTarget] representing the bound of a formal |
| /// function type parameter of this target. |
| NullabilityNodeTarget typeFormalBound(String typeFormalName) => |
| _NullabilityNodeTarget_TypeFormalBound(this, typeFormalName); |
| |
| /// Creates a [NullabilityNodeTarget] referring to a particular point in the |
| /// source code. |
| NullabilityNodeTarget withCodeRef(AstNode astNode) => |
| _NullabilityNodeTarget_CodeRef(this, astNode); |
| } |
| |
| /// Nullability node target representing a reference to a specific location in |
| /// source code. |
| class _NullabilityNodeTarget_CodeRef extends NullabilityNodeTarget { |
| final NullabilityNodeTarget inner; |
| |
| final CodeReference codeReference; |
| |
| _NullabilityNodeTarget_CodeRef(this.inner, AstNode astNode) |
| : codeReference = CodeReference.fromAstNode(astNode), |
| super._(); |
| |
| @override |
| String get description => inner.description; |
| } |
| |
| /// Nullability node target representing the type of an element. |
| class _NullabilityNodeTarget_Element extends NullabilityNodeTarget { |
| final String name; |
| |
| final CodeReference codeReference; |
| |
| _NullabilityNodeTarget_Element(Element element) |
| : name = _computeElementName(element), |
| codeReference = CodeReference.fromElement(element), |
| super._(); |
| |
| @override |
| String get description => name; |
| } |
| |
| /// Nullability node target representing the type of a named function parameter. |
| class _NullabilityNodeTarget_NamedParameter |
| extends _NullabilityNodeTarget_Part { |
| final String name; |
| |
| _NullabilityNodeTarget_NamedParameter(NullabilityNodeTarget inner, this.name) |
| : super(inner); |
| |
| @override |
| String get description => 'parameter $name of ${inner.description}'; |
| } |
| |
| /// Nullability node target representing a type that forms part of a larger type |
| /// (e.g. the `int` part of `List<int>`). |
| abstract class _NullabilityNodeTarget_Part extends NullabilityNodeTarget { |
| final NullabilityNodeTarget inner; |
| |
| _NullabilityNodeTarget_Part(this.inner) : super._(); |
| |
| @override |
| CodeReference? get codeReference => inner.codeReference; |
| } |
| |
| /// Nullability node target representing the type of a positional function |
| /// parameter. |
| class _NullabilityNodeTarget_PositionalParameter |
| extends _NullabilityNodeTarget_Part { |
| final int index; |
| |
| _NullabilityNodeTarget_PositionalParameter( |
| NullabilityNodeTarget inner, this.index) |
| : super(inner); |
| |
| @override |
| String get description => 'parameter $index of ${inner.description}'; |
| } |
| |
| /// Nullability node target representing a function's return type. |
| class _NullabilityNodeTarget_ReturnType extends _NullabilityNodeTarget_Part { |
| _NullabilityNodeTarget_ReturnType(NullabilityNodeTarget inner) : super(inner); |
| |
| @override |
| String get description => 'return type of ${inner.description}'; |
| } |
| |
| /// Nullability node target representing one of a class's supertypes. |
| class _NullabilityNodeTarget_Supertype extends _NullabilityNodeTarget_Part { |
| _NullabilityNodeTarget_Supertype(NullabilityNodeTarget inner) : super(inner); |
| |
| @override |
| String get description => 'supertype of ${inner.description}'; |
| } |
| |
| /// Nullability node target for which we only know a string description. |
| class _NullabilityNodeTarget_Text extends NullabilityNodeTarget { |
| final String name; |
| |
| _NullabilityNodeTarget_Text(this.name) : super._(); |
| |
| @override |
| String get description => name; |
| } |
| |
| /// Nullability node target representing a type argument of an interface type or |
| /// or typedef. |
| class _NullabilityNodeTarget_TypeArgument extends _NullabilityNodeTarget_Part { |
| final int index; |
| |
| _NullabilityNodeTarget_TypeArgument(NullabilityNodeTarget inner, this.index) |
| : super(inner); |
| |
| @override |
| String get description => 'type argument $index of ${inner.description}'; |
| } |
| |
| /// Nullability node target representing a bound of a function type's formal |
| /// type parameter. |
| class _NullabilityNodeTarget_TypeFormalBound |
| extends _NullabilityNodeTarget_Part { |
| final String typeFormalName; |
| |
| _NullabilityNodeTarget_TypeFormalBound( |
| NullabilityNodeTarget inner, this.typeFormalName) |
| : super(inner); |
| |
| @override |
| String get description => |
| 'bound of type formal $typeFormalName of ${inner.description}'; |
| } |
| |
| /// Nullability node target representing a type parameter bound. |
| class _NullabilityNodeTarget_TypeParameterBound extends NullabilityNodeTarget { |
| final String name; |
| |
| _NullabilityNodeTarget_TypeParameterBound(TypeParameterElement element) |
| : name = _computeElementName(element), |
| super._(); |
| |
| @override |
| String get description => 'bound of $name'; |
| } |