| // Copyright (c) 2014, 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. |
| |
| library pub.asset.transformer_isolate; |
| |
| import 'dart:convert'; |
| import 'dart:isolate'; |
| import 'dart:mirrors'; |
| |
| import 'package:barback/barback.dart'; |
| |
| import 'serialize.dart'; |
| |
| /// Sets up the initial communication with the host isolate. |
| void loadTransformers(SendPort replyTo) { |
| var port = new ReceivePort(); |
| replyTo.send(port.sendPort); |
| port.first.then((wrappedMessage) { |
| respond(wrappedMessage, (message) { |
| var library = Uri.parse(message['library']); |
| var configuration = JSON.decode(message['configuration']); |
| var mode = new BarbackMode(message['mode']); |
| return _initialize(library, configuration, mode). |
| map(serializeTransformerOrGroup).toList(); |
| }); |
| }); |
| } |
| |
| /// Loads all the transformers and groups defined in [uri]. |
| /// |
| /// Loads the library, finds any [Transformer] or [TransformerGroup] subclasses |
| /// in it, instantiates them with [configuration] and [mode], and returns them. |
| List _initialize(Uri uri, Map configuration, BarbackMode mode) { |
| var mirrors = currentMirrorSystem(); |
| var transformerClass = reflectClass(Transformer); |
| var groupClass = reflectClass(TransformerGroup); |
| |
| var seen = new Set(); |
| var transformers = []; |
| |
| loadFromLibrary(library) { |
| if (seen.contains(library)) return; |
| seen.add(library); |
| |
| // Load transformers from libraries exported by [library]. |
| for (var dependency in library.libraryDependencies) { |
| if (!dependency.isExport) continue; |
| loadFromLibrary(dependency.targetLibrary); |
| } |
| |
| // TODO(nweiz): if no valid transformers are found, throw an error message |
| // describing candidates and why they were rejected. |
| transformers.addAll(library.declarations.values.map((declaration) { |
| if (declaration is! ClassMirror) return null; |
| var classMirror = declaration; |
| if (classMirror.isPrivate) return null; |
| if (classMirror.isAbstract) return null; |
| if (!classMirror.isSubtypeOf(transformerClass) && |
| !classMirror.isSubtypeOf(groupClass)) { |
| return null; |
| } |
| |
| var constructor = _getConstructor(classMirror, 'asPlugin'); |
| if (constructor == null) return null; |
| if (constructor.parameters.isEmpty) { |
| if (configuration.isNotEmpty) return null; |
| return classMirror.newInstance(const Symbol('asPlugin'), []).reflectee; |
| } |
| if (constructor.parameters.length != 1) return null; |
| |
| return classMirror.newInstance(const Symbol('asPlugin'), |
| [new BarbackSettings(configuration, mode)]).reflectee; |
| }).where((classMirror) => classMirror != null)); |
| } |
| |
| loadFromLibrary(mirrors.libraries[uri]); |
| return transformers; |
| } |
| |
| // TODO(nweiz): clean this up when issue 13248 is fixed. |
| MethodMirror _getConstructor(ClassMirror classMirror, String constructor) { |
| var name = new Symbol("${MirrorSystem.getName(classMirror.simpleName)}" |
| ".$constructor"); |
| var candidate = classMirror.declarations[name]; |
| if (candidate is MethodMirror && candidate.isConstructor) return candidate; |
| return null; |
| } |