| 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 |