Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(259)

Side by Side Diff: lib/src/resolver_impl.dart

Issue 1830403002: switch package to strong mode (Closed) Base URL: git@github.com:dart-lang/code_transformers.git@master
Patch Set: use async Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library code_transformer.src.resolver_impl; 5 library code_transformer.src.resolver_impl;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'package:analyzer/analyzer.dart' show parseDirectives; 8 import 'package:analyzer/analyzer.dart' show parseDirectives;
9 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; 9 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
10 import 'package:analyzer/src/generated/constant.dart' 10 import 'package:analyzer/src/generated/constant.dart'
(...skipping 13 matching lines...) Expand all
24 24
25 // We should always be using url paths here since it's always Dart/pub code. 25 // We should always be using url paths here since it's always Dart/pub code.
26 final path = native_path.url; 26 final path = native_path.url;
27 27
28 /// Resolves and updates an AST based on Barback-based assets. 28 /// Resolves and updates an AST based on Barback-based assets.
29 /// 29 ///
30 /// This also provides a handful of useful APIs for traversing and working 30 /// This also provides a handful of useful APIs for traversing and working
31 /// with the resolved AST. 31 /// with the resolved AST.
32 class ResolverImpl implements Resolver { 32 class ResolverImpl implements Resolver {
33 /// Cache of all asset sources currently referenced. 33 /// Cache of all asset sources currently referenced.
34 final Map<AssetId, _AssetBasedSource> sources; 34 final Map<AssetId, AssetBasedSource> sources;
35 35
36 final InternalAnalysisContext _context = 36 final InternalAnalysisContext _context =
37 AnalysisEngine.instance.createAnalysisContext(); 37 AnalysisEngine.instance.createAnalysisContext();
38 38
39 /// Transform for which this is currently updating, or null when not updating. 39 /// Transform for which this is currently updating, or null when not updating.
40 Transform _currentTransform; 40 Transform _currentTransform;
41 41
42 /// The currently resolved entry libraries, or null if nothing is resolved. 42 /// The currently resolved entry libraries, or null if nothing is resolved.
43 List<LibraryElement> _entryLibraries; 43 List<LibraryElement> _entryLibraries;
44 Set<LibraryElement> _libraries; 44 Set<LibraryElement> _libraries;
45 45
46 /// Future indicating when this resolver is done in the current phase. 46 /// Future indicating when this resolver is done in the current phase.
47 Future _lastPhaseComplete = new Future.value(); 47 Future _lastPhaseComplete = new Future.value();
48 48
49 /// Completer for wrapping up the current phase. 49 /// Completer for wrapping up the current phase.
50 Completer _currentPhaseComplete; 50 Completer _currentPhaseComplete;
51 51
52 /// Creates a resolver with a given [sdk] implementation for resolving 52 /// Creates a resolver with a given [sdk] implementation for resolving
53 /// `dart:*` imports. 53 /// `dart:*` imports.
54 ResolverImpl(DartSdk sdk, DartUriResolver dartUriResolver, 54 ResolverImpl(DartSdk sdk, DartUriResolver dartUriResolver,
55 {AnalysisOptions options, Map<AssetId, _AssetBasedSource> sources}) 55 {AnalysisOptions options, Map<AssetId, AssetBasedSource> sources})
56 : sources = sources ?? <AssetId, _AssetBasedSource>{} { 56 : sources = sources ?? <AssetId, AssetBasedSource>{} {
57 if (options == null) { 57 if (options == null) {
58 options = new AnalysisOptionsImpl() 58 options = new AnalysisOptionsImpl()
59 ..cacheSize = 256 // # of sources to cache ASTs for. 59 ..cacheSize = 256 // # of sources to cache ASTs for.
60 ..preserveComments = false 60 ..preserveComments = false
61 ..analyzeFunctionBodies = true; 61 ..analyzeFunctionBodies = true;
62 } 62 }
63 _context.analysisOptions = options; 63 _context.analysisOptions = options;
64 sdk.context.analysisOptions = options; 64 sdk.context.analysisOptions = options;
65 _context.sourceFactory = 65 _context.sourceFactory =
66 new SourceFactory([dartUriResolver, new _AssetUriResolver(this)]); 66 new SourceFactory([dartUriResolver, new _AssetUriResolver(this)]);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
114 var visited = new Set<AssetId>(); 114 var visited = new Set<AssetId>();
115 var visiting = new FutureGroup(); 115 var visiting = new FutureGroup();
116 var toUpdate = []; 116 var toUpdate = [];
117 117
118 void processAsset(AssetId assetId) { 118 void processAsset(AssetId assetId) {
119 visited.add(assetId); 119 visited.add(assetId);
120 120
121 visiting.add(transform.readInputAsString(assetId).then((contents) { 121 visiting.add(transform.readInputAsString(assetId).then((contents) {
122 var source = sources[assetId]; 122 var source = sources[assetId];
123 if (source == null) { 123 if (source == null) {
124 source = new _AssetBasedSource(assetId, this); 124 source = new AssetBasedSource(assetId, this);
125 sources[assetId] = source; 125 sources[assetId] = source;
126 } 126 }
127 source.updateDependencies(contents); 127 source.updateDependencies(contents);
128 toUpdate.add(new _PendingUpdate(source, contents)); 128 toUpdate.add(new _PendingUpdate(source, contents));
129 source.dependentAssets 129 source.dependentAssets
130 .where((id) => !visited.contains(id)) 130 .where((id) => !visited.contains(id))
131 .forEach(processAsset); 131 .forEach(processAsset);
132 }, onError: (e) { 132 }, onError: (e) {
133 var source = sources[assetId]; 133 var source = sources[assetId];
134 if (source != null && source.exists()) { 134 if (source != null && source.exists()) {
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 .evaluate(expression); 250 .evaluate(expression);
251 } 251 }
252 252
253 Uri getImportUri(LibraryElement lib, {AssetId from}) => 253 Uri getImportUri(LibraryElement lib, {AssetId from}) =>
254 _getSourceUri(lib, from: from); 254 _getSourceUri(lib, from: from);
255 255
256 /// Similar to getImportUri but will get the part URI for parts rather than 256 /// Similar to getImportUri but will get the part URI for parts rather than
257 /// the library URI. 257 /// the library URI.
258 Uri _getSourceUri(Element element, {AssetId from}) { 258 Uri _getSourceUri(Element element, {AssetId from}) {
259 var source = element.source; 259 var source = element.source;
260 if (source is _AssetBasedSource) { 260 if (source is AssetBasedSource) {
261 var uriString = assetIdToUri(source.assetId, from: from); 261 var uriString = assetIdToUri(source.assetId, from: from);
262 return uriString != null ? Uri.parse(uriString) : null; 262 return uriString != null ? Uri.parse(uriString) : null;
263 } else if (source is UriAnnotatedSource) { 263 } else if (source is UriAnnotatedSource) {
264 return source.uri; 264 return source.uri;
265 } 265 }
266 // Should not be able to encounter any other source types. 266 // Should not be able to encounter any other source types.
267 throw new StateError('Unable to resolve URI for ${source.runtimeType}'); 267 throw new StateError('Unable to resolve URI for ${source.runtimeType}');
268 } 268 }
269 269
270 AssetId getSourceAssetId(Element element) { 270 AssetId getSourceAssetId(Element element) {
271 var source = element.source; 271 var source = element.source;
272 if (source is _AssetBasedSource) return source.assetId; 272 if (source is AssetBasedSource) return source.assetId;
273 return null; 273 return null;
274 } 274 }
275 275
276 SourceSpan getSourceSpan(Element element) { 276 SourceSpan getSourceSpan(Element element) {
277 var sourceFile = getSourceFile(element); 277 var sourceFile = getSourceFile(element);
278 if (sourceFile == null) return null; 278 if (sourceFile == null) return null;
279 return sourceFile.span( 279 return sourceFile.span(
280 element.computeNode().offset, element.computeNode().end); 280 element.computeNode().offset, element.computeNode().end);
281 } 281 }
282 282
283 TextEditTransaction createTextEditTransaction(Element element) { 283 TextEditTransaction createTextEditTransaction(Element element) {
284 if (element.source is! _AssetBasedSource) return null; 284 if (element.source is! AssetBasedSource) return null;
285 285
286 // Cannot edit unless there is an active transformer. 286 // Cannot edit unless there is an active transformer.
287 if (_currentTransform == null) return null; 287 if (_currentTransform == null) return null;
288 288
289 _AssetBasedSource source = element.source; 289 AssetBasedSource source = element.source;
290 // Cannot modify assets in other packages. 290 // Cannot modify assets in other packages.
291 if (source.assetId.package != _currentTransform.primaryInput.id.package) { 291 if (source.assetId.package != _currentTransform.primaryInput.id.package) {
292 return null; 292 return null;
293 } 293 }
294 294
295 var sourceFile = getSourceFile(element); 295 var sourceFile = getSourceFile(element);
296 if (sourceFile == null) return null; 296 if (sourceFile == null) return null;
297 297
298 return new TextEditTransaction(source.rawContents, sourceFile); 298 return new TextEditTransaction(source.rawContents, sourceFile);
299 } 299 }
300 300
301 /// Gets the SourceFile for the source of the element. 301 /// Gets the SourceFile for the source of the element.
302 SourceFile getSourceFile(Element element) { 302 SourceFile getSourceFile(Element element) {
303 var assetId = getSourceAssetId(element); 303 var assetId = getSourceAssetId(element);
304 if (assetId == null) return null; 304 if (assetId == null) return null;
305 305
306 var importUri = _getSourceUri(element); 306 var importUri = _getSourceUri(element);
307 var spanPath = importUri != null ? importUri.toString() : assetId.path; 307 var spanPath = importUri != null ? importUri.toString() : assetId.path;
308 return new SourceFile(sources[assetId].rawContents, url: spanPath); 308 return new SourceFile(sources[assetId].rawContents, url: spanPath);
309 } 309 }
310 } 310 }
311 311
312 /// Implementation of Analyzer's Source for Barback based assets. 312 /// Implementation of Analyzer's Source for Barback based assets.
313 class _AssetBasedSource extends Source { 313 class AssetBasedSource extends Source {
314 /// Asset ID where this source can be found. 314 /// Asset ID where this source can be found.
315 final AssetId assetId; 315 final AssetId assetId;
316 316
317 /// The resolver this is being used in. 317 /// The resolver this is being used in.
318 final ResolverImpl _resolver; 318 final ResolverImpl _resolver;
319 319
320 /// Cache of dependent asset IDs, to avoid re-parsing the AST. 320 /// Cache of dependent asset IDs, to avoid re-parsing the AST.
321 Iterable<AssetId> _dependentAssets; 321 Iterable<AssetId> _dependentAssets;
322 322
323 /// The current revision of the file, incremented only when file changes. 323 /// The current revision of the file, incremented only when file changes.
324 int _revision = 0; 324 int _revision = 0;
325 325
326 /// The file contents. 326 /// The file contents.
327 String _contents; 327 String _contents;
328 328
329 _AssetBasedSource(this.assetId, this._resolver); 329 AssetBasedSource(this.assetId, this._resolver);
330 330
331 /// Update the dependencies of this source. This parses [contents] but avoids 331 /// Update the dependencies of this source. This parses [contents] but avoids
332 /// any analyzer resolution. 332 /// any analyzer resolution.
333 void updateDependencies(String contents) { 333 void updateDependencies(String contents) {
334 if (contents == _contents) return; 334 if (contents == _contents) return;
335 var unit = parseDirectives(contents, suppressErrors: true); 335 var unit = parseDirectives(contents, suppressErrors: true);
336 _dependentAssets = unit.directives 336 _dependentAssets = unit.directives
337 .where((d) => (d is ImportDirective || 337 .where((d) => d is UriBasedDirective)
338 d is PartDirective || 338 .map((d) => _resolve(assetId, (d as UriBasedDirective).uri.stringValue,
339 d is ExportDirective)) 339 _logger, _getSpan(d, contents)))
340 .map((d) => _resolve(
341 assetId, d.uri.stringValue, _logger, _getSpan(d, contents)))
342 .where((id) => id != null) 340 .where((id) => id != null)
343 .toSet(); 341 .toSet();
344 } 342 }
345 343
346 /// Update the contents of this file with [contents]. 344 /// Update the contents of this file with [contents].
347 /// 345 ///
348 /// Returns true if the contents of this asset have changed. 346 /// Returns true if the contents of this asset have changed.
349 bool updateContents(String contents) { 347 bool updateContents(String contents) {
350 if (contents == _contents) return false; 348 if (contents == _contents) return false;
351 _contents = contents; 349 _contents = contents;
(...skipping 17 matching lines...) Expand all
369 /// 367 ///
370 /// Only valid while the resolver is updating assets. 368 /// Only valid while the resolver is updating assets.
371 TransformLogger get _logger => _resolver._currentTransform.logger; 369 TransformLogger get _logger => _resolver._currentTransform.logger;
372 370
373 /// Gets all imports/parts/exports which resolve to assets (non-Dart files). 371 /// Gets all imports/parts/exports which resolve to assets (non-Dart files).
374 Iterable<AssetId> get dependentAssets => _dependentAssets; 372 Iterable<AssetId> get dependentAssets => _dependentAssets;
375 373
376 bool exists() => _contents != null; 374 bool exists() => _contents != null;
377 375
378 bool operator ==(Object other) => 376 bool operator ==(Object other) =>
379 other is _AssetBasedSource && assetId == other.assetId; 377 other is AssetBasedSource && assetId == other.assetId;
380 378
381 int get hashCode => assetId.hashCode; 379 int get hashCode => assetId.hashCode;
382 380
383 void getContentsToReceiver(Source_ContentReceiver receiver) { 381 void getContentsToReceiver(Source_ContentReceiver receiver) {
384 receiver.accept(rawContents, modificationStamp); 382 receiver.accept(rawContents, modificationStamp);
385 } 383 }
386 384
387 String get encoding => 385 String get encoding =>
388 "${uriKind.encoding}${assetId.package}/${assetId.path}"; 386 "${uriKind.encoding}${assetId.package}/${assetId.path}";
389 387
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 assetId = _resolve(null, uri.toString(), logger, null); 449 assetId = _resolve(null, uri.toString(), logger, null);
452 if (assetId == null) { 450 if (assetId == null) {
453 logger.error('Unable to resolve asset ID for "$uri"'); 451 logger.error('Unable to resolve asset ID for "$uri"');
454 return null; 452 return null;
455 } 453 }
456 } 454 }
457 var source = _resolver.sources[assetId]; 455 var source = _resolver.sources[assetId];
458 // Analyzer expects that sources which are referenced but do not exist yet 456 // Analyzer expects that sources which are referenced but do not exist yet
459 // still exist, so just make an empty source. 457 // still exist, so just make an empty source.
460 if (source == null) { 458 if (source == null) {
461 source = new _AssetBasedSource(assetId, _resolver); 459 source = new AssetBasedSource(assetId, _resolver);
462 _resolver.sources[assetId] = source; 460 _resolver.sources[assetId] = source;
463 } 461 }
464 return source; 462 return source;
465 } 463 }
466 464
467 Source fromEncoding(UriKind kind, Uri uri) => 465 Source fromEncoding(UriKind kind, Uri uri) =>
468 throw new UnsupportedError('fromEncoding is not supported'); 466 throw new UnsupportedError('fromEncoding is not supported');
469 467
470 Uri restoreAbsolute(Source source) => 468 Uri restoreAbsolute(Source source) =>
471 throw new UnsupportedError('restoreAbsolute is not supported'); 469 throw new UnsupportedError('restoreAbsolute is not supported');
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 * error will be sent to the Future. 550 * error will be sent to the Future.
553 */ 551 */
554 Future<List<E>> get future => _completer.future; 552 Future<List<E>> get future => _completer.future;
555 } 553 }
556 554
557 /// A pending update to notify the resolver that a [Source] has been added or 555 /// A pending update to notify the resolver that a [Source] has been added or
558 /// changed. This is used by the `_performResolve` algorithm above to apply all 556 /// changed. This is used by the `_performResolve` algorithm above to apply all
559 /// changes after it first discovers the transitive closure of files that are 557 /// changes after it first discovers the transitive closure of files that are
560 /// reachable from the sources. 558 /// reachable from the sources.
561 class _PendingUpdate { 559 class _PendingUpdate {
562 _AssetBasedSource source; 560 AssetBasedSource source;
563 String content; 561 String content;
564 562
565 _PendingUpdate(this.source, this.content); 563 _PendingUpdate(this.source, this.content);
566 564
567 void apply(ChangeSet changeSet) { 565 void apply(ChangeSet changeSet) {
568 if (!source.updateContents(content)) return; 566 if (!source.updateContents(content)) return;
569 if (source._revision == 1 && source._contents != null) { 567 if (source._revision == 1 && source._contents != null) {
570 changeSet.addedSource(source); 568 changeSet.addedSource(source);
571 } else { 569 } else {
572 changeSet.changedSource(source); 570 changeSet.changedSource(source);
573 } 571 }
574 } 572 }
575 } 573 }
OLDNEW
« no previous file with comments | « lib/src/dart_sdk.dart ('k') | lib/src/resolvers.dart » ('j') | lib/src/resolvers.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698