Chromium Code Reviews| Index: lib/compiler/implementation/dart_backend/placeholder_collector.dart |
| diff --git a/lib/compiler/implementation/dart_backend/placeholder_collector.dart b/lib/compiler/implementation/dart_backend/placeholder_collector.dart |
| index b1b363908c7a6230cc07bb48da17b4fd90536ce9..a56e675576944af3da8441104e9607d3f9d7d473 100644 |
| --- a/lib/compiler/implementation/dart_backend/placeholder_collector.dart |
| +++ b/lib/compiler/implementation/dart_backend/placeholder_collector.dart |
| @@ -24,6 +24,12 @@ class FunctionScope { |
| } |
| } |
| +class ConstructorPlaceholder { |
| + final Node node; |
| + final DartType type; |
| + ConstructorPlaceholder(this.node, this.type); |
| +} |
| + |
| class DeclarationTypePlaceholder { |
| final TypeAnnotation typeNode; |
| final bool requiresVar; |
| @@ -92,37 +98,16 @@ class SendVisitor extends ResolvedVisitor { |
| || identical(element, compiler.assertMethod)) { |
| return; |
| } |
| + // TODO(smok): We should never go inside this IF, check? |
| if (element.isConstructor() || element.isFactoryConstructor()) { |
| // Rename named constructor in redirection position: |
| // class C { C.named(); C.redirecting() : this.named(); } |
| + // TODO(smok): Fix redirecting constructors. |
| if (node.receiver is Identifier |
| && node.receiver.asIdentifier().isThis()) { |
| assert(node.selector is Identifier); |
| collector.tryMakeMemberPlaceholder(node.selector); |
| } |
| - // Field names can be exposed as names of optional arguments, e.g. |
| - // class C { |
| - // final field; |
| - // C([this.field]); |
| - // } |
| - // Do not forget to rename them as well. |
| - FunctionElement functionElement = element; |
| - Link<Element> optionalParameters = |
| - functionElement.functionSignature.optionalParameters; |
| - for (final argument in node.argumentsNode) { |
| - NamedArgument named = argument.asNamedArgument(); |
| - if (named == null) continue; |
| - Identifier name = named.name; |
| - String nameAsString = name.source.slowToString(); |
| - for (final parameter in optionalParameters) { |
| - if (identical(parameter.kind, ElementKind.FIELD_PARAMETER)) { |
| - if (parameter.name.slowToString() == nameAsString) { |
| - collector.tryMakeMemberPlaceholder(name); |
| - break; |
| - } |
| - } |
| - } |
| - } |
| return; |
| } |
| collector.makeElementPlaceholder(node.selector, element); |
| @@ -146,11 +131,12 @@ class PlaceholderCollector extends Visitor { |
| final Map<Element, ElementAst> elementAsts; |
| final Set<Node> nullNodes; // Nodes that should not be in output. |
| final Set<Identifier> unresolvedNodes; |
| - final Map<Element, Set<Identifier>> elementNodes; |
| + final Map<Element, Set<Node>> elementNodes; |
| final Map<FunctionElement, FunctionScope> functionScopes; |
| final Map<LibraryElement, Set<Identifier>> privateNodes; |
| final List<DeclarationTypePlaceholder> declarationTypePlaceholders; |
| final Map<String, Set<Identifier>> memberPlaceholders; |
| + final Map<Element, List<ConstructorPlaceholder>> constructorPlaceholders; |
| Map<String, LocalPlaceholder> currentLocalPlaceholders; |
| Element currentElement; |
| FunctionElement topmostEnclosingFunction; |
| @@ -165,20 +151,18 @@ class PlaceholderCollector extends Visitor { |
| PlaceholderCollector(this.compiler, this.fixedMemberNames, this.elementAsts) : |
| nullNodes = new Set<Node>(), |
| unresolvedNodes = new Set<Identifier>(), |
| - elementNodes = new Map<Element, Set<Identifier>>(), |
| + elementNodes = new Map<Element, Set<Node>>(), |
| functionScopes = new Map<FunctionElement, FunctionScope>(), |
| privateNodes = new Map<LibraryElement, Set<Identifier>>(), |
| declarationTypePlaceholders = new List<DeclarationTypePlaceholder>(), |
| - memberPlaceholders = new Map<String, Set<Identifier>>(); |
| - |
| - void tryMakeConstructorNamePlaceholder( |
| - FunctionExpression constructor, ClassElement element) { |
| - Node nameNode = constructor.name; |
| - if (nameNode is Send) nameNode = nameNode.receiver; |
| - if (nameNode.asIdentifier().token.slowToString() |
| - == element.name.slowToString()) { |
| - makeElementPlaceholder(nameNode, element); |
| - } |
| + memberPlaceholders = new Map<String, Set<Identifier>>(), |
| + constructorPlaceholders = |
| + new Map<Element, List<ConstructorPlaceholder>>(); |
| + |
| + void tryMakeConstructorPlaceholder( |
| + FunctionExpression constructor, FunctionElement constructorElement) { |
| + DartType type = constructorElement.getEnclosingClass().type.asRaw(); |
| + makeConstructorPlaceholder(constructor.name, constructorElement, type); |
| } |
| void collectFunctionDeclarationPlaceholders( |
| @@ -195,29 +179,7 @@ class PlaceholderCollector extends Visitor { |
| // 0.dart: class C { C(); } |
| // 1.dart: interface C default p0.C { C(); } |
| // the second case is just a bug now. |
| - tryMakeConstructorNamePlaceholder(node, element.getEnclosingClass()); |
| - |
| - // If we have interface constructor, make sure that we put placeholder |
| - // for its default factory implementation. |
| - // Example: |
| - // interface I default C { I();} |
| - // class C { factory I() {} } |
| - // 2 cases: |
| - // Plain interface name. Rename it unless it is the default |
| - // constructor for enclosing class. |
| - // Example: |
| - // interface I { I(); } |
| - // class C implements I { C(); } don't rename this case. |
| - // OR I.named() inside C, rename first part. |
| - if (element.defaultImplementation != null |
| - && !identical(element.defaultImplementation, element)) { |
| - FunctionElement implementingFactory = element.defaultImplementation; |
| - if (implementingFactory is !SynthesizedConstructorElement) { |
| - tryMakeConstructorNamePlaceholder( |
| - elementAsts[implementingFactory].ast, |
| - element.getEnclosingClass()); |
| - } |
| - } |
| + tryMakeConstructorPlaceholder(node, element); |
| } else if (Elements.isStaticOrTopLevel(element)) { |
| // Note: this code should only rename private identifiers for class' |
| // fields/getters/setters/methods. Top-level identifiers are renamed |
| @@ -331,7 +293,7 @@ class PlaceholderCollector extends Visitor { |
| nullNodes.add(node); |
| } |
| - void makeElementPlaceholder(Identifier node, Element element) { |
| + void makeElementPlaceholder(Node node, Element element) { |
| assert(element != null); |
| if (identical(element, entryFunction)) return; |
| if (identical(element.getLibrary(), coreLibrary)) return; |
| @@ -343,7 +305,7 @@ class PlaceholderCollector extends Visitor { |
| 'Should never make element placeholder for dynamic type element', |
| node: node); |
| } |
| - elementNodes.putIfAbsent(element, () => new Set<Identifier>()).add(node); |
| + elementNodes.putIfAbsent(element, () => new Set<Node>()).add(node); |
| } |
| void makePrivateIdentifier(Identifier node) { |
| @@ -369,6 +331,12 @@ class PlaceholderCollector extends Visitor { |
| getLocalPlaceholder().nodes.add(identifier); |
| } |
| + void makeConstructorPlaceholder(Node node, Element element, DartType type) { |
| + constructorPlaceholders |
| + .putIfAbsent(element, () => <ConstructorPlaceholder>[]) |
| + .add(new ConstructorPlaceholder(node, type)); |
| + } |
| + |
| void internalError(String reason, {Node node}) { |
| compiler.cancel(reason, node: node); |
| } |
| @@ -379,6 +347,45 @@ class PlaceholderCollector extends Visitor { |
| visitNode(Node node) { node.visitChildren(this); } // We must go deeper. |
| + visitNewExpression(NewExpression node) { |
| + Send send = node.send; |
| + InterfaceType type = treeElements.getType(node); |
| + assert(type !== null); |
|
Anton Muhin
2012/10/29 18:19:22
nit: != here and everywhere
Roman
2012/10/29 18:40:28
Done.
|
| + Element constructor = treeElements[send]; |
| + assert(constructor !== null); |
| + assert(send.receiver == null); |
| + if (constructor is !ErroneousElement) { |
| + makeConstructorPlaceholder(node.send.selector, constructor, type); |
| + // TODO(smok): Should this be in visitNamedArgument? |
| + // Field names can be exposed as names of optional arguments, e.g. |
| + // class C { |
| + // final field; |
| + // C([this.field]); |
| + // } |
| + // Do not forget to rename them as well. |
| + Link<Element> optionalParameters = |
| + constructor.functionSignature.optionalParameters; |
| + print(send.argumentsNode); |
| + for (final argument in send.argumentsNode) { |
| + NamedArgument named = argument.asNamedArgument(); |
| + if (named == null) continue; |
| + Identifier name = named.name; |
| + String nameAsString = name.source.slowToString(); |
| + for (final parameter in optionalParameters) { |
| + if (identical(parameter.kind, ElementKind.FIELD_PARAMETER)) { |
| + if (parameter.name.slowToString() == nameAsString) { |
| + tryMakeMemberPlaceholder(name); |
| + break; |
| + } |
| + } |
| + } |
| + } |
| + } else { |
| + makeUnresolvedPlaceholder(node.send.selector); |
| + } |
| + visit(node.send.argumentsNode); |
| + } |
| + |
| visitSend(Send send) { |
| new SendVisitor(this, treeElements).visitSend(send); |
| send.visitChildren(this); |
| @@ -448,62 +455,21 @@ class PlaceholderCollector extends Visitor { |
| } |
| // We call [resolveReturnType] to allow having 'void'. |
| final type = compiler.resolveReturnType(currentElement, node); |
| - bool hasPrefix = false; |
| if (type is InterfaceType || type is TypedefType) { |
| - Node target = node.typeName; |
| - if (node.typeName is Send) { |
| - final send = node.typeName.asSend(); |
| - Identifier receiver = send.receiver; |
| - Identifier selector = send.selector; |
| - Element potentialPrefix = |
| - currentElement.getLibrary().findLocal(receiver.source); |
| - if (potentialPrefix != null && potentialPrefix.isPrefix()) { |
| - // prefix.Class case. |
| - hasPrefix = true; |
| - } else { |
| - // Class.namedContructor case. |
| - target = receiver; |
| - // If element is unresolved, mark namedConstructor as unresolved. |
| - if (treeElements[node] == null) { |
| - makeUnresolvedPlaceholder(selector); |
| - } |
| - } |
| - } |
| // TODO(antonm): is there a better way to detect unresolved types? |
| // Corner case: dart:core type with a prefix. |
| // Most probably there are some additional problems with |
| // coreLibPrefix.topLevels. |
| - Element typeElement = type.element; |
| - Element dynamicTypeElement = compiler.types.dynamicType.element; |
| - if (hasPrefix && |
| - (identical(typeElement.getLibrary(), coreLibrary) || |
| - identical(typeElement, dynamicTypeElement))) { |
| - makeNullPlaceholder(node.typeName.asSend().receiver); |
| + if (!identical(type.element, compiler.types.dynamicType.element)) { |
| + makeTypePlaceholder(node.typeName, type); |
| } else { |
| - if (hasPrefix) { |
| - assert(node.typeName is Send); |
| - Send typeName = node.typeName; |
| - assert(typeName.receiver is Identifier); |
| - assert(typeName.selector is Identifier); |
| - makeNullPlaceholder(typeName.receiver); |
| - } |
| - if (!identical(typeElement, dynamicTypeElement)) { |
| - makeTypePlaceholder(target, type); |
| - } else { |
| - if (!isDynamicType(node)) makeUnresolvedPlaceholder(target); |
| - } |
| + if (!isDynamicType(node)) makeUnresolvedPlaceholder(node.typeName); |
| } |
| } |
| - // Trying to differentiate new A.foo() and lib.A cases. In the latter case |
| - // we don't want to go deeper into typeName. |
| - if (hasPrefix) { |
| - // Visit only type arguments, otherwise in case of lib.Class type |
| - // annotation typeName is Send and we go to visitGetterSend, as a result |
| - // "Class" is added to member placeholders. |
| - visit(node.typeArguments); |
| - } else { |
| - node.visitChildren(this); |
| - } |
| + // Visit only type arguments, otherwise in case of lib.Class type |
| + // annotation typeName is Send and we go to visitGetterSend, as a result |
| + // "Class" is added to member placeholders. |
| + visit(node.typeArguments); |
| } |
| visitVariableDefinitions(VariableDefinitions node) { |