| OLD | NEW |
| (Empty) |
| 1 library di.transformers.refactor; | |
| 2 | |
| 3 import 'package:analyzer/src/generated/ast.dart'; | |
| 4 import 'package:analyzer/src/generated/element.dart'; | |
| 5 import 'package:barback/barback.dart'; | |
| 6 import 'package:code_transformers/resolver.dart'; | |
| 7 import 'package:source_maps/refactor.dart'; | |
| 8 | |
| 9 | |
| 10 /// Transforms all simple identifiers of [identifier] to be | |
| 11 /// [importPrefix].[replacement] in the entry point of the application. | |
| 12 /// | |
| 13 /// When the identifier is replaced, this function also adds a prefixed import | |
| 14 /// of the form `import "[importUrl]" as [importPrefix]`. | |
| 15 /// | |
| 16 /// This will resolve the full name of [identifier] and warn if it cannot be | |
| 17 /// resolved. This will only modify the main entry point of the application and | |
| 18 /// will not traverse into parts. | |
| 19 void transformIdentifiers(Transform transform, Resolver resolver, | |
| 20 {String identifier, String replacement, String importUrl, | |
| 21 String importPrefix}) { | |
| 22 | |
| 23 var identifierElement = resolver.getLibraryVariable(identifier); | |
| 24 if (identifierElement != null) { | |
| 25 identifierElement = identifierElement.getter; | |
| 26 } else { | |
| 27 identifierElement = resolver.getLibraryFunction(identifier); | |
| 28 } | |
| 29 | |
| 30 if (identifierElement == null) { | |
| 31 // TODO(blois) enable once on barback 0.12.0 | |
| 32 // transform.logger.fine('Unable to resolve $identifier, not ' | |
| 33 // 'transforming entry point.'); | |
| 34 transform.addOutput(transform.primaryInput); | |
| 35 return; | |
| 36 } | |
| 37 | |
| 38 var lib = resolver.getLibrary(transform.primaryInput.id); | |
| 39 var transaction = resolver.createTextEditTransaction(lib); | |
| 40 var unit = lib.definingCompilationUnit.node; | |
| 41 | |
| 42 unit.accept(new _IdentifierTransformer(transaction, identifierElement, | |
| 43 '$importPrefix.$replacement', transform.logger)); | |
| 44 | |
| 45 if (transaction.hasEdits) { | |
| 46 _addImport(transaction, unit, importUrl, importPrefix); | |
| 47 } | |
| 48 _commitTransaction(transaction, transform); | |
| 49 } | |
| 50 | |
| 51 /// Commits the transaction if there have been edits, otherwise just adds | |
| 52 /// the input as an output. | |
| 53 void _commitTransaction(TextEditTransaction transaction, Transform transform) { | |
| 54 var id = transform.primaryInput.id; | |
| 55 | |
| 56 if (transaction.hasEdits) { | |
| 57 var printer = transaction.commit(); | |
| 58 var url = id.path.startsWith('lib/') | |
| 59 ? 'package:${id.package}/${id.path.substring(4)}' : id.path; | |
| 60 printer.build(url); | |
| 61 transform.addOutput(new Asset.fromString(id, printer.text)); | |
| 62 } else { | |
| 63 // No modifications, so just pass the source through. | |
| 64 transform.addOutput(transform.primaryInput); | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 /// Injects an import into the list of imports in the file. | |
| 69 void _addImport(TextEditTransaction transaction, CompilationUnit unit, | |
| 70 String uri, String prefix) { | |
| 71 var libDirective; | |
| 72 for (var directive in unit.directives) { | |
| 73 if (directive is ImportDirective) { | |
| 74 transaction.edit(directive.keyword.offset, directive.keyword.offset, | |
| 75 'import \'$uri\' as $prefix;\n'); | |
| 76 return; | |
| 77 } else if (directive is LibraryDirective) { | |
| 78 libDirective = directive; | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 // No imports, add after the library directive if there was one. | |
| 83 if (libDirective != null) { | |
| 84 transaction.edit(libDirective.endToken.offset + 2, | |
| 85 libDirective.endToken.offset + 2, | |
| 86 'import \'$uri\' as $prefix;\n'); | |
| 87 } | |
| 88 } | |
| 89 | |
| 90 /// Vistior which changes every reference to a resolved element to a specific | |
| 91 /// string value. | |
| 92 class _IdentifierTransformer extends GeneralizingAstVisitor { | |
| 93 final TextEditTransaction transaction; | |
| 94 /// The element which all references to should be replaced. | |
| 95 final Element original; | |
| 96 /// The text which should replace [original]. | |
| 97 final String replacement; | |
| 98 /// The current logger. | |
| 99 final TransformLogger logger; | |
| 100 | |
| 101 _IdentifierTransformer(this.transaction, this.original, this.replacement, | |
| 102 this.logger); | |
| 103 | |
| 104 visitIdentifier(Identifier node) { | |
| 105 if (node.bestElement == original) { | |
| 106 transaction.edit(node.beginToken.offset, node.endToken.end, replacement); | |
| 107 return; | |
| 108 } | |
| 109 | |
| 110 super.visitIdentifier(node); | |
| 111 } | |
| 112 | |
| 113 // Top-level methods are not treated as prefixed identifiers, so handle those | |
| 114 // here. | |
| 115 visitMethodInvocation(MethodInvocation m) { | |
| 116 if (m.methodName.bestElement == original) { | |
| 117 if (m.target is SimpleIdentifier) { | |
| 118 // Include the prefix in the rename. | |
| 119 transaction.edit(m.target.beginToken.offset, m.methodName.endToken.end, | |
| 120 replacement); | |
| 121 } else { | |
| 122 transaction.edit(m.methodName.beginToken.offset, | |
| 123 m.methodName.endToken.end, replacement); | |
| 124 } | |
| 125 return; | |
| 126 } | |
| 127 super.visitMethodInvocation(m); | |
| 128 } | |
| 129 | |
| 130 // Skip the contents of imports/exports/parts | |
| 131 visitUriBasedDirective(ImportDirective d) {} | |
| 132 | |
| 133 visitPartDirective(PartDirective node) { | |
| 134 logger.warning('Not transforming code within ${node.uri}.'); | |
| 135 } | |
| 136 } | |
| OLD | NEW |