| Index: packages/analyzer/lib/src/dart/element/member.dart
|
| diff --git a/packages/analyzer/lib/src/dart/element/member.dart b/packages/analyzer/lib/src/dart/element/member.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d498728b9ef73c41cd2ad500978ebe1d6d45a03e
|
| --- /dev/null
|
| +++ b/packages/analyzer/lib/src/dart/element/member.dart
|
| @@ -0,0 +1,1030 @@
|
| +// Copyright (c) 2014, 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.
|
| +
|
| +library analyzer.src.dart.element.member;
|
| +
|
| +import 'package:analyzer/dart/ast/ast.dart';
|
| +import 'package:analyzer/dart/constant/value.dart';
|
| +import 'package:analyzer/dart/element/element.dart';
|
| +import 'package:analyzer/dart/element/type.dart';
|
| +import 'package:analyzer/src/dart/element/element.dart';
|
| +import 'package:analyzer/src/dart/element/type.dart';
|
| +import 'package:analyzer/src/generated/engine.dart'
|
| + show AnalysisContext, AnalysisEngine;
|
| +import 'package:analyzer/src/generated/java_engine.dart';
|
| +import 'package:analyzer/src/generated/source.dart';
|
| +import 'package:analyzer/src/generated/utilities_dart.dart';
|
| +
|
| +/**
|
| + * A constructor element defined in a parameterized type where the values of the
|
| + * type parameters are known.
|
| + */
|
| +class ConstructorMember extends ExecutableMember implements ConstructorElement {
|
| + /**
|
| + * Initialize a newly created element to represent a constructor, based on the
|
| + * [baseElement], defined by the [definingType]. If [type] is passed, it
|
| + * represents the full type of the member, and will take precedence over
|
| + * the [definingType].
|
| + */
|
| + ConstructorMember(ConstructorElement baseElement, InterfaceType definingType,
|
| + [FunctionType type])
|
| + : super(baseElement, definingType, type);
|
| +
|
| + @override
|
| + ConstructorElement get baseElement => super.baseElement as ConstructorElement;
|
| +
|
| + @override
|
| + InterfaceType get definingType => super.definingType as InterfaceType;
|
| +
|
| + @override
|
| + ClassElement get enclosingElement => baseElement.enclosingElement;
|
| +
|
| + @override
|
| + bool get isConst => baseElement.isConst;
|
| +
|
| + @override
|
| + bool get isDefaultConstructor => baseElement.isDefaultConstructor;
|
| +
|
| + @override
|
| + bool get isFactory => baseElement.isFactory;
|
| +
|
| + @override
|
| + int get nameEnd => baseElement.nameEnd;
|
| +
|
| + @override
|
| + int get periodOffset => baseElement.periodOffset;
|
| +
|
| + @override
|
| + ConstructorElement get redirectedConstructor =>
|
| + from(baseElement.redirectedConstructor, definingType);
|
| +
|
| + @override
|
| + accept(ElementVisitor visitor) => visitor.visitConstructorElement(this);
|
| +
|
| + @override
|
| + ConstructorDeclaration computeNode() => baseElement.computeNode();
|
| +
|
| + @override
|
| + String toString() {
|
| + ConstructorElement baseElement = this.baseElement;
|
| + List<ParameterElement> parameters = this.parameters;
|
| + FunctionType type = this.type;
|
| + StringBuffer buffer = new StringBuffer();
|
| + buffer.write(baseElement.enclosingElement.displayName);
|
| + String name = displayName;
|
| + if (name != null && !name.isEmpty) {
|
| + buffer.write(".");
|
| + buffer.write(name);
|
| + }
|
| + buffer.write("(");
|
| + int parameterCount = parameters.length;
|
| + for (int i = 0; i < parameterCount; i++) {
|
| + if (i > 0) {
|
| + buffer.write(", ");
|
| + }
|
| + buffer.write(parameters[i]);
|
| + }
|
| + buffer.write(")");
|
| + if (type != null) {
|
| + buffer.write(ElementImpl.RIGHT_ARROW);
|
| + buffer.write(type.returnType);
|
| + }
|
| + return buffer.toString();
|
| + }
|
| +
|
| + /**
|
| + * If the given [constructor]'s type is different when any type parameters
|
| + * from the defining type's declaration are replaced with the actual type
|
| + * arguments from the [definingType], create a constructor member representing
|
| + * the given constructor. Return the member that was created, or the original
|
| + * constructor if no member was created.
|
| + */
|
| + static ConstructorElement from(
|
| + ConstructorElement constructor, InterfaceType definingType) {
|
| + if (constructor == null || definingType.typeArguments.length == 0) {
|
| + return constructor;
|
| + }
|
| + FunctionType baseType = constructor.type;
|
| + if (baseType == null) {
|
| + // TODO(brianwilkerson) We need to understand when this can happen.
|
| + return constructor;
|
| + }
|
| + List<DartType> argumentTypes = definingType.typeArguments;
|
| + List<DartType> parameterTypes = definingType.element.type.typeArguments;
|
| + FunctionType substitutedType =
|
| + baseType.substitute2(argumentTypes, parameterTypes);
|
| + return new ConstructorMember(constructor, definingType, substitutedType);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * An executable element defined in a parameterized type where the values of the
|
| + * type parameters are known.
|
| + */
|
| +abstract class ExecutableMember extends Member implements ExecutableElement {
|
| + FunctionType _type;
|
| +
|
| + /**
|
| + * Initialize a newly created element to represent a callable element (like a
|
| + * method or function or property), based on the [baseElement], defined by the
|
| + * [definingType]. If [type] is passed, it represents the full type of the
|
| + * member, and will take precedence over the [definingType].
|
| + */
|
| + ExecutableMember(ExecutableElement baseElement, InterfaceType definingType,
|
| + [FunctionType type])
|
| + : _type = type,
|
| + super(baseElement, definingType);
|
| +
|
| + @override
|
| + ExecutableElement get baseElement => super.baseElement as ExecutableElement;
|
| +
|
| + @override
|
| + List<FunctionElement> get functions {
|
| + //
|
| + // Elements within this element should have type parameters substituted,
|
| + // just like this element.
|
| + //
|
| + throw new UnsupportedError('functions');
|
| +// return getBaseElement().getFunctions();
|
| + }
|
| +
|
| + @override
|
| + bool get hasImplicitReturnType => baseElement.hasImplicitReturnType;
|
| +
|
| + @override
|
| + bool get isAbstract => baseElement.isAbstract;
|
| +
|
| + @override
|
| + bool get isAsynchronous => baseElement.isAsynchronous;
|
| +
|
| + @override
|
| + bool get isExternal => baseElement.isExternal;
|
| +
|
| + @override
|
| + bool get isGenerator => baseElement.isGenerator;
|
| +
|
| + @override
|
| + bool get isOperator => baseElement.isOperator;
|
| +
|
| + @override
|
| + bool get isStatic => baseElement.isStatic;
|
| +
|
| + @override
|
| + bool get isSynchronous => baseElement.isSynchronous;
|
| +
|
| + @override
|
| + List<LabelElement> get labels => baseElement.labels;
|
| +
|
| + @override
|
| + List<LocalVariableElement> get localVariables {
|
| + //
|
| + // Elements within this element should have type parameters substituted,
|
| + // just like this element.
|
| + //
|
| + throw new UnsupportedError('localVariables');
|
| +// return getBaseElement().getLocalVariables();
|
| + }
|
| +
|
| + @override
|
| + List<ParameterElement> get parameters => type.parameters;
|
| +
|
| + @override
|
| + DartType get returnType => type.returnType;
|
| +
|
| + @override
|
| + FunctionType get type {
|
| + return _type ??= baseElement.type.substitute2(definingType.typeArguments,
|
| + TypeParameterTypeImpl.getTypes(definingType.typeParameters));
|
| + }
|
| +
|
| + @override
|
| + List<TypeParameterElement> get typeParameters => baseElement.typeParameters;
|
| +
|
| + @override
|
| + void visitChildren(ElementVisitor visitor) {
|
| + // TODO(brianwilkerson) We need to finish implementing the accessors used
|
| + // below so that we can safely invoke them.
|
| + super.visitChildren(visitor);
|
| + safelyVisitChildren(baseElement.functions, visitor);
|
| + safelyVisitChildren(labels, visitor);
|
| + safelyVisitChildren(baseElement.localVariables, visitor);
|
| + safelyVisitChildren(parameters, visitor);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A parameter element defined in a parameterized type where the values of the
|
| + * type parameters are known.
|
| + */
|
| +class FieldFormalParameterMember extends ParameterMember
|
| + implements FieldFormalParameterElement {
|
| + /**
|
| + * Initialize a newly created element to represent a field formal parameter,
|
| + * based on the [baseElement], defined by the [definingType]. If [type]
|
| + * is passed it will be used as the substituted type for this member.
|
| + */
|
| + FieldFormalParameterMember(
|
| + FieldFormalParameterElement baseElement, ParameterizedType definingType,
|
| + [DartType type])
|
| + : super(baseElement, definingType, type);
|
| +
|
| + @override
|
| + bool get isCovariant => baseElement.isCovariant;
|
| +
|
| + @override
|
| + FieldElement get field {
|
| + FieldElement field = (baseElement as FieldFormalParameterElement).field;
|
| + if (field is FieldElement) {
|
| + return FieldMember.from(
|
| + field, substituteFor(field.enclosingElement.type));
|
| + }
|
| + return field;
|
| + }
|
| +
|
| + @override
|
| + accept(ElementVisitor visitor) =>
|
| + visitor.visitFieldFormalParameterElement(this);
|
| +}
|
| +
|
| +/**
|
| + * A field element defined in a parameterized type where the values of the type
|
| + * parameters are known.
|
| + */
|
| +class FieldMember extends VariableMember implements FieldElement {
|
| + /**
|
| + * Initialize a newly created element to represent a field, based on the
|
| + * [baseElement], defined by the [definingType].
|
| + */
|
| + FieldMember(FieldElement baseElement, InterfaceType definingType)
|
| + : super(baseElement, definingType);
|
| +
|
| + @override
|
| + FieldElement get baseElement => super.baseElement as FieldElement;
|
| +
|
| + @override
|
| + ClassElement get enclosingElement => baseElement.enclosingElement;
|
| +
|
| + @override
|
| + PropertyAccessorElement get getter =>
|
| + PropertyAccessorMember.from(baseElement.getter, definingType);
|
| +
|
| + @override
|
| + bool get isEnumConstant => baseElement.isEnumConstant;
|
| +
|
| + @override
|
| + bool get isVirtual => baseElement.isVirtual;
|
| +
|
| + @override
|
| + DartType get propagatedType => substituteFor(baseElement.propagatedType);
|
| +
|
| + @override
|
| + PropertyAccessorElement get setter =>
|
| + PropertyAccessorMember.from(baseElement.setter, definingType);
|
| +
|
| + @override
|
| + accept(ElementVisitor visitor) => visitor.visitFieldElement(this);
|
| +
|
| + @override
|
| + VariableDeclaration computeNode() => baseElement.computeNode();
|
| +
|
| + @override
|
| + String toString() => '$type $displayName';
|
| +
|
| + /**
|
| + * If the given [field]'s type is different when any type parameters from the
|
| + * defining type's declaration are replaced with the actual type arguments
|
| + * from the [definingType], create a field member representing the given
|
| + * field. Return the member that was created, or the base field if no member
|
| + * was created.
|
| + */
|
| + static FieldElement from(FieldElement field, ParameterizedType definingType) {
|
| + if (!_isChangedByTypeSubstitution(field, definingType)) {
|
| + return field;
|
| + }
|
| + // TODO(brianwilkerson) Consider caching the substituted type in the
|
| + // instance. It would use more memory but speed up some operations.
|
| + // We need to see how often the type is being re-computed.
|
| + return new FieldMember(field, definingType);
|
| + }
|
| +
|
| + /**
|
| + * Determine whether the given [field]'s type is changed when type parameters
|
| + * from the [definingType]'s declaration are replaced with the actual type
|
| + * arguments from the defining type.
|
| + */
|
| + static bool _isChangedByTypeSubstitution(
|
| + FieldElement field, ParameterizedType definingType) {
|
| + List<DartType> argumentTypes = definingType.typeArguments;
|
| + if (field != null && argumentTypes.length != 0) {
|
| + DartType baseType = field.type;
|
| + List<DartType> parameterTypes =
|
| + TypeParameterTypeImpl.getTypes(definingType.typeParameters);
|
| + if (baseType != null) {
|
| + DartType substitutedType =
|
| + baseType.substitute2(argumentTypes, parameterTypes);
|
| + if (baseType != substitutedType) {
|
| + return true;
|
| + }
|
| + }
|
| + // If the field has a propagated type, then we need to check whether the
|
| + // propagated type needs substitution.
|
| + DartType basePropagatedType = field.propagatedType;
|
| + if (basePropagatedType != null) {
|
| + DartType substitutedPropagatedType =
|
| + basePropagatedType.substitute2(argumentTypes, parameterTypes);
|
| + if (basePropagatedType != substitutedPropagatedType) {
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Deprecated: this type is no longer used. Use
|
| + * [MethodInvocation.staticInvokeType] to get the instantiated type of a generic
|
| + * method invocation.
|
| + *
|
| + * An element of a generic function, where the type parameters are known.
|
| + */
|
| +// TODO(jmesserly): the term "function member" is a bit weird, but it allows
|
| +// a certain consistency.
|
| +@deprecated
|
| +class FunctionMember extends ExecutableMember implements FunctionElement {
|
| + /**
|
| + * Initialize a newly created element to represent a function, based on the
|
| + * [baseElement], with the corresponding function [type].
|
| + */
|
| + @deprecated
|
| + FunctionMember(FunctionElement baseElement, [DartType type])
|
| + : super(baseElement, null, type);
|
| +
|
| + @override
|
| + FunctionElement get baseElement => super.baseElement as FunctionElement;
|
| +
|
| + @override
|
| + Element get enclosingElement => baseElement.enclosingElement;
|
| +
|
| + @override
|
| + bool get isEntryPoint => baseElement.isEntryPoint;
|
| +
|
| + @override
|
| + SourceRange get visibleRange => baseElement.visibleRange;
|
| +
|
| + @override
|
| + accept(ElementVisitor visitor) => visitor.visitFunctionElement(this);
|
| +
|
| + @override
|
| + FunctionDeclaration computeNode() => baseElement.computeNode();
|
| +
|
| + @override
|
| + String toString() {
|
| + StringBuffer buffer = new StringBuffer();
|
| + buffer.write(baseElement.displayName);
|
| + (type as FunctionTypeImpl).appendTo(buffer);
|
| + return buffer.toString();
|
| + }
|
| +
|
| + /**
|
| + * If the given [method]'s type is different when any type parameters from the
|
| + * defining type's declaration are replaced with the actual type arguments
|
| + * from the [definingType], create a method member representing the given
|
| + * method. Return the member that was created, or the base method if no member
|
| + * was created.
|
| + */
|
| + static MethodElement from(
|
| + MethodElement method, ParameterizedType definingType) {
|
| + if (method == null || definingType.typeArguments.length == 0) {
|
| + return method;
|
| + }
|
| + FunctionType baseType = method.type;
|
| + List<DartType> argumentTypes = definingType.typeArguments;
|
| + List<DartType> parameterTypes =
|
| + TypeParameterTypeImpl.getTypes(definingType.typeParameters);
|
| + FunctionType substitutedType =
|
| + baseType.substitute2(argumentTypes, parameterTypes);
|
| + return new MethodMember(method, definingType, substitutedType);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * An element defined in a parameterized type where the values of the type
|
| + * parameters are known.
|
| + */
|
| +abstract class Member implements Element {
|
| + /**
|
| + * The element on which the parameterized element was created.
|
| + */
|
| + final Element _baseElement;
|
| +
|
| + /**
|
| + * The type in which the element is defined.
|
| + */
|
| + final ParameterizedType _definingType;
|
| +
|
| + /**
|
| + * Initialize a newly created element to represent a member, based on the
|
| + * [baseElement], defined by the [definingType].
|
| + */
|
| + Member(this._baseElement, this._definingType);
|
| +
|
| + /**
|
| + * Return the element on which the parameterized element was created.
|
| + */
|
| + Element get baseElement => _baseElement;
|
| +
|
| + @override
|
| + AnalysisContext get context => _baseElement.context;
|
| +
|
| + /**
|
| + * Return the type in which the element is defined.
|
| + */
|
| + ParameterizedType get definingType => _definingType;
|
| +
|
| + @override
|
| + String get displayName => _baseElement.displayName;
|
| +
|
| + @override
|
| + String get documentationComment => _baseElement.documentationComment;
|
| +
|
| + @override
|
| + int get id => _baseElement.id;
|
| +
|
| + @override
|
| + bool get isDeprecated => _baseElement.isDeprecated;
|
| +
|
| + @override
|
| + bool get isFactory => _baseElement.isFactory;
|
| +
|
| + @override
|
| + bool get isJS => _baseElement.isJS;
|
| +
|
| + @override
|
| + bool get isOverride => _baseElement.isOverride;
|
| +
|
| + @override
|
| + bool get isPrivate => _baseElement.isPrivate;
|
| +
|
| + @override
|
| + bool get isProtected => _baseElement.isProtected;
|
| +
|
| + @override
|
| + bool get isPublic => _baseElement.isPublic;
|
| +
|
| + @override
|
| + bool get isRequired => _baseElement.isRequired;
|
| +
|
| + @override
|
| + bool get isSynthetic => _baseElement.isSynthetic;
|
| +
|
| + @override
|
| + ElementKind get kind => _baseElement.kind;
|
| +
|
| + @override
|
| + LibraryElement get library => _baseElement.library;
|
| +
|
| + @override
|
| + Source get librarySource => _baseElement.librarySource;
|
| +
|
| + @override
|
| + ElementLocation get location => _baseElement.location;
|
| +
|
| + @override
|
| + List<ElementAnnotation> get metadata => _baseElement.metadata;
|
| +
|
| + @override
|
| + String get name => _baseElement.name;
|
| +
|
| + @override
|
| + int get nameLength => _baseElement.nameLength;
|
| +
|
| + @override
|
| + int get nameOffset => _baseElement.nameOffset;
|
| +
|
| + @override
|
| + Source get source => _baseElement.source;
|
| +
|
| + @override
|
| + CompilationUnit get unit => _baseElement.unit;
|
| +
|
| + @override
|
| + String computeDocumentationComment() => documentationComment;
|
| +
|
| + @override
|
| + AstNode computeNode() => _baseElement.computeNode();
|
| +
|
| + @override
|
| + Element/*=E*/ getAncestor/*<E extends Element >*/(
|
| + Predicate<Element> predicate) =>
|
| + baseElement.getAncestor(predicate);
|
| +
|
| + @override
|
| + String getExtendedDisplayName(String shortName) =>
|
| + _baseElement.getExtendedDisplayName(shortName);
|
| +
|
| + @override
|
| + bool isAccessibleIn(LibraryElement library) =>
|
| + _baseElement.isAccessibleIn(library);
|
| +
|
| + /**
|
| + * If the given [child] is not `null`, use the given [visitor] to visit it.
|
| + */
|
| + @deprecated
|
| + void safelyVisitChild(Element child, ElementVisitor visitor) {
|
| + // TODO(brianwilkerson) Make this private
|
| + if (child != null) {
|
| + child.accept(visitor);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Use the given [visitor] to visit all of the [children].
|
| + */
|
| + void safelyVisitChildren(List<Element> children, ElementVisitor visitor) {
|
| + // TODO(brianwilkerson) Make this private
|
| + if (children != null) {
|
| + for (Element child in children) {
|
| + child.accept(visitor);
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Return the type that results from replacing the type parameters in the
|
| + * given [type] with the type arguments associated with this member.
|
| + */
|
| + DartType substituteFor(DartType type) {
|
| + if (type == null) {
|
| + return null;
|
| + }
|
| + List<DartType> argumentTypes = _definingType.typeArguments;
|
| + List<DartType> parameterTypes =
|
| + TypeParameterTypeImpl.getTypes(_definingType.typeParameters);
|
| + return type.substitute2(argumentTypes, parameterTypes);
|
| + }
|
| +
|
| + @override
|
| + void visitChildren(ElementVisitor visitor) {
|
| + // There are no children to visit
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A method element defined in a parameterized type where the values of the type
|
| + * parameters are known.
|
| + */
|
| +class MethodMember extends ExecutableMember implements MethodElement {
|
| + /**
|
| + * Initialize a newly created element to represent a method, based on the
|
| + * [baseElement], defined by the [definingType]. If [type] is passed, it
|
| + * represents the full type of the member, and will take precedence over
|
| + * the [definingType].
|
| + */
|
| + MethodMember(MethodElement baseElement, InterfaceType definingType,
|
| + [DartType type])
|
| + : super(baseElement, definingType, type);
|
| +
|
| + @override
|
| + MethodElement get baseElement => super.baseElement as MethodElement;
|
| +
|
| + @override
|
| + ClassElement get enclosingElement => baseElement.enclosingElement;
|
| +
|
| + @override
|
| + accept(ElementVisitor visitor) => visitor.visitMethodElement(this);
|
| +
|
| + @override
|
| + MethodDeclaration computeNode() => baseElement.computeNode();
|
| +
|
| + @override
|
| + String toString() {
|
| + MethodElement baseElement = this.baseElement;
|
| + List<ParameterElement> parameters = this.parameters;
|
| + FunctionType type = this.type;
|
| + StringBuffer buffer = new StringBuffer();
|
| + buffer.write(baseElement.enclosingElement.displayName);
|
| + buffer.write(".");
|
| + buffer.write(baseElement.displayName);
|
| + buffer.write("(");
|
| + int parameterCount = parameters.length;
|
| + for (int i = 0; i < parameterCount; i++) {
|
| + if (i > 0) {
|
| + buffer.write(", ");
|
| + }
|
| + buffer.write(parameters[i]);
|
| + }
|
| + buffer.write(")");
|
| + if (type != null) {
|
| + buffer.write(ElementImpl.RIGHT_ARROW);
|
| + buffer.write(type.returnType);
|
| + }
|
| + return buffer.toString();
|
| + }
|
| +
|
| + /**
|
| + * If the given [method]'s type is different when any type parameters from the
|
| + * defining type's declaration are replaced with the actual type arguments
|
| + * from the [definingType], create a method member representing the given
|
| + * method. Return the member that was created, or the base method if no member
|
| + * was created.
|
| + */
|
| + static MethodElement from(MethodElement method, InterfaceType definingType) {
|
| + if (method == null || definingType.typeArguments.length == 0) {
|
| + return method;
|
| + }
|
| + FunctionType baseType = method.type;
|
| + List<DartType> argumentTypes = definingType.typeArguments;
|
| + List<DartType> parameterTypes = definingType.element.type.typeArguments;
|
| + FunctionType substitutedType =
|
| + baseType.substitute2(argumentTypes, parameterTypes);
|
| + return new MethodMember(method, definingType, substitutedType);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A parameter element defined in a parameterized type where the values of the
|
| + * type parameters are known.
|
| + */
|
| +class ParameterMember extends VariableMember
|
| + with ParameterElementMixin
|
| + implements ParameterElement {
|
| + /**
|
| + * Initialize a newly created element to represent a parameter, based on the
|
| + * [baseElement], defined by the [definingType]. If [type] is passed it will
|
| + * represent the already substituted type.
|
| + */
|
| + ParameterMember(ParameterElement baseElement, ParameterizedType definingType,
|
| + [DartType type])
|
| + : super._(baseElement, definingType, type);
|
| +
|
| + @override
|
| + ParameterElement get baseElement => super.baseElement as ParameterElement;
|
| +
|
| + @override
|
| + String get defaultValueCode => baseElement.defaultValueCode;
|
| +
|
| + @override
|
| + Element get enclosingElement => baseElement.enclosingElement;
|
| +
|
| + @override
|
| + int get hashCode => baseElement.hashCode;
|
| +
|
| + @override
|
| + bool get isCovariant => baseElement.isCovariant;
|
| +
|
| + @override
|
| + bool get isInitializingFormal => baseElement.isInitializingFormal;
|
| +
|
| + @override
|
| + ParameterKind get parameterKind => baseElement.parameterKind;
|
| +
|
| + @override
|
| + List<ParameterElement> get parameters {
|
| + DartType type = this.type;
|
| + if (type is FunctionType) {
|
| + return type.parameters;
|
| + }
|
| + return ParameterElement.EMPTY_LIST;
|
| + }
|
| +
|
| + @override
|
| + List<TypeParameterElement> get typeParameters => baseElement.typeParameters;
|
| +
|
| + @override
|
| + SourceRange get visibleRange => baseElement.visibleRange;
|
| +
|
| + @override
|
| + accept(ElementVisitor visitor) => visitor.visitParameterElement(this);
|
| +
|
| + @override
|
| + FormalParameter computeNode() => baseElement.computeNode();
|
| +
|
| + @override
|
| + Element/*=E*/ getAncestor/*<E extends Element>*/(
|
| + Predicate<Element> predicate) {
|
| + Element element = baseElement.getAncestor(predicate);
|
| + ParameterizedType definingType = this.definingType;
|
| + if (definingType is InterfaceType) {
|
| + if (element is ConstructorElement) {
|
| + return ConstructorMember.from(element, definingType) as Element/*=E*/;
|
| + } else if (element is MethodElement) {
|
| + return MethodMember.from(element, definingType) as Element/*=E*/;
|
| + } else if (element is PropertyAccessorElement) {
|
| + return PropertyAccessorMember.from(element, definingType)
|
| + as Element/*=E*/;
|
| + }
|
| + }
|
| + return element as Element/*=E*/;
|
| + }
|
| +
|
| + @override
|
| + String toString() {
|
| + ParameterElement baseElement = this.baseElement;
|
| + String left = "";
|
| + String right = "";
|
| + while (true) {
|
| + if (baseElement.parameterKind == ParameterKind.NAMED) {
|
| + left = "{";
|
| + right = "}";
|
| + } else if (baseElement.parameterKind == ParameterKind.POSITIONAL) {
|
| + left = "[";
|
| + right = "]";
|
| + } else if (baseElement.parameterKind == ParameterKind.REQUIRED) {}
|
| + break;
|
| + }
|
| + return '$left$type ${baseElement.displayName}$right';
|
| + }
|
| +
|
| + @override
|
| + void visitChildren(ElementVisitor visitor) {
|
| + super.visitChildren(visitor);
|
| + safelyVisitChildren(parameters, visitor);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A property accessor element defined in a parameterized type where the values
|
| + * of the type parameters are known.
|
| + */
|
| +class PropertyAccessorMember extends ExecutableMember
|
| + implements PropertyAccessorElement {
|
| + /**
|
| + * Initialize a newly created element to represent a property, based on the
|
| + * [baseElement], defined by the [definingType].
|
| + */
|
| + PropertyAccessorMember(
|
| + PropertyAccessorElement baseElement, InterfaceType definingType)
|
| + : super(baseElement, definingType);
|
| +
|
| + @override
|
| + PropertyAccessorElement get baseElement =>
|
| + super.baseElement as PropertyAccessorElement;
|
| +
|
| + @override
|
| + PropertyAccessorElement get correspondingGetter =>
|
| + from(baseElement.correspondingGetter, definingType);
|
| +
|
| + @override
|
| + PropertyAccessorElement get correspondingSetter =>
|
| + from(baseElement.correspondingSetter, definingType);
|
| +
|
| + @override
|
| + InterfaceType get definingType => super.definingType as InterfaceType;
|
| +
|
| + @override
|
| + Element get enclosingElement => baseElement.enclosingElement;
|
| +
|
| + @override
|
| + bool get isGetter => baseElement.isGetter;
|
| +
|
| + @override
|
| + bool get isSetter => baseElement.isSetter;
|
| +
|
| + @override
|
| + PropertyInducingElement get variable {
|
| + PropertyInducingElement variable = baseElement.variable;
|
| + if (variable is FieldElement) {
|
| + return FieldMember.from(variable, definingType);
|
| + }
|
| + return variable;
|
| + }
|
| +
|
| + @override
|
| + accept(ElementVisitor visitor) => visitor.visitPropertyAccessorElement(this);
|
| +
|
| + @override
|
| + String toString() {
|
| + PropertyAccessorElement baseElement = this.baseElement;
|
| + List<ParameterElement> parameters = this.parameters;
|
| + FunctionType type = this.type;
|
| + StringBuffer builder = new StringBuffer();
|
| + if (isGetter) {
|
| + builder.write("get ");
|
| + } else {
|
| + builder.write("set ");
|
| + }
|
| + builder.write(baseElement.enclosingElement.displayName);
|
| + builder.write(".");
|
| + builder.write(baseElement.displayName);
|
| + builder.write("(");
|
| + int parameterCount = parameters.length;
|
| + for (int i = 0; i < parameterCount; i++) {
|
| + if (i > 0) {
|
| + builder.write(", ");
|
| + }
|
| + builder.write(parameters[i]);
|
| + }
|
| + builder.write(")");
|
| + if (type != null) {
|
| + builder.write(ElementImpl.RIGHT_ARROW);
|
| + builder.write(type.returnType);
|
| + }
|
| + return builder.toString();
|
| + }
|
| +
|
| + /**
|
| + * If the given [accessor]'s type is different when any type parameters from
|
| + * the defining type's declaration are replaced with the actual type
|
| + * arguments from the [definingType], create an accessor member representing
|
| + * the given accessor. Return the member that was created, or the base
|
| + * accessor if no member was created.
|
| + */
|
| + static PropertyAccessorElement from(
|
| + PropertyAccessorElement accessor, InterfaceType definingType) {
|
| + if (!_isChangedByTypeSubstitution(accessor, definingType)) {
|
| + return accessor;
|
| + }
|
| + // TODO(brianwilkerson) Consider caching the substituted type in the
|
| + // instance. It would use more memory but speed up some operations.
|
| + // We need to see how often the type is being re-computed.
|
| + return new PropertyAccessorMember(accessor, definingType);
|
| + }
|
| +
|
| + /**
|
| + * Determine whether the given property [accessor]'s type is changed when type
|
| + * parameters from the defining type's declaration are replaced with the
|
| + * actual type arguments from the [definingType].
|
| + */
|
| + static bool _isChangedByTypeSubstitution(
|
| + PropertyAccessorElement accessor, InterfaceType definingType) {
|
| + List<DartType> argumentTypes = definingType.typeArguments;
|
| + if (accessor != null && argumentTypes.length != 0) {
|
| + FunctionType baseType = accessor.type;
|
| + if (baseType == null) {
|
| + AnalysisEngine.instance.logger.logInformation(
|
| + 'Type of $accessor is null in PropertyAccessorMember._isChangedByTypeSubstitution');
|
| + return false;
|
| + }
|
| + List<DartType> parameterTypes = definingType.element.type.typeArguments;
|
| + FunctionType substitutedType =
|
| + baseType.substitute2(argumentTypes, parameterTypes);
|
| + if (baseType != substitutedType) {
|
| + return true;
|
| + }
|
| + // If this property accessor is based on a field, that field might have a
|
| + // propagated type. In which case we need to check whether the propagated
|
| + // type of the field needs substitution.
|
| + PropertyInducingElement field = accessor.variable;
|
| + if (!field.isSynthetic) {
|
| + DartType baseFieldType = field.propagatedType;
|
| + if (baseFieldType != null) {
|
| + DartType substitutedFieldType =
|
| + baseFieldType.substitute2(argumentTypes, parameterTypes);
|
| + if (baseFieldType != substitutedFieldType) {
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A type parameter defined inside of another parameterized type, where the
|
| + * values of the enclosing type parameters are known.
|
| + *
|
| + * For example:
|
| + *
|
| + * class C<T> {
|
| + * S m<S extends T>(S s);
|
| + * }
|
| + *
|
| + * If we have `C<num>.m` and we ask for the type parameter "S", we should get
|
| + * `<S extends num>` instead of `<S extends T>`. This is how the parameter
|
| + * and return types work, see: [FunctionType.parameters],
|
| + * [FunctionType.returnType], and [ParameterMember].
|
| + */
|
| +class TypeParameterMember extends Member implements TypeParameterElement {
|
| + @override
|
| + final DartType bound;
|
| +
|
| + DartType _type;
|
| +
|
| + TypeParameterMember(
|
| + TypeParameterElement baseElement, DartType definingType, this.bound)
|
| + : super(baseElement, definingType) {
|
| + _type = new TypeParameterTypeImpl(this);
|
| + }
|
| +
|
| + @override
|
| + TypeParameterElement get baseElement =>
|
| + super.baseElement as TypeParameterElement;
|
| +
|
| + @override
|
| + Element get enclosingElement => baseElement.enclosingElement;
|
| +
|
| + @override
|
| + int get hashCode => baseElement.hashCode;
|
| +
|
| + @override
|
| + TypeParameterType get type => _type;
|
| +
|
| + @override
|
| + bool operator ==(obj) =>
|
| + // TODO(jmesserly): this equality should consider the bound, see:
|
| + // https://github.com/dart-lang/sdk/issues/27210
|
| + obj is TypeParameterMember && obj.baseElement == baseElement;
|
| +
|
| + @override
|
| + accept(ElementVisitor visitor) => visitor.visitTypeParameterElement(this);
|
| +
|
| + /**
|
| + * If the given [parameter]'s type is different when any type parameters from
|
| + * the defining type's declaration are replaced with the actual type
|
| + * arguments from the [definingType], create a parameter member representing
|
| + * the given parameter. Return the member that was created, or the base
|
| + * parameter if no member was created.
|
| + */
|
| + static TypeParameterElement from(
|
| + TypeParameterElement parameter, ParameterizedType definingType) {
|
| + if (parameter?.bound == null || definingType.typeArguments.isEmpty) {
|
| + return parameter;
|
| + }
|
| +
|
| + DartType bound = parameter.bound;
|
| + List<DartType> argumentTypes = definingType.typeArguments;
|
| + List<DartType> parameterTypes =
|
| + TypeParameterTypeImpl.getTypes(definingType.typeParameters);
|
| + DartType substitutedBound =
|
| + bound.substitute2(argumentTypes, parameterTypes);
|
| + return new TypeParameterMember(parameter, definingType, substitutedBound);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * A variable element defined in a parameterized type where the values of the
|
| + * type parameters are known.
|
| + */
|
| +abstract class VariableMember extends Member implements VariableElement {
|
| + @override
|
| + final DartType type;
|
| +
|
| + /**
|
| + * Initialize a newly created element to represent a variable, based on the
|
| + * [baseElement], defined by the [definingType].
|
| + */
|
| + VariableMember(VariableElement baseElement, ParameterizedType definingType,
|
| + [DartType type])
|
| + : type = type ??
|
| + baseElement.type.substitute2(definingType.typeArguments,
|
| + TypeParameterTypeImpl.getTypes(definingType.typeParameters)),
|
| + super(baseElement, definingType);
|
| +
|
| + // TODO(jmesserly): this is temporary to allow the ParameterMember subclass.
|
| + // Apparently mixins don't work with optional params.
|
| + VariableMember._(VariableElement baseElement, ParameterizedType definingType,
|
| + DartType type)
|
| + : this(baseElement, definingType, type);
|
| +
|
| + @override
|
| + VariableElement get baseElement => super.baseElement as VariableElement;
|
| +
|
| + @override
|
| + DartObject get constantValue => baseElement.constantValue;
|
| +
|
| + @override
|
| + bool get hasImplicitType => baseElement.hasImplicitType;
|
| +
|
| + @override
|
| + FunctionElement get initializer {
|
| + //
|
| + // Elements within this element should have type parameters substituted,
|
| + // just like this element.
|
| + //
|
| + throw new UnsupportedError('initializer');
|
| + // return getBaseElement().getInitializer();
|
| + }
|
| +
|
| + @override
|
| + bool get isConst => baseElement.isConst;
|
| +
|
| + @override
|
| + bool get isFinal => baseElement.isFinal;
|
| +
|
| + @override
|
| + @deprecated
|
| + bool get isPotentiallyMutatedInClosure =>
|
| + baseElement.isPotentiallyMutatedInClosure;
|
| +
|
| + @override
|
| + @deprecated
|
| + bool get isPotentiallyMutatedInScope =>
|
| + baseElement.isPotentiallyMutatedInScope;
|
| +
|
| + @override
|
| + bool get isStatic => baseElement.isStatic;
|
| +
|
| + @override
|
| + DartObject computeConstantValue() => baseElement.computeConstantValue();
|
| +
|
| + @override
|
| + void visitChildren(ElementVisitor visitor) {
|
| + // TODO(brianwilkerson) We need to finish implementing the accessors used
|
| + // below so that we can safely invoke them.
|
| + super.visitChildren(visitor);
|
| + baseElement.initializer?.accept(visitor);
|
| + }
|
| +}
|
|
|