Index: test/dependency_graph_test.dart |
diff --git a/test/dependency_graph_test.dart b/test/dependency_graph_test.dart |
index 4ad9c748bcf447164893038a621ab5e2d83a8261..b2a2024e5d622b7a585b04632d5d310f3b607b8f 100644 |
--- a/test/dependency_graph_test.dart |
+++ b/test/dependency_graph_test.dart |
@@ -55,8 +55,7 @@ main() { |
'/a10.dart': 'library a10;', |
}; |
- nodeOf(String filepath, [bool isPart = false]) => |
- graph.nodeFromUri(new Uri.file(filepath), isPart); |
+ nodeOf(String filepath) => graph.nodeFromUri(new Uri.file(filepath)); |
setUp(() { |
/// We completely reset the TestUriResolver to avoid interference between |
@@ -198,6 +197,101 @@ main() { |
expect(node.exports.contains(nodeOf('/a7.dart')), isTrue); |
expect(node.parts.contains(nodeOf('/a8.dart')), isTrue); |
}); |
+ |
+ test('change part to library', () { |
+ var node = nodeOf('/a2.dart'); |
+ node.update(graph); |
+ expect(node.imports.length, 2); |
+ expect(node.exports.length, 1); |
+ expect(node.parts.length, 1); |
+ expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); |
+ expect(node.imports.contains(nodeOf('/a4.dart')), isTrue); |
+ expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); |
+ expect(node.parts.contains(nodeOf('/a6.dart')), isTrue); |
+ |
+ node.source.contents.modificationTime++; |
+ node.source.contents.data = ''' |
+ library a2; |
+ import 'a3.dart'; |
+ import 'a4.dart'; |
+ export 'a5.dart'; |
+ import 'a6.dart'; // changed from part |
+ '''; |
+ var a6 = nodeOf('/a6.dart'); |
+ a6.source.contents.modificationTime++; |
+ a6.source.contents.data = ''; |
+ node.update(graph); |
+ |
+ expect(node.imports.length, 3); |
+ expect(node.exports.length, 1); |
+ expect(node.parts.length, 0); |
+ expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); |
+ expect(node.imports.contains(nodeOf('/a4.dart')), isTrue); |
+ expect(node.imports.contains(nodeOf('/a6.dart')), isTrue); |
+ expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); |
+ |
+ expect(a6.imports.length, 0); |
+ expect(a6.exports.length, 0); |
+ expect(a6.parts.length, 0); |
+ }); |
+ |
+ test('change library to part', () { |
+ var node = nodeOf('/a2.dart'); |
+ var a4 = nodeOf('/a4.dart'); |
+ node.update(graph); |
+ expect(node.imports.length, 2); |
+ expect(node.exports.length, 1); |
+ expect(node.parts.length, 1); |
+ expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); |
+ expect(node.imports.contains(nodeOf('/a4.dart')), isTrue); |
+ expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); |
+ expect(node.parts.contains(nodeOf('/a6.dart')), isTrue); |
+ |
+ a4.update(graph); |
+ expect(a4.imports.length, 0); |
+ expect(a4.exports.length, 1); |
+ expect(a4.parts.length, 0); |
+ |
+ node.source.contents.modificationTime++; |
+ node.source.contents.data = ''' |
+ library a2; |
+ import 'a3.dart'; |
+ part 'a4.dart'; // changed from export |
+ export 'a5.dart'; |
+ part 'a6.dart'; |
+ '''; |
+ node.update(graph); |
+ |
+ expect(node.imports.length, 1); |
+ expect(node.exports.length, 1); |
+ expect(node.parts.length, 2); |
+ expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); |
+ expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); |
+ expect(node.parts.contains(nodeOf('/a4.dart')), isTrue); |
+ expect(node.parts.contains(nodeOf('/a6.dart')), isTrue); |
+ |
+ // Note, technically we never modified the contents of a4 and it contains |
+ // an export. This is invalid Dart, but we'll let the analyzer report that |
+ // error instead of doing so ourselves. |
+ expect(a4.imports.length, 0); |
+ expect(a4.exports.length, 1); |
+ expect(a4.parts.length, 0); |
+ |
+ // And change it back. |
+ node.source.contents.modificationTime++; |
+ node.source.contents.data = ''' |
+ library a2; |
+ import 'a3.dart'; |
+ import 'a4.dart'; // changed again |
+ export 'a5.dart'; |
+ part 'a6.dart'; |
+ '''; |
+ node.update(graph); |
+ expect(node.imports.contains(a4), isTrue); |
+ expect(a4.imports.length, 0); |
+ expect(a4.exports.length, 1); |
+ expect(a4.parts.length, 0); |
+ }); |
}); |
group('local changes', () { |
@@ -220,7 +314,7 @@ main() { |
test('main library in Dart', () { |
var node = nodeOf('/a2.dart'); |
- var partNode = nodeOf('/a6.dart', true); |
+ var partNode = nodeOf('/a6.dart'); |
node.update(graph); |
expect(node.needsRebuild, isTrue); |
node.needsRebuild = false; |
@@ -240,7 +334,7 @@ main() { |
var node = nodeOf('/a2.dart'); |
var importNode = nodeOf('/a3.dart'); |
var exportNode = nodeOf('/a5.dart'); |
- var partNode = nodeOf('/a6.dart', true); |
+ var partNode = nodeOf('/a6.dart'); |
node.update(graph); |
expect(node.needsRebuild, isTrue); |
node.needsRebuild = false; |
@@ -315,7 +409,7 @@ main() { |
var node = nodeOf('/a2.dart'); |
var importNode = nodeOf('/a3.dart'); |
var exportNode = nodeOf('/a5.dart'); |
- var partNode = nodeOf('/a6.dart', true); |
+ var partNode = nodeOf('/a6.dart'); |
node.update(graph); |
expect(node.structureChanged, isTrue); |
node.structureChanged = false; |
@@ -465,7 +559,7 @@ main() { |
| |-- a4.dart [needs-rebuild] [structure-changed] |
| | |-- a10.dart [needs-rebuild] |
| |-- a5.dart [needs-rebuild] |
- | |-- a6.dart [needs-rebuild] |
+ | |-- a6.dart (part) [needs-rebuild] |
'''); |
}); |
@@ -479,7 +573,7 @@ main() { |
| |-- a4.dart [needs-rebuild] [structure-changed] |
| | |-- a10.dart [needs-rebuild] |
| |-- a5.dart [needs-rebuild] |
- | |-- a6.dart [needs-rebuild] |
+ | |-- a6.dart (part) [needs-rebuild] |
'''); |
clearMarks(node); |
expectGraph(node, ''' |
@@ -489,7 +583,7 @@ main() { |
| |-- a4.dart |
| | |-- a10.dart |
| |-- a5.dart |
- | |-- a6.dart |
+ | |-- a6.dart (part) |
'''); |
refreshStructureAndMarks(node, graph); |
@@ -500,7 +594,7 @@ main() { |
| |-- a4.dart |
| | |-- a10.dart |
| |-- a5.dart |
- | |-- a6.dart |
+ | |-- a6.dart (part) |
'''); |
}); |
@@ -519,7 +613,7 @@ main() { |
| |-- a4.dart |
| | |-- a10.dart |
| |-- a5.dart |
- | |-- a6.dart |
+ | |-- a6.dart (part) |
'''); |
}); |
@@ -541,7 +635,7 @@ main() { |
| |-- a5.dart [needs-rebuild] [structure-changed] |
| | |-- a8.dart [needs-rebuild] [structure-changed] |
| | | |-- a8.dart... |
- | |-- a6.dart |
+ | |-- a6.dart (part) |
'''); |
}); |
}); |
@@ -585,7 +679,7 @@ main() { |
| |-- a4.dart |
| | |-- a10.dart |
| |-- a5.dart |
- | |-- a6.dart |
+ | |-- a6.dart (part) |
'''); |
}); |
@@ -714,6 +808,227 @@ main() { |
rebuild(node, graph, buildNoTransitiveChange); |
expect(results, []); |
}); |
+ |
+ group('file upgrades', () { |
+ // Normally upgrading involves two changes: |
+ // (a) change the affected file |
+ // (b) change directive from part to import (or viceversa) |
+ // These could happen in any order and we should reach a consistent state |
+ // in the end. |
+ |
+ test('convert part to a library before updating the import', () { |
+ var node = nodeOf('/index3.html'); |
+ var a2 = nodeOf('/a2.dart'); |
+ var a6 = nodeOf('/a6.dart'); |
+ rebuild(node, graph, buildNoTransitiveChange); |
+ |
+ expectGraph(node, ''' |
+ index3.html |
+ |-- a2.dart |
+ | |-- a3.dart |
+ | |-- a4.dart |
+ | | |-- a10.dart |
+ | |-- a5.dart |
+ | |-- a6.dart (part) |
+ '''); |
+ |
+ // Modify the file first: |
+ a6.source.contents.modificationTime++; |
+ a6.source.contents.data = 'library a6; import "a5.dart";'; |
+ results = []; |
+ rebuild(node, graph, buildNoTransitiveChange); |
+ |
+ // Looks to us like a change in a part, we'll report errors that the |
+ // part is not really a part-file. Note that a6.dart is not included |
+ // below, because we don't build it as a library. |
+ expect(results, ['a2.dart']); |
+ expectGraph(node, ''' |
+ index3.html |
+ |-- a2.dart |
+ | |-- a3.dart |
+ | |-- a4.dart |
+ | | |-- a10.dart |
+ | |-- a5.dart |
+ | |-- a6.dart (part) |
+ '''); |
+ |
+ a2.source.contents.modificationTime++; |
+ a2.source.contents.data = ''' |
+ library a2; |
+ import 'a3.dart'; |
+ import 'a4.dart'; |
+ import 'a6.dart'; // properly import it |
+ export 'a5.dart'; |
+ '''; |
+ results = []; |
+ rebuild(node, graph, buildNoTransitiveChange); |
+ // Note that a6 is now included, because we haven't built it as a |
+ // library until now: |
+ expect(results, ['a6.dart', 'a2.dart', 'index3.html']); |
+ |
+ a6.source.contents.modificationTime++; |
+ results = []; |
+ rebuild(node, graph, buildNoTransitiveChange); |
+ expect(results, ['a6.dart']); |
+ |
+ expectGraph(node, ''' |
+ index3.html |
+ |-- a2.dart |
+ | |-- a3.dart |
+ | |-- a4.dart |
+ | | |-- a10.dart |
+ | |-- a6.dart |
+ | | |-- a5.dart |
+ | |-- a5.dart... |
+ '''); |
+ }); |
+ |
+ test('convert part to a library after updating the import', () { |
+ var node = nodeOf('/index3.html'); |
+ var a2 = nodeOf('/a2.dart'); |
+ var a6 = nodeOf('/a6.dart'); |
+ rebuild(node, graph, buildNoTransitiveChange); |
+ |
+ expectGraph(node, ''' |
+ index3.html |
+ |-- a2.dart |
+ | |-- a3.dart |
+ | |-- a4.dart |
+ | | |-- a10.dart |
+ | |-- a5.dart |
+ | |-- a6.dart (part) |
+ '''); |
+ |
+ a2.source.contents.modificationTime++; |
+ a2.source.contents.data = ''' |
+ library a2; |
+ import 'a3.dart'; |
+ import 'a4.dart'; |
+ import 'a6.dart'; // properly import it |
+ export 'a5.dart'; |
+ '''; |
+ results = []; |
+ rebuild(node, graph, buildNoTransitiveChange); |
+ expect(results, ['a6.dart', 'a2.dart', 'index3.html']); |
+ expectGraph(node, ''' |
+ index3.html |
+ |-- a2.dart |
+ | |-- a3.dart |
+ | |-- a4.dart |
+ | | |-- a10.dart |
+ | |-- a6.dart |
+ | |-- a5.dart |
+ '''); |
+ |
+ a6.source.contents.modificationTime++; |
+ a6.source.contents.data = 'library a6; import "a5.dart";'; |
+ results = []; |
+ rebuild(node, graph, buildNoTransitiveChange); |
+ expect(results, ['a6.dart', 'index3.html']); |
+ expectGraph(node, ''' |
+ index3.html |
+ |-- a2.dart |
+ | |-- a3.dart |
+ | |-- a4.dart |
+ | | |-- a10.dart |
+ | |-- a6.dart |
+ | | |-- a5.dart |
+ | |-- a5.dart... |
+ '''); |
+ }); |
+ |
+ test('disconnect part making it a library', () { |
+ var node = nodeOf('/index3.html'); |
+ var a2 = nodeOf('/a2.dart'); |
+ var a6 = nodeOf('/a6.dart'); |
+ rebuild(node, graph, buildNoTransitiveChange); |
+ |
+ expectGraph(node, ''' |
+ index3.html |
+ |-- a2.dart |
+ | |-- a3.dart |
+ | |-- a4.dart |
+ | | |-- a10.dart |
+ | |-- a5.dart |
+ | |-- a6.dart (part) |
+ '''); |
+ |
+ a2.source.contents.modificationTime++; |
+ a2.source.contents.data = ''' |
+ library a2; |
+ import 'a3.dart'; |
+ import 'a4.dart'; |
+ export 'a5.dart'; |
+ '''; |
+ a6.source.contents.modificationTime++; |
+ a6.source.contents.data = 'library a6; import "a5.dart";'; |
+ results = []; |
+ rebuild(node, graph, buildNoTransitiveChange); |
+ // a6 is not here, it's not reachable so we don't build it. |
+ expect(results, ['a2.dart', 'index3.html']); |
+ expectGraph(node, ''' |
+ index3.html |
+ |-- a2.dart |
+ | |-- a3.dart |
+ | |-- a4.dart |
+ | | |-- a10.dart |
+ | |-- a5.dart |
+ '''); |
+ }); |
+ |
+ test('convert a library to a part', () { |
+ var node = nodeOf('/index3.html'); |
+ var a2 = nodeOf('/a2.dart'); |
+ var a5 = nodeOf('/a5.dart'); |
+ rebuild(node, graph, buildNoTransitiveChange); |
+ |
+ expectGraph(node, ''' |
+ index3.html |
+ |-- a2.dart |
+ | |-- a3.dart |
+ | |-- a4.dart |
+ | | |-- a10.dart |
+ | |-- a5.dart |
+ | |-- a6.dart (part) |
+ '''); |
+ |
+ a2.source.contents.modificationTime++; |
+ a2.source.contents.data = ''' |
+ library a2; |
+ import 'a3.dart'; |
+ import 'a4.dart'; |
+ part 'a5.dart'; // make it a part |
+ part 'a6.dart'; |
+ '''; |
+ results = []; |
+ rebuild(node, graph, buildNoTransitiveChange); |
+ expect(results, ['a2.dart', 'index3.html']); |
+ expectGraph(node, ''' |
+ index3.html |
+ |-- a2.dart |
+ | |-- a3.dart |
+ | |-- a4.dart |
+ | | |-- a10.dart |
+ | |-- a5.dart (part) |
+ | |-- a6.dart (part) |
+ '''); |
+ |
+ a5.source.contents.modificationTime++; |
+ a5.source.contents.data = 'part of a2;'; |
+ results = []; |
+ rebuild(node, graph, buildNoTransitiveChange); |
+ expect(results, ['a2.dart']); |
+ expectGraph(node, ''' |
+ index3.html |
+ |-- a2.dart |
+ | |-- a3.dart |
+ | |-- a4.dart |
+ | | |-- a10.dart |
+ | |-- a5.dart (part) |
+ | |-- a6.dart (part) |
+ '''); |
+ }); |
+ }); |
}); |
} |
@@ -742,7 +1057,19 @@ printReachable(SourceNode node) { |
..write(n.needsRebuild ? '[needs-rebuild] ' : '') |
..write(n.structureChanged ? '[structure-changed] ' : ' ') |
..write('\n'); |
- n.directDeps.forEach((e) => helper(e, indent: indent + 1)); |
+ n.depsWithoutParts.forEach((e) => helper(e, indent: indent + 1)); |
+ if (n is DartSourceNode) { |
+ n.parts.forEach((e) { |
+ sb |
+ ..write("| " * indent) |
+ ..write("|-- ") |
+ ..write(nameFor(e)) |
+ ..write(" (part) ") |
+ ..write(e.needsRebuild ? '[needs-rebuild] ' : '') |
+ ..write(e.structureChanged ? '[structure-changed] ' : ' ') |
+ ..write('\n'); |
+ }); |
+ } |
} |
helper(node); |
return sb.toString(); |