| 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 /** | 5 /** |
| 6 * Renames only top-level elements that would let to ambiguity if not renamed. | 6 * Renames only top-level elements that would let to ambiguity if not renamed. |
| 7 * TODO(smok): Make sure that top-level fields and methods correctly renamed. | 7 * TODO(smok): Make sure that top-level fields are correctly renamed. |
| 8 */ | 8 */ |
| 9 class ConflictingRenamer extends Renamer { | 9 class ConflictingRenamer extends Renamer { |
| 10 final Compiler compiler; | 10 final Compiler compiler; |
| 11 final Map<Element, String> renamed; | 11 final Map<Element, String> renamed; |
| 12 final Set<String> usedTopLevelIdentifiers; | 12 final Set<String> usedTopLevelIdentifiers; |
| 13 TreeElements contextElements; | 13 TreeElements contextElements; |
| 14 Element context; | 14 Element context; |
| 15 | 15 |
| 16 Map<Element, TreeElements> get resolvedElements() => | 16 Map<Element, TreeElements> get resolvedElements() => |
| 17 compiler.enqueuer.resolution.resolvedElements; | 17 compiler.enqueuer.resolution.resolvedElements; |
| 18 | 18 |
| 19 ConflictingRenamer(this.compiler) : | 19 ConflictingRenamer(this.compiler) : |
| 20 renamed = new Map<Element, String>(), | 20 renamed = new Map<Element, String>(), |
| 21 usedTopLevelIdentifiers = new Set<String>(); | 21 usedTopLevelIdentifiers = new Set<String>(); |
| 22 | 22 |
| 23 void setContext(Element element) { | 23 void setContext(Element element) { |
| 24 this.context = element; | 24 this.context = element; |
| 25 contextElements = resolvedElements[element]; | 25 contextElements = resolvedElements[element]; |
| 26 } | 26 } |
| 27 | 27 |
| 28 String getFactoryName(FunctionExpression node) => |
| 29 node.name.asSend().selector.asIdentifier().source.slowToString(); |
| 30 |
| 31 bool isNamedConstructor(Element element) => |
| 32 element.isGenerativeConstructor() |
| 33 && element.asFunctionElement().cachedNode.name is Send; |
| 34 |
| 28 String renameSendMethod(Send send) { | 35 String renameSendMethod(Send send) { |
| 29 // Rename only if this Send is a function call. | 36 if (contextElements[send] === null) return null; |
| 30 if (contextElements[send] !== null && contextElements[send].isFunction()) { | 37 Element element = contextElements[send]; |
| 31 return renameElement(contextElements[send]); | 38 if (element.isTopLevel()) { |
| 39 return renameElement(element); |
| 40 } else if (isNamedConstructor(element) |
| 41 // Don't want to rename redirects to :this(args). |
| 42 && !Initializers.isConstructorRedirect(send) |
| 43 // Don't want to rename super calls. |
| 44 && !Initializers.isSuperConstructorCall(send)) { |
| 45 FunctionExpression constructor = element.asFunctionElement().cachedNode; |
| 46 return '${renameType(element.getEnclosingClass().type)}' |
| 47 '.${getFactoryName(constructor)}'; |
| 32 } else { | 48 } else { |
| 33 return null; | 49 return null; |
| 34 } | 50 } |
| 35 } | 51 } |
| 36 | 52 |
| 37 String renameTypeName(TypeAnnotation typeAnnotation) { | 53 String renameTypeName(TypeAnnotation typeAnnotation) { |
| 38 if (contextElements === null | 54 Type type; |
| 39 || contextElements.getType(typeAnnotation) === null) { | 55 if (context.isClass()) { |
| 40 // We have no info about this type from resolver. | 56 // This only happens if we're unparsing class declaration. |
| 41 // This happens for class member fields. | 57 type = new TypeResolver(compiler) |
| 42 // TODO(smok): Maybe resolver should have this information, fix if so. | 58 .resolveTypeAnnotation(typeAnnotation, null, context); |
| 43 if (context.isField() | 59 } else { |
| 44 && context.variables.computeType(compiler) !== null) { | 60 type = compiler.resolveTypeAnnotation(context, typeAnnotation); |
| 45 // A field. | |
| 46 return renameType(context.variables.type); | |
| 47 } else { | |
| 48 return typeAnnotation.typeName.unparse(); | |
| 49 } | |
| 50 } | |
| 51 | |
| 52 // TODO(smok): Check if resolver can help us identifying factory | |
| 53 // constructors. | |
| 54 Type type = contextElements.getType(typeAnnotation); | |
| 55 if (typeAnnotation.typeName is Send | |
| 56 && typeAnnotation.typeName.receiver.source.slowToString() | |
| 57 == type.name.slowToString()) { | |
| 58 // Got factory invocation. Need to rename first part. | |
| 59 return "${renameType(type)}." | |
| 60 "${typeAnnotation.typeName.selector.source.slowToString()}"; | |
| 61 } | 61 } |
| 62 return renameType(type); | 62 return renameType(type); |
| 63 } | 63 } |
| 64 | 64 |
| 65 String renameType(Type type) => renameElement(type.element); | 65 String renameType(Type type) => renameElement(type.element); |
| 66 | 66 |
| 67 String renameIdentifier(Identifier node) { | 67 String renameIdentifier(Identifier node) { |
| 68 if (context.isGenerativeConstructor()) { | 68 if (context.isGenerativeConstructor()) { |
| 69 // This is either a factory constructor or simple one. | 69 // This is either a named constructor or simple one. |
| 70 // TODO(smok): Check if resolver can help us identifying factory | 70 // TODO(smok): Check if resolver can help us identifying named |
| 71 // constructors. | 71 // constructors. |
| 72 var enclosingClass = context.getEnclosingClass(); | 72 var enclosingClass = context.getEnclosingClass(); |
| 73 if (node.token.slowToString() == context.name.slowToString() | 73 if (node.token.slowToString() == context.name.slowToString() |
| 74 || enclosingClass.name.slowToString() == node.token.slowToString()) { | 74 || enclosingClass.name.slowToString() == node.token.slowToString()) { |
| 75 return renameElement(enclosingClass); | 75 return renameElement(enclosingClass); |
| 76 } | 76 } |
| 77 } | 77 } |
| 78 if (context.isFunction() && context.cachedNode.name == node) { | 78 if (context.isFunction() && context.cachedNode.name == node) { |
| 79 return renameElement(context); | 79 return renameElement(context); |
| 80 } | 80 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 95 // local identifiers. | 95 // local identifiers. |
| 96 String name = originalName; | 96 String name = originalName; |
| 97 while (usedTopLevelIdentifiers.contains(name)) { | 97 while (usedTopLevelIdentifiers.contains(name)) { |
| 98 name = "_$name"; | 98 name = "_$name"; |
| 99 } | 99 } |
| 100 usedTopLevelIdentifiers.add(name); | 100 usedTopLevelIdentifiers.add(name); |
| 101 renamed[element] = name; | 101 renamed[element] = name; |
| 102 return name; | 102 return name; |
| 103 } | 103 } |
| 104 } | 104 } |
| OLD | NEW |