Chromium Code Reviews| Index: pkg/analyzer/lib/src/generated/resolver.dart |
| diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart |
| index 40a216228e023948cb8ea441a93abc05123bd76a..a33605a947b4f38c19b7159b3cf4477ec8b6105d 100644 |
| --- a/pkg/analyzer/lib/src/generated/resolver.dart |
| +++ b/pkg/analyzer/lib/src/generated/resolver.dart |
| @@ -6,6 +6,8 @@ library engine.resolver; |
| import 'dart:collection'; |
| +import 'package:analyzer/src/generated/scanner.dart'; |
| + |
| import 'ast.dart'; |
| import 'constant.dart'; |
| import 'element.dart'; |
| @@ -136,18 +138,36 @@ class BestPracticesVerifier extends RecursiveAstVisitor<Object> { |
| } |
| @override |
| + Object visitDoStatement(DoStatement node) { |
| + _checkForPossibleNullCondition(node.condition); |
| + return super.visitDoStatement(node); |
| + } |
| + |
| + @override |
| Object visitExportDirective(ExportDirective node) { |
| _checkForDeprecatedMemberUse(node.uriElement, node); |
| return super.visitExportDirective(node); |
| } |
| @override |
| + Object visitForStatement(ForStatement node) { |
| + _checkForPossibleNullCondition(node.condition); |
| + return super.visitForStatement(node); |
| + } |
| + |
| + @override |
| Object visitFunctionDeclaration(FunctionDeclaration node) { |
| _checkForMissingReturn(node.returnType, node.functionExpression.body); |
| return super.visitFunctionDeclaration(node); |
| } |
| @override |
| + Object visitIfStatement(IfStatement node) { |
| + _checkForPossibleNullCondition(node.condition); |
| + return super.visitIfStatement(node); |
| + } |
| + |
| + @override |
| Object visitImportDirective(ImportDirective node) { |
| _checkForDeprecatedMemberUse(node.uriElement, node); |
| ImportElement importElement = node.element; |
| @@ -223,6 +243,12 @@ class BestPracticesVerifier extends RecursiveAstVisitor<Object> { |
| return super.visitVariableDeclaration(node); |
| } |
| + @override |
| + Object visitWhileStatement(WhileStatement node) { |
| + _checkForPossibleNullCondition(node.condition); |
| + return super.visitWhileStatement(node); |
| + } |
| + |
| /** |
| * Check for the passed is expression for the unnecessary type check hint codes as well as null |
| * checks expressed using an is expression. |
| @@ -619,6 +645,28 @@ class BestPracticesVerifier extends RecursiveAstVisitor<Object> { |
| } |
| /** |
| + * Produce a hint if the given [condition] could have a value of `null`. |
| + */ |
| + void _checkForPossibleNullCondition(Expression condition) { |
| + while (condition is ParenthesizedExpression) { |
| + condition = (condition as ParenthesizedExpression).expression; |
| + } |
| + if (condition is MethodInvocation) { |
| + Token operator = condition.operator; |
| + if (operator != null && operator.type == TokenType.QUESTION_PERIOD) { |
|
scheglov
2015/10/25 17:48:52
if (operator?.type == TokenType.QUESTION_PERIOD) m
Brian Wilkerson
2015/10/25 22:11:40
I don't happen to find it to be very readable, but
|
| + _errorReporter.reportErrorForNode( |
| + HintCode.NULL_AWARE_IN_CONDITION, condition); |
| + } |
| + } else if (condition is PropertyAccess) { |
| + Token operator = condition.operator; |
| + if (operator != null && operator.type == TokenType.QUESTION_PERIOD) { |
| + _errorReporter.reportErrorForNode( |
| + HintCode.NULL_AWARE_IN_CONDITION, condition); |
| + } |
| + } |
|
scheglov
2015/10/25 17:48:52
We could also validate every part of &&, ||, etc e
Brian Wilkerson
2015/10/25 22:11:40
Done
|
| + } |
| + |
| + /** |
| * Check for the passed class declaration for the |
| * [HintCode.OVERRIDE_EQUALS_BUT_NOT_HASH_CODE] hint code. |
| * |
| @@ -4824,7 +4872,7 @@ class HintGenerator { |
| _usedImportedElementsVisitor = |
| new GatherUsedImportedElementsVisitor(_library); |
| _enableDart2JSHints = _context.analysisOptions.dart2jsHint; |
| - _manager = new InheritanceManager(_compilationUnits[0].element.library); |
| + _manager = new InheritanceManager(_library); |
| _usedLocalElementsVisitor = new GatherUsedLocalElementsVisitor(_library); |
| } |