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

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

Issue 2199323002: Initial implementation for lazy compound assignment operators (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 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/checker.dart
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 98c4aa6a97dc640c90891e60bdefcfb186c215ad..21281719674209128269d53a0165ed8d8cab6fd2 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -9,6 +9,7 @@ library analyzer.src.task.strong.checker;
import 'package:analyzer/analyzer.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart' show TokenType;
+import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
@@ -20,6 +21,21 @@ import 'package:analyzer/src/generated/type_system.dart';
import 'ast_properties.dart';
+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;
+}
+
DartType _elementType(Element e) {
if (e == null) {
// Malformed code - just return dynamic.
@@ -28,6 +44,8 @@ DartType _elementType(Element e) {
return (e as dynamic).type;
}
+// Return the field on type corresponding to member, or null if none
+// exists or the "field" is actually a getter/setter.
scheglov 2016/08/02 15:25:03 Make this a documentation comment?
Brian Wilkerson 2016/08/02 15:33:53 Or delete it. I didn't add this comment, it was mo
PropertyInducingElement _getMemberField(
InterfaceType type, PropertyAccessorElement member) {
String memberName = member.name;
@@ -53,8 +71,6 @@ PropertyInducingElement _getMemberField(
return field;
}
-// Return the field on type corresponding to member, or null if none
-// exists or the "field" is actually a getter/setter.
/// Looks up the declaration that matches [member] in [type] and returns it's
/// declared type.
FunctionType _getMemberType(InterfaceType type, ExecutableElement member) =>
@@ -176,13 +192,6 @@ class CodeChecker extends RecursiveAstVisitor {
}
@override
- void visitCompilationUnit(CompilationUnit node) {
- _hasImplicitCasts = false;
- node.visitChildren(this);
- setHasImplicitCasts(node, _hasImplicitCasts);
- }
-
- @override
void visitAsExpression(AsExpression node) {
// We could do the same check as the IsExpression below, but that is
// potentially too conservative. Instead, at runtime, we must fail hard
@@ -192,11 +201,16 @@ class CodeChecker extends RecursiveAstVisitor {
@override
void visitAssignmentExpression(AssignmentExpression node) {
- var token = node.operator;
- if (token.type == TokenType.EQ ||
- token.type == TokenType.QUESTION_QUESTION_EQ) {
+ Token operator = node.operator;
+ TokenType operatorType = operator.type;
+ if (operatorType == TokenType.EQ ||
+ operatorType == TokenType.QUESTION_QUESTION_EQ) {
DartType staticType = _getStaticType(node.leftHandSide);
checkAssignment(node.rightHandSide, staticType);
+ } else if (operatorType == TokenType.AMPERSAND_AMPERSAND_EQ ||
+ operatorType == TokenType.BAR_BAR_EQ) {
+ checkAssignment(node.leftHandSide, typeProvider.boolType);
+ checkAssignment(node.rightHandSide, typeProvider.boolType);
} else {
_checkCompoundAssignment(node);
}
@@ -259,6 +273,13 @@ class CodeChecker extends RecursiveAstVisitor {
}
@override
+ void visitCompilationUnit(CompilationUnit node) {
+ _hasImplicitCasts = false;
+ node.visitChildren(this);
+ setHasImplicitCasts(node, _hasImplicitCasts);
+ }
+
+ @override
void visitConditionalExpression(ConditionalExpression node) {
checkBoolean(node.condition);
node.visitChildren(this);
@@ -853,90 +874,6 @@ class CodeChecker extends RecursiveAstVisitor {
}
}
- /// Records an implicit cast for the [expression] from [fromType] to [toType].
- ///
- /// This will emit the appropriate error/warning/hint message as well as mark
- /// the AST node.
- void _recordImplicitCast(
- Expression expression, DartType fromType, DartType 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(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.
- _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
- [expression, fromType, toType]);
- return;
- }
-
- 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.
-
- _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
- [expression, fromType, toType]);
- return;
- }
- }
-
- if (isKnownFunction(expression)) {
- _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
- [expression, fromType, toType]);
- return;
- }
-
- // 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;
- ErrorCode errorCode;
- if (downCastComposite) {
- errorCode = StrongModeCode.DOWN_CAST_COMPOSITE;
- } else if (fromType.isDynamic) {
- errorCode = StrongModeCode.DYNAMIC_CAST;
- } else if (parent is VariableDeclaration &&
- parent.initializer == expression) {
- errorCode = StrongModeCode.ASSIGNMENT_CAST;
- } else {
- errorCode = StrongModeCode.DOWN_CAST_IMPLICIT;
- }
-
- _recordMessage(expression, errorCode, [fromType, toType]);
- setImplicitCast(expression, toType);
- _hasImplicitCasts = true;
- }
-
- // Produce a coercion which coerces something of type fromT
- // to something of type toT.
- // Returns the error coercion if the types cannot be coerced
- // according to our current criteria.
/// Gets the expected return type of the given function [body], either from
/// a normal return/yield, or from a yield*.
DartType _getExpectedReturnType(FunctionBody body, {bool yieldStar: false}) {
@@ -991,6 +928,10 @@ class CodeChecker extends RecursiveAstVisitor {
}
}
+ // Produce a coercion which coerces something of type fromT
+ // to something of type toT.
+ // Returns the error coercion if the types cannot be coerced
+ // according to our current criteria.
scheglov 2016/08/02 15:25:03 Make this a documentation comment?
Brian Wilkerson 2016/08/02 15:33:53 I didn't write this comment either, it was also mo
DartType _getStaticType(Expression expr) {
DartType t = expr.staticType ?? DynamicTypeImpl.instance;
@@ -1085,6 +1026,86 @@ class CodeChecker extends RecursiveAstVisitor {
setIsDynamicInvoke(target, true);
}
+ /// Records an implicit cast for the [expression] from [fromType] to [toType].
+ ///
+ /// This will emit the appropriate error/warning/hint message as well as mark
+ /// the AST node.
+ void _recordImplicitCast(
+ Expression expression, DartType fromType, DartType 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(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.
+ _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
+ [expression, fromType, toType]);
+ return;
+ }
+
+ 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.
+
+ _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
+ [expression, fromType, toType]);
+ return;
+ }
+ }
+
+ if (isKnownFunction(expression)) {
+ _recordMessage(expression, StrongModeCode.STATIC_TYPE_ERROR,
+ [expression, fromType, toType]);
+ return;
+ }
+
+ // 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;
+ ErrorCode errorCode;
+ if (downCastComposite) {
+ errorCode = StrongModeCode.DOWN_CAST_COMPOSITE;
+ } else if (fromType.isDynamic) {
+ errorCode = StrongModeCode.DYNAMIC_CAST;
+ } else if (parent is VariableDeclaration &&
+ parent.initializer == expression) {
+ errorCode = StrongModeCode.ASSIGNMENT_CAST;
+ } else {
+ errorCode = StrongModeCode.DOWN_CAST_IMPLICIT;
+ }
+
+ _recordMessage(expression, errorCode, [fromType, toType]);
+ setImplicitCast(expression, toType);
+ _hasImplicitCasts = true;
+ }
+
void _recordMessage(AstNode node, ErrorCode errorCode, List arguments) {
var severity = errorCode.errorSeverity;
if (severity == ErrorSeverity.ERROR) _failure = true;
@@ -1101,21 +1122,6 @@ class CodeChecker extends RecursiveAstVisitor {
}
}
-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;
-}
-
/// Checks for overriding declarations of fields and methods. This is used to
/// check overrides between classes and superclasses, interfaces, and mixin
/// applications.

Powered by Google App Engine
This is Rietveld 408576698