| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
| 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. | |
| 4 | |
| 5 part of mirror_renamer; | |
| 6 | |
| 7 class MirrorRenamerImpl implements MirrorRenamer { | |
| 8 static const String MIRROR_HELPER_GET_NAME_FUNCTION = 'helperGetName'; | |
| 9 static final Uri DART_MIRROR_HELPER = | |
| 10 new Uri(scheme: 'dart', path: '_mirror_helper'); | |
| 11 static const String MIRROR_HELPER_SYMBOLS_MAP_NAME = '_SYMBOLS'; | |
| 12 | |
| 13 /// Initialized when dart:mirrors is loaded if the useMirrorHelperLibrary | |
| 14 /// field is set. | |
| 15 final LibraryElement helperLibrary; | |
| 16 | |
| 17 /// Initialized when dart:mirrors is loaded if the useMirrorHelperLibrary | |
| 18 /// field is set. | |
| 19 final FunctionElement getNameFunction; | |
| 20 | |
| 21 /// Initialized when dart:mirrors is loaded if the useMirrorHelperLibrary | |
| 22 /// field is set. | |
| 23 final FieldElement symbolsMapVariable; | |
| 24 | |
| 25 /// Maps mangled name to original name. | |
| 26 Map<String, String> symbols = new Map<String, String>(); | |
| 27 | |
| 28 /// Contains all occurrencs of MirrorSystem.getName() calls in the user code. | |
| 29 List<Node> mirrorSystemGetNameNodes = <Node>[]; | |
| 30 | |
| 31 /** | |
| 32 * Initialized when the placeholderCollector collects the FunctionElement | |
| 33 * backend.mirrorHelperGetNameFunction which represents the helperGetName | |
| 34 * function in _mirror_helper. | |
| 35 */ | |
| 36 FunctionExpression get getNameFunctionNode => getNameFunction.node; | |
| 37 VariableDefinitions get symbolsMapNode => symbolsMapVariable.node; | |
| 38 Compiler compiler; | |
| 39 DartBackend backend; | |
| 40 | |
| 41 MirrorRenamerImpl(this.compiler, this.backend, LibraryElement library) | |
| 42 : this.helperLibrary = library, | |
| 43 getNameFunction = library.find( | |
| 44 MirrorRenamerImpl.MIRROR_HELPER_GET_NAME_FUNCTION), | |
| 45 symbolsMapVariable = library.find( | |
| 46 MirrorRenamerImpl.MIRROR_HELPER_SYMBOLS_MAP_NAME); | |
| 47 | |
| 48 bool isMirrorHelperLibrary(LibraryElement element) { | |
| 49 return element == helperLibrary; | |
| 50 } | |
| 51 | |
| 52 void registerStaticSend(Element currentElement, Element target, Send node) { | |
| 53 if (target == compiler.mirrorSystemGetNameFunction && | |
| 54 currentElement.library != helperLibrary) { | |
| 55 // Access to `MirrorSystem.getName` that needs to be redirected to the | |
| 56 // [getNameFunction]. | |
| 57 mirrorSystemGetNameNodes.add(node); | |
| 58 } | |
| 59 } | |
| 60 | |
| 61 /** | |
| 62 * Adds a toplevel node to the output containing a map from the mangled | |
| 63 * to the unmangled names and replaces calls to MirrorSystem.getName() | |
| 64 * with calls to the corresponding wrapper from _mirror_helper which has | |
| 65 * been added during resolution. [renames] is assumed to map nodes in user | |
| 66 * code to mangled names appearing in output code, and [topLevelNodes] should | |
| 67 * contain all the toplevel ast nodes that will be emitted in the output. | |
| 68 */ | |
| 69 void addRenames(Map<Node, String> renames, List<Node> topLevelNodes, | |
| 70 PlaceholderCollector placeholderCollector) { | |
| 71 // Right now we only support instances of MirrorSystem.getName, | |
| 72 // hence if there are no occurence of these we don't do anything. | |
| 73 if (mirrorSystemGetNameNodes.isEmpty) { | |
| 74 return; | |
| 75 } | |
| 76 | |
| 77 Node parse(String text) { | |
| 78 Token tokens = compiler.scanner.tokenize(text); | |
| 79 return compiler.parser.parseCompilationUnit(tokens); | |
| 80 } | |
| 81 | |
| 82 // Add toplevel map containing all renames of members. | |
| 83 symbols = new Map<String, String>(); | |
| 84 for (Set<Identifier> s in placeholderCollector.memberPlaceholders.values) { | |
| 85 // All members in a set have the same name so we only need to look at one. | |
| 86 Identifier sampleNode = s.first; | |
| 87 symbols.putIfAbsent(renames[sampleNode], () => sampleNode.source); | |
| 88 } | |
| 89 | |
| 90 Identifier symbolsMapIdentifier = | |
| 91 symbolsMapNode.definitions.nodes.head.asSend().selector; | |
| 92 assert(symbolsMapIdentifier != null); | |
| 93 topLevelNodes.remove(symbolsMapNode); | |
| 94 | |
| 95 StringBuffer sb = new StringBuffer( | |
| 96 'const ${renames[symbolsMapIdentifier]} = const<String,String>{'); | |
| 97 bool first = true; | |
| 98 for (String mangledName in symbols.keys) { | |
| 99 if (!first) { | |
| 100 sb.write(','); | |
| 101 } else { | |
| 102 first = false; | |
| 103 } | |
| 104 sb.write("'$mangledName' : '"); | |
| 105 sb.write(symbols[mangledName]); | |
| 106 sb.write("'"); | |
| 107 } | |
| 108 sb.write('};'); | |
| 109 sb.writeCharCode(0); // Terminate the string with '0', see [StringScanner]. | |
| 110 topLevelNodes.add(parse(sb.toString())); | |
| 111 | |
| 112 // Replace calls to Mirrorsystem.getName with calls to helper function. | |
| 113 mirrorSystemGetNameNodes.forEach((node) { | |
| 114 renames[node.selector] = renames[getNameFunctionNode.name]; | |
| 115 renames[node.receiver] = ''; | |
| 116 }); | |
| 117 } | |
| 118 } | |
| OLD | NEW |