2016-02-14 3 views
2

Я написал AggregateTransformer, который должен перезаписать файл main.dart с обновленной версией (изменить импорт).Dart Transformer не может перезаписать Asset

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); 

Но обновленная версия исчезает без следа. Попытка получить его по идентификатору дает исходное содержание:

Asset updatedMainAssetRetrieved = await transform.getInput(updatedMainAsset.id); 

трансформатор выводит содержание mainAsset и updatedMainAsset, так что вы можете проверить, что содержание updatedMainAsset действительно обновляется. Вызовите трансформатор, вызвав pub run main.dart.

Полный код/​​псевдо-код выглядит следующим образом:

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/Решение

Деннис Kaselow прав! Метод apply моего метода трансформатора должен вернуть будущее (так что последующие трансформаторы могут дождаться, когда это будет сделано)! Добавив , ответьте до того, как вызов Chain.capture был бы достаточным (поскольку захват i-обратного вызова имеет тело асинхронизации и, следовательно, возвращает Будущее, которое захват будет пересылать/возвращать).

Так изменение

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 
} 

решает мою проблему!

+0

Это похоже на https://groups.google.com/a/dartlang.org/forum/#!topic/editor/vz-arQ_KEFM. Не знаю, помогает ли это. Я предлагаю вам отправить ссылку на этот вопрос SO на https://groups.google.com/a/dartlang.org/forum/#!forum/misc –

+0

Не уверен, что моя проблема связана с той, которую вы связали, потому что что речь идет о частичном файле, и они предложили вложение. Хотя мой актив был единственной файловой библиотекой (без частей), поэтому он уже был встроен. Я добавил сообщение в dart-misc, которого еще нет в сети, потому что первое сообщение модерируется. – StephanS

ответ

2

Решение довольно просто: просто добавьте return перед вашим Chain.capture.

dartdoc из apply говорит:

Если это делает асинхронной работы, он должен вернуть [будущее], который завершает после его завершения.

Если вы получили доступ к вводу после преобразования, вход будет по-прежнему являться исходным входом. Вам также не нужно звонить transform.consumeInput.