| 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() => |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 final TypeAnnotation typeNode; | 26 final TypeAnnotation typeNode; |
| 27 final bool requiresVar; | 27 final bool requiresVar; |
| 28 DeclarationTypePlaceholder(this.typeNode, this.requiresVar); | 28 DeclarationTypePlaceholder(this.typeNode, this.requiresVar); |
| 29 } | 29 } |
| 30 | 30 |
| 31 class SendVisitor extends ResolvedVisitor { | 31 class SendVisitor extends ResolvedVisitor { |
| 32 final PlaceholderCollector collector; | 32 final PlaceholderCollector collector; |
| 33 | 33 |
| 34 SendVisitor(this.collector, TreeElements elements) : super(elements); | 34 SendVisitor(this.collector, TreeElements elements) : super(elements); |
| 35 | 35 |
| 36 visitDynamicSend(Send node) {} | |
| 37 visitSuperSend(Send node) {} | |
| 38 visitOperatorSend(Send node) {} | 36 visitOperatorSend(Send node) {} |
| 39 visitForeignSend(Send node) {} | 37 visitForeignSend(Send node) {} |
| 40 | 38 |
| 39 visitSuperSend(Send node) { |
| 40 collector.tryMakeMemberPlaceholder(node.selector); |
| 41 } |
| 42 |
| 43 visitDynamicSend(Send node) { |
| 44 final element = elements[node]; |
| 45 if (element === null || !element.isErroneous()) { |
| 46 collector.tryMakeMemberPlaceholder(node.selector); |
| 47 } |
| 48 } |
| 49 |
| 41 visitClosureSend(Send node) { | 50 visitClosureSend(Send node) { |
| 42 final element = elements[node]; | 51 final element = elements[node]; |
| 43 if (element !== null) { | 52 if (element !== null) { |
| 44 collector.tryMakeLocalPlaceholder(element, node.selector); | 53 collector.tryMakeLocalPlaceholder(element, node.selector); |
| 45 } | 54 } |
| 46 } | 55 } |
| 47 | 56 |
| 48 visitGetterSend(Send node) { | 57 visitGetterSend(Send node) { |
| 49 final element = elements[node]; | 58 final element = elements[node]; |
| 50 // element === null means dynamic property access. | 59 // element === null means dynamic property access. |
| 51 if (element === null) return; | 60 if (element === null) { |
| 52 if (element.isPrefix()) { | 61 collector.tryMakeMemberPlaceholder(node.selector); |
| 62 } else if (element.isPrefix()) { |
| 53 // Node is prefix part in case of source 'lib.somesetter = 5;' | 63 // Node is prefix part in case of source 'lib.somesetter = 5;' |
| 54 collector.makeNullPlaceholder(node); | 64 collector.makeNullPlaceholder(node); |
| 55 } else if (Elements.isStaticOrTopLevel(element)) { | 65 } else if (Elements.isStaticOrTopLevel(element)) { |
| 56 // Unqualified or prefixed top level or static. | 66 // Unqualified or prefixed top level or static. |
| 57 collector.makeElementPlaceholder(node.selector, element); | 67 collector.makeElementPlaceholder(node.selector, element); |
| 58 } else if (!element.isTopLevel()) { | 68 } else if (!element.isTopLevel()) { |
| 59 // May get FunctionExpression here in selector | 69 if (element.isInstanceMember()) { |
| 60 // in case of A(int this.f()); | 70 collector.tryMakeMemberPlaceholder(node.selector); |
| 61 if (node.selector is Identifier) { | |
| 62 collector.tryMakeLocalPlaceholder(element, node.selector); | |
| 63 } else { | 71 } else { |
| 64 assert(node.selector is FunctionExpression); | 72 // May get FunctionExpression here in selector |
| 73 // in case of A(int this.f()); |
| 74 if (node.selector is Identifier) { |
| 75 collector.tryMakeLocalPlaceholder(element, node.selector); |
| 76 } else { |
| 77 assert(node.selector is FunctionExpression); |
| 78 } |
| 65 } | 79 } |
| 66 } | 80 } |
| 67 } | 81 } |
| 68 | 82 |
| 69 visitStaticSend(Send node) { | 83 visitStaticSend(Send node) { |
| 70 final element = elements[node]; | 84 final element = elements[node]; |
| 71 if (element.isConstructor() || element.isFactoryConstructor()) return; | 85 if (element.isConstructor() || element.isFactoryConstructor()) { |
| 86 // Rename named constructor in redirection position: |
| 87 // class C { C.named(); C.redirecting() : this.named(); } |
| 88 if (node.receiver is Identifier |
| 89 && node.receiver.asIdentifier().isThis()) { |
| 90 assert(node.selector is Identifier); |
| 91 collector.tryMakeMemberPlaceholder(node.selector); |
| 92 } |
| 93 // Field names can be exposed as names of optional arguments, e.g. |
| 94 // class C { |
| 95 // final field; |
| 96 // C([this.field]); |
| 97 // } |
| 98 // Do not forget to rename them as well. |
| 99 FunctionElement functionElement = element; |
| 100 Link<Element> optionalParameters = |
| 101 functionElement.functionSignature.optionalParameters; |
| 102 for (final argument in node.argumentsNode) { |
| 103 NamedArgument named = argument.asNamedArgument(); |
| 104 if (named === null) continue; |
| 105 Identifier name = named.name; |
| 106 String nameAsString = name.source.slowToString(); |
| 107 for (final parameter in optionalParameters) { |
| 108 if (parameter.kind === ElementKind.FIELD_PARAMETER) { |
| 109 if (parameter.name.slowToString() == nameAsString) { |
| 110 collector.tryMakeMemberPlaceholder(name); |
| 111 break; |
| 112 } |
| 113 } |
| 114 } |
| 115 } |
| 116 return; |
| 117 } |
| 72 collector.makeElementPlaceholder(node.selector, element); | 118 collector.makeElementPlaceholder(node.selector, element); |
| 73 // Another ugly case: <lib prefix>.<top level> is represented as | 119 // Another ugly case: <lib prefix>.<top level> is represented as |
| 74 // receiver: lib prefix, selector: top level. | 120 // receiver: lib prefix, selector: top level. |
| 75 if (element.isTopLevel() && node.receiver !== null) { | 121 if (element.isTopLevel() && node.receiver !== null) { |
| 76 assert(elements[node.receiver].isPrefix()); | 122 assert(elements[node.receiver].isPrefix()); |
| 77 // Hack: putting null into map overrides receiver of original node. | 123 // Hack: putting null into map overrides receiver of original node. |
| 78 collector.makeNullPlaceholder(node.receiver); | 124 collector.makeNullPlaceholder(node.receiver); |
| 79 } | 125 } |
| 80 } | 126 } |
| 81 | 127 |
| 82 internalError(String reason, [Node node]) { | 128 internalError(String reason, [Node node]) { |
| 83 collector.internalError(reason, node); | 129 collector.internalError(reason, node); |
| 84 } | 130 } |
| 85 } | 131 } |
| 86 | 132 |
| 87 class PlaceholderCollector extends AbstractVisitor { | 133 class PlaceholderCollector extends AbstractVisitor { |
| 88 final Compiler compiler; | 134 final Compiler compiler; |
| 135 final Set<String> fixedMemberNames; // member names which cannot be renamed. |
| 89 final Set<Node> nullNodes; // Nodes that should not be in output. | 136 final Set<Node> nullNodes; // Nodes that should not be in output. |
| 90 final Set<Identifier> unresolvedNodes; | 137 final Set<Identifier> unresolvedNodes; |
| 91 final Map<Element, Set<Node>> elementNodes; | 138 final Map<Element, Set<Node>> elementNodes; |
| 92 final Map<FunctionElement, FunctionScope> functionScopes; | 139 final Map<FunctionElement, FunctionScope> functionScopes; |
| 93 final Map<LibraryElement, Set<Identifier>> privateNodes; | 140 final Map<LibraryElement, Set<Identifier>> privateNodes; |
| 94 final List<DeclarationTypePlaceholder> declarationTypePlaceholders; | 141 final List<DeclarationTypePlaceholder> declarationTypePlaceholders; |
| 142 final Map<String, Set<Identifier>> memberPlaceholders; |
| 95 Map<String, LocalPlaceholder> currentLocalPlaceholders; | 143 Map<String, LocalPlaceholder> currentLocalPlaceholders; |
| 96 Element currentElement; | 144 Element currentElement; |
| 97 TreeElements treeElements; | 145 TreeElements treeElements; |
| 98 | 146 |
| 99 LibraryElement get coreLibrary => compiler.coreLibrary; | 147 LibraryElement get coreLibrary => compiler.coreLibrary; |
| 100 FunctionElement get entryFunction => compiler.mainApp.find(Compiler.MAIN); | 148 FunctionElement get entryFunction => compiler.mainApp.find(Compiler.MAIN); |
| 101 | 149 |
| 102 PlaceholderCollector(this.compiler) : | 150 PlaceholderCollector(this.compiler, this.fixedMemberNames) : |
| 103 nullNodes = new Set<Node>(), | 151 nullNodes = new Set<Node>(), |
| 104 unresolvedNodes = new Set<Identifier>(), | 152 unresolvedNodes = new Set<Identifier>(), |
| 105 elementNodes = new Map<Element, Set<Node>>(), | 153 elementNodes = new Map<Element, Set<Node>>(), |
| 106 functionScopes = new Map<FunctionElement, FunctionScope>(), | 154 functionScopes = new Map<FunctionElement, FunctionScope>(), |
| 107 privateNodes = new Map<LibraryElement, Set<Identifier>>(), | 155 privateNodes = new Map<LibraryElement, Set<Identifier>>(), |
| 108 declarationTypePlaceholders = new List<DeclarationTypePlaceholder>(); | 156 declarationTypePlaceholders = new List<DeclarationTypePlaceholder>(), |
| 157 memberPlaceholders = new Map<String, Set<Identifier>>(); |
| 109 | 158 |
| 110 void tryMakeConstructorNamePlaceholder( | 159 void tryMakeConstructorNamePlaceholder( |
| 111 FunctionExpression constructor, ClassElement element) { | 160 FunctionExpression constructor, ClassElement element) { |
| 112 Node nameNode = constructor.name; | 161 Node nameNode = constructor.name; |
| 113 if (nameNode is Send) nameNode = nameNode.receiver; | 162 if (nameNode is Send) nameNode = nameNode.receiver; |
| 114 if (nameNode.asIdentifier().token.slowToString() | 163 if (nameNode.asIdentifier().token.slowToString() |
| 115 == element.name.slowToString()) { | 164 == element.name.slowToString()) { |
| 116 makeElementPlaceholder(nameNode, element); | 165 makeElementPlaceholder(nameNode, element); |
| 117 } | 166 } |
| 118 } | 167 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 FunctionElement implementingFactory = element.defaultImplementation; | 199 FunctionElement implementingFactory = element.defaultImplementation; |
| 151 tryMakeConstructorNamePlaceholder(implementingFactory.cachedNode, | 200 tryMakeConstructorNamePlaceholder(implementingFactory.cachedNode, |
| 152 element.getEnclosingClass()); | 201 element.getEnclosingClass()); |
| 153 } | 202 } |
| 154 } else if (Elements.isStaticOrTopLevel(element)) { | 203 } else if (Elements.isStaticOrTopLevel(element)) { |
| 155 // Note: this code should only rename private identifiers for class' | 204 // Note: this code should only rename private identifiers for class' |
| 156 // fields/getters/setters/methods. Top-level identifiers are renamed | 205 // fields/getters/setters/methods. Top-level identifiers are renamed |
| 157 // just to escape conflicts and that should be enough as we shouldn't | 206 // just to escape conflicts and that should be enough as we shouldn't |
| 158 // be able to resolve private identifiers for other libraries. | 207 // be able to resolve private identifiers for other libraries. |
| 159 makeElementPlaceholder(node.name, element); | 208 makeElementPlaceholder(node.name, element); |
| 209 } else if (element.isMember()) { |
| 210 if (node.name is Identifier) { |
| 211 tryMakeMemberPlaceholder(node.name); |
| 212 } else { |
| 213 assert(node.name.asSend().isOperator); |
| 214 } |
| 160 } | 215 } |
| 161 } | 216 } |
| 162 | 217 |
| 163 void collectFieldDeclarationPlaceholders( | 218 void collectFieldDeclarationPlaceholders( |
| 164 Element element, VariableDefinitions node) { | 219 Element element, VariableDefinitions node) { |
| 220 Node fieldNode = element.parseNode(compiler); |
| 221 Identifier name = |
| 222 fieldNode is Identifier ? fieldNode : fieldNode.asSend().selector; |
| 165 if (Elements.isStaticOrTopLevel(element)) { | 223 if (Elements.isStaticOrTopLevel(element)) { |
| 166 Node fieldNode = element.parseNode(compiler); | 224 makeElementPlaceholder(name, element); |
| 167 if (fieldNode is Identifier) { | 225 } else if (Elements.isInstanceField(element)) { |
| 168 makeElementPlaceholder(fieldNode, element); | 226 tryMakeMemberPlaceholder(name); |
| 169 } else if (fieldNode is SendSet) { | |
| 170 makeElementPlaceholder(fieldNode.selector, element); | |
| 171 } else { | |
| 172 unreachable(); | |
| 173 } | |
| 174 } | 227 } |
| 175 makeVarDeclarationTypePlaceholder(node); | 228 makeVarDeclarationTypePlaceholder(node); |
| 176 } | 229 } |
| 177 | 230 |
| 178 void collect(Element element, TreeElements elements) { | 231 void collect(Element element, TreeElements elements) { |
| 179 treeElements = elements; | 232 treeElements = elements; |
| 180 Node elementNode; | 233 Node elementNode; |
| 181 if (element is FunctionElement) { | 234 if (element is FunctionElement) { |
| 182 currentElement = element; | 235 currentElement = element; |
| 183 elementNode = currentElement.parseNode(compiler); | 236 elementNode = currentElement.parseNode(compiler); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 // should not matter if they are local vars. | 268 // should not matter if they are local vars. |
| 216 if (node.source.isPrivate()) return; | 269 if (node.source.isPrivate()) return; |
| 217 if (element.isParameter() && isOptionalParameter()) { | 270 if (element.isParameter() && isOptionalParameter()) { |
| 218 functionScopes.putIfAbsent(currentElement, () => new FunctionScope()) | 271 functionScopes.putIfAbsent(currentElement, () => new FunctionScope()) |
| 219 .registerParameter(node); | 272 .registerParameter(node); |
| 220 } else if (Elements.isLocal(element)) { | 273 } else if (Elements.isLocal(element)) { |
| 221 makeLocalPlaceholder(node); | 274 makeLocalPlaceholder(node); |
| 222 } | 275 } |
| 223 } | 276 } |
| 224 | 277 |
| 278 void tryMakeMemberPlaceholder(Identifier node) { |
| 279 assert(node !== null); |
| 280 if (node.source.isPrivate()) return; |
| 281 if (node is Operator) return; |
| 282 final identifier = node.source.slowToString(); |
| 283 if (fixedMemberNames.contains(identifier)) return; |
| 284 memberPlaceholders.putIfAbsent( |
| 285 identifier, () => new Set<Identifier>()).add(node); |
| 286 } |
| 287 |
| 225 void makeTypePlaceholder(Node node, Type type) { | 288 void makeTypePlaceholder(Node node, Type type) { |
| 226 makeElementPlaceholder(node, type.element); | 289 makeElementPlaceholder(node, type.element); |
| 227 } | 290 } |
| 228 | 291 |
| 229 void makeOmitDeclarationTypePlaceholder(TypeAnnotation type) { | 292 void makeOmitDeclarationTypePlaceholder(TypeAnnotation type) { |
| 230 if (type === null) return; | 293 if (type === null) return; |
| 231 declarationTypePlaceholders.add( | 294 declarationTypePlaceholders.add( |
| 232 new DeclarationTypePlaceholder(type, false)); | 295 new DeclarationTypePlaceholder(type, false)); |
| 233 } | 296 } |
| 234 | 297 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 305 } | 368 } |
| 306 | 369 |
| 307 visitSendSet(SendSet send) { | 370 visitSendSet(SendSet send) { |
| 308 final element = treeElements[send]; | 371 final element = treeElements[send]; |
| 309 if (element !== null) { | 372 if (element !== null) { |
| 310 if (Elements.isStaticOrTopLevel(element)) { | 373 if (Elements.isStaticOrTopLevel(element)) { |
| 311 assert(element is VariableElement || element.isSetter()); | 374 assert(element is VariableElement || element.isSetter()); |
| 312 makeElementPlaceholder(send.selector, element); | 375 makeElementPlaceholder(send.selector, element); |
| 313 } else { | 376 } else { |
| 314 assert(send.selector is Identifier); | 377 assert(send.selector is Identifier); |
| 315 tryMakeLocalPlaceholder(element, send.selector); | 378 if (Elements.isInstanceField(element)) { |
| 379 tryMakeMemberPlaceholder(send.selector); |
| 380 } else { |
| 381 tryMakeLocalPlaceholder(element, send.selector); |
| 382 } |
| 383 } |
| 384 } else { |
| 385 if (send.receiver !== null) { |
| 386 tryMakeMemberPlaceholder(send.selector); |
| 316 } | 387 } |
| 317 } | 388 } |
| 318 send.visitChildren(this); | 389 send.visitChildren(this); |
| 319 } | 390 } |
| 320 | 391 |
| 321 visitIdentifier(Identifier identifier) { | 392 visitIdentifier(Identifier identifier) { |
| 322 if (identifier.source.isPrivate()) makePrivateIdentifier(identifier); | 393 if (identifier.source.isPrivate()) makePrivateIdentifier(identifier); |
| 323 } | 394 } |
| 324 | 395 |
| 325 static bool isPlainTypeName(TypeAnnotation typeAnnotation) { | 396 static bool isPlainTypeName(TypeAnnotation typeAnnotation) { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 385 Element definitionElement = treeElements[definition]; | 456 Element definitionElement = treeElements[definition]; |
| 386 // definitionElement may be null if we're inside variable definitions | 457 // definitionElement may be null if we're inside variable definitions |
| 387 // of a function that is a parameter of another function. | 458 // of a function that is a parameter of another function. |
| 388 // TODO(smok): Fix this when resolver correctly deals with | 459 // TODO(smok): Fix this when resolver correctly deals with |
| 389 // such cases. | 460 // such cases. |
| 390 if (definitionElement === null) continue; | 461 if (definitionElement === null) continue; |
| 391 if (definition is Send) { | 462 if (definition is Send) { |
| 392 // May get FunctionExpression here in definition.selector | 463 // May get FunctionExpression here in definition.selector |
| 393 // in case of A(int this.f()); | 464 // in case of A(int this.f()); |
| 394 if (definition.selector is Identifier) { | 465 if (definition.selector is Identifier) { |
| 395 tryMakeLocalPlaceholder(definitionElement, definition.selector); | 466 if (definitionElement.kind === ElementKind.FIELD_PARAMETER) { |
| 467 tryMakeMemberPlaceholder(definition.selector); |
| 468 } else { |
| 469 tryMakeLocalPlaceholder(definitionElement, definition.selector); |
| 470 } |
| 396 } else { | 471 } else { |
| 397 assert(definition.selector is FunctionExpression); | 472 assert(definition.selector is FunctionExpression); |
| 473 if (definitionElement.kind === ElementKind.FIELD_PARAMETER) { |
| 474 tryMakeMemberPlaceholder( |
| 475 definition.selector.asFunctionExpression().name); |
| 476 } |
| 398 } | 477 } |
| 399 } else if (definition is Identifier) { | 478 } else if (definition is Identifier) { |
| 400 tryMakeLocalPlaceholder(definitionElement, definition); | 479 tryMakeLocalPlaceholder(definitionElement, definition); |
| 401 } else if (definition is FunctionExpression) { | 480 } else if (definition is FunctionExpression) { |
| 402 // Skip, it will be processed in visitFunctionExpression. | 481 // Skip, it will be processed in visitFunctionExpression. |
| 403 } else { | 482 } else { |
| 404 internalError('Unexpected definition structure $definition'); | 483 internalError('Unexpected definition structure $definition'); |
| 405 } | 484 } |
| 406 } | 485 } |
| 407 } | 486 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 491 | 570 |
| 492 visitBlock(Block node) { | 571 visitBlock(Block node) { |
| 493 for (Node statement in node.statements.nodes) { | 572 for (Node statement in node.statements.nodes) { |
| 494 if (statement is VariableDefinitions) { | 573 if (statement is VariableDefinitions) { |
| 495 makeVarDeclarationTypePlaceholder(statement); | 574 makeVarDeclarationTypePlaceholder(statement); |
| 496 } | 575 } |
| 497 } | 576 } |
| 498 node.visitChildren(this); | 577 node.visitChildren(this); |
| 499 } | 578 } |
| 500 } | 579 } |
| OLD | NEW |