| 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 class SendVisitor extends ResolvedVisitor { | 5 class SendVisitor extends ResolvedVisitor { |
| 6 final PlaceholderCollector collector; | 6 final PlaceholderCollector collector; |
| 7 | 7 |
| 8 SendVisitor(this.collector, TreeElements elements) : super(elements); | 8 SendVisitor(this.collector, TreeElements elements) : super(elements); |
| 9 | 9 |
| 10 visitSuperSend(Send node) {} | 10 visitSuperSend(Send node) {} |
| 11 visitOperatorSend(Send node) {} | 11 visitOperatorSend(Send node) {} |
| 12 visitClosureSend(Send node) {} | 12 visitClosureSend(Send node) {} |
| 13 visitForeignSend(Send node) {} | 13 visitForeignSend(Send node) {} |
| 14 | 14 |
| 15 visitDynamicSend(Send node) { | 15 visitDynamicSend(Send node) { |
| 16 tryRenamePrivateSelector(node); | 16 tryRenamePrivateSelector(node); |
| 17 } | 17 } |
| 18 | 18 |
| 19 visitGetterSend(Send node) { | 19 visitGetterSend(Send node) { |
| 20 final element = elements[node]; | 20 final element = elements[node]; |
| 21 // element === null means dynamic property access. | 21 // element === null means dynamic property access. |
| 22 // We don't want to rename non top-level element access. | 22 if (element === null || element.isInstanceMember()) { |
| 23 if (element === null || !element.isTopLevel()) { | |
| 24 tryRenamePrivateSelector(node); | 23 tryRenamePrivateSelector(node); |
| 25 return; | 24 return; |
| 26 } | 25 } |
| 26 // We don't want to rename non top-level element access. |
| 27 if (!element.isTopLevel()) return; |
| 27 // Unqualified <class> in static invocation, why it's not a type annotation? | 28 // Unqualified <class> in static invocation, why it's not a type annotation? |
| 28 // Another option would be to process in visitStaticSend, NB: | 29 // Another option would be to process in visitStaticSend, NB: |
| 29 // those elements are not top-level. | 30 // those elements are not top-level. |
| 30 // OR: unqualified top level. | 31 // OR: unqualified top level. |
| 31 collector.makeElementPlaceholder(node.selector, element); | 32 collector.makeElementPlaceholder(node.selector, element); |
| 32 if (node.receiver !== null) { | 33 if (node.receiver !== null) { |
| 33 // <lib prefix>.<top level>. | 34 // <lib prefix>.<top level>. |
| 34 collector.makeNullPlaceholder(node.receiver); // Cut library prefix. | 35 collector.makeNullPlaceholder(node.receiver); // Cut library prefix. |
| 35 } | 36 } |
| 36 } | 37 } |
| 37 | 38 |
| 38 visitStaticSend(Send node) { | 39 visitStaticSend(Send node) { |
| 39 final element = elements[node]; | 40 final element = elements[node]; |
| 40 if (!element.isTopLevel()) return; | 41 if (!element.isTopLevel()) return; |
| 41 // Another ugly case: <lib prefix>.<top level> is represented as | 42 // Another ugly case: <lib prefix>.<top level> is represented as |
| 42 // receiver: lib prefix, selector: top level. | 43 // receiver: lib prefix, selector: top level. |
| 43 collector.makeElementPlaceholder(node.selector, element); | 44 collector.makeElementPlaceholder(node.selector, element); |
| 44 if (node.receiver !== null) { | 45 if (node.receiver !== null) { |
| 45 assert(elements[node.receiver].isPrefix()); | 46 assert(elements[node.receiver].isPrefix()); |
| 46 // Hack: putting null into map overrides receiver of original node. | 47 // Hack: putting null into map overrides receiver of original node. |
| 47 collector.makeNullPlaceholder(node.receiver); | 48 collector.makeNullPlaceholder(node.receiver); |
| 48 } | 49 } |
| 49 } | 50 } |
| 50 | 51 |
| 51 tryRenamePrivateSelector(Send node) { | 52 tryRenamePrivateSelector(Send node) { |
| 52 Identifier selector = node.selector.asIdentifier(); | 53 collector.tryMakePrivateIdentifier(node.selector.asIdentifier()); |
| 53 assert(selector !== null); | |
| 54 if (selector.source.isPrivate()) { | |
| 55 collector.makePrivateIdentifier(selector); | |
| 56 } | |
| 57 } | 54 } |
| 58 } | 55 } |
| 59 | 56 |
| 60 class PlaceholderCollector extends AbstractVisitor { | 57 class PlaceholderCollector extends AbstractVisitor { |
| 61 final Compiler compiler; | 58 final Compiler compiler; |
| 62 final Map<Node, Placeholder> placeholders; | 59 final Map<Node, Placeholder> placeholders; |
| 63 Element currentElement; | 60 Element currentElement; |
| 64 TreeElements treeElements; | 61 TreeElements treeElements; |
| 65 | 62 |
| 66 PlaceholderCollector(this.compiler) : | 63 PlaceholderCollector(this.compiler) : |
| 67 placeholders = new Map<Node, Placeholder>(); | 64 placeholders = new Map<Node, Placeholder>(); |
| 68 | 65 |
| 69 void collectFunctionDeclarationPlaceholder( | 66 void collectFunctionDeclarationPlaceholders( |
| 70 FunctionElement element, Node node) { | 67 FunctionElement element, Node node) { |
| 71 if (element.isGenerativeConstructor() || element.isFactoryConstructor()) { | 68 if (element.isGenerativeConstructor() || element.isFactoryConstructor()) { |
| 72 // Two complicated cases for class/interface renaming: | 69 // Two complicated cases for class/interface renaming: |
| 73 // 1) class which implements constructors of other interfaces, but not | 70 // 1) class which implements constructors of other interfaces, but not |
| 74 // implements interfaces themselves: | 71 // implements interfaces themselves: |
| 75 // 0.dart: class C { I(); } | 72 // 0.dart: class C { I(); } |
| 76 // 1.dart and 2.dart: interface I default C { I(); } | 73 // 1.dart and 2.dart: interface I default C { I(); } |
| 77 // now we have to duplicate our I() constructor in C class with | 74 // now we have to duplicate our I() constructor in C class with |
| 78 // proper names. | 75 // proper names. |
| 79 // 2) (even worse for us): | 76 // 2) (even worse for us): |
| 80 // 0.dart: class C { C(); } | 77 // 0.dart: class C { C(); } |
| 81 // 1.dart: interface C default p0.C { C(); } | 78 // 1.dart: interface C default p0.C { C(); } |
| 82 // the second case is just a bug now. | 79 // the second case is just a bug now. |
| 83 final enclosingClass = element.getEnclosingClass(); | 80 final enclosingClass = element.getEnclosingClass(); |
| 84 Node nameNode = node.name; | 81 Node nameNode = node.name; |
| 85 if (nameNode is Send) nameNode = nameNode.receiver; | 82 if (nameNode is Send) nameNode = nameNode.receiver; |
| 86 // For cases like class C implements I { I(); } | 83 // For cases like class C implements I { I(); } |
| 87 if (nameNode.token.slowToString() == enclosingClass.name.slowToString()) { | 84 if (nameNode.token.slowToString() == enclosingClass.name.slowToString()) { |
| 88 makeTypePlaceholder(nameNode, enclosingClass.type); | 85 makeTypePlaceholder(nameNode, enclosingClass.type); |
| 89 } | 86 } |
| 87 // Process Ctor(this._field) correctly. |
| 88 for (Node parameter in node.parameters) { |
| 89 VariableDefinitions definitions = parameter.asVariableDefinitions(); |
| 90 if (definitions !== null) { |
| 91 for (Node definition in definitions.definitions) { |
| 92 Send send = definition.asSend(); |
| 93 if (send !== null) { |
| 94 assert(send.receiver.isThis()); |
| 95 tryMakePrivateIdentifier(send.selector.asIdentifier()); |
| 96 } else { |
| 97 assert(definition is Identifier); |
| 98 } |
| 99 } |
| 100 } else { |
| 101 assert(parameter is NodeList); |
| 102 // We don't have to rename privates in optionals. |
| 103 } |
| 104 } |
| 90 } else if (element.isTopLevel()) { | 105 } else if (element.isTopLevel()) { |
| 106 // Note: this code should only rename private identifiers for class' |
| 107 // fields/getters/setters/methods. Top-level identifiers are renamed |
| 108 // just to escape conflicts and that should be enough as we shouldn't |
| 109 // be able to resolve private identifiers for other libraries. |
| 91 makeElementPlaceholder(node.name, element); | 110 makeElementPlaceholder(node.name, element); |
| 111 } else { |
| 112 if (node.name !== null) { |
| 113 Identifier identifier = node.name.asIdentifier(); |
| 114 // operator <blah> names shouldn't be renamed. |
| 115 if (identifier !== null) tryMakePrivateIdentifier(identifier); |
| 116 } |
| 117 } |
| 118 } |
| 119 |
| 120 void collectFieldDeclarationPlaceholders(Element element, Node node) { |
| 121 if (element.isInstanceMember()) { |
| 122 for (Node definition in node.definitions) { |
| 123 if (definition is Identifier) { |
| 124 tryMakePrivateIdentifier(definition.asIdentifier()); |
| 125 } else if (definition is SendSet) { |
| 126 tryMakePrivateIdentifier( |
| 127 definition.asSendSet().selector.asIdentifier()); |
| 128 } else { |
| 129 assert(false); // Unreachable. |
| 130 } |
| 131 } |
| 92 } | 132 } |
| 93 } | 133 } |
| 94 | 134 |
| 95 void collect(Element element, TreeElements elements) { | 135 void collect(Element element, TreeElements elements) { |
| 96 // Skip AbstractFieldElement, it has no node. | 136 // Skip AbstractFieldElement, it has no node. |
| 97 // Instead getters and setters should be processed explicitly. | 137 // Instead getters and setters should be processed explicitly. |
| 98 if (element is AbstractFieldElement) return; | 138 if (element is AbstractFieldElement) return; |
| 99 if (element.isField()) { | 139 treeElements = elements; |
| 140 Node elementNode; |
| 141 if (element is FunctionElement) { |
| 100 currentElement = element; | 142 currentElement = element; |
| 143 elementNode = currentElement.parseNode(compiler); |
| 144 collectFunctionDeclarationPlaceholders(element, elementNode); |
| 145 } else if (element.isField()) { |
| 101 // TODO(smok): In the future make sure we don't process same | 146 // TODO(smok): In the future make sure we don't process same |
| 102 // variable list element twice, better merge this with emitter logic. | 147 // variable list element twice, better merge this with emitter logic. |
| 103 element = element.variables; | 148 currentElement = element.variables; |
| 104 } | 149 elementNode = currentElement.parseNode(compiler); |
| 105 currentElement = element; | 150 collectFieldDeclarationPlaceholders(element, elementNode); |
| 106 treeElements = elements; | 151 } else { |
| 107 Node elementNode = element.parseNode(compiler); | 152 assert(false); // Unreachable. |
| 108 if (element is FunctionElement) { | |
| 109 collectFunctionDeclarationPlaceholder(element, elementNode); | |
| 110 } | 153 } |
| 111 elementNode.accept(this); | 154 elementNode.accept(this); |
| 112 } | 155 } |
| 113 | 156 |
| 114 Type resolveType(TypeAnnotation typeAnnotation) { | 157 Type resolveType(TypeAnnotation typeAnnotation) { |
| 115 if (treeElements === null) return null; | 158 if (treeElements === null) return null; |
| 116 var result = treeElements.getType(typeAnnotation); | 159 var result = treeElements.getType(typeAnnotation); |
| 117 // TODO: Have better type resolution. | 160 // TODO: Have better type resolution. |
| 118 if (result === null) { | 161 if (result === null) { |
| 119 result = compiler.resolveTypeAnnotation(currentElement, typeAnnotation); | 162 result = compiler.resolveTypeAnnotation(currentElement, typeAnnotation); |
| 120 } | 163 } |
| 121 return result; | 164 return result; |
| 122 } | 165 } |
| 123 | 166 |
| 167 tryMakePrivateIdentifier(Identifier identifier) { |
| 168 if (identifier.source.isPrivate()) makePrivateIdentifier(identifier); |
| 169 } |
| 170 |
| 124 void makeTypePlaceholder(Node node, Type type) { | 171 void makeTypePlaceholder(Node node, Type type) { |
| 125 makeElementPlaceholder(node, type.element); | 172 makeElementPlaceholder(node, type.element); |
| 126 } | 173 } |
| 127 | 174 |
| 128 void makeNullPlaceholder(Node node) { | 175 void makeNullPlaceholder(Node node) { |
| 129 placeholders[node] = new NullPlaceholder(); | 176 placeholders[node] = new NullPlaceholder(); |
| 130 } | 177 } |
| 131 | 178 |
| 132 void makeElementPlaceholder(Node node, Element element) { | 179 void makeElementPlaceholder(Node node, Element element) { |
| 133 assert(element !== null); | 180 assert(element !== null); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 145 } | 192 } |
| 146 | 193 |
| 147 visit(Node node) => (node === null) ? null : node.accept(this); | 194 visit(Node node) => (node === null) ? null : node.accept(this); |
| 148 | 195 |
| 149 visitNode(Node node) { node.visitChildren(this); } // We must go deeper. | 196 visitNode(Node node) { node.visitChildren(this); } // We must go deeper. |
| 150 | 197 |
| 151 visitClassNode(ClassNode node) { | 198 visitClassNode(ClassNode node) { |
| 152 internalError('Should never meet ClassNode', node); | 199 internalError('Should never meet ClassNode', node); |
| 153 } | 200 } |
| 154 | 201 |
| 155 void visitIdentifier(Identifier node) { | |
| 156 if (node.source.isPrivate()) { | |
| 157 makePrivateIdentifier(node); | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 visitSend(Send send) { | 202 visitSend(Send send) { |
| 162 new SendVisitor(this, treeElements).visitSend(send); | 203 new SendVisitor(this, treeElements).visitSend(send); |
| 163 super.visitSend(send); | 204 send.visitChildren(this); |
| 205 } |
| 206 |
| 207 visitSendSet(SendSet send) { |
| 208 final element = treeElements[send]; |
| 209 if (element !== null && element.isInstanceMember()) { |
| 210 tryMakePrivateIdentifier(send.selector.asIdentifier()); |
| 211 } |
| 212 send.visitChildren(this); |
| 164 } | 213 } |
| 165 | 214 |
| 166 visitTypeAnnotation(TypeAnnotation node) { | 215 visitTypeAnnotation(TypeAnnotation node) { |
| 167 final type = compiler.resolveTypeAnnotation(currentElement, node); | 216 final type = compiler.resolveTypeAnnotation(currentElement, node); |
| 168 if (type is !InterfaceType) return null; | 217 if (type is !InterfaceType) return null; |
| 169 var target = node.typeName; | 218 var target = node.typeName; |
| 170 if (node.typeName is Send) { | 219 if (node.typeName is Send) { |
| 171 final element = treeElements[node]; | 220 final element = treeElements[node]; |
| 172 if (element !== null) { | 221 if (element !== null) { |
| 173 final send = node.typeName.asSend(); | 222 final send = node.typeName.asSend(); |
| 174 final hasPrefix = element.lookupConstructor( | 223 final hasPrefix = element.lookupConstructor( |
| 175 send.receiver.source, send.selector.source) === null; | 224 send.receiver.source, send.selector.source) === null; |
| 176 if (!hasPrefix) target = send.receiver; | 225 if (!hasPrefix) target = send.receiver; |
| 177 } | 226 } |
| 178 } | 227 } |
| 179 makeTypePlaceholder(target, type); | 228 makeTypePlaceholder(target, type); |
| 180 visit(node.typeArguments); | 229 node.visitChildren(this); |
| 181 } | 230 } |
| 182 } | 231 } |
| OLD | NEW |