| 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'; |
| (...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 // then we don't call resolveInvokedElement(...) which walks up the class | 602 // then we don't call resolveInvokedElement(...) which walks up the class |
| 603 // hierarchy, instead we just look for the member in the type only. This | 603 // hierarchy, instead we just look for the member in the type only. This |
| 604 // does not apply to conditional method invocation (i.e. 'C?.m(...)'). | 604 // does not apply to conditional method invocation (i.e. 'C?.m(...)'). |
| 605 // | 605 // |
| 606 bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD; | 606 bool isConditional = node.operator.type == sc.TokenType.QUESTION_PERIOD; |
| 607 ClassElementImpl typeReference = getTypeReference(target, isConditional); | 607 ClassElementImpl typeReference = getTypeReference(target, isConditional); |
| 608 if (typeReference != null) { | 608 if (typeReference != null) { |
| 609 staticElement = | 609 staticElement = |
| 610 propagatedElement = _resolveElement(typeReference, methodName); | 610 propagatedElement = _resolveElement(typeReference, methodName); |
| 611 } else { | 611 } else { |
| 612 staticElement = | 612 staticElement = _resolveInvokedElementWithTarget( |
| 613 _resolveInvokedElementWithTarget(target, staticType, methodName); | 613 target, staticType, methodName, isConditional); |
| 614 propagatedElement = _resolveInvokedElementWithTarget( | 614 propagatedElement = _resolveInvokedElementWithTarget( |
| 615 target, propagatedType, methodName); | 615 target, propagatedType, methodName, isConditional); |
| 616 } | 616 } |
| 617 } | 617 } |
| 618 staticElement = _convertSetterToGetter(staticElement); | 618 staticElement = _convertSetterToGetter(staticElement); |
| 619 propagatedElement = _convertSetterToGetter(propagatedElement); | 619 propagatedElement = _convertSetterToGetter(propagatedElement); |
| 620 // | 620 // |
| 621 // Record the results. | 621 // Record the results. |
| 622 // | 622 // |
| 623 methodName.staticElement = staticElement; | 623 methodName.staticElement = staticElement; |
| 624 methodName.propagatedElement = propagatedElement; | 624 methodName.propagatedElement = propagatedElement; |
| 625 ArgumentList argumentList = node.argumentList; | 625 ArgumentList argumentList = node.argumentList; |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 } else if (element == null || | 995 } else if (element == null || |
| 996 (element is PrefixElement && !_isValidAsPrefix(node))) { | 996 (element is PrefixElement && !_isValidAsPrefix(node))) { |
| 997 // TODO(brianwilkerson) Recover from this error. | 997 // TODO(brianwilkerson) Recover from this error. |
| 998 if (_isConstructorReturnType(node)) { | 998 if (_isConstructorReturnType(node)) { |
| 999 _resolver.reportErrorForNode( | 999 _resolver.reportErrorForNode( |
| 1000 CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node); | 1000 CompileTimeErrorCode.INVALID_CONSTRUCTOR_NAME, node); |
| 1001 } else if (node.parent is Annotation) { | 1001 } else if (node.parent is Annotation) { |
| 1002 Annotation annotation = node.parent as Annotation; | 1002 Annotation annotation = node.parent as Annotation; |
| 1003 _resolver.reportErrorForNode( | 1003 _resolver.reportErrorForNode( |
| 1004 CompileTimeErrorCode.INVALID_ANNOTATION, annotation); | 1004 CompileTimeErrorCode.INVALID_ANNOTATION, annotation); |
| 1005 } else if (element is PrefixElement) { |
| 1006 _resolver.reportErrorForNode( |
| 1007 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, node, |
| 1008 [element.name]); |
| 1005 } else { | 1009 } else { |
| 1006 _recordUndefinedNode(_resolver.enclosingClass, | 1010 _recordUndefinedNode(_resolver.enclosingClass, |
| 1007 StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]); | 1011 StaticWarningCode.UNDEFINED_IDENTIFIER, node, [node.name]); |
| 1008 } | 1012 } |
| 1009 } | 1013 } |
| 1010 node.staticElement = element; | 1014 node.staticElement = element; |
| 1011 if (node.inSetterContext() && | 1015 if (node.inSetterContext() && |
| 1012 node.inGetterContext() && | 1016 node.inGetterContext() && |
| 1013 enclosingClass != null) { | 1017 enclosingClass != null) { |
| 1014 InterfaceType enclosingType = enclosingClass.type; | 1018 InterfaceType enclosingType = enclosingClass.type; |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1348 element = MultiplyDefinedElementImpl.fromElements( | 1352 element = MultiplyDefinedElementImpl.fromElements( |
| 1349 _definingLibrary.context, element, importedElement); | 1353 _definingLibrary.context, element, importedElement); |
| 1350 } | 1354 } |
| 1351 } | 1355 } |
| 1352 } | 1356 } |
| 1353 } | 1357 } |
| 1354 return element; | 1358 return element; |
| 1355 } | 1359 } |
| 1356 | 1360 |
| 1357 /** | 1361 /** |
| 1362 * Return the best type of the given [expression] that is to be used for |
| 1363 * type analysis. |
| 1364 */ |
| 1365 DartType _getBestType(Expression expression) { |
| 1366 DartType bestType = _resolveTypeParameter(expression.bestType); |
| 1367 if (bestType is FunctionType) { |
| 1368 // |
| 1369 // All function types are subtypes of 'Function', which is itself a |
| 1370 // subclass of 'Object'. |
| 1371 // |
| 1372 bestType = _resolver.typeProvider.functionType; |
| 1373 } |
| 1374 return bestType; |
| 1375 } |
| 1376 |
| 1377 /** |
| 1358 * Assuming that the given [expression] is a prefix for a deferred import, | 1378 * Assuming that the given [expression] is a prefix for a deferred import, |
| 1359 * return the library that is being imported. | 1379 * return the library that is being imported. |
| 1360 */ | 1380 */ |
| 1361 LibraryElement _getImportedLibrary(Expression expression) { | 1381 LibraryElement _getImportedLibrary(Expression expression) { |
| 1362 PrefixElement prefixElement = | 1382 PrefixElement prefixElement = |
| 1363 (expression as SimpleIdentifier).staticElement as PrefixElement; | 1383 (expression as SimpleIdentifier).staticElement as PrefixElement; |
| 1364 List<ImportElement> imports = | 1384 List<ImportElement> imports = |
| 1365 prefixElement.enclosingElement.getImportsWithPrefix(prefixElement); | 1385 prefixElement.enclosingElement.getImportsWithPrefix(prefixElement); |
| 1366 return imports[0].importedLibrary; | 1386 return imports[0].importedLibrary; |
| 1367 } | 1387 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1385 } else if (operatorType == sc.TokenType.MINUS_MINUS) { | 1405 } else if (operatorType == sc.TokenType.MINUS_MINUS) { |
| 1386 return sc.TokenType.MINUS.lexeme; | 1406 return sc.TokenType.MINUS.lexeme; |
| 1387 } else if (operatorType == sc.TokenType.MINUS) { | 1407 } else if (operatorType == sc.TokenType.MINUS) { |
| 1388 return "unary-"; | 1408 return "unary-"; |
| 1389 } else { | 1409 } else { |
| 1390 return operator.lexeme; | 1410 return operator.lexeme; |
| 1391 } | 1411 } |
| 1392 } | 1412 } |
| 1393 | 1413 |
| 1394 /** | 1414 /** |
| 1395 * Return the best type of the given [expression] that is to be used for | |
| 1396 * type analysis. | |
| 1397 */ | |
| 1398 DartType _getBestType(Expression expression) { | |
| 1399 DartType bestType = _resolveTypeParameter(expression.bestType); | |
| 1400 if (bestType is FunctionType) { | |
| 1401 // | |
| 1402 // All function types are subtypes of 'Function', which is itself a | |
| 1403 // subclass of 'Object'. | |
| 1404 // | |
| 1405 bestType = _resolver.typeProvider.functionType; | |
| 1406 } | |
| 1407 return bestType; | |
| 1408 } | |
| 1409 | |
| 1410 /** | |
| 1411 * Return the propagated type of the given [expression] that is to be used for | 1415 * Return the propagated type of the given [expression] that is to be used for |
| 1412 * type analysis. | 1416 * type analysis. |
| 1413 */ | 1417 */ |
| 1414 DartType _getPropagatedType(Expression expression) { | 1418 DartType _getPropagatedType(Expression expression) { |
| 1415 DartType propagatedType = _resolveTypeParameter(expression.propagatedType); | 1419 DartType propagatedType = _resolveTypeParameter(expression.propagatedType); |
| 1416 if (propagatedType is FunctionType) { | 1420 if (propagatedType is FunctionType) { |
| 1417 // | 1421 // |
| 1418 // All function types are subtypes of 'Function', which is itself a | 1422 // All function types are subtypes of 'Function', which is itself a |
| 1419 // subclass of 'Object'. | 1423 // subclass of 'Object'. |
| 1420 // | 1424 // |
| (...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2326 * will be invoked. If the returned element is a getter, the getter will be | 2330 * will be invoked. If the returned element is a getter, the getter will be |
| 2327 * invoked without arguments and the result of that invocation will then be | 2331 * invoked without arguments and the result of that invocation will then be |
| 2328 * invoked with the arguments. The [methodName] is the name of the method | 2332 * invoked with the arguments. The [methodName] is the name of the method |
| 2329 * being invoked ('m'). | 2333 * being invoked ('m'). |
| 2330 */ | 2334 */ |
| 2331 Element _resolveInvokedElement(SimpleIdentifier methodName) { | 2335 Element _resolveInvokedElement(SimpleIdentifier methodName) { |
| 2332 // | 2336 // |
| 2333 // Look first in the lexical scope. | 2337 // Look first in the lexical scope. |
| 2334 // | 2338 // |
| 2335 Element element = _resolver.nameScope.lookup(methodName, _definingLibrary); | 2339 Element element = _resolver.nameScope.lookup(methodName, _definingLibrary); |
| 2336 if (element == null) { | 2340 if (element == null || element is PrefixElement) { |
| 2337 // | 2341 // |
| 2338 // If it isn't defined in the lexical scope, and the invocation is within | 2342 // If it isn't defined in the lexical scope, and the invocation is within |
| 2339 // a class, then look in the inheritance scope. | 2343 // a class, then look in the inheritance scope. |
| 2340 // | 2344 // |
| 2341 ClassElement enclosingClass = _resolver.enclosingClass; | 2345 ClassElement enclosingClass = _resolver.enclosingClass; |
| 2342 if (enclosingClass != null) { | 2346 if (enclosingClass != null) { |
| 2343 InterfaceType enclosingType = enclosingClass.type; | 2347 InterfaceType enclosingType = enclosingClass.type; |
| 2344 element = _lookUpMethod(null, enclosingType, methodName.name); | 2348 element = _lookUpMethod(null, enclosingType, methodName.name); |
| 2345 if (element == null) { | 2349 if (element == null) { |
| 2346 // | 2350 // |
| 2347 // If there's no method, then it's possible that 'm' is a getter that | 2351 // If there's no method, then it's possible that 'm' is a getter that |
| 2348 // returns a function. | 2352 // returns a function. |
| 2349 // | 2353 // |
| 2350 element = _lookUpGetter(null, enclosingType, methodName.name); | 2354 element = _lookUpGetter(null, enclosingType, methodName.name); |
| 2351 } | 2355 } |
| 2352 } | 2356 } |
| 2353 } | 2357 } |
| 2354 // TODO(brianwilkerson) Report this error. | 2358 // TODO(brianwilkerson) Report this error. |
| 2355 return element; | 2359 return element; |
| 2356 } | 2360 } |
| 2357 | 2361 |
| 2358 /** | 2362 /** |
| 2359 * Given an invocation of the form 'e.m(a1, ..., an)', resolve 'e.m' to the | 2363 * Given an invocation of the form 'e.m(a1, ..., an)', resolve 'e.m' to the |
| 2360 * element being invoked. If the returned element is a method, then the method | 2364 * element being invoked. If the returned element is a method, then the method |
| 2361 * will be invoked. If the returned element is a getter, the getter will be | 2365 * will be invoked. If the returned element is a getter, the getter will be |
| 2362 * invoked without arguments and the result of that invocation will then be | 2366 * invoked without arguments and the result of that invocation will then be |
| 2363 * invoked with the arguments. The [target] is the target of the invocation | 2367 * invoked with the arguments. The [target] is the target of the invocation |
| 2364 * ('e'). The [targetType] is the type of the target. The [methodName] is th | 2368 * ('e'). The [targetType] is the type of the target. The [methodName] is th |
| 2365 * name of the method being invoked ('m'). | 2369 * name of the method being invoked ('m'). [isConditional] indicates |
| 2370 * whether the invocatoin uses a '?.' operator. |
| 2366 */ | 2371 */ |
| 2367 Element _resolveInvokedElementWithTarget( | 2372 Element _resolveInvokedElementWithTarget(Expression target, |
| 2368 Expression target, DartType targetType, SimpleIdentifier methodName) { | 2373 DartType targetType, SimpleIdentifier methodName, bool isConditional) { |
| 2369 if (targetType is InterfaceType) { | 2374 if (targetType is InterfaceType) { |
| 2370 Element element = _lookUpMethod(target, targetType, methodName.name); | 2375 Element element = _lookUpMethod(target, targetType, methodName.name); |
| 2371 if (element == null) { | 2376 if (element == null) { |
| 2372 // | 2377 // |
| 2373 // If there's no method, then it's possible that 'm' is a getter that | 2378 // If there's no method, then it's possible that 'm' is a getter that |
| 2374 // returns a function. | 2379 // returns a function. |
| 2375 // | 2380 // |
| 2376 // TODO (collinsn): need to add union type support here too, in the | 2381 // TODO (collinsn): need to add union type support here too, in the |
| 2377 // style of [lookUpMethod]. | 2382 // style of [lookUpMethod]. |
| 2378 element = _lookUpGetter(target, targetType, methodName.name); | 2383 element = _lookUpGetter(target, targetType, methodName.name); |
| 2379 } | 2384 } |
| 2380 return element; | 2385 return element; |
| 2381 } else if (target is SimpleIdentifier) { | 2386 } else if (target is SimpleIdentifier) { |
| 2382 Element targetElement = target.staticElement; | 2387 Element targetElement = target.staticElement; |
| 2383 if (targetElement is PrefixElement) { | 2388 if (targetElement is PrefixElement) { |
| 2389 if (isConditional) { |
| 2390 _resolver.reportErrorForNode( |
| 2391 CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT, |
| 2392 target, [target.name]); |
| 2393 } |
| 2384 // | 2394 // |
| 2385 // Look to see whether the name of the method is really part of a | 2395 // Look to see whether the name of the method is really part of a |
| 2386 // prefixed identifier for an imported top-level function or top-level | 2396 // prefixed identifier for an imported top-level function or top-level |
| 2387 // getter that returns a function. | 2397 // getter that returns a function. |
| 2388 // | 2398 // |
| 2389 String name = "${target.name}.$methodName"; | 2399 String name = "${target.name}.$methodName"; |
| 2390 Identifier functionName = new SyntheticIdentifier(name, methodName); | 2400 Identifier functionName = new SyntheticIdentifier(name, methodName); |
| 2391 Element element = | 2401 Element element = |
| 2392 _resolver.nameScope.lookup(functionName, _definingLibrary); | 2402 _resolver.nameScope.lookup(functionName, _definingLibrary); |
| 2393 if (element != null) { | 2403 if (element != null) { |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2575 if (setter != null) { | 2585 if (setter != null) { |
| 2576 element = setter; | 2586 element = setter; |
| 2577 } | 2587 } |
| 2578 } | 2588 } |
| 2579 } else if (element == null && | 2589 } else if (element == null && |
| 2580 (identifier.inSetterContext() || | 2590 (identifier.inSetterContext() || |
| 2581 identifier.parent is CommentReference)) { | 2591 identifier.parent is CommentReference)) { |
| 2582 element = _resolver.nameScope.lookup( | 2592 element = _resolver.nameScope.lookup( |
| 2583 new SyntheticIdentifier("${identifier.name}=", identifier), | 2593 new SyntheticIdentifier("${identifier.name}=", identifier), |
| 2584 _definingLibrary); | 2594 _definingLibrary); |
| 2595 } else if (element is PrefixElement && !identifier.inGetterContext()) { |
| 2596 element = _resolver.nameScope.lookup( |
| 2597 new SyntheticIdentifier("${identifier.name}=", identifier), |
| 2598 _definingLibrary); |
| 2585 } | 2599 } |
| 2586 ClassElement enclosingClass = _resolver.enclosingClass; | 2600 ClassElement enclosingClass = _resolver.enclosingClass; |
| 2587 if (element == null && enclosingClass != null) { | 2601 if (element == null && enclosingClass != null) { |
| 2588 InterfaceType enclosingType = enclosingClass.type; | 2602 InterfaceType enclosingType = enclosingClass.type; |
| 2589 if (element == null && | 2603 if (element == null && |
| 2590 (identifier.inSetterContext() || | 2604 (identifier.inSetterContext() || |
| 2591 identifier.parent is CommentReference)) { | 2605 identifier.parent is CommentReference)) { |
| 2592 element = _lookUpSetter(null, enclosingType, identifier.name); | 2606 element = _lookUpSetter(null, enclosingType, identifier.name); |
| 2593 } | 2607 } |
| 2594 if (element == null && identifier.inGetterContext()) { | 2608 if (element == null && identifier.inGetterContext()) { |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2792 | 2806 |
| 2793 @override | 2807 @override |
| 2794 Element get staticElement => null; | 2808 Element get staticElement => null; |
| 2795 | 2809 |
| 2796 @override | 2810 @override |
| 2797 accept(AstVisitor visitor) => null; | 2811 accept(AstVisitor visitor) => null; |
| 2798 | 2812 |
| 2799 @override | 2813 @override |
| 2800 void visitChildren(AstVisitor visitor) {} | 2814 void visitChildren(AstVisitor visitor) {} |
| 2801 } | 2815 } |
| OLD | NEW |