| 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 1177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1188 return null; | 1188 return null; |
| 1189 } | 1189 } |
| 1190 if (currentClass.supertype === null) { | 1190 if (currentClass.supertype === null) { |
| 1191 // This is just to guard against internal errors, so no need | 1191 // This is just to guard against internal errors, so no need |
| 1192 // for a real error message. | 1192 // for a real error message. |
| 1193 error(node.receiver, MessageKind.GENERIC, ["Object has no superclass"]); | 1193 error(node.receiver, MessageKind.GENERIC, ["Object has no superclass"]); |
| 1194 } | 1194 } |
| 1195 target = currentClass.lookupSuperMember(name); | 1195 target = currentClass.lookupSuperMember(name); |
| 1196 // [target] may be null which means invoking noSuchMethod on | 1196 // [target] may be null which means invoking noSuchMethod on |
| 1197 // super. | 1197 // super. |
| 1198 } else if (resolvedReceiver === null) { | 1198 } else if (Element.isInvalid(resolvedReceiver)) { |
| 1199 return null; | 1199 return null; |
| 1200 } else if (resolvedReceiver.kind === ElementKind.CLASS) { | 1200 } else if (resolvedReceiver.kind === ElementKind.CLASS) { |
| 1201 ClassElement receiverClass = resolvedReceiver; | 1201 ClassElement receiverClass = resolvedReceiver; |
| 1202 target = receiverClass.ensureResolved(compiler).lookupLocalMember(name); | 1202 target = receiverClass.ensureResolved(compiler).lookupLocalMember(name); |
| 1203 if (target === null) { | 1203 if (target === null) { |
| 1204 error(node, MessageKind.METHOD_NOT_FOUND, [receiverClass.name, name]); | 1204 error(node, MessageKind.METHOD_NOT_FOUND, [receiverClass.name, name]); |
| 1205 } else if (target.isInstanceMember()) { | 1205 } else if (target.isInstanceMember()) { |
| 1206 error(node, MessageKind.MEMBER_NOT_STATIC, [receiverClass.name, name]); | 1206 error(node, MessageKind.MEMBER_NOT_STATIC, [receiverClass.name, name]); |
| 1207 } | 1207 } |
| 1208 } else if (resolvedReceiver.kind === ElementKind.PREFIX) { | 1208 } else if (resolvedReceiver.kind === ElementKind.PREFIX) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1291 if (argument.asNamedArgument() != null) { | 1291 if (argument.asNamedArgument() != null) { |
| 1292 seenNamedArgument = true; | 1292 seenNamedArgument = true; |
| 1293 } else if (seenNamedArgument) { | 1293 } else if (seenNamedArgument) { |
| 1294 error(argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED); | 1294 error(argument, MessageKind.INVALID_ARGUMENT_AFTER_NAMED); |
| 1295 } | 1295 } |
| 1296 } | 1296 } |
| 1297 } | 1297 } |
| 1298 | 1298 |
| 1299 visitSend(Send node) { | 1299 visitSend(Send node) { |
| 1300 Element target = resolveSend(node); | 1300 Element target = resolveSend(node); |
| 1301 if (target != null && target.kind == ElementKind.ABSTRACT_FIELD) { | 1301 if (!Element.isInvalid(target) |
| 1302 && target.kind == ElementKind.ABSTRACT_FIELD) { |
| 1302 AbstractFieldElement field = target; | 1303 AbstractFieldElement field = target; |
| 1303 target = field.getter; | 1304 target = field.getter; |
| 1304 } | 1305 } |
| 1305 | 1306 |
| 1306 bool resolvedArguments = false; | 1307 bool resolvedArguments = false; |
| 1307 if (node.isOperator) { | 1308 if (node.isOperator) { |
| 1308 String operatorString = node.selector.asOperator().source.stringValue; | 1309 String operatorString = node.selector.asOperator().source.stringValue; |
| 1309 if (operatorString === 'is' || operatorString === 'as') { | 1310 if (operatorString === 'is' || operatorString === 'as') { |
| 1310 assert(node.arguments.tail.isEmpty()); | 1311 assert(node.arguments.tail.isEmpty()); |
| 1311 resolveTypeTest(node.arguments.head); | 1312 resolveTypeTest(node.arguments.head); |
| 1312 resolvedArguments = true; | 1313 resolvedArguments = true; |
| 1313 } | 1314 } |
| 1314 } | 1315 } |
| 1315 | 1316 |
| 1316 if (!resolvedArguments) { | 1317 if (!resolvedArguments) { |
| 1317 resolveArguments(node.argumentsNode); | 1318 resolveArguments(node.argumentsNode); |
| 1318 } | 1319 } |
| 1319 | 1320 |
| 1320 // If the selector is null, it means that we will not be generating | 1321 // If the selector is null, it means that we will not be generating |
| 1321 // code for this as a send. | 1322 // code for this as a send. |
| 1322 Selector selector = mapping.getSelector(node); | 1323 Selector selector = mapping.getSelector(node); |
| 1323 if (selector === null) return; | 1324 if (selector === null) return; |
| 1324 | 1325 |
| 1325 // If we don't know what we're calling or if we are calling a getter, | 1326 // If we don't know what we're calling or if we are calling a getter, |
| 1326 // we need to register that fact that we may be calling a closure | 1327 // we need to register that fact that we may be calling a closure |
| 1327 // with the same arguments. | 1328 // with the same arguments. |
| 1328 if (node.isCall && | 1329 if (node.isCall && |
| 1329 (target === null || | 1330 (Element.isInvalid(target) || |
| 1330 target.isGetter() || | 1331 target.isGetter() || |
| 1331 Elements.isClosureSend(node, target))) { | 1332 Elements.isClosureSend(node, target))) { |
| 1332 Selector call = new Selector.callClosureFrom(selector); | 1333 Selector call = new Selector.callClosureFrom(selector); |
| 1333 world.registerDynamicInvocation(call.name, call); | 1334 world.registerDynamicInvocation(call.name, call); |
| 1334 } | 1335 } |
| 1335 | 1336 |
| 1336 // TODO(ngeoffray): We should do the check in | 1337 // TODO(ngeoffray): We should do the check in |
| 1337 // visitExpressionStatement instead. | 1338 // visitExpressionStatement instead. |
| 1338 if (target === compiler.assertMethod && !node.isCall) { | 1339 if (target === compiler.assertMethod && !node.isCall) { |
| 1339 // We can only use assert by calling it. | 1340 // We can only use assert by calling it. |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1523 compiler.internalError("malformed send in new expression"); | 1524 compiler.internalError("malformed send in new expression"); |
| 1524 } | 1525 } |
| 1525 } | 1526 } |
| 1526 | 1527 |
| 1527 /** | 1528 /** |
| 1528 * Try to resolve the constructor that is referred to by [node]. | 1529 * Try to resolve the constructor that is referred to by [node]. |
| 1529 * Note: this function may return an ErroneousFunctionElement instead of | 1530 * Note: this function may return an ErroneousFunctionElement instead of |
| 1530 * [null], if there is no corresponding constructor, class or library. | 1531 * [null], if there is no corresponding constructor, class or library. |
| 1531 */ | 1532 */ |
| 1532 FunctionElement resolveConstructor(NewExpression node) { | 1533 FunctionElement resolveConstructor(NewExpression node) { |
| 1533 TypeAnnotation annotation = getTypeAnnotationFromSend(node.send); | 1534 // Resolve the constructor that [node] refers to. |
| 1534 // TODO(karlklose): clean up: the type should be resolved in the | |
| 1535 // constructor resolver visitor to avoid visiting the node twice. | |
| 1536 resolveTypeRequired(annotation); | |
| 1537 ConstructorResolver visitor = | 1535 ConstructorResolver visitor = |
| 1538 new ConstructorResolver(compiler, this, node.isConst()); | 1536 new ConstructorResolver(compiler, this, node.isConst()); |
| 1539 return node.accept(visitor); | 1537 FunctionElement constructor = node.accept(visitor); |
| 1538 // Try to resolve the type that the new-expression constructs. |
| 1539 TypeAnnotation annotation = getTypeAnnotationFromSend(node.send); |
| 1540 if (Element.isInvalid(constructor)) { |
| 1541 // Resolve the type arguments. We cannot create a type and check the |
| 1542 // number of type arguments for this annotation, because we do not know |
| 1543 // the element. |
| 1544 Link arguments = const EmptyLink<Node>(); |
| 1545 if (annotation.typeArguments != null) { |
| 1546 arguments = annotation.typeArguments.nodes; |
| 1547 } |
| 1548 for (Node argument in arguments) { |
| 1549 resolveTypeRequired(argument); |
| 1550 } |
| 1551 } else { |
| 1552 // Resolve and store the type this annotation resolves to. The type |
| 1553 // is used in the backend, e.g., for creating runtime type information. |
| 1554 // TODO(karlklose): This will resolve the class element again. Refactor |
| 1555 // so we can use the TypeResolver. |
| 1556 resolveTypeRequired(annotation); |
| 1557 } |
| 1558 return constructor; |
| 1540 } | 1559 } |
| 1541 | 1560 |
| 1542 Type resolveTypeRequired(TypeAnnotation node) { | 1561 Type resolveTypeRequired(TypeAnnotation node) { |
| 1543 bool old = typeRequired; | 1562 bool old = typeRequired; |
| 1544 typeRequired = true; | 1563 typeRequired = true; |
| 1545 Type result = resolveTypeAnnotation(node); | 1564 Type result = resolveTypeAnnotation(node); |
| 1546 typeRequired = old; | 1565 typeRequired = old; |
| 1547 return result; | 1566 return result; |
| 1548 } | 1567 } |
| 1549 | 1568 |
| (...skipping 805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2355 final bool inConstContext; | 2374 final bool inConstContext; |
| 2356 | 2375 |
| 2357 ConstructorResolver(Compiler compiler, this.resolver, | 2376 ConstructorResolver(Compiler compiler, this.resolver, |
| 2358 [bool this.inConstContext = false]) | 2377 [bool this.inConstContext = false]) |
| 2359 : super(compiler); | 2378 : super(compiler); |
| 2360 | 2379 |
| 2361 visitNode(Node node) { | 2380 visitNode(Node node) { |
| 2362 throw 'not supported'; | 2381 throw 'not supported'; |
| 2363 } | 2382 } |
| 2364 | 2383 |
| 2384 failOrReturnErroneousElement(Element enclosing, Node diagnosticNode, |
| 2385 MessageKind kind, List arguments) { |
| 2386 if (inConstContext) { |
| 2387 error(diagnosticNode, kind, arguments); |
| 2388 } else { |
| 2389 ResolutionWarning warning = new ResolutionWarning(kind, arguments); |
| 2390 compiler.reportWarning(diagnosticNode, warning); |
| 2391 return new ErroneousFunctionElement(warning.message, enclosing); |
| 2392 } |
| 2393 } |
| 2394 |
| 2365 FunctionElement lookupConstructor(ClassElement cls, | 2395 FunctionElement lookupConstructor(ClassElement cls, |
| 2366 Node diagnosticNode, | 2396 Node diagnosticNode, |
| 2367 SourceString constructorName) { | 2397 SourceString constructorName) { |
| 2368 cls.ensureResolved(compiler); | 2398 cls.ensureResolved(compiler); |
| 2369 Element result = cls.lookupConstructor(cls.name, constructorName); | 2399 Element result = cls.lookupConstructor(cls.name, constructorName); |
| 2370 if (result === null) { | 2400 if (result === null) { |
| 2371 String fullConstructorName = cls.name.slowToString(); | 2401 String fullConstructorName = cls.name.slowToString(); |
| 2372 if (constructorName !== const SourceString('')) { | 2402 if (constructorName !== const SourceString('')) { |
| 2373 fullConstructorName = '$fullConstructorName' | 2403 fullConstructorName = '$fullConstructorName' |
| 2374 '.${constructorName.slowToString()}'; | 2404 '.${constructorName.slowToString()}'; |
| 2375 } | 2405 } |
| 2376 if (inConstContext) { | 2406 return failOrReturnErroneousElement(cls, diagnosticNode, |
| 2377 error(diagnosticNode, MessageKind.CANNOT_FIND_CONSTRUCTOR, | 2407 MessageKind.CANNOT_FIND_CONSTRUCTOR, |
| 2378 [fullConstructorName]); | 2408 [fullConstructorName]); |
| 2379 } else { | |
| 2380 ResolutionWarning warning = | |
| 2381 new ResolutionWarning(MessageKind.CANNOT_FIND_CONSTRUCTOR, | |
| 2382 [fullConstructorName]); | |
| 2383 compiler.reportWarning(diagnosticNode, warning); | |
| 2384 return new ErroneousFunctionElement(warning.message, cls); | |
| 2385 } | |
| 2386 } | 2409 } |
| 2387 return result; | 2410 return result; |
| 2388 } | 2411 } |
| 2389 | 2412 |
| 2390 visitNewExpression(NewExpression node) { | 2413 visitNewExpression(NewExpression node) { |
| 2391 Node selector = node.send.selector; | 2414 Node selector = node.send.selector; |
| 2392 Element e = visit(selector); | 2415 Element e = visit(selector); |
| 2393 if (!Element.isInvalid(e) && e.kind === ElementKind.CLASS) { | 2416 if (!Element.isInvalid(e) && e.kind === ElementKind.CLASS) { |
| 2394 ClassElement cls = e; | 2417 ClassElement cls = e; |
| 2395 cls.ensureResolved(compiler); | 2418 cls.ensureResolved(compiler); |
| 2396 if (cls.isInterface() && (cls.defaultClass === null)) { | 2419 if (cls.isInterface() && (cls.defaultClass === null)) { |
| 2397 error(selector, MessageKind.CANNOT_INSTANTIATE_INTERFACE, [cls.name]); | 2420 error(selector, MessageKind.CANNOT_INSTANTIATE_INTERFACE, [cls.name]); |
| 2398 } | 2421 } |
| 2399 e = lookupConstructor(cls, selector, const SourceString('')); | 2422 e = lookupConstructor(cls, selector, const SourceString('')); |
| 2400 } | 2423 } |
| 2401 return e; | 2424 return e; |
| 2402 } | 2425 } |
| 2403 | 2426 |
| 2404 visitTypeAnnotation(TypeAnnotation node) { | 2427 visitTypeAnnotation(TypeAnnotation node) { |
| 2405 // TODO(ahe): Do not ignore type arguments. | |
| 2406 return visit(node.typeName); | 2428 return visit(node.typeName); |
| 2407 } | 2429 } |
| 2408 | 2430 |
| 2409 visitSend(Send node) { | 2431 visitSend(Send node) { |
| 2410 Element e = visit(node.receiver); | 2432 Element e = visit(node.receiver); |
| 2411 if (e === null) return null; // TODO(ahe): Return erroneous element. | 2433 if (Element.isInvalid(e)) return e; |
| 2412 | |
| 2413 Identifier name = node.selector.asIdentifier(); | 2434 Identifier name = node.selector.asIdentifier(); |
| 2414 if (name === null) internalError(node.selector, 'unexpected node'); | 2435 if (name === null) internalError(node.selector, 'unexpected node'); |
| 2415 | 2436 |
| 2416 if (e.kind === ElementKind.CLASS) { | 2437 if (e.kind === ElementKind.CLASS) { |
| 2417 ClassElement cls = e; | 2438 ClassElement cls = e; |
| 2418 cls.ensureResolved(compiler); | 2439 cls.ensureResolved(compiler); |
| 2419 if (cls.isInterface() && (cls.defaultClass === null)) { | 2440 if (cls.isInterface() && (cls.defaultClass === null)) { |
| 2420 error(node.receiver, MessageKind.CANNOT_INSTANTIATE_INTERFACE, | 2441 error(node.receiver, MessageKind.CANNOT_INSTANTIATE_INTERFACE, |
| 2421 [cls.name]); | 2442 [cls.name]); |
| 2422 } | 2443 } |
| 2423 return lookupConstructor(cls, name, name.source); | 2444 return lookupConstructor(cls, name, name.source); |
| 2424 } else if (e.kind === ElementKind.PREFIX) { | 2445 } else if (e.kind === ElementKind.PREFIX) { |
| 2425 PrefixElement prefix = e; | 2446 PrefixElement prefix = e; |
| 2426 e = prefix.lookupLocalMember(name.source); | 2447 e = prefix.lookupLocalMember(name.source); |
| 2427 if (e === null) { | 2448 if (e === null) { |
| 2428 error(name, MessageKind.CANNOT_RESOLVE, [name]); | 2449 return failOrReturnErroneousElement(e, name, |
| 2429 // TODO(ahe): Return erroneous element. | 2450 MessageKind.CANNOT_RESOLVE, |
| 2451 [name]); |
| 2430 } else if (e.kind !== ElementKind.CLASS) { | 2452 } else if (e.kind !== ElementKind.CLASS) { |
| 2431 error(node, MessageKind.NOT_A_TYPE, [name]); | 2453 error(node, MessageKind.NOT_A_TYPE, [name]); |
| 2432 } | 2454 } |
| 2433 } else { | 2455 } else { |
| 2434 internalError(node.receiver, 'unexpected element $e'); | 2456 internalError(node.receiver, 'unexpected element $e'); |
| 2435 } | 2457 } |
| 2436 return e; | 2458 return e; |
| 2437 } | 2459 } |
| 2438 | 2460 |
| 2439 Element visitIdentifier(Identifier node) { | 2461 Element visitIdentifier(Identifier node) { |
| 2440 SourceString name = node.source; | 2462 SourceString name = node.source; |
| 2441 Element e = resolver.lookup(node, name); | 2463 Element e = resolver.lookup(node, name); |
| 2442 if (e === null) { | 2464 if (e === null) { |
| 2443 error(node, MessageKind.CANNOT_RESOLVE, [name]); | 2465 return failOrReturnErroneousElement(resolver.enclosingElement, node, |
| 2444 // TODO(ahe): Return erroneous element. | 2466 MessageKind.CANNOT_RESOLVE, [name]); |
| 2445 } else if (e.kind === ElementKind.TYPEDEF) { | 2467 } else if (e.kind === ElementKind.TYPEDEF) { |
| 2446 error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF, [name]); | 2468 error(node, MessageKind.CANNOT_INSTANTIATE_TYPEDEF, [name]); |
| 2447 } else if (e.kind !== ElementKind.CLASS && e.kind !== ElementKind.PREFIX) { | 2469 } else if (e.kind !== ElementKind.CLASS && e.kind !== ElementKind.PREFIX) { |
| 2448 error(node, MessageKind.NOT_A_TYPE, [name]); | 2470 error(node, MessageKind.NOT_A_TYPE, [name]); |
| 2449 } | 2471 } |
| 2450 return e; | 2472 return e; |
| 2451 } | 2473 } |
| 2452 } | 2474 } |
| 2453 | 2475 |
| 2454 class Scope { | 2476 class Scope { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2566 TopScope(LibraryElement library) : super(null, library); | 2588 TopScope(LibraryElement library) : super(null, library); |
| 2567 Element lookup(SourceString name) { | 2589 Element lookup(SourceString name) { |
| 2568 return library.find(name); | 2590 return library.find(name); |
| 2569 } | 2591 } |
| 2570 | 2592 |
| 2571 Element add(Element newElement) { | 2593 Element add(Element newElement) { |
| 2572 throw "Cannot add an element in the top scope"; | 2594 throw "Cannot add an element in the top scope"; |
| 2573 } | 2595 } |
| 2574 String toString() => '$element'; | 2596 String toString() => '$element'; |
| 2575 } | 2597 } |
| OLD | NEW |