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

Unified Diff: lib/src/checker/checker.dart

Issue 1147143007: fixes #206, add checking for unary ops (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: merged Created 5 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
« no previous file with comments | « lib/runtime/dart/math.js ('k') | lib/src/codegen/js_codegen.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/checker/checker.dart
diff --git a/lib/src/checker/checker.dart b/lib/src/checker/checker.dart
index 9d328979a5677938e33542f0a601ec3f1ab943b3..78b1a20e68d0344c324558a1439fda3877777e07 100644
--- a/lib/src/checker/checker.dart
+++ b/lib/src/checker/checker.dart
@@ -348,7 +348,7 @@ class CodeChecker extends RecursiveAstVisitor {
_overrideChecker = new _OverrideChecker(rules, reporter, options);
@override
- visitCompilationUnit(CompilationUnit unit) {
+ void visitCompilationUnit(CompilationUnit unit) {
void report(Expression expr) {
_reporter.log(new MissingTypeError(expr));
}
@@ -379,17 +379,20 @@ class CodeChecker extends RecursiveAstVisitor {
_constantContext = o;
}
- visitComment(Comment node) {
+ @override
+ void visitComment(Comment node) {
// skip, no need to do typechecking inside comments (they may contain
// comment references which would require resolution).
}
- visitClassDeclaration(ClassDeclaration node) {
+ @override
+ void visitClassDeclaration(ClassDeclaration node) {
_overrideChecker.check(node);
super.visitClassDeclaration(node);
}
- visitAssignmentExpression(AssignmentExpression node) {
+ @override
+ void visitAssignmentExpression(AssignmentExpression node) {
var token = node.operator;
if (token.type != TokenType.EQ) {
_checkCompoundAssignment(node);
@@ -402,7 +405,7 @@ class CodeChecker extends RecursiveAstVisitor {
/// Check constructor declaration to ensure correct super call placement.
@override
- visitConstructorDeclaration(ConstructorDeclaration node) {
+ void visitConstructorDeclaration(ConstructorDeclaration node) {
_visitMaybeConst(node, (node) {
node.visitChildren(this);
@@ -417,7 +420,7 @@ class CodeChecker extends RecursiveAstVisitor {
}
@override
- visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+ void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
var field = node.fieldName;
DartType staticType = _rules.elementType(field.staticElement);
node.expression = checkAssignment(node.expression, staticType);
@@ -425,7 +428,7 @@ class CodeChecker extends RecursiveAstVisitor {
}
@override
- visitForEachStatement(ForEachStatement node) {
+ void visitForEachStatement(ForEachStatement node) {
// Check that the expression is an Iterable.
var expr = node.iterable;
var iterableType = _rules.provider.iterableType;
@@ -438,7 +441,43 @@ class CodeChecker extends RecursiveAstVisitor {
node.visitChildren(this);
}
- @override visitListLiteral(ListLiteral node) {
+ @override
+ void visitForStatement(ForStatement node) {
+ if (node.condition != null) {
+ node.condition = checkBoolean(node.condition);
+ }
+ node.visitChildren(this);
+ }
+
+ @override
+ void visitIfStatement(IfStatement node) {
+ node.condition = checkBoolean(node.condition);
+ node.visitChildren(this);
+ }
+
+ @override
+ void visitDoStatement(DoStatement node) {
+ node.condition = checkBoolean(node.condition);
+ node.visitChildren(this);
+ }
+
+ @override
+ void visitWhileStatement(WhileStatement node) {
+ node.condition = checkBoolean(node.condition);
+ node.visitChildren(this);
+ }
+
+ @override
+ void visitSwitchStatement(SwitchStatement node) {
+ // SwitchStatement defines a boolean conversion to check the result of the
+ // case value == the switch value, but in dev_compiler we require a boolean
+ // return type from an overridden == operator (because Object.==), so
+ // checking in SwitchStatement shouldn't be necessary.
+ node.visitChildren(this);
+ }
+
+ @override
+ void visitListLiteral(ListLiteral node) {
var type = _rules.provider.dynamicType;
if (node.typeArguments != null) {
var targs = node.typeArguments.arguments;
@@ -451,7 +490,8 @@ class CodeChecker extends RecursiveAstVisitor {
super.visitListLiteral(node);
}
- @override visitMapLiteral(MapLiteral node) {
+ @override
+ void visitMapLiteral(MapLiteral node) {
var ktype = _rules.provider.dynamicType;
var vtype = _rules.provider.dynamicType;
if (node.typeArguments != null) {
@@ -513,24 +553,29 @@ class CodeChecker extends RecursiveAstVisitor {
}
}
- visitMethodInvocation(MethodInvocation node) {
+ @override
+ void visitMethodInvocation(MethodInvocation node) {
checkFunctionApplication(node, node.methodName, node.argumentList);
node.visitChildren(this);
}
- visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+ @override
+ void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
checkFunctionApplication(node, node.function, node.argumentList);
node.visitChildren(this);
}
- visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
+ @override
+ void visitRedirectingConstructorInvocation(
+ RedirectingConstructorInvocation node) {
var type = node.staticElement.type;
bool checked = checkArgumentList(node.argumentList, type);
assert(checked);
node.visitChildren(this);
}
- visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ @override
+ void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
var element = node.staticElement;
if (element == null) {
_recordMessage(new MissingTypeError(node));
@@ -568,24 +613,28 @@ class CodeChecker extends RecursiveAstVisitor {
return checkAssignment(expression, type);
}
- visitExpressionFunctionBody(ExpressionFunctionBody node) {
+ @override
+ void visitExpressionFunctionBody(ExpressionFunctionBody node) {
node.expression = _checkReturn(node.expression, node);
node.visitChildren(this);
}
- visitReturnStatement(ReturnStatement node) {
+ @override
+ void visitReturnStatement(ReturnStatement node) {
node.expression = _checkReturn(node.expression, node);
node.visitChildren(this);
}
- visitPropertyAccess(PropertyAccess node) {
+ @override
+ void visitPropertyAccess(PropertyAccess node) {
if (node.staticType.isDynamic && _rules.isDynamicTarget(node.realTarget)) {
_recordDynamicInvoke(node);
}
node.visitChildren(this);
}
- visitPrefixedIdentifier(PrefixedIdentifier node) {
+ @override
+ void visitPrefixedIdentifier(PrefixedIdentifier node) {
final target = node.prefix;
if (_rules.isDynamicTarget(target)) {
_recordDynamicInvoke(node);
@@ -593,7 +642,8 @@ class CodeChecker extends RecursiveAstVisitor {
node.visitChildren(this);
}
- @override visitDefaultFormalParameter(DefaultFormalParameter node) {
+ @override
+ void visitDefaultFormalParameter(DefaultFormalParameter node) {
_visitMaybeConst(node, (node) {
// Check that defaults have the proper subtype.
var parameter = node.parameter;
@@ -615,7 +665,8 @@ class CodeChecker extends RecursiveAstVisitor {
});
}
- visitFieldFormalParameter(FieldFormalParameter node) {
+ @override
+ void visitFieldFormalParameter(FieldFormalParameter node) {
var element = node.element;
var typeName = node.type;
if (typeName != null) {
@@ -633,7 +684,7 @@ class CodeChecker extends RecursiveAstVisitor {
}
@override
- visitInstanceCreationExpression(InstanceCreationExpression node) {
+ void visitInstanceCreationExpression(InstanceCreationExpression node) {
_visitMaybeConst(node, (node) {
var arguments = node.argumentList;
var element = node.staticElement;
@@ -648,7 +699,7 @@ class CodeChecker extends RecursiveAstVisitor {
}
@override
- visitVariableDeclarationList(VariableDeclarationList node) {
+ void visitVariableDeclarationList(VariableDeclarationList node) {
_visitMaybeConst(node, (node) {
TypeName type = node.type;
if (type == null) {
@@ -682,7 +733,7 @@ class CodeChecker extends RecursiveAstVisitor {
}
@override
- visitVariableDeclaration(VariableDeclaration node) {
+ void visitVariableDeclaration(VariableDeclaration node) {
_visitMaybeConst(node, super.visitVariableDeclaration);
}
@@ -693,19 +744,52 @@ class CodeChecker extends RecursiveAstVisitor {
}
}
- visitAsExpression(AsExpression node) {
+ @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
// if the Dart as and the DDC as would return different values.
node.visitChildren(this);
}
- visitIsExpression(IsExpression node) {
+ @override
+ void visitIsExpression(IsExpression node) {
_checkRuntimeTypeCheck(node, node.type);
node.visitChildren(this);
}
- visitBinaryExpression(BinaryExpression node) {
+ @override
+ void visitPrefixExpression(PrefixExpression node) {
+ if (node.operator.type == TokenType.BANG) {
+ node.operand = checkBoolean(node.operand);
+ } else {
+ _checkUnary(node);
+ }
+ node.visitChildren(this);
+ }
+
+ @override
+ void visitPostfixExpression(PostfixExpression node) {
+ _checkUnary(node);
+ node.visitChildren(this);
+ }
+
+ void _checkUnary(/*PrefixExpression|PostfixExpression*/ node) {
+ var op = node.operator;
+ if (op.isUserDefinableOperator ||
+ op.type == TokenType.PLUS_PLUS ||
+ op.type == TokenType.MINUS_MINUS) {
+ if (_rules.isDynamicTarget(node.operand)) {
+ _recordDynamicInvoke(node);
+ }
+ // For ++ and --, even if it is not dynamic, we still need to check
+ // that the user defined method accepts an `int` as the RHS.
+ // We assume Analyzer has done this already.
+ }
+ }
+
+ @override
+ void visitBinaryExpression(BinaryExpression node) {
var op = node.operator;
if (op.isUserDefinableOperator) {
if (_rules.isDynamicTarget(node.leftOperand)) {
@@ -734,9 +818,8 @@ class CodeChecker extends RecursiveAstVisitor {
switch (op.type) {
case TokenType.AMPERSAND_AMPERSAND:
case TokenType.BAR_BAR:
- var boolType = _rules.provider.boolType;
- node.leftOperand = checkArgument(node.leftOperand, boolType);
- node.rightOperand = checkArgument(node.rightOperand, boolType);
+ node.leftOperand = checkBoolean(node.leftOperand);
+ node.rightOperand = checkBoolean(node.rightOperand);
break;
case TokenType.BANG_EQ:
break;
@@ -748,6 +831,12 @@ class CodeChecker extends RecursiveAstVisitor {
}
@override
+ void visitConditionalExpression(ConditionalExpression node) {
+ node.condition = checkBoolean(node.condition);
+ node.visitChildren(this);
+ }
+
+ @override
void visitIndexExpression(IndexExpression node) {
if (_rules.isDynamicTarget(node.target)) {
_recordDynamicInvoke(node);
@@ -771,6 +860,12 @@ class CodeChecker extends RecursiveAstVisitor {
return (name == null) ? _rules.provider.dynamicType : name.type;
}
+ /// Analyzer checks boolean conversions, but we need to check too, because
+ /// it uses the default assignability rules that allow `dynamic` and `Object`
+ /// to be assigned to bool with no message.
+ Expression checkBoolean(Expression expr) =>
+ checkAssignment(expr, _rules.provider.boolType);
+
Expression checkAssignment(Expression expr, DartType type) {
if (expr is ParenthesizedExpression) {
expr.expression = checkAssignment(expr.expression, type);
« no previous file with comments | « lib/runtime/dart/math.js ('k') | lib/src/codegen/js_codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698