| 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.element_resolver; | 5 library engine.resolver.element_resolver; |
| 6 | 6 |
| 7 import 'dart:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'ast.dart'; | 9 import 'ast.dart'; |
| 10 import 'element.dart'; | 10 import 'element.dart'; |
| 11 import 'engine.dart'; | 11 import 'engine.dart'; |
| 12 import 'error.dart'; | 12 import 'error.dart'; |
| 13 import 'resolver.dart'; | 13 import 'resolver.dart'; |
| 14 import 'scanner.dart' as sc; | 14 import 'scanner.dart' as sc; |
| 15 import 'utilities_dart.dart'; | 15 import 'utilities_dart.dart'; |
| 16 | 16 |
| 17 /** | 17 /** |
| 18 * Instances of the class `ElementResolver` are used by instances of [ResolverVi
sitor] | 18 * An object used by instances of [ResolverVisitor] to resolve references within |
| 19 * to resolve references within the AST structure to the elements being referenc
ed. The requirements | 19 * the AST structure to the elements being referenced. The requirements for the |
| 20 * for the element resolver are: | 20 * element resolver are: |
| 21 * <ol> | 21 * |
| 22 * * Every [SimpleIdentifier] should be resolved to the element to which it refe
rs. | 22 * 1. Every [SimpleIdentifier] should be resolved to the element to which it |
| 23 * Specifically: | 23 * refers. Specifically: |
| 24 * * An identifier within the declaration of that name should resolve to the ele
ment being | 24 * * An identifier within the declaration of that name should resolve to the |
| 25 * declared. | 25 * element being declared. |
| 26 * * An identifier denoting a prefix should resolve to the element representing
the import that | 26 * * An identifier denoting a prefix should resolve to the element |
| 27 * defines the prefix (an [ImportElement]). | 27 * representing the import that defines the prefix (an [ImportElement]). |
| 28 * * An identifier denoting a variable should resolve to the element representin
g the variable (a | 28 * * An identifier denoting a variable should resolve to the element |
| 29 * [VariableElement]). | 29 * representing the variable (a [VariableElement]). |
| 30 * * An identifier denoting a parameter should resolve to the element representi
ng the parameter | 30 * * An identifier denoting a parameter should resolve to the element |
| 31 * (a [ParameterElement]). | 31 * representing the parameter (a [ParameterElement]). |
| 32 * * An identifier denoting a field should resolve to the element representing t
he getter or | 32 * * An identifier denoting a field should resolve to the element |
| 33 * setter being invoked (a [PropertyAccessorElement]). | 33 * representing the getter or setter being invoked (a |
| 34 * * An identifier denoting the name of a method or function being invoked shoul
d resolve to the | 34 * [PropertyAccessorElement]). |
| 35 * element representing the method or function (a [ExecutableElement]). | 35 * * An identifier denoting the name of a method or function being invoked |
| 36 * * An identifier denoting a label should resolve to the element representing t
he label (a | 36 * should resolve to the element representing the method or function (an |
| 37 * [LabelElement]). | 37 * [ExecutableElement]). |
| 38 * The identifiers within directives are exceptions to this rule and are covered
below. | 38 * * An identifier denoting a label should resolve to the element |
| 39 * * Every node containing a token representing an operator that can be overridd
en ( | 39 * representing the label (a [LabelElement]). |
| 40 * [BinaryExpression], [PrefixExpression], [PostfixExpression]) should resolve t
o | 40 * The identifiers within directives are exceptions to this rule and are |
| 41 * the element representing the method invoked by that operator (a [MethodElemen
t]). | 41 * covered below. |
| 42 * * Every [FunctionExpressionInvocation] should resolve to the element represen
ting the | 42 * 2. Every node containing a token representing an operator that can be |
| 43 * function being invoked (a [FunctionElement]). This will be the same element a
s that to | 43 * overridden ( [BinaryExpression], [PrefixExpression], [PostfixExpression]) |
| 44 * which the name is resolved if the function has a name, but is provided for th
ose cases where an | 44 * should resolve to the element representing the method invoked by that |
| 45 * unnamed function is being invoked. | 45 * operator (a [MethodElement]). |
| 46 * * Every [LibraryDirective] and [PartOfDirective] should resolve to the elemen
t | 46 * 3. Every [FunctionExpressionInvocation] should resolve to the element |
| 47 * representing the library being specified by the directive (a [LibraryElement]
) unless, in | 47 * representing the function being invoked (a [FunctionElement]). This will |
| 48 * the case of a part-of directive, the specified library does not exist. | 48 * be the same element as that to which the name is resolved if the function |
| 49 * * Every [ImportDirective] and [ExportDirective] should resolve to the element | 49 * has a name, but is provided for those cases where an unnamed function is |
| 50 * representing the library being specified by the directive unless the specifie
d library does not | 50 * being invoked. |
| 51 * exist (an [ImportElement] or [ExportElement]). | 51 * 4. Every [LibraryDirective] and [PartOfDirective] should resolve to the |
| 52 * * The identifier representing the prefix in an [ImportDirective] should resol
ve to the | 52 * element representing the library being specified by the directive (a |
| 53 * element representing the prefix (a [PrefixElement]). | 53 * [LibraryElement]) unless, in the case of a part-of directive, the |
| 54 * * The identifiers in the hide and show combinators in [ImportDirective]s and | 54 * specified library does not exist. |
| 55 * [ExportDirective]s should resolve to the elements that are being hidden or sh
own, | 55 * 5. Every [ImportDirective] and [ExportDirective] should resolve to the |
| 56 * respectively, unless those names are not defined in the specified library (or
the specified | 56 * element representing the library being specified by the directive unless |
| 57 * library does not exist). | 57 * the specified library does not exist (an [ImportElement] or |
| 58 * * Every [PartDirective] should resolve to the element representing the compil
ation unit | 58 * [ExportElement]). |
| 59 * being specified by the string unless the specified compilation unit does not
exist (a | 59 * 6. The identifier representing the prefix in an [ImportDirective] should |
| 60 * [CompilationUnitElement]). | 60 * resolve to the element representing the prefix (a [PrefixElement]). |
| 61 * </ol> | 61 * 7. The identifiers in the hide and show combinators in [ImportDirective]s |
| 62 * Note that AST nodes that would represent elements that are not defined are no
t resolved to | 62 * and [ExportDirective]s should resolve to the elements that are being |
| 63 * anything. This includes such things as references to undeclared variables (wh
ich is an error) and | 63 * hidden or shown, respectively, unless those names are not defined in the |
| 64 * names in hide and show combinators that are not defined in the imported libra
ry (which is not an | 64 * specified library (or the specified library does not exist). |
| 65 * 8. Every [PartDirective] should resolve to the element representing the |
| 66 * compilation unit being specified by the string unless the specified |
| 67 * compilation unit does not exist (a [CompilationUnitElement]). |
| 68 * |
| 69 * Note that AST nodes that would represent elements that are not defined are |
| 70 * not resolved to anything. This includes such things as references to |
| 71 * undeclared variables (which is an error) and names in hide and show |
| 72 * combinators that are not defined in the imported library (which is not an |
| 65 * error). | 73 * error). |
| 66 */ | 74 */ |
| 67 class ElementResolver extends SimpleAstVisitor<Object> { | 75 class ElementResolver extends SimpleAstVisitor<Object> { |
| 68 /** | 76 /** |
| 69 * The resolver driving this participant. | 77 * The resolver driving this participant. |
| 70 */ | 78 */ |
| 71 final ResolverVisitor _resolver; | 79 final ResolverVisitor _resolver; |
| 72 | 80 |
| 73 /** | 81 /** |
| 74 * The element for the library containing the compilation unit being visited. | 82 * The element for the library containing the compilation unit being visited. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 90 * The type representing the type 'dynamic'. | 98 * The type representing the type 'dynamic'. |
| 91 */ | 99 */ |
| 92 DartType _dynamicType; | 100 DartType _dynamicType; |
| 93 | 101 |
| 94 /** | 102 /** |
| 95 * The type representing the type 'type'. | 103 * The type representing the type 'type'. |
| 96 */ | 104 */ |
| 97 DartType _typeType; | 105 DartType _typeType; |
| 98 | 106 |
| 99 /** | 107 /** |
| 100 * A utility class for the resolver to answer the question of "what are my sub
types?". | 108 * A utility class for the resolver to answer the question of "what are my |
| 109 * subtypes?". |
| 101 */ | 110 */ |
| 102 SubtypeManager _subtypeManager; | 111 SubtypeManager _subtypeManager; |
| 103 | 112 |
| 104 /** | 113 /** |
| 105 * The object keeping track of which elements have had their types promoted. | 114 * The object keeping track of which elements have had their types promoted. |
| 106 */ | 115 */ |
| 107 TypePromotionManager _promoteManager; | 116 TypePromotionManager _promoteManager; |
| 108 | 117 |
| 109 /** | 118 /** |
| 110 * Initialize a newly created visitor to resolve the nodes in a compilation un
it. | 119 * Initialize a newly created visitor to work for the given [_resolver] to |
| 111 * | 120 * resolve the nodes in a compilation unit. |
| 112 * @param resolver the resolver driving this participant | |
| 113 */ | 121 */ |
| 114 ElementResolver(this._resolver) { | 122 ElementResolver(this._resolver) { |
| 115 this._definingLibrary = _resolver.definingLibrary; | 123 this._definingLibrary = _resolver.definingLibrary; |
| 116 AnalysisOptions options = _definingLibrary.context.analysisOptions; | 124 AnalysisOptions options = _definingLibrary.context.analysisOptions; |
| 117 _enableHints = options.hint; | 125 _enableHints = options.hint; |
| 118 _enableStrictCallChecks = options.enableStrictCallChecks; | 126 _enableStrictCallChecks = options.enableStrictCallChecks; |
| 119 _dynamicType = _resolver.typeProvider.dynamicType; | 127 _dynamicType = _resolver.typeProvider.dynamicType; |
| 120 _typeType = _resolver.typeProvider.typeType; | 128 _typeType = _resolver.typeProvider.typeType; |
| 121 _subtypeManager = new SubtypeManager(); | 129 _subtypeManager = new SubtypeManager(); |
| 122 _promoteManager = _resolver.promoteManager; | 130 _promoteManager = _resolver.promoteManager; |
| 123 } | 131 } |
| 124 | 132 |
| 125 /** | 133 /** |
| 126 * @return `true` iff current enclosing function is constant constructor decla
ration. | 134 * Return `true` iff the current enclosing function is a constant constructor |
| 135 * declaration. |
| 127 */ | 136 */ |
| 128 bool get isInConstConstructor { | 137 bool get isInConstConstructor { |
| 129 ExecutableElement function = _resolver.enclosingFunction; | 138 ExecutableElement function = _resolver.enclosingFunction; |
| 130 if (function is ConstructorElement) { | 139 if (function is ConstructorElement) { |
| 131 return function.isConst; | 140 return function.isConst; |
| 132 } | 141 } |
| 133 return false; | 142 return false; |
| 134 } | 143 } |
| 135 | 144 |
| 136 @override | 145 @override |
| (...skipping 944 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1081 return null; | 1090 return null; |
| 1082 } | 1091 } |
| 1083 | 1092 |
| 1084 @override | 1093 @override |
| 1085 Object visitVariableDeclaration(VariableDeclaration node) { | 1094 Object visitVariableDeclaration(VariableDeclaration node) { |
| 1086 _setMetadata(node.element, node); | 1095 _setMetadata(node.element, node); |
| 1087 return null; | 1096 return null; |
| 1088 } | 1097 } |
| 1089 | 1098 |
| 1090 /** | 1099 /** |
| 1091 * Generate annotation elements for each of the annotations in the given node
list and add them to | 1100 * Generate annotation elements for each of the annotations in the |
| 1092 * the given list of elements. | 1101 * [annotationList] and add them to the given list of [annotations]. |
| 1093 * | |
| 1094 * @param annotationList the list of elements to which new elements are to be
added | |
| 1095 * @param annotations the AST nodes used to generate new elements | |
| 1096 */ | 1102 */ |
| 1097 void _addAnnotations(List<ElementAnnotationImpl> annotationList, | 1103 void _addAnnotations(List<ElementAnnotationImpl> annotationList, |
| 1098 NodeList<Annotation> annotations) { | 1104 NodeList<Annotation> annotations) { |
| 1099 int annotationCount = annotations.length; | 1105 int annotationCount = annotations.length; |
| 1100 for (int i = 0; i < annotationCount; i++) { | 1106 for (int i = 0; i < annotationCount; i++) { |
| 1101 Annotation annotation = annotations[i]; | 1107 Annotation annotation = annotations[i]; |
| 1102 Element resolvedElement = annotation.element; | 1108 Element resolvedElement = annotation.element; |
| 1103 if (resolvedElement != null) { | 1109 if (resolvedElement != null) { |
| 1104 ElementAnnotationImpl elementAnnotation = | 1110 ElementAnnotationImpl elementAnnotation = |
| 1105 new ElementAnnotationImpl(resolvedElement); | 1111 new ElementAnnotationImpl(resolvedElement); |
| 1106 annotation.elementAnnotation = elementAnnotation; | 1112 annotation.elementAnnotation = elementAnnotation; |
| 1107 annotationList.add(elementAnnotation); | 1113 annotationList.add(elementAnnotation); |
| 1108 } | 1114 } |
| 1109 } | 1115 } |
| 1110 } | 1116 } |
| 1111 | 1117 |
| 1112 /** | 1118 /** |
| 1113 * Given that we have found code to invoke the given element, return the error
code that should be | 1119 * Given that we have found code to invoke the given [element], return the |
| 1114 * reported, or `null` if no error should be reported. | 1120 * error code that should be reported, or `null` if no error should be |
| 1115 * | 1121 * reported. The [target] is the target of the invocation, or `null` if there |
| 1116 * @param target the target of the invocation, or `null` if there was no targe
t | 1122 * was no target. The flag [useStaticContext] should be `true` if the |
| 1117 * @param useStaticContext | 1123 * invocation is in a static constant (does not have access to instance state. |
| 1118 * @param element the element to be invoked | |
| 1119 * @return the error code that should be reported | |
| 1120 */ | 1124 */ |
| 1121 ErrorCode _checkForInvocationError( | 1125 ErrorCode _checkForInvocationError( |
| 1122 Expression target, bool useStaticContext, Element element) { | 1126 Expression target, bool useStaticContext, Element element) { |
| 1123 // Prefix is not declared, instead "prefix.id" are declared. | 1127 // Prefix is not declared, instead "prefix.id" are declared. |
| 1124 if (element is PrefixElement) { | 1128 if (element is PrefixElement) { |
| 1125 element = null; | 1129 element = null; |
| 1126 } | 1130 } |
| 1127 if (element is PropertyAccessorElement) { | 1131 if (element is PropertyAccessorElement) { |
| 1128 // | 1132 // |
| 1129 // This is really a function expression invocation. | 1133 // This is really a function expression invocation. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1194 // targetType.getElement() | 1198 // targetType.getElement() |
| 1195 return StaticTypeWarningCode.UNDEFINED_METHOD; | 1199 return StaticTypeWarningCode.UNDEFINED_METHOD; |
| 1196 } | 1200 } |
| 1197 } | 1201 } |
| 1198 } | 1202 } |
| 1199 } | 1203 } |
| 1200 return null; | 1204 return null; |
| 1201 } | 1205 } |
| 1202 | 1206 |
| 1203 /** | 1207 /** |
| 1204 * Check that the for some index expression that the method element was resolv
ed, otherwise a | 1208 * Check that the given index [expression] was resolved, otherwise a |
| 1205 * [StaticTypeWarningCode.UNDEFINED_OPERATOR] is generated. | 1209 * [StaticTypeWarningCode.UNDEFINED_OPERATOR] is generated. The [target] is |
| 1206 * | 1210 * the target of the expression. The [methodName] is the name of the operator |
| 1207 * @param node the index expression to resolve | 1211 * associated with the context of using of the given index expression. |
| 1208 * @param target the target of the expression | |
| 1209 * @param methodName the name of the operator associated with the context of u
sing of the given | |
| 1210 * index expression | |
| 1211 * @return `true` if and only if an error code is generated on the passed node | |
| 1212 */ | 1212 */ |
| 1213 bool _checkForUndefinedIndexOperator(IndexExpression node, Expression target, | 1213 bool _checkForUndefinedIndexOperator(IndexExpression expression, |
| 1214 String methodName, MethodElement staticMethod, | 1214 Expression target, String methodName, MethodElement staticMethod, |
| 1215 MethodElement propagatedMethod, DartType staticType, | 1215 MethodElement propagatedMethod, DartType staticType, |
| 1216 DartType propagatedType) { | 1216 DartType propagatedType) { |
| 1217 bool shouldReportMissingMember_static = | 1217 bool shouldReportMissingMember_static = |
| 1218 _shouldReportMissingMember(staticType, staticMethod); | 1218 _shouldReportMissingMember(staticType, staticMethod); |
| 1219 bool shouldReportMissingMember_propagated = | 1219 bool shouldReportMissingMember_propagated = |
| 1220 !shouldReportMissingMember_static && | 1220 !shouldReportMissingMember_static && |
| 1221 _enableHints && | 1221 _enableHints && |
| 1222 _shouldReportMissingMember(propagatedType, propagatedMethod) && | 1222 _shouldReportMissingMember(propagatedType, propagatedMethod) && |
| 1223 !_memberFoundInSubclass( | 1223 !_memberFoundInSubclass( |
| 1224 propagatedType.element, methodName, true, false); | 1224 propagatedType.element, methodName, true, false); |
| 1225 if (shouldReportMissingMember_static || | 1225 if (shouldReportMissingMember_static || |
| 1226 shouldReportMissingMember_propagated) { | 1226 shouldReportMissingMember_propagated) { |
| 1227 sc.Token leftBracket = node.leftBracket; | 1227 sc.Token leftBracket = expression.leftBracket; |
| 1228 sc.Token rightBracket = node.rightBracket; | 1228 sc.Token rightBracket = expression.rightBracket; |
| 1229 ErrorCode errorCode; | 1229 ErrorCode errorCode; |
| 1230 if (shouldReportMissingMember_static) { | 1230 if (shouldReportMissingMember_static) { |
| 1231 if (target is SuperExpression) { | 1231 if (target is SuperExpression) { |
| 1232 errorCode = StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR; | 1232 errorCode = StaticTypeWarningCode.UNDEFINED_SUPER_OPERATOR; |
| 1233 } else { | 1233 } else { |
| 1234 errorCode = StaticTypeWarningCode.UNDEFINED_OPERATOR; | 1234 errorCode = StaticTypeWarningCode.UNDEFINED_OPERATOR; |
| 1235 } | 1235 } |
| 1236 } else { | 1236 } else { |
| 1237 errorCode = HintCode.UNDEFINED_OPERATOR; | 1237 errorCode = HintCode.UNDEFINED_OPERATOR; |
| 1238 } | 1238 } |
| 1239 DartType type = | 1239 DartType type = |
| 1240 shouldReportMissingMember_static ? staticType : propagatedType; | 1240 shouldReportMissingMember_static ? staticType : propagatedType; |
| 1241 if (leftBracket == null || rightBracket == null) { | 1241 if (leftBracket == null || rightBracket == null) { |
| 1242 _recordUndefinedNode( | 1242 _recordUndefinedNode(type.element, errorCode, expression, [ |
| 1243 type.element, errorCode, node, [methodName, type.displayName]); | 1243 methodName, |
| 1244 type.displayName |
| 1245 ]); |
| 1244 } else { | 1246 } else { |
| 1245 int offset = leftBracket.offset; | 1247 int offset = leftBracket.offset; |
| 1246 int length = rightBracket.offset - offset + 1; | 1248 int length = rightBracket.offset - offset + 1; |
| 1247 _recordUndefinedOffset(type.element, errorCode, offset, length, [ | 1249 _recordUndefinedOffset(type.element, errorCode, offset, length, [ |
| 1248 methodName, | 1250 methodName, |
| 1249 type.displayName | 1251 type.displayName |
| 1250 ]); | 1252 ]); |
| 1251 } | 1253 } |
| 1252 return true; | 1254 return true; |
| 1253 } | 1255 } |
| 1254 return false; | 1256 return false; |
| 1255 } | 1257 } |
| 1256 | 1258 |
| 1257 /** | 1259 /** |
| 1258 * Given a list of arguments and the element that will be invoked using those
argument, compute | 1260 * Given an [argumentList] and the executable [element] that will be invoked |
| 1259 * the list of parameters that correspond to the list of arguments. Return the
parameters that | 1261 * using those arguments, compute the list of parameters that correspond to |
| 1260 * correspond to the arguments, or `null` if no correspondence could be comput
ed. | 1262 * the list of arguments. Return the parameters that correspond to the |
| 1261 * | 1263 * arguments, or `null` if no correspondence could be computed. |
| 1262 * @param argumentList the list of arguments being passed to the element | |
| 1263 * @param executableElement the element that will be invoked with the argument
s | |
| 1264 * @return the parameters that correspond to the arguments | |
| 1265 */ | 1264 */ |
| 1266 List<ParameterElement> _computeCorrespondingParameters( | 1265 List<ParameterElement> _computeCorrespondingParameters( |
| 1267 ArgumentList argumentList, Element element) { | 1266 ArgumentList argumentList, Element element) { |
| 1268 if (element is PropertyAccessorElement) { | 1267 if (element is PropertyAccessorElement) { |
| 1269 // | 1268 // |
| 1270 // This is an invocation of the call method defined on the value returned | 1269 // This is an invocation of the call method defined on the value returned |
| 1271 // by the getter. | 1270 // by the getter. |
| 1272 // | 1271 // |
| 1273 FunctionType getterType = element.type; | 1272 FunctionType getterType = element.type; |
| 1274 if (getterType != null) { | 1273 if (getterType != null) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1300 if (callMethod != null) { | 1299 if (callMethod != null) { |
| 1301 List<ParameterElement> parameters = callMethod.parameters; | 1300 List<ParameterElement> parameters = callMethod.parameters; |
| 1302 return _resolveArgumentsToParameters(false, argumentList, parameters); | 1301 return _resolveArgumentsToParameters(false, argumentList, parameters); |
| 1303 } | 1302 } |
| 1304 } | 1303 } |
| 1305 } | 1304 } |
| 1306 return null; | 1305 return null; |
| 1307 } | 1306 } |
| 1308 | 1307 |
| 1309 /** | 1308 /** |
| 1310 * If the given element is a setter, return the getter associated with it. Oth
erwise, return the | 1309 * If the given [element] is a setter, return the getter associated with it. |
| 1311 * element unchanged. | 1310 * Otherwise, return the element unchanged. |
| 1312 * | |
| 1313 * @param element the element to be normalized | |
| 1314 * @return a non-setter element derived from the given element | |
| 1315 */ | 1311 */ |
| 1316 Element _convertSetterToGetter(Element element) { | 1312 Element _convertSetterToGetter(Element element) { |
| 1317 // TODO(brianwilkerson) Determine whether and why the element could ever be | 1313 // TODO(brianwilkerson) Determine whether and why the element could ever be |
| 1318 // a setter. | 1314 // a setter. |
| 1319 if (element is PropertyAccessorElement) { | 1315 if (element is PropertyAccessorElement) { |
| 1320 return element.variable.getter; | 1316 return element.variable.getter; |
| 1321 } | 1317 } |
| 1322 return element; | 1318 return element; |
| 1323 } | 1319 } |
| 1324 | 1320 |
| 1325 /** | 1321 /** |
| 1326 * Return `true` if the given element is not a proxy. | 1322 * Return `true` if the given [element] is not a proxy. See |
| 1327 * | 1323 * [ClassElement.isOrInheritsProxy]. |
| 1328 * @param element the enclosing element. If null, `true` will be returned. | |
| 1329 * @return `false` iff the passed [Element] is a [ClassElement] that is a prox
y | |
| 1330 * or inherits proxy | |
| 1331 * See [ClassElement.isOrInheritsProxy]. | |
| 1332 */ | 1324 */ |
| 1333 bool _doesntHaveProxy(Element element) => | 1325 bool _doesntHaveProxy(Element element) => |
| 1334 !(element is ClassElement && element.isOrInheritsProxy); | 1326 !(element is ClassElement && element.isOrInheritsProxy); |
| 1335 | 1327 |
| 1336 /** | 1328 /** |
| 1337 * Look for any declarations of the given identifier that are imported using a
prefix. Return the | 1329 * Look for any declarations of the given [identifier] that are imported using |
| 1338 * element that was found, or `null` if the name is not imported using a prefi
x. | 1330 * a prefix. Return the element that was found, or `null` if the name is not |
| 1339 * | 1331 * imported using a prefix. |
| 1340 * @param identifier the identifier that might have been imported using a pref
ix | |
| 1341 * @return the element that was found | |
| 1342 */ | 1332 */ |
| 1343 Element _findImportWithoutPrefix(SimpleIdentifier identifier) { | 1333 Element _findImportWithoutPrefix(SimpleIdentifier identifier) { |
| 1344 Element element = null; | 1334 Element element = null; |
| 1345 Scope nameScope = _resolver.nameScope; | 1335 Scope nameScope = _resolver.nameScope; |
| 1346 for (ImportElement importElement in _definingLibrary.imports) { | 1336 for (ImportElement importElement in _definingLibrary.imports) { |
| 1347 PrefixElement prefixElement = importElement.prefix; | 1337 PrefixElement prefixElement = importElement.prefix; |
| 1348 if (prefixElement != null) { | 1338 if (prefixElement != null) { |
| 1349 Identifier prefixedIdentifier = new SyntheticIdentifier( | 1339 Identifier prefixedIdentifier = new SyntheticIdentifier( |
| 1350 "${prefixElement.name}.${identifier.name}", identifier); | 1340 "${prefixElement.name}.${identifier.name}", identifier); |
| 1351 Element importedElement = | 1341 Element importedElement = |
| 1352 nameScope.lookup(prefixedIdentifier, _definingLibrary); | 1342 nameScope.lookup(prefixedIdentifier, _definingLibrary); |
| 1353 if (importedElement != null) { | 1343 if (importedElement != null) { |
| 1354 if (element == null) { | 1344 if (element == null) { |
| 1355 element = importedElement; | 1345 element = importedElement; |
| 1356 } else { | 1346 } else { |
| 1357 element = MultiplyDefinedElementImpl.fromElements( | 1347 element = MultiplyDefinedElementImpl.fromElements( |
| 1358 _definingLibrary.context, element, importedElement); | 1348 _definingLibrary.context, element, importedElement); |
| 1359 } | 1349 } |
| 1360 } | 1350 } |
| 1361 } | 1351 } |
| 1362 } | 1352 } |
| 1363 return element; | 1353 return element; |
| 1364 } | 1354 } |
| 1365 | 1355 |
| 1366 /** | 1356 /** |
| 1367 * Assuming that the given expression is a prefix for a deferred import, retur
n the library that | 1357 * Assuming that the given [expression] is a prefix for a deferred import, |
| 1368 * is being imported. | 1358 * return the library that is being imported. |
| 1369 * | |
| 1370 * @param expression the expression representing the deferred import's prefix | |
| 1371 * @return the library that is being imported by the import associated with th
e prefix | |
| 1372 */ | 1359 */ |
| 1373 LibraryElement _getImportedLibrary(Expression expression) { | 1360 LibraryElement _getImportedLibrary(Expression expression) { |
| 1374 PrefixElement prefixElement = | 1361 PrefixElement prefixElement = |
| 1375 (expression as SimpleIdentifier).staticElement as PrefixElement; | 1362 (expression as SimpleIdentifier).staticElement as PrefixElement; |
| 1376 List<ImportElement> imports = | 1363 List<ImportElement> imports = |
| 1377 prefixElement.enclosingElement.getImportsWithPrefix(prefixElement); | 1364 prefixElement.enclosingElement.getImportsWithPrefix(prefixElement); |
| 1378 return imports[0].importedLibrary; | 1365 return imports[0].importedLibrary; |
| 1379 } | 1366 } |
| 1380 | 1367 |
| 1381 /** | 1368 /** |
| 1382 * Return the name of the method invoked by the given postfix expression. | 1369 * Return the name of the method invoked by the given postfix [expression]. |
| 1383 * | |
| 1384 * @param node the postfix expression being invoked | |
| 1385 * @return the name of the method invoked by the expression | |
| 1386 */ | 1370 */ |
| 1387 String _getPostfixOperator(PostfixExpression node) => | 1371 String _getPostfixOperator(PostfixExpression expression) => |
| 1388 (node.operator.type == sc.TokenType.PLUS_PLUS) | 1372 (expression.operator.type == sc.TokenType.PLUS_PLUS) |
| 1389 ? sc.TokenType.PLUS.lexeme | 1373 ? sc.TokenType.PLUS.lexeme |
| 1390 : sc.TokenType.MINUS.lexeme; | 1374 : sc.TokenType.MINUS.lexeme; |
| 1391 | 1375 |
| 1392 /** | 1376 /** |
| 1393 * Return the name of the method invoked by the given postfix expression. | 1377 * Return the name of the method invoked by the given postfix [expression]. |
| 1394 * | |
| 1395 * @param node the postfix expression being invoked | |
| 1396 * @return the name of the method invoked by the expression | |
| 1397 */ | 1378 */ |
| 1398 String _getPrefixOperator(PrefixExpression node) { | 1379 String _getPrefixOperator(PrefixExpression expression) { |
| 1399 sc.Token operator = node.operator; | 1380 sc.Token operator = expression.operator; |
| 1400 sc.TokenType operatorType = operator.type; | 1381 sc.TokenType operatorType = operator.type; |
| 1401 if (operatorType == sc.TokenType.PLUS_PLUS) { | 1382 if (operatorType == sc.TokenType.PLUS_PLUS) { |
| 1402 return sc.TokenType.PLUS.lexeme; | 1383 return sc.TokenType.PLUS.lexeme; |
| 1403 } else if (operatorType == sc.TokenType.MINUS_MINUS) { | 1384 } else if (operatorType == sc.TokenType.MINUS_MINUS) { |
| 1404 return sc.TokenType.MINUS.lexeme; | 1385 return sc.TokenType.MINUS.lexeme; |
| 1405 } else if (operatorType == sc.TokenType.MINUS) { | 1386 } else if (operatorType == sc.TokenType.MINUS) { |
| 1406 return "unary-"; | 1387 return "unary-"; |
| 1407 } else { | 1388 } else { |
| 1408 return operator.lexeme; | 1389 return operator.lexeme; |
| 1409 } | 1390 } |
| 1410 } | 1391 } |
| 1411 | 1392 |
| 1412 /** | 1393 /** |
| 1413 * Return the propagated type of the given expression that is to be used for t
ype analysis. | 1394 * Return the propagated type of the given [expression] that is to be used for |
| 1414 * | 1395 * type analysis. |
| 1415 * @param expression the expression whose type is to be returned | |
| 1416 * @return the type of the given expression | |
| 1417 */ | 1396 */ |
| 1418 DartType _getPropagatedType(Expression expression) { | 1397 DartType _getPropagatedType(Expression expression) { |
| 1419 DartType propagatedType = _resolveTypeParameter(expression.propagatedType); | 1398 DartType propagatedType = _resolveTypeParameter(expression.propagatedType); |
| 1420 if (propagatedType is FunctionType) { | 1399 if (propagatedType is FunctionType) { |
| 1421 // | 1400 // |
| 1422 // All function types are subtypes of 'Function', which is itself a | 1401 // All function types are subtypes of 'Function', which is itself a |
| 1423 // subclass of 'Object'. | 1402 // subclass of 'Object'. |
| 1424 // | 1403 // |
| 1425 propagatedType = _resolver.typeProvider.functionType; | 1404 propagatedType = _resolver.typeProvider.functionType; |
| 1426 } | 1405 } |
| 1427 return propagatedType; | 1406 return propagatedType; |
| 1428 } | 1407 } |
| 1429 | 1408 |
| 1430 /** | 1409 /** |
| 1431 * Return the static type of the given expression that is to be used for type
analysis. | 1410 * Return the static type of the given [expression] that is to be used for |
| 1432 * | 1411 * type analysis. |
| 1433 * @param expression the expression whose type is to be returned | |
| 1434 * @return the type of the given expression | |
| 1435 */ | 1412 */ |
| 1436 DartType _getStaticType(Expression expression) { | 1413 DartType _getStaticType(Expression expression) { |
| 1437 if (expression is NullLiteral) { | 1414 if (expression is NullLiteral) { |
| 1438 return _resolver.typeProvider.bottomType; | 1415 return _resolver.typeProvider.bottomType; |
| 1439 } | 1416 } |
| 1440 DartType staticType = _resolveTypeParameter(expression.staticType); | 1417 DartType staticType = _resolveTypeParameter(expression.staticType); |
| 1441 if (staticType is FunctionType) { | 1418 if (staticType is FunctionType) { |
| 1442 // | 1419 // |
| 1443 // All function types are subtypes of 'Function', which is itself a | 1420 // All function types are subtypes of 'Function', which is itself a |
| 1444 // subclass of 'Object'. | 1421 // subclass of 'Object'. |
| 1445 // | 1422 // |
| 1446 staticType = _resolver.typeProvider.functionType; | 1423 staticType = _resolver.typeProvider.functionType; |
| 1447 } | 1424 } |
| 1448 return staticType; | 1425 return staticType; |
| 1449 } | 1426 } |
| 1450 | 1427 |
| 1451 /** | 1428 /** |
| 1452 * Return `true` if the given expression is a prefix for a deferred import. | 1429 * Return `true` if the given [expression] is a prefix for a deferred import. |
| 1453 * | |
| 1454 * @param expression the expression being tested | |
| 1455 * @return `true` if the given expression is a prefix for a deferred import | |
| 1456 */ | 1430 */ |
| 1457 bool _isDeferredPrefix(Expression expression) { | 1431 bool _isDeferredPrefix(Expression expression) { |
| 1458 if (expression is! SimpleIdentifier) { | 1432 if (expression is! SimpleIdentifier) { |
| 1459 return false; | 1433 return false; |
| 1460 } | 1434 } |
| 1461 Element element = (expression as SimpleIdentifier).staticElement; | 1435 Element element = (expression as SimpleIdentifier).staticElement; |
| 1462 if (element is! PrefixElement) { | 1436 if (element is! PrefixElement) { |
| 1463 return false; | 1437 return false; |
| 1464 } | 1438 } |
| 1465 PrefixElement prefixElement = element as PrefixElement; | 1439 PrefixElement prefixElement = element as PrefixElement; |
| 1466 List<ImportElement> imports = | 1440 List<ImportElement> imports = |
| 1467 prefixElement.enclosingElement.getImportsWithPrefix(prefixElement); | 1441 prefixElement.enclosingElement.getImportsWithPrefix(prefixElement); |
| 1468 if (imports.length != 1) { | 1442 if (imports.length != 1) { |
| 1469 return false; | 1443 return false; |
| 1470 } | 1444 } |
| 1471 return imports[0].isDeferred; | 1445 return imports[0].isDeferred; |
| 1472 } | 1446 } |
| 1473 | 1447 |
| 1474 /** | 1448 /** |
| 1475 * Return `true` if the given type represents an object that could be invoked
using the call | 1449 * Return `true` if the given [type] represents an object that could be |
| 1476 * operator '()'. | 1450 * invoked using the call operator '()'. |
| 1477 * | |
| 1478 * @param type the type being tested | |
| 1479 * @return `true` if the given type represents an object that could be invoked | |
| 1480 */ | 1451 */ |
| 1481 bool _isExecutableType(DartType type) { | 1452 bool _isExecutableType(DartType type) { |
| 1482 if (type.isDynamic || type is FunctionType) { | 1453 if (type.isDynamic || type is FunctionType) { |
| 1483 return true; | 1454 return true; |
| 1484 } else if (!_enableStrictCallChecks && | 1455 } else if (!_enableStrictCallChecks && |
| 1485 (type.isDartCoreFunction || type.isObject)) { | 1456 (type.isDartCoreFunction || type.isObject)) { |
| 1486 return true; | 1457 return true; |
| 1487 } else if (type is InterfaceType) { | 1458 } else if (type is InterfaceType) { |
| 1488 ClassElement classElement = type.element; | 1459 ClassElement classElement = type.element; |
| 1489 // 16078 from Gilad: If the type is a Functor with the @proxy annotation, | 1460 // 16078 from Gilad: If the type is a Functor with the @proxy annotation, |
| 1490 // treat it as an executable type. | 1461 // treat it as an executable type. |
| 1491 // example code: NonErrorResolverTest. | 1462 // example code: NonErrorResolverTest. |
| 1492 // test_invocationOfNonFunction_proxyOnFunctionClass() | 1463 // test_invocationOfNonFunction_proxyOnFunctionClass() |
| 1493 if (classElement.isProxy && | 1464 if (classElement.isProxy && |
| 1494 type.isSubtypeOf(_resolver.typeProvider.functionType)) { | 1465 type.isSubtypeOf(_resolver.typeProvider.functionType)) { |
| 1495 return true; | 1466 return true; |
| 1496 } | 1467 } |
| 1497 MethodElement methodElement = classElement.lookUpMethod( | 1468 MethodElement methodElement = classElement.lookUpMethod( |
| 1498 FunctionElement.CALL_METHOD_NAME, _definingLibrary); | 1469 FunctionElement.CALL_METHOD_NAME, _definingLibrary); |
| 1499 return methodElement != null; | 1470 return methodElement != null; |
| 1500 } | 1471 } |
| 1501 return false; | 1472 return false; |
| 1502 } | 1473 } |
| 1503 | 1474 |
| 1504 /** | 1475 /** |
| 1505 * Return `true` if the given element is a static element. | 1476 * Return `true` if the given [element] is a static element. |
| 1506 * | |
| 1507 * @param element the element being tested | |
| 1508 * @return `true` if the given element is a static element | |
| 1509 */ | 1477 */ |
| 1510 bool _isStatic(Element element) { | 1478 bool _isStatic(Element element) { |
| 1511 if (element is ExecutableElement) { | 1479 if (element is ExecutableElement) { |
| 1512 return element.isStatic; | 1480 return element.isStatic; |
| 1513 } else if (element is PropertyInducingElement) { | 1481 } else if (element is PropertyInducingElement) { |
| 1514 return element.isStatic; | 1482 return element.isStatic; |
| 1515 } | 1483 } |
| 1516 return false; | 1484 return false; |
| 1517 } | 1485 } |
| 1518 | 1486 |
| 1519 /** | 1487 /** |
| 1520 * Return `true` if the given node can validly be resolved to a prefix: | 1488 * Return `true` if the given [node] can validly be resolved to a prefix: |
| 1521 * * it is the prefix in an import directive, or | 1489 * * it is the prefix in an import directive, or |
| 1522 * * it is the prefix in a prefixed identifier. | 1490 * * it is the prefix in a prefixed identifier. |
| 1523 * | |
| 1524 * @param node the node being tested | |
| 1525 * @return `true` if the given node is the prefix in an import directive | |
| 1526 */ | 1491 */ |
| 1527 bool _isValidAsPrefix(SimpleIdentifier node) { | 1492 bool _isValidAsPrefix(SimpleIdentifier node) { |
| 1528 AstNode parent = node.parent; | 1493 AstNode parent = node.parent; |
| 1529 if (parent is ImportDirective) { | 1494 if (parent is ImportDirective) { |
| 1530 return identical(parent.prefix, node); | 1495 return identical(parent.prefix, node); |
| 1531 } else if (parent is PrefixedIdentifier) { | 1496 } else if (parent is PrefixedIdentifier) { |
| 1532 return true; | 1497 return true; |
| 1533 } else if (parent is MethodInvocation) { | 1498 } else if (parent is MethodInvocation) { |
| 1534 return identical(parent.target, node); | 1499 return identical(parent.target, node); |
| 1535 } | 1500 } |
| 1536 return false; | 1501 return false; |
| 1537 } | 1502 } |
| 1538 | 1503 |
| 1539 /** | 1504 /** |
| 1540 * Return the target of a break or continue statement, and update the static | 1505 * Return the target of a break or continue statement, and update the static |
| 1541 * element of its label (if any). [parentNode] is the AST node of the break | 1506 * element of its label (if any). The [parentNode] is the AST node of the |
| 1542 * or continue statement, [labelNode] is the label contained in that | 1507 * break or continue statement. The [labelNode] is the label contained in that |
| 1543 * statement (if any), and [isContinue] is true if the node being visited is | 1508 * statement (if any). The flag [isContinue] is `true` if the node being |
| 1544 * a continue statement. | 1509 * visited is a continue statement. |
| 1545 */ | 1510 */ |
| 1546 AstNode _lookupBreakOrContinueTarget( | 1511 AstNode _lookupBreakOrContinueTarget( |
| 1547 AstNode parentNode, SimpleIdentifier labelNode, bool isContinue) { | 1512 AstNode parentNode, SimpleIdentifier labelNode, bool isContinue) { |
| 1548 if (labelNode == null) { | 1513 if (labelNode == null) { |
| 1549 return _resolver.implicitLabelScope.getTarget(isContinue); | 1514 return _resolver.implicitLabelScope.getTarget(isContinue); |
| 1550 } else { | 1515 } else { |
| 1551 LabelScope labelScope = _resolver.labelScope; | 1516 LabelScope labelScope = _resolver.labelScope; |
| 1552 if (labelScope == null) { | 1517 if (labelScope == null) { |
| 1553 // There are no labels in scope, so by definition the label is | 1518 // There are no labels in scope, so by definition the label is |
| 1554 // undefined. | 1519 // undefined. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1570 .getAncestor((element) => element is ExecutableElement); | 1535 .getAncestor((element) => element is ExecutableElement); |
| 1571 if (!identical(labelContainer, _resolver.enclosingFunction)) { | 1536 if (!identical(labelContainer, _resolver.enclosingFunction)) { |
| 1572 _resolver.reportErrorForNode(CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE, | 1537 _resolver.reportErrorForNode(CompileTimeErrorCode.LABEL_IN_OUTER_SCOPE, |
| 1573 labelNode, [labelNode.name]); | 1538 labelNode, [labelNode.name]); |
| 1574 } | 1539 } |
| 1575 return definingScope.node; | 1540 return definingScope.node; |
| 1576 } | 1541 } |
| 1577 } | 1542 } |
| 1578 | 1543 |
| 1579 /** | 1544 /** |
| 1580 * Look up the getter with the given name in the given type. Return the elemen
t representing the | 1545 * Look up the getter with the given [getterName] in the given [type]. Return |
| 1581 * getter that was found, or `null` if there is no getter with the given name. | 1546 * the element representing the getter that was found, or `null` if there is |
| 1582 * | 1547 * no getter with the given name. The [target] is the target of the |
| 1583 * @param target the target of the invocation, or `null` if there is no target | 1548 * invocation, or `null` if there is no target. |
| 1584 * @param type the type in which the getter is defined | |
| 1585 * @param getterName the name of the getter being looked up | |
| 1586 * @return the element representing the getter that was found | |
| 1587 */ | 1549 */ |
| 1588 PropertyAccessorElement _lookUpGetter( | 1550 PropertyAccessorElement _lookUpGetter( |
| 1589 Expression target, DartType type, String getterName) { | 1551 Expression target, DartType type, String getterName) { |
| 1590 type = _resolveTypeParameter(type); | 1552 type = _resolveTypeParameter(type); |
| 1591 if (type is InterfaceType) { | 1553 if (type is InterfaceType) { |
| 1592 InterfaceType interfaceType = type; | 1554 InterfaceType interfaceType = type; |
| 1593 PropertyAccessorElement accessor; | 1555 PropertyAccessorElement accessor; |
| 1594 if (target is SuperExpression) { | 1556 if (target is SuperExpression) { |
| 1595 accessor = interfaceType.lookUpGetterInSuperclass( | 1557 accessor = interfaceType.lookUpGetterInSuperclass( |
| 1596 getterName, _definingLibrary); | 1558 getterName, _definingLibrary); |
| 1597 } else { | 1559 } else { |
| 1598 accessor = interfaceType.lookUpGetter(getterName, _definingLibrary); | 1560 accessor = interfaceType.lookUpGetter(getterName, _definingLibrary); |
| 1599 } | 1561 } |
| 1600 if (accessor != null) { | 1562 if (accessor != null) { |
| 1601 return accessor; | 1563 return accessor; |
| 1602 } | 1564 } |
| 1603 return _lookUpGetterInInterfaces( | 1565 return _lookUpGetterInInterfaces( |
| 1604 interfaceType, false, getterName, new HashSet<ClassElement>()); | 1566 interfaceType, false, getterName, new HashSet<ClassElement>()); |
| 1605 } | 1567 } |
| 1606 return null; | 1568 return null; |
| 1607 } | 1569 } |
| 1608 | 1570 |
| 1609 /** | 1571 /** |
| 1610 * Look up the getter with the given name in the interfaces implemented by the
given type, either | 1572 * Look up the getter with the given [getterName] in the interfaces |
| 1611 * directly or indirectly. Return the element representing the getter that was
found, or | 1573 * implemented by the given [targetType], either directly or indirectly. |
| 1612 * `null` if there is no getter with the given name. | 1574 * Return the element representing the getter that was found, or `null` if |
| 1613 * | 1575 * there is no getter with the given name. The flag [includeTargetType] should |
| 1614 * @param targetType the type in which the getter might be defined | 1576 * be `true` if the search should include the target type. The |
| 1615 * @param includeTargetType `true` if the search should include the target typ
e | 1577 * [visitedInterfaces] is a set containing all of the interfaces that have |
| 1616 * @param getterName the name of the getter being looked up | 1578 * been examined, used to prevent infinite recursion and to optimize the |
| 1617 * @param visitedInterfaces a set containing all of the interfaces that have b
een examined, used | 1579 * search. |
| 1618 * to prevent infinite recursion and to optimize the search | |
| 1619 * @return the element representing the getter that was found | |
| 1620 */ | 1580 */ |
| 1621 PropertyAccessorElement _lookUpGetterInInterfaces(InterfaceType targetType, | 1581 PropertyAccessorElement _lookUpGetterInInterfaces(InterfaceType targetType, |
| 1622 bool includeTargetType, String getterName, | 1582 bool includeTargetType, String getterName, |
| 1623 HashSet<ClassElement> visitedInterfaces) { | 1583 HashSet<ClassElement> visitedInterfaces) { |
| 1624 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | 1584 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the |
| 1625 // specification (titled "Inheritance and Overriding" under "Interfaces") | 1585 // specification (titled "Inheritance and Overriding" under "Interfaces") |
| 1626 // describes a much more complex scheme for finding the inherited member. | 1586 // describes a much more complex scheme for finding the inherited member. |
| 1627 // We need to follow that scheme. The code below should cover the 80% case. | 1587 // We need to follow that scheme. The code below should cover the 80% case. |
| 1628 ClassElement targetClass = targetType.element; | 1588 ClassElement targetClass = targetType.element; |
| 1629 if (visitedInterfaces.contains(targetClass)) { | 1589 if (visitedInterfaces.contains(targetClass)) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1652 } | 1612 } |
| 1653 InterfaceType superclass = targetType.superclass; | 1613 InterfaceType superclass = targetType.superclass; |
| 1654 if (superclass == null) { | 1614 if (superclass == null) { |
| 1655 return null; | 1615 return null; |
| 1656 } | 1616 } |
| 1657 return _lookUpGetterInInterfaces( | 1617 return _lookUpGetterInInterfaces( |
| 1658 superclass, true, getterName, visitedInterfaces); | 1618 superclass, true, getterName, visitedInterfaces); |
| 1659 } | 1619 } |
| 1660 | 1620 |
| 1661 /** | 1621 /** |
| 1662 * Look up the method or getter with the given name in the given type. Return
the element | 1622 * Look up the method or getter with the given [memberName] in the given |
| 1663 * representing the method or getter that was found, or `null` if there is no
method or | 1623 * [type]. Return the element representing the method or getter that was |
| 1664 * getter with the given name. | 1624 * found, or `null` if there is no method or getter with the given name. |
| 1665 * | |
| 1666 * @param type the type in which the method or getter is defined | |
| 1667 * @param memberName the name of the method or getter being looked up | |
| 1668 * @return the element representing the method or getter that was found | |
| 1669 */ | 1625 */ |
| 1670 ExecutableElement _lookupGetterOrMethod(DartType type, String memberName) { | 1626 ExecutableElement _lookupGetterOrMethod(DartType type, String memberName) { |
| 1671 type = _resolveTypeParameter(type); | 1627 type = _resolveTypeParameter(type); |
| 1672 if (type is InterfaceType) { | 1628 if (type is InterfaceType) { |
| 1673 InterfaceType interfaceType = type; | 1629 InterfaceType interfaceType = type; |
| 1674 ExecutableElement member = | 1630 ExecutableElement member = |
| 1675 interfaceType.lookUpMethod(memberName, _definingLibrary); | 1631 interfaceType.lookUpMethod(memberName, _definingLibrary); |
| 1676 if (member != null) { | 1632 if (member != null) { |
| 1677 return member; | 1633 return member; |
| 1678 } | 1634 } |
| 1679 member = interfaceType.lookUpGetter(memberName, _definingLibrary); | 1635 member = interfaceType.lookUpGetter(memberName, _definingLibrary); |
| 1680 if (member != null) { | 1636 if (member != null) { |
| 1681 return member; | 1637 return member; |
| 1682 } | 1638 } |
| 1683 return _lookUpGetterOrMethodInInterfaces( | 1639 return _lookUpGetterOrMethodInInterfaces( |
| 1684 interfaceType, false, memberName, new HashSet<ClassElement>()); | 1640 interfaceType, false, memberName, new HashSet<ClassElement>()); |
| 1685 } | 1641 } |
| 1686 return null; | 1642 return null; |
| 1687 } | 1643 } |
| 1688 | 1644 |
| 1689 /** | 1645 /** |
| 1690 * Look up the method or getter with the given name in the interfaces implemen
ted by the given | 1646 * Look up the method or getter with the given [memberName] in the interfaces |
| 1691 * type, either directly or indirectly. Return the element representing the me
thod or getter that | 1647 * implemented by the given [targetType], either directly or indirectly. |
| 1692 * was found, or `null` if there is no method or getter with the given name. | 1648 * Return the element representing the method or getter that was found, or |
| 1693 * | 1649 * `null` if there is no method or getter with the given name. The flag |
| 1694 * @param targetType the type in which the method or getter might be defined | 1650 * [includeTargetType] should be `true` if the search should include the |
| 1695 * @param includeTargetType `true` if the search should include the target typ
e | 1651 * target type. The [visitedInterfaces] is a set containing all of the |
| 1696 * @param memberName the name of the method or getter being looked up | 1652 * interfaces that have been examined, used to prevent infinite recursion and |
| 1697 * @param visitedInterfaces a set containing all of the interfaces that have b
een examined, used | 1653 * to optimize the search. |
| 1698 * to prevent infinite recursion and to optimize the search | |
| 1699 * @return the element representing the method or getter that was found | |
| 1700 */ | 1654 */ |
| 1701 ExecutableElement _lookUpGetterOrMethodInInterfaces(InterfaceType targetType, | 1655 ExecutableElement _lookUpGetterOrMethodInInterfaces(InterfaceType targetType, |
| 1702 bool includeTargetType, String memberName, | 1656 bool includeTargetType, String memberName, |
| 1703 HashSet<ClassElement> visitedInterfaces) { | 1657 HashSet<ClassElement> visitedInterfaces) { |
| 1704 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | 1658 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the |
| 1705 // specification (titled "Inheritance and Overriding" under "Interfaces") | 1659 // specification (titled "Inheritance and Overriding" under "Interfaces") |
| 1706 // describes a much more complex scheme for finding the inherited member. | 1660 // describes a much more complex scheme for finding the inherited member. |
| 1707 // We need to follow that scheme. The code below should cover the 80% case. | 1661 // We need to follow that scheme. The code below should cover the 80% case. |
| 1708 ClassElement targetClass = targetType.element; | 1662 ClassElement targetClass = targetType.element; |
| 1709 if (visitedInterfaces.contains(targetClass)) { | 1663 if (visitedInterfaces.contains(targetClass)) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1736 } | 1690 } |
| 1737 InterfaceType superclass = targetType.superclass; | 1691 InterfaceType superclass = targetType.superclass; |
| 1738 if (superclass == null) { | 1692 if (superclass == null) { |
| 1739 return null; | 1693 return null; |
| 1740 } | 1694 } |
| 1741 return _lookUpGetterOrMethodInInterfaces( | 1695 return _lookUpGetterOrMethodInInterfaces( |
| 1742 superclass, true, memberName, visitedInterfaces); | 1696 superclass, true, memberName, visitedInterfaces); |
| 1743 } | 1697 } |
| 1744 | 1698 |
| 1745 /** | 1699 /** |
| 1746 * Look up the method with the given name in the given type. Return the elemen
t representing the | 1700 * Look up the method with the given [methodName] in the given [type]. Return |
| 1747 * method that was found, or `null` if there is no method with the given name. | 1701 * the element representing the method that was found, or `null` if there is |
| 1748 * | 1702 * no method with the given name. The [target] is the target of the |
| 1749 * @param target the target of the invocation, or `null` if there is no target | 1703 * invocation, or `null` if there is no target. |
| 1750 * @param type the type in which the method is defined | |
| 1751 * @param methodName the name of the method being looked up | |
| 1752 * @return the element representing the method that was found | |
| 1753 */ | 1704 */ |
| 1754 MethodElement _lookUpMethod( | 1705 MethodElement _lookUpMethod( |
| 1755 Expression target, DartType type, String methodName) { | 1706 Expression target, DartType type, String methodName) { |
| 1756 type = _resolveTypeParameter(type); | 1707 type = _resolveTypeParameter(type); |
| 1757 if (type is InterfaceType) { | 1708 if (type is InterfaceType) { |
| 1758 InterfaceType interfaceType = type; | 1709 InterfaceType interfaceType = type; |
| 1759 MethodElement method; | 1710 MethodElement method; |
| 1760 if (target is SuperExpression) { | 1711 if (target is SuperExpression) { |
| 1761 method = interfaceType.lookUpMethodInSuperclass( | 1712 method = interfaceType.lookUpMethodInSuperclass( |
| 1762 methodName, _definingLibrary); | 1713 methodName, _definingLibrary); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1773 // and work with functions, methods, constructors, and property accessors. | 1724 // and work with functions, methods, constructors, and property accessors. |
| 1774 // However, I won't be able to assume it returns [MethodElement] here | 1725 // However, I won't be able to assume it returns [MethodElement] here |
| 1775 // then. | 1726 // then. |
| 1776 return _maybeMergeExecutableElements( | 1727 return _maybeMergeExecutableElements( |
| 1777 _lookupMethods(target, type, methodName)) as MethodElement; | 1728 _lookupMethods(target, type, methodName)) as MethodElement; |
| 1778 } | 1729 } |
| 1779 return null; | 1730 return null; |
| 1780 } | 1731 } |
| 1781 | 1732 |
| 1782 /** | 1733 /** |
| 1783 * Look up the method with the given name in the interfaces implemented by the
given type, either | 1734 * Look up the method with the given [methodName] in the interfaces |
| 1784 * directly or indirectly. Return the element representing the method that was
found, or | 1735 * implemented by the given [targetType], either directly or indirectly. |
| 1785 * `null` if there is no method with the given name. | 1736 * Return the element representing the method that was found, or `null` if |
| 1786 * | 1737 * there is no method with the given name. The flag [includeTargetType] should |
| 1787 * @param targetType the type in which the member might be defined | 1738 * be `true` if the search should include the target type. The |
| 1788 * @param includeTargetType `true` if the search should include the target typ
e | 1739 * [visitedInterfaces] is a set containing all of the interfaces that have |
| 1789 * @param methodName the name of the method being looked up | 1740 * been examined, used to prevent infinite recursion and to optimize the |
| 1790 * @param visitedInterfaces a set containing all of the interfaces that have b
een examined, used | 1741 * search. |
| 1791 * to prevent infinite recursion and to optimize the search | |
| 1792 * @return the element representing the method that was found | |
| 1793 */ | 1742 */ |
| 1794 MethodElement _lookUpMethodInInterfaces(InterfaceType targetType, | 1743 MethodElement _lookUpMethodInInterfaces(InterfaceType targetType, |
| 1795 bool includeTargetType, String methodName, | 1744 bool includeTargetType, String methodName, |
| 1796 HashSet<ClassElement> visitedInterfaces) { | 1745 HashSet<ClassElement> visitedInterfaces) { |
| 1797 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | 1746 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the |
| 1798 // specification (titled "Inheritance and Overriding" under "Interfaces") | 1747 // specification (titled "Inheritance and Overriding" under "Interfaces") |
| 1799 // describes a much more complex scheme for finding the inherited member. | 1748 // describes a much more complex scheme for finding the inherited member. |
| 1800 // We need to follow that scheme. The code below should cover the 80% case. | 1749 // We need to follow that scheme. The code below should cover the 80% case. |
| 1801 ClassElement targetClass = targetType.element; | 1750 ClassElement targetClass = targetType.element; |
| 1802 if (visitedInterfaces.contains(targetClass)) { | 1751 if (visitedInterfaces.contains(targetClass)) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1825 } | 1774 } |
| 1826 InterfaceType superclass = targetType.superclass; | 1775 InterfaceType superclass = targetType.superclass; |
| 1827 if (superclass == null) { | 1776 if (superclass == null) { |
| 1828 return null; | 1777 return null; |
| 1829 } | 1778 } |
| 1830 return _lookUpMethodInInterfaces( | 1779 return _lookUpMethodInInterfaces( |
| 1831 superclass, true, methodName, visitedInterfaces); | 1780 superclass, true, methodName, visitedInterfaces); |
| 1832 } | 1781 } |
| 1833 | 1782 |
| 1834 /** | 1783 /** |
| 1835 * Look up all methods of a given name defined on a union type. | 1784 * Look up all methods with the given [methodName] that are defined on the |
| 1836 * | 1785 * given union [type]. |
| 1837 * @param target | |
| 1838 * @param type | |
| 1839 * @param methodName | |
| 1840 * @return all methods named `methodName` defined on the union type `type`. | |
| 1841 */ | 1786 */ |
| 1842 Set<ExecutableElement> _lookupMethods( | 1787 Set<ExecutableElement> _lookupMethods( |
| 1843 Expression target, UnionType type, String methodName) { | 1788 Expression target, UnionType type, String methodName) { |
| 1844 Set<ExecutableElement> methods = new HashSet<ExecutableElement>(); | 1789 Set<ExecutableElement> methods = new HashSet<ExecutableElement>(); |
| 1845 bool allElementsHaveMethod = true; | 1790 bool allElementsHaveMethod = true; |
| 1846 for (DartType t in type.elements) { | 1791 for (DartType t in type.elements) { |
| 1847 MethodElement m = _lookUpMethod(target, t, methodName); | 1792 MethodElement m = _lookUpMethod(target, t, methodName); |
| 1848 if (m != null) { | 1793 if (m != null) { |
| 1849 methods.add(m); | 1794 methods.add(m); |
| 1850 } else { | 1795 } else { |
| 1851 allElementsHaveMethod = false; | 1796 allElementsHaveMethod = false; |
| 1852 } | 1797 } |
| 1853 } | 1798 } |
| 1854 // For strict union types we require that all types in the union define the | 1799 // For strict union types we require that all types in the union define the |
| 1855 // method. | 1800 // method. |
| 1856 if (AnalysisEngine.instance.strictUnionTypes) { | 1801 if (AnalysisEngine.instance.strictUnionTypes) { |
| 1857 if (allElementsHaveMethod) { | 1802 if (allElementsHaveMethod) { |
| 1858 return methods; | 1803 return methods; |
| 1859 } else { | 1804 } else { |
| 1860 return new Set<ExecutableElement>(); | 1805 return new Set<ExecutableElement>(); |
| 1861 } | 1806 } |
| 1862 } else { | 1807 } else { |
| 1863 return methods; | 1808 return methods; |
| 1864 } | 1809 } |
| 1865 } | 1810 } |
| 1866 | 1811 |
| 1867 /** | 1812 /** |
| 1868 * Look up the setter with the given name in the given type. Return the elemen
t representing the | 1813 * Look up the setter with the given [setterName] in the given [type]. Return |
| 1869 * setter that was found, or `null` if there is no setter with the given name. | 1814 * the element representing the setter that was found, or `null` if there is |
| 1870 * | 1815 * no setter with the given name. The [target] is the target of the |
| 1871 * @param target the target of the invocation, or `null` if there is no target | 1816 * invocation, or `null` if there is no target. |
| 1872 * @param type the type in which the setter is defined | |
| 1873 * @param setterName the name of the setter being looked up | |
| 1874 * @return the element representing the setter that was found | |
| 1875 */ | 1817 */ |
| 1876 PropertyAccessorElement _lookUpSetter( | 1818 PropertyAccessorElement _lookUpSetter( |
| 1877 Expression target, DartType type, String setterName) { | 1819 Expression target, DartType type, String setterName) { |
| 1878 type = _resolveTypeParameter(type); | 1820 type = _resolveTypeParameter(type); |
| 1879 if (type is InterfaceType) { | 1821 if (type is InterfaceType) { |
| 1880 InterfaceType interfaceType = type; | 1822 InterfaceType interfaceType = type; |
| 1881 PropertyAccessorElement accessor; | 1823 PropertyAccessorElement accessor; |
| 1882 if (target is SuperExpression) { | 1824 if (target is SuperExpression) { |
| 1883 accessor = interfaceType.lookUpSetterInSuperclass( | 1825 accessor = interfaceType.lookUpSetterInSuperclass( |
| 1884 setterName, _definingLibrary); | 1826 setterName, _definingLibrary); |
| 1885 } else { | 1827 } else { |
| 1886 accessor = interfaceType.lookUpSetter(setterName, _definingLibrary); | 1828 accessor = interfaceType.lookUpSetter(setterName, _definingLibrary); |
| 1887 } | 1829 } |
| 1888 if (accessor != null) { | 1830 if (accessor != null) { |
| 1889 return accessor; | 1831 return accessor; |
| 1890 } | 1832 } |
| 1891 return _lookUpSetterInInterfaces( | 1833 return _lookUpSetterInInterfaces( |
| 1892 interfaceType, false, setterName, new HashSet<ClassElement>()); | 1834 interfaceType, false, setterName, new HashSet<ClassElement>()); |
| 1893 } | 1835 } |
| 1894 return null; | 1836 return null; |
| 1895 } | 1837 } |
| 1896 | 1838 |
| 1897 /** | 1839 /** |
| 1898 * Look up the setter with the given name in the interfaces implemented by the
given type, either | 1840 * Look up the setter with the given [setterName] in the interfaces |
| 1899 * directly or indirectly. Return the element representing the setter that was
found, or | 1841 * implemented by the given [targetType], either directly or indirectly. |
| 1900 * `null` if there is no setter with the given name. | 1842 * Return the element representing the setter that was found, or `null` if |
| 1901 * | 1843 * there is no setter with the given name. The [targetType] is the type in |
| 1902 * @param targetType the type in which the setter might be defined | 1844 * which the setter might be defined. The flag [includeTargetType] should be |
| 1903 * @param includeTargetType `true` if the search should include the target typ
e | 1845 * `true` if the search should include the target type. The |
| 1904 * @param setterName the name of the setter being looked up | 1846 * [visitedInterfaces] is a set containing all of the interfaces that have |
| 1905 * @param visitedInterfaces a set containing all of the interfaces that have b
een examined, used | 1847 * been examined, used to prevent infinite recursion and to optimize the |
| 1906 * to prevent infinite recursion and to optimize the search | 1848 * search. |
| 1907 * @return the element representing the setter that was found | |
| 1908 */ | 1849 */ |
| 1909 PropertyAccessorElement _lookUpSetterInInterfaces(InterfaceType targetType, | 1850 PropertyAccessorElement _lookUpSetterInInterfaces(InterfaceType targetType, |
| 1910 bool includeTargetType, String setterName, | 1851 bool includeTargetType, String setterName, |
| 1911 HashSet<ClassElement> visitedInterfaces) { | 1852 HashSet<ClassElement> visitedInterfaces) { |
| 1912 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the | 1853 // TODO(brianwilkerson) This isn't correct. Section 8.1.1 of the |
| 1913 // specification (titled "Inheritance and Overriding" under "Interfaces") | 1854 // specification (titled "Inheritance and Overriding" under "Interfaces") |
| 1914 // describes a much more complex scheme for finding the inherited member. | 1855 // describes a much more complex scheme for finding the inherited member. |
| 1915 // We need to follow that scheme. The code below should cover the 80% case. | 1856 // We need to follow that scheme. The code below should cover the 80% case. |
| 1916 ClassElement targetClass = targetType.element; | 1857 ClassElement targetClass = targetType.element; |
| 1917 if (visitedInterfaces.contains(targetClass)) { | 1858 if (visitedInterfaces.contains(targetClass)) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1940 } | 1881 } |
| 1941 InterfaceType superclass = targetType.superclass; | 1882 InterfaceType superclass = targetType.superclass; |
| 1942 if (superclass == null) { | 1883 if (superclass == null) { |
| 1943 return null; | 1884 return null; |
| 1944 } | 1885 } |
| 1945 return _lookUpSetterInInterfaces( | 1886 return _lookUpSetterInInterfaces( |
| 1946 superclass, true, setterName, visitedInterfaces); | 1887 superclass, true, setterName, visitedInterfaces); |
| 1947 } | 1888 } |
| 1948 | 1889 |
| 1949 /** | 1890 /** |
| 1950 * Given some class element, this method uses [subtypeManager] to find the set
of all | 1891 * Given some class [element], this method uses [_subtypeManager] to find the |
| 1951 * subtypes; the subtypes are then searched for a member (method, getter, or s
etter), that matches | 1892 * set of all subtypes; the subtypes are then searched for a member (method, |
| 1952 * a passed | 1893 * getter, or setter), that has the given [memberName]. The flag [asMethod] |
| 1953 * | 1894 * should be `true` if the methods should be searched for in the subtypes. The |
| 1954 * @param element the class element to search the subtypes of, if a non-ClassE
lement element is | 1895 * flag [asAccessor] should be `true` if the accessors (getters and setters) |
| 1955 * passed, then `false` is returned | 1896 * should be searched for in the subtypes. |
| 1956 * @param memberName the member name to search for | |
| 1957 * @param asMethod `true` if the methods should be searched for in the subtype
s | |
| 1958 * @param asAccessor `true` if the accessors (getters and setters) should be s
earched for in | |
| 1959 * the subtypes | |
| 1960 * @return `true` if and only if the passed memberName was found in a subtype | |
| 1961 */ | 1897 */ |
| 1962 bool _memberFoundInSubclass( | 1898 bool _memberFoundInSubclass( |
| 1963 Element element, String memberName, bool asMethod, bool asAccessor) { | 1899 Element element, String memberName, bool asMethod, bool asAccessor) { |
| 1964 if (element is ClassElement) { | 1900 if (element is ClassElement) { |
| 1965 _subtypeManager.ensureLibraryVisited(_definingLibrary); | 1901 _subtypeManager.ensureLibraryVisited(_definingLibrary); |
| 1966 HashSet<ClassElement> subtypeElements = | 1902 HashSet<ClassElement> subtypeElements = |
| 1967 _subtypeManager.computeAllSubtypes(element); | 1903 _subtypeManager.computeAllSubtypes(element); |
| 1968 for (ClassElement subtypeElement in subtypeElements) { | 1904 for (ClassElement subtypeElement in subtypeElements) { |
| 1969 if (asMethod && subtypeElement.getMethod(memberName) != null) { | 1905 if (asMethod && subtypeElement.getMethod(memberName) != null) { |
| 1970 return true; | 1906 return true; |
| 1971 } else if (asAccessor && | 1907 } else if (asAccessor && |
| 1972 (subtypeElement.getGetter(memberName) != null || | 1908 (subtypeElement.getGetter(memberName) != null || |
| 1973 subtypeElement.getSetter(memberName) != null)) { | 1909 subtypeElement.getSetter(memberName) != null)) { |
| 1974 return true; | 1910 return true; |
| 1975 } | 1911 } |
| 1976 } | 1912 } |
| 1977 } | 1913 } |
| 1978 return false; | 1914 return false; |
| 1979 } | 1915 } |
| 1980 | 1916 |
| 1981 /** | 1917 /** |
| 1982 * Return the binary operator that is invoked by the given compound assignment
operator. | 1918 * Return the binary operator that is invoked by the given compound assignment |
| 1983 * | 1919 * [operator]. |
| 1984 * @param operator the assignment operator being mapped | |
| 1985 * @return the binary operator that invoked by the given assignment operator | |
| 1986 */ | 1920 */ |
| 1987 sc.TokenType _operatorFromCompoundAssignment(sc.TokenType operator) { | 1921 sc.TokenType _operatorFromCompoundAssignment(sc.TokenType operator) { |
| 1988 while (true) { | 1922 while (true) { |
| 1989 if (operator == sc.TokenType.AMPERSAND_EQ) { | 1923 if (operator == sc.TokenType.AMPERSAND_EQ) { |
| 1990 return sc.TokenType.AMPERSAND; | 1924 return sc.TokenType.AMPERSAND; |
| 1991 } else if (operator == sc.TokenType.BAR_EQ) { | 1925 } else if (operator == sc.TokenType.BAR_EQ) { |
| 1992 return sc.TokenType.BAR; | 1926 return sc.TokenType.BAR; |
| 1993 } else if (operator == sc.TokenType.CARET_EQ) { | 1927 } else if (operator == sc.TokenType.CARET_EQ) { |
| 1994 return sc.TokenType.CARET; | 1928 return sc.TokenType.CARET; |
| 1995 } else if (operator == sc.TokenType.GT_GT_EQ) { | 1929 } else if (operator == sc.TokenType.GT_GT_EQ) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2012 // Internal error: Unmapped assignment operator. | 1946 // Internal error: Unmapped assignment operator. |
| 2013 AnalysisEngine.instance.logger.logError( | 1947 AnalysisEngine.instance.logger.logError( |
| 2014 "Failed to map ${operator.lexeme} to it's corresponding operator"); | 1948 "Failed to map ${operator.lexeme} to it's corresponding operator"); |
| 2015 return operator; | 1949 return operator; |
| 2016 } | 1950 } |
| 2017 break; | 1951 break; |
| 2018 } | 1952 } |
| 2019 } | 1953 } |
| 2020 | 1954 |
| 2021 /** | 1955 /** |
| 2022 * Record that the given node is undefined, causing an error to be reported if
appropriate. | 1956 * Record that the given [node] is undefined, causing an error to be reported |
| 2023 * | 1957 * if appropriate. The [declaringElement] is the element inside which no |
| 2024 * @param declaringElement the element inside which no declaration was found.
If this element is a | 1958 * declaration was found. If this element is a proxy, no error will be |
| 2025 * proxy, no error will be reported. If null, then an error will alwa
ys be reported. | 1959 * reported. If null, then an error will always be reported. The [errorCode] |
| 2026 * @param errorCode the error code to report. | 1960 * is the error code to report. The [arguments] are the arguments to the error |
| 2027 * @param node the node which is undefined. | 1961 * message. |
| 2028 * @param arguments arguments to the error message. | |
| 2029 */ | 1962 */ |
| 2030 void _recordUndefinedNode(Element declaringElement, ErrorCode errorCode, | 1963 void _recordUndefinedNode(Element declaringElement, ErrorCode errorCode, |
| 2031 AstNode node, List<Object> arguments) { | 1964 AstNode node, List<Object> arguments) { |
| 2032 if (_doesntHaveProxy(declaringElement)) { | 1965 if (_doesntHaveProxy(declaringElement)) { |
| 2033 _resolver.reportErrorForNode(errorCode, node, arguments); | 1966 _resolver.reportErrorForNode(errorCode, node, arguments); |
| 2034 } | 1967 } |
| 2035 } | 1968 } |
| 2036 | 1969 |
| 2037 /** | 1970 /** |
| 2038 * Record that the given offset/length is undefined, causing an error to be re
ported if | 1971 * Record that the given [offset]/[length] is undefined, causing an error to |
| 2039 * appropriate. | 1972 * be reported if appropriate. The [declaringElement] is the element inside |
| 2040 * | 1973 * which no declaration was found. If this element is a proxy, no error will |
| 2041 * @param declaringElement the element inside which no declaration was found.
If this element is a | 1974 * be reported. If null, then an error will always be reported. The |
| 2042 * proxy, no error will be reported. If null, then an error will alwa
ys be reported. | 1975 * [errorCode] is the error code to report. The [arguments] are arguments to |
| 2043 * @param errorCode the error code to report. | 1976 * the error message. |
| 2044 * @param offset the offset to the text which is undefined. | |
| 2045 * @param length the length of the text which is undefined. | |
| 2046 * @param arguments arguments to the error message. | |
| 2047 */ | 1977 */ |
| 2048 void _recordUndefinedOffset(Element declaringElement, ErrorCode errorCode, | 1978 void _recordUndefinedOffset(Element declaringElement, ErrorCode errorCode, |
| 2049 int offset, int length, List<Object> arguments) { | 1979 int offset, int length, List<Object> arguments) { |
| 2050 if (_doesntHaveProxy(declaringElement)) { | 1980 if (_doesntHaveProxy(declaringElement)) { |
| 2051 _resolver.reportErrorForOffset(errorCode, offset, length, arguments); | 1981 _resolver.reportErrorForOffset(errorCode, offset, length, arguments); |
| 2052 } | 1982 } |
| 2053 } | 1983 } |
| 2054 | 1984 |
| 2055 /** | 1985 /** |
| 2056 * Record that the given token is undefined, causing an error to be reported i
f appropriate. | 1986 * Record that the given [token] is undefined, causing an error to be reported |
| 2057 * | 1987 * if appropriate. The [declaringElement] is the element inside which no |
| 2058 * @param declaringElement the element inside which no declaration was found.
If this element is a | 1988 * declaration was found. If this element is a proxy, no error will be |
| 2059 * proxy, no error will be reported. If null, then an error will alwa
ys be reported. | 1989 * reported. If null, then an error will always be reported. The [errorCode] |
| 2060 * @param errorCode the error code to report. | 1990 * is the error code to report. The [arguments] are arguments to the error |
| 2061 * @param token the token which is undefined. | 1991 * message. |
| 2062 * @param arguments arguments to the error message. | |
| 2063 */ | 1992 */ |
| 2064 void _recordUndefinedToken(Element declaringElement, ErrorCode errorCode, | 1993 void _recordUndefinedToken(Element declaringElement, ErrorCode errorCode, |
| 2065 sc.Token token, List<Object> arguments) { | 1994 sc.Token token, List<Object> arguments) { |
| 2066 if (_doesntHaveProxy(declaringElement)) { | 1995 if (_doesntHaveProxy(declaringElement)) { |
| 2067 _resolver.reportErrorForToken(errorCode, token, arguments); | 1996 _resolver.reportErrorForToken(errorCode, token, arguments); |
| 2068 } | 1997 } |
| 2069 } | 1998 } |
| 2070 | 1999 |
| 2071 void _resolveAnnotationConstructorInvocationArguments( | 2000 void _resolveAnnotationConstructorInvocationArguments( |
| 2072 Annotation annotation, ConstructorElement constructor) { | 2001 Annotation annotation, ConstructorElement constructor) { |
| 2073 ArgumentList argumentList = annotation.arguments; | 2002 ArgumentList argumentList = annotation.arguments; |
| 2074 // error will be reported in ConstantVerifier | 2003 // error will be reported in ConstantVerifier |
| 2075 if (argumentList == null) { | 2004 if (argumentList == null) { |
| 2076 return; | 2005 return; |
| 2077 } | 2006 } |
| 2078 // resolve arguments to parameters | 2007 // resolve arguments to parameters |
| 2079 List<ParameterElement> parameters = | 2008 List<ParameterElement> parameters = |
| 2080 _resolveArgumentsToFunction(true, argumentList, constructor); | 2009 _resolveArgumentsToFunction(true, argumentList, constructor); |
| 2081 if (parameters != null) { | 2010 if (parameters != null) { |
| 2082 argumentList.correspondingStaticParameters = parameters; | 2011 argumentList.correspondingStaticParameters = parameters; |
| 2083 } | 2012 } |
| 2084 } | 2013 } |
| 2085 | 2014 |
| 2086 /** | 2015 /** |
| 2087 * Continues resolution of the given [Annotation]. | 2016 * Continues resolution of the given [annotation]. |
| 2088 * | |
| 2089 * @param annotation the [Annotation] to resolve | |
| 2090 */ | 2017 */ |
| 2091 void _resolveAnnotationElement(Annotation annotation) { | 2018 void _resolveAnnotationElement(Annotation annotation) { |
| 2092 SimpleIdentifier nameNode1; | 2019 SimpleIdentifier nameNode1; |
| 2093 SimpleIdentifier nameNode2; | 2020 SimpleIdentifier nameNode2; |
| 2094 { | 2021 { |
| 2095 Identifier annName = annotation.name; | 2022 Identifier annName = annotation.name; |
| 2096 if (annName is PrefixedIdentifier) { | 2023 if (annName is PrefixedIdentifier) { |
| 2097 PrefixedIdentifier prefixed = annName; | 2024 PrefixedIdentifier prefixed = annName; |
| 2098 nameNode1 = prefixed.prefix; | 2025 nameNode1 = prefixed.prefix; |
| 2099 nameNode2 = prefixed.identifier; | 2026 nameNode2 = prefixed.identifier; |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2199 VariableElement variableElement = accessorElement.variable; | 2126 VariableElement variableElement = accessorElement.variable; |
| 2200 if (!variableElement.isConst) { | 2127 if (!variableElement.isConst) { |
| 2201 _resolver.reportErrorForNode( | 2128 _resolver.reportErrorForNode( |
| 2202 CompileTimeErrorCode.INVALID_ANNOTATION, annotation); | 2129 CompileTimeErrorCode.INVALID_ANNOTATION, annotation); |
| 2203 } | 2130 } |
| 2204 // OK | 2131 // OK |
| 2205 return; | 2132 return; |
| 2206 } | 2133 } |
| 2207 | 2134 |
| 2208 /** | 2135 /** |
| 2209 * Given a list of arguments and the element that will be invoked using those
argument, compute | 2136 * Given an [argumentList] and the [executableElement] that will be invoked |
| 2210 * the list of parameters that correspond to the list of arguments. Return the
parameters that | 2137 * using those argument, compute the list of parameters that correspond to the |
| 2211 * correspond to the arguments, or `null` if no correspondence could be comput
ed. | 2138 * list of arguments. An error will be reported if any of the arguments cannot |
| 2212 * | 2139 * be matched to a parameter. The flag [reportError] should be `true` if a |
| 2213 * @param reportError if `true` then compile-time error should be reported; if
`false` | 2140 * compile-time error should be reported; or `false` if a compile-time warning |
| 2214 * then compile-time warning | 2141 * should be reported. Return the parameters that correspond to the arguments, |
| 2215 * @param argumentList the list of arguments being passed to the element | 2142 * or `null` if no correspondence could be computed. |
| 2216 * @param executableElement the element that will be invoked with the argument
s | |
| 2217 * @return the parameters that correspond to the arguments | |
| 2218 */ | 2143 */ |
| 2219 List<ParameterElement> _resolveArgumentsToFunction(bool reportError, | 2144 List<ParameterElement> _resolveArgumentsToFunction(bool reportError, |
| 2220 ArgumentList argumentList, ExecutableElement executableElement) { | 2145 ArgumentList argumentList, ExecutableElement executableElement) { |
| 2221 if (executableElement == null) { | 2146 if (executableElement == null) { |
| 2222 return null; | 2147 return null; |
| 2223 } | 2148 } |
| 2224 List<ParameterElement> parameters = executableElement.parameters; | 2149 List<ParameterElement> parameters = executableElement.parameters; |
| 2225 return _resolveArgumentsToParameters(reportError, argumentList, parameters); | 2150 return _resolveArgumentsToParameters(reportError, argumentList, parameters); |
| 2226 } | 2151 } |
| 2227 | 2152 |
| 2228 /** | 2153 /** |
| 2229 * Given a list of arguments and the parameters related to the element that wi
ll be invoked using | 2154 * Given an [argumentList] and the [parameters] related to the element that |
| 2230 * those argument, compute the list of parameters that correspond to the list
of arguments. Return | 2155 * will be invoked using those arguments, compute the list of parameters that |
| 2231 * the parameters that correspond to the arguments. | 2156 * correspond to the list of arguments. An error will be reported if any of |
| 2232 * | 2157 * the arguments cannot be matched to a parameter. The flag [reportError] |
| 2233 * @param reportError if `true` then compile-time error should be reported; if
`false` | 2158 * should be `true` if a compile-time error should be reported; or `false` if |
| 2234 * then compile-time warning | 2159 * a compile-time warning should be reported. Return the parameters that |
| 2235 * @param argumentList the list of arguments being passed to the element | 2160 * correspond to the arguments. |
| 2236 * @param parameters the of the function that will be invoked with the argumen
ts | |
| 2237 * @return the parameters that correspond to the arguments | |
| 2238 */ | 2161 */ |
| 2239 List<ParameterElement> _resolveArgumentsToParameters(bool reportError, | 2162 List<ParameterElement> _resolveArgumentsToParameters(bool reportError, |
| 2240 ArgumentList argumentList, List<ParameterElement> parameters) { | 2163 ArgumentList argumentList, List<ParameterElement> parameters) { |
| 2241 List<ParameterElement> requiredParameters = new List<ParameterElement>(); | 2164 List<ParameterElement> requiredParameters = new List<ParameterElement>(); |
| 2242 List<ParameterElement> positionalParameters = new List<ParameterElement>(); | 2165 List<ParameterElement> positionalParameters = new List<ParameterElement>(); |
| 2243 HashMap<String, ParameterElement> namedParameters = | 2166 HashMap<String, ParameterElement> namedParameters = |
| 2244 new HashMap<String, ParameterElement>(); | 2167 new HashMap<String, ParameterElement>(); |
| 2245 for (ParameterElement parameter in parameters) { | 2168 for (ParameterElement parameter in parameters) { |
| 2246 ParameterKind kind = parameter.parameterKind; | 2169 ParameterKind kind = parameter.parameterKind; |
| 2247 if (kind == ParameterKind.REQUIRED) { | 2170 if (kind == ParameterKind.REQUIRED) { |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2347 _recordUndefinedToken(propagatedType.element, | 2270 _recordUndefinedToken(propagatedType.element, |
| 2348 HintCode.UNDEFINED_OPERATOR, node.operator, [ | 2271 HintCode.UNDEFINED_OPERATOR, node.operator, [ |
| 2349 methodName, | 2272 methodName, |
| 2350 propagatedType.displayName | 2273 propagatedType.displayName |
| 2351 ]); | 2274 ]); |
| 2352 } | 2275 } |
| 2353 } | 2276 } |
| 2354 } | 2277 } |
| 2355 | 2278 |
| 2356 /** | 2279 /** |
| 2357 * Resolve the names in the given combinators in the scope of the given librar
y. | 2280 * Resolve the names in the given [combinators] in the scope of the given |
| 2358 * | 2281 * [library]. |
| 2359 * @param library the library that defines the names | |
| 2360 * @param combinators the combinators containing the names to be resolved | |
| 2361 */ | 2282 */ |
| 2362 void _resolveCombinators( | 2283 void _resolveCombinators( |
| 2363 LibraryElement library, NodeList<Combinator> combinators) { | 2284 LibraryElement library, NodeList<Combinator> combinators) { |
| 2364 if (library == null) { | 2285 if (library == null) { |
| 2365 // | 2286 // |
| 2366 // The library will be null if the directive containing the combinators | 2287 // The library will be null if the directive containing the combinators |
| 2367 // has a URI that is not valid. | 2288 // has a URI that is not valid. |
| 2368 // | 2289 // |
| 2369 return; | 2290 return; |
| 2370 } | 2291 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 2389 if (element is PropertyAccessorElement) { | 2310 if (element is PropertyAccessorElement) { |
| 2390 element = (element as PropertyAccessorElement).variable; | 2311 element = (element as PropertyAccessorElement).variable; |
| 2391 } | 2312 } |
| 2392 name.staticElement = element; | 2313 name.staticElement = element; |
| 2393 } | 2314 } |
| 2394 } | 2315 } |
| 2395 } | 2316 } |
| 2396 } | 2317 } |
| 2397 | 2318 |
| 2398 /** | 2319 /** |
| 2399 * Given that we are accessing a property of the given [classElement] with | 2320 * Given that we are accessing a property of the given [classElement] with the |
| 2400 * the given [propertyName], return the element that represents the property. | 2321 * given [propertyName], return the element that represents the property. |
| 2401 */ | 2322 */ |
| 2402 Element _resolveElement( | 2323 Element _resolveElement( |
| 2403 ClassElementImpl classElement, SimpleIdentifier propertyName) { | 2324 ClassElementImpl classElement, SimpleIdentifier propertyName) { |
| 2404 String name = propertyName.name; | 2325 String name = propertyName.name; |
| 2405 Element element = null; | 2326 Element element = null; |
| 2406 if (propertyName.inSetterContext()) { | 2327 if (propertyName.inSetterContext()) { |
| 2407 element = classElement.getSetter(name); | 2328 element = classElement.getSetter(name); |
| 2408 } | 2329 } |
| 2409 if (element == null) { | 2330 if (element == null) { |
| 2410 element = classElement.getGetter(name); | 2331 element = classElement.getGetter(name); |
| 2411 } | 2332 } |
| 2412 if (element == null) { | 2333 if (element == null) { |
| 2413 element = classElement.getMethod(name); | 2334 element = classElement.getMethod(name); |
| 2414 } | 2335 } |
| 2415 if (element != null && element.isAccessibleIn(_definingLibrary)) { | 2336 if (element != null && element.isAccessibleIn(_definingLibrary)) { |
| 2416 return element; | 2337 return element; |
| 2417 } | 2338 } |
| 2418 return null; | 2339 return null; |
| 2419 } | 2340 } |
| 2420 | 2341 |
| 2421 /** | 2342 /** |
| 2422 * Given an invocation of the form 'm(a1, ..., an)', resolve 'm' to the elemen
t being invoked. If | 2343 * Given an invocation of the form 'm(a1, ..., an)', resolve 'm' to the |
| 2423 * the returned element is a method, then the method will be invoked. If the r
eturned element is a | 2344 * element being invoked. If the returned element is a method, then the method |
| 2424 * getter, the getter will be invoked without arguments and the result of that
invocation will | 2345 * will be invoked. If the returned element is a getter, the getter will be |
| 2425 * then be invoked with the arguments. | 2346 * invoked without arguments and the result of that invocation will then be |
| 2426 * | 2347 * invoked with the arguments. The [methodName] is the name of the method |
| 2427 * @param methodName the name of the method being invoked ('m') | 2348 * being invoked ('m'). |
| 2428 * @return the element being invoked | |
| 2429 */ | 2349 */ |
| 2430 Element _resolveInvokedElement(SimpleIdentifier methodName) { | 2350 Element _resolveInvokedElement(SimpleIdentifier methodName) { |
| 2431 // | 2351 // |
| 2432 // Look first in the lexical scope. | 2352 // Look first in the lexical scope. |
| 2433 // | 2353 // |
| 2434 Element element = _resolver.nameScope.lookup(methodName, _definingLibrary); | 2354 Element element = _resolver.nameScope.lookup(methodName, _definingLibrary); |
| 2435 if (element == null) { | 2355 if (element == null) { |
| 2436 // | 2356 // |
| 2437 // If it isn't defined in the lexical scope, and the invocation is within | 2357 // If it isn't defined in the lexical scope, and the invocation is within |
| 2438 // a class, then look in the inheritance scope. | 2358 // a class, then look in the inheritance scope. |
| 2439 // | 2359 // |
| 2440 ClassElement enclosingClass = _resolver.enclosingClass; | 2360 ClassElement enclosingClass = _resolver.enclosingClass; |
| 2441 if (enclosingClass != null) { | 2361 if (enclosingClass != null) { |
| 2442 InterfaceType enclosingType = enclosingClass.type; | 2362 InterfaceType enclosingType = enclosingClass.type; |
| 2443 element = _lookUpMethod(null, enclosingType, methodName.name); | 2363 element = _lookUpMethod(null, enclosingType, methodName.name); |
| 2444 if (element == null) { | 2364 if (element == null) { |
| 2445 // | 2365 // |
| 2446 // If there's no method, then it's possible that 'm' is a getter that | 2366 // If there's no method, then it's possible that 'm' is a getter that |
| 2447 // returns a function. | 2367 // returns a function. |
| 2448 // | 2368 // |
| 2449 element = _lookUpGetter(null, enclosingType, methodName.name); | 2369 element = _lookUpGetter(null, enclosingType, methodName.name); |
| 2450 } | 2370 } |
| 2451 } | 2371 } |
| 2452 } | 2372 } |
| 2453 // TODO(brianwilkerson) Report this error. | 2373 // TODO(brianwilkerson) Report this error. |
| 2454 return element; | 2374 return element; |
| 2455 } | 2375 } |
| 2456 | 2376 |
| 2457 /** | 2377 /** |
| 2458 * Given an invocation of the form 'e.m(a1, ..., an)', resolve 'e.m' to the el
ement being invoked. | 2378 * Given an invocation of the form 'e.m(a1, ..., an)', resolve 'e.m' to the |
| 2459 * If the returned element is a method, then the method will be invoked. If th
e returned element | 2379 * element being invoked. If the returned element is a method, then the method |
| 2460 * is a getter, the getter will be invoked without arguments and the result of
that invocation | 2380 * will be invoked. If the returned element is a getter, the getter will be |
| 2461 * will then be invoked with the arguments. | 2381 * invoked without arguments and the result of that invocation will then be |
| 2462 * | 2382 * invoked with the arguments. The [target] is the target of the invocation |
| 2463 * @param target the target of the invocation ('e') | 2383 * ('e'). The [targetType] is the type of the target. The [methodName] is th |
| 2464 * @param targetType the type of the target | 2384 * name of the method being invoked ('m'). |
| 2465 * @param methodName the name of the method being invoked ('m') | |
| 2466 * @return the element being invoked | |
| 2467 */ | 2385 */ |
| 2468 Element _resolveInvokedElementWithTarget( | 2386 Element _resolveInvokedElementWithTarget( |
| 2469 Expression target, DartType targetType, SimpleIdentifier methodName) { | 2387 Expression target, DartType targetType, SimpleIdentifier methodName) { |
| 2470 if (targetType is InterfaceType || targetType is UnionType) { | 2388 if (targetType is InterfaceType || targetType is UnionType) { |
| 2471 Element element = _lookUpMethod(target, targetType, methodName.name); | 2389 Element element = _lookUpMethod(target, targetType, methodName.name); |
| 2472 if (element == null) { | 2390 if (element == null) { |
| 2473 // | 2391 // |
| 2474 // If there's no method, then it's possible that 'm' is a getter that | 2392 // If there's no method, then it's possible that 'm' is a getter that |
| 2475 // returns a function. | 2393 // returns a function. |
| 2476 // | 2394 // |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2497 // identifier. Consider re-writing the AST. | 2415 // identifier. Consider re-writing the AST. |
| 2498 return element; | 2416 return element; |
| 2499 } | 2417 } |
| 2500 } | 2418 } |
| 2501 } | 2419 } |
| 2502 // TODO(brianwilkerson) Report this error. | 2420 // TODO(brianwilkerson) Report this error. |
| 2503 return null; | 2421 return null; |
| 2504 } | 2422 } |
| 2505 | 2423 |
| 2506 /** | 2424 /** |
| 2507 * Given that we are accessing a property of the given type with the given nam
e, return the | 2425 * Given that we are accessing a property of the given [targetType] with the |
| 2508 * element that represents the property. | 2426 * given [propertyName], return the element that represents the property. The |
| 2509 * | 2427 * [target] is the target of the invocation ('e'). |
| 2510 * @param target the target of the invocation ('e') | |
| 2511 * @param targetType the type in which the search for the property should begi
n | |
| 2512 * @param propertyName the name of the property being accessed | |
| 2513 * @return the element that represents the property | |
| 2514 */ | 2428 */ |
| 2515 ExecutableElement _resolveProperty( | 2429 ExecutableElement _resolveProperty( |
| 2516 Expression target, DartType targetType, SimpleIdentifier propertyName) { | 2430 Expression target, DartType targetType, SimpleIdentifier propertyName) { |
| 2517 ExecutableElement memberElement = null; | 2431 ExecutableElement memberElement = null; |
| 2518 if (propertyName.inSetterContext()) { | 2432 if (propertyName.inSetterContext()) { |
| 2519 memberElement = _lookUpSetter(target, targetType, propertyName.name); | 2433 memberElement = _lookUpSetter(target, targetType, propertyName.name); |
| 2520 } | 2434 } |
| 2521 if (memberElement == null) { | 2435 if (memberElement == null) { |
| 2522 memberElement = _lookUpGetter(target, targetType, propertyName.name); | 2436 memberElement = _lookUpGetter(target, targetType, propertyName.name); |
| 2523 } | 2437 } |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2654 ]); | 2568 ]); |
| 2655 } else { | 2569 } else { |
| 2656 _recordUndefinedNode(declaringElement, | 2570 _recordUndefinedNode(declaringElement, |
| 2657 StaticWarningCode.UNDEFINED_IDENTIFIER, propertyName, | 2571 StaticWarningCode.UNDEFINED_IDENTIFIER, propertyName, |
| 2658 [propertyName.name]); | 2572 [propertyName.name]); |
| 2659 } | 2573 } |
| 2660 } | 2574 } |
| 2661 } | 2575 } |
| 2662 | 2576 |
| 2663 /** | 2577 /** |
| 2664 * Resolve the given simple identifier if possible. Return the element to whic
h it could be | 2578 * Resolve the given simple [identifier] if possible. Return the element to |
| 2665 * resolved, or `null` if it could not be resolved. This does not record the r
esults of the | 2579 * which it could be resolved, or `null` if it could not be resolved. This |
| 2666 * resolution. | 2580 * does not record the results of the resolution. |
| 2667 * | |
| 2668 * @param node the identifier to be resolved | |
| 2669 * @return the element to which the identifier could be resolved | |
| 2670 */ | 2581 */ |
| 2671 Element _resolveSimpleIdentifier(SimpleIdentifier node) { | 2582 Element _resolveSimpleIdentifier(SimpleIdentifier identifier) { |
| 2672 Element element = _resolver.nameScope.lookup(node, _definingLibrary); | 2583 Element element = _resolver.nameScope.lookup(identifier, _definingLibrary); |
| 2673 if (element is PropertyAccessorElement && node.inSetterContext()) { | 2584 if (element is PropertyAccessorElement && identifier.inSetterContext()) { |
| 2674 PropertyInducingElement variable = | 2585 PropertyInducingElement variable = |
| 2675 (element as PropertyAccessorElement).variable; | 2586 (element as PropertyAccessorElement).variable; |
| 2676 if (variable != null) { | 2587 if (variable != null) { |
| 2677 PropertyAccessorElement setter = variable.setter; | 2588 PropertyAccessorElement setter = variable.setter; |
| 2678 if (setter == null) { | 2589 if (setter == null) { |
| 2679 // | 2590 // |
| 2680 // Check to see whether there might be a locally defined getter and | 2591 // Check to see whether there might be a locally defined getter and |
| 2681 // an inherited setter. | 2592 // an inherited setter. |
| 2682 // | 2593 // |
| 2683 ClassElement enclosingClass = _resolver.enclosingClass; | 2594 ClassElement enclosingClass = _resolver.enclosingClass; |
| 2684 if (enclosingClass != null) { | 2595 if (enclosingClass != null) { |
| 2685 setter = _lookUpSetter(null, enclosingClass.type, node.name); | 2596 setter = _lookUpSetter(null, enclosingClass.type, identifier.name); |
| 2686 } | 2597 } |
| 2687 } | 2598 } |
| 2688 if (setter != null) { | 2599 if (setter != null) { |
| 2689 element = setter; | 2600 element = setter; |
| 2690 } | 2601 } |
| 2691 } | 2602 } |
| 2692 } else if (element == null && | 2603 } else if (element == null && |
| 2693 (node.inSetterContext() || node.parent is CommentReference)) { | 2604 (identifier.inSetterContext() || |
| 2605 identifier.parent is CommentReference)) { |
| 2694 element = _resolver.nameScope.lookup( | 2606 element = _resolver.nameScope.lookup( |
| 2695 new SyntheticIdentifier("${node.name}=", node), _definingLibrary); | 2607 new SyntheticIdentifier("${identifier.name}=", identifier), |
| 2608 _definingLibrary); |
| 2696 } | 2609 } |
| 2697 ClassElement enclosingClass = _resolver.enclosingClass; | 2610 ClassElement enclosingClass = _resolver.enclosingClass; |
| 2698 if (element == null && enclosingClass != null) { | 2611 if (element == null && enclosingClass != null) { |
| 2699 InterfaceType enclosingType = enclosingClass.type; | 2612 InterfaceType enclosingType = enclosingClass.type; |
| 2700 if (element == null && | 2613 if (element == null && |
| 2701 (node.inSetterContext() || node.parent is CommentReference)) { | 2614 (identifier.inSetterContext() || |
| 2702 element = _lookUpSetter(null, enclosingType, node.name); | 2615 identifier.parent is CommentReference)) { |
| 2616 element = _lookUpSetter(null, enclosingType, identifier.name); |
| 2703 } | 2617 } |
| 2704 if (element == null && node.inGetterContext()) { | 2618 if (element == null && identifier.inGetterContext()) { |
| 2705 element = _lookUpGetter(null, enclosingType, node.name); | 2619 element = _lookUpGetter(null, enclosingType, identifier.name); |
| 2706 } | 2620 } |
| 2707 if (element == null) { | 2621 if (element == null) { |
| 2708 element = _lookUpMethod(null, enclosingType, node.name); | 2622 element = _lookUpMethod(null, enclosingType, identifier.name); |
| 2709 } | 2623 } |
| 2710 } | 2624 } |
| 2711 return element; | 2625 return element; |
| 2712 } | 2626 } |
| 2713 | 2627 |
| 2714 /** | 2628 /** |
| 2715 * If the given type is a type parameter, resolve it to the type that should b
e used when looking | 2629 * If the given [type] is a type parameter, resolve it to the type that should |
| 2716 * up members. Otherwise, return the original type. | 2630 * be used when looking up members. Otherwise, return the original type. |
| 2717 * | |
| 2718 * @param type the type that is to be resolved if it is a type parameter | |
| 2719 * @return the type that should be used in place of the argument if it is a ty
pe parameter, or the | |
| 2720 * original argument if it isn't a type parameter | |
| 2721 */ | 2631 */ |
| 2722 DartType _resolveTypeParameter(DartType type) { | 2632 DartType _resolveTypeParameter(DartType type) { |
| 2723 if (type is TypeParameterType) { | 2633 if (type is TypeParameterType) { |
| 2724 DartType bound = type.element.bound; | 2634 DartType bound = type.element.bound; |
| 2725 if (bound == null) { | 2635 if (bound == null) { |
| 2726 return _resolver.typeProvider.objectType; | 2636 return _resolver.typeProvider.objectType; |
| 2727 } | 2637 } |
| 2728 return bound; | 2638 return bound; |
| 2729 } | 2639 } |
| 2730 return type; | 2640 return type; |
| 2731 } | 2641 } |
| 2732 | 2642 |
| 2733 /** | 2643 /** |
| 2734 * Given a node that can have annotations associated with it and the element t
o which that node | 2644 * Given a [node] that can have annotations associated with it and the |
| 2735 * has been resolved, create the annotations in the element model representing
the annotations on | 2645 * [element] to which that node has been resolved, create the annotations in |
| 2736 * the node. | 2646 * the element model representing the annotations on the node. |
| 2737 * | |
| 2738 * @param element the element to which the node has been resolved | |
| 2739 * @param node the node that can have annotations associated with it | |
| 2740 */ | 2647 */ |
| 2741 void _setMetadata(Element element, AnnotatedNode node) { | 2648 void _setMetadata(Element element, AnnotatedNode node) { |
| 2742 if (element is! ElementImpl) { | 2649 if (element is! ElementImpl) { |
| 2743 return; | 2650 return; |
| 2744 } | 2651 } |
| 2745 List<ElementAnnotationImpl> annotationList = | 2652 List<ElementAnnotationImpl> annotationList = |
| 2746 new List<ElementAnnotationImpl>(); | 2653 new List<ElementAnnotationImpl>(); |
| 2747 _addAnnotations(annotationList, node.metadata); | 2654 _addAnnotations(annotationList, node.metadata); |
| 2748 if (node is VariableDeclaration && node.parent is VariableDeclarationList) { | 2655 if (node is VariableDeclaration && node.parent is VariableDeclarationList) { |
| 2749 VariableDeclarationList list = node.parent as VariableDeclarationList; | 2656 VariableDeclarationList list = node.parent as VariableDeclarationList; |
| 2750 _addAnnotations(annotationList, list.metadata); | 2657 _addAnnotations(annotationList, list.metadata); |
| 2751 if (list.parent is FieldDeclaration) { | 2658 if (list.parent is FieldDeclaration) { |
| 2752 FieldDeclaration fieldDeclaration = list.parent as FieldDeclaration; | 2659 FieldDeclaration fieldDeclaration = list.parent as FieldDeclaration; |
| 2753 _addAnnotations(annotationList, fieldDeclaration.metadata); | 2660 _addAnnotations(annotationList, fieldDeclaration.metadata); |
| 2754 } else if (list.parent is TopLevelVariableDeclaration) { | 2661 } else if (list.parent is TopLevelVariableDeclaration) { |
| 2755 TopLevelVariableDeclaration variableDeclaration = | 2662 TopLevelVariableDeclaration variableDeclaration = |
| 2756 list.parent as TopLevelVariableDeclaration; | 2663 list.parent as TopLevelVariableDeclaration; |
| 2757 _addAnnotations(annotationList, variableDeclaration.metadata); | 2664 _addAnnotations(annotationList, variableDeclaration.metadata); |
| 2758 } | 2665 } |
| 2759 } | 2666 } |
| 2760 if (!annotationList.isEmpty) { | 2667 if (!annotationList.isEmpty) { |
| 2761 (element as ElementImpl).metadata = annotationList; | 2668 (element as ElementImpl).metadata = annotationList; |
| 2762 } | 2669 } |
| 2763 } | 2670 } |
| 2764 | 2671 |
| 2765 /** | 2672 /** |
| 2766 * Given a node that can have annotations associated with it and the element t
o which that node | 2673 * Given a [node] that can have annotations associated with it and the |
| 2767 * has been resolved, create the annotations in the element model representing
the annotations on | 2674 * [element] to which that node has been resolved, create the annotations in |
| 2768 * the node. | 2675 * the element model representing the annotations on the node. |
| 2769 * | |
| 2770 * @param element the element to which the node has been resolved | |
| 2771 * @param node the node that can have annotations associated with it | |
| 2772 */ | 2676 */ |
| 2773 void _setMetadataForParameter(Element element, NormalFormalParameter node) { | 2677 void _setMetadataForParameter(Element element, NormalFormalParameter node) { |
| 2774 if (element is! ElementImpl) { | 2678 if (element is! ElementImpl) { |
| 2775 return; | 2679 return; |
| 2776 } | 2680 } |
| 2777 List<ElementAnnotationImpl> annotationList = | 2681 List<ElementAnnotationImpl> annotationList = |
| 2778 new List<ElementAnnotationImpl>(); | 2682 new List<ElementAnnotationImpl>(); |
| 2779 _addAnnotations(annotationList, node.metadata); | 2683 _addAnnotations(annotationList, node.metadata); |
| 2780 if (!annotationList.isEmpty) { | 2684 if (!annotationList.isEmpty) { |
| 2781 (element as ElementImpl).metadata = annotationList; | 2685 (element as ElementImpl).metadata = annotationList; |
| 2782 } | 2686 } |
| 2783 } | 2687 } |
| 2784 | 2688 |
| 2785 /** | 2689 /** |
| 2786 * Return `true` if we should report an error as a result of looking up a memb
er in the | 2690 * Return `true` if we should report an error as a result of looking up a |
| 2787 * given type and not finding any member. | 2691 * [member] in the given [type] and not finding any member. |
| 2788 * | |
| 2789 * @param type the type in which we attempted to perform the look-up | |
| 2790 * @param member the result of the look-up | |
| 2791 * @return `true` if we should report an error | |
| 2792 */ | 2692 */ |
| 2793 bool _shouldReportMissingMember(DartType type, Element member) { | 2693 bool _shouldReportMissingMember(DartType type, Element member) { |
| 2794 if (member != null || type == null || type.isDynamic || type.isBottom) { | 2694 if (member != null || type == null || type.isDynamic || type.isBottom) { |
| 2795 return false; | 2695 return false; |
| 2796 } | 2696 } |
| 2797 return true; | 2697 return true; |
| 2798 } | 2698 } |
| 2799 | 2699 |
| 2800 /** | 2700 /** |
| 2801 * Checks whether the given expression is a reference to a class. If it is the
n the | 2701 * Checks whether the given [expression] is a reference to a class. If it is |
| 2802 * [ClassElement] is returned, otherwise `null` is returned. | 2702 * then the element representing the class is returned, otherwise `null` is |
| 2803 * | 2703 * returned. |
| 2804 * @param expression the expression to evaluate | |
| 2805 * @return the element representing the class | |
| 2806 */ | 2704 */ |
| 2807 static ClassElementImpl getTypeReference(Expression expression) { | 2705 static ClassElementImpl getTypeReference(Expression expression) { |
| 2808 if (expression is Identifier) { | 2706 if (expression is Identifier) { |
| 2809 Element staticElement = expression.staticElement; | 2707 Element staticElement = expression.staticElement; |
| 2810 if (staticElement is ClassElementImpl) { | 2708 if (staticElement is ClassElementImpl) { |
| 2811 return staticElement; | 2709 return staticElement; |
| 2812 } | 2710 } |
| 2813 } | 2711 } |
| 2814 return null; | 2712 return null; |
| 2815 } | 2713 } |
| 2816 | 2714 |
| 2817 /** | 2715 /** |
| 2818 * Helper function for `maybeMergeExecutableElements` that does the actual mer
ging. | 2716 * Helper function for `maybeMergeExecutableElements` that does the actual |
| 2819 * | 2717 * merging. The [elementArrayToMerge] is the non-empty list of elements to |
| 2820 * @param elementArrayToMerge non-empty array of elements to merge. | 2718 * merge. |
| 2821 * @return | |
| 2822 */ | 2719 */ |
| 2823 static ExecutableElement _computeMergedExecutableElement( | 2720 static ExecutableElement _computeMergedExecutableElement( |
| 2824 List<ExecutableElement> elementArrayToMerge) { | 2721 List<ExecutableElement> elementArrayToMerge) { |
| 2825 // Flatten methods structurally. Based on | 2722 // Flatten methods structurally. Based on |
| 2826 // [InheritanceManager.computeMergedExecutableElement] and | 2723 // [InheritanceManager.computeMergedExecutableElement] and |
| 2827 // [InheritanceManager.createSyntheticExecutableElement]. | 2724 // [InheritanceManager.createSyntheticExecutableElement]. |
| 2828 // | 2725 // |
| 2829 // However, the approach we take here is much simpler, but expected to work | 2726 // However, the approach we take here is much simpler, but expected to work |
| 2830 // well in the common case. It degrades gracefully in the uncommon case, | 2727 // well in the common case. It degrades gracefully in the uncommon case, |
| 2831 // by computing the type [dynamic] for the method, preventing any | 2728 // by computing the type [dynamic] for the method, preventing any |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2883 e_out.synthetic = true; | 2780 e_out.synthetic = true; |
| 2884 e_out.returnType = r_out; | 2781 e_out.returnType = r_out; |
| 2885 e_out.parameters = ps_out; | 2782 e_out.parameters = ps_out; |
| 2886 e_out.type = new FunctionTypeImpl.con1(e_out); | 2783 e_out.type = new FunctionTypeImpl.con1(e_out); |
| 2887 // Get NPE in [toString()] w/o this. | 2784 // Get NPE in [toString()] w/o this. |
| 2888 e_out.enclosingElement = e_0.enclosingElement; | 2785 e_out.enclosingElement = e_0.enclosingElement; |
| 2889 return e_out; | 2786 return e_out; |
| 2890 } | 2787 } |
| 2891 | 2788 |
| 2892 /** | 2789 /** |
| 2893 * Return `true` if the given identifier is the return type of a constructor d
eclaration. | 2790 * Return `true` if the given [identifier] is the return type of a constructor |
| 2894 * | 2791 * declaration. |
| 2895 * @return `true` if the given identifier is the return type of a constructor
declaration. | |
| 2896 */ | 2792 */ |
| 2897 static bool _isConstructorReturnType(SimpleIdentifier identifier) { | 2793 static bool _isConstructorReturnType(SimpleIdentifier identifier) { |
| 2898 AstNode parent = identifier.parent; | 2794 AstNode parent = identifier.parent; |
| 2899 if (parent is ConstructorDeclaration) { | 2795 if (parent is ConstructorDeclaration) { |
| 2900 return identical(parent.returnType, identifier); | 2796 return identical(parent.returnType, identifier); |
| 2901 } | 2797 } |
| 2902 return false; | 2798 return false; |
| 2903 } | 2799 } |
| 2904 | 2800 |
| 2905 /** | 2801 /** |
| 2906 * Return `true` if the given identifier is the return type of a factory const
ructor. | 2802 * Return `true` if the given [identifier] is the return type of a factory |
| 2907 * | 2803 * constructor. |
| 2908 * @return `true` if the given identifier is the return type of a factory cons
tructor | |
| 2909 * declaration. | |
| 2910 */ | 2804 */ |
| 2911 static bool _isFactoryConstructorReturnType(SimpleIdentifier node) { | 2805 static bool _isFactoryConstructorReturnType(SimpleIdentifier identifier) { |
| 2912 AstNode parent = node.parent; | 2806 AstNode parent = identifier.parent; |
| 2913 if (parent is ConstructorDeclaration) { | 2807 if (parent is ConstructorDeclaration) { |
| 2914 ConstructorDeclaration constructor = parent; | 2808 ConstructorDeclaration constructor = parent; |
| 2915 return identical(constructor.returnType, node) && | 2809 return identical(constructor.returnType, identifier) && |
| 2916 constructor.factoryKeyword != null; | 2810 constructor.factoryKeyword != null; |
| 2917 } | 2811 } |
| 2918 return false; | 2812 return false; |
| 2919 } | 2813 } |
| 2920 | 2814 |
| 2921 /** | 2815 /** |
| 2922 * Return `true` if the given 'super' expression is used in a valid context. | 2816 * Return `true` if the given 'super' [expression] is used in a valid context. |
| 2923 * | |
| 2924 * @param node the 'super' expression to analyze | |
| 2925 * @return `true` if the 'super' expression is in a valid context | |
| 2926 */ | 2817 */ |
| 2927 static bool _isSuperInValidContext(SuperExpression node) { | 2818 static bool _isSuperInValidContext(SuperExpression expression) { |
| 2928 for (AstNode n = node; n != null; n = n.parent) { | 2819 for (AstNode node = expression; node != null; node = node.parent) { |
| 2929 if (n is CompilationUnit) { | 2820 if (node is CompilationUnit) { |
| 2930 return false; | 2821 return false; |
| 2931 } | 2822 } |
| 2932 if (n is ConstructorDeclaration) { | 2823 if (node is ConstructorDeclaration) { |
| 2933 return n.factoryKeyword == null; | 2824 return node.factoryKeyword == null; |
| 2934 } | 2825 } |
| 2935 if (n is ConstructorFieldInitializer) { | 2826 if (node is ConstructorFieldInitializer) { |
| 2936 return false; | 2827 return false; |
| 2937 } | 2828 } |
| 2938 if (n is MethodDeclaration) { | 2829 if (node is MethodDeclaration) { |
| 2939 return !n.isStatic; | 2830 return !node.isStatic; |
| 2940 } | 2831 } |
| 2941 } | 2832 } |
| 2942 return false; | 2833 return false; |
| 2943 } | 2834 } |
| 2944 | 2835 |
| 2945 /** | 2836 /** |
| 2946 * Return a method representing the merge of the given elements. The type of t
he merged element is | 2837 * Return a method representing the merge of the given [elements]. The type of |
| 2947 * the component-wise union of the types of the given elements. If not all inp
ut elements have the | 2838 * the merged element is the component-wise union of the types of the given |
| 2948 * same shape then [null] is returned. | 2839 * elements. If not all input elements have the same shape then `null` is |
| 2949 * | 2840 * returned. |
| 2950 * @param elements the `ExecutableElement`s to merge | |
| 2951 * @return an `ExecutableElement` representing the merge of `elements` | |
| 2952 */ | 2841 */ |
| 2953 static ExecutableElement _maybeMergeExecutableElements( | 2842 static ExecutableElement _maybeMergeExecutableElements( |
| 2954 Set<ExecutableElement> elements) { | 2843 Set<ExecutableElement> elements) { |
| 2955 List<ExecutableElement> elementArrayToMerge = new List.from(elements); | 2844 List<ExecutableElement> elementArrayToMerge = new List.from(elements); |
| 2956 if (elementArrayToMerge.length == 0) { | 2845 if (elementArrayToMerge.length == 0) { |
| 2957 return null; | 2846 return null; |
| 2958 } else if (elementArrayToMerge.length == 1) { | 2847 } else if (elementArrayToMerge.length == 1) { |
| 2959 // If all methods are equal, don't bother building a new one. | 2848 // If all methods are equal, don't bother building a new one. |
| 2960 return elementArrayToMerge[0]; | 2849 return elementArrayToMerge[0]; |
| 2961 } else { | 2850 } else { |
| 2962 return _computeMergedExecutableElement(elementArrayToMerge); | 2851 return _computeMergedExecutableElement(elementArrayToMerge); |
| 2963 } | 2852 } |
| 2964 } | 2853 } |
| 2965 } | 2854 } |
| 2966 | 2855 |
| 2967 /** | 2856 /** |
| 2968 * A `SyntheticIdentifier` is an identifier that can be used to look up names in | 2857 * An identifier that can be used to look up names in the lexical scope when |
| 2969 * the lexical scope when there is no identifier in the AST structure. There is | 2858 * there is no identifier in the AST structure. There is no identifier in the |
| 2970 * no identifier in the AST when the parser could not distinguish between a | 2859 * AST when the parser could not distinguish between a method invocation and an |
| 2971 * method invocation and an invocation of a top-level function imported with a | 2860 * invocation of a top-level function imported with a prefix. |
| 2972 * prefix. | |
| 2973 */ | 2861 */ |
| 2974 class SyntheticIdentifier extends Identifier { | 2862 class SyntheticIdentifier extends Identifier { |
| 2975 /** | 2863 /** |
| 2976 * The name of the synthetic identifier. | 2864 * The name of the synthetic identifier. |
| 2977 */ | 2865 */ |
| 2978 final String name; | 2866 final String name; |
| 2979 | 2867 |
| 2980 /** | 2868 /** |
| 2981 * The identifier to be highlighted in case of an error | 2869 * The identifier to be highlighted in case of an error |
| 2982 */ | 2870 */ |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3019 | 2907 |
| 3020 @override | 2908 @override |
| 3021 Element get staticElement => null; | 2909 Element get staticElement => null; |
| 3022 | 2910 |
| 3023 @override | 2911 @override |
| 3024 accept(AstVisitor visitor) => null; | 2912 accept(AstVisitor visitor) => null; |
| 3025 | 2913 |
| 3026 @override | 2914 @override |
| 3027 void visitChildren(AstVisitor visitor) {} | 2915 void visitChildren(AstVisitor visitor) {} |
| 3028 } | 2916 } |
| OLD | NEW |