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.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 |