Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1079)

Unified Diff: pkg/analyzer/lib/src/task/strong/info.dart

Issue 2060013002: Refactor strong mode to use standard Analyzer errors (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fix hasImplicitCasts on the CompilationUnit Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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';
-}

Powered by Google App Engine
This is Rietveld 408576698