This repository has been archived by the owner on Aug 18, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 11
/
resolvers.dart
138 lines (121 loc) · 5.47 KB
/
resolvers.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// 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/file_system/physical_file_system.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptions;
import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
import 'package:analyzer/src/generated/engine.dart';
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 Resolver _resolver;
Resolvers.fromSdk(DartSdk dartSdk, DartUriResolver dartUriResolver,
{AnalysisOptions options})
: _resolver =
new ResolverImpl(dartSdk, dartUriResolver, options: options);
factory Resolvers(String dartSdkDirectory, {AnalysisOptions options}) {
_initAnalysisEngine();
var sdk = new FolderBasedDartSdkProxy(
PhysicalResourceProvider.INSTANCE, 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}) {
_initAnalysisEngine();
var sdk = new MockDartSdk(sources, options, 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.
///
/// See [Resolver#resolve] for more info on the `resolveAllLibraries` option.
Future<Resolver> get(Transform transform,
[List<AssetId> entryPoints, bool resolveAllLibraries]) =>
_resolver.resolve(transform, entryPoints, resolveAllLibraries);
}
/// 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;
/// See [Resolver#resolve] for more info - can be overridden by a subclass.
bool get resolveAllLibraries => true;
/// By default only process possible 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 as Asset).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, resolveAllLibraries)
.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);
}
bool _analysisEngineInitialized = false;
_initAnalysisEngine() {
if (_analysisEngineInitialized) return;
_analysisEngineInitialized = true;
AnalysisEngine.instance.processRequiredPlugins();
}