| 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, HashMap; | 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; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 190 var reporter = graph._reporter; | 190 var reporter = graph._reporter; |
| 191 if (reporter is SummaryReporter) { | 191 if (reporter is SummaryReporter) { |
| 192 reporter.clearHtml(uri); | 192 reporter.clearHtml(uri); |
| 193 } | 193 } |
| 194 document = html.parse(contents, generateSpans: true); | 194 document = html.parse(contents, generateSpans: true); |
| 195 var newScripts = new Set<DartSourceNode>(); | 195 var newScripts = new Set<DartSourceNode>(); |
| 196 var tags = document.querySelectorAll('script[type="application/dart"]'); | 196 var tags = document.querySelectorAll('script[type="application/dart"]'); |
| 197 for (var script in tags) { | 197 for (var script in tags) { |
| 198 var src = script.attributes['src']; | 198 var src = script.attributes['src']; |
| 199 if (src == null) { | 199 if (src == null) { |
| 200 _reportError(graph, 'inlined script tags not supported at this time ' | 200 _reportError( |
| 201 graph, |
| 202 'inlined script tags not supported at this time ' |
| 201 '(see https://github.com/dart-lang/dart-dev-compiler/issues/54).', | 203 '(see https://github.com/dart-lang/dart-dev-compiler/issues/54).', |
| 202 script); | 204 script); |
| 203 continue; | 205 continue; |
| 204 } | 206 } |
| 205 DartSourceNode node = graph.nodeFromUri(uri.resolve(src)); | 207 DartSourceNode node = graph.nodeFromUri(uri.resolve(src)); |
| 206 if (node == null || !node.source.exists()) { | 208 if (node == null || !node.source.exists()) { |
| 207 _reportError(graph, 'Script file $src not found', script); | 209 _reportError(graph, 'Script file $src not found', script); |
| 208 } | 210 } |
| 209 if (node != null) newScripts.add(node); | 211 if (node != null) newScripts.add(node); |
| 210 } | 212 } |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 // API may be affected by transitive changes. The re-export case is just one | 447 // API may be affected by transitive changes. The re-export case is just one |
| 446 // of those transitive cases, but is not sufficient. See | 448 // of those transitive cases, but is not sufficient. See |
| 447 // https://github.com/dart-lang/dev_compiler/issues/76 | 449 // https://github.com/dart-lang/dev_compiler/issues/76 |
| 448 var apiChangeDetected = new HashSet<SourceNode>(); | 450 var apiChangeDetected = new HashSet<SourceNode>(); |
| 449 bool htmlNeedsRebuild = false; | 451 bool htmlNeedsRebuild = false; |
| 450 | 452 |
| 451 bool shouldBuildNode(SourceNode n) { | 453 bool shouldBuildNode(SourceNode n) { |
| 452 if (n.needsRebuild) return true; | 454 if (n.needsRebuild) return true; |
| 453 if (n is HtmlSourceNode) return htmlNeedsRebuild; | 455 if (n is HtmlSourceNode) return htmlNeedsRebuild; |
| 454 if (n is ResourceSourceNode) return false; | 456 if (n is ResourceSourceNode) return false; |
| 455 return (n as DartSourceNode).imports | 457 return (n as DartSourceNode) |
| 458 .imports |
| 456 .any((i) => apiChangeDetected.contains(i)); | 459 .any((i) => apiChangeDetected.contains(i)); |
| 457 } | 460 } |
| 458 | 461 |
| 459 visitInPostOrder(start, (n) { | 462 visitInPostOrder( |
| 460 if (n.structureChanged) htmlNeedsRebuild = true; | 463 start, |
| 461 if (shouldBuildNode(n)) { | 464 (n) { |
| 462 var oldHash = n.cachingHash; | 465 if (n.structureChanged) htmlNeedsRebuild = true; |
| 463 if (build(n)) apiChangeDetected.add(n); | 466 if (shouldBuildNode(n)) { |
| 464 if (oldHash != n.cachingHash) htmlNeedsRebuild = true; | 467 var oldHash = n.cachingHash; |
| 465 } else if (n is DartSourceNode && | 468 if (build(n)) apiChangeDetected.add(n); |
| 466 n.exports.any((e) => apiChangeDetected.contains(e))) { | 469 if (oldHash != n.cachingHash) htmlNeedsRebuild = true; |
| 467 apiChangeDetected.add(n); | 470 } else if (n is DartSourceNode && |
| 468 } | 471 n.exports.any((e) => apiChangeDetected.contains(e))) { |
| 469 n.needsRebuild = false; | 472 apiChangeDetected.add(n); |
| 470 n.structureChanged = false; | 473 } |
| 471 if (n is DartSourceNode) { | 474 n.needsRebuild = false; |
| 472 // Note: clearing out flags in the parts could be a problem if someone | 475 n.structureChanged = false; |
| 473 // tries to use a file both as a part and a library at the same time. | 476 if (n is DartSourceNode) { |
| 474 // In that case, we might not correctly propagate changes in the places | 477 // Note: clearing out flags in the parts could be a problem if someone |
| 475 // where it is used as a library. Technically it's not allowed to have a | 478 // tries to use a file both as a part and a library at the same time. |
| 476 // file as a part and a library at once, and the analyzer should report an | 479 // In that case, we might not correctly propagate changes in the |
| 477 // error in that case. | 480 // places where it is used as a library. |
| 478 n.parts.forEach((p) => p.needsRebuild = p.structureChanged = false); | 481 // Technically it's not allowed to have a file as a part and a library |
| 479 } | 482 // at once, and the analyzer should report an error in that case. |
| 480 }, includeParts: false); | 483 n.parts.forEach((p) => p.needsRebuild = p.structureChanged = false); |
| 484 } |
| 485 }, |
| 486 includeParts: false); |
| 481 } | 487 } |
| 482 | 488 |
| 483 /// Helper that runs [action] on nodes reachable from [start] in pre-order. | 489 /// Helper that runs [action] on nodes reachable from [start] in pre-order. |
| 484 visitInPreOrder(SourceNode start, void action(SourceNode node), | 490 visitInPreOrder(SourceNode start, void action(SourceNode node), |
| 485 {bool includeParts: false}) { | 491 {bool includeParts: false}) { |
| 486 var seen = new HashSet<SourceNode>(); | 492 var seen = new HashSet<SourceNode>(); |
| 487 helper(SourceNode node) { | 493 helper(SourceNode node) { |
| 488 if (!seen.add(node)) return; | 494 if (!seen.add(node)) return; |
| 489 action(node); | 495 action(node); |
| 490 var deps = includeParts ? node.allDeps : node.depsWithoutParts; | 496 var deps = includeParts ? node.allDeps : node.depsWithoutParts; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 502 var deps = includeParts ? node.allDeps : node.depsWithoutParts; | 508 var deps = includeParts ? node.allDeps : node.depsWithoutParts; |
| 503 deps.forEach(helper); | 509 deps.forEach(helper); |
| 504 action(node); | 510 action(node); |
| 505 } | 511 } |
| 506 helper(start); | 512 helper(start); |
| 507 } | 513 } |
| 508 | 514 |
| 509 bool _same(Set a, Set b) => a.length == b.length && a.containsAll(b); | 515 bool _same(Set a, Set b) => a.length == b.length && a.containsAll(b); |
| 510 | 516 |
| 511 final _log = new Logger('dev_compiler.dependency_graph'); | 517 final _log = new Logger('dev_compiler.dependency_graph'); |
| OLD | NEW |