Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Side by Side Diff: lib/compiler/implementation/resolver.dart

Issue 10868069: Throw a runtime error when trying to call a constructor of a class that could not be resolved. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/lib/js_helper.dart ('k') | lib/compiler/implementation/ssa/builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698