Index: packages/code_transformers/lib/src/resolver_impl.dart |
diff --git a/packages/code_transformers/lib/src/resolver_impl.dart b/packages/code_transformers/lib/src/resolver_impl.dart |
index 9670c3a9aae8eba7886d319ed6d0c2b74a5142de..48b5405a3614755750c89955456893bc94d7871c 100644 |
--- a/packages/code_transformers/lib/src/resolver_impl.dart |
+++ b/packages/code_transformers/lib/src/resolver_impl.dart |
@@ -6,10 +6,10 @@ library code_transformer.src.resolver_impl; |
import 'dart:async'; |
import 'package:analyzer/analyzer.dart' show parseDirectives; |
-import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
+import 'package:analyzer/dart/ast/ast.dart'; |
import 'package:analyzer/src/generated/constant.dart' |
show ConstantEvaluator, EvaluationResult; |
-import 'package:analyzer/src/generated/element.dart'; |
+import 'package:analyzer/dart/element/element.dart'; |
import 'package:analyzer/src/generated/engine.dart'; |
import 'package:analyzer/src/generated/sdk.dart' show DartSdk; |
import 'package:analyzer/src/generated/source.dart'; |
@@ -31,8 +31,7 @@ final path = native_path.url; |
/// with the resolved AST. |
class ResolverImpl implements Resolver { |
/// Cache of all asset sources currently referenced. |
- final Map<AssetId, _AssetBasedSource> sources = |
- <AssetId, _AssetBasedSource>{}; |
+ final Map<AssetId, AssetBasedSource> sources = {}; |
final InternalAnalysisContext _context = |
AnalysisEngine.instance.createAnalysisContext(); |
@@ -56,29 +55,42 @@ class ResolverImpl implements Resolver { |
{AnalysisOptions options}) { |
if (options == null) { |
options = new AnalysisOptionsImpl() |
- ..cacheSize = 256 // # of sources to cache ASTs for. |
..preserveComments = false |
..analyzeFunctionBodies = true; |
} |
_context.analysisOptions = options; |
- sdk.context.analysisOptions = options; |
_context.sourceFactory = |
new SourceFactory([dartUriResolver, new _AssetUriResolver(this)]); |
} |
+ @override |
+ bool isLibrary(AssetId assetId) { |
+ var source = sources[assetId]; |
+ return source != null && _isLibrary(source); |
+ } |
+ |
+ bool _isLibrary(Source source) => |
+ _context.computeKindOf(source) == SourceKind.LIBRARY; |
+ |
+ @override |
LibraryElement getLibrary(AssetId assetId) { |
var source = sources[assetId]; |
- return source == null ? null : _context.computeLibraryElement(source); |
+ if (source == null) return null; |
+ if (!_isLibrary(source)) return null; |
+ return _context.computeLibraryElement(source); |
} |
- Future<Resolver> resolve(Transform transform, [List<AssetId> entryPoints]) { |
+ Future<Resolver> resolve(Transform transform, |
+ [List<AssetId> entryPoints, bool resolveAllLibraries]) { |
// Can only have one resolve in progress at a time, so chain the current |
// resolution to be after the last one. |
var phaseComplete = new Completer(); |
var future = _lastPhaseComplete.whenComplete(() { |
_currentPhaseComplete = phaseComplete; |
- return _performResolve(transform, |
- entryPoints == null ? [transform.primaryInput.id] : entryPoints); |
+ return _performResolve( |
+ transform, |
+ entryPoints == null ? [transform.primaryInput.id] : entryPoints, |
+ resolveAllLibraries); |
}).then((_) => this); |
// Advance the lastPhaseComplete to be done when this phase is all done. |
_lastPhaseComplete = phaseComplete.future; |
@@ -98,7 +110,9 @@ class ResolverImpl implements Resolver { |
_currentTransform = null; |
} |
- Future _performResolve(Transform transform, List<AssetId> entryPoints) { |
+ Future _performResolve(Transform transform, List<AssetId> entryPoints, |
+ bool resolveAllLibraries) { |
+ resolveAllLibraries ??= true; |
if (_currentTransform != null) { |
throw new StateError('Cannot be accessed by concurrent transforms'); |
} |
@@ -116,7 +130,7 @@ class ResolverImpl implements Resolver { |
visiting.add(transform.readInputAsString(assetId).then((contents) { |
var source = sources[assetId]; |
if (source == null) { |
- source = new _AssetBasedSource(assetId, this); |
+ source = new AssetBasedSource(assetId, this); |
sources[assetId] = source; |
} |
source.updateDependencies(contents); |
@@ -132,6 +146,7 @@ class ResolverImpl implements Resolver { |
} |
})); |
} |
+ |
entryPoints.forEach(processAsset); |
// Once we have all asset sources updated with the new contents then |
@@ -139,13 +154,6 @@ class ResolverImpl implements Resolver { |
return visiting.future.then((_) { |
var changeSet = new ChangeSet(); |
toUpdate.forEach((pending) => pending.apply(changeSet)); |
- var unreachableAssets = |
- sources.keys.toSet().difference(visited).map((id) => sources[id]); |
- for (var unreachable in unreachableAssets) { |
- changeSet.removedSource(unreachable); |
- unreachable.updateContents(null); |
- sources.remove(unreachable.assetId); |
- } |
// Update the analyzer context with the latest sources |
_context.applyChanges(changeSet); |
@@ -154,8 +162,26 @@ class ResolverImpl implements Resolver { |
_entryLibraries = entryPoints.map((id) { |
var source = sources[id]; |
if (source == null) return null; |
+ var kind = _context.computeKindOf(source); |
+ if (kind != SourceKind.LIBRARY) return null; |
return _context.computeLibraryElement(source); |
}).toList(); |
+ |
+ if (resolveAllLibraries) { |
+ // Force resolve all other available libraries. As of analyzer > 0.27.1 |
+ // this is necessary to get resolved constants. |
+ var newLibraries = new Set<LibraryElement>(); |
+ for (var library in libraries) { |
+ if (library.source.uri.scheme == 'dart' || |
+ _entryLibraries.contains(library)) { |
+ newLibraries.add(library); |
+ } else { |
+ newLibraries.add(_context |
+ .computeLibraryElement(library.definingCompilationUnit.source)); |
+ } |
+ } |
+ _libraries = newLibraries; |
+ } |
}); |
} |
@@ -236,7 +262,7 @@ class ResolverImpl implements Resolver { |
/// the library URI. |
Uri _getSourceUri(Element element, {AssetId from}) { |
var source = element.source; |
- if (source is _AssetBasedSource) { |
+ if (source is AssetBasedSource) { |
var uriString = assetIdToUri(source.assetId, from: from); |
return uriString != null ? Uri.parse(uriString) : null; |
} else if (source is UriAnnotatedSource) { |
@@ -248,23 +274,24 @@ class ResolverImpl implements Resolver { |
AssetId getSourceAssetId(Element element) { |
var source = element.source; |
- if (source is _AssetBasedSource) return source.assetId; |
+ if (source is AssetBasedSource) return source.assetId; |
return null; |
} |
SourceSpan getSourceSpan(Element element) { |
var sourceFile = getSourceFile(element); |
if (sourceFile == null) return null; |
- return sourceFile.span(element.node.offset, element.node.end); |
+ return sourceFile.span( |
+ element.computeNode().offset, element.computeNode().end); |
} |
TextEditTransaction createTextEditTransaction(Element element) { |
- if (element.source is! _AssetBasedSource) return null; |
+ if (element.source is! AssetBasedSource) return null; |
// Cannot edit unless there is an active transformer. |
if (_currentTransform == null) return null; |
- _AssetBasedSource source = element.source; |
+ AssetBasedSource source = element.source; |
// Cannot modify assets in other packages. |
if (source.assetId.package != _currentTransform.primaryInput.id.package) { |
return null; |
@@ -288,8 +315,7 @@ class ResolverImpl implements Resolver { |
} |
/// Implementation of Analyzer's Source for Barback based assets. |
-class _AssetBasedSource extends Source { |
- |
+class AssetBasedSource extends Source { |
/// Asset ID where this source can be found. |
final AssetId assetId; |
@@ -305,7 +331,7 @@ class _AssetBasedSource extends Source { |
/// The file contents. |
String _contents; |
- _AssetBasedSource(this.assetId, this._resolver); |
+ AssetBasedSource(this.assetId, this._resolver); |
/// Update the dependencies of this source. This parses [contents] but avoids |
/// any analyzer resolution. |
@@ -313,11 +339,9 @@ class _AssetBasedSource extends Source { |
if (contents == _contents) return; |
var unit = parseDirectives(contents, suppressErrors: true); |
_dependentAssets = unit.directives |
- .where((d) => (d is ImportDirective || |
- d is PartDirective || |
- d is ExportDirective)) |
- .map((d) => _resolve( |
- assetId, d.uri.stringValue, _logger, _getSpan(d, contents))) |
+ .where((d) => d is UriBasedDirective) |
+ .map((d) => _resolve(assetId, (d as UriBasedDirective).uri.stringValue, |
+ _logger, _getSpan(d, contents))) |
.where((id) => id != null) |
.toSet(); |
} |
@@ -355,7 +379,7 @@ class _AssetBasedSource extends Source { |
bool exists() => _contents != null; |
bool operator ==(Object other) => |
- other is _AssetBasedSource && assetId == other.assetId; |
+ other is AssetBasedSource && assetId == other.assetId; |
int get hashCode => assetId.hashCode; |
@@ -437,7 +461,7 @@ class _AssetUriResolver implements UriResolver { |
// Analyzer expects that sources which are referenced but do not exist yet |
// still exist, so just make an empty source. |
if (source == null) { |
- source = new _AssetBasedSource(assetId, _resolver); |
+ source = new AssetBasedSource(assetId, _resolver); |
_resolver.sources[assetId] = source; |
} |
return source; |
@@ -538,7 +562,7 @@ class FutureGroup<E> { |
/// changes after it first discovers the transitive closure of files that are |
/// reachable from the sources. |
class _PendingUpdate { |
- _AssetBasedSource source; |
+ AssetBasedSource source; |
String content; |
_PendingUpdate(this.source, this.content); |