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'; |
(...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
763 } | 763 } |
764 | 764 |
765 @override | 765 @override |
766 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { | 766 Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) { |
767 Expression functionExpression = node.function; | 767 Expression functionExpression = node.function; |
768 DartType expressionType = functionExpression.staticType; | 768 DartType expressionType = functionExpression.staticType; |
769 if (!_isFunctionType(expressionType)) { | 769 if (!_isFunctionType(expressionType)) { |
770 _errorReporter.reportErrorForNode( | 770 _errorReporter.reportErrorForNode( |
771 StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, | 771 StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, |
772 functionExpression); | 772 functionExpression); |
773 } else if (expressionType is FunctionType) { | |
774 _checkTypeArguments(expressionType.element, node.typeArguments); | |
773 } | 775 } |
774 return super.visitFunctionExpressionInvocation(node); | 776 return super.visitFunctionExpressionInvocation(node); |
775 } | 777 } |
776 | 778 |
777 @override | 779 @override |
778 Object visitFunctionTypeAlias(FunctionTypeAlias node) { | 780 Object visitFunctionTypeAlias(FunctionTypeAlias node) { |
779 _checkForBuiltInIdentifierAsName( | 781 _checkForBuiltInIdentifierAsName( |
780 node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME); | 782 node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPEDEF_NAME); |
781 _checkForDefaultValueInFunctionTypeAlias(node); | 783 _checkForDefaultValueInFunctionTypeAlias(node); |
782 _checkForTypeAliasCannotReferenceItself_function(node); | 784 _checkForTypeAliasCannotReferenceItself_function(node); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
936 SimpleIdentifier methodName = node.methodName; | 938 SimpleIdentifier methodName = node.methodName; |
937 if (target != null) { | 939 if (target != null) { |
938 ClassElement typeReference = ElementResolver.getTypeReference(target); | 940 ClassElement typeReference = ElementResolver.getTypeReference(target); |
939 _checkForStaticAccessToInstanceMember(typeReference, methodName); | 941 _checkForStaticAccessToInstanceMember(typeReference, methodName); |
940 _checkForInstanceAccessToStaticMember(typeReference, methodName); | 942 _checkForInstanceAccessToStaticMember(typeReference, methodName); |
941 } else { | 943 } else { |
942 _checkForUnqualifiedReferenceToNonLocalStaticMember(methodName); | 944 _checkForUnqualifiedReferenceToNonLocalStaticMember(methodName); |
943 } | 945 } |
944 _checkForMissingRequiredParam( | 946 _checkForMissingRequiredParam( |
945 node.staticInvokeType, node.argumentList, methodName); | 947 node.staticInvokeType, node.argumentList, methodName); |
948 _checkTypeArguments( | |
949 node.methodName.staticElement, node.typeArguments, target?.staticType); | |
946 return super.visitMethodInvocation(node); | 950 return super.visitMethodInvocation(node); |
947 } | 951 } |
948 | 952 |
949 @override | 953 @override |
950 Object visitNativeClause(NativeClause node) { | 954 Object visitNativeClause(NativeClause node) { |
951 // TODO(brianwilkerson) Figure out the right rule for when 'native' is | 955 // TODO(brianwilkerson) Figure out the right rule for when 'native' is |
952 // allowed. | 956 // allowed. |
953 if (!_isInSystemLibrary) { | 957 if (!_isInSystemLibrary) { |
954 _errorReporter.reportErrorForNode( | 958 _errorReporter.reportErrorForNode( |
955 ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, node); | 959 ParserErrorCode.NATIVE_CLAUSE_IN_NON_SDK_CODE, node); |
(...skipping 4254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5210 if (element is ClassElement) { | 5214 if (element is ClassElement) { |
5211 // prepare type parameters | 5215 // prepare type parameters |
5212 List<DartType> typeParameters = element.type.typeArguments; | 5216 List<DartType> typeParameters = element.type.typeArguments; |
5213 List<TypeParameterElement> boundingElts = element.typeParameters; | 5217 List<TypeParameterElement> boundingElts = element.typeParameters; |
5214 // iterate over each bounded type parameter and corresponding argument | 5218 // iterate over each bounded type parameter and corresponding argument |
5215 NodeList<TypeName> typeNameArgList = typeName.typeArguments.arguments; | 5219 NodeList<TypeName> typeNameArgList = typeName.typeArguments.arguments; |
5216 List<DartType> typeArguments = (type as InterfaceType).typeArguments; | 5220 List<DartType> typeArguments = (type as InterfaceType).typeArguments; |
5217 int loopThroughIndex = | 5221 int loopThroughIndex = |
5218 math.min(typeNameArgList.length, boundingElts.length); | 5222 math.min(typeNameArgList.length, boundingElts.length); |
5219 | 5223 |
5224 bool shouldSubstitute = typeArguments.length != 0 && | |
5225 typeArguments.length == typeParameters.length; | |
5220 for (int i = 0; i < loopThroughIndex; i++) { | 5226 for (int i = 0; i < loopThroughIndex; i++) { |
5221 TypeName argTypeName = typeNameArgList[i]; | 5227 TypeName argTypeName = typeNameArgList[i]; |
5222 DartType argType = argTypeName.type; | 5228 DartType argType = argTypeName.type; |
5223 DartType boundType = boundingElts[i].bound; | 5229 DartType boundType = boundingElts[i].bound; |
5224 if (argType != null && boundType != null) { | 5230 if (argType != null && boundType != null) { |
5225 if (typeArguments.length != 0 && | 5231 if (shouldSubstitute) { |
5226 typeArguments.length == typeParameters.length) { | |
5227 boundType = boundType.substitute2(typeArguments, typeParameters); | 5232 boundType = boundType.substitute2(typeArguments, typeParameters); |
5228 } | 5233 } |
5229 if (!_typeSystem.isSubtypeOf(argType, boundType)) { | 5234 if (!_typeSystem.isSubtypeOf(argType, boundType)) { |
5230 ErrorCode errorCode; | 5235 ErrorCode errorCode; |
5231 if (_isInConstInstanceCreation) { | 5236 if (_isInConstInstanceCreation) { |
5232 errorCode = | 5237 errorCode = |
5233 CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS; | 5238 CompileTimeErrorCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS; |
5234 } else { | 5239 } else { |
5235 errorCode = | 5240 errorCode = |
5236 StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS; | 5241 StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS; |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5639 for (TypeName interfaceNode in implementsClause.interfaces) { | 5644 for (TypeName interfaceNode in implementsClause.interfaces) { |
5640 if (interfaceNode.type == superType) { | 5645 if (interfaceNode.type == superType) { |
5641 _errorReporter.reportErrorForNode( | 5646 _errorReporter.reportErrorForNode( |
5642 CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, | 5647 CompileTimeErrorCode.IMPLEMENTS_SUPER_CLASS, |
5643 interfaceNode, | 5648 interfaceNode, |
5644 [superType.displayName]); | 5649 [superType.displayName]); |
5645 } | 5650 } |
5646 } | 5651 } |
5647 } | 5652 } |
5648 | 5653 |
5654 /** | |
5655 * Verify that the given [typeArguments] are all within their bounds, as | |
5656 * defined by the given [element]. | |
5657 * | |
5658 * See [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS]. | |
5659 */ | |
5660 void _checkTypeArguments(Element element, TypeArgumentList typeArguments, | |
Jennifer Messerly
2016/04/28 17:30:02
one idea here: FunctionExpressionInvocation and Me
Brian Wilkerson
2016/04/28 20:46:11
Yes, but I was hoping to use the same method for t
| |
5661 [DartType targetType]) { | |
5662 if (element == null || typeArguments == null) { | |
5663 return; | |
5664 } | |
5665 void reportError( | |
5666 TypeName argument, DartType argumentType, DartType parameterType) { | |
5667 _errorReporter.reportTypeErrorForNode( | |
5668 StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, | |
5669 argument, | |
5670 [argumentType, parameterType]); | |
5671 } | |
5672 if (element is FunctionTypedElement) { | |
Jennifer Messerly
2016/04/28 17:30:02
Would it make sense to use the type instead of the
Brian Wilkerson
2016/04/28 20:46:11
Not sure. I'll look into that as part of the next
| |
5673 _checkTypeArgumentsAgainstBounds( | |
5674 element.typeParameters, typeArguments, targetType, reportError); | |
5675 } else if (element is ClassElement) { | |
Jennifer Messerly
2016/04/28 17:30:02
is ClassElement possible here? (it looks like it's
Brian Wilkerson
2016/04/28 20:46:11
Sorry, you're seeing an incomplete thought.
It is
| |
5676 _checkTypeArgumentsAgainstBounds( | |
5677 element.typeParameters, typeArguments, targetType, reportError); | |
5678 } else if (element is ParameterElement || element is LocalVariableElement) { | |
5679 // TODO(brianwilkerson) Implement this case | |
5680 } else { | |
5681 print('Unhandled element type: ${element.runtimeType}'); | |
5682 } | |
5683 } | |
5684 | |
5685 void _checkTypeArgumentsAgainstBounds( | |
5686 List<TypeParameterElement> typeParameters, | |
5687 TypeArgumentList typeArgumentList, | |
5688 DartType targetType, | |
5689 void reportError( | |
5690 TypeName argument, DartType argumentType, DartType parameterType)) { | |
5691 NodeList<TypeName> typeArguments = typeArgumentList.arguments; | |
5692 int argumentsLength = typeArguments.length; | |
5693 int maxIndex = math.min(typeParameters.length, argumentsLength); | |
5694 | |
5695 bool shouldSubstitute = | |
5696 argumentsLength != 0 && argumentsLength == typeParameters.length; | |
5697 List<DartType> argumentTypes = shouldSubstitute | |
5698 ? typeArguments.map((TypeName typeName) => typeName.type).toList() | |
5699 : null; | |
5700 List<DartType> parameterTypes = shouldSubstitute | |
5701 ? typeParameters | |
5702 .map((TypeParameterElement element) => element.type) | |
5703 .toList() | |
5704 : null; | |
5705 for (int i = 0; i < maxIndex; i++) { | |
5706 TypeName argTypeName = typeArguments[i]; | |
5707 DartType argType = argTypeName.type; | |
5708 DartType boundType = typeParameters[i].bound; | |
5709 if (argType != null && boundType != null) { | |
5710 if (targetType is ParameterizedType) { | |
5711 boundType = boundType.substitute2( | |
5712 targetType.typeArguments, | |
5713 targetType.typeParameters | |
5714 .map((TypeParameterElement element) => element.type) | |
5715 .toList()); | |
scheglov
2016/04/28 17:14:52
It looks that this expression can be extracted.
t
Brian Wilkerson
2016/04/28 20:46:11
Done
| |
5716 } | |
5717 if (shouldSubstitute) { | |
5718 boundType = boundType.substitute2(argumentTypes, parameterTypes); | |
5719 } | |
5720 if (!_typeSystem.isSubtypeOf(argType, boundType)) { | |
5721 reportError(argTypeName, argType, boundType); | |
5722 } | |
5723 } | |
5724 } | |
5725 } | |
5726 | |
5649 DartType _computeReturnTypeForMethod(Expression returnExpression) { | 5727 DartType _computeReturnTypeForMethod(Expression returnExpression) { |
5650 // This method should never be called for generators, since generators are | 5728 // This method should never be called for generators, since generators are |
5651 // never allowed to contain return statements with expressions. | 5729 // never allowed to contain return statements with expressions. |
5652 assert(!_inGenerator); | 5730 assert(!_inGenerator); |
5653 if (returnExpression == null) { | 5731 if (returnExpression == null) { |
5654 if (_enclosingFunction.isAsynchronous) { | 5732 if (_enclosingFunction.isAsynchronous) { |
5655 return _typeProvider.futureNullType; | 5733 return _typeProvider.futureNullType; |
5656 } else { | 5734 } else { |
5657 return VoidTypeImpl.instance; | 5735 return VoidTypeImpl.instance; |
5658 } | 5736 } |
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6138 class _InvocationCollector extends RecursiveAstVisitor { | 6216 class _InvocationCollector extends RecursiveAstVisitor { |
6139 final List<String> superCalls = <String>[]; | 6217 final List<String> superCalls = <String>[]; |
6140 | 6218 |
6141 @override | 6219 @override |
6142 visitMethodInvocation(MethodInvocation node) { | 6220 visitMethodInvocation(MethodInvocation node) { |
6143 if (node.target is SuperExpression) { | 6221 if (node.target is SuperExpression) { |
6144 superCalls.add(node.methodName.name); | 6222 superCalls.add(node.methodName.name); |
6145 } | 6223 } |
6146 } | 6224 } |
6147 } | 6225 } |
OLD | NEW |