| 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 LocalPlaceholder implements Hashable { | 5 class LocalPlaceholder implements Hashable { |
| 6 final String identifier; | 6 final String identifier; |
| 7 final Set<Node> nodes; | 7 final Set<Node> nodes; |
| 8 LocalPlaceholder(this.identifier) : nodes = new Set<Node>(); | 8 LocalPlaceholder(this.identifier) : nodes = new Set<Node>(); |
| 9 int hashCode() => identifier.hashCode(); | 9 int hashCode() => identifier.hashCode(); |
| 10 String toString() => | 10 String toString() => |
| 11 'local_placeholder[id($identifier), nodes($nodes)]'; | 11 'local_placeholder[id($identifier), nodes($nodes)]'; |
| 12 } | 12 } |
| 13 | 13 |
| 14 class SendVisitor extends ResolvedVisitor { | 14 class SendVisitor extends ResolvedVisitor { |
| 15 final PlaceholderCollector collector; | 15 final PlaceholderCollector collector; |
| 16 | 16 |
| 17 SendVisitor(this.collector, TreeElements elements) : super(elements); | 17 SendVisitor(this.collector, TreeElements elements) : super(elements); |
| 18 | 18 |
| 19 visitDynamicSend(Send node) {} |
| 19 visitSuperSend(Send node) {} | 20 visitSuperSend(Send node) {} |
| 20 visitOperatorSend(Send node) {} | 21 visitOperatorSend(Send node) {} |
| 21 visitForeignSend(Send node) {} | 22 visitForeignSend(Send node) {} |
| 22 | 23 |
| 23 visitClosureSend(Send node) { | 24 visitClosureSend(Send node) { |
| 24 final element = elements[node]; | 25 final element = elements[node]; |
| 25 if (element !== null) { | 26 if (element !== null) { |
| 26 collector.tryMakeLocalPlaceholder(element, node.selector); | 27 collector.tryMakeLocalPlaceholder(element, node.selector); |
| 27 } | 28 } |
| 28 } | 29 } |
| 29 | 30 |
| 30 visitDynamicSend(Send node) { | |
| 31 tryRenamePrivateSelector(node); | |
| 32 } | |
| 33 | |
| 34 visitGetterSend(Send node) { | 31 visitGetterSend(Send node) { |
| 35 final element = elements[node]; | 32 final element = elements[node]; |
| 36 // element === null means dynamic property access. | 33 // element === null means dynamic property access. |
| 37 if (element === null || element.isMember()) { | 34 if (element === null) return; |
| 38 tryRenamePrivateSelector(node); | |
| 39 return; | |
| 40 } | |
| 41 // We don't want to rename non top-level element access | 35 // We don't want to rename non top-level element access |
| 42 // unless it's a local variable. | 36 // unless it's a local variable. |
| 43 if (element.isPrefix()) { | 37 if (element.isPrefix()) { |
| 44 // Node is prefix part in case of source 'lib.somesetter = 5;' | 38 // Node is prefix part in case of source 'lib.somesetter = 5;' |
| 45 collector.makeNullPlaceholder(node); | 39 collector.makeNullPlaceholder(node); |
| 46 return; | 40 return; |
| 47 } else if (!element.isTopLevel()) { | 41 } else if (!element.isTopLevel()) { |
| 48 // May get FunctionExpression here in selector | 42 // May get FunctionExpression here in selector |
| 49 // in case of A(int this.f()); | 43 // in case of A(int this.f()); |
| 50 if (node.selector is Identifier) { | 44 if (node.selector is Identifier) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 74 if (node.receiver !== null) { | 68 if (node.receiver !== null) { |
| 75 assert(elements[node.receiver].isPrefix()); | 69 assert(elements[node.receiver].isPrefix()); |
| 76 // Hack: putting null into map overrides receiver of original node. | 70 // Hack: putting null into map overrides receiver of original node. |
| 77 collector.makeNullPlaceholder(node.receiver); | 71 collector.makeNullPlaceholder(node.receiver); |
| 78 } | 72 } |
| 79 } | 73 } |
| 80 | 74 |
| 81 internalError(String reason, [Node node]) { | 75 internalError(String reason, [Node node]) { |
| 82 collector.internalError(reason, node); | 76 collector.internalError(reason, node); |
| 83 } | 77 } |
| 84 | |
| 85 tryRenamePrivateSelector(Send node) { | |
| 86 collector.tryMakePrivateIdentifier(node.selector.asIdentifier()); | |
| 87 } | |
| 88 } | 78 } |
| 89 | 79 |
| 90 class PlaceholderCollector extends AbstractVisitor { | 80 class PlaceholderCollector extends AbstractVisitor { |
| 91 final Compiler compiler; | 81 final Compiler compiler; |
| 92 final Set<Node> nullNodes; // Nodes that should not be in output. | 82 final Set<Node> nullNodes; // Nodes that should not be in output. |
| 93 final Set<Identifier> unresolvedNodes; | 83 final Set<Identifier> unresolvedNodes; |
| 94 final Map<Element, Set<Node>> elementNodes; | 84 final Map<Element, Set<Node>> elementNodes; |
| 95 final Map<FunctionElement, Set<LocalPlaceholder>> localPlaceholders; | 85 final Map<FunctionElement, Set<LocalPlaceholder>> localPlaceholders; |
| 96 final Map<LibraryElement, Set<Identifier>> privateNodes; | 86 final Map<LibraryElement, Set<Identifier>> privateNodes; |
| 97 Map<String, LocalPlaceholder> currentLocalPlaceholders; | 87 Map<String, LocalPlaceholder> currentLocalPlaceholders; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 // Example: | 135 // Example: |
| 146 // interface I { I(); } | 136 // interface I { I(); } |
| 147 // class C implements I { C(); } don't rename this case. | 137 // class C implements I { C(); } don't rename this case. |
| 148 // OR I.named() inside C, rename first part. | 138 // OR I.named() inside C, rename first part. |
| 149 if (element.defaultImplementation !== null | 139 if (element.defaultImplementation !== null |
| 150 && element.defaultImplementation !== element) { | 140 && element.defaultImplementation !== element) { |
| 151 FunctionElement implementingFactory = element.defaultImplementation; | 141 FunctionElement implementingFactory = element.defaultImplementation; |
| 152 tryMakeConstructorNamePlaceholder(implementingFactory.cachedNode, | 142 tryMakeConstructorNamePlaceholder(implementingFactory.cachedNode, |
| 153 element.getEnclosingClass()); | 143 element.getEnclosingClass()); |
| 154 } | 144 } |
| 155 | |
| 156 // Process Ctor(this._field) correctly. | |
| 157 for (Node parameter in node.parameters) { | |
| 158 VariableDefinitions definitions = parameter.asVariableDefinitions(); | |
| 159 if (definitions !== null) { | |
| 160 for (Node definition in definitions.definitions) { | |
| 161 Send send = definition.asSend(); | |
| 162 if (send !== null) { | |
| 163 assert(send.receiver is Identifier); | |
| 164 assert(send.receiver.asIdentifier().isThis()); | |
| 165 if (send.selector is Identifier) { | |
| 166 tryMakePrivateIdentifier(send.selector.asIdentifier()); | |
| 167 } else if (send.selector is FunctionExpression) { | |
| 168 // C(int this.f()) case where f is field of function type. | |
| 169 tryMakePrivateIdentifier( | |
| 170 send.selector.asFunctionExpression().name.asIdentifier()); | |
| 171 } else { | |
| 172 unreachable(); | |
| 173 } | |
| 174 } else { | |
| 175 assert(definition is Identifier | |
| 176 || definition is FunctionExpression); | |
| 177 } | |
| 178 } | |
| 179 } else { | |
| 180 assert(parameter is NodeList); | |
| 181 // We don't have to rename privates in optionals. | |
| 182 } | |
| 183 } | |
| 184 } else if (element.isTopLevel()) { | 145 } else if (element.isTopLevel()) { |
| 185 // Note: this code should only rename private identifiers for class' | 146 // Note: this code should only rename private identifiers for class' |
| 186 // fields/getters/setters/methods. Top-level identifiers are renamed | 147 // fields/getters/setters/methods. Top-level identifiers are renamed |
| 187 // just to escape conflicts and that should be enough as we shouldn't | 148 // just to escape conflicts and that should be enough as we shouldn't |
| 188 // be able to resolve private identifiers for other libraries. | 149 // be able to resolve private identifiers for other libraries. |
| 189 makeElementPlaceholder(node.name, element); | 150 makeElementPlaceholder(node.name, element); |
| 190 } else { | |
| 191 if (node.name !== null) { | |
| 192 Identifier identifier = node.name.asIdentifier(); | |
| 193 // operator <blah> names shouldn't be renamed. | |
| 194 if (identifier !== null) tryMakePrivateIdentifier(identifier); | |
| 195 } | |
| 196 } | 151 } |
| 197 } | 152 } |
| 198 | 153 |
| 199 void collectFieldDeclarationPlaceholders( | 154 void collectFieldDeclarationPlaceholders( |
| 200 Element element, VariableDefinitions node) { | 155 Element element, VariableDefinitions node) { |
| 201 if (element.isInstanceMember()) { | 156 if (element.isTopLevel()) { |
| 202 for (Node definition in node.definitions) { | |
| 203 if (definition is Identifier) { | |
| 204 tryMakePrivateIdentifier(definition.asIdentifier()); | |
| 205 } else if (definition is SendSet) { | |
| 206 tryMakePrivateIdentifier( | |
| 207 definition.asSendSet().selector.asIdentifier()); | |
| 208 } else { | |
| 209 unreachable(); | |
| 210 } | |
| 211 } | |
| 212 } else if (element.isTopLevel()) { | |
| 213 Node fieldNode = element.parseNode(compiler); | 157 Node fieldNode = element.parseNode(compiler); |
| 214 if (fieldNode is Identifier) { | 158 if (fieldNode is Identifier) { |
| 215 makeElementPlaceholder(fieldNode, element); | 159 makeElementPlaceholder(fieldNode, element); |
| 216 } else if (fieldNode is SendSet) { | 160 } else if (fieldNode is SendSet) { |
| 217 makeElementPlaceholder(fieldNode.selector, element); | 161 makeElementPlaceholder(fieldNode.selector, element); |
| 218 } else { | 162 } else { |
| 219 unreachable(); | 163 unreachable(); |
| 220 } | 164 } |
| 221 } | 165 } |
| 222 } | 166 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 241 elementNode = currentElement.parseNode(compiler); | 185 elementNode = currentElement.parseNode(compiler); |
| 242 } else { | 186 } else { |
| 243 unreachable(); | 187 unreachable(); |
| 244 } | 188 } |
| 245 currentLocalPlaceholders = new Map<String, LocalPlaceholder>(); | 189 currentLocalPlaceholders = new Map<String, LocalPlaceholder>(); |
| 246 compiler.withCurrentElement(element, () { | 190 compiler.withCurrentElement(element, () { |
| 247 elementNode.accept(this); | 191 elementNode.accept(this); |
| 248 }); | 192 }); |
| 249 } | 193 } |
| 250 | 194 |
| 251 void tryMakePrivateIdentifier(Identifier identifier) { | |
| 252 if (identifier.source.isPrivate()) makePrivateIdentifier(identifier); | |
| 253 } | |
| 254 | |
| 255 void tryMakeLocalPlaceholder(Element element, Identifier node) { | 195 void tryMakeLocalPlaceholder(Element element, Identifier node) { |
| 256 // TODO(smok): Maybe we should rename privates as well, their privacy | 196 // TODO(smok): Maybe we should rename privates as well, their privacy |
| 257 // should not matter if they are local vars. | 197 // should not matter if they are local vars. |
| 258 if (node.source.isPrivate()) return; | 198 if (node.source.isPrivate()) return; |
| 259 if (element.isVariable() | 199 if (element.isVariable() |
| 260 || (element.isFunction() && !Elements.isStaticOrTopLevel(element))) { | 200 || (element.isFunction() && !Elements.isStaticOrTopLevel(element))) { |
| 261 makeLocalPlaceholder(node); | 201 makeLocalPlaceholder(node); |
| 262 } | 202 } |
| 263 } | 203 } |
| 264 | 204 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 compiler.cancel(reason: reason, node: node); | 247 compiler.cancel(reason: reason, node: node); |
| 308 } | 248 } |
| 309 | 249 |
| 310 void unreachable() { internalError('Unreachable case'); } | 250 void unreachable() { internalError('Unreachable case'); } |
| 311 | 251 |
| 312 visit(Node node) => (node === null) ? null : node.accept(this); | 252 visit(Node node) => (node === null) ? null : node.accept(this); |
| 313 | 253 |
| 314 visitNode(Node node) { node.visitChildren(this); } // We must go deeper. | 254 visitNode(Node node) { node.visitChildren(this); } // We must go deeper. |
| 315 | 255 |
| 316 visitSend(Send send) { | 256 visitSend(Send send) { |
| 317 Element element = treeElements[send]; | |
| 318 if (element !== null && element.isErroneous()) { | |
| 319 // TODO(antonm): this is an unresolved constructor, not a dynamic send. | |
| 320 ErroneousElement erroneousElement = element; | |
| 321 compiler.cancel(reason: erroneousElement.errorMessage.toString(), | |
| 322 node: send); | |
| 323 } | |
| 324 new SendVisitor(this, treeElements).visitSend(send); | 257 new SendVisitor(this, treeElements).visitSend(send); |
| 325 send.visitChildren(this); | 258 send.visitChildren(this); |
| 326 } | 259 } |
| 327 | 260 |
| 328 visitSendSet(SendSet send) { | 261 visitSendSet(SendSet send) { |
| 329 if (send.selector is Identifier) { | |
| 330 tryMakePrivateIdentifier(send.selector.asIdentifier()); | |
| 331 } | |
| 332 final element = treeElements[send]; | 262 final element = treeElements[send]; |
| 333 if (element !== null) { | 263 if (element !== null) { |
| 334 if (element.isTopLevel()) { | 264 if (element.isTopLevel()) { |
| 335 assert(element is VariableElement || element.isSetter()); | 265 assert(element is VariableElement || element.isSetter()); |
| 336 makeElementPlaceholder(send.selector, element); | 266 makeElementPlaceholder(send.selector, element); |
| 337 } else { | 267 } else { |
| 338 assert(send.selector is Identifier); | 268 assert(send.selector is Identifier); |
| 339 tryMakeLocalPlaceholder(element, send.selector); | 269 tryMakeLocalPlaceholder(element, send.selector); |
| 340 } | 270 } |
| 341 } | 271 } |
| 342 send.visitChildren(this); | 272 send.visitChildren(this); |
| 343 } | 273 } |
| 344 | 274 |
| 275 visitIdentifier(Identifier identifier) { |
| 276 if (identifier.source.isPrivate()) makePrivateIdentifier(identifier); |
| 277 } |
| 278 |
| 345 static bool isPlainTypeName(TypeAnnotation typeAnnotation) { | 279 static bool isPlainTypeName(TypeAnnotation typeAnnotation) { |
| 346 if (typeAnnotation.typeName is !Identifier) return false; | 280 if (typeAnnotation.typeName is !Identifier) return false; |
| 347 if (typeAnnotation.typeArguments === null) return true; | 281 if (typeAnnotation.typeArguments === null) return true; |
| 348 if (typeAnnotation.typeArguments.length === 0) return true; | 282 if (typeAnnotation.typeArguments.length === 0) return true; |
| 349 return false; | 283 return false; |
| 350 } | 284 } |
| 351 | 285 |
| 352 static bool isDynamicType(TypeAnnotation typeAnnotation) { | 286 static bool isDynamicType(TypeAnnotation typeAnnotation) { |
| 353 if (!isPlainTypeName(typeAnnotation)) return false; | 287 if (!isPlainTypeName(typeAnnotation)) return false; |
| 354 String name = typeAnnotation.typeName.asIdentifier().source.slowToString(); | 288 String name = typeAnnotation.typeName.asIdentifier().source.slowToString(); |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 visit(node.defaultClause.typeArguments); | 400 visit(node.defaultClause.typeArguments); |
| 467 } | 401 } |
| 468 } | 402 } |
| 469 | 403 |
| 470 visitTypedef(Typedef node) { | 404 visitTypedef(Typedef node) { |
| 471 assert(currentElement is TypedefElement); | 405 assert(currentElement is TypedefElement); |
| 472 makeElementPlaceholder(node.name, currentElement); | 406 makeElementPlaceholder(node.name, currentElement); |
| 473 node.visitChildren(this); | 407 node.visitChildren(this); |
| 474 } | 408 } |
| 475 } | 409 } |
| OLD | NEW |