| Index: pkg/analyzer/lib/src/task/strong/info.dart
|
| diff --git a/pkg/analyzer/lib/src/task/strong/info.dart b/pkg/analyzer/lib/src/task/strong/info.dart
|
| deleted file mode 100644
|
| index 5b147e745c7401e30a9db0f1268a0064d4874b49..0000000000000000000000000000000000000000
|
| --- a/pkg/analyzer/lib/src/task/strong/info.dart
|
| +++ /dev/null
|
| @@ -1,468 +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/dart/ast/ast.dart';
|
| -import 'package:analyzer/dart/element/element.dart';
|
| -import 'package:analyzer/dart/element/type.dart';
|
| -import 'package:analyzer/src/dart/element/type.dart';
|
| -import 'package:analyzer/src/generated/error.dart';
|
| -import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
|
| -import 'package:analyzer/src/generated/type_system.dart';
|
| -
|
| -/// Implicitly injected expression conversion.
|
| -abstract class CoercionInfo extends StaticInfo {
|
| - static const String _propertyName = 'dev_compiler.src.info.CoercionInfo';
|
| -
|
| - final Expression node;
|
| -
|
| - CoercionInfo(this.node);
|
| -
|
| - DartType get baseType => node.staticType ?? DynamicTypeImpl.instance;
|
| - DartType get convertedType;
|
| -
|
| - String get message;
|
| - DartType get staticType => convertedType;
|
| -
|
| - toErrorCode() => new HintCode(name, message);
|
| -
|
| - /// 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;
|
| - }
|
| -}
|
| -
|
| -/// Implicit casts from base type to sub type.
|
| -class DownCast extends CoercionInfo {
|
| - final DartType _fromType;
|
| - final DartType _toType;
|
| - ErrorCode _errorCode;
|
| -
|
| - DownCast._(
|
| - Expression expression, this._fromType, this._toType, this._errorCode)
|
| - : super(expression);
|
| -
|
| - @override
|
| - List<Object> get arguments => [baseType, convertedType];
|
| -
|
| - /// The type being cast from.
|
| - ///
|
| - /// This is usually the static type of the associated expression, but may not
|
| - /// be if the cast is attached to a variable in a for-in loop.
|
| - @override
|
| - DartType get baseType => _fromType;
|
| -
|
| - @override
|
| - DartType get convertedType => _toType;
|
| -
|
| - @override
|
| - String get message => _message;
|
| -
|
| - @override
|
| - String get name => _errorCode.name;
|
| -
|
| - @override
|
| - toErrorCode() => _errorCode;
|
| -
|
| - static const String _message = 'Unsound implicit cast from {0} to {1}';
|
| -
|
| - /// Factory to create correct DownCast variant.
|
| - static StaticInfo create(StrongTypeSystemImpl rules, Expression expression,
|
| - DartType fromType, DartType toType, AnalysisOptionsImpl options) {
|
| - // 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(toType.isSubtypeOf(fromType) || fromType.isAssignableTo(toType));
|
| -
|
| - // Inference "casts":
|
| - if (expression is Literal || expression is FunctionExpression) {
|
| - // fromT should be an exact type - this will almost certainly fail at
|
| - // runtime.
|
| - return new StaticTypeError(expression, toType);
|
| - }
|
| -
|
| - if (expression is InstanceCreationExpression) {
|
| - ConstructorElement e = expression.staticElement;
|
| - if (e == null || !e.isFactory) {
|
| - // fromT should be an exact type - this will almost certainly fail at
|
| - // runtime.
|
| - return new StaticTypeError(expression, toType);
|
| - }
|
| - }
|
| -
|
| - if (StaticInfo.isKnownFunction(expression)) {
|
| - return new StaticTypeError(expression, toType);
|
| - }
|
| -
|
| - // TODO(vsm): Change this to an assert when we have generic methods and
|
| - // fix TypeRules._coerceTo to disallow implicit sideways casts.
|
| - bool downCastComposite = false;
|
| - if (!rules.isSubtypeOf(toType, fromType)) {
|
| - assert(toType.isSubtypeOf(fromType) || fromType.isAssignableTo(toType));
|
| - downCastComposite = true;
|
| - }
|
| -
|
| - // Composite cast: these are more likely to fail.
|
| - if (!rules.isGroundType(toType)) {
|
| - // This cast is (probably) due to our different treatment of dynamic.
|
| - // It may be more likely to fail at runtime.
|
| - if (fromType is InterfaceType) {
|
| - // For class types, we'd like to allow non-generic down casts, e.g.,
|
| - // Iterable<T> to List<T>. The intuition here is that raw (generic)
|
| - // casts are problematic, and we should complain about those.
|
| - var typeArgs = fromType.typeArguments;
|
| - downCastComposite =
|
| - typeArgs.isEmpty || typeArgs.any((t) => t.isDynamic);
|
| - } else {
|
| - downCastComposite = true;
|
| - }
|
| - }
|
| -
|
| - var parent = expression.parent;
|
| - String name;
|
| - if (downCastComposite) {
|
| - name = 'STRONG_MODE_DOWN_CAST_COMPOSITE';
|
| - } else if (fromType.isDynamic) {
|
| - name = 'STRONG_MODE_DYNAMIC_CAST';
|
| - } else if (parent is VariableDeclaration &&
|
| - parent.initializer == expression) {
|
| - name = 'STRONG_MODE_ASSIGNMENT_CAST';
|
| - } else {
|
| - name = 'STRONG_MODE_DOWN_CAST_IMPLICIT';
|
| - }
|
| -
|
| - // For the remaining cases, we allow implicit casts by default.
|
| - // However this can be disabled with an option.
|
| - ErrorCode errorCode;
|
| - if (!options.implicitCasts) {
|
| - errorCode = new CompileTimeErrorCode(name, _message);
|
| - } else if (downCastComposite) {
|
| - errorCode = new StaticWarningCode(name, _message);
|
| - } else {
|
| - errorCode = new HintCode(name, _message);
|
| - }
|
| - return new DownCast._(expression, fromType, toType, errorCode);
|
| - }
|
| -}
|
| -
|
| -class DynamicInvoke extends CoercionInfo {
|
| - static const String _propertyName = 'dev_compiler.src.info.DynamicInvoke';
|
| -
|
| - DynamicInvoke(Expression expression) : super(expression);
|
| - DartType get convertedType => DynamicTypeImpl.instance;
|
| - String get message => '{0} requires dynamic invoke';
|
| -
|
| - @override
|
| - String get name => 'STRONG_MODE_DYNAMIC_INVOKE';
|
| -
|
| - toErrorCode() => new HintCode(name, message);
|
| -
|
| - /// Whether this [node] is the target of a dynamic operation.
|
| - static bool get(AstNode node) => node.getProperty(_propertyName) ?? 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;
|
| - }
|
| -}
|
| -
|
| -/// A marker for an inferred type.
|
| -class InferredType extends CoercionInfo {
|
| - @override
|
| - final String name;
|
| -
|
| - final DartType type;
|
| -
|
| - InferredType(Expression expression, this.type, this.name) : super(expression);
|
| -
|
| - /// Factory to create correct InferredType variant.
|
| - static InferredType create(
|
| - TypeSystem rules, Expression expression, DartType type) {
|
| - // Specialized inference:
|
| - String name;
|
| - if (expression is Literal) {
|
| - name = 'STRONG_MODE_INFERRED_TYPE_LITERAL';
|
| - } else if (expression is InstanceCreationExpression) {
|
| - name = 'STRONG_MODE_INFERRED_TYPE_ALLOCATION';
|
| - } else if (expression is FunctionExpression) {
|
| - name = 'STRONG_MODE_INFERRED_TYPE_CLOSURE';
|
| - } else {
|
| - name = 'STRONG_MODE_INFERRED_TYPE';
|
| - }
|
| - return new InferredType(expression, type, name);
|
| - }
|
| -
|
| - @override
|
| - List get arguments => [node, type];
|
| -
|
| - DartType get convertedType => type;
|
| -
|
| - @override
|
| - String get message => '{0} has inferred type {1}';
|
| -
|
| - toErrorCode() => new HintCode(name, message);
|
| -}
|
| -
|
| -class InvalidFieldOverride extends InvalidOverride {
|
| - InvalidFieldOverride(AstNode node, ExecutableElement element,
|
| - InterfaceType base, DartType subType, DartType baseType)
|
| - : super(node, element, base, subType, baseType);
|
| -
|
| - String get message => 'Field declaration {3}.{1} cannot be '
|
| - 'overridden in {0}.';
|
| -
|
| - @override
|
| - String get name => 'STRONG_MODE_INVALID_FIELD_OVERRIDE';
|
| -}
|
| -
|
| -/// 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');
|
| -
|
| - @override
|
| - String get name => 'STRONG_MODE_INVALID_METHOD_OVERRIDE';
|
| -}
|
| -
|
| -/// 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);
|
| -
|
| - @override
|
| - List<Object> get arguments =>
|
| - [parent.name, element.name, subType, base, baseType];
|
| -
|
| - ClassElement get parent => element.enclosingElement;
|
| -
|
| - 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}).';
|
| - }
|
| -}
|
| -
|
| -class InvalidParameterDeclaration extends StaticError {
|
| - final DartType expectedType;
|
| -
|
| - InvalidParameterDeclaration(
|
| - TypeSystem 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}';
|
| - @override
|
| - String get name => 'STRONG_MODE_INVALID_PARAMETER_DECLARATION';
|
| -}
|
| -
|
| -/// 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:
|
| -/// <https://goo.gl/EY6hDP>
|
| -///
|
| -/// 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 https://goo.gl/EY6hDP): {0}";
|
| -
|
| - @override
|
| - String get name => 'STRONG_MODE_INVALID_SUPER_INVOCATION';
|
| -}
|
| -
|
| -class InvalidVariableDeclaration extends StaticError {
|
| - final DartType expectedType;
|
| -
|
| - InvalidVariableDeclaration(
|
| - TypeSystem 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}';
|
| -
|
| - @override
|
| - String get name => 'STRONG_MODE_INVALID_VARIABLE_DECLARATION';
|
| -}
|
| -
|
| -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";
|
| -
|
| - @override
|
| - String get name => 'STRONG_MODE_NON_GROUND_TYPE_CHECK_INFO';
|
| -
|
| - toErrorCode() => new HintCode(name, message);
|
| -}
|
| -
|
| -abstract class StaticError extends StaticInfo {
|
| - final AstNode node;
|
| -
|
| - StaticError(this.node);
|
| -
|
| - String get message;
|
| -
|
| - toErrorCode() => new CompileTimeErrorCode(name, message);
|
| -}
|
| -
|
| -// 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 {
|
| - /// Strong-mode error code names.
|
| - ///
|
| - /// Used for error code configuration validation in an analysis options file.
|
| - static const List<String> names = const [
|
| - //
|
| - // Manually populated.
|
| - //
|
| - 'STRONG_MODE_ASSIGNMENT_CAST',
|
| - 'STRONG_MODE_DOWN_CAST_COMPOSITE',
|
| - 'STRONG_MODE_DOWN_CAST_IMPLICIT',
|
| - 'STRONG_MODE_DYNAMIC_CAST',
|
| - 'STRONG_MODE_DYNAMIC_INVOKE',
|
| - 'STRONG_MODE_INFERRED_TYPE',
|
| - 'STRONG_MODE_INFERRED_TYPE_ALLOCATION',
|
| - 'STRONG_MODE_INFERRED_TYPE_CLOSURE',
|
| - 'STRONG_MODE_INFERRED_TYPE_LITERAL',
|
| - 'STRONG_MODE_INVALID_FIELD_OVERRIDE',
|
| - 'STRONG_MODE_INVALID_METHOD_OVERRIDE',
|
| - 'STRONG_MODE_INVALID_PARAMETER_DECLARATION',
|
| - 'STRONG_MODE_INVALID_SUPER_INVOCATION',
|
| - 'STRONG_MODE_INVALID_VARIABLE_DECLARATION',
|
| - 'STRONG_MODE_NON_GROUND_TYPE_CHECK_INFO',
|
| - 'STRONG_MODE_STATIC_TYPE_ERROR',
|
| - ];
|
| -
|
| - List<Object> get arguments => [node];
|
| -
|
| - String get name;
|
| -
|
| - /// AST Node this info is attached to.
|
| - AstNode get 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);
|
| - }
|
| -
|
| - // TODO(jmesserly): review the usage of error codes. We probably want our own,
|
| - // as well as some DDC specific [ErrorType]s.
|
| - ErrorCode toErrorCode();
|
| -
|
| - static bool isKnownFunction(Expression expression) {
|
| - Element element = null;
|
| - if (expression is FunctionExpression) {
|
| - return true;
|
| - } else if (expression is PropertyAccess) {
|
| - element = expression.propertyName.staticElement;
|
| - } else if (expression is Identifier) {
|
| - element = expression.staticElement;
|
| - }
|
| - // First class functions and static methods, where we know the original
|
| - // declaration, will have an exact type, so we know a downcast will fail.
|
| - return element is FunctionElement ||
|
| - element is MethodElement && element.isStatic;
|
| - }
|
| -}
|
| -
|
| -class StaticTypeError extends StaticError {
|
| - final DartType baseType;
|
| - final DartType expectedType;
|
| -
|
| - StaticTypeError(Expression expression, this.expectedType)
|
| - : baseType = expression.staticType ?? DynamicTypeImpl.instance,
|
| - super(expression);
|
| -
|
| - @override
|
| - List<Object> get arguments => [node, baseType, expectedType];
|
| - @override
|
| - String get message => 'Type check failed: {0} ({1}) is not of type {2}';
|
| -
|
| - @override
|
| - String get name => 'STRONG_MODE_STATIC_TYPE_ERROR';
|
| -}
|
|
|