| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 /// Tracks the shape of the import/export graph and dependencies between files. | 5 /// Tracks the shape of the import/export graph and dependencies between files. |
| 6 library dev_compiler.src.dependency_graph; | 6 library dev_compiler.src.dependency_graph; |
| 7 | 7 |
| 8 import 'dart:collection' show HashSet; | 8 import 'dart:collection' show HashSet; |
| 9 | 9 |
| 10 import 'package:analyzer/analyzer.dart' show parseDirectives; | 10 import 'package:analyzer/analyzer.dart' show parseDirectives; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 final SourceGraph graph; | 83 final SourceGraph graph; |
| 84 | 84 |
| 85 /// Resolved URI for this node. | 85 /// Resolved URI for this node. |
| 86 final Uri uri; | 86 final Uri uri; |
| 87 | 87 |
| 88 /// Resolved source from the analyzer. We let the analyzer internally track | 88 /// Resolved source from the analyzer. We let the analyzer internally track |
| 89 /// for modifications to the source files. | 89 /// for modifications to the source files. |
| 90 Source _source; | 90 Source _source; |
| 91 Source get source => _source; | 91 Source get source => _source; |
| 92 | 92 |
| 93 String get contents => graph._context.getContents(source).data; | 93 String get contents => graph._context.getContents(_source).data; |
| 94 | 94 |
| 95 /// Last stamp read from `source.modificationStamp`. | 95 /// Last stamp read from `source.modificationStamp`. |
| 96 int _lastStamp = 0; | 96 /// This starts at -1, because analyzer uses that for files that don't exist. |
| 97 int _lastStamp = -1; |
| 97 | 98 |
| 98 /// A hash used to help browsers cache the output that would be produced from | 99 /// A hash used to help browsers cache the output that would be produced from |
| 99 /// building this node. | 100 /// building this node. |
| 100 String cachingHash; | 101 String cachingHash; |
| 101 | 102 |
| 102 /// Whether we need to rebuild this source file. | 103 /// Whether we need to rebuild this source file. |
| 103 bool needsRebuild = false; | 104 bool needsRebuild = false; |
| 104 | 105 |
| 105 /// Whether the structure of dependencies from this node (scripts, imports, | 106 /// Whether the structure of dependencies from this node (scripts, imports, |
| 106 /// exports, or parts) changed after we reparsed its contents. | 107 /// exports, or parts) changed after we reparsed its contents. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 117 | 118 |
| 118 SourceNode(this.graph, this.uri, this._source); | 119 SourceNode(this.graph, this.uri, this._source); |
| 119 | 120 |
| 120 /// Check for whether the file has changed and, if so, mark [needsRebuild] and | 121 /// Check for whether the file has changed and, if so, mark [needsRebuild] and |
| 121 /// [structureChanged] as necessary. | 122 /// [structureChanged] as necessary. |
| 122 void update() { | 123 void update() { |
| 123 if (_source == null) { | 124 if (_source == null) { |
| 124 _source = graph._context.sourceFactory.forUri(Uri.encodeFull('$uri')); | 125 _source = graph._context.sourceFactory.forUri(Uri.encodeFull('$uri')); |
| 125 if (_source == null) return; | 126 if (_source == null) return; |
| 126 } | 127 } |
| 127 int newStamp = _source.modificationStamp; | 128 |
| 128 if (newStamp > _lastStamp) { | 129 int newStamp = _source.exists() ? _source.modificationStamp : -1; |
| 130 if (newStamp > _lastStamp || newStamp == -1 && _lastStamp != -1) { |
| 129 // If the timestamp changed, read the file from disk and cache it. | 131 // If the timestamp changed, read the file from disk and cache it. |
| 130 // We don't want the source text to change during compilation. | 132 // We don't want the source text to change during compilation. |
| 131 saveUpdatedContents(); | 133 saveUpdatedContents(); |
| 132 _lastStamp = newStamp; | 134 _lastStamp = newStamp; |
| 133 needsRebuild = true; | 135 needsRebuild = true; |
| 134 } | 136 } |
| 135 } | 137 } |
| 136 | 138 |
| 137 void saveUpdatedContents() {} | 139 void saveUpdatedContents() {} |
| 138 | 140 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 204 newResources.add(graph.nodeFromUri(uri.resolve(tag.attributes['src']))); | 206 newResources.add(graph.nodeFromUri(uri.resolve(tag.attributes['src']))); |
| 205 } | 207 } |
| 206 if (!_same(newResources, resources)) { | 208 if (!_same(newResources, resources)) { |
| 207 structureChanged = true; | 209 structureChanged = true; |
| 208 resources = newResources; | 210 resources = newResources; |
| 209 } | 211 } |
| 210 } | 212 } |
| 211 } | 213 } |
| 212 | 214 |
| 213 void _reportError(SourceGraph graph, String message, Node node) { | 215 void _reportError(SourceGraph graph, String message, Node node) { |
| 214 graph._reporter.enterHtml(source.uri); | 216 graph._reporter.enterHtml(_source.uri); |
| 215 var span = node.sourceSpan; | 217 var span = node.sourceSpan; |
| 216 graph._reporter.log( | 218 graph._reporter.log( |
| 217 new Message(message, Level.SEVERE, span.start.offset, span.end.offset)); | 219 new Message(message, Level.SEVERE, span.start.offset, span.end.offset)); |
| 218 graph._reporter.leaveHtml(); | 220 graph._reporter.leaveHtml(); |
| 219 } | 221 } |
| 220 } | 222 } |
| 221 | 223 |
| 222 /// A node representing a Dart library or part. | 224 /// A node representing a Dart library or part. |
| 223 class DartSourceNode extends SourceNode { | 225 class DartSourceNode extends SourceNode { |
| 224 /// Set of imported libraries (empty for part files). | 226 /// Set of imported libraries (empty for part files). |
| (...skipping 20 matching lines...) Expand all Loading... |
| 245 | 247 |
| 246 LibraryInfo info; | 248 LibraryInfo info; |
| 247 | 249 |
| 248 // TODO(jmesserly): it would be nice to not keep all sources in memory at | 250 // TODO(jmesserly): it would be nice to not keep all sources in memory at |
| 249 // once, but how else can we ensure a consistent view across a given | 251 // once, but how else can we ensure a consistent view across a given |
| 250 // compile? One different from dev_compiler vs analyzer is that our | 252 // compile? One different from dev_compiler vs analyzer is that our |
| 251 // messages later in the compiler need the original source text to print | 253 // messages later in the compiler need the original source text to print |
| 252 // spans. We also read source text ourselves to parse directives. | 254 // spans. We also read source text ourselves to parse directives. |
| 253 // But we could discard it after that point. | 255 // But we could discard it after that point. |
| 254 void saveUpdatedContents() { | 256 void saveUpdatedContents() { |
| 255 graph._context.setContents(source, source.contents.data); | 257 graph._context.setContents(_source, _source.contents.data); |
| 256 } | 258 } |
| 257 | 259 |
| 258 @override | 260 @override |
| 259 void update() { | 261 void update() { |
| 260 super.update(); | 262 super.update(); |
| 261 | 263 |
| 262 if (needsRebuild && contents != null) { | 264 if (needsRebuild) { |
| 263 graph._reporter.clearLibrary(uri); | 265 graph._reporter.clearLibrary(uri); |
| 264 // If the defining compilation-unit changed, the structure might have | 266 // If the defining compilation-unit changed, the structure might have |
| 265 // changed. | 267 // changed. |
| 266 var unit = parseDirectives(contents, name: source.fullName); | 268 var unit = parseDirectives(contents, name: _source.fullName); |
| 267 var newImports = new Set<DartSourceNode>(); | 269 var newImports = new Set<DartSourceNode>(); |
| 268 var newExports = new Set<DartSourceNode>(); | 270 var newExports = new Set<DartSourceNode>(); |
| 269 var newParts = new Set<DartSourceNode>(); | 271 var newParts = new Set<DartSourceNode>(); |
| 270 for (var d in unit.directives) { | 272 for (var d in unit.directives) { |
| 271 // Nothing to do for parts. | 273 // Nothing to do for parts. |
| 272 if (d is PartOfDirective) return; | 274 if (d is PartOfDirective) return; |
| 273 if (d is LibraryDirective) continue; | 275 if (d is LibraryDirective) continue; |
| 274 | 276 |
| 275 // `dart:core` and other similar URLs only contain a name, but it is | 277 // `dart:core` and other similar URLs only contain a name, but it is |
| 276 // meant to be a folder when resolving relative paths from it. | 278 // meant to be a folder when resolving relative paths from it. |
| 277 var targetUri = uri.scheme == 'dart' && uri.pathSegments.length == 1 | 279 var targetUri = uri.scheme == 'dart' && uri.pathSegments.length == 1 |
| 278 ? Uri.parse('$uri/').resolve(d.uri.stringValue) | 280 ? Uri.parse('$uri/').resolve(d.uri.stringValue) |
| 279 : uri.resolve(d.uri.stringValue); | 281 : uri.resolve(d.uri.stringValue); |
| 280 var target = | 282 var target = |
| 281 ParseDartTask.resolveDirective(graph._context, source, d, null); | 283 ParseDartTask.resolveDirective(graph._context, _source, d, null); |
| 282 if (target != null) { | 284 if (target != null) { |
| 283 if (targetUri != target.uri) print(">> ${target.uri} $targetUri"); | 285 if (targetUri != target.uri) print(">> ${target.uri} $targetUri"); |
| 284 } | 286 } |
| 285 var node = graph.nodes.putIfAbsent( | 287 var node = graph.nodes.putIfAbsent( |
| 286 targetUri, () => new DartSourceNode(graph, targetUri, target)); | 288 targetUri, () => new DartSourceNode(graph, targetUri, target)); |
| 287 //var node = graph.nodeFromUri(targetUri); | 289 //var node = graph.nodeFromUri(targetUri); |
| 288 if (node.source == null || !node.source.exists()) { | 290 if (node._source == null || !node._source.exists()) { |
| 289 _reportError(graph, 'File $targetUri not found', unit, d); | 291 _reportError(graph, 'File $targetUri not found', unit, d); |
| 290 } | 292 } |
| 291 | 293 |
| 292 if (d is ImportDirective) { | 294 if (d is ImportDirective) { |
| 293 newImports.add(node); | 295 newImports.add(node); |
| 294 } else if (d is ExportDirective) { | 296 } else if (d is ExportDirective) { |
| 295 newExports.add(node); | 297 newExports.add(node); |
| 296 } else if (d is PartDirective) { | 298 } else if (d is PartDirective) { |
| 297 newParts.add(node); | 299 newParts.add(node); |
| 298 } | 300 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 // However we do a full update to make it easier to adjust when users | 338 // However we do a full update to make it easier to adjust when users |
| 337 // switch a file from a part to a library. | 339 // switch a file from a part to a library. |
| 338 p.update(); | 340 p.update(); |
| 339 if (p.needsRebuild) needsRebuild = true; | 341 if (p.needsRebuild) needsRebuild = true; |
| 340 } | 342 } |
| 341 } | 343 } |
| 342 | 344 |
| 343 void _reportError( | 345 void _reportError( |
| 344 SourceGraph graph, String message, CompilationUnit unit, AstNode node) { | 346 SourceGraph graph, String message, CompilationUnit unit, AstNode node) { |
| 345 graph._reporter | 347 graph._reporter |
| 346 ..enterLibrary(source.uri) | 348 ..enterLibrary(_source.uri) |
| 347 ..enterCompilationUnit(unit, source) | 349 ..enterCompilationUnit(unit, _source) |
| 348 ..log(new Message(message, Level.SEVERE, node.offset, node.end)) | 350 ..log(new Message(message, Level.SEVERE, node.offset, node.end)) |
| 349 ..leaveCompilationUnit() | 351 ..leaveCompilationUnit() |
| 350 ..leaveLibrary(); | 352 ..leaveLibrary(); |
| 351 } | 353 } |
| 352 } | 354 } |
| 353 | 355 |
| 354 /// Represents a runtime resource from our compiler that is needed to run an | 356 /// Represents a runtime resource from our compiler that is needed to run an |
| 355 /// application. | 357 /// application. |
| 356 class ResourceSourceNode extends SourceNode { | 358 class ResourceSourceNode extends SourceNode { |
| 357 ResourceSourceNode(graph, uri, source) : super(graph, uri, source); | 359 ResourceSourceNode(graph, uri, source) : super(graph, uri, source); |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 'dart._interceptors', | 511 'dart._interceptors', |
| 510 'dart._native_typed_data', | 512 'dart._native_typed_data', |
| 511 */ | 513 */ |
| 512 ]; | 514 ]; |
| 513 | 515 |
| 514 /// Runtime files added to applications when running in server mode. | 516 /// Runtime files added to applications when running in server mode. |
| 515 final runtimeFilesForServerMode = new List<String>.from(defaultRuntimeFiles) | 517 final runtimeFilesForServerMode = new List<String>.from(defaultRuntimeFiles) |
| 516 ..addAll(const ['messages_widget.js', 'messages.css']); | 518 ..addAll(const ['messages_widget.js', 'messages.css']); |
| 517 | 519 |
| 518 final _log = new Logger('dev_compiler.dependency_graph'); | 520 final _log = new Logger('dev_compiler.dependency_graph'); |
| OLD | NEW |