Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library analyzer.src.generated.resolver; | 5 library analyzer.src.generated.resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
| 10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 | 66 |
| 67 static String _TO_INT_METHOD_NAME = "toInt"; | 67 static String _TO_INT_METHOD_NAME = "toInt"; |
| 68 | 68 |
| 69 /** | 69 /** |
| 70 * The class containing the AST nodes being visited, or `null` if we are not i n the scope of | 70 * The class containing the AST nodes being visited, or `null` if we are not i n the scope of |
| 71 * a class. | 71 * a class. |
| 72 */ | 72 */ |
| 73 ClassElement _enclosingClass; | 73 ClassElement _enclosingClass; |
| 74 | 74 |
| 75 /** | 75 /** |
| 76 * A flag indicating whether a surrounding member (compilation unit or class) | |
| 77 * is deprecated. | |
| 78 */ | |
| 79 bool inDeprecatedMember = false; | |
| 80 | |
| 81 /** | |
| 76 * The error reporter by which errors will be reported. | 82 * The error reporter by which errors will be reported. |
| 77 */ | 83 */ |
| 78 final ErrorReporter _errorReporter; | 84 final ErrorReporter _errorReporter; |
| 79 | 85 |
| 80 /** | 86 /** |
| 81 * The type Future<Null>, which is needed for determining whether it is safe | 87 * The type Future<Null>, which is needed for determining whether it is safe |
| 82 * to have a bare "return;" in an async method. | 88 * to have a bare "return;" in an async method. |
| 83 */ | 89 */ |
| 84 final InterfaceType _futureNullType; | 90 final InterfaceType _futureNullType; |
| 85 | 91 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 131 @override | 137 @override |
| 132 Object visitBinaryExpression(BinaryExpression node) { | 138 Object visitBinaryExpression(BinaryExpression node) { |
| 133 _checkForDivisionOptimizationHint(node); | 139 _checkForDivisionOptimizationHint(node); |
| 134 _checkForDeprecatedMemberUse(node.bestElement, node); | 140 _checkForDeprecatedMemberUse(node.bestElement, node); |
| 135 return super.visitBinaryExpression(node); | 141 return super.visitBinaryExpression(node); |
| 136 } | 142 } |
| 137 | 143 |
| 138 @override | 144 @override |
| 139 Object visitClassDeclaration(ClassDeclaration node) { | 145 Object visitClassDeclaration(ClassDeclaration node) { |
| 140 ClassElement outerClass = _enclosingClass; | 146 ClassElement outerClass = _enclosingClass; |
| 147 bool wasInDeprecatedMember = inDeprecatedMember; | |
| 148 ClassElement element = node.element; | |
| 149 if (element != null && element.isDeprecated) { | |
| 150 inDeprecatedMember = true; | |
|
scheglov
2016/03/13 20:41:23
This could be a single assignment statement.
| |
| 151 } | |
| 141 try { | 152 try { |
| 142 _enclosingClass = node.element; | 153 _enclosingClass = element; |
| 143 // Commented out until we decide that we want this hint in the analyzer | 154 // Commented out until we decide that we want this hint in the analyzer |
| 144 // checkForOverrideEqualsButNotHashCode(node); | 155 // checkForOverrideEqualsButNotHashCode(node); |
| 145 return super.visitClassDeclaration(node); | 156 return super.visitClassDeclaration(node); |
| 146 } finally { | 157 } finally { |
| 147 _enclosingClass = outerClass; | 158 _enclosingClass = outerClass; |
| 159 inDeprecatedMember = wasInDeprecatedMember; | |
| 148 } | 160 } |
| 149 } | 161 } |
| 150 | 162 |
| 151 @override | 163 @override |
| 152 Object visitConditionalExpression(ConditionalExpression node) { | 164 Object visitConditionalExpression(ConditionalExpression node) { |
| 153 _checkForPossibleNullCondition(node.condition); | 165 _checkForPossibleNullCondition(node.condition); |
| 154 return super.visitConditionalExpression(node); | 166 return super.visitConditionalExpression(node); |
| 155 } | 167 } |
| 156 | 168 |
| 157 @override | 169 @override |
| 158 Object visitDoStatement(DoStatement node) { | 170 Object visitDoStatement(DoStatement node) { |
| 159 _checkForPossibleNullCondition(node.condition); | 171 _checkForPossibleNullCondition(node.condition); |
| 160 return super.visitDoStatement(node); | 172 return super.visitDoStatement(node); |
| 161 } | 173 } |
| 162 | 174 |
| 163 @override | 175 @override |
| 164 Object visitExportDirective(ExportDirective node) { | 176 Object visitExportDirective(ExportDirective node) { |
| 165 _checkForDeprecatedMemberUse(node.uriElement, node); | 177 _checkForDeprecatedMemberUse(node.uriElement, node); |
| 166 return super.visitExportDirective(node); | 178 return super.visitExportDirective(node); |
| 167 } | 179 } |
| 168 | 180 |
| 169 @override | 181 @override |
| 170 Object visitForStatement(ForStatement node) { | 182 Object visitForStatement(ForStatement node) { |
| 171 _checkForPossibleNullCondition(node.condition); | 183 _checkForPossibleNullCondition(node.condition); |
| 172 return super.visitForStatement(node); | 184 return super.visitForStatement(node); |
| 173 } | 185 } |
| 174 | 186 |
| 175 @override | 187 @override |
| 176 Object visitFunctionDeclaration(FunctionDeclaration node) { | 188 Object visitFunctionDeclaration(FunctionDeclaration node) { |
| 177 _checkForMissingReturn(node.returnType, node.functionExpression.body); | 189 bool wasInDeprecatedMember = inDeprecatedMember; |
| 178 return super.visitFunctionDeclaration(node); | 190 ExecutableElement element = node.element; |
| 191 if (element != null && element.isDeprecated) { | |
| 192 inDeprecatedMember = true; | |
| 193 } | |
| 194 try { | |
| 195 _checkForMissingReturn(node.returnType, node.functionExpression.body); | |
| 196 return super.visitFunctionDeclaration(node); | |
| 197 } finally { | |
| 198 inDeprecatedMember = wasInDeprecatedMember; | |
| 199 } | |
| 179 } | 200 } |
| 180 | 201 |
| 181 @override | 202 @override |
| 182 Object visitIfStatement(IfStatement node) { | 203 Object visitIfStatement(IfStatement node) { |
| 183 _checkForPossibleNullCondition(node.condition); | 204 _checkForPossibleNullCondition(node.condition); |
| 184 return super.visitIfStatement(node); | 205 return super.visitIfStatement(node); |
| 185 } | 206 } |
| 186 | 207 |
| 187 @override | 208 @override |
| 188 Object visitImportDirective(ImportDirective node) { | 209 Object visitImportDirective(ImportDirective node) { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 209 } | 230 } |
| 210 | 231 |
| 211 @override | 232 @override |
| 212 Object visitIsExpression(IsExpression node) { | 233 Object visitIsExpression(IsExpression node) { |
| 213 _checkAllTypeChecks(node); | 234 _checkAllTypeChecks(node); |
| 214 return super.visitIsExpression(node); | 235 return super.visitIsExpression(node); |
| 215 } | 236 } |
| 216 | 237 |
| 217 @override | 238 @override |
| 218 Object visitMethodDeclaration(MethodDeclaration node) { | 239 Object visitMethodDeclaration(MethodDeclaration node) { |
| 219 // This was determined to not be a good hint, see: dartbug.com/16029 | 240 bool wasInDeprecatedMember = inDeprecatedMember; |
| 220 //checkForOverridingPrivateMember(node); | 241 ExecutableElement element = node.element; |
| 221 _checkForMissingReturn(node.returnType, node.body); | 242 if (element != null && element.isDeprecated) { |
| 222 _checkForUnnecessaryNoSuchMethod(node); | 243 inDeprecatedMember = true; |
| 223 return super.visitMethodDeclaration(node); | 244 } |
| 245 try { | |
| 246 // This was determined to not be a good hint, see: dartbug.com/16029 | |
| 247 //checkForOverridingPrivateMember(node); | |
| 248 _checkForMissingReturn(node.returnType, node.body); | |
| 249 _checkForUnnecessaryNoSuchMethod(node); | |
| 250 return super.visitMethodDeclaration(node); | |
| 251 } finally { | |
| 252 inDeprecatedMember = wasInDeprecatedMember; | |
| 253 } | |
| 224 } | 254 } |
| 225 | 255 |
| 226 @override | 256 @override |
| 227 Object visitMethodInvocation(MethodInvocation node) { | 257 Object visitMethodInvocation(MethodInvocation node) { |
| 228 _checkForCanBeNullAfterNullAware(node.realTarget, node.operator); | 258 _checkForCanBeNullAfterNullAware(node.realTarget, node.operator); |
| 229 _checkForInvalidProtectedMethodCalls(node); | 259 _checkForInvalidProtectedMethodCalls(node); |
| 230 return super.visitMethodInvocation(node); | 260 return super.visitMethodInvocation(node); |
| 231 } | 261 } |
| 232 | 262 |
| 233 @override | 263 @override |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 497 | 527 |
| 498 /** | 528 /** |
| 499 * Given some [Element], look at the associated metadata and report the use of the member if | 529 * Given some [Element], look at the associated metadata and report the use of the member if |
| 500 * it is declared as deprecated. | 530 * it is declared as deprecated. |
| 501 * | 531 * |
| 502 * @param element some element to check for deprecated use of | 532 * @param element some element to check for deprecated use of |
| 503 * @param node the node use for the location of the error | 533 * @param node the node use for the location of the error |
| 504 * @return `true` if and only if a hint code is generated on the passed node | 534 * @return `true` if and only if a hint code is generated on the passed node |
| 505 * See [HintCode.DEPRECATED_MEMBER_USE]. | 535 * See [HintCode.DEPRECATED_MEMBER_USE]. |
| 506 */ | 536 */ |
| 507 bool _checkForDeprecatedMemberUse(Element element, AstNode node) { | 537 void _checkForDeprecatedMemberUse(Element element, AstNode node) { |
| 508 if (element != null && element.isDeprecated) { | 538 if (element != null && element.isDeprecated && !inDeprecatedMember) { |
| 509 String displayName = element.displayName; | 539 String displayName = element.displayName; |
| 510 if (element is ConstructorElement) { | 540 if (element is ConstructorElement) { |
| 511 // TODO(jwren) We should modify ConstructorElement.getDisplayName(), | 541 // TODO(jwren) We should modify ConstructorElement.getDisplayName(), |
| 512 // or have the logic centralized elsewhere, instead of doing this logic | 542 // or have the logic centralized elsewhere, instead of doing this logic |
| 513 // here. | 543 // here. |
| 514 ConstructorElement constructorElement = element; | 544 ConstructorElement constructorElement = element; |
| 515 displayName = constructorElement.enclosingElement.displayName; | 545 displayName = constructorElement.enclosingElement.displayName; |
| 516 if (!constructorElement.displayName.isEmpty) { | 546 if (!constructorElement.displayName.isEmpty) { |
| 517 displayName = "$displayName.${constructorElement.displayName}"; | 547 displayName = "$displayName.${constructorElement.displayName}"; |
| 518 } | 548 } |
| 519 } | 549 } |
| 520 _errorReporter.reportErrorForNode( | 550 _errorReporter.reportErrorForNode( |
| 521 HintCode.DEPRECATED_MEMBER_USE, node, [displayName]); | 551 HintCode.DEPRECATED_MEMBER_USE, node, [displayName]); |
| 522 return true; | |
| 523 } | 552 } |
| 524 return false; | |
| 525 } | 553 } |
| 526 | 554 |
| 527 /** | 555 /** |
| 528 * For [SimpleIdentifier]s, only call [checkForDeprecatedMemberUse] | 556 * For [SimpleIdentifier]s, only call [checkForDeprecatedMemberUse] |
| 529 * if the node is not in a declaration context. | 557 * if the node is not in a declaration context. |
| 530 * | 558 * |
| 531 * Also, if the identifier is a constructor name in a constructor invocation, then calls to the | 559 * Also, if the identifier is a constructor name in a constructor invocation, then calls to the |
| 532 * deprecated constructor will be caught by | 560 * deprecated constructor will be caught by |
| 533 * [visitInstanceCreationExpression] and | 561 * [visitInstanceCreationExpression] and |
| 534 * [visitSuperConstructorInvocation], and can be ignored by | 562 * [visitSuperConstructorInvocation], and can be ignored by |
| 535 * this visit method. | 563 * this visit method. |
| 536 * | 564 * |
| 537 * @param identifier some simple identifier to check for deprecated use of | 565 * @param identifier some simple identifier to check for deprecated use of |
| 538 * @return `true` if and only if a hint code is generated on the passed node | 566 * @return `true` if and only if a hint code is generated on the passed node |
| 539 * See [HintCode.DEPRECATED_MEMBER_USE]. | 567 * See [HintCode.DEPRECATED_MEMBER_USE]. |
| 540 */ | 568 */ |
| 541 bool _checkForDeprecatedMemberUseAtIdentifier(SimpleIdentifier identifier) { | 569 void _checkForDeprecatedMemberUseAtIdentifier(SimpleIdentifier identifier) { |
| 542 if (identifier.inDeclarationContext()) { | 570 if (identifier.inDeclarationContext()) { |
| 543 return false; | 571 return; |
| 544 } | 572 } |
| 545 AstNode parent = identifier.parent; | 573 AstNode parent = identifier.parent; |
| 546 if ((parent is ConstructorName && identical(identifier, parent.name)) || | 574 if ((parent is ConstructorName && identical(identifier, parent.name)) || |
| 547 (parent is ConstructorDeclaration && | 575 (parent is ConstructorDeclaration && |
| 548 identical(identifier, parent.returnType)) || | 576 identical(identifier, parent.returnType)) || |
| 549 (parent is SuperConstructorInvocation && | 577 (parent is SuperConstructorInvocation && |
| 550 identical(identifier, parent.constructorName)) || | 578 identical(identifier, parent.constructorName)) || |
| 551 parent is HideCombinator) { | 579 parent is HideCombinator) { |
| 552 return false; | 580 return; |
| 553 } | 581 } |
| 554 return _checkForDeprecatedMemberUse(identifier.bestElement, identifier); | 582 _checkForDeprecatedMemberUse(identifier.bestElement, identifier); |
| 555 } | 583 } |
| 556 | 584 |
| 557 /** | 585 /** |
| 558 * Check for the passed binary expression for the [HintCode.DIVISION_OPTIMIZAT ION]. | 586 * Check for the passed binary expression for the [HintCode.DIVISION_OPTIMIZAT ION]. |
| 559 * | 587 * |
| 560 * @param node the binary expression to check | 588 * @param node the binary expression to check |
| 561 * @return `true` if and only if a hint code is generated on the passed node | 589 * @return `true` if and only if a hint code is generated on the passed node |
| 562 * See [HintCode.DIVISION_OPTIMIZATION]. | 590 * See [HintCode.DIVISION_OPTIMIZATION]. |
| 563 */ | 591 */ |
| 564 bool _checkForDivisionOptimizationHint(BinaryExpression node) { | 592 bool _checkForDivisionOptimizationHint(BinaryExpression node) { |
| (...skipping 12369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12934 nonFields.add(node); | 12962 nonFields.add(node); |
| 12935 return null; | 12963 return null; |
| 12936 } | 12964 } |
| 12937 | 12965 |
| 12938 @override | 12966 @override |
| 12939 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 12967 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
| 12940 | 12968 |
| 12941 @override | 12969 @override |
| 12942 Object visitWithClause(WithClause node) => null; | 12970 Object visitWithClause(WithClause node) => null; |
| 12943 } | 12971 } |
| OLD | NEW |