| Index: observatory_pub_packages/code_transformers/src/resolvers.dart
|
| ===================================================================
|
| --- observatory_pub_packages/code_transformers/src/resolvers.dart (revision 0)
|
| +++ observatory_pub_packages/code_transformers/src/resolvers.dart (working copy)
|
| @@ -0,0 +1,124 @@
|
| +// 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 code_transformers.src.resolvers;
|
| +
|
| +import 'dart:async';
|
| +import 'package:barback/barback.dart';
|
| +
|
| +import 'package:analyzer/src/generated/engine.dart' show AnalysisOptions;
|
| +import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
|
| +import 'package:analyzer/src/generated/source.dart' show DartUriResolver;
|
| +
|
| +import 'entry_point.dart';
|
| +import 'resolver.dart';
|
| +import 'resolver_impl.dart';
|
| +import 'dart_sdk.dart' hide dartSdkDirectory;
|
| +
|
| +/// Barback-based code resolvers which maintains up-to-date resolved ASTs for
|
| +/// the specified code entry points.
|
| +///
|
| +/// This can used by transformers dependent on resolved ASTs to handle the
|
| +/// resolution of the AST and cache the results between compilations.
|
| +///
|
| +/// If multiple transformers rely on a resolved AST they should (ideally) share
|
| +/// the same Resolvers object to minimize re-parsing the AST.
|
| +class Resolvers {
|
| + final Map<AssetId, Resolver> _resolvers = {};
|
| + final DartSdk dartSdk;
|
| + final DartUriResolver dartUriResolver;
|
| + final AnalysisOptions options;
|
| +
|
| + Resolvers.fromSdk(this.dartSdk, this.dartUriResolver, {this.options});
|
| +
|
| + factory Resolvers(dartSdkDirectory, {AnalysisOptions options}) {
|
| + var sdk = new DirectoryBasedDartSdkProxy(dartSdkDirectory);
|
| + var uriResolver = new DartUriResolverProxy(sdk);
|
| + return new Resolvers.fromSdk(sdk, uriResolver, options: options);
|
| + }
|
| +
|
| + factory Resolvers.fromMock(Map<String, String> sources,
|
| + {bool reportMissing: false, AnalysisOptions options}) {
|
| + var sdk = new MockDartSdk(sources, reportMissing: reportMissing);
|
| + return new Resolvers.fromSdk(sdk, sdk.resolver, options: options);
|
| + }
|
| +
|
| + /// Get a resolver for [transform]. If provided, this resolves the code
|
| + /// starting from each of the assets in [entryPoints]. If not, this resolves
|
| + /// the code starting from `transform.primaryInput.id` by default.
|
| + ///
|
| + /// [Resolver.release] must be called once it's done being used, or
|
| + /// [ResolverTransformer] should be used to automatically release the
|
| + /// resolver.
|
| + Future<Resolver> get(Transform transform, [List<AssetId> entryPoints]) {
|
| + var id = transform.primaryInput.id;
|
| + var resolver = _resolvers.putIfAbsent(id,
|
| + () => new ResolverImpl(dartSdk, dartUriResolver, options: options));
|
| + return resolver.resolve(transform, entryPoints);
|
| + }
|
| +}
|
| +
|
| +/// Transformer mixin which automatically gets and releases resolvers.
|
| +///
|
| +/// To use mix this class in, set the resolvers field and override
|
| +/// [applyResolver].
|
| +abstract class ResolverTransformer implements Transformer {
|
| + /// The cache of resolvers- must be set from subclass.
|
| + Resolvers resolvers;
|
| +
|
| + /// By default only process prossible entry point assets.
|
| + ///
|
| + /// This is only a preliminary check based on the asset ID.
|
| + Future<bool> isPrimary(assetOrId) {
|
| + // assetOrId is to handle the transition from Asset to AssetID between
|
| + // pub 1.3 and 1.4. Once support for 1.3 is dropped this should only
|
| + // support AssetId.
|
| + var id = assetOrId is AssetId ? assetOrId : assetOrId.id;
|
| + return new Future.value(isPossibleDartEntryId(id));
|
| + }
|
| +
|
| + /// Check to see if this should apply with the resolver on the provided asset.
|
| + ///
|
| + /// By default this will only apply on possible Dart entry points (see
|
| + /// [isPossibleDartEntry]).
|
| + Future<bool> shouldApplyResolver(Asset asset) => isPossibleDartEntry(asset);
|
| +
|
| +
|
| + /// This provides a default implementation of `Transformer.apply` that will
|
| + /// get and release resolvers automatically. Internally this:
|
| + /// * Gets a resolver associated with the transform primary input.
|
| + /// * Does resolution to the code starting from that input.
|
| + /// * Calls [applyResolver].
|
| + /// * Then releases the resolver.
|
| + ///
|
| + /// Use [applyToEntryPoints] instead if you need to override the entry points
|
| + /// to run the resolver on.
|
| + Future apply(Transform transform) =>
|
| + shouldApplyResolver(transform.primaryInput).then((result) {
|
| + if (result) return applyToEntryPoints(transform);
|
| + });
|
| +
|
| +
|
| + /// Helper function to make it easy to write an `Transformer.apply` method
|
| + /// that automatically gets and releases the resolver. This is typically used
|
| + /// as follows:
|
| + ///
|
| + /// Future apply(Transform transform) {
|
| + /// var entryPoints = ...; // compute entry points
|
| + /// return applyToEntryPoints(transform, entryPoints);
|
| + /// }
|
| + Future applyToEntryPoints(Transform transform, [List<AssetId> entryPoints]) {
|
| + return resolvers.get(transform, entryPoints).then((resolver) {
|
| + return new Future(() => applyResolver(transform, resolver))
|
| + .whenComplete(() {
|
| + resolver.release();
|
| + });
|
| + });
|
| + }
|
| +
|
| + /// Invoked when the resolver is ready to be processed.
|
| + ///
|
| + /// Return a Future to indicate when apply is completed.
|
| + applyResolver(Transform transform, Resolver resolver);
|
| +}
|
|
|