Chromium Code Reviews| 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 get currentElement; | 8 Element get currentElement; |
| 9 Set<Node> get superUses; | 9 Set<Node> get superUses; |
| 10 | 10 |
| (...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 538 compiler.withCurrentElement(element, () => measure(() { | 538 compiler.withCurrentElement(element, () => measure(() { |
| 539 assert(element.resolutionState == STATE_NOT_STARTED); | 539 assert(element.resolutionState == STATE_NOT_STARTED); |
| 540 element.resolutionState = STATE_STARTED; | 540 element.resolutionState = STATE_STARTED; |
| 541 Node tree = element.parseNode(compiler); | 541 Node tree = element.parseNode(compiler); |
| 542 loadSupertypes(element, tree); | 542 loadSupertypes(element, tree); |
| 543 | 543 |
| 544 ClassResolverVisitor visitor = | 544 ClassResolverVisitor visitor = |
| 545 new ClassResolverVisitor(compiler, element); | 545 new ClassResolverVisitor(compiler, element); |
| 546 visitor.visit(tree); | 546 visitor.visit(tree); |
| 547 element.resolutionState = STATE_DONE; | 547 element.resolutionState = STATE_DONE; |
| 548 compiler.onClassResolved(element); | |
| 548 })); | 549 })); |
| 549 if (element.isPatched) { | 550 if (element.isPatched) { |
| 550 // Ensure handling patch after origin. | 551 // Ensure handling patch after origin. |
| 551 element.patch.ensureResolved(compiler); | 552 element.patch.ensureResolved(compiler); |
| 552 } | 553 } |
| 553 } else { // Handle patch classes: | 554 } else { // Handle patch classes: |
| 554 element.resolutionState = STATE_STARTED; | 555 element.resolutionState = STATE_STARTED; |
| 555 // Ensure handling origin before patch. | 556 // Ensure handling origin before patch. |
| 556 element.origin.ensureResolved(compiler); | 557 element.origin.ensureResolved(compiler); |
| 557 // Ensure that the type is computed. | 558 // Ensure that the type is computed. |
| (...skipping 1054 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1612 bool inCatchBlock; | 1613 bool inCatchBlock; |
| 1613 Scope scope; | 1614 Scope scope; |
| 1614 ClassElement currentClass; | 1615 ClassElement currentClass; |
| 1615 ExpressionStatement currentExpressionStatement; | 1616 ExpressionStatement currentExpressionStatement; |
| 1616 bool typeRequired = false; | 1617 bool typeRequired = false; |
| 1617 bool sendIsMemberAccess = false; | 1618 bool sendIsMemberAccess = false; |
| 1618 StatementScope statementScope; | 1619 StatementScope statementScope; |
| 1619 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION | 1620 int allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION |
| 1620 | ElementCategory.IMPLIES_TYPE; | 1621 | ElementCategory.IMPLIES_TYPE; |
| 1621 | 1622 |
| 1623 // TODO(ahe): Find a way to share this with runtime implementation. | |
| 1624 static final RegExp symbolValidationPattern = | |
| 1625 new RegExp(r'^(?:[a-zA-Z$][a-zA-Z$0-9_]*\.)*(?:[a-zA-Z$][a-zA-Z$0-9_]*=?|' | |
| 1626 r'-|' | |
| 1627 r'unary-|' | |
| 1628 r'\[\]=|' | |
| 1629 r'~|' | |
| 1630 r'==|' | |
| 1631 r'\[\]|' | |
| 1632 r'\*|' | |
| 1633 r'/|' | |
| 1634 r'%|' | |
| 1635 r'~/|' | |
| 1636 r'\+|' | |
| 1637 r'<<|' | |
| 1638 r'>>|' | |
| 1639 r'>=|' | |
| 1640 r'>|' | |
| 1641 r'<=|' | |
| 1642 r'<|' | |
| 1643 r'&|' | |
| 1644 r'\^|' | |
| 1645 r'\|' | |
| 1646 r')$'); | |
| 1647 | |
| 1622 ResolverVisitor(Compiler compiler, Element element, this.mapping) | 1648 ResolverVisitor(Compiler compiler, Element element, this.mapping) |
| 1623 : this.enclosingElement = element, | 1649 : this.enclosingElement = element, |
| 1624 // When the element is a field, we are actually resolving its | 1650 // When the element is a field, we are actually resolving its |
| 1625 // initial value, which should not have access to instance | 1651 // initial value, which should not have access to instance |
| 1626 // fields. | 1652 // fields. |
| 1627 inInstanceContext = (element.isInstanceMember() && !element.isField()) | 1653 inInstanceContext = (element.isInstanceMember() && !element.isField()) |
| 1628 || element.isGenerativeConstructor(), | 1654 || element.isGenerativeConstructor(), |
| 1629 this.currentClass = element.isMember() ? element.getEnclosingClass() | 1655 this.currentClass = element.isMember() ? element.getEnclosingClass() |
| 1630 : null, | 1656 : null, |
| 1631 this.statementScope = new StatementScope(), | 1657 this.statementScope = new StatementScope(), |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2155 } | 2181 } |
| 2156 } | 2182 } |
| 2157 } | 2183 } |
| 2158 | 2184 |
| 2159 visitSend(Send node) { | 2185 visitSend(Send node) { |
| 2160 bool oldSendIsMemberAccess = sendIsMemberAccess; | 2186 bool oldSendIsMemberAccess = sendIsMemberAccess; |
| 2161 sendIsMemberAccess = node.isPropertyAccess || node.isCall; | 2187 sendIsMemberAccess = node.isPropertyAccess || node.isCall; |
| 2162 Element target = resolveSend(node); | 2188 Element target = resolveSend(node); |
| 2163 sendIsMemberAccess = oldSendIsMemberAccess; | 2189 sendIsMemberAccess = oldSendIsMemberAccess; |
| 2164 | 2190 |
| 2191 if (target != null && target == compiler.mirrorSystemGetNameFunction) { | |
| 2192 compiler.reportWarningCode( | |
| 2193 node.selector, MessageKind.GENERIC, | |
|
ahe
2013/04/18 11:34:44
Will provide real MessageKind before submitting.
| |
| 2194 {'text': 'Warning: using ' | |
| 2195 '"${compiler.mirrorSystemClass.name.slowToString()}.' | |
| 2196 '${compiler.mirrorSystemGetNameFunction.name.slowToString()}" ' | |
| 2197 'will increase the size of compiled code.'}); | |
| 2198 } | |
| 2199 | |
| 2165 if (!Elements.isUnresolved(target)) { | 2200 if (!Elements.isUnresolved(target)) { |
| 2166 if (target.isAbstractField()) { | 2201 if (target.isAbstractField()) { |
| 2167 AbstractFieldElement field = target; | 2202 AbstractFieldElement field = target; |
| 2168 target = field.getter; | 2203 target = field.getter; |
| 2169 if (target == null && !inInstanceContext) { | 2204 if (target == null && !inInstanceContext) { |
| 2170 compiler.backend.registerThrowNoSuchMethod(mapping); | 2205 compiler.backend.registerThrowNoSuchMethod(mapping); |
| 2171 target = | 2206 target = |
| 2172 warnAndCreateErroneousElement(node.selector, field.name, | 2207 warnAndCreateErroneousElement(node.selector, field.name, |
| 2173 MessageKind.CANNOT_RESOLVE_GETTER); | 2208 MessageKind.CANNOT_RESOLVE_GETTER); |
| 2174 } | 2209 } |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2404 | 2439 |
| 2405 visitReturn(Return node) { | 2440 visitReturn(Return node) { |
| 2406 if (node.isRedirectingFactoryBody) { | 2441 if (node.isRedirectingFactoryBody) { |
| 2407 handleRedirectingFactoryBody(node); | 2442 handleRedirectingFactoryBody(node); |
| 2408 } else { | 2443 } else { |
| 2409 visit(node.expression); | 2444 visit(node.expression); |
| 2410 } | 2445 } |
| 2411 } | 2446 } |
| 2412 | 2447 |
| 2413 void handleRedirectingFactoryBody(Return node) { | 2448 void handleRedirectingFactoryBody(Return node) { |
| 2449 final isSymbolConstructor = enclosingElement == compiler.symbolConstructor; | |
| 2414 if (!enclosingElement.isFactoryConstructor()) { | 2450 if (!enclosingElement.isFactoryConstructor()) { |
| 2415 compiler.reportErrorCode( | 2451 compiler.reportErrorCode( |
| 2416 node, MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY); | 2452 node, MessageKind.FACTORY_REDIRECTION_IN_NON_FACTORY); |
| 2417 compiler.reportErrorCode( | 2453 compiler.reportErrorCode( |
| 2418 enclosingElement, MessageKind.MISSING_FACTORY_KEYWORD); | 2454 enclosingElement, MessageKind.MISSING_FACTORY_KEYWORD); |
| 2419 } | 2455 } |
| 2420 Element redirectionTarget = resolveRedirectingFactory(node); | 2456 Element redirectionTarget = resolveRedirectingFactory(node); |
| 2421 var type = mapping.getType(node.expression); | 2457 var type = mapping.getType(node.expression); |
| 2422 if (type is InterfaceType && !type.isRaw) { | 2458 if (type is InterfaceType && !type.isRaw) { |
| 2423 unimplemented(node.expression, 'type arguments on redirecting factory'); | 2459 unimplemented(node.expression, 'type arguments on redirecting factory'); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 2438 FunctionElement targetImplementation = redirectionTarget.implementation; | 2474 FunctionElement targetImplementation = redirectionTarget.implementation; |
| 2439 FunctionExpression function = targetImplementation.parseNode(compiler); | 2475 FunctionExpression function = targetImplementation.parseNode(compiler); |
| 2440 if (function.body != null && function.body.asReturn() != null | 2476 if (function.body != null && function.body.asReturn() != null |
| 2441 && function.body.asReturn().isRedirectingFactoryBody) { | 2477 && function.body.asReturn().isRedirectingFactoryBody) { |
| 2442 unimplemented(node.expression, 'redirecing to redirecting factory'); | 2478 unimplemented(node.expression, 'redirecing to redirecting factory'); |
| 2443 } | 2479 } |
| 2444 } | 2480 } |
| 2445 world.registerStaticUse(redirectionTarget); | 2481 world.registerStaticUse(redirectionTarget); |
| 2446 world.registerInstantiatedClass( | 2482 world.registerInstantiatedClass( |
| 2447 redirectionTarget.enclosingElement.declaration, mapping); | 2483 redirectionTarget.enclosingElement.declaration, mapping); |
| 2484 if (isSymbolConstructor) { | |
| 2485 // Make sure that collection_dev.Symbol.validated is registered. | |
| 2486 // TODO(ahe): Don't simply use head. | |
|
ahe
2013/04/18 11:34:44
Will fix before submitting.
| |
| 2487 world.registerStaticUse( | |
| 2488 redirectionTarget.enclosingElement.constructors.head); | |
| 2489 } | |
| 2448 } | 2490 } |
| 2449 | 2491 |
| 2450 visitThrow(Throw node) { | 2492 visitThrow(Throw node) { |
| 2451 if (!inCatchBlock && node.expression == null) { | 2493 if (!inCatchBlock && node.expression == null) { |
| 2452 error(node, MessageKind.THROW_WITHOUT_EXPRESSION); | 2494 error(node, MessageKind.THROW_WITHOUT_EXPRESSION); |
| 2453 } | 2495 } |
| 2454 // We don't know ahead of time whether we will need the throw in a statement | 2496 // We don't know ahead of time whether we will need the throw in a statement |
| 2455 // context or an expression context, so we register both here, even though | 2497 // context or an expression context, so we register both here, even though |
| 2456 // we may not need ThrowExpression. | 2498 // we may not need ThrowExpression. |
| 2457 compiler.backend.registerWrapException(mapping); | 2499 compiler.backend.registerWrapException(mapping); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 2483 visitParenthesizedExpression(ParenthesizedExpression node) { | 2525 visitParenthesizedExpression(ParenthesizedExpression node) { |
| 2484 bool oldSendIsMemberAccess = sendIsMemberAccess; | 2526 bool oldSendIsMemberAccess = sendIsMemberAccess; |
| 2485 sendIsMemberAccess = false; | 2527 sendIsMemberAccess = false; |
| 2486 visit(node.expression); | 2528 visit(node.expression); |
| 2487 sendIsMemberAccess = oldSendIsMemberAccess; | 2529 sendIsMemberAccess = oldSendIsMemberAccess; |
| 2488 } | 2530 } |
| 2489 | 2531 |
| 2490 visitNewExpression(NewExpression node) { | 2532 visitNewExpression(NewExpression node) { |
| 2491 Node selector = node.send.selector; | 2533 Node selector = node.send.selector; |
| 2492 FunctionElement constructor = resolveConstructor(node); | 2534 FunctionElement constructor = resolveConstructor(node); |
| 2535 final bool isSymbolConstructor = constructor == compiler.symbolConstructor; | |
| 2536 if (!node.isConst() && isSymbolConstructor) { | |
| 2537 String name = compiler.symbolClass.name.slowToString(); | |
| 2538 compiler.reportWarningCode( | |
| 2539 node.newToken, MessageKind.GENERIC, | |
|
ahe
2013/04/18 11:34:44
Will provide real MessageKind before submitting.
| |
| 2540 {'text': 'Warning: using "new $name" will increase the size of ' | |
| 2541 'compiled code. Use "const $name" if possible.'}); | |
| 2542 } | |
| 2493 resolveSelector(node.send); | 2543 resolveSelector(node.send); |
| 2494 resolveArguments(node.send.argumentsNode); | 2544 resolveArguments(node.send.argumentsNode); |
| 2495 useElement(node.send, constructor); | 2545 useElement(node.send, constructor); |
| 2496 if (Elements.isUnresolved(constructor)) return constructor; | 2546 if (Elements.isUnresolved(constructor)) return constructor; |
| 2497 Selector callSelector = mapping.getSelector(node.send); | 2547 Selector callSelector = mapping.getSelector(node.send); |
| 2498 if (!callSelector.applies(constructor, compiler)) { | 2548 if (!callSelector.applies(constructor, compiler)) { |
| 2499 warnArgumentMismatch(node.send, constructor); | 2549 warnArgumentMismatch(node.send, constructor); |
| 2500 compiler.backend.registerThrowNoSuchMethod(mapping); | 2550 compiler.backend.registerThrowNoSuchMethod(mapping); |
| 2501 } | 2551 } |
| 2502 compiler.withCurrentElement(constructor, () { | 2552 compiler.withCurrentElement(constructor, () { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 2525 compiler.backend.registerAbstractClassInstantiation(mapping); | 2575 compiler.backend.registerAbstractClassInstantiation(mapping); |
| 2526 } | 2576 } |
| 2527 // [cls] might be the declaration element and we want to include injected | 2577 // [cls] might be the declaration element and we want to include injected |
| 2528 // members. | 2578 // members. |
| 2529 cls.implementation.forEachInstanceField( | 2579 cls.implementation.forEachInstanceField( |
| 2530 (ClassElement enclosingClass, Element member) { | 2580 (ClassElement enclosingClass, Element member) { |
| 2531 world.addToWorkList(member); | 2581 world.addToWorkList(member); |
| 2532 }, | 2582 }, |
| 2533 includeBackendMembers: false, | 2583 includeBackendMembers: false, |
| 2534 includeSuperMembers: true); | 2584 includeSuperMembers: true); |
| 2585 | |
| 2586 if (node.isConst() && isSymbolConstructor) { | |
| 2587 Node argumentNode = node.send.arguments.head; | |
| 2588 Constant name = compiler.metadataHandler.compileNodeWithDefinitions( | |
| 2589 argumentNode, mapping, isConst: true); | |
| 2590 if (!name.isString()) { | |
| 2591 compiler.reportErrorCode(argumentNode, MessageKind.GENERIC, | |
|
ahe
2013/04/18 11:34:44
Will provide real MessageKind before submitting.
| |
| 2592 {'text': 'Not a string'}); | |
| 2593 } else { | |
| 2594 validateSymbol(argumentNode, name.toDartString().slowToString()); | |
| 2595 } | |
| 2596 } | |
| 2597 | |
| 2535 return null; | 2598 return null; |
| 2536 } | 2599 } |
| 2537 | 2600 |
| 2601 void validateSymbol(Node node, String name) { | |
| 2602 if (name.isEmpty) return; | |
| 2603 if (name.startsWith('_')) { | |
| 2604 compiler.reportErrorCode(node, MessageKind.GENERIC, | |
|
ahe
2013/04/18 11:34:44
Will provide real MessageKind before submitting.
| |
| 2605 {'text': '"$name" is a private identifier.'}); | |
| 2606 return; | |
| 2607 } | |
| 2608 if (!symbolValidationPattern.hasMatch(name)) { | |
| 2609 // TODO(ahe): Better error message. | |
| 2610 compiler.reportErrorCode( | |
| 2611 node, MessageKind.GENERIC, | |
|
ahe
2013/04/18 11:34:44
Will provide real MessageKind before submitting.
| |
| 2612 {'text': | |
| 2613 '"$name" must be a library name, operator name, or identifier.'}); | |
| 2614 } | |
| 2615 } | |
| 2616 | |
| 2617 | |
| 2538 /** | 2618 /** |
| 2539 * Try to resolve the constructor that is referred to by [node]. | 2619 * Try to resolve the constructor that is referred to by [node]. |
| 2540 * Note: this function may return an ErroneousFunctionElement instead of | 2620 * Note: this function may return an ErroneousFunctionElement instead of |
| 2541 * [null], if there is no corresponding constructor, class or library. | 2621 * [null], if there is no corresponding constructor, class or library. |
| 2542 */ | 2622 */ |
| 2543 FunctionElement resolveConstructor(NewExpression node) { | 2623 FunctionElement resolveConstructor(NewExpression node) { |
| 2544 return node.accept(new ConstructorResolver(compiler, this)); | 2624 return node.accept(new ConstructorResolver(compiler, this)); |
| 2545 } | 2625 } |
| 2546 | 2626 |
| 2547 FunctionElement resolveRedirectingFactory(Return node) { | 2627 FunctionElement resolveRedirectingFactory(Return node) { |
| (...skipping 1329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3877 return e; | 3957 return e; |
| 3878 } | 3958 } |
| 3879 | 3959 |
| 3880 /// Assumed to be called by [resolveRedirectingFactory]. | 3960 /// Assumed to be called by [resolveRedirectingFactory]. |
| 3881 Element visitReturn(Return node) { | 3961 Element visitReturn(Return node) { |
| 3882 Node expression = node.expression; | 3962 Node expression = node.expression; |
| 3883 return finishConstructorReference(visit(expression), | 3963 return finishConstructorReference(visit(expression), |
| 3884 expression, expression); | 3964 expression, expression); |
| 3885 } | 3965 } |
| 3886 } | 3966 } |
| OLD | NEW |