| 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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 * is deprecated. | 57 * is deprecated. |
| 58 */ | 58 */ |
| 59 bool inDeprecatedMember; | 59 bool inDeprecatedMember; |
| 60 | 60 |
| 61 /** | 61 /** |
| 62 * The error reporter by which errors will be reported. | 62 * The error reporter by which errors will be reported. |
| 63 */ | 63 */ |
| 64 final ErrorReporter _errorReporter; | 64 final ErrorReporter _errorReporter; |
| 65 | 65 |
| 66 /** | 66 /** |
| 67 * The type [Null]. |
| 68 */ |
| 69 final InterfaceType _nullType; |
| 70 |
| 71 /** |
| 67 * The type Future<Null>, which is needed for determining whether it is safe | 72 * The type Future<Null>, which is needed for determining whether it is safe |
| 68 * to have a bare "return;" in an async method. | 73 * to have a bare "return;" in an async method. |
| 69 */ | 74 */ |
| 70 final InterfaceType _futureNullType; | 75 final InterfaceType _futureNullType; |
| 71 | 76 |
| 72 /** | 77 /** |
| 73 * The type system primitives | 78 * The type system primitives |
| 74 */ | 79 */ |
| 75 TypeSystem _typeSystem; | 80 TypeSystem _typeSystem; |
| 76 | 81 |
| 77 /** | 82 /** |
| 78 * The current library | 83 * The current library |
| 79 */ | 84 */ |
| 80 LibraryElement _currentLibrary; | 85 LibraryElement _currentLibrary; |
| 81 | 86 |
| 82 /** | 87 /** |
| 83 * Create a new instance of the [BestPracticesVerifier]. | 88 * Create a new instance of the [BestPracticesVerifier]. |
| 84 * | 89 * |
| 85 * @param errorReporter the error reporter | 90 * @param errorReporter the error reporter |
| 86 */ | 91 */ |
| 87 BestPracticesVerifier( | 92 BestPracticesVerifier( |
| 88 this._errorReporter, TypeProvider typeProvider, this._currentLibrary, | 93 this._errorReporter, TypeProvider typeProvider, this._currentLibrary, |
| 89 {TypeSystem typeSystem}) | 94 {TypeSystem typeSystem}) |
| 90 : _futureNullType = typeProvider.futureNullType, | 95 : _nullType = typeProvider.nullType, |
| 96 _futureNullType = typeProvider.futureNullType, |
| 91 _typeSystem = typeSystem ?? new TypeSystemImpl() { | 97 _typeSystem = typeSystem ?? new TypeSystemImpl() { |
| 92 inDeprecatedMember = _currentLibrary.isDeprecated; | 98 inDeprecatedMember = _currentLibrary.isDeprecated; |
| 93 } | 99 } |
| 94 | 100 |
| 95 @override | 101 @override |
| 96 Object visitAnnotation(Annotation node) { | 102 Object visitAnnotation(Annotation node) { |
| 97 if (node.elementAnnotation?.isFactory == true) { | 103 if (node.elementAnnotation?.isFactory == true) { |
| 98 AstNode parent = node.parent; | 104 AstNode parent = node.parent; |
| 99 if (parent is MethodDeclaration) { | 105 if (parent is MethodDeclaration) { |
| 100 _checkForInvalidFactory(parent); | 106 _checkForInvalidFactory(parent); |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 268 _checkForMissingReturn(node.returnType, node.body); | 274 _checkForMissingReturn(node.returnType, node.body); |
| 269 _checkForUnnecessaryNoSuchMethod(node); | 275 _checkForUnnecessaryNoSuchMethod(node); |
| 270 return super.visitMethodDeclaration(node); | 276 return super.visitMethodDeclaration(node); |
| 271 } finally { | 277 } finally { |
| 272 inDeprecatedMember = wasInDeprecatedMember; | 278 inDeprecatedMember = wasInDeprecatedMember; |
| 273 } | 279 } |
| 274 } | 280 } |
| 275 | 281 |
| 276 @override | 282 @override |
| 277 Object visitMethodInvocation(MethodInvocation node) { | 283 Object visitMethodInvocation(MethodInvocation node) { |
| 278 _checkForCanBeNullAfterNullAware(node.realTarget, node.operator); | 284 _checkForCanBeNullAfterNullAware( |
| 285 node.realTarget, node.operator, null, node.methodName); |
| 279 DartType staticInvokeType = node.staticInvokeType; | 286 DartType staticInvokeType = node.staticInvokeType; |
| 280 if (staticInvokeType is InterfaceType) { | 287 if (staticInvokeType is InterfaceType) { |
| 281 MethodElement methodElement = staticInvokeType.lookUpMethod( | 288 MethodElement methodElement = staticInvokeType.lookUpMethod( |
| 282 FunctionElement.CALL_METHOD_NAME, _currentLibrary); | 289 FunctionElement.CALL_METHOD_NAME, _currentLibrary); |
| 283 _checkForDeprecatedMemberUse(methodElement, node); | 290 _checkForDeprecatedMemberUse(methodElement, node); |
| 284 } | 291 } |
| 285 return super.visitMethodInvocation(node); | 292 return super.visitMethodInvocation(node); |
| 286 } | 293 } |
| 287 | 294 |
| 288 @override | 295 @override |
| 289 Object visitPostfixExpression(PostfixExpression node) { | 296 Object visitPostfixExpression(PostfixExpression node) { |
| 290 _checkForDeprecatedMemberUse(node.bestElement, node); | 297 _checkForDeprecatedMemberUse(node.bestElement, node); |
| 291 return super.visitPostfixExpression(node); | 298 return super.visitPostfixExpression(node); |
| 292 } | 299 } |
| 293 | 300 |
| 294 @override | 301 @override |
| 295 Object visitPrefixExpression(PrefixExpression node) { | 302 Object visitPrefixExpression(PrefixExpression node) { |
| 296 _checkForDeprecatedMemberUse(node.bestElement, node); | 303 _checkForDeprecatedMemberUse(node.bestElement, node); |
| 297 return super.visitPrefixExpression(node); | 304 return super.visitPrefixExpression(node); |
| 298 } | 305 } |
| 299 | 306 |
| 300 @override | 307 @override |
| 301 Object visitPropertyAccess(PropertyAccess node) { | 308 Object visitPropertyAccess(PropertyAccess node) { |
| 302 _checkForCanBeNullAfterNullAware(node.realTarget, node.operator); | 309 _checkForCanBeNullAfterNullAware( |
| 310 node.realTarget, node.operator, node.propertyName, null); |
| 303 return super.visitPropertyAccess(node); | 311 return super.visitPropertyAccess(node); |
| 304 } | 312 } |
| 305 | 313 |
| 306 @override | 314 @override |
| 307 Object visitRedirectingConstructorInvocation( | 315 Object visitRedirectingConstructorInvocation( |
| 308 RedirectingConstructorInvocation node) { | 316 RedirectingConstructorInvocation node) { |
| 309 _checkForDeprecatedMemberUse(node.staticElement, node); | 317 _checkForDeprecatedMemberUse(node.staticElement, node); |
| 310 return super.visitRedirectingConstructorInvocation(node); | 318 return super.visitRedirectingConstructorInvocation(node); |
| 311 } | 319 } |
| 312 | 320 |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 bool problemReported = false; | 522 bool problemReported = false; |
| 515 for (Expression argument in argumentList.arguments) { | 523 for (Expression argument in argumentList.arguments) { |
| 516 if (_checkForArgumentTypeNotAssignableForArgument(argument)) { | 524 if (_checkForArgumentTypeNotAssignableForArgument(argument)) { |
| 517 problemReported = true; | 525 problemReported = true; |
| 518 } | 526 } |
| 519 } | 527 } |
| 520 return problemReported; | 528 return problemReported; |
| 521 } | 529 } |
| 522 | 530 |
| 523 /** | 531 /** |
| 524 * Produce a hint if the given [target] could have a value of `null`. | 532 * Produce a hint if the given [target] could have a value of `null`, and |
| 533 * [identifier] is not a name of a getter or a method that exists in the |
| 534 * class [Null]. |
| 525 */ | 535 */ |
| 526 void _checkForCanBeNullAfterNullAware(Expression target, Token operator) { | 536 void _checkForCanBeNullAfterNullAware( |
| 537 Expression target, Token operator, SimpleIdentifier propertyName, SimpleId
entifier methodName) { |
| 527 if (operator?.type == TokenType.QUESTION_PERIOD) { | 538 if (operator?.type == TokenType.QUESTION_PERIOD) { |
| 528 return; | 539 return; |
| 529 } | 540 } |
| 541 bool isNullTypeMember() { |
| 542 if (propertyName != null) { |
| 543 String name = propertyName.name; |
| 544 return _nullType.lookUpGetter(name, _currentLibrary) != null; |
| 545 } |
| 546 if (methodName != null) { |
| 547 String name = methodName.name; |
| 548 return _nullType.lookUpMethod(name, _currentLibrary) != null; |
| 549 } |
| 550 return false; |
| 551 } |
| 552 |
| 530 target = target?.unParenthesized; | 553 target = target?.unParenthesized; |
| 531 if (target is MethodInvocation) { | 554 if (target is MethodInvocation) { |
| 532 if (target.operator?.type == TokenType.QUESTION_PERIOD) { | 555 if (target.operator?.type == TokenType.QUESTION_PERIOD && |
| 556 !isNullTypeMember()) { |
| 533 _errorReporter.reportErrorForNode( | 557 _errorReporter.reportErrorForNode( |
| 534 HintCode.CAN_BE_NULL_AFTER_NULL_AWARE, target); | 558 HintCode.CAN_BE_NULL_AFTER_NULL_AWARE, target); |
| 535 } | 559 } |
| 536 } else if (target is PropertyAccess) { | 560 } else if (target is PropertyAccess) { |
| 537 if (target.operator.type == TokenType.QUESTION_PERIOD) { | 561 if (target.operator.type == TokenType.QUESTION_PERIOD && |
| 562 !isNullTypeMember()) { |
| 538 _errorReporter.reportErrorForNode( | 563 _errorReporter.reportErrorForNode( |
| 539 HintCode.CAN_BE_NULL_AFTER_NULL_AWARE, target); | 564 HintCode.CAN_BE_NULL_AFTER_NULL_AWARE, target); |
| 540 } | 565 } |
| 541 } | 566 } |
| 542 } | 567 } |
| 543 | 568 |
| 544 /** | 569 /** |
| 545 * Given some [Element], look at the associated metadata and report the use of
the member if | 570 * Given some [Element], look at the associated metadata and report the use of
the member if |
| 546 * it is declared as deprecated. | 571 * it is declared as deprecated. |
| 547 * | 572 * |
| (...skipping 10588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11136 return null; | 11161 return null; |
| 11137 } | 11162 } |
| 11138 if (identical(node.staticElement, variable)) { | 11163 if (identical(node.staticElement, variable)) { |
| 11139 if (node.inSetterContext()) { | 11164 if (node.inSetterContext()) { |
| 11140 result = true; | 11165 result = true; |
| 11141 } | 11166 } |
| 11142 } | 11167 } |
| 11143 return null; | 11168 return null; |
| 11144 } | 11169 } |
| 11145 } | 11170 } |
| OLD | NEW |