| Index: packages/analyzer/lib/src/task/strong/info.dart
|
| diff --git a/packages/analyzer/lib/src/task/strong/info.dart b/packages/analyzer/lib/src/task/strong/info.dart
|
| deleted file mode 100644
|
| index a18f76fe36f45b3b82d84d70e6ed8d7196461b05..0000000000000000000000000000000000000000
|
| --- a/packages/analyzer/lib/src/task/strong/info.dart
|
| +++ /dev/null
|
| @@ -1,472 +0,0 @@
|
| -// Copyright (c) 2015, 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.
|
| -
|
| -/// Defines static information collected by the type checker and used later by
|
| -/// emitters to generate code.
|
| -// TODO(jmesserly): this was ported from package:dev_compiler, and needs to be
|
| -// refactored to fit into analyzer.
|
| -library analyzer.src.task.strong.info;
|
| -
|
| -import 'package:analyzer/src/generated/ast.dart';
|
| -import 'package:analyzer/src/generated/element.dart';
|
| -import 'package:analyzer/src/generated/error.dart';
|
| -
|
| -import 'rules.dart';
|
| -
|
| -// The abstract type of coercions mapping one type to another.
|
| -// This class also exposes static builder functions which
|
| -// check for errors and reduce redundant coercions to the identity.
|
| -abstract class Coercion {
|
| - final DartType fromType;
|
| - final DartType toType;
|
| - Coercion(this.fromType, this.toType);
|
| - static Coercion cast(DartType fromT, DartType toT) => new Cast(fromT, toT);
|
| - static Coercion identity(DartType type) => new Identity(type);
|
| - static Coercion error() => new CoercionError();
|
| -}
|
| -
|
| -// Coercion which casts one type to another
|
| -class Cast extends Coercion {
|
| - Cast(DartType fromType, DartType toType) : super(fromType, toType);
|
| -}
|
| -
|
| -// The identity coercion
|
| -class Identity extends Coercion {
|
| - Identity(DartType fromType) : super(fromType, fromType);
|
| -}
|
| -
|
| -// The error coercion. This coercion signals that a coercion
|
| -// could not be generated. The code generator should not see
|
| -// these.
|
| -class CoercionError extends Coercion {
|
| - CoercionError() : super(null, null);
|
| -}
|
| -
|
| -// TODO(jmesserly): this could use some refactoring. These are essentially
|
| -// like ErrorCodes in analyzer, but we're including some details in our message.
|
| -// Analyzer instead has template strings, and replaces '{0}' with the first
|
| -// argument.
|
| -abstract class StaticInfo {
|
| - /// AST Node this info is attached to.
|
| - AstNode get node;
|
| -
|
| - // TODO(jmesserly): review the usage of error codes. We probably want our own,
|
| - // as well as some DDC specific [ErrorType]s.
|
| - ErrorCode toErrorCode();
|
| -
|
| - // TODO(jmesserly): what convention to use here?
|
| - String get name => 'dev_compiler.$runtimeType';
|
| -
|
| - List<Object> get arguments => [node];
|
| -
|
| - AnalysisError toAnalysisError() {
|
| - int begin = node is AnnotatedNode
|
| - ? (node as AnnotatedNode).firstTokenAfterCommentAndMetadata.offset
|
| - : node.offset;
|
| - int length = node.end - begin;
|
| - var source = (node.root as CompilationUnit).element.source;
|
| - return new AnalysisError(source, begin, length, toErrorCode(), arguments);
|
| - }
|
| -}
|
| -
|
| -/// Implicitly injected expression conversion.
|
| -abstract class CoercionInfo extends StaticInfo {
|
| - final TypeRules rules;
|
| -
|
| - final Expression node;
|
| -
|
| - DartType get convertedType;
|
| -
|
| - CoercionInfo(this.rules, this.node);
|
| -
|
| - DartType get baseType => rules.getStaticType(node);
|
| - DartType get staticType => convertedType;
|
| -
|
| - String get message;
|
| - toErrorCode() => new HintCode(name, message);
|
| -
|
| - static const String _propertyName = 'dev_compiler.src.info.CoercionInfo';
|
| -
|
| - /// Gets the coercion info associated with this node.
|
| - static CoercionInfo get(AstNode node) => node.getProperty(_propertyName);
|
| -
|
| - /// Sets the coercion info associated with this node.
|
| - static CoercionInfo set(AstNode node, CoercionInfo info) {
|
| - node.setProperty(_propertyName, info);
|
| - return info;
|
| - }
|
| -}
|
| -
|
| -// Base class for all casts from base type to sub type.
|
| -abstract class DownCast extends CoercionInfo {
|
| - Cast _cast;
|
| -
|
| - DownCast._internal(TypeRules rules, Expression expression, this._cast)
|
| - : super(rules, expression) {
|
| - assert(_cast.toType != baseType &&
|
| - _cast.fromType == baseType &&
|
| - (baseType.isDynamic ||
|
| - // Call methods make the following non-redundant
|
| - _cast.toType.isSubtypeOf(baseType) ||
|
| - baseType.isAssignableTo(_cast.toType)));
|
| - }
|
| -
|
| - Cast get cast => _cast;
|
| -
|
| - DartType get convertedType => _cast.toType;
|
| -
|
| - @override List<Object> get arguments => [node, baseType, convertedType];
|
| - @override String get message => '{0} ({1}) will need runtime check '
|
| - 'to cast to type {2}';
|
| -
|
| - // Factory to create correct DownCast variant.
|
| - static StaticInfo create(TypeRules rules, Expression expression, Cast cast,
|
| - {String reason}) {
|
| - final fromT = cast.fromType;
|
| - final toT = cast.toType;
|
| -
|
| - // toT <:_R fromT => to <: fromT
|
| - // NB: classes with call methods are subtypes of function
|
| - // types, but the function type is not assignable to the class
|
| - assert(toT.isSubtypeOf(fromT) || fromT.isAssignableTo(toT));
|
| -
|
| - // Handle null call specially.
|
| - if (expression is NullLiteral) {
|
| - // TODO(vsm): Create a NullCast for this once we revisit nonnullability.
|
| - return new DownCastImplicit(rules, expression, cast);
|
| - }
|
| -
|
| - // Inference "casts":
|
| - if (expression is Literal) {
|
| - // fromT should be an exact type - this will almost certainly fail at
|
| - // runtime.
|
| - return new StaticTypeError(rules, expression, toT, reason: reason);
|
| - }
|
| - if (expression is FunctionExpression) {
|
| - // fromT should be an exact type - this will almost certainly fail at
|
| - // runtime.
|
| - return new UninferredClosure(rules, expression, cast);
|
| - }
|
| - if (expression is InstanceCreationExpression) {
|
| - // fromT should be an exact type - this will almost certainly fail at
|
| - // runtime.
|
| - return new StaticTypeError(rules, expression, toT, reason: reason);
|
| - }
|
| -
|
| - // Composite cast: these are more likely to fail.
|
| - if (!rules.isGroundType(toT)) {
|
| - // This cast is (probably) due to our different treatment of dynamic.
|
| - // It may be more likely to fail at runtime.
|
| - return new DownCastComposite(rules, expression, cast);
|
| - }
|
| -
|
| - // Dynamic cast
|
| - if (fromT.isDynamic) {
|
| - return new DynamicCast(rules, expression, cast);
|
| - }
|
| -
|
| - // Assignment cast
|
| - var parent = expression.parent;
|
| - if (parent is VariableDeclaration && (parent.initializer == expression)) {
|
| - return new AssignmentCast(rules, expression, cast);
|
| - }
|
| -
|
| - // Other casts
|
| - return new DownCastImplicit(rules, expression, cast);
|
| - }
|
| -}
|
| -
|
| -//
|
| -// Standard down casts. These casts are implicitly injected by the compiler.
|
| -//
|
| -
|
| -// A down cast from dynamic to T.
|
| -class DynamicCast extends DownCast {
|
| - DynamicCast(TypeRules rules, Expression expression, Cast cast)
|
| - : super._internal(rules, expression, cast);
|
| -
|
| - toErrorCode() => new HintCode(name, message);
|
| -}
|
| -
|
| -// A down cast due to a variable declaration to a ground type. E.g.,
|
| -// T x = expr;
|
| -// where T is ground. We exclude non-ground types as these behave differently
|
| -// compared to standard Dart.
|
| -class AssignmentCast extends DownCast {
|
| - AssignmentCast(TypeRules rules, Expression expression, Cast cast)
|
| - : super._internal(rules, expression, cast);
|
| -
|
| - toErrorCode() => new HintCode(name, message);
|
| -}
|
| -
|
| -//
|
| -// Temporary "casts" of allocation sites - literals, constructor invocations,
|
| -// and closures. These should be handled by contextual inference. In most
|
| -// cases, inference will be sufficient, though in some it may unmask an actual
|
| -// error: e.g.,
|
| -// List<int> l = [1, 2, 3]; // Inference succeeds
|
| -// List<String> l = [1, 2, 3]; // Inference reveals static type error
|
| -// We're marking all as warnings for now.
|
| -//
|
| -// TODO(vsm,leafp): Remove this.
|
| -class UninferredClosure extends DownCast {
|
| - UninferredClosure(TypeRules rules, FunctionExpression expression, Cast cast)
|
| - : super._internal(rules, expression, cast);
|
| -
|
| - toErrorCode() => new StaticTypeWarningCode(name, message);
|
| -}
|
| -
|
| -//
|
| -// Implicit down casts. These are only injected by the compiler by flag.
|
| -//
|
| -
|
| -// A down cast to a non-ground type. These behave differently from standard
|
| -// Dart and may be more likely to fail at runtime.
|
| -class DownCastComposite extends DownCast {
|
| - DownCastComposite(TypeRules rules, Expression expression, Cast cast)
|
| - : super._internal(rules, expression, cast);
|
| -
|
| - toErrorCode() => new StaticTypeWarningCode(name, message);
|
| -}
|
| -
|
| -// A down cast to a non-ground type. These behave differently from standard
|
| -// Dart and may be more likely to fail at runtime.
|
| -class DownCastImplicit extends DownCast {
|
| - DownCastImplicit(TypeRules rules, Expression expression, Cast cast)
|
| - : super._internal(rules, expression, cast);
|
| -
|
| - toErrorCode() => new HintCode(name, message);
|
| -}
|
| -
|
| -// An inferred type for the wrapped expression, which may need to be
|
| -// reified into the term
|
| -abstract class InferredTypeBase extends CoercionInfo {
|
| - final DartType _type;
|
| -
|
| - InferredTypeBase._internal(TypeRules rules, Expression expression, this._type)
|
| - : super(rules, expression);
|
| -
|
| - DartType get type => _type;
|
| - DartType get convertedType => type;
|
| - @override String get message => '{0} has inferred type {1}';
|
| - @override List get arguments => [node, type];
|
| -
|
| - toErrorCode() => new HintCode(name, message);
|
| -}
|
| -
|
| -// Standard / unspecialized inferred type
|
| -class InferredType extends InferredTypeBase {
|
| - InferredType(TypeRules rules, Expression expression, DartType type)
|
| - : super._internal(rules, expression, type);
|
| -
|
| - // Factory to create correct InferredType variant.
|
| - static InferredTypeBase create(
|
| - TypeRules rules, Expression expression, DartType type) {
|
| - // Specialized inference:
|
| - if (expression is Literal) {
|
| - return new InferredTypeLiteral(rules, expression, type);
|
| - }
|
| - if (expression is InstanceCreationExpression) {
|
| - return new InferredTypeAllocation(rules, expression, type);
|
| - }
|
| - if (expression is FunctionExpression) {
|
| - return new InferredTypeClosure(rules, expression, type);
|
| - }
|
| - return new InferredType(rules, expression, type);
|
| - }
|
| -}
|
| -
|
| -// An infered type for a literal expression.
|
| -class InferredTypeLiteral extends InferredTypeBase {
|
| - InferredTypeLiteral(TypeRules rules, Expression expression, DartType type)
|
| - : super._internal(rules, expression, type);
|
| -}
|
| -
|
| -// An inferred type for a non-literal allocation site.
|
| -class InferredTypeAllocation extends InferredTypeBase {
|
| - InferredTypeAllocation(TypeRules rules, Expression expression, DartType type)
|
| - : super._internal(rules, expression, type);
|
| -}
|
| -
|
| -// An inferred type for a closure expression
|
| -class InferredTypeClosure extends InferredTypeBase {
|
| - InferredTypeClosure(TypeRules rules, Expression expression, DartType type)
|
| - : super._internal(rules, expression, type);
|
| -}
|
| -
|
| -class DynamicInvoke extends CoercionInfo {
|
| - DynamicInvoke(TypeRules rules, Expression expression)
|
| - : super(rules, expression);
|
| -
|
| - DartType get convertedType => rules.provider.dynamicType;
|
| - String get message => '{0} requires dynamic invoke';
|
| - toErrorCode() => new HintCode(name, message);
|
| -
|
| - static const String _propertyName = 'dev_compiler.src.info.DynamicInvoke';
|
| -
|
| - /// Whether this [node] is the target of a dynamic operation.
|
| - static bool get(AstNode node) {
|
| - var value = node.getProperty(_propertyName);
|
| - return value != null ? value : false;
|
| - }
|
| -
|
| - /// Sets whether this node is the target of a dynamic operation.
|
| - static bool set(AstNode node, bool value) {
|
| - // Free the storage for things that aren't dynamic.
|
| - if (value == false) value = null;
|
| - node.setProperty(_propertyName, value);
|
| - return value;
|
| - }
|
| -}
|
| -
|
| -abstract class StaticError extends StaticInfo {
|
| - final AstNode node;
|
| -
|
| - StaticError(this.node);
|
| -
|
| - String get message;
|
| -
|
| - toErrorCode() => new CompileTimeErrorCode(name, message);
|
| -}
|
| -
|
| -class StaticTypeError extends StaticError {
|
| - final DartType baseType;
|
| - final DartType expectedType;
|
| - String reason = null;
|
| -
|
| - StaticTypeError(TypeRules rules, Expression expression, this.expectedType,
|
| - {this.reason})
|
| - : baseType = rules.getStaticType(expression),
|
| - super(expression);
|
| -
|
| - @override List<Object> get arguments => [node, baseType, expectedType];
|
| - @override String get message =>
|
| - 'Type check failed: {0} ({1}) is not of type {2}' +
|
| - ((reason == null) ? '' : ' because $reason');
|
| -}
|
| -
|
| -class InvalidVariableDeclaration extends StaticError {
|
| - final DartType expectedType;
|
| -
|
| - InvalidVariableDeclaration(
|
| - TypeRules rules, AstNode declaration, this.expectedType)
|
| - : super(declaration);
|
| -
|
| - @override List<Object> get arguments => [expectedType];
|
| - @override String get message => 'Type check failed: null is not of type {0}';
|
| -}
|
| -
|
| -class InvalidParameterDeclaration extends StaticError {
|
| - final DartType expectedType;
|
| -
|
| - InvalidParameterDeclaration(
|
| - TypeRules rules, FormalParameter declaration, this.expectedType)
|
| - : super(declaration);
|
| -
|
| - @override List<Object> get arguments => [node, expectedType];
|
| - @override String get message => 'Type check failed: {0} is not of type {1}';
|
| -}
|
| -
|
| -class NonGroundTypeCheckInfo extends StaticInfo {
|
| - final DartType type;
|
| - final AstNode node;
|
| -
|
| - NonGroundTypeCheckInfo(this.node, this.type) {
|
| - assert(node is IsExpression || node is AsExpression);
|
| - }
|
| -
|
| - @override List<Object> get arguments => [type];
|
| - String get message =>
|
| - "Runtime check on non-ground type {0} may throw StrongModeError";
|
| -
|
| - toErrorCode() => new HintCode(name, message);
|
| -}
|
| -
|
| -// Invalid override of an instance member of a class.
|
| -abstract class InvalidOverride extends StaticError {
|
| - /// Member declaration with the invalid override.
|
| - final ExecutableElement element;
|
| -
|
| - /// Type (class or interface) that provides the base declaration.
|
| - final InterfaceType base;
|
| -
|
| - /// Actual type of the overridden member.
|
| - final DartType subType;
|
| -
|
| - /// Actual type of the base member.
|
| - final DartType baseType;
|
| -
|
| - /// Whether the error comes from combining a base class and an interface
|
| - final bool fromBaseClass;
|
| -
|
| - /// Whether the error comes from a mixin (either overriding a base class or an
|
| - /// interface declaration).
|
| - final bool fromMixin;
|
| -
|
| - InvalidOverride(
|
| - AstNode node, this.element, this.base, this.subType, this.baseType)
|
| - : fromBaseClass = node is ExtendsClause,
|
| - fromMixin = node.parent is WithClause,
|
| - super(node);
|
| -
|
| - ClassElement get parent => element.enclosingElement;
|
| -
|
| - @override List<Object> get arguments =>
|
| - [parent.name, element.name, subType, base, baseType];
|
| -
|
| - String _messageHelper(String errorName) {
|
| - var lcErrorName = errorName.toLowerCase();
|
| - var intro = fromBaseClass
|
| - ? 'Base class introduces an $lcErrorName'
|
| - : (fromMixin ? 'Mixin introduces an $lcErrorName' : errorName);
|
| - return '$intro. The type of {0}.{1} ({2}) is not a '
|
| - 'subtype of {3}.{1} ({4}).';
|
| - }
|
| -}
|
| -
|
| -// Invalid override due to incompatible type. I.e., the overridden signature
|
| -// is not compatible with the original.
|
| -class InvalidMethodOverride extends InvalidOverride {
|
| - InvalidMethodOverride(AstNode node, ExecutableElement element,
|
| - InterfaceType base, FunctionType subType, FunctionType baseType)
|
| - : super(node, element, base, subType, baseType);
|
| -
|
| - String get message => _messageHelper('Invalid override');
|
| -}
|
| -
|
| -/// Dart constructors have one weird quirk, illustrated with this example:
|
| -///
|
| -/// class Base {
|
| -/// var x;
|
| -/// Base() : x = print('Base.1') {
|
| -/// print('Base.2');
|
| -/// }
|
| -/// }
|
| -///
|
| -/// class Derived extends Base {
|
| -/// var y, z;
|
| -/// Derived()
|
| -/// : y = print('Derived.1'),
|
| -/// super(),
|
| -/// z = print('Derived.2') {
|
| -/// print('Derived.3');
|
| -/// }
|
| -/// }
|
| -///
|
| -/// The order will be Derived.1, Base.1, Derived.2, Base.2, Derived.3; this
|
| -/// ordering preserves the invariant that code can't observe uninitialized
|
| -/// state, however it results in super constructor body not being run
|
| -/// immediately after super initializers. Normally this isn't observable, but it
|
| -/// could be if initializers have side effects.
|
| -///
|
| -/// Better to have `super` at the end, as required by the Dart style guide:
|
| -/// <http://goo.gl/q1T4BB>
|
| -///
|
| -/// For now this is the only pattern we support.
|
| -class InvalidSuperInvocation extends StaticError {
|
| - InvalidSuperInvocation(SuperConstructorInvocation node) : super(node);
|
| -
|
| - @override String get message => "super call must be last in an initializer "
|
| - "list (see http://goo.gl/q1T4BB): {0}";
|
| -}
|
|
|