Dart Transformer 无法覆盖资产
Dart Transformer fails to overwrite an Asset
我写了一个 AggregateTransformer,它应该用更新版本(更改导入)覆盖 main.dart 文件。
Asset mainAsset = await _getFileAsset(transform, "main.dart");
Asset updatedMainAsset = await _replaceDefaultImport(mainAsset, transform.package, "default.dart", newLibFileName);
//overwrite mainAsset because mainAsset and updatedMainAsset have the same id
transform.addOutput(updatedMainAsset);
(在添加新版本之前先删除资产不会改变任何东西:)
transform.consumePrimary(mainAsset.id);
transform.addOutput(updatedMainAsset);
但是更新后的版本消失得无影无踪。尝试通过 id 检索它会产生原始内容:
Asset updatedMainAssetRetrieved = await transform.getInput(updatedMainAsset.id);
transformer输出mainAsset和updatedMainAsset的内容,可以确认updatedMainAsset的内容确实更新了。通过调用 pub 运行 main.dart.
来调用转换器
完整的 code/pseudo-code 如下所示:
class ReplacePackageTransformer extends AggregateTransformer {
ReplacePackageTransformer.asPlugin();
@override
String classifyPrimary(AssetId id) => id.toString().endsWith(".dart") ? "dart-files" : null;
@override
apply(AggregateTransform transform) {
//capture the whole execution to allow better stacktraces if an error occurs
Chain.capture(() async {
//create a file lib/replacement.dart that defines the same method as lib/default.dart
final newLibFileName = "replacement.dart";
final newLibAsset = _createReplacementAsset(...);
//add this new asset
transform.addOutput(newLibAsset);
//rewrite main.dart to import replacement.dart instead of default.dart. To that end:
//1) retrieve the asset for main.dart
Asset mainAsset = await _getFileAsset(transform, "main.dart");
//2) create a new asset with the same id as mainAsset but with updated content
Asset updatedMainAsset = await _replaceDefaultImport(mainAsset, ...);
//3) adding this asset should overwrite/replace the original main.dart-asset because they use the same id
transform.addOutput(updatedMainAsset);
});
}
//helper methods ...
}
您可以找到整个变压器(以及项目的其余部分)here。
Update/Solution
丹尼斯·凯斯洛是对的!我的转换器的应用方法必须 return 一个 Future(以便后续转换器可以等待它完成)!在调用 Chain.capture 之前添加一个 return 就足够了(因为我捕获的回调有一个异步主体,因此 returns 是一个 Future该捕获将 forward/return).
如此变化
apply(AggregateTransform transform) {
Chain.capture(() async {...});
//no return statement so void is returned
}
至
Future apply(AggregateTransform transform) {
return Chain.capture(() async {...});
//() async {...} returns a Future that Chain.capture and apply forward/return
}
解决了我的问题!
解决方法很简单:在你的Chain.capture
前加一个return
即可。
apply
的 dartdoc 说:
If this does asynchronous work, it should return a [Future] that completes once it's finished.
如果在转换后访问输入,输入仍然是原始输入。您也不需要调用 transform.consumeInput
。
我写了一个 AggregateTransformer,它应该用更新版本(更改导入)覆盖 main.dart 文件。
Asset mainAsset = await _getFileAsset(transform, "main.dart");
Asset updatedMainAsset = await _replaceDefaultImport(mainAsset, transform.package, "default.dart", newLibFileName);
//overwrite mainAsset because mainAsset and updatedMainAsset have the same id
transform.addOutput(updatedMainAsset);
(在添加新版本之前先删除资产不会改变任何东西:)
transform.consumePrimary(mainAsset.id);
transform.addOutput(updatedMainAsset);
但是更新后的版本消失得无影无踪。尝试通过 id 检索它会产生原始内容:
Asset updatedMainAssetRetrieved = await transform.getInput(updatedMainAsset.id);
transformer输出mainAsset和updatedMainAsset的内容,可以确认updatedMainAsset的内容确实更新了。通过调用 pub 运行 main.dart.
来调用转换器完整的 code/pseudo-code 如下所示:
class ReplacePackageTransformer extends AggregateTransformer {
ReplacePackageTransformer.asPlugin();
@override
String classifyPrimary(AssetId id) => id.toString().endsWith(".dart") ? "dart-files" : null;
@override
apply(AggregateTransform transform) {
//capture the whole execution to allow better stacktraces if an error occurs
Chain.capture(() async {
//create a file lib/replacement.dart that defines the same method as lib/default.dart
final newLibFileName = "replacement.dart";
final newLibAsset = _createReplacementAsset(...);
//add this new asset
transform.addOutput(newLibAsset);
//rewrite main.dart to import replacement.dart instead of default.dart. To that end:
//1) retrieve the asset for main.dart
Asset mainAsset = await _getFileAsset(transform, "main.dart");
//2) create a new asset with the same id as mainAsset but with updated content
Asset updatedMainAsset = await _replaceDefaultImport(mainAsset, ...);
//3) adding this asset should overwrite/replace the original main.dart-asset because they use the same id
transform.addOutput(updatedMainAsset);
});
}
//helper methods ...
}
您可以找到整个变压器(以及项目的其余部分)here。
Update/Solution
丹尼斯·凯斯洛是对的!我的转换器的应用方法必须 return 一个 Future(以便后续转换器可以等待它完成)!在调用 Chain.capture 之前添加一个 return 就足够了(因为我捕获的回调有一个异步主体,因此 returns 是一个 Future该捕获将 forward/return).
如此变化
apply(AggregateTransform transform) {
Chain.capture(() async {...});
//no return statement so void is returned
}
至
Future apply(AggregateTransform transform) {
return Chain.capture(() async {...});
//() async {...} returns a Future that Chain.capture and apply forward/return
}
解决了我的问题!
解决方法很简单:在你的Chain.capture
前加一个return
即可。
apply
的 dartdoc 说:
If this does asynchronous work, it should return a [Future] that completes once it's finished.
如果在转换后访问输入,输入仍然是原始输入。您也不需要调用 transform.consumeInput
。