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

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 1177 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698