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 abstract class TreeElements { | 7 abstract class TreeElements { |
8 Element operator[](Node node); | 8 Element operator[](Node node); |
9 Selector getSelector(Send send); | 9 Selector getSelector(Send send); |
10 DartType getType(Node node); | 10 DartType getType(Node node); |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
377 | 377 |
378 TreeElements resolveField(VariableElement element) { | 378 TreeElements resolveField(VariableElement element) { |
379 Node tree = element.parseNode(compiler); | 379 Node tree = element.parseNode(compiler); |
380 if(element.modifiers.isStatic() && element.variables.isTopLevel()) { | 380 if(element.modifiers.isStatic() && element.variables.isTopLevel()) { |
381 error(element.modifiers.getStatic(), | 381 error(element.modifiers.getStatic(), |
382 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); | 382 MessageKind.TOP_LEVEL_VARIABLE_DECLARED_STATIC); |
383 } | 383 } |
384 ResolverVisitor visitor = visitorFor(element); | 384 ResolverVisitor visitor = visitorFor(element); |
385 initializerDo(tree, visitor.visit); | 385 initializerDo(tree, visitor.visit); |
386 | 386 |
387 if (Elements.isStaticOrTopLevelField(element)) { | |
388 if (tree.asSendSet() != null) { | |
389 // TODO(ngeoffray): We could do better here. | |
kasperl
2013/02/18 10:31:52
Improve comment to explain how.
ngeoffray
2013/02/18 11:32:18
Done.
| |
390 compiler.backend.registerLazyField(); | |
391 } | |
392 } | |
393 | |
387 // Perform various checks as side effect of "computing" the type. | 394 // Perform various checks as side effect of "computing" the type. |
388 element.computeType(compiler); | 395 element.computeType(compiler); |
389 | 396 |
390 return visitor.mapping; | 397 return visitor.mapping; |
391 } | 398 } |
392 | 399 |
393 TreeElements resolveParameter(Element element) { | 400 TreeElements resolveParameter(Element element) { |
394 Node tree = element.parseNode(compiler); | 401 Node tree = element.parseNode(compiler); |
395 ResolverVisitor visitor = visitorFor(element.enclosingElement); | 402 ResolverVisitor visitor = visitorFor(element.enclosingElement); |
396 initializerDo(tree, visitor.visit); | 403 initializerDo(tree, visitor.visit); |
(...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1451 new TypedefType(typdef, arguments.toLink())); | 1458 new TypedefType(typdef, arguments.toLink())); |
1452 } else { | 1459 } else { |
1453 if (arguments.isEmpty) { | 1460 if (arguments.isEmpty) { |
1454 type = typdef.rawType; | 1461 type = typdef.rawType; |
1455 } else { | 1462 } else { |
1456 type = new TypedefType(typdef, arguments.toLink()); | 1463 type = new TypedefType(typdef, arguments.toLink()); |
1457 } | 1464 } |
1458 } | 1465 } |
1459 } else if (element.isTypeVariable()) { | 1466 } else if (element.isTypeVariable()) { |
1460 if (enclosingElement.isInStaticMember()) { | 1467 if (enclosingElement.isInStaticMember()) { |
1468 compiler.backend.registerThrowRuntimeError(); | |
1461 compiler.reportWarning(node, | 1469 compiler.reportWarning(node, |
1462 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.message( | 1470 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.message( |
1463 {'typeVariableName': node})); | 1471 {'typeVariableName': node})); |
1464 type = new MalformedType( | 1472 type = new MalformedType( |
1465 new ErroneousElementX( | 1473 new ErroneousElementX( |
1466 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, | 1474 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, |
1467 {'typeVariableName': node}, | 1475 {'typeVariableName': node}, |
1468 typeName.source, enclosingElement), | 1476 typeName.source, enclosingElement), |
1469 element.computeType(compiler)); | 1477 element.computeType(compiler)); |
1470 } else { | 1478 } else { |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1635 error(node, MessageKind.INVALID_USE_OF_SUPER); | 1643 error(node, MessageKind.INVALID_USE_OF_SUPER); |
1636 } | 1644 } |
1637 return null; | 1645 return null; |
1638 } else { | 1646 } else { |
1639 Element element = lookup(node, node.source); | 1647 Element element = lookup(node, node.source); |
1640 if (element == null) { | 1648 if (element == null) { |
1641 if (!inInstanceContext) { | 1649 if (!inInstanceContext) { |
1642 element = warnAndCreateErroneousElement(node, node.source, | 1650 element = warnAndCreateErroneousElement(node, node.source, |
1643 MessageKind.CANNOT_RESOLVE, | 1651 MessageKind.CANNOT_RESOLVE, |
1644 {'name': node}); | 1652 {'name': node}); |
1653 compiler.backend.registerThrowNoSuchMethod(); | |
karlklose
2013/02/18 10:35:52
Can you move this to warnAndCreateErroneousElement
ngeoffray
2013/02/18 11:32:18
Actually, I'd rather not. warnAndCreateErroneousEl
| |
1645 } | 1654 } |
1646 } else if (element.isErroneous()) { | 1655 } else if (element.isErroneous()) { |
1647 // Use the erroneous element. | 1656 // Use the erroneous element. |
1648 } else { | 1657 } else { |
1649 if ((element.kind.category & allowedCategory) == 0) { | 1658 if ((element.kind.category & allowedCategory) == 0) { |
1650 // TODO(ahe): Improve error message. Need UX input. | 1659 // TODO(ahe): Improve error message. Need UX input. |
1651 error(node, MessageKind.GENERIC, | 1660 error(node, MessageKind.GENERIC, |
1652 {'text': "is not an expression $element"}); | 1661 {'text': "is not an expression $element"}); |
1653 } | 1662 } |
1654 } | 1663 } |
1655 if (!Elements.isUnresolved(element) | 1664 if (!Elements.isUnresolved(element) && element.isClass()) { |
1656 && element.kind == ElementKind.CLASS) { | |
1657 ClassElement classElement = element; | 1665 ClassElement classElement = element; |
1658 classElement.ensureResolved(compiler); | 1666 classElement.ensureResolved(compiler); |
1667 compiler.backend.registerTypeLiteral(); | |
1659 } | 1668 } |
1660 return useElement(node, element); | 1669 return useElement(node, element); |
1661 } | 1670 } |
1662 } | 1671 } |
1663 | 1672 |
1664 Element visitTypeAnnotation(TypeAnnotation node) { | 1673 Element visitTypeAnnotation(TypeAnnotation node) { |
1665 DartType type = resolveTypeAnnotation(node); | 1674 DartType type = resolveTypeAnnotation(node); |
1666 if (type != null) { | 1675 if (type != null) { |
1667 if (inCheckContext) { | 1676 if (inCheckContext) { |
1668 compiler.enqueuer.resolution.registerIsCheck(type); | 1677 compiler.enqueuer.resolution.registerIsCheck(type); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1826 } | 1835 } |
1827 | 1836 |
1828 visitFunctionExpression(FunctionExpression node) { | 1837 visitFunctionExpression(FunctionExpression node) { |
1829 visit(node.returnType); | 1838 visit(node.returnType); |
1830 SourceString name; | 1839 SourceString name; |
1831 if (node.name == null) { | 1840 if (node.name == null) { |
1832 name = const SourceString(""); | 1841 name = const SourceString(""); |
1833 } else { | 1842 } else { |
1834 name = node.name.asIdentifier().source; | 1843 name = node.name.asIdentifier().source; |
1835 } | 1844 } |
1836 | |
1837 FunctionElement function = new FunctionElementX.node( | 1845 FunctionElement function = new FunctionElementX.node( |
1838 name, node, ElementKind.FUNCTION, Modifiers.EMPTY, | 1846 name, node, ElementKind.FUNCTION, Modifiers.EMPTY, |
1839 enclosingElement); | 1847 enclosingElement); |
1840 // [function] and its enclosing method share the same | 1848 // [function] and its enclosing method share the same |
1841 // [TreeElementMapping]. | 1849 // [TreeElementMapping]. |
1842 compiler.enqueuer.resolution.resolvedElements[function] = mapping; | 1850 compiler.enqueuer.resolution.resolvedElements[function] = mapping; |
1843 Scope oldScope = scope; // The scope is modified by [setupFunction]. | 1851 Scope oldScope = scope; // The scope is modified by [setupFunction]. |
1844 setupFunction(node, function); | 1852 setupFunction(node, function); |
1845 defineElement(node, function, doAddToScope: node.name != null); | 1853 defineElement(node, function, doAddToScope: node.name != null); |
1846 | 1854 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1918 // This is just to guard against internal errors, so no need | 1926 // This is just to guard against internal errors, so no need |
1919 // for a real error message. | 1927 // for a real error message. |
1920 error(node.receiver, MessageKind.GENERIC, | 1928 error(node.receiver, MessageKind.GENERIC, |
1921 {'text': "Object has no superclass"}); | 1929 {'text': "Object has no superclass"}); |
1922 } | 1930 } |
1923 // TODO(johnniwinther): Ensure correct behavior if currentClass is a | 1931 // TODO(johnniwinther): Ensure correct behavior if currentClass is a |
1924 // patch. | 1932 // patch. |
1925 target = currentClass.lookupSuperMember(name); | 1933 target = currentClass.lookupSuperMember(name); |
1926 // [target] may be null which means invoking noSuchMethod on | 1934 // [target] may be null which means invoking noSuchMethod on |
1927 // super. | 1935 // super. |
1936 if (target == null) { | |
1937 compiler.backend.registerSuperNoSuchMethod(); | |
1938 } | |
1928 } else if (Elements.isUnresolved(resolvedReceiver)) { | 1939 } else if (Elements.isUnresolved(resolvedReceiver)) { |
1929 return null; | 1940 return null; |
1930 } else if (identical(resolvedReceiver.kind, ElementKind.CLASS)) { | 1941 } else if (resolvedReceiver.isClass()) { |
1931 ClassElement receiverClass = resolvedReceiver; | 1942 ClassElement receiverClass = resolvedReceiver; |
1932 receiverClass.ensureResolved(compiler); | 1943 receiverClass.ensureResolved(compiler); |
1933 if (node.isOperator) { | 1944 if (node.isOperator) { |
1934 // When the resolved receiver is a class, we can have two cases: | 1945 // When the resolved receiver is a class, we can have two cases: |
1935 // 1) a static send: C.foo, or | 1946 // 1) a static send: C.foo, or |
1936 // 2) an operator send, where the receiver is a class literal: 'C + 1'. | 1947 // 2) an operator send, where the receiver is a class literal: 'C + 1'. |
1937 // The following code that looks up the selector on the resolved | 1948 // The following code that looks up the selector on the resolved |
1938 // receiver will treat the second as the invocation of a static operator | 1949 // receiver will treat the second as the invocation of a static operator |
1939 // if the resolved receiver is not null. | 1950 // if the resolved receiver is not null. |
1940 return null; | 1951 return null; |
1941 } | 1952 } |
1942 target = receiverClass.lookupLocalMember(name); | 1953 target = receiverClass.lookupLocalMember(name); |
1943 if (target == null) { | 1954 if (target == null) { |
1955 compiler.backend.registerThrowNoSuchMethod(); | |
karlklose
2013/02/18 10:35:52
Ditto.
| |
1944 // TODO(johnniwinther): With the simplified [TreeElements] invariant, | 1956 // TODO(johnniwinther): With the simplified [TreeElements] invariant, |
1945 // try to resolve injected elements if [currentClass] is in the patch | 1957 // try to resolve injected elements if [currentClass] is in the patch |
1946 // library of [receiverClass]. | 1958 // library of [receiverClass]. |
1947 | 1959 |
1948 // TODO(karlklose): this should be reported by the caller of | 1960 // TODO(karlklose): this should be reported by the caller of |
1949 // [resolveSend] to select better warning messages for getters and | 1961 // [resolveSend] to select better warning messages for getters and |
1950 // setters. | 1962 // setters. |
1951 return warnAndCreateErroneousElement(node, name, | 1963 return warnAndCreateErroneousElement(node, name, |
1952 MessageKind.METHOD_NOT_FOUND, | 1964 MessageKind.METHOD_NOT_FOUND, |
1953 {'className': receiverClass.name, | 1965 {'className': receiverClass.name, |
1954 'methodName': name}); | 1966 'methodName': name}); |
1955 } else if (target.isInstanceMember()) { | 1967 } else if (target.isInstanceMember()) { |
1956 error(node, MessageKind.MEMBER_NOT_STATIC, | 1968 error(node, MessageKind.MEMBER_NOT_STATIC, |
1957 {'className': receiverClass.name, | 1969 {'className': receiverClass.name, |
1958 'memberName': name}); | 1970 'memberName': name}); |
1959 } | 1971 } |
1960 } else if (identical(resolvedReceiver.kind, ElementKind.PREFIX)) { | 1972 } else if (identical(resolvedReceiver.kind, ElementKind.PREFIX)) { |
1961 PrefixElement prefix = resolvedReceiver; | 1973 PrefixElement prefix = resolvedReceiver; |
1962 target = prefix.lookupLocalMember(name); | 1974 target = prefix.lookupLocalMember(name); |
1963 if (Elements.isUnresolved(target)) { | 1975 if (Elements.isUnresolved(target)) { |
1976 compiler.backend.registerThrowNoSuchMethod(); | |
karlklose
2013/02/18 10:35:52
Ditto.
| |
1964 return warnAndCreateErroneousElement( | 1977 return warnAndCreateErroneousElement( |
1965 node, name, MessageKind.NO_SUCH_LIBRARY_MEMBER, | 1978 node, name, MessageKind.NO_SUCH_LIBRARY_MEMBER, |
1966 {'libraryName': prefix.name, 'memberName': name}); | 1979 {'libraryName': prefix.name, 'memberName': name}); |
1967 } else if (target.kind == ElementKind.CLASS) { | 1980 } else if (target.kind == ElementKind.CLASS) { |
1968 ClassElement classElement = target; | 1981 ClassElement classElement = target; |
1969 classElement.ensureResolved(compiler); | 1982 classElement.ensureResolved(compiler); |
1970 } | 1983 } |
1971 } | 1984 } |
1972 return target; | 1985 return target; |
1973 } | 1986 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2064 } | 2077 } |
2065 } | 2078 } |
2066 | 2079 |
2067 visitSend(Send node) { | 2080 visitSend(Send node) { |
2068 Element target = resolveSend(node); | 2081 Element target = resolveSend(node); |
2069 if (!Elements.isUnresolved(target) | 2082 if (!Elements.isUnresolved(target) |
2070 && target.kind == ElementKind.ABSTRACT_FIELD) { | 2083 && target.kind == ElementKind.ABSTRACT_FIELD) { |
2071 AbstractFieldElement field = target; | 2084 AbstractFieldElement field = target; |
2072 target = field.getter; | 2085 target = field.getter; |
2073 if (target == null && !inInstanceContext) { | 2086 if (target == null && !inInstanceContext) { |
2087 compiler.backend.registerThrowNoSuchMethod(); | |
karlklose
2013/02/18 10:35:52
Ditto.
| |
2074 target = | 2088 target = |
2075 warnAndCreateErroneousElement(node.selector, field.name, | 2089 warnAndCreateErroneousElement(node.selector, field.name, |
2076 MessageKind.CANNOT_RESOLVE_GETTER); | 2090 MessageKind.CANNOT_RESOLVE_GETTER); |
2077 } | 2091 } |
2078 } | 2092 } |
2079 | 2093 |
2080 bool resolvedArguments = false; | 2094 bool resolvedArguments = false; |
2081 if (node.isOperator) { | 2095 if (node.isOperator) { |
2082 String operatorString = node.selector.asOperator().source.stringValue; | 2096 String operatorString = node.selector.asOperator().source.stringValue; |
2083 if (identical(operatorString, 'is') || identical(operatorString, 'as')) { | 2097 if (operatorString == 'is' || operatorString == 'as') { |
2084 assert(node.arguments.tail.isEmpty); | 2098 assert(node.arguments.tail.isEmpty); |
2085 DartType type = resolveTypeTest(node.arguments.head); | 2099 DartType type = resolveTypeTest(node.arguments.head); |
2086 if (type != null) { | 2100 if (type != null) { |
2087 compiler.enqueuer.resolution.registerIsCheck(type); | 2101 compiler.enqueuer.resolution.registerIsCheck(type); |
kasperl
2013/02/18 10:31:52
Why are we unconditionally registering the is chec
ngeoffray
2013/02/18 11:32:18
Done.
| |
2102 if (operatorString == 'as') { | |
2103 compiler.backend.registerAsCheck(type); | |
2104 } | |
2088 } | 2105 } |
2089 resolvedArguments = true; | 2106 resolvedArguments = true; |
2090 } else if (identical(operatorString, '?')) { | 2107 } else if (identical(operatorString, '?')) { |
2091 Element parameter = mapping[node.receiver]; | 2108 Element parameter = mapping[node.receiver]; |
2092 if (parameter == null | 2109 if (parameter == null |
2093 || !identical(parameter.kind, ElementKind.PARAMETER)) { | 2110 || !identical(parameter.kind, ElementKind.PARAMETER)) { |
2094 error(node.receiver, MessageKind.PARAMETER_NAME_EXPECTED); | 2111 error(node.receiver, MessageKind.PARAMETER_NAME_EXPECTED); |
2095 } else { | 2112 } else { |
2096 mapping.checkedParameters.add(parameter); | 2113 mapping.checkedParameters.add(parameter); |
2097 } | 2114 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2136 useElement(node, target); | 2153 useElement(node, target); |
2137 registerSend(selector, target); | 2154 registerSend(selector, target); |
2138 if (node.isPropertyAccess) { | 2155 if (node.isPropertyAccess) { |
2139 // It might be the closurization of a method. | 2156 // It might be the closurization of a method. |
2140 world.registerInstantiatedClass(compiler.functionClass); | 2157 world.registerInstantiatedClass(compiler.functionClass); |
2141 } | 2158 } |
2142 return node.isPropertyAccess ? target : null; | 2159 return node.isPropertyAccess ? target : null; |
2143 } | 2160 } |
2144 | 2161 |
2145 void warnArgumentMismatch(Send node, Element target) { | 2162 void warnArgumentMismatch(Send node, Element target) { |
2163 compiler.backend.registerThrowNoSuchMethod(); | |
2146 // TODO(karlklose): we can be more precise about the reason of the | 2164 // TODO(karlklose): we can be more precise about the reason of the |
2147 // mismatch. | 2165 // mismatch. |
2148 warning(node.argumentsNode, MessageKind.INVALID_ARGUMENTS, | 2166 warning(node.argumentsNode, MessageKind.INVALID_ARGUMENTS, |
2149 {'methodName': target.name}); | 2167 {'methodName': target.name}); |
2150 } | 2168 } |
2151 | 2169 |
2152 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. | 2170 /// Callback for native enqueuer to parse a type. Returns [:null:] on error. |
2153 DartType resolveTypeFromString(String typeName) { | 2171 DartType resolveTypeFromString(String typeName) { |
2154 Element element = scope.lookup(new SourceString(typeName)); | 2172 Element element = scope.lookup(new SourceString(typeName)); |
2155 if (element == null) return null; | 2173 if (element == null) return null; |
2156 if (element is! ClassElement) return null; | 2174 if (element is! ClassElement) return null; |
2157 element.ensureResolved(compiler); | 2175 element.ensureResolved(compiler); |
2158 return element.computeType(compiler); | 2176 return element.computeType(compiler); |
2159 } | 2177 } |
2160 | 2178 |
2161 visitSendSet(SendSet node) { | 2179 visitSendSet(SendSet node) { |
2162 Element target = resolveSend(node); | 2180 Element target = resolveSend(node); |
2163 Element setter = target; | 2181 Element setter = target; |
2164 Element getter = target; | 2182 Element getter = target; |
2165 SourceString operatorName = node.assignmentOperator.source; | 2183 SourceString operatorName = node.assignmentOperator.source; |
2166 String source = operatorName.stringValue; | 2184 String source = operatorName.stringValue; |
2167 bool isComplex = !identical(source, '='); | 2185 bool isComplex = !identical(source, '='); |
2168 if (!Elements.isUnresolved(target) | 2186 if (!Elements.isUnresolved(target)) { |
2169 && target.kind == ElementKind.ABSTRACT_FIELD) { | 2187 if (target.isAbstractField()) { |
2170 AbstractFieldElement field = target; | 2188 AbstractFieldElement field = target; |
2171 setter = field.setter; | 2189 setter = field.setter; |
2172 getter = field.getter; | 2190 getter = field.getter; |
2173 if (setter == null && !inInstanceContext) { | 2191 if (setter == null && !inInstanceContext) { |
2174 setter = | 2192 setter = |
2175 warnAndCreateErroneousElement(node.selector, field.name, | 2193 warnAndCreateErroneousElement(node.selector, field.name, |
2176 MessageKind.CANNOT_RESOLVE_SETTER); | 2194 MessageKind.CANNOT_RESOLVE_SETTER); |
2177 } | 2195 compiler.backend.registerThrowNoSuchMethod(); |
2178 if (isComplex && getter == null && !inInstanceContext) { | 2196 } |
2179 getter = | 2197 if (isComplex && getter == null && !inInstanceContext) { |
2180 warnAndCreateErroneousElement(node.selector, field.name, | 2198 getter = |
2181 MessageKind.CANNOT_RESOLVE_GETTER); | 2199 warnAndCreateErroneousElement(node.selector, field.name, |
2200 MessageKind.CANNOT_RESOLVE_GETTER); | |
2201 compiler.backend.registerThrowNoSuchMethod(); | |
2202 } | |
2203 } else if (target.impliesType()) { | |
2204 compiler.backend.registerThrowNoSuchMethod(); | |
2182 } | 2205 } |
2183 } | 2206 } |
2184 | 2207 |
2185 visit(node.argumentsNode); | 2208 visit(node.argumentsNode); |
2186 | 2209 |
2187 // TODO(ngeoffray): Check if the target can be assigned. | 2210 // TODO(ngeoffray): Check if the target can be assigned. |
2188 // TODO(ngeoffray): Warn if target is null and the send is | 2211 // TODO(ngeoffray): Warn if target is null and the send is |
2189 // unqualified. | 2212 // unqualified. |
2190 | 2213 |
2191 Selector selector = mapping.getSelector(node); | 2214 Selector selector = mapping.getSelector(node); |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2323 } | 2346 } |
2324 world.registerStaticUse(redirectionTarget); | 2347 world.registerStaticUse(redirectionTarget); |
2325 world.registerInstantiatedClass( | 2348 world.registerInstantiatedClass( |
2326 redirectionTarget.enclosingElement.declaration); | 2349 redirectionTarget.enclosingElement.declaration); |
2327 } | 2350 } |
2328 | 2351 |
2329 visitThrow(Throw node) { | 2352 visitThrow(Throw node) { |
2330 if (!inCatchBlock && node.expression == null) { | 2353 if (!inCatchBlock && node.expression == null) { |
2331 error(node, MessageKind.THROW_WITHOUT_EXPRESSION); | 2354 error(node, MessageKind.THROW_WITHOUT_EXPRESSION); |
2332 } | 2355 } |
2356 compiler.backend.registerThrow(); | |
2333 visit(node.expression); | 2357 visit(node.expression); |
2334 } | 2358 } |
2335 | 2359 |
2336 visitVariableDefinitions(VariableDefinitions node) { | 2360 visitVariableDefinitions(VariableDefinitions node) { |
2337 VariableDefinitionsVisitor visitor = | 2361 VariableDefinitionsVisitor visitor = |
2338 new VariableDefinitionsVisitor(compiler, node, this, | 2362 new VariableDefinitionsVisitor(compiler, node, this, |
2339 ElementKind.VARIABLE); | 2363 ElementKind.VARIABLE); |
2340 // Ensure that we set the type of the [VariableListElement] since it depends | 2364 // Ensure that we set the type of the [VariableListElement] since it depends |
2341 // on the current scope. If the current scope is a [MethodScope] or | 2365 // on the current scope. If the current scope is a [MethodScope] or |
2342 // [BlockScope] it will not be available for the | 2366 // [BlockScope] it will not be available for the |
(...skipping 15 matching lines...) Expand all Loading... | |
2358 visit(node.expression); | 2382 visit(node.expression); |
2359 } | 2383 } |
2360 | 2384 |
2361 visitNewExpression(NewExpression node) { | 2385 visitNewExpression(NewExpression node) { |
2362 Node selector = node.send.selector; | 2386 Node selector = node.send.selector; |
2363 FunctionElement constructor = resolveConstructor(node); | 2387 FunctionElement constructor = resolveConstructor(node); |
2364 resolveSelector(node.send); | 2388 resolveSelector(node.send); |
2365 resolveArguments(node.send.argumentsNode); | 2389 resolveArguments(node.send.argumentsNode); |
2366 useElement(node.send, constructor); | 2390 useElement(node.send, constructor); |
2367 if (Elements.isUnresolved(constructor)) return constructor; | 2391 if (Elements.isUnresolved(constructor)) return constructor; |
2368 // TODO(karlklose): handle optional arguments. | 2392 Selector callSelector = mapping.getSelector(node.send); |
2369 if (node.send.argumentCount() != constructor.parameterCount(compiler)) { | 2393 if (!callSelector.applies(constructor, compiler)) { |
2370 // TODO(ngeoffray): resolution error with wrong number of | 2394 warnArgumentMismatch(node.send, constructor); |
2371 // parameters. We cannot do this rigth now because of the | 2395 compiler.backend.registerThrowNoSuchMethod(); |
2372 // List constructor. | |
2373 } | 2396 } |
2374 // [constructor] might be the implementation element and only declaration | 2397 // [constructor] might be the implementation element and only declaration |
2375 // elements may be registered. | 2398 // elements may be registered. |
2376 world.registerStaticUse(constructor.declaration); | 2399 world.registerStaticUse(constructor.declaration); |
2377 compiler.withCurrentElement(constructor, () { | 2400 compiler.withCurrentElement(constructor, () { |
2378 FunctionExpression tree = constructor.parseNode(compiler); | 2401 FunctionExpression tree = constructor.parseNode(compiler); |
2379 compiler.resolver.resolveConstructorImplementation(constructor, tree); | 2402 compiler.resolver.resolveConstructorImplementation(constructor, tree); |
2380 }); | 2403 }); |
2381 // [constructor.defaultImplementation] might be the implementation element | 2404 // [constructor.defaultImplementation] might be the implementation element |
2382 // and only declaration elements may be registered. | 2405 // and only declaration elements may be registered. |
2383 world.registerStaticUse(constructor.defaultImplementation.declaration); | 2406 world.registerStaticUse(constructor.defaultImplementation.declaration); |
2384 ClassElement cls = constructor.defaultImplementation.getEnclosingClass(); | 2407 ClassElement cls = constructor.defaultImplementation.getEnclosingClass(); |
2385 // [cls] might be the implementation element and only declaration elements | 2408 // [cls] might be the implementation element and only declaration elements |
2386 // may be registered. | 2409 // may be registered. |
2387 world.registerInstantiatedClass(cls.declaration); | 2410 world.registerInstantiatedClass(cls.declaration); |
2411 if (cls.isAbstract(compiler)) { | |
2412 compiler.backend.registerAbstractClassInstantiation(); | |
2413 } | |
2388 // [cls] might be the declaration element and we want to include injected | 2414 // [cls] might be the declaration element and we want to include injected |
2389 // members. | 2415 // members. |
2390 cls.implementation.forEachInstanceField( | 2416 cls.implementation.forEachInstanceField( |
2391 (ClassElement enclosingClass, Element member) { | 2417 (ClassElement enclosingClass, Element member) { |
2392 world.addToWorkList(member); | 2418 world.addToWorkList(member); |
2393 }, | 2419 }, |
2394 includeBackendMembers: false, | 2420 includeBackendMembers: false, |
2395 includeSuperMembers: true); | 2421 includeSuperMembers: true); |
2396 return null; | 2422 return null; |
2397 } | 2423 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2480 } | 2506 } |
2481 visit(node.elements); | 2507 visit(node.elements); |
2482 } | 2508 } |
2483 | 2509 |
2484 visitConditional(Conditional node) { | 2510 visitConditional(Conditional node) { |
2485 node.visitChildren(this); | 2511 node.visitChildren(this); |
2486 } | 2512 } |
2487 | 2513 |
2488 visitStringInterpolation(StringInterpolation node) { | 2514 visitStringInterpolation(StringInterpolation node) { |
2489 world.registerInstantiatedClass(compiler.stringClass); | 2515 world.registerInstantiatedClass(compiler.stringClass); |
2516 compiler.backend.registerStringInterpolation(); | |
2490 node.visitChildren(this); | 2517 node.visitChildren(this); |
2491 } | 2518 } |
2492 | 2519 |
2493 visitStringInterpolationPart(StringInterpolationPart node) { | 2520 visitStringInterpolationPart(StringInterpolationPart node) { |
2494 registerImplicitInvocation(const SourceString('toString'), 0); | 2521 registerImplicitInvocation(const SourceString('toString'), 0); |
2495 node.visitChildren(this); | 2522 node.visitChildren(this); |
2496 } | 2523 } |
2497 | 2524 |
2498 visitBreakStatement(BreakStatement node) { | 2525 visitBreakStatement(BreakStatement node) { |
2499 TargetElement target; | 2526 TargetElement target; |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2620 }); | 2647 }); |
2621 if (!targetElement.isTarget && identical(mapping[body], targetElement)) { | 2648 if (!targetElement.isTarget && identical(mapping[body], targetElement)) { |
2622 // If the body is itself a break or continue for another target, it | 2649 // If the body is itself a break or continue for another target, it |
2623 // might have updated its mapping to the target it actually does target. | 2650 // might have updated its mapping to the target it actually does target. |
2624 mapping.remove(body); | 2651 mapping.remove(body); |
2625 } | 2652 } |
2626 } | 2653 } |
2627 | 2654 |
2628 visitLiteralMap(LiteralMap node) { | 2655 visitLiteralMap(LiteralMap node) { |
2629 world.registerInstantiatedClass(compiler.mapClass); | 2656 world.registerInstantiatedClass(compiler.mapClass); |
2657 if (node.isConst()) { | |
2658 compiler.backend.registerConstantMap(); | |
2659 } | |
2630 node.visitChildren(this); | 2660 node.visitChildren(this); |
2631 } | 2661 } |
2632 | 2662 |
2633 visitLiteralMapEntry(LiteralMapEntry node) { | 2663 visitLiteralMapEntry(LiteralMapEntry node) { |
2634 node.visitChildren(this); | 2664 node.visitChildren(this); |
2635 } | 2665 } |
2636 | 2666 |
2637 visitNamedArgument(NamedArgument node) { | 2667 visitNamedArgument(NamedArgument node) { |
2638 visit(node.expression); | 2668 visit(node.expression); |
2639 } | 2669 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2697 | 2727 |
2698 // Clean-up unused labels. | 2728 // Clean-up unused labels. |
2699 continueLabels.forEach((String key, LabelElement label) { | 2729 continueLabels.forEach((String key, LabelElement label) { |
2700 if (!label.isContinueTarget) { | 2730 if (!label.isContinueTarget) { |
2701 TargetElement targetElement = label.target; | 2731 TargetElement targetElement = label.target; |
2702 SwitchCase switchCase = targetElement.statement; | 2732 SwitchCase switchCase = targetElement.statement; |
2703 mapping.remove(switchCase); | 2733 mapping.remove(switchCase); |
2704 mapping.remove(label.label); | 2734 mapping.remove(label.label); |
2705 } | 2735 } |
2706 }); | 2736 }); |
2737 // TODO(ngeoffray): We should check here instead of the SSA backend if | |
2738 // there might be an error. | |
2739 compiler.backend.registerFallThroughError(); | |
2707 } | 2740 } |
2708 | 2741 |
2709 visitSwitchCase(SwitchCase node) { | 2742 visitSwitchCase(SwitchCase node) { |
2710 node.labelsAndCases.accept(this); | 2743 node.labelsAndCases.accept(this); |
2711 visitIn(node.statements, new BlockScope(scope)); | 2744 visitIn(node.statements, new BlockScope(scope)); |
2712 } | 2745 } |
2713 | 2746 |
2714 visitCaseMatch(CaseMatch node) { | 2747 visitCaseMatch(CaseMatch node) { |
2715 visit(node.expression); | 2748 visit(node.expression); |
2716 } | 2749 } |
2717 | 2750 |
2718 visitTryStatement(TryStatement node) { | 2751 visitTryStatement(TryStatement node) { |
2719 visit(node.tryBlock); | 2752 visit(node.tryBlock); |
2720 if (node.catchBlocks.isEmpty && node.finallyBlock == null) { | 2753 if (node.catchBlocks.isEmpty && node.finallyBlock == null) { |
2721 // TODO(ngeoffray): The precise location is | 2754 // TODO(ngeoffray): The precise location is |
2722 // node.getEndtoken.next. Adjust when issue #1581 is fixed. | 2755 // node.getEndtoken.next. Adjust when issue #1581 is fixed. |
2723 error(node, MessageKind.NO_CATCH_NOR_FINALLY); | 2756 error(node, MessageKind.NO_CATCH_NOR_FINALLY); |
2724 } | 2757 } |
2725 visit(node.catchBlocks); | 2758 visit(node.catchBlocks); |
2726 visit(node.finallyBlock); | 2759 visit(node.finallyBlock); |
2727 } | 2760 } |
2728 | 2761 |
2729 visitCatchBlock(CatchBlock node) { | 2762 visitCatchBlock(CatchBlock node) { |
2763 compiler.backend.registerCatchStatement(); | |
2730 // Check that if catch part is present, then | 2764 // Check that if catch part is present, then |
2731 // it has one or two formal parameters. | 2765 // it has one or two formal parameters. |
2732 if (node.formals != null) { | 2766 if (node.formals != null) { |
2733 if (node.formals.isEmpty) { | 2767 if (node.formals.isEmpty) { |
2734 error(node, MessageKind.EMPTY_CATCH_DECLARATION); | 2768 error(node, MessageKind.EMPTY_CATCH_DECLARATION); |
2735 } | 2769 } |
2736 if (!node.formals.nodes.tail.isEmpty && | 2770 if (!node.formals.nodes.tail.isEmpty) { |
2737 !node.formals.nodes.tail.tail.isEmpty) { | 2771 if (!node.formals.nodes.tail.tail.isEmpty) { |
2738 for (Node extra in node.formals.nodes.tail.tail) { | 2772 for (Node extra in node.formals.nodes.tail.tail) { |
2739 error(extra, MessageKind.EXTRA_CATCH_DECLARATION); | 2773 error(extra, MessageKind.EXTRA_CATCH_DECLARATION); |
2774 } | |
2740 } | 2775 } |
2776 compiler.backend.registerStackTraceInCatch(); | |
2741 } | 2777 } |
2742 | 2778 |
2743 // Check that the formals aren't optional and that they have no | 2779 // Check that the formals aren't optional and that they have no |
2744 // modifiers or type. | 2780 // modifiers or type. |
2745 for (Link<Node> link = node.formals.nodes; | 2781 for (Link<Node> link = node.formals.nodes; |
2746 !link.isEmpty; | 2782 !link.isEmpty; |
2747 link = link.tail) { | 2783 link = link.tail) { |
2748 // If the formal parameter is a node list, it means that it is a | 2784 // If the formal parameter is a node list, it means that it is a |
2749 // sequence of optional parameters. | 2785 // sequence of optional parameters. |
2750 NodeList nodeList = link.head.asNodeList(); | 2786 NodeList nodeList = link.head.asNodeList(); |
2751 if (nodeList != null) { | 2787 if (nodeList != null) { |
2752 error(nodeList, MessageKind.OPTIONAL_PARAMETER_IN_CATCH); | 2788 error(nodeList, MessageKind.OPTIONAL_PARAMETER_IN_CATCH); |
2753 } else { | 2789 } else { |
2754 VariableDefinitions declaration = link.head; | 2790 VariableDefinitions declaration = link.head; |
2755 for (Node modifier in declaration.modifiers.nodes) { | 2791 for (Node modifier in declaration.modifiers.nodes) { |
2756 error(modifier, MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH); | 2792 error(modifier, MessageKind.PARAMETER_WITH_MODIFIER_IN_CATCH); |
2757 } | 2793 } |
2758 TypeAnnotation type = declaration.type; | 2794 TypeAnnotation type = declaration.type; |
2759 if (type != null) { | 2795 if (type != null) { |
2760 error(type, MessageKind.PARAMETER_WITH_TYPE_IN_CATCH); | 2796 error(type, MessageKind.PARAMETER_WITH_TYPE_IN_CATCH); |
2761 } | 2797 } |
2762 } | 2798 } |
2763 } | 2799 } |
2764 } | 2800 } |
(...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3509 | 3545 |
3510 ConstructorResolver(Compiler compiler, this.resolver) : super(compiler); | 3546 ConstructorResolver(Compiler compiler, this.resolver) : super(compiler); |
3511 | 3547 |
3512 visitNode(Node node) { | 3548 visitNode(Node node) { |
3513 throw 'not supported'; | 3549 throw 'not supported'; |
3514 } | 3550 } |
3515 | 3551 |
3516 failOrReturnErroneousElement(Element enclosing, Node diagnosticNode, | 3552 failOrReturnErroneousElement(Element enclosing, Node diagnosticNode, |
3517 SourceString targetName, MessageKind kind, | 3553 SourceString targetName, MessageKind kind, |
3518 Map arguments) { | 3554 Map arguments) { |
3555 if (kind == MessageKind.CANNOT_FIND_CONSTRUCTOR) { | |
3556 compiler.backend.registerThrowNoSuchMethod(); | |
3557 } else { | |
3558 compiler.backend.registerThrowRuntimeError(); | |
3559 } | |
3519 if (inConstContext) { | 3560 if (inConstContext) { |
3520 error(diagnosticNode, kind, arguments); | 3561 error(diagnosticNode, kind, arguments); |
3521 } else { | 3562 } else { |
3522 ResolutionWarning warning = new ResolutionWarning(kind, arguments); | 3563 ResolutionWarning warning = new ResolutionWarning(kind, arguments); |
3523 compiler.reportWarning(diagnosticNode, warning); | 3564 compiler.reportWarning(diagnosticNode, warning); |
3524 return new ErroneousElementX(kind, arguments, targetName, enclosing); | 3565 return new ErroneousElementX(kind, arguments, targetName, enclosing); |
3525 } | 3566 } |
3526 } | 3567 } |
3527 | 3568 |
3528 Selector createConstructorSelector(SourceString constructorName) { | 3569 Selector createConstructorSelector(SourceString constructorName) { |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3657 return e; | 3698 return e; |
3658 } | 3699 } |
3659 | 3700 |
3660 /// Assumed to be called by [resolveRedirectingFactory]. | 3701 /// Assumed to be called by [resolveRedirectingFactory]. |
3661 Element visitReturn(Return node) { | 3702 Element visitReturn(Return node) { |
3662 Node expression = node.expression; | 3703 Node expression = node.expression; |
3663 return finishConstructorReference(visit(expression), | 3704 return finishConstructorReference(visit(expression), |
3664 expression, expression); | 3705 expression, expression); |
3665 } | 3706 } |
3666 } | 3707 } |
OLD | NEW |