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 engine.resolver; | 5 library engine.resolver; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 | 8 |
9 import 'package:analyzer/src/generated/scanner.dart'; | 9 import 'package:analyzer/src/generated/scanner.dart'; |
10 | 10 |
(...skipping 5834 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5845 */ | 5845 */ |
5846 ExecutableElement lookupMember(ClassElement classElt, String memberName) { | 5846 ExecutableElement lookupMember(ClassElement classElt, String memberName) { |
5847 ExecutableElement element = _lookupMemberInClass(classElt, memberName); | 5847 ExecutableElement element = _lookupMemberInClass(classElt, memberName); |
5848 if (element != null) { | 5848 if (element != null) { |
5849 return element; | 5849 return element; |
5850 } | 5850 } |
5851 return lookupInheritance(classElt, memberName); | 5851 return lookupInheritance(classElt, memberName); |
5852 } | 5852 } |
5853 | 5853 |
5854 /** | 5854 /** |
5855 * Given some [InterfaceType] and some member name, this returns the | |
5856 * [FunctionType] of the [ExecutableElement] that the | |
5857 * class either declares itself, or inherits, that has the member name, if no member is inherited | |
5858 * `null` is returned. The returned [FunctionType] has all type | |
5859 * parameters substituted with corresponding type arguments from the given [In terfaceType]. | |
5860 * | |
5861 * @param interfaceType the interface type to query | |
5862 * @param memberName the name of the executable element to find and return | |
5863 * @return the member's function type, or `null` if no such member exists | |
5864 */ | |
5865 FunctionType lookupMemberType( | |
5866 InterfaceType interfaceType, String memberName) { | |
5867 ExecutableElement iteratorMember = | |
5868 lookupMember(interfaceType.element, memberName); | |
5869 if (iteratorMember == null) { | |
5870 return null; | |
5871 } | |
5872 return substituteTypeArgumentsInMemberFromInheritance( | |
5873 iteratorMember.type, memberName, interfaceType); | |
5874 } | |
5875 | |
5876 /** | |
5877 * Determine the set of methods which is overridden by the given class member. If no member is | 5855 * Determine the set of methods which is overridden by the given class member. If no member is |
5878 * inherited, an empty list is returned. If one of the inherited members is a | 5856 * inherited, an empty list is returned. If one of the inherited members is a |
5879 * [MultiplyInheritedExecutableElement], then it is expanded into its constitu ent inherited | 5857 * [MultiplyInheritedExecutableElement], then it is expanded into its constitu ent inherited |
5880 * elements. | 5858 * elements. |
5881 * | 5859 * |
5882 * @param classElt the class to query | 5860 * @param classElt the class to query |
5883 * @param memberName the name of the class member to query | 5861 * @param memberName the name of the class member to query |
5884 * @return a list of overridden methods | 5862 * @return a list of overridden methods |
5885 */ | 5863 */ |
5886 List<ExecutableElement> lookupOverrides( | 5864 List<ExecutableElement> lookupOverrides( |
(...skipping 18 matching lines...) Expand all Loading... | |
5905 } else { | 5883 } else { |
5906 result.add(overriddenElement); | 5884 result.add(overriddenElement); |
5907 } | 5885 } |
5908 } | 5886 } |
5909 } | 5887 } |
5910 } | 5888 } |
5911 return result; | 5889 return result; |
5912 } | 5890 } |
5913 | 5891 |
5914 /** | 5892 /** |
5915 * This method takes some inherited [FunctionType], and resolves all the param eterized types | |
5916 * in the function type, dependent on the class in which it is being overridde n. | |
5917 * | |
5918 * @param baseFunctionType the function type that is being overridden | |
5919 * @param memberName the name of the member, this is used to lookup the inheri tance path of the | |
5920 * override | |
5921 * @param definingType the type that is overriding the member | |
5922 * @return the passed function type with any parameterized types substituted | |
5923 */ | |
5924 FunctionType substituteTypeArgumentsInMemberFromInheritance( | |
5925 FunctionType baseFunctionType, | |
5926 String memberName, | |
5927 InterfaceType definingType) { | |
5928 // if the baseFunctionType is null, or does not have any parameters, | |
5929 // return it. | |
5930 if (baseFunctionType == null || | |
5931 baseFunctionType.typeArguments.length == 0) { | |
5932 return baseFunctionType; | |
5933 } | |
5934 // First, generate the path from the defining type to the overridden member | |
5935 Queue<InterfaceType> inheritancePath = new Queue<InterfaceType>(); | |
5936 _computeInheritancePath(inheritancePath, definingType, memberName); | |
5937 if (inheritancePath == null || inheritancePath.isEmpty) { | |
5938 // TODO(jwren) log analysis engine error | |
5939 return baseFunctionType; | |
5940 } | |
5941 FunctionType functionTypeToReturn = baseFunctionType; | |
5942 // loop backward through the list substituting as we go: | |
5943 while (!inheritancePath.isEmpty) { | |
5944 InterfaceType lastType = inheritancePath.removeLast(); | |
5945 List<DartType> parameterTypes = lastType.element.type.typeArguments; | |
5946 List<DartType> argumentTypes = lastType.typeArguments; | |
5947 functionTypeToReturn = | |
5948 functionTypeToReturn.substitute2(argumentTypes, parameterTypes); | |
5949 } | |
5950 return functionTypeToReturn; | |
5951 } | |
5952 | |
5953 /** | |
5954 * Compute and return a mapping between the set of all string names of the mem bers inherited from | 5893 * Compute and return a mapping between the set of all string names of the mem bers inherited from |
5955 * the passed [ClassElement] superclass hierarchy, and the associated | 5894 * the passed [ClassElement] superclass hierarchy, and the associated |
5956 * [ExecutableElement]. | 5895 * [ExecutableElement]. |
5957 * | 5896 * |
5958 * @param classElt the class element to query | 5897 * @param classElt the class element to query |
5959 * @param visitedClasses a set of visited classes passed back into this method when it calls | 5898 * @param visitedClasses a set of visited classes passed back into this method when it calls |
5960 * itself recursively | 5899 * itself recursively |
5961 * @return a mapping between the set of all string names of the members inheri ted from the passed | 5900 * @return a mapping between the set of all string names of the members inheri ted from the passed |
5962 * [ClassElement] superclass hierarchy, and the associated [Executable Element] | 5901 * [ClassElement] superclass hierarchy, and the associated [Executable Element] |
5963 */ | 5902 */ |
(...skipping 5621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11585 * The given expression is the expression used to compute the iterator for a | 11524 * The given expression is the expression used to compute the iterator for a |
11586 * for-each statement. Attempt to compute the type of objects that will be | 11525 * for-each statement. Attempt to compute the type of objects that will be |
11587 * assigned to the loop variable and return that type. Return `null` if the | 11526 * assigned to the loop variable and return that type. Return `null` if the |
11588 * type could not be determined. The [iteratorExpression] is the expression | 11527 * type could not be determined. The [iteratorExpression] is the expression |
11589 * that will return the Iterable being iterated over. | 11528 * that will return the Iterable being iterated over. |
11590 */ | 11529 */ |
11591 DartType _getIteratorElementType(Expression iteratorExpression) { | 11530 DartType _getIteratorElementType(Expression iteratorExpression) { |
11592 DartType expressionType = iteratorExpression.bestType; | 11531 DartType expressionType = iteratorExpression.bestType; |
11593 if (expressionType is InterfaceType) { | 11532 if (expressionType is InterfaceType) { |
11594 InterfaceType interfaceType = expressionType; | 11533 InterfaceType interfaceType = expressionType; |
11595 FunctionType iteratorFunction = | 11534 PropertyAccessorElement iteratorFunction = |
11596 _inheritanceManager.lookupMemberType(interfaceType, "iterator"); | 11535 interfaceType.lookUpInheritedGetter("iterator"); |
11597 if (iteratorFunction == null) { | 11536 if (iteratorFunction == null) { |
11598 // TODO(brianwilkerson) Should we report this error? | 11537 // TODO(brianwilkerson) Should we report this error? |
11599 return null; | 11538 return null; |
11600 } | 11539 } |
11601 DartType iteratorType = iteratorFunction.returnType; | 11540 DartType iteratorType = iteratorFunction.returnType; |
11602 if (iteratorType is InterfaceType) { | 11541 if (iteratorType is InterfaceType) { |
11603 InterfaceType iteratorInterfaceType = iteratorType; | 11542 InterfaceType iteratorInterfaceType = iteratorType; |
11604 FunctionType currentFunction = _inheritanceManager.lookupMemberType( | 11543 PropertyAccessorElement currentFunction = |
11605 iteratorInterfaceType, "current"); | 11544 iteratorInterfaceType.lookUpInheritedGetter("current"); |
11606 if (currentFunction == null) { | 11545 if (currentFunction == null) { |
11607 // TODO(brianwilkerson) Should we report this error? | 11546 // TODO(brianwilkerson) Should we report this error? |
11608 return null; | 11547 return null; |
11609 } | 11548 } |
11610 return currentFunction.returnType; | 11549 return currentFunction.returnType; |
11611 } | 11550 } |
11612 } | 11551 } |
11613 return null; | 11552 return null; |
11614 } | 11553 } |
11615 | 11554 |
11616 /** | 11555 /** |
11617 * The given expression is the expression used to compute the stream for an | 11556 * The given expression is the expression used to compute the stream for an |
11618 * asyncronous for-each statement. Attempt to compute the type of objects that | 11557 * asynchronous for-each statement. Attempt to compute the type of objects |
11619 * will be assigned to the loop variable and return that type. Return `null` | 11558 * that will be assigned to the loop variable and return that type. |
11620 * if the type could not be determined. The [streamExpression] is the | 11559 * Return `null` if the type could not be determined. The [streamExpression] |
11621 * expression that will return the stream being iterated over. | 11560 * is the expression that will return the stream being iterated over. |
11622 */ | 11561 */ |
11623 DartType _getStreamElementType(Expression streamExpression) { | 11562 DartType _getStreamElementType(Expression streamExpression) { |
11624 DartType streamType = streamExpression.bestType; | 11563 DartType streamType = streamExpression.bestType; |
11625 if (streamType is InterfaceType) { | 11564 if (streamType is InterfaceType) { |
11626 FunctionType listenFunction = | 11565 MethodElement listenFunction = streamType.lookUpInheritedMethod("listen"); |
11627 _inheritanceManager.lookupMemberType(streamType, "listen"); | |
11628 if (listenFunction == null) { | 11566 if (listenFunction == null) { |
11629 return null; | 11567 return null; |
11630 } | 11568 } |
11631 List<ParameterElement> listenParameters = listenFunction.parameters; | 11569 List<ParameterElement> listenParameters = listenFunction.parameters; |
11632 if (listenParameters == null || listenParameters.length < 1) { | 11570 if (listenParameters == null || listenParameters.length < 1) { |
11633 return null; | 11571 return null; |
11634 } | 11572 } |
11635 DartType onDataType = listenParameters[0].type; | 11573 DartType onDataType = listenParameters[0].type; |
11636 if (onDataType is FunctionType) { | 11574 if (onDataType is FunctionType) { |
11637 List<ParameterElement> onDataParameters = onDataType.parameters; | 11575 List<ParameterElement> onDataParameters = onDataType.parameters; |
11638 if (onDataParameters == null || onDataParameters.length < 1) { | 11576 if (onDataParameters == null || onDataParameters.isEmpty) { |
11639 return null; | 11577 return null; |
11640 } | 11578 } |
11641 DartType eventType = onDataParameters[0].type; | 11579 return onDataParameters[0].type; |
11642 // TODO(paulberry): checking that typeParameters.isNotEmpty is a | |
11643 // band-aid fix for dartbug.com/24191. Figure out what the correct | |
11644 // logic should be. | |
11645 if (streamType.typeParameters.isNotEmpty && | |
11646 eventType.element == streamType.typeParameters[0]) { | |
11647 return streamType.typeArguments[0]; | |
11648 } | |
11649 } | 11580 } |
11650 } | 11581 } |
11651 return null; | 11582 return null; |
11652 } | 11583 } |
11653 | 11584 |
11654 /** | 11585 /** |
11655 * If given "mayBeClosure" is [FunctionExpression] without explicit parameters types and its | 11586 * If given "mayBeClosure" is [FunctionExpression] without explicit parameters types and its |
11656 * required type is [FunctionType], then infer parameters types from [Function Type]. | 11587 * required type is [FunctionType], then infer parameters types from [Function Type]. |
11657 */ | 11588 */ |
11658 void _inferFunctionExpressionParametersTypes( | 11589 void _inferFunctionExpressionParametersTypes( |
(...skipping 1215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
12874 return false; | 12805 return false; |
12875 } | 12806 } |
12876 | 12807 |
12877 @override | 12808 @override |
12878 bool isSubtypeOf(DartType leftType, DartType rightType) { | 12809 bool isSubtypeOf(DartType leftType, DartType rightType) { |
12879 return _isSubtypeOf(leftType, rightType, null); | 12810 return _isSubtypeOf(leftType, rightType, null); |
12880 } | 12811 } |
12881 | 12812 |
12882 FunctionType _getCallMethodType(DartType t) { | 12813 FunctionType _getCallMethodType(DartType t) { |
12883 if (t is InterfaceType) { | 12814 if (t is InterfaceType) { |
12884 ClassElement element = t.element; | 12815 MethodElement callMethod = t.lookUpInheritedMethod("call"); |
12885 InheritanceManager manager = new InheritanceManager(element.library); | 12816 return callMethod != null ? callMethod.type : null; |
Paul Berry
2015/10/29 16:29:59
Nit: these two lines could be collapsed to:
retur
Jennifer Messerly
2015/10/29 16:36:40
not sure if I can use null aware ops yet
Paul Berry
2015/10/29 16:43:10
There was a brief period where we couldn't use the
Jennifer Messerly
2015/10/29 17:24:33
Ah thank you!
BTW, I didn't intend to reply to yo
| |
12886 FunctionType callType = manager.lookupMemberType(t, "call"); | |
12887 return callType; | |
12888 } | 12817 } |
12889 return null; | 12818 return null; |
12890 } | 12819 } |
12891 | 12820 |
12892 // Given a type t, if t is an interface type with a call method | 12821 // Given a type t, if t is an interface type with a call method |
12893 // defined, return the function type for the call method, otherwise | 12822 // defined, return the function type for the call method, otherwise |
12894 // return null. | 12823 // return null. |
12895 _GuardedSubtypeChecker<DartType> _guard( | 12824 _GuardedSubtypeChecker<DartType> _guard( |
12896 _GuardedSubtypeChecker<DartType> check) { | 12825 _GuardedSubtypeChecker<DartType> check) { |
12897 return (DartType t1, DartType t2, Set<Element> visited) { | 12826 return (DartType t1, DartType t2, Set<Element> visited) { |
(...skipping 3166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
16064 nonFields.add(node); | 15993 nonFields.add(node); |
16065 return null; | 15994 return null; |
16066 } | 15995 } |
16067 | 15996 |
16068 @override | 15997 @override |
16069 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); | 15998 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); |
16070 | 15999 |
16071 @override | 16000 @override |
16072 Object visitWithClause(WithClause node) => null; | 16001 Object visitWithClause(WithClause node) => null; |
16073 } | 16002 } |
OLD | NEW |