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

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

Issue 199413020: Fixes code_transformers after the latest analyzer changes (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/code_transformers/lib/src/test_harness.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 parseCompilationUnit;
8 import 'package:analyzer/src/generated/ast.dart'; 9 import 'package:analyzer/src/generated/ast.dart';
9 import 'package:analyzer/src/generated/element.dart'; 10 import 'package:analyzer/src/generated/element.dart';
10 import 'package:analyzer/src/generated/engine.dart'; 11 import 'package:analyzer/src/generated/engine.dart';
12 import 'package:analyzer/src/generated/error.dart';
11 import 'package:analyzer/src/generated/java_io.dart'; 13 import 'package:analyzer/src/generated/java_io.dart';
14 import 'package:analyzer/src/generated/parser.dart';
15 import 'package:analyzer/src/generated/scanner.dart';
12 import 'package:analyzer/src/generated/sdk.dart' show DartSdk; 16 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
13 import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk; 17 import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk;
14 import 'package:analyzer/src/generated/source.dart'; 18 import 'package:analyzer/src/generated/source.dart';
15 import 'package:barback/barback.dart'; 19 import 'package:barback/barback.dart';
16 import 'package:path/path.dart' as native_path; 20 import 'package:path/path.dart' as native_path;
17 import 'package:source_maps/refactor.dart'; 21 import 'package:source_maps/refactor.dart';
18 import 'package:source_maps/span.dart' show SourceFile, Span; 22 import 'package:source_maps/span.dart' show SourceFile, Span;
19 23
20 import 'resolver.dart'; 24 import 'resolver.dart';
21 25
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 Future _performResolve(Transform transform) { 108 Future _performResolve(Transform transform) {
105 if (_currentTransform != null) { 109 if (_currentTransform != null) {
106 throw new StateError('Cannot be accessed by concurrent transforms'); 110 throw new StateError('Cannot be accessed by concurrent transforms');
107 } 111 }
108 _currentTransform = transform; 112 _currentTransform = transform;
109 113
110 // Basic approach is to start at the first file, update it's contents 114 // Basic approach is to start at the first file, update it's contents
111 // and see if it changed, then walk all files accessed by it. 115 // and see if it changed, then walk all files accessed by it.
112 var visited = new Set<AssetId>(); 116 var visited = new Set<AssetId>();
113 var visiting = new FutureGroup(); 117 var visiting = new FutureGroup();
118 var toUpdate = [];
114 119
115 void processAsset(AssetId assetId) { 120 void processAsset(AssetId assetId) {
116 visited.add(assetId); 121 visited.add(assetId);
117 122
118 visiting.add(transform.readInputAsString(assetId).then((contents) { 123 visiting.add(transform.readInputAsString(assetId).then((contents) {
119 var source = sources[assetId]; 124 var source = sources[assetId];
120 if (source == null) { 125 if (source == null) {
121 source = new _AssetBasedSource(assetId, this); 126 source = new _AssetBasedSource(assetId, this);
122 sources[assetId] = source; 127 sources[assetId] = source;
123 } 128 }
124 source.updateContents(contents); 129 source.updateDependencies(contents);
125 130 toUpdate.add(new _PendingUpdate(source, contents));
126 source.dependentAssets 131 source.dependentAssets.where((id) => !visited.contains(id))
127 .where((id) => !visited.contains(id))
128 .forEach(processAsset); 132 .forEach(processAsset);
129
130 }, onError: (e) { 133 }, onError: (e) {
131 _context.applyChanges(new ChangeSet()..removedSource(sources[assetId])); 134 _context.applyChanges(new ChangeSet()..removedSource(sources[assetId]));
132 sources.remove(assetId); 135 sources.remove(assetId);
133 })); 136 }));
134 } 137 }
135 processAsset(entryPoint); 138 processAsset(entryPoint);
136 139
137 // Once we have all asset sources updated with the new contents then 140 // Once we have all asset sources updated with the new contents then
138 // resolve everything. 141 // resolve everything.
139 return visiting.future.then((_) { 142 return visiting.future.then((_) {
140 var changeSet = new ChangeSet(); 143 var changeSet = new ChangeSet();
144 toUpdate.forEach((pending) => pending.apply(changeSet));
141 var unreachableAssets = new Set.from(sources.keys).difference(visited); 145 var unreachableAssets = new Set.from(sources.keys).difference(visited);
142 for (var unreachable in unreachableAssets) { 146 for (var unreachable in unreachableAssets) {
143 changeSet.removedSource(sources[unreachable]); 147 changeSet.removedSource(sources[unreachable]);
144 sources.remove(unreachable); 148 sources.remove(unreachable);
145 } 149 }
146 150
147 // Update the analyzer context with the latest sources 151 // Update the analyzer context with the latest sources
148 _context.applyChanges(changeSet); 152 _context.applyChanges(changeSet);
149 // Resolve the AST 153 // Resolve the AST
150 _entryLibrary = _context.computeLibraryElement(sources[entryPoint]); 154 _entryLibrary = _context.computeLibraryElement(sources[entryPoint]);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 Iterable<AssetId> _dependentAssets; 272 Iterable<AssetId> _dependentAssets;
269 273
270 /// The current revision of the file, incremented only when file changes. 274 /// The current revision of the file, incremented only when file changes.
271 int _revision = 0; 275 int _revision = 0;
272 276
273 /// The file contents. 277 /// The file contents.
274 String _contents; 278 String _contents;
275 279
276 _AssetBasedSource(this.assetId, this._resolver); 280 _AssetBasedSource(this.assetId, this._resolver);
277 281
282 /// Update the dependencies of this source. This parses [contents] but avoids
283 /// any analyzer resolution.
284 void updateDependencies(String contents) {
285 if (contents == _contents) return;
286 var unit = parseCompilationUnit(contents);
287 _dependentAssets = unit.directives
288 .where((d) => (d is ImportDirective || d is PartDirective ||
289 d is ExportDirective))
290 .map((d) => _resolve(assetId, d.uri.stringValue, _logger,
291 _getSpan(d, contents)))
292 .where((id) => id != null).toSet();
293 }
294
278 /// Update the contents of this file with [contents]. 295 /// Update the contents of this file with [contents].
279 /// 296 ///
280 /// Returns true if the contents of this asset have changed. 297 /// Returns true if the contents of this asset have changed.
281 bool updateContents(String contents) { 298 bool updateContents(String contents) {
282 if (contents == _contents) return false; 299 if (contents == _contents) return false;
283 var added = _contents == null;
284 _contents = contents; 300 _contents = contents;
285 ++_revision; 301 ++_revision;
286 // Invalidate the imports so we only parse the AST when needed.
287 _dependentAssets = null;
288
289 if (added) {
290 _resolver._context.applyChanges(new ChangeSet()..addedSource(this));
291 } else {
292 _resolver._context.applyChanges(new ChangeSet()..changedSource(this));
293 }
294
295 var compilationUnit = _resolver._context.parseCompilationUnit(this);
296 _dependentAssets = compilationUnit.directives
297 .where((d) => (d is ImportDirective || d is PartDirective ||
298 d is ExportDirective))
299 .map((d) => _resolve(assetId, d.uri.stringValue,
300 _logger, _getSpan(d)))
301 .where((id) => id != null).toSet();
302 return true; 302 return true;
303 } 303 }
304 304
305 /// Contents of the file. 305 /// Contents of the file.
306 TimestampedData<String> get contents => 306 TimestampedData<String> get contents =>
307 new TimestampedData<String>(modificationStamp, _contents); 307 new TimestampedData<String>(modificationStamp, _contents);
308 308
309 /// Contents of the file. 309 /// Contents of the file.
310 String get rawContents => _contents; 310 String get rawContents => _contents;
311 311
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 350
351 // The entire AST should have been parsed and loaded at this point. 351 // The entire AST should have been parsed and loaded at this point.
352 var source = _resolver.sources[id]; 352 var source = _resolver.sources[id];
353 if (source == null) { 353 if (source == null) {
354 _logger.error('Could not load asset $id'); 354 _logger.error('Could not load asset $id');
355 } 355 }
356 return source; 356 return source;
357 } 357 }
358 358
359 /// For logging errors. 359 /// For logging errors.
360 Span _getSpan(AstNode node) => _sourceFile.span(node.offset, node.end); 360 Span _getSpan(AstNode node, [String contents]) =>
361 _getSourceFile(contents).span(node.offset, node.end);
361 /// For logging errors. 362 /// For logging errors.
362 SourceFile get _sourceFile { 363 SourceFile _getSourceFile([String contents]) {
363 var uri = getSourceUri(_resolver.entryPoint); 364 var uri = getSourceUri(_resolver.entryPoint);
364 var path = uri != null ? uri.toString() : assetId.path; 365 var path = uri != null ? uri.toString() : assetId.path;
365 366 return new SourceFile.text(path, contents != null ? contents : rawContents);
366 return new SourceFile.text(path, rawContents);
367 } 367 }
368 368
369 /// Gets a URI which would be appropriate for importing this file. 369 /// Gets a URI which would be appropriate for importing this file.
370 /// 370 ///
371 /// Note that this file may represent a non-importable file such as a part. 371 /// Note that this file may represent a non-importable file such as a part.
372 Uri getSourceUri([AssetId from]) { 372 Uri getSourceUri([AssetId from]) {
373 if (!assetId.path.startsWith('lib/')) { 373 if (!assetId.path.startsWith('lib/')) {
374 // Cannot do absolute imports of non lib-based assets. 374 // Cannot do absolute imports of non lib-based assets.
375 if (from == null) return null; 375 if (from == null) return null;
376 376
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
567 567
568 /** 568 /**
569 * A Future that complets with a List of the values from all the added 569 * A Future that complets with a List of the values from all the added
570 * tasks, when they have all completed. 570 * tasks, when they have all completed.
571 * 571 *
572 * If any task fails, this Future will receive the error. Only the first 572 * If any task fails, this Future will receive the error. Only the first
573 * error will be sent to the Future. 573 * error will be sent to the Future.
574 */ 574 */
575 Future<List<E>> get future => _completer.future; 575 Future<List<E>> get future => _completer.future;
576 } 576 }
577
578 /// A pending update to notify the resolver that a [Source] has been added or
579 /// changed. This is used by the `_performResolve` algorithm above to apply all
580 /// changes after it first discovers the transitive closure of files that are
581 /// reachable from the sources.
582 class _PendingUpdate {
583 _AssetBasedSource source;
584 String content;
585
586 _PendingUpdate(this.source, this.content);
587
588 void apply(ChangeSet changeSet) {
589 if (!source.updateContents(content)) return;
590 if (source._revision == 1 && source._contents != null) {
591 changeSet.addedSource(source);
592 } else {
593 changeSet.changedSource(source);
594 }
595 }
596 }
OLDNEW
« no previous file with comments | « no previous file | pkg/code_transformers/lib/src/test_harness.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698