| 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 71e11c99303fc7724a77d9e5f8ada1d6a4235c92..a07e5ce878a758968a0ca60e37185bd43fe3ec1e 100644
|
| --- a/lib/compiler/implementation/dart_backend/placeholder_collector.dart
|
| +++ b/lib/compiler/implementation/dart_backend/placeholder_collector.dart
|
| @@ -33,11 +33,20 @@ class SendVisitor extends ResolvedVisitor {
|
|
|
| SendVisitor(this.collector, TreeElements elements) : super(elements);
|
|
|
| - visitDynamicSend(Send node) {}
|
| - visitSuperSend(Send node) {}
|
| visitOperatorSend(Send node) {}
|
| visitForeignSend(Send node) {}
|
|
|
| + visitSuperSend(Send node) {
|
| + collector.tryMakeMemberPlaceholder(node.selector);
|
| + }
|
| +
|
| + visitDynamicSend(Send node) {
|
| + final element = elements[node];
|
| + if (element === null || !element.isErroneous()) {
|
| + collector.tryMakeMemberPlaceholder(node.selector);
|
| + }
|
| + }
|
| +
|
| visitClosureSend(Send node) {
|
| final element = elements[node];
|
| if (element !== null) {
|
| @@ -48,27 +57,64 @@ class SendVisitor extends ResolvedVisitor {
|
| visitGetterSend(Send node) {
|
| final element = elements[node];
|
| // element === null means dynamic property access.
|
| - if (element === null) return;
|
| - if (element.isPrefix()) {
|
| + if (element === null) {
|
| + collector.tryMakeMemberPlaceholder(node.selector);
|
| + } else if (element.isPrefix()) {
|
| // Node is prefix part in case of source 'lib.somesetter = 5;'
|
| collector.makeNullPlaceholder(node);
|
| } else if (Elements.isStaticOrTopLevel(element)) {
|
| // Unqualified or prefixed top level or static.
|
| collector.makeElementPlaceholder(node.selector, element);
|
| } else if (!element.isTopLevel()) {
|
| - // May get FunctionExpression here in selector
|
| - // in case of A(int this.f());
|
| - if (node.selector is Identifier) {
|
| - collector.tryMakeLocalPlaceholder(element, node.selector);
|
| + if (element.isInstanceMember()) {
|
| + collector.tryMakeMemberPlaceholder(node.selector);
|
| } else {
|
| - assert(node.selector is FunctionExpression);
|
| + // May get FunctionExpression here in selector
|
| + // in case of A(int this.f());
|
| + if (node.selector is Identifier) {
|
| + collector.tryMakeLocalPlaceholder(element, node.selector);
|
| + } else {
|
| + assert(node.selector is FunctionExpression);
|
| + }
|
| }
|
| }
|
| }
|
|
|
| visitStaticSend(Send node) {
|
| final element = elements[node];
|
| - if (element.isConstructor() || element.isFactoryConstructor()) return;
|
| + if (element.isConstructor() || element.isFactoryConstructor()) {
|
| + // Rename named constructor in redirection position:
|
| + // class C { C.named(); C.redirecting() : this.named(); }
|
| + 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 (parameter.kind === ElementKind.FIELD_PARAMETER) {
|
| + if (parameter.name.slowToString() == nameAsString) {
|
| + collector.tryMakeMemberPlaceholder(name);
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + return;
|
| + }
|
| collector.makeElementPlaceholder(node.selector, element);
|
| // Another ugly case: <lib prefix>.<top level> is represented as
|
| // receiver: lib prefix, selector: top level.
|
| @@ -86,12 +132,14 @@ class SendVisitor extends ResolvedVisitor {
|
|
|
| class PlaceholderCollector extends AbstractVisitor {
|
| final Compiler compiler;
|
| + final Set<String> fixedMemberNames; // member names which cannot be renamed.
|
| final Set<Node> nullNodes; // Nodes that should not be in output.
|
| final Set<Identifier> unresolvedNodes;
|
| 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;
|
| Map<String, LocalPlaceholder> currentLocalPlaceholders;
|
| Element currentElement;
|
| TreeElements treeElements;
|
| @@ -99,13 +147,14 @@ class PlaceholderCollector extends AbstractVisitor {
|
| LibraryElement get coreLibrary => compiler.coreLibrary;
|
| FunctionElement get entryFunction => compiler.mainApp.find(Compiler.MAIN);
|
|
|
| - PlaceholderCollector(this.compiler) :
|
| + PlaceholderCollector(this.compiler, this.fixedMemberNames) :
|
| nullNodes = new Set<Node>(),
|
| unresolvedNodes = new Set<Identifier>(),
|
| elementNodes = new Map<Element, Set<Node>>(),
|
| functionScopes = new Map<FunctionElement, FunctionScope>(),
|
| privateNodes = new Map<LibraryElement, Set<Identifier>>(),
|
| - declarationTypePlaceholders = new List<DeclarationTypePlaceholder>();
|
| + declarationTypePlaceholders = new List<DeclarationTypePlaceholder>(),
|
| + memberPlaceholders = new Map<String, Set<Identifier>>();
|
|
|
| void tryMakeConstructorNamePlaceholder(
|
| FunctionExpression constructor, ClassElement element) {
|
| @@ -157,20 +206,24 @@ class PlaceholderCollector extends AbstractVisitor {
|
| // just to escape conflicts and that should be enough as we shouldn't
|
| // be able to resolve private identifiers for other libraries.
|
| makeElementPlaceholder(node.name, element);
|
| + } else if (element.isMember()) {
|
| + if (node.name is Identifier) {
|
| + tryMakeMemberPlaceholder(node.name);
|
| + } else {
|
| + assert(node.name.asSend().isOperator);
|
| + }
|
| }
|
| }
|
|
|
| void collectFieldDeclarationPlaceholders(
|
| Element element, VariableDefinitions node) {
|
| + Node fieldNode = element.parseNode(compiler);
|
| + Identifier name =
|
| + fieldNode is Identifier ? fieldNode : fieldNode.asSend().selector;
|
| if (Elements.isStaticOrTopLevel(element)) {
|
| - Node fieldNode = element.parseNode(compiler);
|
| - if (fieldNode is Identifier) {
|
| - makeElementPlaceholder(fieldNode, element);
|
| - } else if (fieldNode is SendSet) {
|
| - makeElementPlaceholder(fieldNode.selector, element);
|
| - } else {
|
| - unreachable();
|
| - }
|
| + makeElementPlaceholder(name, element);
|
| + } else if (Elements.isInstanceField(element)) {
|
| + tryMakeMemberPlaceholder(name);
|
| }
|
| makeVarDeclarationTypePlaceholder(node);
|
| }
|
| @@ -222,6 +275,16 @@ class PlaceholderCollector extends AbstractVisitor {
|
| }
|
| }
|
|
|
| + void tryMakeMemberPlaceholder(Identifier node) {
|
| + assert(node !== null);
|
| + if (node.source.isPrivate()) return;
|
| + if (node is Operator) return;
|
| + final identifier = node.source.slowToString();
|
| + if (fixedMemberNames.contains(identifier)) return;
|
| + memberPlaceholders.putIfAbsent(
|
| + identifier, () => new Set<Identifier>()).add(node);
|
| + }
|
| +
|
| void makeTypePlaceholder(Node node, Type type) {
|
| makeElementPlaceholder(node, type.element);
|
| }
|
| @@ -312,7 +375,15 @@ class PlaceholderCollector extends AbstractVisitor {
|
| makeElementPlaceholder(send.selector, element);
|
| } else {
|
| assert(send.selector is Identifier);
|
| - tryMakeLocalPlaceholder(element, send.selector);
|
| + if (Elements.isInstanceField(element)) {
|
| + tryMakeMemberPlaceholder(send.selector);
|
| + } else {
|
| + tryMakeLocalPlaceholder(element, send.selector);
|
| + }
|
| + }
|
| + } else {
|
| + if (send.receiver !== null) {
|
| + tryMakeMemberPlaceholder(send.selector);
|
| }
|
| }
|
| send.visitChildren(this);
|
| @@ -392,9 +463,17 @@ class PlaceholderCollector extends AbstractVisitor {
|
| // May get FunctionExpression here in definition.selector
|
| // in case of A(int this.f());
|
| if (definition.selector is Identifier) {
|
| - tryMakeLocalPlaceholder(definitionElement, definition.selector);
|
| + if (definitionElement.kind === ElementKind.FIELD_PARAMETER) {
|
| + tryMakeMemberPlaceholder(definition.selector);
|
| + } else {
|
| + tryMakeLocalPlaceholder(definitionElement, definition.selector);
|
| + }
|
| } else {
|
| assert(definition.selector is FunctionExpression);
|
| + if (definitionElement.kind === ElementKind.FIELD_PARAMETER) {
|
| + tryMakeMemberPlaceholder(
|
| + definition.selector.asFunctionExpression().name);
|
| + }
|
| }
|
| } else if (definition is Identifier) {
|
| tryMakeLocalPlaceholder(definitionElement, definition);
|
|
|