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

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

Issue 2989763002: Update charted to 0.4.8 and roll (Closed)
Patch Set: Removed Cutch from list of reviewers Created 3 years, 4 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/dart/ast/ast.dart';
10 import 'package:analyzer/src/generated/constant.dart' 10 import 'package:analyzer/src/generated/constant.dart'
11 show ConstantEvaluator, EvaluationResult; 11 show ConstantEvaluator, EvaluationResult;
12 import 'package:analyzer/src/generated/element.dart'; 12 import 'package:analyzer/dart/element/element.dart';
13 import 'package:analyzer/src/generated/engine.dart'; 13 import 'package:analyzer/src/generated/engine.dart';
14 import 'package:analyzer/src/generated/sdk.dart' show DartSdk; 14 import 'package:analyzer/src/generated/sdk.dart' show DartSdk;
15 import 'package:analyzer/src/generated/source.dart'; 15 import 'package:analyzer/src/generated/source.dart';
16 import 'package:barback/barback.dart'; 16 import 'package:barback/barback.dart';
17 import 'package:code_transformers/assets.dart'; 17 import 'package:code_transformers/assets.dart';
18 import 'package:path/path.dart' as native_path; 18 import 'package:path/path.dart' as native_path;
19 import 'package:source_maps/refactor.dart'; 19 import 'package:source_maps/refactor.dart';
20 import 'package:source_span/source_span.dart'; 20 import 'package:source_span/source_span.dart';
21 21
22 import 'resolver.dart'; 22 import 'resolver.dart';
23 import 'dart_sdk.dart' show UriAnnotatedSource; 23 import 'dart_sdk.dart' show UriAnnotatedSource;
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 <AssetId, _AssetBasedSource>{};
36 35
37 final InternalAnalysisContext _context = 36 final InternalAnalysisContext _context =
38 AnalysisEngine.instance.createAnalysisContext(); 37 AnalysisEngine.instance.createAnalysisContext();
39 38
40 /// 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.
41 Transform _currentTransform; 40 Transform _currentTransform;
42 41
43 /// The currently resolved entry libraries, or null if nothing is resolved. 42 /// The currently resolved entry libraries, or null if nothing is resolved.
44 List<LibraryElement> _entryLibraries; 43 List<LibraryElement> _entryLibraries;
45 Set<LibraryElement> _libraries; 44 Set<LibraryElement> _libraries;
46 45
47 /// Future indicating when this resolver is done in the current phase. 46 /// Future indicating when this resolver is done in the current phase.
48 Future _lastPhaseComplete = new Future.value(); 47 Future _lastPhaseComplete = new Future.value();
49 48
50 /// Completer for wrapping up the current phase. 49 /// Completer for wrapping up the current phase.
51 Completer _currentPhaseComplete; 50 Completer _currentPhaseComplete;
52 51
53 /// Creates a resolver with a given [sdk] implementation for resolving 52 /// Creates a resolver with a given [sdk] implementation for resolving
54 /// `dart:*` imports. 53 /// `dart:*` imports.
55 ResolverImpl(DartSdk sdk, DartUriResolver dartUriResolver, 54 ResolverImpl(DartSdk sdk, DartUriResolver dartUriResolver,
56 {AnalysisOptions options}) { 55 {AnalysisOptions options}) {
57 if (options == null) { 56 if (options == null) {
58 options = new AnalysisOptionsImpl() 57 options = new AnalysisOptionsImpl()
59 ..cacheSize = 256 // # of sources to cache ASTs for.
60 ..preserveComments = false 58 ..preserveComments = false
61 ..analyzeFunctionBodies = true; 59 ..analyzeFunctionBodies = true;
62 } 60 }
63 _context.analysisOptions = options; 61 _context.analysisOptions = options;
64 sdk.context.analysisOptions = options;
65 _context.sourceFactory = 62 _context.sourceFactory =
66 new SourceFactory([dartUriResolver, new _AssetUriResolver(this)]); 63 new SourceFactory([dartUriResolver, new _AssetUriResolver(this)]);
67 } 64 }
68 65
66 @override
67 bool isLibrary(AssetId assetId) {
68 var source = sources[assetId];
69 return source != null && _isLibrary(source);
70 }
71
72 bool _isLibrary(Source source) =>
73 _context.computeKindOf(source) == SourceKind.LIBRARY;
74
75 @override
69 LibraryElement getLibrary(AssetId assetId) { 76 LibraryElement getLibrary(AssetId assetId) {
70 var source = sources[assetId]; 77 var source = sources[assetId];
71 return source == null ? null : _context.computeLibraryElement(source); 78 if (source == null) return null;
79 if (!_isLibrary(source)) return null;
80 return _context.computeLibraryElement(source);
72 } 81 }
73 82
74 Future<Resolver> resolve(Transform transform, [List<AssetId> entryPoints]) { 83 Future<Resolver> resolve(Transform transform,
84 [List<AssetId> entryPoints, bool resolveAllLibraries]) {
75 // Can only have one resolve in progress at a time, so chain the current 85 // Can only have one resolve in progress at a time, so chain the current
76 // resolution to be after the last one. 86 // resolution to be after the last one.
77 var phaseComplete = new Completer(); 87 var phaseComplete = new Completer();
78 var future = _lastPhaseComplete.whenComplete(() { 88 var future = _lastPhaseComplete.whenComplete(() {
79 _currentPhaseComplete = phaseComplete; 89 _currentPhaseComplete = phaseComplete;
80 return _performResolve(transform, 90 return _performResolve(
81 entryPoints == null ? [transform.primaryInput.id] : entryPoints); 91 transform,
92 entryPoints == null ? [transform.primaryInput.id] : entryPoints,
93 resolveAllLibraries);
82 }).then((_) => this); 94 }).then((_) => this);
83 // Advance the lastPhaseComplete to be done when this phase is all done. 95 // Advance the lastPhaseComplete to be done when this phase is all done.
84 _lastPhaseComplete = phaseComplete.future; 96 _lastPhaseComplete = phaseComplete.future;
85 return future; 97 return future;
86 } 98 }
87 99
88 void release() { 100 void release() {
89 if (_currentPhaseComplete == null) { 101 if (_currentPhaseComplete == null) {
90 throw new StateError('Releasing without current lock.'); 102 throw new StateError('Releasing without current lock.');
91 } 103 }
92 _currentPhaseComplete.complete(null); 104 _currentPhaseComplete.complete(null);
93 _currentPhaseComplete = null; 105 _currentPhaseComplete = null;
94 106
95 // Clear out libraries since they should not be referenced after release. 107 // Clear out libraries since they should not be referenced after release.
96 _entryLibraries = null; 108 _entryLibraries = null;
97 _libraries = null; 109 _libraries = null;
98 _currentTransform = null; 110 _currentTransform = null;
99 } 111 }
100 112
101 Future _performResolve(Transform transform, List<AssetId> entryPoints) { 113 Future _performResolve(Transform transform, List<AssetId> entryPoints,
114 bool resolveAllLibraries) {
115 resolveAllLibraries ??= true;
102 if (_currentTransform != null) { 116 if (_currentTransform != null) {
103 throw new StateError('Cannot be accessed by concurrent transforms'); 117 throw new StateError('Cannot be accessed by concurrent transforms');
104 } 118 }
105 _currentTransform = transform; 119 _currentTransform = transform;
106 120
107 // Basic approach is to start at the first file, update it's contents 121 // Basic approach is to start at the first file, update it's contents
108 // and see if it changed, then walk all files accessed by it. 122 // and see if it changed, then walk all files accessed by it.
109 var visited = new Set<AssetId>(); 123 var visited = new Set<AssetId>();
110 var visiting = new FutureGroup(); 124 var visiting = new FutureGroup();
111 var toUpdate = []; 125 var toUpdate = [];
112 126
113 void processAsset(AssetId assetId) { 127 void processAsset(AssetId assetId) {
114 visited.add(assetId); 128 visited.add(assetId);
115 129
116 visiting.add(transform.readInputAsString(assetId).then((contents) { 130 visiting.add(transform.readInputAsString(assetId).then((contents) {
117 var source = sources[assetId]; 131 var source = sources[assetId];
118 if (source == null) { 132 if (source == null) {
119 source = new _AssetBasedSource(assetId, this); 133 source = new AssetBasedSource(assetId, this);
120 sources[assetId] = source; 134 sources[assetId] = source;
121 } 135 }
122 source.updateDependencies(contents); 136 source.updateDependencies(contents);
123 toUpdate.add(new _PendingUpdate(source, contents)); 137 toUpdate.add(new _PendingUpdate(source, contents));
124 source.dependentAssets 138 source.dependentAssets
125 .where((id) => !visited.contains(id)) 139 .where((id) => !visited.contains(id))
126 .forEach(processAsset); 140 .forEach(processAsset);
127 }, onError: (e) { 141 }, onError: (e) {
128 var source = sources[assetId]; 142 var source = sources[assetId];
129 if (source != null && source.exists()) { 143 if (source != null && source.exists()) {
130 _context.applyChanges(new ChangeSet()..removedSource(source)); 144 _context.applyChanges(new ChangeSet()..removedSource(source));
131 sources[assetId].updateContents(null); 145 sources[assetId].updateContents(null);
132 } 146 }
133 })); 147 }));
134 } 148 }
149
135 entryPoints.forEach(processAsset); 150 entryPoints.forEach(processAsset);
136 151
137 // Once we have all asset sources updated with the new contents then 152 // Once we have all asset sources updated with the new contents then
138 // resolve everything. 153 // resolve everything.
139 return visiting.future.then((_) { 154 return visiting.future.then((_) {
140 var changeSet = new ChangeSet(); 155 var changeSet = new ChangeSet();
141 toUpdate.forEach((pending) => pending.apply(changeSet)); 156 toUpdate.forEach((pending) => pending.apply(changeSet));
142 var unreachableAssets =
143 sources.keys.toSet().difference(visited).map((id) => sources[id]);
144 for (var unreachable in unreachableAssets) {
145 changeSet.removedSource(unreachable);
146 unreachable.updateContents(null);
147 sources.remove(unreachable.assetId);
148 }
149 157
150 // Update the analyzer context with the latest sources 158 // Update the analyzer context with the latest sources
151 _context.applyChanges(changeSet); 159 _context.applyChanges(changeSet);
152 // Force resolve each entry point (the getter will ensure the library is 160 // Force resolve each entry point (the getter will ensure the library is
153 // computed first). 161 // computed first).
154 _entryLibraries = entryPoints.map((id) { 162 _entryLibraries = entryPoints.map((id) {
155 var source = sources[id]; 163 var source = sources[id];
156 if (source == null) return null; 164 if (source == null) return null;
165 var kind = _context.computeKindOf(source);
166 if (kind != SourceKind.LIBRARY) return null;
157 return _context.computeLibraryElement(source); 167 return _context.computeLibraryElement(source);
158 }).toList(); 168 }).toList();
169
170 if (resolveAllLibraries) {
171 // Force resolve all other available libraries. As of analyzer > 0.27.1
172 // this is necessary to get resolved constants.
173 var newLibraries = new Set<LibraryElement>();
174 for (var library in libraries) {
175 if (library.source.uri.scheme == 'dart' ||
176 _entryLibraries.contains(library)) {
177 newLibraries.add(library);
178 } else {
179 newLibraries.add(_context
180 .computeLibraryElement(library.definingCompilationUnit.source));
181 }
182 }
183 _libraries = newLibraries;
184 }
159 }); 185 });
160 } 186 }
161 187
162 Iterable<LibraryElement> get libraries { 188 Iterable<LibraryElement> get libraries {
163 if (_libraries == null) { 189 if (_libraries == null) {
164 // Note: we don't use `lib.visibleLibraries` because that excludes the 190 // Note: we don't use `lib.visibleLibraries` because that excludes the
165 // exports seen in the entry libraries. 191 // exports seen in the entry libraries.
166 _libraries = new Set<LibraryElement>(); 192 _libraries = new Set<LibraryElement>();
167 _entryLibraries.forEach(_collectLibraries); 193 _entryLibraries.forEach(_collectLibraries);
168 } 194 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 .evaluate(expression); 255 .evaluate(expression);
230 } 256 }
231 257
232 Uri getImportUri(LibraryElement lib, {AssetId from}) => 258 Uri getImportUri(LibraryElement lib, {AssetId from}) =>
233 _getSourceUri(lib, from: from); 259 _getSourceUri(lib, from: from);
234 260
235 /// Similar to getImportUri but will get the part URI for parts rather than 261 /// Similar to getImportUri but will get the part URI for parts rather than
236 /// the library URI. 262 /// the library URI.
237 Uri _getSourceUri(Element element, {AssetId from}) { 263 Uri _getSourceUri(Element element, {AssetId from}) {
238 var source = element.source; 264 var source = element.source;
239 if (source is _AssetBasedSource) { 265 if (source is AssetBasedSource) {
240 var uriString = assetIdToUri(source.assetId, from: from); 266 var uriString = assetIdToUri(source.assetId, from: from);
241 return uriString != null ? Uri.parse(uriString) : null; 267 return uriString != null ? Uri.parse(uriString) : null;
242 } else if (source is UriAnnotatedSource) { 268 } else if (source is UriAnnotatedSource) {
243 return source.uri; 269 return source.uri;
244 } 270 }
245 // Should not be able to encounter any other source types. 271 // Should not be able to encounter any other source types.
246 throw new StateError('Unable to resolve URI for ${source.runtimeType}'); 272 throw new StateError('Unable to resolve URI for ${source.runtimeType}');
247 } 273 }
248 274
249 AssetId getSourceAssetId(Element element) { 275 AssetId getSourceAssetId(Element element) {
250 var source = element.source; 276 var source = element.source;
251 if (source is _AssetBasedSource) return source.assetId; 277 if (source is AssetBasedSource) return source.assetId;
252 return null; 278 return null;
253 } 279 }
254 280
255 SourceSpan getSourceSpan(Element element) { 281 SourceSpan getSourceSpan(Element element) {
256 var sourceFile = getSourceFile(element); 282 var sourceFile = getSourceFile(element);
257 if (sourceFile == null) return null; 283 if (sourceFile == null) return null;
258 return sourceFile.span(element.node.offset, element.node.end); 284 return sourceFile.span(
285 element.computeNode().offset, element.computeNode().end);
259 } 286 }
260 287
261 TextEditTransaction createTextEditTransaction(Element element) { 288 TextEditTransaction createTextEditTransaction(Element element) {
262 if (element.source is! _AssetBasedSource) return null; 289 if (element.source is! AssetBasedSource) return null;
263 290
264 // Cannot edit unless there is an active transformer. 291 // Cannot edit unless there is an active transformer.
265 if (_currentTransform == null) return null; 292 if (_currentTransform == null) return null;
266 293
267 _AssetBasedSource source = element.source; 294 AssetBasedSource source = element.source;
268 // Cannot modify assets in other packages. 295 // Cannot modify assets in other packages.
269 if (source.assetId.package != _currentTransform.primaryInput.id.package) { 296 if (source.assetId.package != _currentTransform.primaryInput.id.package) {
270 return null; 297 return null;
271 } 298 }
272 299
273 var sourceFile = getSourceFile(element); 300 var sourceFile = getSourceFile(element);
274 if (sourceFile == null) return null; 301 if (sourceFile == null) return null;
275 302
276 return new TextEditTransaction(source.rawContents, sourceFile); 303 return new TextEditTransaction(source.rawContents, sourceFile);
277 } 304 }
278 305
279 /// Gets the SourceFile for the source of the element. 306 /// Gets the SourceFile for the source of the element.
280 SourceFile getSourceFile(Element element) { 307 SourceFile getSourceFile(Element element) {
281 var assetId = getSourceAssetId(element); 308 var assetId = getSourceAssetId(element);
282 if (assetId == null) return null; 309 if (assetId == null) return null;
283 310
284 var importUri = _getSourceUri(element); 311 var importUri = _getSourceUri(element);
285 var spanPath = importUri != null ? importUri.toString() : assetId.path; 312 var spanPath = importUri != null ? importUri.toString() : assetId.path;
286 return new SourceFile(sources[assetId].rawContents, url: spanPath); 313 return new SourceFile(sources[assetId].rawContents, url: spanPath);
287 } 314 }
288 } 315 }
289 316
290 /// Implementation of Analyzer's Source for Barback based assets. 317 /// Implementation of Analyzer's Source for Barback based assets.
291 class _AssetBasedSource extends Source { 318 class AssetBasedSource extends Source {
292
293 /// Asset ID where this source can be found. 319 /// Asset ID where this source can be found.
294 final AssetId assetId; 320 final AssetId assetId;
295 321
296 /// The resolver this is being used in. 322 /// The resolver this is being used in.
297 final ResolverImpl _resolver; 323 final ResolverImpl _resolver;
298 324
299 /// Cache of dependent asset IDs, to avoid re-parsing the AST. 325 /// Cache of dependent asset IDs, to avoid re-parsing the AST.
300 Iterable<AssetId> _dependentAssets; 326 Iterable<AssetId> _dependentAssets;
301 327
302 /// The current revision of the file, incremented only when file changes. 328 /// The current revision of the file, incremented only when file changes.
303 int _revision = 0; 329 int _revision = 0;
304 330
305 /// The file contents. 331 /// The file contents.
306 String _contents; 332 String _contents;
307 333
308 _AssetBasedSource(this.assetId, this._resolver); 334 AssetBasedSource(this.assetId, this._resolver);
309 335
310 /// Update the dependencies of this source. This parses [contents] but avoids 336 /// Update the dependencies of this source. This parses [contents] but avoids
311 /// any analyzer resolution. 337 /// any analyzer resolution.
312 void updateDependencies(String contents) { 338 void updateDependencies(String contents) {
313 if (contents == _contents) return; 339 if (contents == _contents) return;
314 var unit = parseDirectives(contents, suppressErrors: true); 340 var unit = parseDirectives(contents, suppressErrors: true);
315 _dependentAssets = unit.directives 341 _dependentAssets = unit.directives
316 .where((d) => (d is ImportDirective || 342 .where((d) => d is UriBasedDirective)
317 d is PartDirective || 343 .map((d) => _resolve(assetId, (d as UriBasedDirective).uri.stringValue,
318 d is ExportDirective)) 344 _logger, _getSpan(d, contents)))
319 .map((d) => _resolve(
320 assetId, d.uri.stringValue, _logger, _getSpan(d, contents)))
321 .where((id) => id != null) 345 .where((id) => id != null)
322 .toSet(); 346 .toSet();
323 } 347 }
324 348
325 /// Update the contents of this file with [contents]. 349 /// Update the contents of this file with [contents].
326 /// 350 ///
327 /// Returns true if the contents of this asset have changed. 351 /// Returns true if the contents of this asset have changed.
328 bool updateContents(String contents) { 352 bool updateContents(String contents) {
329 if (contents == _contents) return false; 353 if (contents == _contents) return false;
330 _contents = contents; 354 _contents = contents;
(...skipping 17 matching lines...) Expand all
348 /// 372 ///
349 /// Only valid while the resolver is updating assets. 373 /// Only valid while the resolver is updating assets.
350 TransformLogger get _logger => _resolver._currentTransform.logger; 374 TransformLogger get _logger => _resolver._currentTransform.logger;
351 375
352 /// Gets all imports/parts/exports which resolve to assets (non-Dart files). 376 /// Gets all imports/parts/exports which resolve to assets (non-Dart files).
353 Iterable<AssetId> get dependentAssets => _dependentAssets; 377 Iterable<AssetId> get dependentAssets => _dependentAssets;
354 378
355 bool exists() => _contents != null; 379 bool exists() => _contents != null;
356 380
357 bool operator ==(Object other) => 381 bool operator ==(Object other) =>
358 other is _AssetBasedSource && assetId == other.assetId; 382 other is AssetBasedSource && assetId == other.assetId;
359 383
360 int get hashCode => assetId.hashCode; 384 int get hashCode => assetId.hashCode;
361 385
362 void getContentsToReceiver(Source_ContentReceiver receiver) { 386 void getContentsToReceiver(Source_ContentReceiver receiver) {
363 receiver.accept(rawContents, modificationStamp); 387 receiver.accept(rawContents, modificationStamp);
364 } 388 }
365 389
366 String get encoding => 390 String get encoding =>
367 "${uriKind.encoding}${assetId.package}/${assetId.path}"; 391 "${uriKind.encoding}${assetId.package}/${assetId.path}";
368 392
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
430 assetId = _resolve(null, uri.toString(), logger, null); 454 assetId = _resolve(null, uri.toString(), logger, null);
431 if (assetId == null) { 455 if (assetId == null) {
432 logger.error('Unable to resolve asset ID for "$uri"'); 456 logger.error('Unable to resolve asset ID for "$uri"');
433 return null; 457 return null;
434 } 458 }
435 } 459 }
436 var source = _resolver.sources[assetId]; 460 var source = _resolver.sources[assetId];
437 // Analyzer expects that sources which are referenced but do not exist yet 461 // Analyzer expects that sources which are referenced but do not exist yet
438 // still exist, so just make an empty source. 462 // still exist, so just make an empty source.
439 if (source == null) { 463 if (source == null) {
440 source = new _AssetBasedSource(assetId, _resolver); 464 source = new AssetBasedSource(assetId, _resolver);
441 _resolver.sources[assetId] = source; 465 _resolver.sources[assetId] = source;
442 } 466 }
443 return source; 467 return source;
444 } 468 }
445 469
446 Source fromEncoding(UriKind kind, Uri uri) => 470 Source fromEncoding(UriKind kind, Uri uri) =>
447 throw new UnsupportedError('fromEncoding is not supported'); 471 throw new UnsupportedError('fromEncoding is not supported');
448 472
449 Uri restoreAbsolute(Source source) => 473 Uri restoreAbsolute(Source source) =>
450 throw new UnsupportedError('restoreAbsolute is not supported'); 474 throw new UnsupportedError('restoreAbsolute is not supported');
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 * error will be sent to the Future. 555 * error will be sent to the Future.
532 */ 556 */
533 Future<List<E>> get future => _completer.future; 557 Future<List<E>> get future => _completer.future;
534 } 558 }
535 559
536 /// A pending update to notify the resolver that a [Source] has been added or 560 /// A pending update to notify the resolver that a [Source] has been added or
537 /// changed. This is used by the `_performResolve` algorithm above to apply all 561 /// changed. This is used by the `_performResolve` algorithm above to apply all
538 /// changes after it first discovers the transitive closure of files that are 562 /// changes after it first discovers the transitive closure of files that are
539 /// reachable from the sources. 563 /// reachable from the sources.
540 class _PendingUpdate { 564 class _PendingUpdate {
541 _AssetBasedSource source; 565 AssetBasedSource source;
542 String content; 566 String content;
543 567
544 _PendingUpdate(this.source, this.content); 568 _PendingUpdate(this.source, this.content);
545 569
546 void apply(ChangeSet changeSet) { 570 void apply(ChangeSet changeSet) {
547 if (!source.updateContents(content)) return; 571 if (!source.updateContents(content)) return;
548 if (source._revision == 1 && source._contents != null) { 572 if (source._revision == 1 && source._contents != null) {
549 changeSet.addedSource(source); 573 changeSet.addedSource(source);
550 } else { 574 } else {
551 changeSet.changedSource(source); 575 changeSet.changedSource(source);
552 } 576 }
553 } 577 }
554 } 578 }
OLDNEW
« no previous file with comments | « packages/code_transformers/lib/src/resolver.dart ('k') | packages/code_transformers/lib/src/resolvers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698