OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2015, 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 library initialize.plugin_transformer; |
| 5 |
| 6 import 'dart:async'; |
| 7 import 'package:analyzer/analyzer.dart'; |
| 8 import 'package:barback/barback.dart'; |
| 9 import 'package:source_maps/refactor.dart'; |
| 10 import 'package:source_span/source_span.dart'; |
| 11 |
| 12 /// Abstract transformer which will call [initEntry] for every [InitEntry] |
| 13 /// expression found in the bootstrap file. This is used to centralize logic |
| 14 /// for initializers which want to do something special at transform time. |
| 15 abstract class InitializePluginTransformer extends AggregateTransformer { |
| 16 // Path to the bootstrap file created by the initialize transformer. |
| 17 final String _bootstrapFile; |
| 18 |
| 19 // All the extra assets that were found, if child classes override |
| 20 // classifyPrimary this lets them get at the other assets easily. |
| 21 final allAssets = <Asset>[]; |
| 22 |
| 23 TransformLogger _logger; |
| 24 |
| 25 InitializePluginTransformer(this._bootstrapFile); |
| 26 |
| 27 classifyPrimary(AssetId id) => |
| 28 _bootstrapFile == id.path ? _bootstrapFile : null; |
| 29 |
| 30 Future apply(AggregateTransform transform) { |
| 31 _logger = transform.logger; |
| 32 var listener = transform.primaryInputs.listen((Asset asset) { |
| 33 allAssets.add(asset); |
| 34 var id = asset.id; |
| 35 if (id.path != _bootstrapFile) return; |
| 36 // Calls initEntry for each InitEntry expression. |
| 37 asset.readAsString().then((dartCode) { |
| 38 var url = id.path.startsWith('lib/') |
| 39 ? 'package:${id.package}/${id.path.substring(4)}' |
| 40 : id.path; |
| 41 var source = new SourceFile(dartCode, url: url); |
| 42 var transaction = new TextEditTransaction(dartCode, source); |
| 43 (parseCompilationUnit(dartCode, |
| 44 suppressErrors: true) as dynamic).declarations.firstWhere( |
| 45 (d) => d.name.toString() == |
| 46 'main').functionExpression.body.block.statements.firstWhere( |
| 47 (statement) { |
| 48 return statement.expression.target.toString() == 'initializers' && |
| 49 statement.expression.methodName.toString() == 'addAll'; |
| 50 }).expression.argumentList.arguments[0].elements |
| 51 .where((arg) => arg is InstanceCreationExpression) |
| 52 .forEach((e) => initEntry(e, transaction)); |
| 53 |
| 54 // Apply any transformations. |
| 55 if (!transaction.hasEdits) { |
| 56 transform.addOutput(asset); |
| 57 } else { |
| 58 var printer = transaction.commit(); |
| 59 printer.build(url); |
| 60 transform.addOutput(new Asset.fromString(id, printer.text)); |
| 61 } |
| 62 }); |
| 63 }); |
| 64 |
| 65 // Make sure all the assets are read before returning. |
| 66 return listener.asFuture(); |
| 67 } |
| 68 |
| 69 /// Gets called once for each generated [InitEntry] expression in the |
| 70 /// bootstrap file. A [TextEditTransaction] is supplied so that the user can |
| 71 /// modify the expression however they see fit. |
| 72 void initEntry( |
| 73 InstanceCreationExpression expression, TextEditTransaction transaction); |
| 74 |
| 75 /// Convenience method to delete an Initializer expression completely. |
| 76 void removeInitializer( |
| 77 InstanceCreationExpression expression, TextEditTransaction transaction) { |
| 78 // Delete the entire line. |
| 79 var line = transaction.file.getLine(expression.offset); |
| 80 transaction.edit(transaction.file.getOffset(line), |
| 81 transaction.file.getOffset(line + 1), ''); |
| 82 } |
| 83 } |
OLD | NEW |