| 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 interface TreeElements { | 5 interface TreeElements { |
| 6 Element operator[](Node node); | 6 Element operator[](Node node); |
| 7 Selector getSelector(Send send); | 7 Selector getSelector(Send send); |
| 8 Type getType(TypeAnnotation annotation); | 8 Type getType(TypeAnnotation annotation); |
| 9 } | 9 } |
| 10 | 10 |
| (...skipping 1204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1215 return null; | 1215 return null; |
| 1216 } | 1216 } |
| 1217 if (currentClass.supertype === null) { | 1217 if (currentClass.supertype === null) { |
| 1218 // This is just to guard against internal errors, so no need | 1218 // This is just to guard against internal errors, so no need |
| 1219 // for a real error message. | 1219 // for a real error message. |
| 1220 error(node.receiver, MessageKind.GENERIC, ["Object has no superclass"]); | 1220 error(node.receiver, MessageKind.GENERIC, ["Object has no superclass"]); |
| 1221 } | 1221 } |
| 1222 target = currentClass.lookupSuperMember(name); | 1222 target = currentClass.lookupSuperMember(name); |
| 1223 // [target] may be null which means invoking noSuchMethod on | 1223 // [target] may be null which means invoking noSuchMethod on |
| 1224 // super. | 1224 // super. |
| 1225 } else if (resolvedReceiver === null) { | 1225 } else if (Element.isInvalid(resolvedReceiver)) { |
| 1226 return null; | 1226 return null; |
| 1227 } else if (resolvedReceiver.kind === ElementKind.CLASS) { | 1227 } else if (resolvedReceiver.kind === ElementKind.CLASS) { |
| 1228 ClassElement receiverClass = resolvedReceiver; | 1228 ClassElement receiverClass = resolvedReceiver; |
| 1229 target = receiverClass.ensureResolved(compiler).lookupLocalMember(name); | 1229 target = receiverClass.ensureResolved(compiler).lookupLocalMember(name); |
| 1230 if (target === null) { | 1230 if (target === null) { |
| 1231 error(node, MessageKind.METHOD_NOT_FOUND, [receiverClass.name, name]); | 1231 error(node, MessageKind.METHOD_NOT_FOUND, [receiverClass.name, name]); |
| 1232 } else if (target.isInstanceMember()) { | 1232 } else if (target.isInstanceMember()) { |
| 1233 error(node, MessageKind.MEMBER_NOT_STATIC, [receiverClass.name, name]); | 1233 error(node, MessageKind.MEMBER_NOT_STATIC, [receiverClass.name, name]); |
| 1234 } | 1234 } |
| 1235 } else if (resolvedReceiver.kind === ElementKind.PREFIX) { | 1235 } else if (resolvedReceiver.kind === ElementKind.PREFIX) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1318 if (argument.asNamedArgument() != null) { | 1318 if (argument.asNamedArgument() != null) { |
| 1319 seenNamedArgument = true; | 1319 seenNamedArgument = true; |
| 1320 } else if (seenNamedArgument) { | 1320 } else if (seenNamedArgument) { |
| 1321 error(argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED); | 1321 error(argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED); |
| 1322 } | 1322 } |
| 1323 } | 1323 } |
| 1324 } | 1324 } |
| 1325 | 1325 |
| 1326 visitSend(Send node) { | 1326 visitSend(Send node) { |
| 1327 Element target = resolveSend(node); | 1327 Element target = resolveSend(node); |
| 1328 if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) { | 1328 if (!Element.isInvalid(target) |
| 1329 && target.kind == ElementKind.ABSTRACT_FIELD) { |
| 1329 AbstractFieldElement field = target; | 1330 AbstractFieldElement field = target; |
| 1330 target = field.getter; | 1331 target = field.getter; |
| 1331 } | 1332 } |
| 1332 | 1333 |
| 1333 bool resolvedArguments = false; | 1334 bool resolvedArguments = false; |
| 1334 if (node.isOperator) { | 1335 if (node.isOperator) { |
| 1335 String operatorString = node.selector.asOperator().source.stringValue; | 1336 String operatorString = node.selector.asOperator().source.stringValue; |
| 1336 if (operatorString === 'is' || operatorString === 'as') { | 1337 if (operatorString === 'is' || operatorString === 'as') { |
| 1337 assert(node.arguments.tail.isEmpty()); | 1338 assert(node.arguments.tail.isEmpty()); |
| 1338 resolveTypeTest(node.arguments.head); | 1339 resolveTypeTest(node.arguments.head); |
| 1339 resolvedArguments = true; | 1340 resolvedArguments = true; |
| 1340 } | 1341 } |
| 1341 } | 1342 } |
| 1342 | 1343 |
| 1343 if (!resolvedArguments) { | 1344 if (!resolvedArguments) { |
| 1344 resolveArguments(node.argumentsNode); | 1345 resolveArguments(node.argumentsNode); |
| 1345 } | 1346 } |
| 1346 | 1347 |
| 1347 // If the selector is null, it means that we will not be generating | 1348 // If the selector is null, it means that we will not be generating |
| 1348 // code for this as a send. | 1349 // code for this as a send. |
| 1349 Selector selector = mapping.getSelector(node); | 1350 Selector selector = mapping.getSelector(node); |
| 1350 if (selector === null) return; | 1351 if (selector === null) return; |
| 1351 | 1352 |
| 1352 // If we don't know what we're calling or if we are calling a getter, | 1353 // If we don't know what we're calling or if we are calling a getter, |
| 1353 // we need to register that fact that we may be calling a closure | 1354 // we need to register that fact that we may be calling a closure |
| 1354 // with the same arguments. | 1355 // with the same arguments. |
| 1355 if (node.isCall && | 1356 if (node.isCall && |
| 1356 (target === null || | 1357 (Element.isInvalid(target) || |
| 1357 target.isGetter() || | 1358 target.isGetter() || |
| 1358 Elements.isClosureSend(node, target))) { | 1359 Elements.isClosureSend(node, target))) { |
| 1359 Selector call = new Selector.callClosureFrom(selector); | 1360 Selector call = new Selector.callClosureFrom(selector); |
| 1360 world.registerDynamicInvocation(call.name, call); | 1361 world.registerDynamicInvocation(call.name, call); |
| 1361 } | 1362 } |
| 1362 | 1363 |
| 1363 // TODO(ngeoffray): We should do the check in | 1364 // TODO(ngeoffray): We should do the check in |
| 1364 // visitExpressionStatement instead. | 1365 // visitExpressionStatement instead. |
| 1365 if (target === compiler.assertMethod && !node.isCall) { | 1366 if (target === compiler.assertMethod && !node.isCall) { |
| 1366 // We can only use assert by calling it. | 1367 // We can only use assert by calling it. |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1550 compiler.internalError("malformed send in new expression"); | 1551 compiler.internalError("malformed send in new expression"); |
| 1551 } | 1552 } |
| 1552 } | 1553 } |
| 1553 | 1554 |
| 1554 /** | 1555 /** |
| 1555 * Try to resolve the constructor that is referred to by [node]. | 1556 * Try to resolve the constructor that is referred to by [node]. |
| 1556 * Note: this function may return an ErroneousFunctionElement instead of | 1557 * Note: this function may return an ErroneousFunctionElement instead of |
| 1557 * [null], if there is no corresponding constructor, class or library. | 1558 * [null], if there is no corresponding constructor, class or library. |
| 1558 */ | 1559 */ |
| 1559 FunctionElement resolveConstructor(NewExpression node) { | 1560 FunctionElement resolveConstructor(NewExpression node) { |
| 1560 TypeAnnotation annotation = getTypeAnnotationFromSend(node.send); | 1561 // Resolve the constructor that [node] refers to. |
| 1561 // TODO(karlklose): clean up: the type should be resolved in the | |
| 1562 // constructor resolver visitor to avoid visiting the node twice. | |
| 1563 resolveTypeRequired(annotation); | |
| 1564 ConstructorResolver visitor = | 1562 ConstructorResolver visitor = |
| 1565 new ConstructorResolver(compiler, this, node.isConst()); | 1563 new ConstructorResolver(compiler, this, node.isConst()); |
| 1566 return node.accept(visitor); | 1564 FunctionElement constructor = node.accept(visitor); |
| 1565 // Try to resolve the type that the new-expression constructs. |
| 1566 TypeAnnotation annotation = getTypeAnnotationFromSend(node.send); |
| 1567 if (Element.isInvalid(constructor)) { |
| 1568 // Resolve the type arguments. We cannot create a type and check the |
| 1569 // number of type arguments for this annotation, because we do not know |
| 1570 // the element. |
| 1571 Link arguments = const EmptyLink<Node>(); |
| 1572 if (annotation.typeArguments != null) { |
| 1573 arguments = annotation.typeArguments.nodes; |
| 1574 } |
| 1575 for (Node argument in arguments) { |
| 1576 resolveTypeRequired(argument); |
| 1577 } |
| 1578 } else { |
| 1579 // Resolve and store the type this annotation resolves to. The type |
| 1580 // is used in the backend, e.g., for creating runtime type information. |
| 1581 // TODO(karlklose): This will resolve the class element again. Refactor |
| 1582 // so we can use the TypeResolver. |
| 1583 resolveTypeRequired(annotation); |
| 1584 } |
| 1585 return constructor; |
| 1567 } | 1586 } |
| 1568 | 1587 |
| 1569 Type resolveTypeRequired(TypeAnnotation node) { | 1588 Type resolveTypeRequired(TypeAnnotation node) { |
| 1570 bool old = typeRequired; | 1589 bool old = typeRequired; |
| 1571 typeRequired = true; | 1590 typeRequired = true; |
| 1572 Type result = resolveTypeAnnotation(node); | 1591 Type result = resolveTypeAnnotation(node); |
| 1573 typeRequired = old; | 1592 typeRequired = old; |
| 1574 return result; | 1593 return result; |
| 1575 } | 1594 } |
| 1576 | 1595 |
| (...skipping 818 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2395 final bool inConstContext; | 2414 final bool inConstContext; |
| 2396 | 2415 |
| 2397 ConstructorResolver(Compiler compiler, this.resolver, | 2416 ConstructorResolver(Compiler compiler, this.resolver, |
| 2398 [bool this.inConstContext = false]) | 2417 [bool this.inConstContext = false]) |
| 2399 : super(compiler); | 2418 : super(compiler); |
| 2400 | 2419 |
| 2401 visitNode(Node node) { | 2420 visitNode(Node node) { |
| 2402 throw 'not supported'; | 2421 throw 'not supported'; |
| 2403 } | 2422 } |
| 2404 | 2423 |
| 2424 failOrReturnErroneousElement(Element enclosing, Node diagnosticNode, |
| 2425 MessageKind kind, List arguments) { |
| 2426 if (inConstContext) { |
| 2427 error(diagnosticNode, kind, arguments); |
| 2428 } else { |
| 2429 ResolutionWarning warning = new ResolutionWarning(kind, arguments); |
| 2430 compiler.reportWarning(diagnosticNode, warning); |
| 2431 return new ErroneousFunctionElement(warning.message, enclosing); |
| 2432 } |
| 2433 } |
| 2434 |
| 2405 FunctionElement lookupConstructor(ClassElement cls, | 2435 FunctionElement lookupConstructor(ClassElement cls, |
| 2406 Node diagnosticNode, | 2436 Node diagnosticNode, |
| 2407 SourceString constructorName) { | 2437 SourceString constructorName) { |
| 2408 cls.ensureResolved(compiler); | 2438 cls.ensureResolved(compiler); |
| 2409 Element result = cls.lookupConstructor(cls.name, constructorName); | 2439 Element result = cls.lookupConstructor(cls.name, constructorName); |
| 2410 if (result === null) { | 2440 if (result === null) { |
| 2411 String fullConstructorName = cls.name.slowToString(); | 2441 String fullConstructorName = cls.name.slowToString(); |
| 2412 if (constructorName !== const SourceString('')) { | 2442 if (constructorName !== const SourceString('')) { |
| 2413 fullConstructorName = '$fullConstructorName' | 2443 fullConstructorName = '$fullConstructorName' |
| 2414 '.${constructorName.slowToString()}'; | 2444 '.${constructorName.slowToString()}'; |
| 2415 } | 2445 } |
| 2416 if (inConstContext) { | 2446 return failOrReturnErroneousElement(cls, diagnosticNode, |
| 2417 error(diagnosticNode, MessageKind.CANNOT_FIND_CONSTRUCTOR, | 2447 MessageKind.CANNOT_FIND_CONSTRUCTOR, |
| 2418 [fullConstructorName]); | 2448 [fullConstructorName]); |
| 2419 } else { | |
| 2420 ResolutionWarning warning = | |
| 2421 new ResolutionWarning(MessageKind.CANNOT_FIND_CONSTRUCTOR, | |
| 2422 [fullConstructorName]); | |
| 2423 compiler.reportWarning(diagnosticNode, warning); | |
| 2424 return new ErroneousFunctionElement(warning.message, cls); | |
| 2425 } | |
| 2426 } | 2449 } |
| 2427 return result; | 2450 return result; |
| 2428 } | 2451 } |
| 2429 | 2452 |
| 2430 visitNewExpression(NewExpression node) { | 2453 visitNewExpression(NewExpression node) { |
| 2431 Node selector = node.send.selector; | 2454 Node selector = node.send.selector; |
| 2432 Element e = visit(selector); | 2455 Element e = visit(selector); |
| 2433 if (!Element.isInvalid(e) && e.kind === ElementKind.CLASS) { | 2456 if (!Element.isInvalid(e) && e.kind === ElementKind.CLASS) { |
| 2434 ClassElement cls = e; | 2457 ClassElement cls = e; |
| 2435 cls.ensureResolved(compiler); | 2458 cls.ensureResolved(compiler); |
| 2436 if (cls.isInterface() && (cls.defaultClass === null)) { | 2459 if (cls.isInterface() && (cls.defaultClass === null)) { |
| 2437 error(selector, MessageKind.CANNOT_INSTANTIATE_INTERFACE, [cls.name]); | 2460 error(selector, MessageKind.CANNOT_INSTANTIATE_INTERFACE, [cls.name]); |
| 2438 } | 2461 } |
| 2439 e = lookupConstructor(cls, selector, const SourceString('')); | 2462 e = lookupConstructor(cls, selector, const SourceString('')); |
| 2440 } | 2463 } |
| 2441 return e; | 2464 return e; |
| 2442 } | 2465 } |
| 2443 | 2466 |
| 2444 visitTypeAnnotation(TypeAnnotation node) { | 2467 visitTypeAnnotation(TypeAnnotation node) { |
| 2445 // TODO(ahe): Do not ignore type arguments. | |
| 2446 return visit(node.typeName); | 2468 return visit(node.typeName); |
| 2447 } | 2469 } |
| 2448 | 2470 |
| 2449 visitSend(Send node) { | 2471 visitSend(Send node) { |
| 2450 Element e = visit(node.receiver); | 2472 Element e = visit(node.receiver); |
| 2451 if (e === null) return null; // TODO(ahe): Return erroneous element. | 2473 if (Element.isInvalid(e)) return e; |
| 2452 | |
| 2453 Identifier name = node.selector.asIdentifier(); | 2474 Identifier name = node.selector.asIdentifier(); |
| 2454 if (name === null) internalError(node.selector, 'unexpected node'); | 2475 if (name === null) internalError(node.selector, 'unexpected node'); |
| 2455 | 2476 |
| 2456 if (e.kind === ElementKind.CLASS) { | 2477 if (e.kind === ElementKind.CLASS) { |
| 2457 ClassElement cls = e; | 2478 ClassElement cls = e; |
| 2458 cls.ensureResolved(compiler); | 2479 cls.ensureResolved(compiler); |
| 2459 if (cls.isInterface() && (cls.defaultClass === null)) { | 2480 if (cls.isInterface() && (cls.defaultClass === null)) { |
| 2460 error(node.receiver, MessageKind.CANNOT_INSTANTIATE_INTERFACE, | 2481 error(node.receiver, MessageKind.CANNOT_INSTANTIATE_INTERFACE, |
| 2461 [cls.name]); | 2482 [cls.name]); |
| 2462 } | 2483 } |
| 2463 return lookupConstructor(cls, name, name.source); | 2484 return lookupConstructor(cls, name, name.source); |
| 2464 } else if (e.kind === ElementKind.PREFIX) { | 2485 } else if (e.kind === ElementKind.PREFIX) { |
| 2465 PrefixElement prefix = e; | 2486 PrefixElement prefix = e; |
| 2466 e = prefix.lookupLocalMember(name.source); | 2487 e = prefix.lookupLocalMember(name.source); |
| 2467 if (e === null) { | 2488 if (e === null) { |
| 2468 error(name, MessageKind.CANNOT_RESOLVE, [name]); | 2489 return failOrReturnErroneousElement(e, name, |
| 2469 // TODO(ahe): Return erroneous element. | 2490 MessageKind.CANNOT_RESOLVE, |
| 2491 [name]); |
| 2470 } else if (e.kind !== ElementKind.CLASS) { | 2492 } else if (e.kind !== ElementKind.CLASS) { |
| 2471 error(node, MessageKind.NOT_A_TYPE, [name]); | 2493 error(node, MessageKind.NOT_A_TYPE, [name]); |
| 2472 } | 2494 } |
| 2473 } else { | 2495 } else { |
| 2474 internalError(node.receiver, 'unexpected element $e'); | 2496 internalError(node.receiver, 'unexpected element $e'); |
| 2475 } | 2497 } |
| 2476 return e; | 2498 return e; |
| 2477 } | 2499 } |
| 2478 | 2500 |
| 2479 Element visitIdentifier(Identifier node) { | 2501 Element visitIdentifier(Identifier node) { |
| 2480 SourceString name = node.source; | 2502 SourceString name = node.source; |
| 2481 Element e = resolver.lookup(node, name); | 2503 Element e = resolver.lookup(node, name); |
| 2482 if (e === null) { | 2504 if (e === null) { |
| 2483 error(node, MessageKind.CANNOT_RESOLVE, [name]); | 2505 return failOrReturnErroneousElement(resolver.enclosingElement, node, |
| 2484 // TODO(ahe): Return erroneous element. | 2506 MessageKind.CANNOT_RESOLVE, [name]); |
| 2485 } else if (e.kind === ElementKind.TYPEDEF) { | 2507 } else if (e.kind === ElementKind.TYPEDEF) { |
| 2486 error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF, [name]); | 2508 error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF, [name]); |
| 2487 } else if (e.kind !== ElementKind.CLASS && e.kind !== ElementKind.PREFIX) { | 2509 } else if (e.kind !== ElementKind.CLASS && e.kind !== ElementKind.PREFIX) { |
| 2488 error(node, MessageKind.NOT_A_TYPE, [name]); | 2510 error(node, MessageKind.NOT_A_TYPE, [name]); |
| 2489 } | 2511 } |
| 2490 return e; | 2512 return e; |
| 2491 } | 2513 } |
| 2492 } | 2514 } |
| 2493 | 2515 |
| 2494 class Scope { | 2516 class Scope { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2606 TopScope(LibraryElement library) : super(null, library); | 2628 TopScope(LibraryElement library) : super(null, library); |
| 2607 Element lookup(SourceString name) { | 2629 Element lookup(SourceString name) { |
| 2608 return library.find(name); | 2630 return library.find(name); |
| 2609 } | 2631 } |
| 2610 | 2632 |
| 2611 Element add(Element newElement) { | 2633 Element add(Element newElement) { |
| 2612 throw "Cannot add an element in the top scope"; | 2634 throw "Cannot add an element in the top scope"; |
| 2613 } | 2635 } |
| 2614 String toString() => '$element'; | 2636 String toString() => '$element'; |
| 2615 } | 2637 } |
| OLD | NEW |