| 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..e4ffc3ac78590da519de58362eebe06949dbe8f0 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);
|
| + 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) {
|
|
|