Chromium Code Reviews| Index: lib/src/checker/checker.dart |
| diff --git a/lib/src/checker/checker.dart b/lib/src/checker/checker.dart |
| index f11aef694ff1ac139d46db6066191c78d3d8860f..f25ef64572c8c0fd102a78266339a0464ac22ab8 100644 |
| --- a/lib/src/checker/checker.dart |
| +++ b/lib/src/checker/checker.dart |
| @@ -337,6 +337,7 @@ class CodeChecker extends RecursiveAstVisitor { |
| final TypeRules _rules; |
| final CheckerReporter _reporter; |
| final _OverrideChecker _overrideChecker; |
| + bool _constantContext = false; |
| bool _failure = false; |
| bool get failure => _failure || _overrideChecker._failure; |
| @@ -346,6 +347,25 @@ class CodeChecker extends RecursiveAstVisitor { |
| _reporter = reporter, |
| _overrideChecker = new _OverrideChecker(rules, reporter, options); |
| + _visitMaybeConst(AstNode n, visitNode(AstNode n)) { |
|
vsm
2015/02/27 00:20:16
Would be nice if we had generic methods. :-)
Leaf
2015/02/27 00:44:21
Acknowledged.
|
| + var o = _constantContext; |
| + if (!o) { |
| + if (n is VariableDeclarationList) { |
| + _constantContext = o || n.isConst; |
| + } else if (n is VariableDeclaration) { |
| + _constantContext = o || n.isConst; |
| + } else if (n is FormalParameter) { |
| + _constantContext = o || n.isConst; |
| + } else if (n is InstanceCreationExpression) { |
| + _constantContext = o || n.isConst; |
| + } else if (n is ConstructorDeclaration) { |
| + _constantContext = o || n.element.isConst; |
| + } |
| + } |
| + visitNode(n); |
| + _constantContext = o; |
| + } |
| + |
| visitComment(Comment node) { |
| // skip, no need to do typechecking inside comments (they may contain |
| // comment references which would require resolution). |
| @@ -367,9 +387,7 @@ class CodeChecker extends RecursiveAstVisitor { |
| node.visitChildren(this); |
| } |
| - /// Check constructor declaration to ensure correct super call placement. |
| - @override |
| - visitConstructorDeclaration(ConstructorDeclaration node) { |
| + _visitConstructorDeclaration(ConstructorDeclaration node) { |
| node.visitChildren(this); |
| final init = node.initializers; |
| @@ -381,6 +399,47 @@ class CodeChecker extends RecursiveAstVisitor { |
| } |
| } |
| + /// Check constructor declaration to ensure correct super call placement. |
| + @override |
| + visitConstructorDeclaration(ConstructorDeclaration node) { |
| + _visitMaybeConst(node, _visitConstructorDeclaration); |
|
vsm
2015/02/27 00:20:16
Perhaps just inline the closure here instead of a
Leaf
2015/02/27 00:44:21
Done.
|
| + } |
| + |
| + @override |
| + visitInstanceCreationExpression(InstanceCreationExpression node) { |
| + _visitMaybeConst(node, super.visitInstanceCreationExpression); |
| + } |
| + |
| + @override visitListLiteral(ListLiteral node) { |
| + var type = _rules.provider.dynamicType; |
| + if (node.typeArguments != null) { |
| + var targs = node.typeArguments.arguments; |
| + if (targs.length > 0) type = targs[0].type; |
| + } |
| + var elements = node.elements; |
| + for (int i = 0; i < elements.length; i++) { |
| + elements[i] = checkArgument(elements[i], type); |
| + } |
| + super.visitListLiteral(node); |
| + } |
| + |
| + @override visitMapLiteral(MapLiteral node) { |
| + var ktype = _rules.provider.dynamicType; |
| + var vtype = _rules.provider.dynamicType; |
| + if (node.typeArguments != null) { |
| + var targs = node.typeArguments.arguments; |
| + if (targs.length > 0) ktype = targs[0].type; |
| + if (targs.length > 1) vtype = targs[1].type; |
| + } |
| + var entries = node.entries; |
| + for (int i = 0; i < entries.length; i++) { |
| + var entry = entries[i]; |
| + entry.key = checkArgument(entry.key, ktype); |
| + entry.value = checkArgument(entry.value, vtype); |
| + } |
| + super.visitMapLiteral(node); |
| + } |
| + |
| // Check invocations |
| bool checkArgumentList(ArgumentList node, FunctionType type) { |
| NodeList<Expression> list = node.arguments; |
| @@ -508,7 +567,7 @@ class CodeChecker extends RecursiveAstVisitor { |
| node.visitChildren(this); |
| } |
| - visitDefaultFormalParameter(DefaultFormalParameter node) { |
| + _visitDefaultFormalParameter(DefaultFormalParameter node) { |
| // Check that defaults have the proper subtype. |
| var parameter = node.parameter; |
| var parameterType = _rules.elementType(parameter.element); |
| @@ -534,7 +593,11 @@ class CodeChecker extends RecursiveAstVisitor { |
| node.visitChildren(this); |
| } |
| - visitVariableDeclarationList(VariableDeclarationList node) { |
| + @override visitDefaultFormalParameter(DefaultFormalParameter node) { |
| + _visitMaybeConst(node, _visitDefaultFormalParameter); |
| + } |
| + |
| + _visitVariableDeclarationList(VariableDeclarationList node) { |
| TypeName type = node.type; |
| if (type == null) { |
| // No checks are needed when the type is var. Although internally the |
| @@ -565,6 +628,16 @@ class CodeChecker extends RecursiveAstVisitor { |
| node.visitChildren(this); |
| } |
| + @override |
| + visitVariableDeclarationList(VariableDeclarationList node) { |
| + _visitMaybeConst(node, _visitVariableDeclarationList); |
| + } |
| + |
| + @override |
| + visitVariableDeclaration(VariableDeclaration node) { |
| + _visitMaybeConst(node, super.visitVariableDeclaration); |
| + } |
| + |
| void _checkRuntimeTypeCheck(AstNode node, TypeName typeName) { |
| var type = getType(typeName); |
| if (!_rules.isGroundType(type)) { |
| @@ -586,7 +659,7 @@ class CodeChecker extends RecursiveAstVisitor { |
| } |
| Expression checkAssignment(Expression expr, DartType type) { |
| - final staticInfo = _rules.checkAssignment(expr, type); |
| + final staticInfo = _rules.checkAssignment(expr, type, _constantContext); |
| _recordMessage(staticInfo); |
| if (staticInfo is Conversion) expr = staticInfo; |
| return expr; |
| @@ -660,7 +733,8 @@ class CodeChecker extends RecursiveAstVisitor { |
| // Check the rhs type |
| if (staticInfo is! Conversion) { |
| var paramType = paramTypes.first; |
| - staticInfo = _rules.checkAssignment(expr.rightHandSide, paramType); |
| + staticInfo = _rules.checkAssignment( |
| + expr.rightHandSide, paramType, _constantContext); |
| _recordMessage(staticInfo); |
| if (staticInfo is Conversion) expr.rightHandSide = staticInfo; |
| } |