Index: lib/src/info.dart |
diff --git a/lib/src/info.dart b/lib/src/info.dart |
index c48fb361141ed613cf52708daabc374962ad5b42..75e74a338724c7faf0076dd8b35040b94f087529 100644 |
--- a/lib/src/info.dart |
+++ b/lib/src/info.dart |
@@ -8,20 +8,19 @@ library dev_compiler.src.info; |
import 'package:analyzer/src/generated/ast.dart'; |
import 'package:analyzer/src/generated/element.dart'; |
-import 'package:analyzer/src/generated/error.dart'; |
import 'package:analyzer/src/generated/parser.dart'; |
-import 'checker/rules.dart'; |
import 'utils.dart' as utils; |
+import 'package:analyzer/src/task/strong/info.dart'; |
+export 'package:analyzer/src/task/strong/info.dart'; |
/// Represents a summary of the results collected by running the program |
/// checker. |
class CheckerResults { |
final List<LibraryInfo> libraries; |
- final TypeRules rules; |
final bool failure; |
- CheckerResults(this.libraries, this.rules, this.failure); |
+ CheckerResults(this.libraries, this.failure); |
} |
/// Computed information about each library. |
@@ -102,474 +101,3 @@ class _AstCloner extends AstCloner { |
return clone; |
} |
} |
- |
-// 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'); |
-} |
- |
-/// Used to mark unexpected situations in our compiler were we couldn't compute |
-/// the type of an expression. |
-// TODO(sigmund): This is normally a result of another error that is caught by |
-// the analyzer, so this should likely be removed in the future. |
-class MissingTypeError extends StaticInfo { |
- final AstNode node; |
- toErrorCode() => new StaticTypeWarningCode(name, message); |
- |
- MissingTypeError(this.node); |
- |
- @override List<Object> get arguments => [node, node.runtimeType]; |
- String get message => "type analysis didn't compute the type of: {0} {1}"; |
-} |
- |
-/// 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}"; |
-} |