| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of resolution; | 5 part of resolution; |
| 6 | 6 |
| 7 /// The state of constants in resolutions. | 7 /// The state of constants in resolutions. |
| 8 enum ConstantState { | 8 enum ConstantState { |
| 9 /// Expressions are not required to be constants. | 9 /// Expressions are not required to be constants. |
| 10 NON_CONSTANT, | 10 NON_CONSTANT, |
| (...skipping 1757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1768 return handleStaticInstanceMemberAccess( | 1768 return handleStaticInstanceMemberAccess( |
| 1769 node, memberName, receiverClass, member); | 1769 node, memberName, receiverClass, member); |
| 1770 } else if (memberName.isPrivate && memberName.library != member.library) { | 1770 } else if (memberName.isPrivate && memberName.library != member.library) { |
| 1771 return handlePrivateStaticMemberAccess( | 1771 return handlePrivateStaticMemberAccess( |
| 1772 node, memberName, receiverClass, member); | 1772 node, memberName, receiverClass, member); |
| 1773 } else { | 1773 } else { |
| 1774 return handleStaticOrTopLevelAccess(node, memberName, member); | 1774 return handleStaticOrTopLevelAccess(node, memberName, member); |
| 1775 } | 1775 } |
| 1776 } | 1776 } |
| 1777 | 1777 |
| 1778 /// Handle access to a type literal of type variable [element]. Like `T` or |
| 1779 /// `T()` where 'T' is type variable. |
| 1780 // TODO(johnniwinther): Remove [name] when [Selector] is not required for the |
| 1781 // the [GetStructure]. |
| 1782 // TODO(johnniwinther): Remove [element] when it is no longer needed for |
| 1783 // evaluating constants. |
| 1784 ResolutionResult handleTypeVariableTypeLiteralAccess( |
| 1785 Send node, |
| 1786 Name name, |
| 1787 TypeVariableElement element) { |
| 1788 if (!Elements.hasAccessToTypeVariables(enclosingElement)) { |
| 1789 compiler.reportError(node, |
| 1790 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, |
| 1791 {'typeVariableName': node.selector}); |
| 1792 // TODO(johnniwinther): Add another access semantics for this. |
| 1793 } |
| 1794 registry.registerClassUsingVariableExpression(element.enclosingClass); |
| 1795 registry.registerTypeVariableExpression(); |
| 1796 |
| 1797 AccessSemantics semantics = |
| 1798 new StaticAccess.typeParameterTypeLiteral(element); |
| 1799 registry.useElement(node, element); |
| 1800 registry.registerTypeLiteral(node, element.type); |
| 1801 |
| 1802 if (node.isCall) { |
| 1803 CallStructure callStructure = |
| 1804 resolveArguments(node.argumentsNode).callStructure; |
| 1805 Selector selector = callStructure.callSelector; |
| 1806 // TODO(johnniwinther): Remove this when all information goes through |
| 1807 // the [SendStructure]. |
| 1808 registry.setSelector(node, selector); |
| 1809 |
| 1810 registry.registerSendStructure(node, |
| 1811 new InvokeStructure(semantics, selector)); |
| 1812 } else { |
| 1813 // TODO(johnniwinther): Avoid the need for a [Selector] here. |
| 1814 registry.registerSendStructure(node, |
| 1815 new GetStructure(semantics, |
| 1816 new Selector(SelectorKind.GETTER, name, CallStructure.NO_ARGS))); |
| 1817 } |
| 1818 return const NoneResult(); |
| 1819 } |
| 1820 |
| 1821 /// Handle access to a constant type literal of [type]. |
| 1822 // TODO(johnniwinther): Remove [name] when [Selector] is not required for the |
| 1823 // the [GetStructure]. |
| 1824 // TODO(johnniwinther): Remove [element] when it is no longer needed for |
| 1825 // evaluating constants. |
| 1826 ResolutionResult handleConstantTypeLiteralAccess( |
| 1827 Send node, |
| 1828 Name name, |
| 1829 TypeDeclarationElement element, |
| 1830 DartType type, |
| 1831 ConstantAccess semantics) { |
| 1832 registry.useElement(node, element); |
| 1833 registry.registerTypeLiteral(node, type); |
| 1834 |
| 1835 if (node.isCall) { |
| 1836 CallStructure callStructure = |
| 1837 resolveArguments(node.argumentsNode).callStructure; |
| 1838 Selector selector = callStructure.callSelector; |
| 1839 // TODO(johnniwinther): Remove this when all information goes through |
| 1840 // the [SendStructure]. |
| 1841 registry.setSelector(node, selector); |
| 1842 |
| 1843 // The node itself is not a constant but we register the selector (the |
| 1844 // identifier that refers to the class/typedef) as a constant. |
| 1845 registry.useElement(node.selector, element); |
| 1846 analyzeConstantDeferred(node.selector, enforceConst: false); |
| 1847 |
| 1848 registry.registerSendStructure(node, |
| 1849 new InvokeStructure(semantics, selector)); |
| 1850 return const NoneResult(); |
| 1851 } else { |
| 1852 analyzeConstantDeferred(node, enforceConst: false); |
| 1853 |
| 1854 // TODO(johnniwinther): Avoid the need for a [Selector] here. |
| 1855 registry.registerSendStructure(node, |
| 1856 new GetStructure(semantics, |
| 1857 new Selector(SelectorKind.GETTER, name, CallStructure.NO_ARGS))); |
| 1858 return new ConstantResult(node, semantics.constant); |
| 1859 } |
| 1860 } |
| 1861 |
| 1862 /// Handle access to a type literal of a typedef. Like `F` or |
| 1863 /// `F()` where 'F' is typedef. |
| 1864 ResolutionResult handleTypedefTypeLiteralAccess( |
| 1865 Send node, |
| 1866 Name name, |
| 1867 TypedefElement typdef) { |
| 1868 typdef.ensureResolved(compiler); |
| 1869 DartType type = typdef.rawType; |
| 1870 ConstantExpression constant = new TypeConstantExpression(type); |
| 1871 AccessSemantics semantics = new ConstantAccess.typedefTypeLiteral(constant); |
| 1872 return handleConstantTypeLiteralAccess(node, name, typdef, type, semantics); |
| 1873 } |
| 1874 |
| 1875 /// Handle access to a type literal of the type 'dynamic'. Like `dynamic` or |
| 1876 /// `dynamic()`. |
| 1877 ResolutionResult handleDynamicTypeLiteralAccess(Send node) { |
| 1878 DartType type = const DynamicType(); |
| 1879 ConstantExpression constant = new TypeConstantExpression( |
| 1880 // TODO(johnniwinther): Use [type] when evaluation of constants is done |
| 1881 // directly on the constant expressions. |
| 1882 node.isCall ? coreTypes.typeType : type); |
| 1883 AccessSemantics semantics = new ConstantAccess.dynamicTypeLiteral(constant); |
| 1884 return handleConstantTypeLiteralAccess( |
| 1885 node, const PublicName('dynamic'), compiler.typeClass, type, semantics); |
| 1886 } |
| 1887 |
| 1888 /// Handle access to a type literal of a class. Like `C` or |
| 1889 /// `C()` where 'C' is class. |
| 1890 ResolutionResult handleClassTypeLiteralAccess( |
| 1891 Send node, |
| 1892 Name name, |
| 1893 ClassElement cls) { |
| 1894 DartType type = cls.rawType; |
| 1895 ConstantExpression constant = new TypeConstantExpression(type); |
| 1896 AccessSemantics semantics = new ConstantAccess.classTypeLiteral(constant); |
| 1897 return handleConstantTypeLiteralAccess(node, name, cls, type, semantics); |
| 1898 } |
| 1899 |
| 1900 /// Handle a [Send] that resolves to a [prefix]. Like `prefix` in |
| 1901 /// `prefix.Class` or `prefix` in `prefix()`, the latter being a compile time |
| 1902 /// error. |
| 1903 ResolutionResult handleClassSend( |
| 1904 Send node, |
| 1905 Name name, |
| 1906 ClassElement cls) { |
| 1907 cls.ensureResolved(compiler); |
| 1908 if (sendIsMemberAccess) { |
| 1909 registry.useElement(node, cls); |
| 1910 return new ElementResult(cls); |
| 1911 } else { |
| 1912 // `C` or `C()` where 'C' is a class. |
| 1913 return handleClassTypeLiteralAccess(node, name, cls); |
| 1914 } |
| 1915 } |
| 1916 |
| 1778 /// Handle qualified [Send] where the receiver resolves to a [prefix], | 1917 /// Handle qualified [Send] where the receiver resolves to a [prefix], |
| 1779 /// like `prefix.toplevelFunction()` or `prefix.Class.staticField` where | 1918 /// like `prefix.toplevelFunction()` or `prefix.Class.staticField` where |
| 1780 /// `prefix` is a library prefix. | 1919 /// `prefix` is a library prefix. |
| 1781 ResolutionResult handleLibraryPrefixSend( | 1920 ResolutionResult handleLibraryPrefixSend( |
| 1782 Send node, PrefixElement prefix, Name name) { | 1921 Send node, PrefixElement prefix, Name name) { |
| 1783 Element member = prefix.lookupLocalMember(name.text); | 1922 Element member = prefix.lookupLocalMember(name.text); |
| 1784 if (member == null) { | 1923 if (member == null) { |
| 1785 registry.registerThrowNoSuchMethod(); | 1924 registry.registerThrowNoSuchMethod(); |
| 1786 Element error = reportAndCreateErroneousElement( | 1925 Element error = reportAndCreateErroneousElement( |
| 1787 node, name.text, MessageKind.NO_SUCH_LIBRARY_MEMBER, | 1926 node, name.text, MessageKind.NO_SUCH_LIBRARY_MEMBER, |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1809 } | 1948 } |
| 1810 if (prefix.isDeferred) { | 1949 if (prefix.isDeferred) { |
| 1811 // TODO(johnniwinther): Remove this when deferred access is detected | 1950 // TODO(johnniwinther): Remove this when deferred access is detected |
| 1812 // through a [SendStructure]. | 1951 // through a [SendStructure]. |
| 1813 registry.useElement(node.selector, prefix); | 1952 registry.useElement(node.selector, prefix); |
| 1814 } | 1953 } |
| 1815 registry.useElement(node, prefix); | 1954 registry.useElement(node, prefix); |
| 1816 return new ElementResult(prefix); | 1955 return new ElementResult(prefix); |
| 1817 } | 1956 } |
| 1818 | 1957 |
| 1819 | |
| 1820 /// Handle qualified [Send] where the receiver resolves to an [Element], like | 1958 /// Handle qualified [Send] where the receiver resolves to an [Element], like |
| 1821 /// `a.b` where `a` is a local, field, class, or prefix, etc. | 1959 /// `a.b` where `a` is a local, field, class, or prefix, etc. |
| 1822 ResolutionResult handleResolvedQualifiedSend( | 1960 ResolutionResult handleResolvedQualifiedSend( |
| 1823 Send node, Name name, Element element) { | 1961 Send node, Name name, Element element) { |
| 1824 if (element.isPrefix) { | 1962 if (element.isPrefix) { |
| 1825 return handleLibraryPrefixSend(node, element, name); | 1963 return handleLibraryPrefixSend(node, element, name); |
| 1826 } else if (element.isClass) { | 1964 } else if (element.isClass) { |
| 1827 return handleStaticMemberAccess(node, name, element); | 1965 return handleStaticMemberAccess(node, name, element); |
| 1828 } | 1966 } |
| 1829 return oldVisitSend(node); | 1967 // TODO(johnniwinther): Use the [element]. |
| 1968 return handleDynamicPropertyAccess(node, name); |
| 1830 } | 1969 } |
| 1831 | 1970 |
| 1832 /// Handle dynamic access of [semantics]. | 1971 /// Handle dynamic access of [semantics]. |
| 1833 ResolutionResult handleDynamicAccessSemantics( | 1972 ResolutionResult handleDynamicAccessSemantics( |
| 1834 Send node, Name name, AccessSemantics semantics) { | 1973 Send node, Name name, AccessSemantics semantics) { |
| 1835 SendStructure sendStructure; | 1974 SendStructure sendStructure; |
| 1836 Selector selector; | 1975 Selector selector; |
| 1837 if (node.isCall) { | 1976 if (node.isCall) { |
| 1838 CallStructure callStructure = | 1977 CallStructure callStructure = |
| 1839 resolveArguments(node.argumentsNode).callStructure; | 1978 resolveArguments(node.argumentsNode).callStructure; |
| (...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2093 } else { | 2232 } else { |
| 2094 member = abstractField.setter; | 2233 member = abstractField.setter; |
| 2095 } | 2234 } |
| 2096 } else { | 2235 } else { |
| 2097 member = element; | 2236 member = element; |
| 2098 } | 2237 } |
| 2099 // TODO(johnniwinther): Needed to provoke a parsing and with it discovery | 2238 // TODO(johnniwinther): Needed to provoke a parsing and with it discovery |
| 2100 // of parse errors to make [element] erroneous. Fix this! | 2239 // of parse errors to make [element] erroneous. Fix this! |
| 2101 member.computeType(compiler); | 2240 member.computeType(compiler); |
| 2102 | 2241 |
| 2242 |
| 2243 if (member == compiler.mirrorSystemGetNameFunction && |
| 2244 !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) { |
| 2245 compiler.reportHint( |
| 2246 node.selector, MessageKind.STATIC_FUNCTION_BLOAT, |
| 2247 {'class': compiler.mirrorSystemClass.name, |
| 2248 'name': compiler.mirrorSystemGetNameFunction.name}); |
| 2249 } |
| 2250 |
| 2103 Selector selector; | 2251 Selector selector; |
| 2104 AccessSemantics semantics = | 2252 AccessSemantics semantics = |
| 2105 computeStaticOrTopLevelAccessSemantics(node, member); | 2253 computeStaticOrTopLevelAccessSemantics(node, member); |
| 2106 if (node.isCall) { | 2254 if (node.isCall) { |
| 2107 ArgumentsResult argumentsResult = | 2255 ArgumentsResult argumentsResult = |
| 2108 resolveArguments(node.argumentsNode); | 2256 resolveArguments(node.argumentsNode); |
| 2109 CallStructure callStructure = argumentsResult.callStructure; | 2257 CallStructure callStructure = argumentsResult.callStructure; |
| 2110 selector = new Selector(SelectorKind.CALL, name, callStructure); | 2258 selector = new Selector(SelectorKind.CALL, name, callStructure); |
| 2111 | 2259 |
| 2112 bool isIncompatibleInvoke = false; | 2260 bool isIncompatibleInvoke = false; |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2225 new StaticAccess.unresolved(element)); | 2373 new StaticAccess.unresolved(element)); |
| 2226 } | 2374 } |
| 2227 if (element.isInstanceMember) { | 2375 if (element.isInstanceMember) { |
| 2228 if (inInstanceContext) { | 2376 if (inInstanceContext) { |
| 2229 // TODO(johnniwinther): Maybe use the found [element]. | 2377 // TODO(johnniwinther): Maybe use the found [element]. |
| 2230 return handleThisPropertyAccess(node, name); | 2378 return handleThisPropertyAccess(node, name); |
| 2231 } else { | 2379 } else { |
| 2232 return handleStaticInstanceSend(node, name, element); | 2380 return handleStaticInstanceSend(node, name, element); |
| 2233 } | 2381 } |
| 2234 } | 2382 } |
| 2235 if (element.isClass || element.isTypedef) { | 2383 if (element.isClass) { |
| 2236 return oldVisitSend(node); | 2384 // `C`, `C()`, or 'C.b` where 'C' is a class. |
| 2385 return handleClassSend(node, name, element); |
| 2386 } else if (element.isTypedef) { |
| 2387 // `F` or `F()` where 'F' is a typedef. |
| 2388 return handleTypedefTypeLiteralAccess(node, name, element); |
| 2237 } else if (element.isTypeVariable) { | 2389 } else if (element.isTypeVariable) { |
| 2238 return oldVisitSend(node); | 2390 return handleTypeVariableTypeLiteralAccess(node, name, element); |
| 2239 } else if (element.isPrefix) { | 2391 } else if (element.isPrefix) { |
| 2240 return handleLibraryPrefix(node, name, element); | 2392 return handleLibraryPrefix(node, name, element); |
| 2241 } else if (element.isLocal) { | 2393 } else if (element.isLocal) { |
| 2242 return handleLocalAccess(node, name, element); | 2394 return handleLocalAccess(node, name, element); |
| 2243 } else if (element.isStatic || element.isTopLevel) { | 2395 } else if (element.isStatic || element.isTopLevel) { |
| 2244 return handleStaticOrTopLevelAccess(node, name, element); | 2396 return handleStaticOrTopLevelAccess(node, name, element); |
| 2245 } | 2397 } |
| 2246 return internalError(node, "Unexpected resolved send: $element"); | 2398 return internalError(node, "Unexpected resolved send: $element"); |
| 2247 } | 2399 } |
| 2248 | 2400 |
| 2249 /// Handle an unqualified [Send], that is where the `node.receiver` is null, | 2401 /// Handle an unqualified [Send], that is where the `node.receiver` is null, |
| 2250 /// like `a`, `a()`, `this()`, `assert()`, and `(){}()`. | 2402 /// like `a`, `a()`, `this()`, `assert()`, and `(){}()`. |
| 2251 ResolutionResult handleUnqualifiedSend(Send node) { | 2403 ResolutionResult handleUnqualifiedSend(Send node) { |
| 2252 Identifier selector = node.selector.asIdentifier(); | 2404 Identifier selector = node.selector.asIdentifier(); |
| 2253 if (selector == null) { | 2405 if (selector == null) { |
| 2254 // `(){}()` and `(foo)()`. | 2406 // `(){}()` and `(foo)()`. |
| 2255 return handleExpressionInvoke(node); | 2407 return handleExpressionInvoke(node); |
| 2256 } | 2408 } |
| 2257 String text = selector.source; | 2409 String text = selector.source; |
| 2258 if (text == 'assert') { | 2410 if (text == 'assert') { |
| 2259 // `assert()`. | 2411 // `assert()`. |
| 2260 return handleAssert(node); | 2412 return handleAssert(node); |
| 2261 } else if (text == 'this') { | 2413 } else if (text == 'this') { |
| 2262 // `this()`. | 2414 // `this()`. |
| 2263 return handleThisAccess(node); | 2415 return handleThisAccess(node); |
| 2264 } else if (text == 'dynamic') { | |
| 2265 // `dynamic` || `dynamic()`. | |
| 2266 // TODO(johnniwinther): Handle dynamic type literal access. | |
| 2267 return oldVisitSend(node); | |
| 2268 } | 2416 } |
| 2269 // `name` or `name()` | 2417 // `name` or `name()` |
| 2270 Name name = new Name(text, enclosingElement.library); | 2418 Name name = new Name(text, enclosingElement.library); |
| 2271 Element element = lookupInScope(compiler, node, scope, text); | 2419 Element element = lookupInScope(compiler, node, scope, text); |
| 2272 if (element == null) { | 2420 if (element == null) { |
| 2273 if (inInstanceContext) { | 2421 if (text == 'dynamic') { |
| 2422 // `dynamic` or `dynamic()` where 'dynamic' is not declared in the |
| 2423 // current scope. |
| 2424 return handleDynamicTypeLiteralAccess(node); |
| 2425 } else if (inInstanceContext) { |
| 2274 // Implicitly `this.name`. | 2426 // Implicitly `this.name`. |
| 2275 return handleThisPropertyAccess(node, name); | 2427 return handleThisPropertyAccess(node, name); |
| 2276 } else { | 2428 } else { |
| 2277 // Create [ErroneousElement] for unresolved access. | 2429 // Create [ErroneousElement] for unresolved access. |
| 2278 ErroneousElement error = reportCannotResolve(node, text); | 2430 ErroneousElement error = reportCannotResolve(node, text); |
| 2279 return handleUnresolvedAccess(node, name, error); | 2431 return handleUnresolvedAccess(node, name, error); |
| 2280 } | 2432 } |
| 2281 } else { | 2433 } else { |
| 2282 return handleResolvedSend(node, name, element); | 2434 return handleResolvedSend(node, name, element); |
| 2283 } | 2435 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2300 void registerPotentialAccessInClosure(Send node, Element target) { | 2452 void registerPotentialAccessInClosure(Send node, Element target) { |
| 2301 if (isPotentiallyMutableTarget(target)) { | 2453 if (isPotentiallyMutableTarget(target)) { |
| 2302 if (enclosingElement != target.enclosingElement) { | 2454 if (enclosingElement != target.enclosingElement) { |
| 2303 for (Node scope in promotionScope) { | 2455 for (Node scope in promotionScope) { |
| 2304 registry.setAccessedByClosureIn(scope, target, node); | 2456 registry.setAccessedByClosureIn(scope, target, node); |
| 2305 } | 2457 } |
| 2306 } | 2458 } |
| 2307 } | 2459 } |
| 2308 } | 2460 } |
| 2309 | 2461 |
| 2310 ResolutionResult oldVisitSend(Send node) { | |
| 2311 bool oldSendIsMemberAccess = sendIsMemberAccess; | |
| 2312 sendIsMemberAccess = node.isPropertyAccess || node.isCall; | |
| 2313 | |
| 2314 ResolutionResult result = resolveSend(node); | |
| 2315 sendIsMemberAccess = oldSendIsMemberAccess; | |
| 2316 | |
| 2317 Element target = result.element; | |
| 2318 | |
| 2319 if (target != null | |
| 2320 && target == compiler.mirrorSystemGetNameFunction | |
| 2321 && !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) { | |
| 2322 compiler.reportHint( | |
| 2323 node.selector, MessageKind.STATIC_FUNCTION_BLOAT, | |
| 2324 {'class': compiler.mirrorSystemClass.name, | |
| 2325 'name': compiler.mirrorSystemGetNameFunction.name}); | |
| 2326 } | |
| 2327 | |
| 2328 if (target != null) { | |
| 2329 if (target.isErroneous) { | |
| 2330 registry.registerThrowNoSuchMethod(); | |
| 2331 } else if (target.isAbstractField) { | |
| 2332 AbstractFieldElement field = target; | |
| 2333 target = field.getter; | |
| 2334 if (target == null) { | |
| 2335 if (!inInstanceContext || field.isTopLevel || field.isStatic) { | |
| 2336 registry.registerThrowNoSuchMethod(); | |
| 2337 target = reportAndCreateErroneousElement(node.selector, field.name, | |
| 2338 MessageKind.CANNOT_RESOLVE_GETTER, const {}); | |
| 2339 } | |
| 2340 } | |
| 2341 } else if (target.isTypeVariable) { | |
| 2342 ClassElement cls = target.enclosingClass; | |
| 2343 assert(enclosingElement.enclosingClass == cls); | |
| 2344 if (!Elements.hasAccessToTypeVariables(enclosingElement)) { | |
| 2345 compiler.reportError(node, | |
| 2346 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, | |
| 2347 {'typeVariableName': node.selector}); | |
| 2348 } | |
| 2349 registry.registerClassUsingVariableExpression(cls); | |
| 2350 registry.registerTypeVariableExpression(); | |
| 2351 registerTypeLiteralAccess(node, target); | |
| 2352 } else if (target.impliesType && (!sendIsMemberAccess || node.isCall)) { | |
| 2353 registerTypeLiteralAccess(node, target); | |
| 2354 } | |
| 2355 registerPotentialAccessInClosure(node, target); | |
| 2356 } | |
| 2357 | |
| 2358 resolveArguments(node.argumentsNode); | |
| 2359 | |
| 2360 // If the selector is null, it means that we will not be generating | |
| 2361 // code for this as a send. | |
| 2362 Selector selector = registry.getSelector(node); | |
| 2363 if (selector == null) return const NoneResult(); | |
| 2364 | |
| 2365 if (node.isCall) { | |
| 2366 if (Elements.isUnresolved(target) || | |
| 2367 target.isGetter || | |
| 2368 target.isField || | |
| 2369 Elements.isClosureSend(node, target)) { | |
| 2370 // If we don't know what we're calling or if we are calling a getter, | |
| 2371 // we need to register that fact that we may be calling a closure | |
| 2372 // with the same arguments. | |
| 2373 Selector call = new Selector.callClosureFrom(selector); | |
| 2374 registry.registerDynamicInvocation( | |
| 2375 new UniverseSelector(selector, null)); | |
| 2376 } else if (target.impliesType) { | |
| 2377 // We call 'call()' on a Type instance returned from the reference to a | |
| 2378 // class or typedef literal. We do not need to register this call as a | |
| 2379 // dynamic invocation, because we statically know what the target is. | |
| 2380 } else { | |
| 2381 if (target is FunctionElement) { | |
| 2382 FunctionElement function = target; | |
| 2383 function.computeType(compiler); | |
| 2384 } | |
| 2385 if (!selector.applies(target, compiler.world)) { | |
| 2386 registry.registerThrowNoSuchMethod(); | |
| 2387 if (node.isSuperCall) { | |
| 2388 internalError(node, "Unexpected super call $node"); | |
| 2389 } | |
| 2390 } | |
| 2391 } | |
| 2392 | |
| 2393 handleForeignCall(node, target, selector); | |
| 2394 } | |
| 2395 | |
| 2396 registry.useElement(node, target); | |
| 2397 registerSend(selector, target); | |
| 2398 if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) { | |
| 2399 registry.registerGetOfStaticFunction(target.declaration); | |
| 2400 } | |
| 2401 return node.isPropertyAccess | |
| 2402 ? new ResolutionResult.forElement(target) : const NoneResult(); | |
| 2403 } | |
| 2404 | |
| 2405 // TODO(johnniwinther): Move this to the backend resolution callbacks. | 2462 // TODO(johnniwinther): Move this to the backend resolution callbacks. |
| 2406 void handleForeignCall(Send node, Element target, Selector selector) { | 2463 void handleForeignCall(Send node, Element target, Selector selector) { |
| 2407 if (target != null && compiler.backend.isForeign(target)) { | 2464 if (target != null && compiler.backend.isForeign(target)) { |
| 2408 if (selector.name == 'JS') { | 2465 if (selector.name == 'JS') { |
| 2409 registry.registerJsCall(node, this); | 2466 registry.registerJsCall(node, this); |
| 2410 } else if (selector.name == 'JS_EMBEDDED_GLOBAL') { | 2467 } else if (selector.name == 'JS_EMBEDDED_GLOBAL') { |
| 2411 registry.registerJsEmbeddedGlobalCall(node, this); | 2468 registry.registerJsEmbeddedGlobalCall(node, this); |
| 2412 } else if (selector.name == 'JS_BUILTIN') { | 2469 } else if (selector.name == 'JS_BUILTIN') { |
| 2413 registry.registerJsBuiltinCall(node, this); | 2470 registry.registerJsBuiltinCall(node, this); |
| 2414 } else if (selector.name == 'JS_INTERCEPTOR_CONSTANT') { | 2471 } else if (selector.name == 'JS_INTERCEPTOR_CONSTANT') { |
| (...skipping 1303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3718 } | 3775 } |
| 3719 return const NoneResult(); | 3776 return const NoneResult(); |
| 3720 } | 3777 } |
| 3721 } | 3778 } |
| 3722 | 3779 |
| 3723 /// Looks up [name] in [scope] and unwraps the result. | 3780 /// Looks up [name] in [scope] and unwraps the result. |
| 3724 Element lookupInScope(Compiler compiler, Node node, | 3781 Element lookupInScope(Compiler compiler, Node node, |
| 3725 Scope scope, String name) { | 3782 Scope scope, String name) { |
| 3726 return Elements.unwrap(scope.lookup(name), compiler, node); | 3783 return Elements.unwrap(scope.lookup(name), compiler, node); |
| 3727 } | 3784 } |
| OLD | NEW |