Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(124)

Side by Side Diff: pkg/analyzer/lib/src/generated/error_verifier.dart

Issue 1927103002: Add checks for type bounds on generic methods (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698