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, HashMap; |
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:html/dom.dart' show Document, Node; | 24 import 'package:html/dom.dart' show Document, Node, Element; |
25 import 'package:html/parser.dart' as html; | 25 import 'package:html/parser.dart' as html; |
26 import 'package:logging/logging.dart' show Logger, 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 | 28 |
29 import 'info.dart'; | 29 import 'info.dart'; |
30 import 'options.dart'; | 30 import 'options.dart'; |
31 import 'report.dart'; | 31 import 'report.dart'; |
32 | 32 |
33 /// Holds references to all source nodes in the import graph. This is mainly | 33 /// Holds references to all source nodes in the import graph. This is mainly |
34 /// used as a level of indirection to ensure that each source has a canonical | 34 /// used as a level of indirection to ensure that each source has a canonical |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 @override | 160 @override |
161 Iterable<SourceNode> get allDeps => | 161 Iterable<SourceNode> get allDeps => |
162 [scripts, resources, runtimeDeps].expand((e) => e); | 162 [scripts, resources, runtimeDeps].expand((e) => e); |
163 | 163 |
164 @override | 164 @override |
165 Iterable<SourceNode> get depsWithoutParts => allDeps; | 165 Iterable<SourceNode> get depsWithoutParts => allDeps; |
166 | 166 |
167 /// Parsed document, updated whenever [update] is invoked. | 167 /// Parsed document, updated whenever [update] is invoked. |
168 Document document; | 168 Document document; |
169 | 169 |
| 170 /// Tracks resource files referenced from HTML nodes, e.g. |
| 171 /// `<link rel=stylesheet href=...>` and `<img src=...>` |
| 172 final htmlResourceNodes = new HashMap<Element, ResourceSourceNode>(); |
| 173 |
170 HtmlSourceNode(SourceGraph graph, Uri uri, Source source) | 174 HtmlSourceNode(SourceGraph graph, Uri uri, Source source) |
171 : runtimeDeps = graph.runtimeDeps, | 175 : runtimeDeps = graph.runtimeDeps, |
172 super(graph, uri, source); | 176 super(graph, uri, source); |
173 | 177 |
174 @override | 178 @override |
175 void update() { | 179 void update() { |
176 super.update(); | 180 super.update(); |
177 if (needsRebuild) { | 181 if (needsRebuild) { |
178 graph._reporter.clearHtml(uri); | 182 graph._reporter.clearHtml(uri); |
179 document = html.parse(contents, generateSpans: true); | 183 document = html.parse(contents, generateSpans: true); |
(...skipping 12 matching lines...) Expand all Loading... |
192 _reportError(graph, 'Script file $src not found', script); | 196 _reportError(graph, 'Script file $src not found', script); |
193 } | 197 } |
194 if (node != null) newScripts.add(node); | 198 if (node != null) newScripts.add(node); |
195 } | 199 } |
196 | 200 |
197 if (!_same(newScripts, scripts)) { | 201 if (!_same(newScripts, scripts)) { |
198 structureChanged = true; | 202 structureChanged = true; |
199 scripts = newScripts; | 203 scripts = newScripts; |
200 } | 204 } |
201 | 205 |
| 206 // TODO(jmesserly): simplify the design here. Ideally we wouldn't need |
| 207 // to track user-defined CSS, images, etc. Also we don't have a clear |
| 208 // way to distinguish runtime injected resources, like messages.css, from |
| 209 // user-defined files. |
| 210 htmlResourceNodes.clear(); |
202 var newResources = new Set<SourceNode>(); | 211 var newResources = new Set<SourceNode>(); |
203 for (var resource in graph.resources) { | 212 for (var resource in graph.resources) { |
204 newResources.add(graph.nodeFromUri(uri.resolve(resource))); | 213 newResources.add(graph.nodeFromUri(uri.resolve(resource))); |
205 } | 214 } |
206 for (var tag in document.querySelectorAll('link[rel="stylesheet"]')) { | 215 for (var tag in document.querySelectorAll('link[rel="stylesheet"]')) { |
207 newResources | 216 var res = graph.nodeFromUri(uri.resolve(tag.attributes['href'])); |
208 .add(graph.nodeFromUri(uri.resolve(tag.attributes['href']))); | 217 htmlResourceNodes[tag] = res; |
| 218 newResources.add(res); |
209 } | 219 } |
210 for (var tag in document.querySelectorAll('img')) { | 220 for (var tag in document.querySelectorAll('img[src]')) { |
211 newResources.add(graph.nodeFromUri(uri.resolve(tag.attributes['src']))); | 221 var res = graph.nodeFromUri(uri.resolve(tag.attributes['src'])); |
| 222 htmlResourceNodes[tag] = res; |
| 223 newResources.add(res); |
212 } | 224 } |
213 if (!_same(newResources, resources)) { | 225 if (!_same(newResources, resources)) { |
214 structureChanged = true; | 226 structureChanged = true; |
215 resources = newResources; | 227 resources = newResources; |
216 } | 228 } |
217 } | 229 } |
218 } | 230 } |
219 | 231 |
220 void _reportError(SourceGraph graph, String message, Node node) { | 232 void _reportError(SourceGraph graph, String message, Node node) { |
221 graph._reporter.enterHtml(_source.uri); | 233 graph._reporter.enterHtml(_source.uri); |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 'dart._interceptors', | 528 'dart._interceptors', |
517 'dart._native_typed_data', | 529 'dart._native_typed_data', |
518 */ | 530 */ |
519 ]; | 531 ]; |
520 | 532 |
521 /// Runtime files added to applications when running in server mode. | 533 /// Runtime files added to applications when running in server mode. |
522 final runtimeFilesForServerMode = new List<String>.from(defaultRuntimeFiles) | 534 final runtimeFilesForServerMode = new List<String>.from(defaultRuntimeFiles) |
523 ..addAll(const ['messages_widget.js', 'messages.css']); | 535 ..addAll(const ['messages_widget.js', 'messages.css']); |
524 | 536 |
525 final _log = new Logger('dev_compiler.dependency_graph'); | 537 final _log = new Logger('dev_compiler.dependency_graph'); |
OLD | NEW |