| 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; |
| 11 import 'package:analyzer/src/generated/ast.dart' | 11 import 'package:analyzer/src/generated/ast.dart' |
| 12 show | 12 show |
| 13 AstNode, | 13 AstNode, |
| 14 CompilationUnit, | 14 CompilationUnit, |
| 15 ExportDirective, | 15 ExportDirective, |
| 16 Identifier, | 16 Identifier, |
| 17 ImportDirective, | 17 ImportDirective, |
| 18 LibraryDirective, | 18 LibraryDirective, |
| 19 PartDirective, | 19 PartDirective, |
| 20 PartOfDirective; | 20 PartOfDirective; |
| 21 import 'package:analyzer/src/generated/engine.dart' | 21 import 'package:analyzer/src/generated/engine.dart' |
| 22 show ParseDartTask, AnalysisContext; | 22 show ParseDartTask, AnalysisContext; |
| 23 import 'package:analyzer/src/generated/source.dart' show Source, SourceKind; | 23 import 'package:analyzer/src/generated/source.dart' show Source, SourceKind; |
| 24 import 'package:html5lib/dom.dart' show Document, Node; | 24 import 'package:html5lib/dom.dart' show Document, Node; |
| 25 import 'package:html5lib/parser.dart' as html; | 25 import 'package:html5lib/parser.dart' as html; |
| 26 import 'package:logging/logging.dart' show Level; | 26 import 'package:logging/logging.dart' show Logger, Level; |
| 27 import 'package:path/path.dart' as path; | 27 import 'package:path/path.dart' as path; |
| 28 import 'package:source_span/source_span.dart' show SourceSpan; | 28 import 'package:source_span/source_span.dart' show SourceSpan; |
| 29 | 29 |
| 30 import 'info.dart'; | 30 import 'info.dart'; |
| 31 import 'options.dart'; | 31 import 'options.dart'; |
| 32 import 'report.dart'; | 32 import 'report.dart'; |
| 33 import 'utils.dart'; | 33 import 'utils.dart'; |
| 34 | 34 |
| 35 /// Holds references to all source nodes in the import graph. This is mainly | 35 /// Holds references to all source nodes in the import graph. This is mainly |
| 36 /// used as a level of indirection to ensure that each source has a canonical | 36 /// used as a level of indirection to ensure that each source has a canonical |
| 37 /// representation. | 37 /// representation. |
| 38 class SourceGraph { | 38 class SourceGraph { |
| 39 /// All nodes in the source graph. Used to get a canonical representation for | 39 /// All nodes in the source graph. Used to get a canonical representation for |
| 40 /// any node. | 40 /// any node. |
| 41 final Map<Uri, SourceNode> nodes = {}; | 41 final Map<Uri, SourceNode> nodes = {}; |
| 42 | 42 |
| 43 /// Resources included by default on any application. |
| 44 final runtimeDeps = new Set<ResourceSourceNode>(); |
| 45 |
| 43 /// Analyzer used to resolve source files. | 46 /// Analyzer used to resolve source files. |
| 44 final AnalysisContext _context; | 47 final AnalysisContext _context; |
| 45 final CheckerReporter _reporter; | 48 final CheckerReporter _reporter; |
| 46 final CompilerOptions _options; | 49 final CompilerOptions _options; |
| 47 | 50 |
| 48 SourceGraph(this._context, this._reporter, this._options); | 51 SourceGraph(this._context, this._reporter, this._options) { |
| 52 var dir = _options.runtimeDir; |
| 53 if (dir == null) { |
| 54 _log.severe('Runtime dir could not be determined automatically, ' |
| 55 'please specify the --runtime-dir flag on the command line.'); |
| 56 return; |
| 57 } |
| 58 var prefix = path.absolute(dir); |
| 59 var files = |
| 60 _options.serverMode ? runtimeFilesForServerMode : defaultRuntimeFiles; |
| 61 for (var file in files) { |
| 62 runtimeDeps.add(nodeFromUri(path.toUri(path.join(prefix, file)))); |
| 63 } |
| 64 } |
| 49 | 65 |
| 50 /// Node associated with a resolved [uri]. | 66 /// Node associated with a resolved [uri]. |
| 51 SourceNode nodeFromUri(Uri uri) { | 67 SourceNode nodeFromUri(Uri uri) { |
| 52 var uriString = Uri.encodeFull('$uri'); | 68 var uriString = Uri.encodeFull('$uri'); |
| 53 return nodes.putIfAbsent(uri, () { | 69 return nodes.putIfAbsent(uri, () { |
| 54 var source = _context.sourceFactory.forUri(uriString); | 70 var source = _context.sourceFactory.forUri(uriString); |
| 55 var extension = path.extension(uriString); | 71 var extension = path.extension(uriString); |
| 56 if (extension == '.html') { | 72 if (extension == '.html') { |
| 57 return new HtmlSourceNode(uri, source, this); | 73 return new HtmlSourceNode(uri, source, this); |
| 58 } else if (extension == '.dart' || uriString.startsWith('dart:')) { | 74 } else if (extension == '.dart' || uriString.startsWith('dart:')) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 | 133 |
| 118 String toString() { | 134 String toString() { |
| 119 var simpleUri = uri.scheme == 'file' ? path.relative(uri.path) : "$uri"; | 135 var simpleUri = uri.scheme == 'file' ? path.relative(uri.path) : "$uri"; |
| 120 return '[$runtimeType: $simpleUri]'; | 136 return '[$runtimeType: $simpleUri]'; |
| 121 } | 137 } |
| 122 } | 138 } |
| 123 | 139 |
| 124 /// A node representing an entry HTML source file. | 140 /// A node representing an entry HTML source file. |
| 125 class HtmlSourceNode extends SourceNode { | 141 class HtmlSourceNode extends SourceNode { |
| 126 /// Resources included by default on any application. | 142 /// Resources included by default on any application. |
| 127 final runtimeDeps = new Set<ResourceSourceNode>(); | 143 final runtimeDeps; |
| 128 | 144 |
| 129 /// Libraries referred to via script tags. | 145 /// Libraries referred to via script tags. |
| 130 Set<DartSourceNode> scripts = new Set<DartSourceNode>(); | 146 Set<DartSourceNode> scripts = new Set<DartSourceNode>(); |
| 131 | 147 |
| 132 @override | 148 @override |
| 133 Iterable<SourceNode> get allDeps => [scripts, runtimeDeps].expand((e) => e); | 149 Iterable<SourceNode> get allDeps => [scripts, runtimeDeps].expand((e) => e); |
| 134 | 150 |
| 135 @override | 151 @override |
| 136 Iterable<SourceNode> get depsWithoutParts => allDeps; | 152 Iterable<SourceNode> get depsWithoutParts => allDeps; |
| 137 | 153 |
| 138 /// Parsed document, updated whenever [update] is invoked. | 154 /// Parsed document, updated whenever [update] is invoked. |
| 139 Document document; | 155 Document document; |
| 140 | 156 |
| 141 HtmlSourceNode(uri, source, graph) : super(uri, source) { | 157 HtmlSourceNode(Uri uri, Source source, SourceGraph graph) |
| 142 var prefix = 'package:dev_compiler/runtime'; | 158 : runtimeDeps = graph.runtimeDeps, |
| 143 var files = ['harmony_feature_check.js', 'dart_runtime.js', 'dart_core.js']; | 159 super(uri, source); |
| 144 if (graph._options.serverMode) { | |
| 145 files.addAll(const ['messages_widget.js', 'messages.css']); | |
| 146 } | |
| 147 files.forEach((file) { | |
| 148 runtimeDeps.add(graph.nodeFromUri(Uri.parse('$prefix/$file'))); | |
| 149 }); | |
| 150 } | |
| 151 | 160 |
| 152 void update(SourceGraph graph) { | 161 void update(SourceGraph graph) { |
| 153 super.update(graph); | 162 super.update(graph); |
| 154 if (needsRebuild) { | 163 if (needsRebuild) { |
| 155 graph._reporter.clearHtml(uri); | 164 graph._reporter.clearHtml(uri); |
| 156 document = html.parse(source.contents.data, generateSpans: true); | 165 document = html.parse(source.contents.data, generateSpans: true); |
| 157 var newScripts = new Set<DartSourceNode>(); | 166 var newScripts = new Set<DartSourceNode>(); |
| 158 var tags = document.querySelectorAll('script[type="application/dart"]'); | 167 var tags = document.querySelectorAll('script[type="application/dart"]'); |
| 159 for (var script in tags) { | 168 for (var script in tags) { |
| 160 var src = script.attributes['src']; | 169 var src = script.attributes['src']; |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 helper(start); | 437 helper(start); |
| 429 } | 438 } |
| 430 | 439 |
| 431 bool _same(Set a, Set b) => a.length == b.length && a.containsAll(b); | 440 bool _same(Set a, Set b) => a.length == b.length && a.containsAll(b); |
| 432 | 441 |
| 433 /// An error message discovered while parsing the dependencies between files. | 442 /// An error message discovered while parsing the dependencies between files. |
| 434 class DependencyGraphError extends MessageWithSpan { | 443 class DependencyGraphError extends MessageWithSpan { |
| 435 const DependencyGraphError(String message, SourceSpan span) | 444 const DependencyGraphError(String message, SourceSpan span) |
| 436 : super(message, Level.SEVERE, span); | 445 : super(message, Level.SEVERE, span); |
| 437 } | 446 } |
| 447 |
| 448 /// Runtime files added to all applications when running the compiler in the |
| 449 /// command line. |
| 450 const defaultRuntimeFiles = const [ |
| 451 'harmony_feature_check.js', |
| 452 'dart_runtime.js', |
| 453 'dart_core.js' |
| 454 ]; |
| 455 |
| 456 /// Runtime files added to applications when running in server mode. |
| 457 final runtimeFilesForServerMode = new List<String>.from(defaultRuntimeFiles) |
| 458 ..addAll(const ['messages_widget.js', 'messages.css']); |
| 459 |
| 460 final _log = new Logger('dev_compiler.dependency_graph'); |
| OLD | NEW |