blob: 3f4ca617cd30db8c2db6c1cad72723ba31ccf425 [file] [log] [blame]
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:convert';
import 'package:async/async.dart';
import 'package:build/build.dart';
import 'meta_module.dart';
import 'meta_module_clean_builder.dart';
import 'modules.dart';
import 'platform.dart';
/// The extension for serialized module assets.
String moduleExtension(DartPlatform platform) => '.${platform.name}.module';
/// A [Resource] that provides a [_CleanMetaModuleCache].
final _cleanMetaModules = Resource<_CleanMetaModuleCache>(
() => _CleanMetaModuleCache(),
dispose: (c) => c.dispose());
/// Safely caches deserialized [MetaModule] objects by their [AssetId].
///
/// Tracks access to assets via [BuildStep.canRead] calls.
class _CleanMetaModuleCache {
final _modules = <AssetId, Future<Result<MetaModule>>>{};
void dispose() => _modules.clear();
Future<MetaModule> find(
DartPlatform platform, String package, AssetReader reader) async {
var cleanMetaAsset =
AssetId(package, 'lib/${metaModuleCleanExtension(platform)}');
if (!await reader.canRead(cleanMetaAsset)) return null;
var metaResult = _modules.putIfAbsent(
cleanMetaAsset,
() => Result.capture(reader.readAsString(cleanMetaAsset).then((c) =>
MetaModule.fromJson(jsonDecode(c) as Map<String, dynamic>))));
return Result.release(metaResult);
}
}
/// Creates `.module` files for any `.dart` file that is the primary dart
/// source of a [Module].
class ModuleBuilder implements Builder {
final DartPlatform _platform;
ModuleBuilder(this._platform)
: buildExtensions = {
'.dart': [moduleExtension(_platform)]
};
@override
final Map<String, List<String>> buildExtensions;
@override
Future build(BuildStep buildStep) async {
var cleanMetaModules = await buildStep.fetchResource(_cleanMetaModules);
var metaModule = await cleanMetaModules.find(
_platform, buildStep.inputId.package, buildStep);
final outputModule = metaModule.modules.firstWhere(
(m) => m.primarySource == buildStep.inputId,
orElse: () => null);
if (outputModule == null) return;
await buildStep.writeAsString(
buildStep.inputId.changeExtension(moduleExtension(_platform)),
jsonEncode(outputModule.toJson()));
}
}