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.error_verifier; | 5 library analyzer.src.generated.error_verifier; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 import "dart:math" as math; | 8 import "dart:math" as math; |
9 | 9 |
10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
11 import 'package:analyzer/dart/ast/token.dart'; | 11 import 'package:analyzer/dart/ast/token.dart'; |
12 import 'package:analyzer/dart/ast/visitor.dart'; | 12 import 'package:analyzer/dart/ast/visitor.dart'; |
13 import 'package:analyzer/dart/element/element.dart'; | 13 import 'package:analyzer/dart/element/element.dart'; |
14 import 'package:analyzer/dart/element/type.dart'; | 14 import 'package:analyzer/dart/element/type.dart'; |
15 import 'package:analyzer/dart/element/visitor.dart'; | 15 import 'package:analyzer/dart/element/visitor.dart'; |
16 import 'package:analyzer/src/dart/ast/utilities.dart'; | 16 import 'package:analyzer/src/dart/ast/utilities.dart'; |
17 import 'package:analyzer/src/dart/element/element.dart'; | 17 import 'package:analyzer/src/dart/element/element.dart'; |
18 import 'package:analyzer/src/dart/element/member.dart'; | 18 import 'package:analyzer/src/dart/element/member.dart'; |
19 import 'package:analyzer/src/dart/element/type.dart'; | 19 import 'package:analyzer/src/dart/element/type.dart'; |
20 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; | 20 import 'package:analyzer/src/dart/resolver/inheritance_manager.dart'; |
| 21 import 'package:analyzer/src/error/pending_error.dart'; |
21 import 'package:analyzer/src/generated/constant.dart'; | 22 import 'package:analyzer/src/generated/constant.dart'; |
22 import 'package:analyzer/src/generated/element_resolver.dart'; | 23 import 'package:analyzer/src/generated/element_resolver.dart'; |
23 import 'package:analyzer/src/generated/engine.dart'; | 24 import 'package:analyzer/src/generated/engine.dart'; |
24 import 'package:analyzer/src/generated/error.dart'; | 25 import 'package:analyzer/src/generated/error.dart'; |
25 import 'package:analyzer/src/generated/java_engine.dart'; | 26 import 'package:analyzer/src/generated/java_engine.dart'; |
26 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode; | 27 import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode; |
27 import 'package:analyzer/src/generated/resolver.dart'; | 28 import 'package:analyzer/src/generated/resolver.dart'; |
28 import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary; | 29 import 'package:analyzer/src/generated/sdk.dart' show DartSdk, SdkLibrary; |
| 30 import 'package:analyzer/src/generated/source.dart'; |
29 import 'package:analyzer/src/generated/utilities_dart.dart'; | 31 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 32 import 'package:analyzer/src/task/dart.dart'; |
30 import 'package:analyzer/src/task/strong/info.dart' show StaticInfo; | 33 import 'package:analyzer/src/task/strong/info.dart' show StaticInfo; |
31 | 34 |
32 /** | 35 /** |
33 * A visitor used to traverse an AST structure looking for additional errors and | 36 * A visitor used to traverse an AST structure looking for additional errors and |
34 * warnings not covered by the parser and resolver. | 37 * warnings not covered by the parser and resolver. |
35 */ | 38 */ |
36 class ErrorVerifier extends RecursiveAstVisitor<Object> { | 39 class ErrorVerifier extends RecursiveAstVisitor<Object> { |
37 /** | 40 /** |
38 * Static final string with value `"getter "` used in the construction of the | 41 * Static final string with value `"getter "` used in the construction of the |
39 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE], and | 42 * [StaticWarningCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_ONE], and |
(...skipping 782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
822 Object visitInstanceCreationExpression(InstanceCreationExpression node) { | 825 Object visitInstanceCreationExpression(InstanceCreationExpression node) { |
823 bool wasInConstInstanceCreation = _isInConstInstanceCreation; | 826 bool wasInConstInstanceCreation = _isInConstInstanceCreation; |
824 _isInConstInstanceCreation = node.isConst; | 827 _isInConstInstanceCreation = node.isConst; |
825 try { | 828 try { |
826 ConstructorName constructorName = node.constructorName; | 829 ConstructorName constructorName = node.constructorName; |
827 TypeName typeName = constructorName.type; | 830 TypeName typeName = constructorName.type; |
828 DartType type = typeName.type; | 831 DartType type = typeName.type; |
829 if (type is InterfaceType) { | 832 if (type is InterfaceType) { |
830 _checkForConstOrNewWithAbstractClass(node, typeName, type); | 833 _checkForConstOrNewWithAbstractClass(node, typeName, type); |
831 _checkForConstOrNewWithEnum(node, typeName, type); | 834 _checkForConstOrNewWithEnum(node, typeName, type); |
832 _checkForMissingRequiredParam( | |
833 node.staticElement?.type, node.argumentList, node.constructorName); | |
834 if (_isInConstInstanceCreation) { | 835 if (_isInConstInstanceCreation) { |
835 _checkForConstWithNonConst(node); | 836 _checkForConstWithNonConst(node); |
836 _checkForConstWithUndefinedConstructor( | 837 _checkForConstWithUndefinedConstructor( |
837 node, constructorName, typeName); | 838 node, constructorName, typeName); |
838 _checkForConstWithTypeParameters(typeName); | 839 _checkForConstWithTypeParameters(typeName); |
839 _checkForConstDeferredClass(node, constructorName, typeName); | 840 _checkForConstDeferredClass(node, constructorName, typeName); |
840 } else { | 841 } else { |
841 _checkForNewWithUndefinedConstructor(node, constructorName, typeName); | 842 _checkForNewWithUndefinedConstructor(node, constructorName, typeName); |
842 } | 843 } |
843 } | 844 } |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
935 Object visitMethodInvocation(MethodInvocation node) { | 936 Object visitMethodInvocation(MethodInvocation node) { |
936 Expression target = node.realTarget; | 937 Expression target = node.realTarget; |
937 SimpleIdentifier methodName = node.methodName; | 938 SimpleIdentifier methodName = node.methodName; |
938 if (target != null) { | 939 if (target != null) { |
939 ClassElement typeReference = ElementResolver.getTypeReference(target); | 940 ClassElement typeReference = ElementResolver.getTypeReference(target); |
940 _checkForStaticAccessToInstanceMember(typeReference, methodName); | 941 _checkForStaticAccessToInstanceMember(typeReference, methodName); |
941 _checkForInstanceAccessToStaticMember(typeReference, methodName); | 942 _checkForInstanceAccessToStaticMember(typeReference, methodName); |
942 } else { | 943 } else { |
943 _checkForUnqualifiedReferenceToNonLocalStaticMember(methodName); | 944 _checkForUnqualifiedReferenceToNonLocalStaticMember(methodName); |
944 } | 945 } |
945 _checkForMissingRequiredParam( | |
946 node.staticInvokeType, node.argumentList, methodName); | |
947 _checkTypeArguments( | 946 _checkTypeArguments( |
948 node.methodName.staticElement, node.typeArguments, target?.staticType); | 947 node.methodName.staticElement, node.typeArguments, target?.staticType); |
949 return super.visitMethodInvocation(node); | 948 return super.visitMethodInvocation(node); |
950 } | 949 } |
951 | 950 |
952 @override | 951 @override |
953 Object visitNativeClause(NativeClause node) { | 952 Object visitNativeClause(NativeClause node) { |
954 // TODO(brianwilkerson) Figure out the right rule for when 'native' is | 953 // TODO(brianwilkerson) Figure out the right rule for when 'native' is |
955 // allowed. | 954 // allowed. |
956 if (!_isInSystemLibrary) { | 955 if (!_isInSystemLibrary) { |
(...skipping 3282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4239 void _checkForMissingJSLibAnnotation(Annotation node) { | 4238 void _checkForMissingJSLibAnnotation(Annotation node) { |
4240 if (node.elementAnnotation?.isJS ?? false) { | 4239 if (node.elementAnnotation?.isJS ?? false) { |
4241 Element element = ElementLocator.locate(node.parent); | 4240 Element element = ElementLocator.locate(node.parent); |
4242 if (element?.library?.isJS != true) { | 4241 if (element?.library?.isJS != true) { |
4243 _errorReporter.reportErrorForNode( | 4242 _errorReporter.reportErrorForNode( |
4244 HintCode.MISSING_JS_LIB_ANNOTATION, node, [element.name]); | 4243 HintCode.MISSING_JS_LIB_ANNOTATION, node, [element.name]); |
4245 } | 4244 } |
4246 } | 4245 } |
4247 } | 4246 } |
4248 | 4247 |
4249 void _checkForMissingRequiredParam( | |
4250 DartType type, ArgumentList argumentList, AstNode node) { | |
4251 if (type is FunctionType) { | |
4252 List<ParameterElement> parameters = type.parameters; | |
4253 for (ParameterElement param in parameters) { | |
4254 if (param.parameterKind == ParameterKind.NAMED) { | |
4255 ElementAnnotationImpl annotation = _getRequiredAnnotation(param); | |
4256 if (annotation != null) { | |
4257 String paramName = param.name; | |
4258 if (!_containsNamedExpression(argumentList, paramName)) { | |
4259 DartObject constantValue = annotation.constantValue; | |
4260 String reason = | |
4261 constantValue?.getField('reason')?.toStringValue(); | |
4262 if (reason != null) { | |
4263 _errorReporter.reportErrorForNode( | |
4264 HintCode.MISSING_REQUIRED_PARAM_WITH_DETAILS, | |
4265 node, | |
4266 [paramName, reason]); | |
4267 } else { | |
4268 _errorReporter.reportErrorForNode( | |
4269 HintCode.MISSING_REQUIRED_PARAM, node, [paramName]); | |
4270 } | |
4271 } | |
4272 } | |
4273 } | |
4274 } | |
4275 } | |
4276 } | |
4277 | |
4278 /** | 4248 /** |
4279 * Verify that the given function [body] does not contain return statements | 4249 * Verify that the given function [body] does not contain return statements |
4280 * that both have and do not have return values. | 4250 * that both have and do not have return values. |
4281 * | 4251 * |
4282 * See [StaticWarningCode.MIXED_RETURN_TYPES]. | 4252 * See [StaticWarningCode.MIXED_RETURN_TYPES]. |
4283 */ | 4253 */ |
4284 void _checkForMixedReturns(BlockFunctionBody body) { | 4254 void _checkForMixedReturns(BlockFunctionBody body) { |
4285 if (_hasReturnWithoutValue) { | 4255 if (_hasReturnWithoutValue) { |
4286 return; | 4256 return; |
4287 } | 4257 } |
(...skipping 1466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5754 } | 5724 } |
5755 } | 5725 } |
5756 DartType staticReturnType = getStaticType(returnExpression); | 5726 DartType staticReturnType = getStaticType(returnExpression); |
5757 if (staticReturnType != null && _enclosingFunction.isAsynchronous) { | 5727 if (staticReturnType != null && _enclosingFunction.isAsynchronous) { |
5758 return _typeProvider.futureType.instantiate( | 5728 return _typeProvider.futureType.instantiate( |
5759 <DartType>[staticReturnType.flattenFutures(_typeSystem)]); | 5729 <DartType>[staticReturnType.flattenFutures(_typeSystem)]); |
5760 } | 5730 } |
5761 return staticReturnType; | 5731 return staticReturnType; |
5762 } | 5732 } |
5763 | 5733 |
5764 bool _containsNamedExpression(ArgumentList args, String name) { | |
5765 for (Expression expression in args.arguments) { | |
5766 if (expression is NamedExpression) { | |
5767 if (expression.name.label.name == name) { | |
5768 return true; | |
5769 } | |
5770 } | |
5771 } | |
5772 return false; | |
5773 } | |
5774 | |
5775 bool _expressionIsAssignableAtType(Expression expression, | 5734 bool _expressionIsAssignableAtType(Expression expression, |
5776 DartType actualStaticType, DartType expectedStaticType) { | 5735 DartType actualStaticType, DartType expectedStaticType) { |
5777 bool concrete = | 5736 bool concrete = |
5778 _options.strongMode && StaticInfo.isKnownFunction(expression); | 5737 _options.strongMode && StaticInfo.isKnownFunction(expression); |
5779 if (concrete) { | 5738 if (concrete) { |
5780 actualStaticType = | 5739 actualStaticType = |
5781 _typeSystem.typeToConcreteType(_typeProvider, actualStaticType); | 5740 _typeSystem.typeToConcreteType(_typeProvider, actualStaticType); |
5782 // TODO(leafp): Move the Downcast functionality here. | 5741 // TODO(leafp): Move the Downcast functionality here. |
5783 // TODO(leafp): Support strict downcasts | 5742 // TODO(leafp): Support strict downcasts |
5784 } | 5743 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5858 } | 5817 } |
5859 | 5818 |
5860 ClassElement classElement = | 5819 ClassElement classElement = |
5861 member.getAncestor((element) => element is ClassElement); | 5820 member.getAncestor((element) => element is ClassElement); |
5862 if (classElement == null) { | 5821 if (classElement == null) { |
5863 return null; | 5822 return null; |
5864 } | 5823 } |
5865 return _inheritanceManager.lookupInheritance(classElement, member.name); | 5824 return _inheritanceManager.lookupInheritance(classElement, member.name); |
5866 } | 5825 } |
5867 | 5826 |
5868 ElementAnnotationImpl _getRequiredAnnotation(ParameterElement param) => param | |
5869 .metadata | |
5870 .firstWhere((ElementAnnotation e) => e.isRequired, orElse: () => null); | |
5871 | |
5872 /** | 5827 /** |
5873 * Return the type of the first and only parameter of the given [setter]. | 5828 * Return the type of the first and only parameter of the given [setter]. |
5874 */ | 5829 */ |
5875 DartType _getSetterType(PropertyAccessorElement setter) { | 5830 DartType _getSetterType(PropertyAccessorElement setter) { |
5876 // Get the parameters for MethodDeclaration or FunctionDeclaration | 5831 // Get the parameters for MethodDeclaration or FunctionDeclaration |
5877 List<ParameterElement> setterParameters = setter.parameters; | 5832 List<ParameterElement> setterParameters = setter.parameters; |
5878 // If there are no setter parameters, return no type. | 5833 // If there are no setter parameters, return no type. |
5879 if (setterParameters.length == 0) { | 5834 if (setterParameters.length == 0) { |
5880 return null; | 5835 return null; |
5881 } | 5836 } |
(...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6222 // type arguments | 6177 // type arguments |
6223 if (type is InterfaceType) { | 6178 if (type is InterfaceType) { |
6224 for (DartType typeArgument in type.typeArguments) { | 6179 for (DartType typeArgument in type.typeArguments) { |
6225 _addTypeToCheck(typeArgument); | 6180 _addTypeToCheck(typeArgument); |
6226 } | 6181 } |
6227 } | 6182 } |
6228 } | 6183 } |
6229 } | 6184 } |
6230 | 6185 |
6231 /** | 6186 /** |
| 6187 * A class used to compute a list of the constants whose value needs to be |
| 6188 * computed before errors can be computed by the [VerifyUnitTask]. |
| 6189 */ |
| 6190 class RequiredConstantsComputer extends RecursiveAstVisitor { |
| 6191 /** |
| 6192 * The source with which any pending errors will be associated. |
| 6193 */ |
| 6194 final Source source; |
| 6195 |
| 6196 /** |
| 6197 * A list of the pending errors that were computed. |
| 6198 */ |
| 6199 final List<PendingError> pendingErrors = <PendingError>[]; |
| 6200 |
| 6201 /** |
| 6202 * A list of the constants whose value needs to be computed before the pending |
| 6203 * errors can be used to compute an analysis error. |
| 6204 */ |
| 6205 final List<ConstantEvaluationTarget> requiredConstants = |
| 6206 <ConstantEvaluationTarget>[]; |
| 6207 |
| 6208 /** |
| 6209 * Initialize a newly created computer to compute required constants within |
| 6210 * the given [source]. |
| 6211 */ |
| 6212 RequiredConstantsComputer(this.source); |
| 6213 |
| 6214 @override |
| 6215 Object visitInstanceCreationExpression(InstanceCreationExpression node) { |
| 6216 DartType type = node.constructorName.type.type; |
| 6217 if (type is InterfaceType) { |
| 6218 _checkForMissingRequiredParam( |
| 6219 node.staticElement?.type, node.argumentList, node.constructorName); |
| 6220 } |
| 6221 return super.visitInstanceCreationExpression(node); |
| 6222 } |
| 6223 |
| 6224 @override |
| 6225 Object visitMethodInvocation(MethodInvocation node) { |
| 6226 _checkForMissingRequiredParam( |
| 6227 node.staticInvokeType, node.argumentList, node.methodName); |
| 6228 return super.visitMethodInvocation(node); |
| 6229 } |
| 6230 |
| 6231 void _checkForMissingRequiredParam( |
| 6232 DartType type, ArgumentList argumentList, AstNode node) { |
| 6233 if (type is FunctionType) { |
| 6234 for (ParameterElement parameter in type.parameters) { |
| 6235 if (parameter.parameterKind == ParameterKind.NAMED) { |
| 6236 ElementAnnotationImpl annotation = _getRequiredAnnotation(parameter); |
| 6237 if (annotation != null) { |
| 6238 String parameterName = parameter.name; |
| 6239 if (!_containsNamedExpression(argumentList, parameterName)) { |
| 6240 requiredConstants.add(annotation); |
| 6241 pendingErrors.add(new PendingMissingRequiredParameterError( |
| 6242 source, parameterName, node, annotation)); |
| 6243 } |
| 6244 } |
| 6245 } |
| 6246 } |
| 6247 } |
| 6248 } |
| 6249 |
| 6250 bool _containsNamedExpression(ArgumentList args, String name) { |
| 6251 NodeList<Expression> arguments = args.arguments; |
| 6252 for (int i = arguments.length - 1; i >= 0; i--) { |
| 6253 Expression expression = arguments[i]; |
| 6254 if (expression is NamedExpression) { |
| 6255 if (expression.name.label.name == name) { |
| 6256 return true; |
| 6257 } |
| 6258 } |
| 6259 } |
| 6260 return false; |
| 6261 } |
| 6262 |
| 6263 ElementAnnotationImpl _getRequiredAnnotation(ParameterElement param) => param |
| 6264 .metadata |
| 6265 .firstWhere((ElementAnnotation e) => e.isRequired, orElse: () => null); |
| 6266 } |
| 6267 |
| 6268 /** |
6232 * Recursively visits an AST, looking for method invocations. | 6269 * Recursively visits an AST, looking for method invocations. |
6233 */ | 6270 */ |
6234 class _InvocationCollector extends RecursiveAstVisitor { | 6271 class _InvocationCollector extends RecursiveAstVisitor { |
6235 final List<String> superCalls = <String>[]; | 6272 final List<String> superCalls = <String>[]; |
6236 | 6273 |
6237 @override | 6274 @override |
6238 visitMethodInvocation(MethodInvocation node) { | 6275 visitMethodInvocation(MethodInvocation node) { |
6239 if (node.target is SuperExpression) { | 6276 if (node.target is SuperExpression) { |
6240 superCalls.add(node.methodName.name); | 6277 superCalls.add(node.methodName.name); |
6241 } | 6278 } |
6242 } | 6279 } |
6243 } | 6280 } |
OLD | NEW |