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 library dev_compiler.test.dependency_graph_test; | 5 library dev_compiler.test.dependency_graph_test; |
6 | 6 |
| 7 import 'package:analyzer/file_system/file_system.dart'; |
| 8 import 'package:analyzer/file_system/memory_file_system.dart'; |
| 9 import 'package:analyzer/src/generated/source.dart'; |
7 import 'package:unittest/unittest.dart'; | 10 import 'package:unittest/unittest.dart'; |
8 | 11 |
9 import 'package:dev_compiler/src/checker/dart_sdk.dart' | 12 import 'package:dev_compiler/src/checker/dart_sdk.dart' |
10 show mockSdkSources, dartSdkDirectory; | 13 show mockSdkSources, dartSdkDirectory; |
11 import 'package:dev_compiler/src/in_memory.dart'; | |
12 import 'package:dev_compiler/src/options.dart'; | 14 import 'package:dev_compiler/src/options.dart'; |
13 import 'package:dev_compiler/src/checker/resolver.dart'; | 15 import 'package:dev_compiler/src/checker/resolver.dart'; |
14 import 'package:dev_compiler/src/dependency_graph.dart'; | 16 import 'package:dev_compiler/src/dependency_graph.dart'; |
15 import 'package:dev_compiler/src/report.dart'; | 17 import 'package:dev_compiler/src/report.dart'; |
| 18 import 'package:dev_compiler/src/testing.dart'; |
16 import 'package:path/path.dart' as path; | 19 import 'package:path/path.dart' as path; |
17 | 20 |
18 import 'test_util.dart'; | 21 import 'test_util.dart'; |
19 | 22 |
20 void main() { | 23 void main() { |
21 configureTest(); | 24 configureTest(); |
22 | 25 |
23 var options = new CompilerOptions(runtimeDir: '/dev_compiler_runtime/'); | 26 var options = new CompilerOptions(runtimeDir: '/dev_compiler_runtime/'); |
24 var testUriResolver; | 27 MemoryResourceProvider testResourceProvider; |
| 28 ResourceUriResolver testUriResolver; |
25 var context; | 29 var context; |
26 var graph; | 30 var graph; |
27 | 31 |
28 /// Initial values for test files | 32 /// Initial values for test files |
29 var testFiles = { | 33 var testFiles = { |
30 '/index1.html': ''' | 34 '/index1.html': ''' |
31 <script src="foo.js"></script> | 35 <script src="foo.js"></script> |
32 ''', | 36 ''', |
33 '/index2.html': ''' | 37 '/index2.html': ''' |
34 <script type="application/dart" src="a1.dart"></script> | 38 <script type="application/dart" src="a1.dart"></script> |
(...skipping 19 matching lines...) Expand all Loading... |
54 '/a8.dart': 'library a8; import "a8.dart";', | 58 '/a8.dart': 'library a8; import "a8.dart";', |
55 '/a9.dart': 'library a9; import "a8.dart";', | 59 '/a9.dart': 'library a9; import "a8.dart";', |
56 '/a10.dart': 'library a10;', | 60 '/a10.dart': 'library a10;', |
57 }; | 61 }; |
58 | 62 |
59 nodeOf(String filepath) => graph.nodeFromUri(new Uri.file(filepath)); | 63 nodeOf(String filepath) => graph.nodeFromUri(new Uri.file(filepath)); |
60 | 64 |
61 setUp(() { | 65 setUp(() { |
62 /// We completely reset the TestUriResolver to avoid interference between | 66 /// We completely reset the TestUriResolver to avoid interference between |
63 /// tests (since some tests modify the state of the files). | 67 /// tests (since some tests modify the state of the files). |
64 testUriResolver = new InMemoryUriResolver(testFiles); | 68 testResourceProvider = createTestResourceProvider(testFiles); |
| 69 testUriResolver = new ResourceUriResolver(testResourceProvider); |
65 context = new TypeResolver.fromMock(mockSdkSources, options, | 70 context = new TypeResolver.fromMock(mockSdkSources, options, |
66 otherResolvers: [testUriResolver]).context; | 71 otherResolvers: [testUriResolver]).context; |
67 graph = new SourceGraph(context, new LogReporter(context), options); | 72 graph = new SourceGraph(context, new LogReporter(context), options); |
68 }); | 73 }); |
69 | 74 |
| 75 updateFile(Source source, [String newContents]) { |
| 76 var path = testResourceProvider.pathContext.fromUri(source.uri); |
| 77 if (newContents == null) newContents = source.contents.data; |
| 78 testResourceProvider.updateFile(path, newContents); |
| 79 } |
| 80 |
70 group('HTML deps', () { | 81 group('HTML deps', () { |
71 test('initial deps', () { | 82 test('initial deps', () { |
72 var i1 = nodeOf('/index1.html'); | 83 var i1 = nodeOf('/index1.html'); |
73 var i2 = nodeOf('/index2.html'); | 84 var i2 = nodeOf('/index2.html'); |
74 expect(i1.scripts.length, 0); | 85 expect(i1.scripts.length, 0); |
75 expect(i2.scripts.length, 0); | 86 expect(i2.scripts.length, 0); |
76 i1.update(); | 87 i1.update(); |
77 i2.update(); | 88 i2.update(); |
78 expect(i1.scripts.length, 0); | 89 expect(i1.scripts.length, 0); |
79 expect(i2.scripts.length, 1); | 90 expect(i2.scripts.length, 1); |
80 expect(i2.scripts.first, nodeOf('/a1.dart')); | 91 expect(i2.scripts.first, nodeOf('/a1.dart')); |
81 }); | 92 }); |
82 | 93 |
83 test('add a dep', () { | 94 test('add a dep', () { |
84 // After initial load, dependencies are 0: | 95 // After initial load, dependencies are 0: |
85 var node = nodeOf('/index1.html'); | 96 var node = nodeOf('/index1.html'); |
86 node.update(); | 97 node.update(); |
87 expect(node.scripts.length, 0); | 98 expect(node.scripts.length, 0); |
88 | 99 |
89 // Adding the dependency is discovered on the next round of updates: | 100 // Adding the dependency is discovered on the next round of updates: |
90 node.source.contents.modificationTime++; | 101 updateFile(node.source, |
91 node.source.contents.data = | 102 '<script type="application/dart" src="a2.dart"></script>'); |
92 '<script type="application/dart" src="a2.dart"></script>'; | |
93 expect(node.scripts.length, 0); | 103 expect(node.scripts.length, 0); |
94 node.update(); | 104 node.update(); |
95 expect(node.scripts.length, 1); | 105 expect(node.scripts.length, 1); |
96 expect(node.scripts.first, nodeOf('/a2.dart')); | 106 expect(node.scripts.first, nodeOf('/a2.dart')); |
97 }); | 107 }); |
98 | 108 |
99 test('add more deps', () { | 109 test('add more deps', () { |
100 // After initial load, dependencies are 1: | 110 // After initial load, dependencies are 1: |
101 var node = nodeOf('/index2.html'); | 111 var node = nodeOf('/index2.html'); |
102 node.update(); | 112 node.update(); |
103 expect(node.scripts.length, 1); | 113 expect(node.scripts.length, 1); |
104 expect(node.scripts.first, nodeOf('/a1.dart')); | 114 expect(node.scripts.first, nodeOf('/a1.dart')); |
105 | 115 |
106 node.source.contents.modificationTime++; | 116 updateFile(node.source, node.source.contents.data + |
107 node.source.contents.data += | 117 '<script type="application/dart" src="a2.dart"></script>'); |
108 '<script type="application/dart" src="a2.dart"></script>'; | |
109 expect(node.scripts.length, 1); | 118 expect(node.scripts.length, 1); |
110 node.update(); | 119 node.update(); |
111 expect(node.scripts.length, 2); | 120 expect(node.scripts.length, 2); |
112 expect(node.scripts.first, nodeOf('/a1.dart')); | 121 expect(node.scripts.first, nodeOf('/a1.dart')); |
113 expect(node.scripts.last, nodeOf('/a2.dart')); | 122 expect(node.scripts.last, nodeOf('/a2.dart')); |
114 }); | 123 }); |
115 | 124 |
116 test('remove all deps', () { | 125 test('remove all deps', () { |
117 // After initial load, dependencies are 1: | 126 // After initial load, dependencies are 1: |
118 var node = nodeOf('/index2.html'); | 127 var node = nodeOf('/index2.html'); |
119 node.update(); | 128 node.update(); |
120 expect(node.scripts.length, 1); | 129 expect(node.scripts.length, 1); |
121 expect(node.scripts.first, nodeOf('/a1.dart')); | 130 expect(node.scripts.first, nodeOf('/a1.dart')); |
122 | 131 |
123 // Removing the dependency is discovered on the next round of updates: | 132 // Removing the dependency is discovered on the next round of updates: |
124 node.source.contents.modificationTime++; | 133 updateFile(node.source, ''); |
125 node.source.contents.data = ''; | |
126 expect(node.scripts.length, 1); | 134 expect(node.scripts.length, 1); |
127 node.update(); | 135 node.update(); |
128 expect(node.scripts.length, 0); | 136 expect(node.scripts.length, 0); |
129 }); | 137 }); |
130 }); | 138 }); |
131 | 139 |
132 group('Dart deps', () { | 140 group('Dart deps', () { |
133 test('initial deps', () { | 141 test('initial deps', () { |
134 var a1 = nodeOf('/a1.dart'); | 142 var a1 = nodeOf('/a1.dart'); |
135 var a2 = nodeOf('/a2.dart'); | 143 var a2 = nodeOf('/a2.dart'); |
(...skipping 19 matching lines...) Expand all Loading... |
155 expect(a2.parts.contains(nodeOf('/a6.dart')), isTrue); | 163 expect(a2.parts.contains(nodeOf('/a6.dart')), isTrue); |
156 }); | 164 }); |
157 | 165 |
158 test('add deps', () { | 166 test('add deps', () { |
159 var node = nodeOf('/a1.dart'); | 167 var node = nodeOf('/a1.dart'); |
160 node.update(); | 168 node.update(); |
161 expect(node.imports.length, 0); | 169 expect(node.imports.length, 0); |
162 expect(node.exports.length, 0); | 170 expect(node.exports.length, 0); |
163 expect(node.parts.length, 0); | 171 expect(node.parts.length, 0); |
164 | 172 |
165 node.source.contents.modificationTime++; | 173 updateFile( |
166 node.source.contents.data = | 174 node.source, 'import "a3.dart"; export "a5.dart"; part "a8.dart";'); |
167 'import "a3.dart"; export "a5.dart"; part "a8.dart";'; | |
168 node.update(); | 175 node.update(); |
169 | 176 |
170 expect(node.imports.length, 1); | 177 expect(node.imports.length, 1); |
171 expect(node.exports.length, 1); | 178 expect(node.exports.length, 1); |
172 expect(node.parts.length, 1); | 179 expect(node.parts.length, 1); |
173 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); | 180 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); |
174 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); | 181 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); |
175 expect(node.parts.contains(nodeOf('/a8.dart')), isTrue); | 182 expect(node.parts.contains(nodeOf('/a8.dart')), isTrue); |
176 }); | 183 }); |
177 | 184 |
178 test('remove deps', () { | 185 test('remove deps', () { |
179 var node = nodeOf('/a2.dart'); | 186 var node = nodeOf('/a2.dart'); |
180 node.update(); | 187 node.update(); |
181 expect(node.imports.length, 2); | 188 expect(node.imports.length, 2); |
182 expect(node.exports.length, 1); | 189 expect(node.exports.length, 1); |
183 expect(node.parts.length, 1); | 190 expect(node.parts.length, 1); |
184 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); | 191 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); |
185 expect(node.imports.contains(nodeOf('/a4.dart')), isTrue); | 192 expect(node.imports.contains(nodeOf('/a4.dart')), isTrue); |
186 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); | 193 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); |
187 expect(node.parts.contains(nodeOf('/a6.dart')), isTrue); | 194 expect(node.parts.contains(nodeOf('/a6.dart')), isTrue); |
188 | 195 |
189 node.source.contents.modificationTime++; | 196 updateFile( |
190 node.source.contents.data = | 197 node.source, 'import "a3.dart"; export "a7.dart"; part "a8.dart";'); |
191 'import "a3.dart"; export "a7.dart"; part "a8.dart";'; | |
192 node.update(); | 198 node.update(); |
193 | 199 |
194 expect(node.imports.length, 1); | 200 expect(node.imports.length, 1); |
195 expect(node.exports.length, 1); | 201 expect(node.exports.length, 1); |
196 expect(node.parts.length, 1); | 202 expect(node.parts.length, 1); |
197 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); | 203 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); |
198 expect(node.exports.contains(nodeOf('/a7.dart')), isTrue); | 204 expect(node.exports.contains(nodeOf('/a7.dart')), isTrue); |
199 expect(node.parts.contains(nodeOf('/a8.dart')), isTrue); | 205 expect(node.parts.contains(nodeOf('/a8.dart')), isTrue); |
200 }); | 206 }); |
201 | 207 |
202 test('change part to library', () { | 208 test('change part to library', () { |
203 var node = nodeOf('/a2.dart'); | 209 var node = nodeOf('/a2.dart'); |
204 node.update(); | 210 node.update(); |
205 expect(node.imports.length, 2); | 211 expect(node.imports.length, 2); |
206 expect(node.exports.length, 1); | 212 expect(node.exports.length, 1); |
207 expect(node.parts.length, 1); | 213 expect(node.parts.length, 1); |
208 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); | 214 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); |
209 expect(node.imports.contains(nodeOf('/a4.dart')), isTrue); | 215 expect(node.imports.contains(nodeOf('/a4.dart')), isTrue); |
210 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); | 216 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); |
211 expect(node.parts.contains(nodeOf('/a6.dart')), isTrue); | 217 expect(node.parts.contains(nodeOf('/a6.dart')), isTrue); |
212 | 218 |
213 node.source.contents.modificationTime++; | 219 updateFile(node.source, ''' |
214 node.source.contents.data = ''' | |
215 library a2; | 220 library a2; |
216 import 'a3.dart'; | 221 import 'a3.dart'; |
217 import 'a4.dart'; | 222 import 'a4.dart'; |
218 export 'a5.dart'; | 223 export 'a5.dart'; |
219 import 'a6.dart'; // changed from part | 224 import 'a6.dart'; // changed from part |
220 '''; | 225 '''); |
221 var a6 = nodeOf('/a6.dart'); | 226 var a6 = nodeOf('/a6.dart'); |
222 a6.source.contents.modificationTime++; | 227 updateFile(a6.source, ''); |
223 a6.source.contents.data = ''; | |
224 node.update(); | 228 node.update(); |
225 | 229 |
226 expect(node.imports.length, 3); | 230 expect(node.imports.length, 3); |
227 expect(node.exports.length, 1); | 231 expect(node.exports.length, 1); |
228 expect(node.parts.length, 0); | 232 expect(node.parts.length, 0); |
229 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); | 233 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); |
230 expect(node.imports.contains(nodeOf('/a4.dart')), isTrue); | 234 expect(node.imports.contains(nodeOf('/a4.dart')), isTrue); |
231 expect(node.imports.contains(nodeOf('/a6.dart')), isTrue); | 235 expect(node.imports.contains(nodeOf('/a6.dart')), isTrue); |
232 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); | 236 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); |
233 | 237 |
(...skipping 12 matching lines...) Expand all Loading... |
246 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); | 250 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); |
247 expect(node.imports.contains(nodeOf('/a4.dart')), isTrue); | 251 expect(node.imports.contains(nodeOf('/a4.dart')), isTrue); |
248 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); | 252 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); |
249 expect(node.parts.contains(nodeOf('/a6.dart')), isTrue); | 253 expect(node.parts.contains(nodeOf('/a6.dart')), isTrue); |
250 | 254 |
251 a4.update(); | 255 a4.update(); |
252 expect(a4.imports.length, 0); | 256 expect(a4.imports.length, 0); |
253 expect(a4.exports.length, 1); | 257 expect(a4.exports.length, 1); |
254 expect(a4.parts.length, 0); | 258 expect(a4.parts.length, 0); |
255 | 259 |
256 node.source.contents.modificationTime++; | 260 updateFile(node.source, ''' |
257 node.source.contents.data = ''' | |
258 library a2; | 261 library a2; |
259 import 'a3.dart'; | 262 import 'a3.dart'; |
260 part 'a4.dart'; // changed from export | 263 part 'a4.dart'; // changed from export |
261 export 'a5.dart'; | 264 export 'a5.dart'; |
262 part 'a6.dart'; | 265 part 'a6.dart'; |
263 '''; | 266 '''); |
264 node.update(); | 267 node.update(); |
265 | 268 |
266 expect(node.imports.length, 1); | 269 expect(node.imports.length, 1); |
267 expect(node.exports.length, 1); | 270 expect(node.exports.length, 1); |
268 expect(node.parts.length, 2); | 271 expect(node.parts.length, 2); |
269 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); | 272 expect(node.imports.contains(nodeOf('/a3.dart')), isTrue); |
270 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); | 273 expect(node.exports.contains(nodeOf('/a5.dart')), isTrue); |
271 expect(node.parts.contains(nodeOf('/a4.dart')), isTrue); | 274 expect(node.parts.contains(nodeOf('/a4.dart')), isTrue); |
272 expect(node.parts.contains(nodeOf('/a6.dart')), isTrue); | 275 expect(node.parts.contains(nodeOf('/a6.dart')), isTrue); |
273 | 276 |
274 // Note, technically we never modified the contents of a4 and it contains | 277 // Note, technically we never modified the contents of a4 and it contains |
275 // an export. This is invalid Dart, but we'll let the analyzer report that | 278 // an export. This is invalid Dart, but we'll let the analyzer report that |
276 // error instead of doing so ourselves. | 279 // error instead of doing so ourselves. |
277 expect(a4.imports.length, 0); | 280 expect(a4.imports.length, 0); |
278 expect(a4.exports.length, 1); | 281 expect(a4.exports.length, 1); |
279 expect(a4.parts.length, 0); | 282 expect(a4.parts.length, 0); |
280 | 283 |
281 // And change it back. | 284 // And change it back. |
282 node.source.contents.modificationTime++; | 285 updateFile(node.source, ''' |
283 node.source.contents.data = ''' | |
284 library a2; | 286 library a2; |
285 import 'a3.dart'; | 287 import 'a3.dart'; |
286 import 'a4.dart'; // changed again | 288 import 'a4.dart'; // changed again |
287 export 'a5.dart'; | 289 export 'a5.dart'; |
288 part 'a6.dart'; | 290 part 'a6.dart'; |
289 '''; | 291 '''); |
290 node.update(); | 292 node.update(); |
291 expect(node.imports.contains(a4), isTrue); | 293 expect(node.imports.contains(a4), isTrue); |
292 expect(a4.imports.length, 0); | 294 expect(a4.imports.length, 0); |
293 expect(a4.exports.length, 1); | 295 expect(a4.exports.length, 1); |
294 expect(a4.parts.length, 0); | 296 expect(a4.parts.length, 0); |
295 }); | 297 }); |
296 }); | 298 }); |
297 | 299 |
298 group('local changes', () { | 300 group('local changes', () { |
299 group('needs rebuild', () { | 301 group('needs rebuild', () { |
300 test('in HTML', () { | 302 test('in HTML', () { |
301 var node = nodeOf('/index1.html'); | 303 var node = nodeOf('/index1.html'); |
302 node.update(); | 304 node.update(); |
303 expect(node.needsRebuild, isTrue); | 305 expect(node.needsRebuild, isTrue); |
304 node.needsRebuild = false; | 306 node.needsRebuild = false; |
305 | 307 |
306 node.update(); | 308 node.update(); |
307 expect(node.needsRebuild, isFalse); | 309 expect(node.needsRebuild, isFalse); |
308 | 310 |
309 // For now, an empty modification is enough to trigger a rebuild | 311 // For now, an empty modification is enough to trigger a rebuild |
310 node.source.contents.modificationTime++; | 312 updateFile(node.source); |
311 expect(node.needsRebuild, isFalse); | 313 expect(node.needsRebuild, isFalse); |
312 node.update(); | 314 node.update(); |
313 expect(node.needsRebuild, isTrue); | 315 expect(node.needsRebuild, isTrue); |
314 }); | 316 }); |
315 | 317 |
316 test('main library in Dart', () { | 318 test('main library in Dart', () { |
317 var node = nodeOf('/a2.dart'); | 319 var node = nodeOf('/a2.dart'); |
318 var partNode = nodeOf('/a6.dart'); | 320 var partNode = nodeOf('/a6.dart'); |
319 node.update(); | 321 node.update(); |
320 expect(node.needsRebuild, isTrue); | 322 expect(node.needsRebuild, isTrue); |
321 node.needsRebuild = false; | 323 node.needsRebuild = false; |
322 partNode.needsRebuild = false; | 324 partNode.needsRebuild = false; |
323 | 325 |
324 node.update(); | 326 node.update(); |
325 expect(node.needsRebuild, isFalse); | 327 expect(node.needsRebuild, isFalse); |
326 | 328 |
327 // For now, an empty modification is enough to trigger a rebuild | 329 // For now, an empty modification is enough to trigger a rebuild |
328 node.source.contents.modificationTime++; | 330 updateFile(node.source); |
329 expect(node.needsRebuild, isFalse); | 331 expect(node.needsRebuild, isFalse); |
330 node.update(); | 332 node.update(); |
331 expect(node.needsRebuild, isTrue); | 333 expect(node.needsRebuild, isTrue); |
332 }); | 334 }); |
333 | 335 |
334 test('part of library in Dart', () { | 336 test('part of library in Dart', () { |
335 var node = nodeOf('/a2.dart'); | 337 var node = nodeOf('/a2.dart'); |
336 var importNode = nodeOf('/a3.dart'); | 338 var importNode = nodeOf('/a3.dart'); |
337 var exportNode = nodeOf('/a5.dart'); | 339 var exportNode = nodeOf('/a5.dart'); |
338 var partNode = nodeOf('/a6.dart'); | 340 var partNode = nodeOf('/a6.dart'); |
339 node.update(); | 341 node.update(); |
340 expect(node.needsRebuild, isTrue); | 342 expect(node.needsRebuild, isTrue); |
341 node.needsRebuild = false; | 343 node.needsRebuild = false; |
342 partNode.needsRebuild = false; | 344 partNode.needsRebuild = false; |
343 | 345 |
344 node.update(); | 346 node.update(); |
345 expect(node.needsRebuild, isFalse); | 347 expect(node.needsRebuild, isFalse); |
346 | 348 |
347 // Modification in imported/exported node makes no difference for local | 349 // Modification in imported/exported node makes no difference for local |
348 // rebuild label (globally that's tested elsewhere) | 350 // rebuild label (globally that's tested elsewhere) |
349 importNode.source.contents.modificationTime++; | 351 updateFile(importNode.source); |
350 exportNode.source.contents.modificationTime++; | 352 updateFile(exportNode.source); |
351 node.update(); | 353 node.update(); |
352 expect(node.needsRebuild, isFalse); | 354 expect(node.needsRebuild, isFalse); |
353 expect(partNode.needsRebuild, isFalse); | 355 expect(partNode.needsRebuild, isFalse); |
354 | 356 |
355 // Modification in part triggers change in containing library: | 357 // Modification in part triggers change in containing library: |
356 partNode.source.contents.modificationTime++; | 358 updateFile(partNode.source); |
357 expect(node.needsRebuild, isFalse); | 359 expect(node.needsRebuild, isFalse); |
358 expect(partNode.needsRebuild, isFalse); | 360 expect(partNode.needsRebuild, isFalse); |
359 node.update(); | 361 node.update(); |
360 expect(node.needsRebuild, isTrue); | 362 expect(node.needsRebuild, isTrue); |
361 expect(partNode.needsRebuild, isTrue); | 363 expect(partNode.needsRebuild, isTrue); |
362 }); | 364 }); |
363 }); | 365 }); |
364 | 366 |
365 group('structure change', () { | 367 group('structure change', () { |
366 test('no mod in HTML', () { | 368 test('no mod in HTML', () { |
367 var node = nodeOf('/index2.html'); | 369 var node = nodeOf('/index2.html'); |
368 node.update(); | 370 node.update(); |
369 expect(node.structureChanged, isTrue); | 371 expect(node.structureChanged, isTrue); |
370 node.structureChanged = false; | 372 node.structureChanged = false; |
371 | 373 |
372 node.update(); | 374 node.update(); |
373 expect(node.structureChanged, isFalse); | 375 expect(node.structureChanged, isFalse); |
374 | 376 |
375 // An empty modification will not trigger a structural change | 377 // An empty modification will not trigger a structural change |
376 node.source.contents.modificationTime++; | 378 updateFile(node.source); |
377 expect(node.structureChanged, isFalse); | 379 expect(node.structureChanged, isFalse); |
378 node.update(); | 380 node.update(); |
379 expect(node.structureChanged, isFalse); | 381 expect(node.structureChanged, isFalse); |
380 }); | 382 }); |
381 | 383 |
382 test('added scripts in HTML', () { | 384 test('added scripts in HTML', () { |
383 var node = nodeOf('/index2.html'); | 385 var node = nodeOf('/index2.html'); |
384 node.update(); | 386 node.update(); |
385 expect(node.structureChanged, isTrue); | 387 expect(node.structureChanged, isTrue); |
386 expect(node.scripts.length, 1); | 388 expect(node.scripts.length, 1); |
387 | 389 |
388 node.structureChanged = false; | 390 node.structureChanged = false; |
389 node.update(); | 391 node.update(); |
390 expect(node.structureChanged, isFalse); | 392 expect(node.structureChanged, isFalse); |
391 | 393 |
392 // This change will not include new script tags: | 394 // This change will not include new script tags: |
393 node.source.contents.modificationTime++; | 395 updateFile(node.source, node.source.contents.data + '<div></div>'); |
394 node.source.contents.data += '<div></div>'; | |
395 expect(node.structureChanged, isFalse); | 396 expect(node.structureChanged, isFalse); |
396 node.update(); | 397 node.update(); |
397 expect(node.structureChanged, isFalse); | 398 expect(node.structureChanged, isFalse); |
398 expect(node.scripts.length, 1); | 399 expect(node.scripts.length, 1); |
399 | 400 |
400 node.source.contents.modificationTime++; | 401 updateFile(node.source, node.source.contents.data + |
401 node.source.contents.data += | 402 '<script type="application/dart" src="a4.dart"></script>'); |
402 '<script type="application/dart" src="a4.dart"></script>'; | |
403 expect(node.structureChanged, isFalse); | 403 expect(node.structureChanged, isFalse); |
404 node.update(); | 404 node.update(); |
405 expect(node.structureChanged, isTrue); | 405 expect(node.structureChanged, isTrue); |
406 expect(node.scripts.length, 2); | 406 expect(node.scripts.length, 2); |
407 }); | 407 }); |
408 | 408 |
409 test('no mod in Dart', () { | 409 test('no mod in Dart', () { |
410 var node = nodeOf('/a2.dart'); | 410 var node = nodeOf('/a2.dart'); |
411 var importNode = nodeOf('/a3.dart'); | 411 var importNode = nodeOf('/a3.dart'); |
412 var exportNode = nodeOf('/a5.dart'); | 412 var exportNode = nodeOf('/a5.dart'); |
413 var partNode = nodeOf('/a6.dart'); | 413 var partNode = nodeOf('/a6.dart'); |
414 node.update(); | 414 node.update(); |
415 expect(node.structureChanged, isTrue); | 415 expect(node.structureChanged, isTrue); |
416 node.structureChanged = false; | 416 node.structureChanged = false; |
417 | 417 |
418 node.update(); | 418 node.update(); |
419 expect(node.structureChanged, isFalse); | 419 expect(node.structureChanged, isFalse); |
420 | 420 |
421 // These modifications make no difference at all. | 421 // These modifications make no difference at all. |
422 importNode.source.contents.modificationTime++; | 422 updateFile(importNode.source); |
423 exportNode.source.contents.modificationTime++; | 423 updateFile(exportNode.source); |
424 partNode.source.contents.modificationTime++; | 424 updateFile(partNode.source); |
425 node.source.contents.modificationTime++; | 425 updateFile(node.source); |
426 | 426 |
427 expect(node.structureChanged, isFalse); | 427 expect(node.structureChanged, isFalse); |
428 node.update(); | 428 node.update(); |
429 expect(node.structureChanged, isFalse); | 429 expect(node.structureChanged, isFalse); |
430 }); | 430 }); |
431 | 431 |
432 test('same directives, different order', () { | 432 test('same directives, different order', () { |
433 var node = nodeOf('/a2.dart'); | 433 var node = nodeOf('/a2.dart'); |
434 node.update(); | 434 node.update(); |
435 expect(node.structureChanged, isTrue); | 435 expect(node.structureChanged, isTrue); |
436 node.structureChanged = false; | 436 node.structureChanged = false; |
437 | 437 |
438 node.update(); | 438 node.update(); |
439 expect(node.structureChanged, isFalse); | 439 expect(node.structureChanged, isFalse); |
440 | 440 |
441 // modified order of imports, but structure stays the same: | 441 // modified order of imports, but structure stays the same: |
442 node.source.contents.modificationTime++; | 442 updateFile(node.source, 'import "a4.dart"; import "a3.dart"; ' |
443 node.source.contents.data = 'import "a4.dart"; import "a3.dart"; ' | 443 'export "a5.dart"; part "a6.dart";'); |
444 'export "a5.dart"; part "a6.dart";'; | |
445 node.update(); | 444 node.update(); |
446 | 445 |
447 expect(node.structureChanged, isFalse); | 446 expect(node.structureChanged, isFalse); |
448 node.update(); | 447 node.update(); |
449 expect(node.structureChanged, isFalse); | 448 expect(node.structureChanged, isFalse); |
450 }); | 449 }); |
451 | 450 |
452 test('changed parts', () { | 451 test('changed parts', () { |
453 var node = nodeOf('/a2.dart'); | 452 var node = nodeOf('/a2.dart'); |
454 node.update(); | 453 node.update(); |
455 expect(node.structureChanged, isTrue); | 454 expect(node.structureChanged, isTrue); |
456 node.structureChanged = false; | 455 node.structureChanged = false; |
457 | 456 |
458 node.update(); | 457 node.update(); |
459 expect(node.structureChanged, isFalse); | 458 expect(node.structureChanged, isFalse); |
460 | 459 |
461 // added one. | 460 // added one. |
462 node.source.contents.modificationTime++; | 461 updateFile(node.source, 'import "a4.dart"; import "a3.dart"; ' |
463 node.source.contents.data = 'import "a4.dart"; import "a3.dart"; ' | 462 'export "a5.dart"; part "a6.dart"; part "a7.dart";'); |
464 'export "a5.dart"; part "a6.dart"; part "a7.dart";'; | |
465 expect(node.structureChanged, isFalse); | 463 expect(node.structureChanged, isFalse); |
466 node.update(); | 464 node.update(); |
467 expect(node.structureChanged, isTrue); | 465 expect(node.structureChanged, isTrue); |
468 | 466 |
469 // no change | 467 // no change |
470 node.structureChanged = false; | 468 node.structureChanged = false; |
471 node.source.contents.modificationTime++; | 469 updateFile(node.source); |
472 node.update(); | 470 node.update(); |
473 expect(node.structureChanged, isFalse); | 471 expect(node.structureChanged, isFalse); |
474 | 472 |
475 // removed one | 473 // removed one |
476 node.source.contents.modificationTime++; | 474 updateFile(node.source); |
477 node.source.contents.data = 'import "a4.dart"; import "a3.dart"; ' | 475 updateFile(node.source, 'import "a4.dart"; import "a3.dart"; ' |
478 'export "a5.dart"; part "a7.dart";'; | 476 'export "a5.dart"; part "a7.dart";'); |
479 expect(node.structureChanged, isFalse); | 477 expect(node.structureChanged, isFalse); |
480 node.update(); | 478 node.update(); |
481 expect(node.structureChanged, isTrue); | 479 expect(node.structureChanged, isTrue); |
482 }); | 480 }); |
483 | 481 |
484 test('changed import', () { | 482 test('changed import', () { |
485 var node = nodeOf('/a2.dart'); | 483 var node = nodeOf('/a2.dart'); |
486 node.update(); | 484 node.update(); |
487 expect(node.structureChanged, isTrue); | 485 expect(node.structureChanged, isTrue); |
488 node.structureChanged = false; | 486 node.structureChanged = false; |
489 | 487 |
490 node.update(); | 488 node.update(); |
491 expect(node.structureChanged, isFalse); | 489 expect(node.structureChanged, isFalse); |
492 | 490 |
493 // added one. | 491 // added one. |
494 node.source.contents.modificationTime++; | 492 updateFile(node.source, |
495 node.source.contents.data = | |
496 'import "a4.dart"; import "a3.dart"; import "a7.dart";' | 493 'import "a4.dart"; import "a3.dart"; import "a7.dart";' |
497 'export "a5.dart"; part "a6.dart";'; | 494 'export "a5.dart"; part "a6.dart";'); |
498 expect(node.structureChanged, isFalse); | 495 expect(node.structureChanged, isFalse); |
499 node.update(); | 496 node.update(); |
500 expect(node.structureChanged, isTrue); | 497 expect(node.structureChanged, isTrue); |
501 | 498 |
502 // no change | 499 // no change |
503 node.structureChanged = false; | 500 node.structureChanged = false; |
504 node.source.contents.modificationTime++; | 501 updateFile(node.source); |
505 node.update(); | 502 node.update(); |
506 expect(node.structureChanged, isFalse); | 503 expect(node.structureChanged, isFalse); |
507 | 504 |
508 // removed one | 505 // removed one |
509 node.source.contents.modificationTime++; | 506 updateFile(node.source, 'import "a4.dart"; import "a7.dart"; ' |
510 node.source.contents.data = 'import "a4.dart"; import "a7.dart"; ' | 507 'export "a5.dart"; part "a6.dart";'); |
511 'export "a5.dart"; part "a6.dart";'; | |
512 expect(node.structureChanged, isFalse); | 508 expect(node.structureChanged, isFalse); |
513 node.update(); | 509 node.update(); |
514 expect(node.structureChanged, isTrue); | 510 expect(node.structureChanged, isTrue); |
515 }); | 511 }); |
516 | 512 |
517 test('changed exports', () { | 513 test('changed exports', () { |
518 var node = nodeOf('/a2.dart'); | 514 var node = nodeOf('/a2.dart'); |
519 node.update(); | 515 node.update(); |
520 expect(node.structureChanged, isTrue); | 516 expect(node.structureChanged, isTrue); |
521 node.structureChanged = false; | 517 node.structureChanged = false; |
522 | 518 |
523 node.update(); | 519 node.update(); |
524 expect(node.structureChanged, isFalse); | 520 expect(node.structureChanged, isFalse); |
525 | 521 |
526 // added one. | 522 // added one. |
527 node.source.contents.modificationTime++; | 523 updateFile(node.source, 'import "a4.dart"; import "a3.dart";' |
528 node.source.contents.data = 'import "a4.dart"; import "a3.dart";' | 524 'export "a5.dart"; export "a9.dart"; part "a6.dart";'); |
529 'export "a5.dart"; export "a9.dart"; part "a6.dart";'; | |
530 expect(node.structureChanged, isFalse); | 525 expect(node.structureChanged, isFalse); |
531 node.update(); | 526 node.update(); |
532 expect(node.structureChanged, isTrue); | 527 expect(node.structureChanged, isTrue); |
533 | 528 |
534 // no change | 529 // no change |
535 node.structureChanged = false; | 530 node.structureChanged = false; |
536 node.source.contents.modificationTime++; | 531 updateFile(node.source); |
537 node.update(); | 532 node.update(); |
538 expect(node.structureChanged, isFalse); | 533 expect(node.structureChanged, isFalse); |
539 | 534 |
540 // removed one | 535 // removed one |
541 node.source.contents.modificationTime++; | 536 updateFile(node.source, 'import "a4.dart"; import "a3.dart"; ' |
542 node.source.contents.data = 'import "a4.dart"; import "a3.dart"; ' | 537 'export "a5.dart"; part "a6.dart";'); |
543 'export "a5.dart"; part "a6.dart";'; | |
544 expect(node.structureChanged, isFalse); | 538 expect(node.structureChanged, isFalse); |
545 node.update(); | 539 node.update(); |
546 expect(node.structureChanged, isTrue); | 540 expect(node.structureChanged, isTrue); |
547 }); | 541 }); |
548 }); | 542 }); |
549 }); | 543 }); |
550 | 544 |
551 group('refresh structure and marks', () { | 545 group('refresh structure and marks', () { |
552 test('initial marks', () { | 546 test('initial marks', () { |
553 var node = nodeOf('/index3.html'); | 547 var node = nodeOf('/index3.html'); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 | |-- a6.dart (part) | 598 | |-- a6.dart (part) |
605 $_RUNTIME_GRAPH | 599 $_RUNTIME_GRAPH |
606 '''); | 600 '''); |
607 }); | 601 }); |
608 | 602 |
609 test('needsRebuild mark updated on local modifications', () { | 603 test('needsRebuild mark updated on local modifications', () { |
610 var node = nodeOf('/index3.html'); | 604 var node = nodeOf('/index3.html'); |
611 refreshStructureAndMarks(node); | 605 refreshStructureAndMarks(node); |
612 clearMarks(node); | 606 clearMarks(node); |
613 var a3 = nodeOf('/a3.dart'); | 607 var a3 = nodeOf('/a3.dart'); |
614 a3.source.contents.modificationTime++; | 608 updateFile(a3.source); |
615 | 609 |
616 refreshStructureAndMarks(node); | 610 refreshStructureAndMarks(node); |
617 expectGraph(node, ''' | 611 expectGraph(node, ''' |
618 index3.html | 612 index3.html |
619 |-- a2.dart | 613 |-- a2.dart |
620 | |-- a3.dart [needs-rebuild] | 614 | |-- a3.dart [needs-rebuild] |
621 | |-- a4.dart | 615 | |-- a4.dart |
622 | | |-- a10.dart | 616 | | |-- a10.dart |
623 | |-- a5.dart | 617 | |-- a5.dart |
624 | |-- a6.dart (part) | 618 | |-- a6.dart (part) |
625 $_RUNTIME_GRAPH | 619 $_RUNTIME_GRAPH |
626 '''); | 620 '''); |
627 }); | 621 }); |
628 | 622 |
629 test('structuredChanged mark updated on structure modifications', () { | 623 test('structuredChanged mark updated on structure modifications', () { |
630 var node = nodeOf('/index3.html'); | 624 var node = nodeOf('/index3.html'); |
631 refreshStructureAndMarks(node); | 625 refreshStructureAndMarks(node); |
632 clearMarks(node); | 626 clearMarks(node); |
633 var a5 = nodeOf('/a5.dart'); | 627 var a5 = nodeOf('/a5.dart'); |
634 a5.source.contents.modificationTime++; | 628 updateFile(a5.source, 'import "a8.dart";'); |
635 a5.source.contents.data = 'import "a8.dart";'; | |
636 | 629 |
637 refreshStructureAndMarks(node); | 630 refreshStructureAndMarks(node); |
638 expectGraph(node, ''' | 631 expectGraph(node, ''' |
639 index3.html | 632 index3.html |
640 |-- a2.dart | 633 |-- a2.dart |
641 | |-- a3.dart | 634 | |-- a3.dart |
642 | |-- a4.dart | 635 | |-- a4.dart |
643 | | |-- a10.dart | 636 | | |-- a10.dart |
644 | |-- a5.dart [needs-rebuild] [structure-changed] | 637 | |-- a5.dart [needs-rebuild] [structure-changed] |
645 | | |-- a8.dart [needs-rebuild] [structure-changed] | 638 | | |-- a8.dart [needs-rebuild] [structure-changed] |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
730 rebuild(node, buildNoTransitiveChange); | 723 rebuild(node, buildNoTransitiveChange); |
731 expect(results, []); | 724 expect(results, []); |
732 }); | 725 }); |
733 | 726 |
734 test('modified part triggers building library', () { | 727 test('modified part triggers building library', () { |
735 var node = nodeOf('/index3.html'); | 728 var node = nodeOf('/index3.html'); |
736 rebuild(node, buildNoTransitiveChange); | 729 rebuild(node, buildNoTransitiveChange); |
737 results = []; | 730 results = []; |
738 | 731 |
739 var a6 = nodeOf('/a6.dart'); | 732 var a6 = nodeOf('/a6.dart'); |
740 a6.source.contents.modificationTime++; | 733 updateFile(a6.source); |
741 rebuild(node, buildNoTransitiveChange); | 734 rebuild(node, buildNoTransitiveChange); |
742 expect(results, ['a2.dart']); | 735 expect(results, ['a2.dart']); |
743 | 736 |
744 results = []; | 737 results = []; |
745 rebuild(node, buildNoTransitiveChange); | 738 rebuild(node, buildNoTransitiveChange); |
746 expect(results, []); | 739 expect(results, []); |
747 }); | 740 }); |
748 | 741 |
749 test('non-API change triggers build stays local', () { | 742 test('non-API change triggers build stays local', () { |
750 var node = nodeOf('/index3.html'); | 743 var node = nodeOf('/index3.html'); |
751 rebuild(node, buildNoTransitiveChange); | 744 rebuild(node, buildNoTransitiveChange); |
752 results = []; | 745 results = []; |
753 | 746 |
754 var a3 = nodeOf('/a3.dart'); | 747 var a3 = nodeOf('/a3.dart'); |
755 a3.source.contents.modificationTime++; | 748 updateFile(a3.source); |
756 rebuild(node, buildNoTransitiveChange); | 749 rebuild(node, buildNoTransitiveChange); |
757 expect(results, ['a3.dart']); | 750 expect(results, ['a3.dart']); |
758 | 751 |
759 results = []; | 752 results = []; |
760 rebuild(node, buildNoTransitiveChange); | 753 rebuild(node, buildNoTransitiveChange); |
761 expect(results, []); | 754 expect(results, []); |
762 }); | 755 }); |
763 | 756 |
764 test('no-API change in exported file stays local', () { | 757 test('no-API change in exported file stays local', () { |
765 var node = nodeOf('/index3.html'); | 758 var node = nodeOf('/index3.html'); |
766 rebuild(node, buildNoTransitiveChange); | 759 rebuild(node, buildNoTransitiveChange); |
767 results = []; | 760 results = []; |
768 | 761 |
769 // similar to the test above, but a10 is exported from a4. | 762 // similar to the test above, but a10 is exported from a4. |
770 var a3 = nodeOf('/a10.dart'); | 763 var a3 = nodeOf('/a10.dart'); |
771 a3.source.contents.modificationTime++; | 764 updateFile(a3.source); |
772 rebuild(node, buildNoTransitiveChange); | 765 rebuild(node, buildNoTransitiveChange); |
773 expect(results, ['a10.dart']); | 766 expect(results, ['a10.dart']); |
774 | 767 |
775 results = []; | 768 results = []; |
776 rebuild(node, buildNoTransitiveChange); | 769 rebuild(node, buildNoTransitiveChange); |
777 expect(results, []); | 770 expect(results, []); |
778 }); | 771 }); |
779 | 772 |
780 test('API change in lib, triggers build on imports', () { | 773 test('API change in lib, triggers build on imports', () { |
781 var node = nodeOf('/index3.html'); | 774 var node = nodeOf('/index3.html'); |
782 rebuild(node, buildNoTransitiveChange); | 775 rebuild(node, buildNoTransitiveChange); |
783 results = []; | 776 results = []; |
784 | 777 |
785 var a3 = nodeOf('/a3.dart'); | 778 var a3 = nodeOf('/a3.dart'); |
786 a3.source.contents.modificationTime++; | 779 updateFile(a3.source); |
787 rebuild(node, buildWithTransitiveChange); | 780 rebuild(node, buildWithTransitiveChange); |
788 expect(results, ['a3.dart', 'a2.dart']); | 781 expect(results, ['a3.dart', 'a2.dart']); |
789 | 782 |
790 results = []; | 783 results = []; |
791 rebuild(node, buildNoTransitiveChange); | 784 rebuild(node, buildNoTransitiveChange); |
792 expect(results, []); | 785 expect(results, []); |
793 }); | 786 }); |
794 | 787 |
795 test('API change in export, triggers build on imports', () { | 788 test('API change in export, triggers build on imports', () { |
796 var node = nodeOf('/index3.html'); | 789 var node = nodeOf('/index3.html'); |
797 rebuild(node, buildNoTransitiveChange); | 790 rebuild(node, buildNoTransitiveChange); |
798 results = []; | 791 results = []; |
799 | 792 |
800 var a3 = nodeOf('/a10.dart'); | 793 var a3 = nodeOf('/a10.dart'); |
801 a3.source.contents.modificationTime++; | 794 updateFile(a3.source); |
802 rebuild(node, buildWithTransitiveChange); | 795 rebuild(node, buildWithTransitiveChange); |
803 | 796 |
804 // Node: a4.dart reexports a10.dart, but it doesn't import it, so we don't | 797 // Node: a4.dart reexports a10.dart, but it doesn't import it, so we don't |
805 // need to rebuild it. | 798 // need to rebuild it. |
806 expect(results, ['a10.dart', 'a2.dart']); | 799 expect(results, ['a10.dart', 'a2.dart']); |
807 | 800 |
808 results = []; | 801 results = []; |
809 rebuild(node, buildNoTransitiveChange); | 802 rebuild(node, buildNoTransitiveChange); |
810 expect(results, []); | 803 expect(results, []); |
811 }); | 804 }); |
812 | 805 |
813 test('structural change rebuilds HTML, but skips unreachable code', () { | 806 test('structural change rebuilds HTML, but skips unreachable code', () { |
814 var node = nodeOf('/index3.html'); | 807 var node = nodeOf('/index3.html'); |
815 rebuild(node, buildNoTransitiveChange); | 808 rebuild(node, buildNoTransitiveChange); |
816 results = []; | 809 results = []; |
817 | 810 |
818 var a2 = nodeOf('/a2.dart'); | 811 var a2 = nodeOf('/a2.dart'); |
819 a2.source.contents.modificationTime++; | 812 updateFile(a2.source, 'import "a4.dart";'); |
820 a2.source.contents.data = 'import "a4.dart";'; | |
821 | 813 |
822 var a3 = nodeOf('/a3.dart'); | 814 var a3 = nodeOf('/a3.dart'); |
823 a3.source.contents.modificationTime++; | 815 updateFile(a3.source); |
824 rebuild(node, buildNoTransitiveChange); | 816 rebuild(node, buildNoTransitiveChange); |
825 | 817 |
826 // a3 will become unreachable, index3 reflects structural changes. | 818 // a3 will become unreachable, index3 reflects structural changes. |
827 expect(results, ['a2.dart', 'index3.html']); | 819 expect(results, ['a2.dart', 'index3.html']); |
828 | 820 |
829 results = []; | 821 results = []; |
830 rebuild(node, buildNoTransitiveChange); | 822 rebuild(node, buildNoTransitiveChange); |
831 expect(results, []); | 823 expect(results, []); |
832 }); | 824 }); |
833 | 825 |
834 test('newly discovered files get built too', () { | 826 test('newly discovered files get built too', () { |
835 var node = nodeOf('/index3.html'); | 827 var node = nodeOf('/index3.html'); |
836 rebuild(node, buildNoTransitiveChange); | 828 rebuild(node, buildNoTransitiveChange); |
837 results = []; | 829 results = []; |
838 | 830 |
839 var a2 = nodeOf('/a2.dart'); | 831 var a2 = nodeOf('/a2.dart'); |
840 a2.source.contents.modificationTime++; | 832 updateFile(a2.source, 'import "a9.dart";'); |
841 a2.source.contents.data = 'import "a9.dart";'; | |
842 | 833 |
843 rebuild(node, buildNoTransitiveChange); | 834 rebuild(node, buildNoTransitiveChange); |
844 expect(results, ['a8.dart', 'a9.dart', 'a2.dart', 'index3.html']); | 835 expect(results, ['a8.dart', 'a9.dart', 'a2.dart', 'index3.html']); |
845 | 836 |
846 results = []; | 837 results = []; |
847 rebuild(node, buildNoTransitiveChange); | 838 rebuild(node, buildNoTransitiveChange); |
848 expect(results, []); | 839 expect(results, []); |
849 }); | 840 }); |
850 | 841 |
851 group('file upgrades', () { | 842 group('file upgrades', () { |
(...skipping 14 matching lines...) Expand all Loading... |
866 |-- a2.dart | 857 |-- a2.dart |
867 | |-- a3.dart | 858 | |-- a3.dart |
868 | |-- a4.dart | 859 | |-- a4.dart |
869 | | |-- a10.dart | 860 | | |-- a10.dart |
870 | |-- a5.dart | 861 | |-- a5.dart |
871 | |-- a6.dart (part) | 862 | |-- a6.dart (part) |
872 $_RUNTIME_GRAPH | 863 $_RUNTIME_GRAPH |
873 '''); | 864 '''); |
874 | 865 |
875 // Modify the file first: | 866 // Modify the file first: |
876 a6.source.contents.modificationTime++; | 867 updateFile(a6.source, 'library a6; import "a5.dart";'); |
877 a6.source.contents.data = 'library a6; import "a5.dart";'; | |
878 results = []; | 868 results = []; |
879 rebuild(node, buildNoTransitiveChange); | 869 rebuild(node, buildNoTransitiveChange); |
880 | 870 |
881 // Looks to us like a change in a part, we'll report errors that the | 871 // Looks to us like a change in a part, we'll report errors that the |
882 // part is not really a part-file. Note that a6.dart is not included | 872 // part is not really a part-file. Note that a6.dart is not included |
883 // below, because we don't build it as a library. | 873 // below, because we don't build it as a library. |
884 expect(results, ['a2.dart']); | 874 expect(results, ['a2.dart']); |
885 expectGraph(node, ''' | 875 expectGraph(node, ''' |
886 index3.html | 876 index3.html |
887 |-- a2.dart | 877 |-- a2.dart |
888 | |-- a3.dart | 878 | |-- a3.dart |
889 | |-- a4.dart | 879 | |-- a4.dart |
890 | | |-- a10.dart | 880 | | |-- a10.dart |
891 | |-- a5.dart | 881 | |-- a5.dart |
892 | |-- a6.dart (part) | 882 | |-- a6.dart (part) |
893 $_RUNTIME_GRAPH | 883 $_RUNTIME_GRAPH |
894 '''); | 884 '''); |
895 | 885 |
896 a2.source.contents.modificationTime++; | 886 updateFile(a2.source, ''' |
897 a2.source.contents.data = ''' | |
898 library a2; | 887 library a2; |
899 import 'a3.dart'; | 888 import 'a3.dart'; |
900 import 'a4.dart'; | 889 import 'a4.dart'; |
901 import 'a6.dart'; // properly import it | 890 import 'a6.dart'; // properly import it |
902 export 'a5.dart'; | 891 export 'a5.dart'; |
903 '''; | 892 '''); |
904 results = []; | 893 results = []; |
905 rebuild(node, buildNoTransitiveChange); | 894 rebuild(node, buildNoTransitiveChange); |
906 // Note that a6 is now included, because we haven't built it as a | 895 // Note that a6 is now included, because we haven't built it as a |
907 // library until now: | 896 // library until now: |
908 expect(results, ['a6.dart', 'a2.dart', 'index3.html']); | 897 expect(results, ['a6.dart', 'a2.dart', 'index3.html']); |
909 | 898 |
910 a6.source.contents.modificationTime++; | 899 updateFile(a6.source); |
911 results = []; | 900 results = []; |
912 rebuild(node, buildNoTransitiveChange); | 901 rebuild(node, buildNoTransitiveChange); |
913 expect(results, ['a6.dart']); | 902 expect(results, ['a6.dart']); |
914 | 903 |
915 expectGraph(node, ''' | 904 expectGraph(node, ''' |
916 index3.html | 905 index3.html |
917 |-- a2.dart | 906 |-- a2.dart |
918 | |-- a3.dart | 907 | |-- a3.dart |
919 | |-- a4.dart | 908 | |-- a4.dart |
920 | | |-- a10.dart | 909 | | |-- a10.dart |
(...skipping 14 matching lines...) Expand all Loading... |
935 index3.html | 924 index3.html |
936 |-- a2.dart | 925 |-- a2.dart |
937 | |-- a3.dart | 926 | |-- a3.dart |
938 | |-- a4.dart | 927 | |-- a4.dart |
939 | | |-- a10.dart | 928 | | |-- a10.dart |
940 | |-- a5.dart | 929 | |-- a5.dart |
941 | |-- a6.dart (part) | 930 | |-- a6.dart (part) |
942 $_RUNTIME_GRAPH | 931 $_RUNTIME_GRAPH |
943 '''); | 932 '''); |
944 | 933 |
945 a2.source.contents.modificationTime++; | 934 updateFile(a2.source, ''' |
946 a2.source.contents.data = ''' | |
947 library a2; | 935 library a2; |
948 import 'a3.dart'; | 936 import 'a3.dart'; |
949 import 'a4.dart'; | 937 import 'a4.dart'; |
950 import 'a6.dart'; // properly import it | 938 import 'a6.dart'; // properly import it |
951 export 'a5.dart'; | 939 export 'a5.dart'; |
952 '''; | 940 '''); |
953 results = []; | 941 results = []; |
954 rebuild(node, buildNoTransitiveChange); | 942 rebuild(node, buildNoTransitiveChange); |
955 expect(results, ['a6.dart', 'a2.dart', 'index3.html']); | 943 expect(results, ['a6.dart', 'a2.dart', 'index3.html']); |
956 expectGraph(node, ''' | 944 expectGraph(node, ''' |
957 index3.html | 945 index3.html |
958 |-- a2.dart | 946 |-- a2.dart |
959 | |-- a3.dart | 947 | |-- a3.dart |
960 | |-- a4.dart | 948 | |-- a4.dart |
961 | | |-- a10.dart | 949 | | |-- a10.dart |
962 | |-- a6.dart | 950 | |-- a6.dart |
963 | |-- a5.dart | 951 | |-- a5.dart |
964 $_RUNTIME_GRAPH | 952 $_RUNTIME_GRAPH |
965 '''); | 953 '''); |
966 | 954 |
967 a6.source.contents.modificationTime++; | 955 updateFile(a6.source, 'library a6; import "a5.dart";'); |
968 a6.source.contents.data = 'library a6; import "a5.dart";'; | |
969 results = []; | 956 results = []; |
970 rebuild(node, buildNoTransitiveChange); | 957 rebuild(node, buildNoTransitiveChange); |
971 expect(results, ['a6.dart', 'index3.html']); | 958 expect(results, ['a6.dart', 'index3.html']); |
972 expectGraph(node, ''' | 959 expectGraph(node, ''' |
973 index3.html | 960 index3.html |
974 |-- a2.dart | 961 |-- a2.dart |
975 | |-- a3.dart | 962 | |-- a3.dart |
976 | |-- a4.dart | 963 | |-- a4.dart |
977 | | |-- a10.dart | 964 | | |-- a10.dart |
978 | |-- a6.dart | 965 | |-- a6.dart |
(...skipping 13 matching lines...) Expand all Loading... |
992 index3.html | 979 index3.html |
993 |-- a2.dart | 980 |-- a2.dart |
994 | |-- a3.dart | 981 | |-- a3.dart |
995 | |-- a4.dart | 982 | |-- a4.dart |
996 | | |-- a10.dart | 983 | | |-- a10.dart |
997 | |-- a5.dart | 984 | |-- a5.dart |
998 | |-- a6.dart (part) | 985 | |-- a6.dart (part) |
999 $_RUNTIME_GRAPH | 986 $_RUNTIME_GRAPH |
1000 '''); | 987 '''); |
1001 | 988 |
1002 a2.source.contents.modificationTime++; | 989 updateFile(a2.source, ''' |
1003 a2.source.contents.data = ''' | |
1004 library a2; | 990 library a2; |
1005 import 'a3.dart'; | 991 import 'a3.dart'; |
1006 import 'a4.dart'; | 992 import 'a4.dart'; |
1007 export 'a5.dart'; | 993 export 'a5.dart'; |
1008 '''; | 994 '''); |
1009 a6.source.contents.modificationTime++; | 995 updateFile(a6.source, 'library a6; import "a5.dart";'); |
1010 a6.source.contents.data = 'library a6; import "a5.dart";'; | |
1011 results = []; | 996 results = []; |
1012 rebuild(node, buildNoTransitiveChange); | 997 rebuild(node, buildNoTransitiveChange); |
1013 // a6 is not here, it's not reachable so we don't build it. | 998 // a6 is not here, it's not reachable so we don't build it. |
1014 expect(results, ['a2.dart', 'index3.html']); | 999 expect(results, ['a2.dart', 'index3.html']); |
1015 expectGraph(node, ''' | 1000 expectGraph(node, ''' |
1016 index3.html | 1001 index3.html |
1017 |-- a2.dart | 1002 |-- a2.dart |
1018 | |-- a3.dart | 1003 | |-- a3.dart |
1019 | |-- a4.dart | 1004 | |-- a4.dart |
1020 | | |-- a10.dart | 1005 | | |-- a10.dart |
(...skipping 12 matching lines...) Expand all Loading... |
1033 index3.html | 1018 index3.html |
1034 |-- a2.dart | 1019 |-- a2.dart |
1035 | |-- a3.dart | 1020 | |-- a3.dart |
1036 | |-- a4.dart | 1021 | |-- a4.dart |
1037 | | |-- a10.dart | 1022 | | |-- a10.dart |
1038 | |-- a5.dart | 1023 | |-- a5.dart |
1039 | |-- a6.dart (part) | 1024 | |-- a6.dart (part) |
1040 $_RUNTIME_GRAPH | 1025 $_RUNTIME_GRAPH |
1041 '''); | 1026 '''); |
1042 | 1027 |
1043 a2.source.contents.modificationTime++; | 1028 updateFile(a2.source, ''' |
1044 a2.source.contents.data = ''' | |
1045 library a2; | 1029 library a2; |
1046 import 'a3.dart'; | 1030 import 'a3.dart'; |
1047 import 'a4.dart'; | 1031 import 'a4.dart'; |
1048 part 'a5.dart'; // make it a part | 1032 part 'a5.dart'; // make it a part |
1049 part 'a6.dart'; | 1033 part 'a6.dart'; |
1050 '''; | 1034 '''); |
1051 results = []; | 1035 results = []; |
1052 rebuild(node, buildNoTransitiveChange); | 1036 rebuild(node, buildNoTransitiveChange); |
1053 expect(results, ['a2.dart', 'index3.html']); | 1037 expect(results, ['a2.dart', 'index3.html']); |
1054 expectGraph(node, ''' | 1038 expectGraph(node, ''' |
1055 index3.html | 1039 index3.html |
1056 |-- a2.dart | 1040 |-- a2.dart |
1057 | |-- a3.dart | 1041 | |-- a3.dart |
1058 | |-- a4.dart | 1042 | |-- a4.dart |
1059 | | |-- a10.dart | 1043 | | |-- a10.dart |
1060 | |-- a5.dart (part) | 1044 | |-- a5.dart (part) |
1061 | |-- a6.dart (part) | 1045 | |-- a6.dart (part) |
1062 $_RUNTIME_GRAPH | 1046 $_RUNTIME_GRAPH |
1063 '''); | 1047 '''); |
1064 | 1048 |
1065 a5.source.contents.modificationTime++; | 1049 updateFile(a5.source, 'part of a2;'); |
1066 a5.source.contents.data = 'part of a2;'; | |
1067 results = []; | 1050 results = []; |
1068 rebuild(node, buildNoTransitiveChange); | 1051 rebuild(node, buildNoTransitiveChange); |
1069 expect(results, ['a2.dart']); | 1052 expect(results, ['a2.dart']); |
1070 expectGraph(node, ''' | 1053 expectGraph(node, ''' |
1071 index3.html | 1054 index3.html |
1072 |-- a2.dart | 1055 |-- a2.dart |
1073 | |-- a3.dart | 1056 | |-- a3.dart |
1074 | |-- a4.dart | 1057 | |-- a4.dart |
1075 | | |-- a10.dart | 1058 | | |-- a10.dart |
1076 | |-- a5.dart (part) | 1059 | |-- a5.dart (part) |
1077 | |-- a6.dart (part) | 1060 | |-- a6.dart (part) |
1078 $_RUNTIME_GRAPH | 1061 $_RUNTIME_GRAPH |
1079 '''); | 1062 '''); |
1080 }); | 1063 }); |
1081 }); | 1064 }); |
1082 | 1065 |
1083 group('represented non-existing files', () { | 1066 group('represented non-existing files', () { |
1084 test('recognize locally change between existing and not-existing', () { | 1067 test('recognize locally change between existing and not-existing', () { |
1085 var n = nodeOf('/foo.dart'); | 1068 var n = nodeOf('/foo.dart'); |
1086 expect(n.source, isNotNull); | 1069 expect(n.source, isNotNull); |
1087 expect(n.source.exists(), isFalse); | 1070 expect(n.source.exists(), isFalse); |
1088 var source = testUriResolver.files[new Uri.file('/foo.dart')]; | 1071 var source = testUriResolver.resolveAbsolute(new Uri.file('/foo.dart')); |
1089 expect(n.source, source); | 1072 expect(n.source, source); |
1090 source.contents.data = "hi"; | 1073 updateFile(source, "hi"); |
1091 source.contents.modificationTime++; | |
1092 expect(n.source.exists(), isTrue); | 1074 expect(n.source.exists(), isTrue); |
1093 }); | 1075 }); |
1094 | 1076 |
1095 test('non-existing files are tracked in dependencies', () { | 1077 test('non-existing files are tracked in dependencies', () { |
1096 var node = nodeOf('/foo.dart'); | 1078 var node = nodeOf('/foo.dart'); |
1097 node.source.contents.data = "import 'bar.dart';"; | 1079 updateFile(node.source, "import 'bar.dart';"); |
1098 rebuild(node, buildNoTransitiveChange); | 1080 rebuild(node, buildNoTransitiveChange); |
1099 expect(node.allDeps.contains(nodeOf('/bar.dart')), isTrue); | 1081 expect(node.allDeps.contains(nodeOf('/bar.dart')), isTrue); |
1100 | 1082 |
1101 var source = nodeOf('/bar.dart').source; | 1083 var source = nodeOf('/bar.dart').source; |
1102 source.contents.data = "hi"; | 1084 updateFile(source, "hi"); |
1103 source.contents.modificationTime++; | |
1104 results = []; | 1085 results = []; |
1105 rebuild(node, buildWithTransitiveChange); | 1086 rebuild(node, buildWithTransitiveChange); |
1106 expect(results, ['bar.dart', 'foo.dart']); | 1087 expect(results, ['bar.dart', 'foo.dart']); |
1107 }); | 1088 }); |
1108 }); | 1089 }); |
1109 | 1090 |
1110 group('null for non-existing files', () { | 1091 group('null for non-existing files', () { |
1111 setUp(() { | 1092 setUp(() { |
1112 testUriResolver = new InMemoryUriResolver(testFiles, | |
1113 representNonExistingFiles: false); | |
1114 context = new TypeResolver.fromMock(mockSdkSources, options, | 1093 context = new TypeResolver.fromMock(mockSdkSources, options, |
1115 otherResolvers: [testUriResolver]).context; | 1094 otherResolvers: [testUriResolver]).context; |
1116 graph = new SourceGraph(context, new LogReporter(context), options); | 1095 graph = new SourceGraph(context, new LogReporter(context), options); |
1117 }); | 1096 }); |
1118 | 1097 |
1119 test('recognize locally change between existing and not-existing', () { | 1098 test('recognize locally change between existing and not-existing', () { |
1120 var n = nodeOf('/foo.dart'); | 1099 var n = nodeOf('/foo.dart'); |
1121 expect(n.source, isNull); | 1100 expect(n.source.exists(), isFalse); |
1122 var source = new InMemorySource(new Uri.file('/foo.dart'), "hi"); | 1101 var source = |
1123 testUriResolver.files[source.uri] = source; | 1102 testResourceProvider.newFile('/foo.dart', 'hi').createSource(); |
1124 expect(n.source, isNull); | 1103 expect( |
1125 n.update(); | 1104 testUriResolver.resolveAbsolute(new Uri.file('/foo.dart')), source); |
1126 expect(n.source, source); | 1105 expect(n.source, source); |
1127 expect(n.source.exists(), isTrue); | 1106 expect(n.source.exists(), isTrue); |
| 1107 n.update(); |
1128 expect(n.needsRebuild, isTrue); | 1108 expect(n.needsRebuild, isTrue); |
1129 }); | 1109 }); |
1130 | 1110 |
1131 test('non-existing files are tracked in dependencies', () { | 1111 test('non-existing files are tracked in dependencies', () { |
1132 var s1 = | 1112 var s1 = testResourceProvider |
1133 new InMemorySource(new Uri.file('/foo.dart'), "import 'bar.dart';"); | 1113 .newFile('/foo.dart', "import 'bar.dart';") |
1134 testUriResolver.files[s1.uri] = s1; | 1114 .createSource(); |
1135 var node = nodeOf('/foo.dart'); | 1115 var node = nodeOf('/foo.dart'); |
1136 rebuild(node, buildNoTransitiveChange); | 1116 rebuild(node, buildNoTransitiveChange); |
1137 expect(node.allDeps.length, 1); | 1117 expect(node.allDeps.length, 1); |
1138 expect(node.allDeps.contains(nodeOf('/bar.dart')), isTrue); | 1118 expect(node.allDeps.contains(nodeOf('/bar.dart')), isTrue); |
1139 expect(nodeOf('/bar.dart').source, isNull); | 1119 expect(nodeOf('/bar.dart').source.exists(), isFalse); |
1140 | 1120 |
1141 var s2 = new InMemorySource(new Uri.file('/bar.dart'), "hi"); | 1121 var s2 = testResourceProvider.newFile('/bar.dart', 'hi').createSource(); |
1142 testUriResolver.files[s2.uri] = s2; | |
1143 results = []; | 1122 results = []; |
1144 rebuild(node, buildWithTransitiveChange); | 1123 rebuild(node, buildWithTransitiveChange); |
1145 expect(results, ['bar.dart', 'foo.dart']); | 1124 expect(results, ['bar.dart', 'foo.dart']); |
1146 }); | 1125 }); |
1147 }); | 1126 }); |
1148 }); | 1127 }); |
1149 } | 1128 } |
1150 | 1129 |
1151 expectGraph(SourceNode node, String expectation) { | 1130 expectGraph(SourceNode node, String expectation) { |
1152 expect(printReachable(node), equalsIgnoringWhitespace(expectation)); | 1131 expect(printReachable(node), equalsIgnoringWhitespace(expectation)); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1190 helper(node); | 1169 helper(node); |
1191 return sb.toString(); | 1170 return sb.toString(); |
1192 } | 1171 } |
1193 | 1172 |
1194 final runtimeFilesWithoutPath = defaultRuntimeFiles | 1173 final runtimeFilesWithoutPath = defaultRuntimeFiles |
1195 .map((f) => f.replaceAll('dart/', '')) | 1174 .map((f) => f.replaceAll('dart/', '')) |
1196 .toList(growable: false); | 1175 .toList(growable: false); |
1197 final _RUNTIME_GRAPH = runtimeFilesWithoutPath.map((s) => '|-- $s').join('\n'); | 1176 final _RUNTIME_GRAPH = runtimeFilesWithoutPath.map((s) => '|-- $s').join('\n'); |
1198 final _RUNTIME_GRAPH_REBUILD = | 1177 final _RUNTIME_GRAPH_REBUILD = |
1199 runtimeFilesWithoutPath.map((s) => '|-- $s [needs-rebuild]').join('\n'); | 1178 runtimeFilesWithoutPath.map((s) => '|-- $s [needs-rebuild]').join('\n'); |
1200 | |
1201 bool _same(Set a, Set b) => a.length == b.length && a.containsAll(b); | |
OLD | NEW |