OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'package:expect/expect.dart'; | 6 import 'package:expect/expect.dart'; |
7 import 'package:async_helper/async_helper.dart'; | 7 import 'package:async_helper/async_helper.dart'; |
8 import 'package:compiler/src/compiler.dart'; | 8 import 'package:compiler/src/compiler.dart'; |
9 import 'package:compiler/src/diagnostics/messages.dart' show | 9 import 'package:compiler/src/diagnostics/messages.dart' show |
10 MessageKind; | 10 MessageKind; |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 Expect.equals(element, element.implementation); | 118 Expect.equals(element, element.implementation); |
119 | 119 |
120 if (checkHasBody) { | 120 if (checkHasBody) { |
121 expectHasBody(compiler, element); | 121 expectHasBody(compiler, element); |
122 } | 122 } |
123 } | 123 } |
124 Expect.isFalse(element.isPatched && element.isPatch); | 124 Expect.isFalse(element.isPatched && element.isPatch); |
125 return element; | 125 return element; |
126 } | 126 } |
127 | 127 |
128 testPatchFunction() { | 128 Future testPatchFunction() async { |
129 asyncTest(() => applyPatch( | 129 var compiler = await applyPatch( |
130 "external test();", | 130 "external test();", |
131 "@patch test() { return 'string'; } ").then((compiler) { | 131 "@patch test() { return 'string'; } "); |
132 ensure(compiler, "test", compiler.coreLibrary.find, | 132 ensure(compiler, "test", compiler.coreLibrary.find, |
133 expectIsPatched: true, checkHasBody: true); | 133 expectIsPatched: true, checkHasBody: true); |
134 ensure(compiler, "test", compiler.coreLibrary.patch.find, | 134 ensure(compiler, "test", compiler.coreLibrary.patch.find, |
135 expectIsPatch: true, checkHasBody: true); | 135 expectIsPatch: true, checkHasBody: true); |
136 | 136 |
137 Expect.isTrue(compiler.warnings.isEmpty, | 137 Expect.isTrue(compiler.warnings.isEmpty, |
138 "Unexpected warnings: ${compiler.warnings}"); | 138 "Unexpected warnings: ${compiler.warnings}"); |
139 Expect.isTrue(compiler.errors.isEmpty, | 139 Expect.isTrue(compiler.errors.isEmpty, |
140 "Unexpected errors: ${compiler.errors}"); | 140 "Unexpected errors: ${compiler.errors}"); |
141 })); | 141 } |
| 142 |
| 143 Future testPatchFunctionMetadata() async { |
| 144 var compiler = await applyPatch( |
| 145 """ |
| 146 const a = 0; |
| 147 @a external test(); |
| 148 """, |
| 149 """ |
| 150 const b = 1; |
| 151 @patch @b test() {} |
| 152 """); |
| 153 Element origin = ensure(compiler, "test", compiler.coreLibrary.find, |
| 154 expectIsPatched: true, checkHasBody: true); |
| 155 Element patch = ensure(compiler, "test", compiler.coreLibrary.patch.find, |
| 156 expectIsPatch: true, checkHasBody: true); |
| 157 |
| 158 Expect.isTrue(compiler.warnings.isEmpty, |
| 159 "Unexpected warnings: ${compiler.warnings}"); |
| 160 Expect.isTrue(compiler.errors.isEmpty, |
| 161 "Unexpected errors: ${compiler.errors}"); |
| 162 |
| 163 Expect.equals(1, origin.metadata.length, |
| 164 "Unexpected origin metadata: ${origin.metadata}."); |
| 165 Expect.equals(3, patch.metadata.length, |
| 166 "Unexpected patch metadata: ${patch.metadata}."); |
142 } | 167 } |
143 | 168 |
144 | 169 |
145 testPatchVersioned() { | 170 Future testPatchVersioned() async { |
146 String fullPatch = "test(){return 'string';}"; | 171 String fullPatch = "test(){return 'string';}"; |
147 String lazyPatch = "test(){return 'new and improved string';}"; | 172 String lazyPatch = "test(){return 'new and improved string';}"; |
148 | 173 |
149 String patchSource = | 174 String patchSource = |
150 """ | 175 """ |
151 @patch_full $fullPatch | 176 @patch_full $fullPatch |
152 @patch_lazy $lazyPatch | 177 @patch_lazy $lazyPatch |
153 """; | 178 """; |
154 | 179 |
155 test(String patchVersion, | 180 Future test(String patchVersion, |
156 {String patchText, | 181 {String patchText, |
157 bool expectIsPatched: true, | 182 bool expectIsPatched: true, |
158 String expectedError, | 183 String expectedError, |
159 String defaultPatch: '', | 184 String defaultPatch: '', |
160 String expectedInternalError}) { | 185 String expectedInternalError}) async { |
161 asyncTest(() => applyPatch( | 186 return applyPatch( |
162 "external test();", | 187 "external test();", |
163 """ | 188 """ |
164 $defaultPatch | 189 $defaultPatch |
165 $patchSource | 190 $patchSource |
166 """, | 191 """, |
167 patchVersion: patchVersion).then((compiler) { | 192 patchVersion: patchVersion).then((compiler) { |
168 Element origin = | 193 Element origin = |
169 ensure(compiler, "test", compiler.coreLibrary.find, | 194 ensure(compiler, "test", compiler.coreLibrary.find, |
170 expectIsPatched: expectIsPatched, checkHasBody: true); | 195 expectIsPatched: expectIsPatched, checkHasBody: true); |
171 if (expectIsPatched) { | 196 if (expectIsPatched) { |
172 AstElement patch = | 197 AstElement patch = |
173 ensure(compiler, "test", compiler.coreLibrary.patch.find, | 198 ensure(compiler, "test", compiler.coreLibrary.patch.find, |
174 expectIsPatch: true, checkHasBody: true); | 199 expectIsPatch: true, checkHasBody: true); |
175 Expect.equals(origin.patch, patch); | 200 Expect.equals(origin.patch, patch); |
176 Expect.equals(patch.origin, origin); | 201 Expect.equals(patch.origin, origin); |
177 Expect.equals(patchText, patch.node.toString()); | 202 Expect.equals(patchText, patch.node.toString()); |
178 } | 203 } |
179 | 204 |
180 compiler.analyzeElement(origin); | 205 compiler.analyzeElement(origin); |
181 compiler.enqueuer.resolution.emptyDeferredTaskQueue(); | 206 compiler.enqueuer.resolution.emptyDeferredTaskQueue(); |
182 | 207 |
183 Expect.isTrue(compiler.warnings.isEmpty, | 208 Expect.isTrue(compiler.warnings.isEmpty, |
184 "Unexpected warnings: ${compiler.warnings}"); | 209 "Unexpected warnings: ${compiler.warnings}"); |
185 if (expectedError != null) { | 210 if (expectedError != null) { |
186 Expect.equals(expectedError, | 211 Expect.equals(expectedError, |
187 compiler.errors[0].message.toString()); | 212 compiler.errors[0].message.toString()); |
188 } else { | 213 } else { |
189 Expect.isTrue(compiler.errors.isEmpty, | 214 Expect.isTrue(compiler.errors.isEmpty, |
190 "Unexpected errors: ${compiler.errors}"); | 215 "Unexpected errors: ${compiler.errors}"); |
191 } | 216 } |
192 }).catchError((error) { | 217 }).catchError((error) { |
193 if (expectedInternalError != null) { | 218 if (expectedInternalError != null) { |
194 Expect.equals( | 219 Expect.equals( |
195 'Internal Error: $expectedInternalError', error.toString()); | 220 'Internal Error: $expectedInternalError', error.toString()); |
196 } else { | 221 } else { |
197 throw error; | 222 throw error; |
198 } | 223 } |
199 })); | 224 }); |
200 } | 225 } |
201 | 226 |
202 test('full', patchText: fullPatch); | 227 await test('full', patchText: fullPatch); |
203 test('lazy', patchText: lazyPatch); | 228 await test('lazy', patchText: lazyPatch); |
204 test('unknown', expectIsPatched: false, | 229 await test('unknown', expectIsPatched: false, |
205 expectedError: 'External method without an implementation.'); | 230 expectedError: 'External method without an implementation.'); |
206 test('full', | 231 await test('full', |
207 defaultPatch: "@patch test(){}", | 232 defaultPatch: "@patch test(){}", |
208 expectedInternalError: "Trying to patch a function more than once."); | 233 expectedInternalError: "Trying to patch a function more than once."); |
209 } | 234 } |
210 | 235 |
211 testPatchConstructor() { | 236 Future testPatchConstructor() async { |
212 asyncTest(() => applyPatch( | 237 var compiler = await applyPatch( |
213 """ | 238 """ |
214 class Class { | 239 class Class { |
215 external Class(); | 240 external Class(); |
216 } | 241 } |
217 """, | 242 """, |
218 """ | 243 """ |
219 @patch class Class { | 244 @patch class Class { |
220 @patch Class(); | 245 @patch Class(); |
221 } | 246 } |
222 """).then((compiler) { | 247 """); |
223 var classOrigin = ensure(compiler, "Class", compiler.coreLibrary.find, | 248 var classOrigin = ensure(compiler, "Class", compiler.coreLibrary.find, |
224 expectIsPatched: true); | 249 expectIsPatched: true); |
225 classOrigin.ensureResolved(compiler); | 250 classOrigin.ensureResolved(compiler); |
226 var classPatch = ensure(compiler, "Class", compiler.coreLibrary.patch.find, | 251 var classPatch = ensure(compiler, "Class", compiler.coreLibrary.patch.find, |
227 expectIsPatch: true); | 252 expectIsPatch: true); |
228 | 253 |
229 Expect.equals(classPatch, classOrigin.patch); | 254 Expect.equals(classPatch, classOrigin.patch); |
230 Expect.equals(classOrigin, classPatch.origin); | 255 Expect.equals(classOrigin, classPatch.origin); |
231 | 256 |
232 var constructorOrigin = ensure(compiler, "", | 257 var constructorOrigin = ensure(compiler, "", |
233 (name) => classOrigin.localLookup(name), | 258 (name) => classOrigin.localLookup(name), |
234 expectIsPatched: true); | 259 expectIsPatched: true); |
235 var constructorPatch = ensure(compiler, "", | 260 var constructorPatch = ensure(compiler, "", |
236 (name) => classPatch.localLookup(name), | 261 (name) => classPatch.localLookup(name), |
237 expectIsPatch: true); | 262 expectIsPatch: true); |
238 | 263 |
239 Expect.equals(constructorPatch, constructorOrigin.patch); | 264 Expect.equals(constructorPatch, constructorOrigin.patch); |
240 Expect.equals(constructorOrigin, constructorPatch.origin); | 265 Expect.equals(constructorOrigin, constructorPatch.origin); |
241 | 266 |
242 Expect.isTrue(compiler.warnings.isEmpty, | 267 Expect.isTrue(compiler.warnings.isEmpty, |
243 "Unexpected warnings: ${compiler.warnings}"); | 268 "Unexpected warnings: ${compiler.warnings}"); |
244 Expect.isTrue(compiler.errors.isEmpty, | 269 Expect.isTrue(compiler.errors.isEmpty, |
245 "Unexpected errors: ${compiler.errors}"); | 270 "Unexpected errors: ${compiler.errors}"); |
246 })); | |
247 } | 271 } |
248 | 272 |
249 testPatchRedirectingConstructor() { | 273 Future testPatchRedirectingConstructor() async { |
250 asyncTest(() => applyPatch( | 274 var compiler = await applyPatch( |
251 """ | 275 """ |
252 class Class { | 276 class Class { |
253 Class(x) : this._(x, false); | 277 Class(x) : this._(x, false); |
254 | 278 |
255 external Class._(x, y); | 279 external Class._(x, y); |
256 } | 280 } |
257 """, | 281 """, |
258 r""" | 282 r""" |
259 @patch class Class { | 283 @patch class Class { |
260 @patch Class._(x, y) { print('$x,$y'); } | 284 @patch Class._(x, y) { print('$x,$y'); } |
261 } | 285 } |
262 """).then((compiler) { | 286 """); |
263 var classOrigin = ensure(compiler, "Class", compiler.coreLibrary.find, | 287 var classOrigin = ensure(compiler, "Class", compiler.coreLibrary.find, |
264 expectIsPatched: true); | 288 expectIsPatched: true); |
265 classOrigin.ensureResolved(compiler); | 289 classOrigin.ensureResolved(compiler); |
266 | 290 |
267 var classPatch = ensure(compiler, "Class", compiler.coreLibrary.patch.find, | 291 var classPatch = ensure(compiler, "Class", compiler.coreLibrary.patch.find, |
268 expectIsPatch: true); | 292 expectIsPatch: true); |
269 | 293 |
270 Expect.equals(classOrigin, classPatch.origin); | 294 Expect.equals(classOrigin, classPatch.origin); |
271 Expect.equals(classPatch, classOrigin.patch); | 295 Expect.equals(classPatch, classOrigin.patch); |
272 | 296 |
273 var constructorRedirecting = | 297 var constructorRedirecting = |
274 ensure(compiler, "", | 298 ensure(compiler, "", |
275 (name) => classOrigin.localLookup(name)); | 299 (name) => classOrigin.localLookup(name)); |
276 var constructorOrigin = | 300 var constructorOrigin = |
277 ensure(compiler, "_", | 301 ensure(compiler, "_", |
278 (name) => classOrigin.localLookup(name), | 302 (name) => classOrigin.localLookup(name), |
279 expectIsPatched: true); | 303 expectIsPatched: true); |
280 var constructorPatch = | 304 var constructorPatch = |
281 ensure(compiler, "_", | 305 ensure(compiler, "_", |
282 (name) => classPatch.localLookup(name), | 306 (name) => classPatch.localLookup(name), |
283 expectIsPatch: true); | 307 expectIsPatch: true); |
284 Expect.equals(constructorOrigin, constructorPatch.origin); | 308 Expect.equals(constructorOrigin, constructorPatch.origin); |
285 Expect.equals(constructorPatch, constructorOrigin.patch); | 309 Expect.equals(constructorPatch, constructorOrigin.patch); |
286 | 310 |
287 compiler.resolver.resolve(constructorRedirecting); | 311 compiler.resolver.resolve(constructorRedirecting); |
288 | 312 |
289 Expect.isTrue(compiler.warnings.isEmpty, | 313 Expect.isTrue(compiler.warnings.isEmpty, |
290 "Unexpected warnings: ${compiler.warnings}"); | 314 "Unexpected warnings: ${compiler.warnings}"); |
291 Expect.isTrue(compiler.errors.isEmpty, | 315 Expect.isTrue(compiler.errors.isEmpty, |
292 "Unexpected errors: ${compiler.errors}"); | 316 "Unexpected errors: ${compiler.errors}"); |
293 })); | |
294 } | 317 } |
295 | 318 |
296 testPatchMember() { | 319 Future testPatchMember() async { |
297 asyncTest(() => applyPatch( | 320 var compiler = await applyPatch( |
298 """ | 321 """ |
299 class Class { | 322 class Class { |
300 external String toString(); | 323 external String toString(); |
301 } | 324 } |
302 """, | 325 """, |
303 """ | 326 """ |
304 @patch class Class { | 327 @patch class Class { |
305 @patch String toString() => 'string'; | 328 @patch String toString() => 'string'; |
306 } | 329 } |
307 """).then((compiler) { | 330 """); |
308 var container = ensure(compiler, "Class", compiler.coreLibrary.find, | 331 var container = ensure(compiler, "Class", compiler.coreLibrary.find, |
309 expectIsPatched: true); | 332 expectIsPatched: true); |
310 container.parseNode(compiler); | 333 container.parseNode(compiler); |
311 ensure(compiler, "Class", compiler.coreLibrary.patch.find, | 334 ensure(compiler, "Class", compiler.coreLibrary.patch.find, |
312 expectIsPatch: true); | 335 expectIsPatch: true); |
313 | 336 |
314 ensure(compiler, "toString", container.lookupLocalMember, | 337 ensure(compiler, "toString", container.lookupLocalMember, |
315 expectIsPatched: true, checkHasBody: true); | 338 expectIsPatched: true, checkHasBody: true); |
316 ensure(compiler, "toString", container.patch.lookupLocalMember, | 339 ensure(compiler, "toString", container.patch.lookupLocalMember, |
317 expectIsPatch: true, checkHasBody: true); | 340 expectIsPatch: true, checkHasBody: true); |
318 | 341 |
319 Expect.isTrue(compiler.warnings.isEmpty, | 342 Expect.isTrue(compiler.warnings.isEmpty, |
320 "Unexpected warnings: ${compiler.warnings}"); | 343 "Unexpected warnings: ${compiler.warnings}"); |
321 Expect.isTrue(compiler.errors.isEmpty, | 344 Expect.isTrue(compiler.errors.isEmpty, |
322 "Unexpected errors: ${compiler.errors}"); | 345 "Unexpected errors: ${compiler.errors}"); |
323 })); | |
324 } | 346 } |
325 | 347 |
326 testPatchGetter() { | 348 Future testPatchGetter() async { |
327 asyncTest(() => applyPatch( | 349 var compiler = await applyPatch( |
328 """ | 350 """ |
329 class Class { | 351 class Class { |
330 external int get field; | 352 external int get field; |
331 } | 353 } |
332 """, | 354 """, |
333 """ | 355 """ |
334 @patch class Class { | 356 @patch class Class { |
335 @patch int get field => 5; | 357 @patch int get field => 5; |
336 } | 358 } |
337 """).then((compiler) { | 359 """); |
338 var container = ensure(compiler, "Class", compiler.coreLibrary.find, | 360 var container = ensure(compiler, "Class", compiler.coreLibrary.find, |
339 expectIsPatched: true); | 361 expectIsPatched: true); |
340 container.parseNode(compiler); | 362 container.parseNode(compiler); |
341 ensure(compiler, | 363 ensure(compiler, |
342 "field", | 364 "field", |
343 container.lookupLocalMember, | 365 container.lookupLocalMember, |
344 expectIsGetter: true, | 366 expectIsGetter: true, |
345 expectIsPatched: true, | 367 expectIsPatched: true, |
346 checkHasBody: true); | 368 checkHasBody: true); |
347 ensure(compiler, | 369 ensure(compiler, |
348 "field", | 370 "field", |
349 container.patch.lookupLocalMember, | 371 container.patch.lookupLocalMember, |
350 expectIsGetter: true, | 372 expectIsGetter: true, |
351 expectIsPatch: true, | 373 expectIsPatch: true, |
352 checkHasBody: true); | 374 checkHasBody: true); |
353 | 375 |
354 Expect.isTrue(compiler.warnings.isEmpty, | 376 Expect.isTrue(compiler.warnings.isEmpty, |
355 "Unexpected warnings: ${compiler.warnings}"); | 377 "Unexpected warnings: ${compiler.warnings}"); |
356 Expect.isTrue(compiler.errors.isEmpty, | 378 Expect.isTrue(compiler.errors.isEmpty, |
357 "Unexpected errors: ${compiler.errors}"); | 379 "Unexpected errors: ${compiler.errors}"); |
358 })); | |
359 } | 380 } |
360 | 381 |
361 testRegularMember() { | 382 Future testRegularMember() async { |
362 asyncTest(() => applyPatch( | 383 var compiler = await applyPatch( |
363 """ | 384 """ |
364 class Class { | 385 class Class { |
365 void regular() {} | 386 void regular() {} |
366 } | 387 } |
367 """, | 388 """, |
368 """ | 389 """ |
369 @patch class Class { | 390 @patch class Class { |
370 } | 391 } |
371 """).then((compiler) { | 392 """); |
372 var container = ensure(compiler, "Class", compiler.coreLibrary.find, | 393 var container = ensure(compiler, "Class", compiler.coreLibrary.find, |
373 expectIsPatched: true); | 394 expectIsPatched: true); |
374 container.parseNode(compiler); | 395 container.parseNode(compiler); |
375 ensure(compiler, "Class", compiler.coreLibrary.patch.find, | 396 ensure(compiler, "Class", compiler.coreLibrary.patch.find, |
376 expectIsPatch: true); | 397 expectIsPatch: true); |
377 | 398 |
378 ensure(compiler, "regular", container.lookupLocalMember, | 399 ensure(compiler, "regular", container.lookupLocalMember, |
379 checkHasBody: true, expectIsRegular: true); | 400 checkHasBody: true, expectIsRegular: true); |
380 ensure(compiler, "regular", container.patch.lookupLocalMember, | 401 ensure(compiler, "regular", container.patch.lookupLocalMember, |
381 checkHasBody: true, expectIsRegular: true); | 402 checkHasBody: true, expectIsRegular: true); |
382 | 403 |
383 Expect.isTrue(compiler.warnings.isEmpty, | 404 Expect.isTrue(compiler.warnings.isEmpty, |
384 "Unexpected warnings: ${compiler.warnings}"); | 405 "Unexpected warnings: ${compiler.warnings}"); |
385 Expect.isTrue(compiler.errors.isEmpty, | 406 Expect.isTrue(compiler.errors.isEmpty, |
386 "Unexpected errors: ${compiler.errors}"); | 407 "Unexpected errors: ${compiler.errors}"); |
387 })); | |
388 } | 408 } |
389 | 409 |
390 testGhostMember() { | 410 Future testGhostMember() async { |
391 asyncTest(() => applyPatch( | 411 var compiler = await applyPatch( |
392 """ | 412 """ |
393 class Class { | 413 class Class { |
394 } | 414 } |
395 """, | 415 """, |
396 """ | 416 """ |
397 @patch class Class { | 417 @patch class Class { |
398 void ghost() {} | 418 void ghost() {} |
399 } | 419 } |
400 """).then((compiler) { | 420 """); |
401 var container = ensure(compiler, "Class", compiler.coreLibrary.find, | 421 var container = ensure(compiler, "Class", compiler.coreLibrary.find, |
402 expectIsPatched: true); | 422 expectIsPatched: true); |
403 container.parseNode(compiler); | 423 container.parseNode(compiler); |
404 ensure(compiler, "Class", compiler.coreLibrary.patch.find, | 424 ensure(compiler, "Class", compiler.coreLibrary.patch.find, |
405 expectIsPatch: true); | 425 expectIsPatch: true); |
406 | 426 |
407 ensure(compiler, "ghost", container.lookupLocalMember, | 427 ensure(compiler, "ghost", container.lookupLocalMember, |
408 expectIsFound: false); | 428 expectIsFound: false); |
409 ensure(compiler, "ghost", container.patch.lookupLocalMember, | 429 ensure(compiler, "ghost", container.patch.lookupLocalMember, |
410 checkHasBody: true, expectIsRegular: true); | 430 checkHasBody: true, expectIsRegular: true); |
411 | 431 |
412 Expect.isTrue(compiler.warnings.isEmpty, | 432 Expect.isTrue(compiler.warnings.isEmpty, |
413 "Unexpected warnings: ${compiler.warnings}"); | 433 "Unexpected warnings: ${compiler.warnings}"); |
414 Expect.isTrue(compiler.errors.isEmpty, | 434 Expect.isTrue(compiler.errors.isEmpty, |
415 "Unexpected errors: ${compiler.errors}"); | 435 "Unexpected errors: ${compiler.errors}"); |
416 })); | |
417 } | 436 } |
418 | 437 |
419 testInjectFunction() { | 438 Future testInjectFunction() async { |
420 asyncTest(() => applyPatch( | 439 var compiler = await applyPatch( |
421 "", | 440 "", |
422 "int _function() => 5;").then((compiler) { | 441 "int _function() => 5;"); |
423 ensure(compiler, | 442 ensure(compiler, |
424 "_function", | 443 "_function", |
425 compiler.coreLibrary.find, | 444 compiler.coreLibrary.find, |
426 expectIsFound: false); | 445 expectIsFound: false); |
427 ensure(compiler, | 446 ensure(compiler, |
428 "_function", | 447 "_function", |
429 compiler.coreLibrary.patch.find, | 448 compiler.coreLibrary.patch.find, |
430 checkHasBody: true, expectIsRegular: true); | 449 checkHasBody: true, expectIsRegular: true); |
431 | 450 |
432 Expect.isTrue(compiler.warnings.isEmpty, | 451 Expect.isTrue(compiler.warnings.isEmpty, |
433 "Unexpected warnings: ${compiler.warnings}"); | 452 "Unexpected warnings: ${compiler.warnings}"); |
434 Expect.isTrue(compiler.errors.isEmpty, | 453 Expect.isTrue(compiler.errors.isEmpty, |
435 "Unexpected errors: ${compiler.errors}"); | 454 "Unexpected errors: ${compiler.errors}"); |
436 })); | |
437 } | 455 } |
438 | 456 |
439 testPatchSignatureCheck() { | 457 Future testPatchSignatureCheck() async { |
440 asyncTest(() => applyPatch( | 458 var compiler = await applyPatch( |
441 """ | 459 """ |
442 class Class { | 460 class Class { |
443 external String method1(); | 461 external String method1(); |
444 external void method2(String str); | 462 external void method2(String str); |
445 external void method3(String s1); | 463 external void method3(String s1); |
446 external void method4([String str]); | 464 external void method4([String str]); |
447 external void method5({String str}); | 465 external void method5({String str}); |
448 external void method6({String str}); | 466 external void method6({String str}); |
449 external void method7([String s1]); | 467 external void method7([String s1]); |
450 external void method8({String s1}); | 468 external void method8({String s1}); |
451 external void method9(String str); | 469 external void method9(String str); |
452 external void method10([String str]); | 470 external void method10([String str]); |
453 external void method11({String str}); | 471 external void method11({String str}); |
454 } | 472 } |
455 """, | 473 """, |
456 """ | 474 """ |
457 @patch class Class { | 475 @patch class Class { |
458 @patch int method1() => 0; | 476 @patch int method1() => 0; |
459 @patch void method2() {} | 477 @patch void method2() {} |
460 @patch void method3(String s2) {} | 478 @patch void method3(String s2) {} |
461 @patch void method4([String str, int i]) {} | 479 @patch void method4([String str, int i]) {} |
462 @patch void method5() {} | 480 @patch void method5() {} |
463 @patch void method6([String str]) {} | 481 @patch void method6([String str]) {} |
464 @patch void method7([String s2]) {} | 482 @patch void method7([String s2]) {} |
465 @patch void method8({String s2}) {} | 483 @patch void method8({String s2}) {} |
466 @patch void method9(int str) {} | 484 @patch void method9(int str) {} |
467 @patch void method10([int str]) {} | 485 @patch void method10([int str]) {} |
468 @patch void method11({int str}) {} | 486 @patch void method11({int str}) {} |
469 } | 487 } |
470 """).then((compiler) { | 488 """); |
471 var container = ensure(compiler, "Class", compiler.coreLibrary.find, | 489 var container = ensure(compiler, "Class", compiler.coreLibrary.find, |
472 expectIsPatched: true); | 490 expectIsPatched: true); |
473 container.ensureResolved(compiler); | 491 container.ensureResolved(compiler); |
474 container.parseNode(compiler); | 492 container.parseNode(compiler); |
475 | 493 |
476 void expect(String methodName, List infos, List errors) { | 494 void expect(String methodName, List infos, List errors) { |
477 compiler.clearMessages(); | 495 compiler.clearMessages(); |
478 compiler.resolver.resolveMethodElement( | 496 compiler.resolver.resolveMethodElement( |
479 ensure(compiler, methodName, container.lookupLocalMember, | 497 ensure(compiler, methodName, container.lookupLocalMember, |
480 expectIsPatched: true, checkHasBody: true)); | 498 expectIsPatched: true, checkHasBody: true)); |
481 Expect.equals(0, compiler.warnings.length); | 499 Expect.equals(0, compiler.warnings.length); |
482 Expect.equals(infos.length, compiler.infos.length, | 500 Expect.equals(infos.length, compiler.infos.length, |
483 "Unexpected infos: ${compiler.infos} on $methodName"); | 501 "Unexpected infos: ${compiler.infos} on $methodName"); |
484 for (int i = 0 ; i < infos.length ; i++) { | 502 for (int i = 0 ; i < infos.length ; i++) { |
485 Expect.equals(infos[i], compiler.infos[i].message.kind); | 503 Expect.equals(infos[i], compiler.infos[i].message.kind); |
486 } | |
487 Expect.equals(errors.length, compiler.errors.length, | |
488 "Unexpected errors: ${compiler.errors} on $methodName"); | |
489 for (int i = 0 ; i < errors.length ; i++) { | |
490 Expect.equals(errors[i], compiler.errors[i].message.kind); | |
491 } | |
492 } | 504 } |
| 505 Expect.equals(errors.length, compiler.errors.length, |
| 506 "Unexpected errors: ${compiler.errors} on $methodName"); |
| 507 for (int i = 0 ; i < errors.length ; i++) { |
| 508 Expect.equals(errors[i], compiler.errors[i].message.kind); |
| 509 } |
| 510 } |
493 | 511 |
494 expect("method1", [], [MessageKind.PATCH_RETURN_TYPE_MISMATCH]); | 512 expect("method1", [], [MessageKind.PATCH_RETURN_TYPE_MISMATCH]); |
495 expect("method2", [], | 513 expect("method2", [], |
496 [MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH]); | 514 [MessageKind.PATCH_REQUIRED_PARAMETER_COUNT_MISMATCH]); |
497 expect("method3", [MessageKind.PATCH_POINT_TO_PARAMETER], | 515 expect("method3", [MessageKind.PATCH_POINT_TO_PARAMETER], |
498 [MessageKind.PATCH_PARAMETER_MISMATCH]); | 516 [MessageKind.PATCH_PARAMETER_MISMATCH]); |
499 expect("method4", [], | 517 expect("method4", [], |
500 [MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH]); | 518 [MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH]); |
501 expect("method5", [], | 519 expect("method5", [], |
502 [MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH]); | 520 [MessageKind.PATCH_OPTIONAL_PARAMETER_COUNT_MISMATCH]); |
503 expect("method6", [], | 521 expect("method6", [], |
504 [MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH]); | 522 [MessageKind.PATCH_OPTIONAL_PARAMETER_NAMED_MISMATCH]); |
505 expect("method7", [MessageKind.PATCH_POINT_TO_PARAMETER], | 523 expect("method7", [MessageKind.PATCH_POINT_TO_PARAMETER], |
506 [MessageKind.PATCH_PARAMETER_MISMATCH]); | 524 [MessageKind.PATCH_PARAMETER_MISMATCH]); |
507 expect("method8", [MessageKind.PATCH_POINT_TO_PARAMETER], | 525 expect("method8", [MessageKind.PATCH_POINT_TO_PARAMETER], |
508 [MessageKind.PATCH_PARAMETER_MISMATCH]); | 526 [MessageKind.PATCH_PARAMETER_MISMATCH]); |
509 expect("method9", [MessageKind.PATCH_POINT_TO_PARAMETER], | 527 expect("method9", [MessageKind.PATCH_POINT_TO_PARAMETER], |
510 [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]); | 528 [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]); |
511 expect("method10", [MessageKind.PATCH_POINT_TO_PARAMETER], | 529 expect("method10", [MessageKind.PATCH_POINT_TO_PARAMETER], |
512 [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]); | 530 [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]); |
513 expect("method11", [MessageKind.PATCH_POINT_TO_PARAMETER], | 531 expect("method11", [MessageKind.PATCH_POINT_TO_PARAMETER], |
514 [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]); | 532 [MessageKind.PATCH_PARAMETER_TYPE_MISMATCH]); |
515 })); | |
516 } | 533 } |
517 | 534 |
518 testExternalWithoutImplementationTopLevel() { | 535 Future testExternalWithoutImplementationTopLevel() async { |
519 asyncTest(() => applyPatch( | 536 var compiler = await applyPatch( |
520 """ | 537 """ |
521 external void foo(); | 538 external void foo(); |
522 """, | 539 """, |
523 """ | 540 """ |
524 // @patch void foo() {} | 541 // @patch void foo() {} |
525 """).then((compiler) { | 542 """); |
526 var function = ensure(compiler, "foo", compiler.coreLibrary.find); | 543 var function = ensure(compiler, "foo", compiler.coreLibrary.find); |
527 compiler.resolver.resolve(function); | 544 compiler.resolver.resolve(function); |
528 Expect.isTrue(compiler.warnings.isEmpty, | 545 Expect.isTrue(compiler.warnings.isEmpty, |
529 "Unexpected warnings: ${compiler.warnings}"); | 546 "Unexpected warnings: ${compiler.warnings}"); |
530 print('testExternalWithoutImplementationTopLevel:${compiler.errors}'); | 547 print('testExternalWithoutImplementationTopLevel:${compiler.errors}'); |
531 Expect.equals(1, compiler.errors.length); | 548 Expect.equals(1, compiler.errors.length); |
532 Expect.isTrue( | 549 Expect.isTrue( |
533 compiler.errors[0].message.kind == | 550 compiler.errors[0].message.kind == |
534 MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION); | 551 MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION); |
535 Expect.stringEquals('External method without an implementation.', | 552 Expect.stringEquals('External method without an implementation.', |
536 compiler.errors[0].message.toString()); | 553 compiler.errors[0].message.toString()); |
537 })); | |
538 } | 554 } |
539 | 555 |
540 testExternalWithoutImplementationMember() { | 556 Future testExternalWithoutImplementationMember() async { |
541 asyncTest(() => applyPatch( | 557 var compiler = await applyPatch( |
542 """ | 558 """ |
543 class Class { | 559 class Class { |
544 external void foo(); | 560 external void foo(); |
545 } | 561 } |
546 """, | 562 """, |
547 """ | 563 """ |
548 @patch class Class { | 564 @patch class Class { |
549 // @patch void foo() {} | 565 // @patch void foo() {} |
550 } | 566 } |
551 """).then((compiler) { | 567 """); |
552 var container = ensure(compiler, "Class", compiler.coreLibrary.find, | 568 var container = ensure(compiler, "Class", compiler.coreLibrary.find, |
553 expectIsPatched: true); | 569 expectIsPatched: true); |
554 container.parseNode(compiler); | 570 container.parseNode(compiler); |
555 | 571 |
556 compiler.warnings.clear(); | 572 compiler.warnings.clear(); |
557 compiler.errors.clear(); | 573 compiler.errors.clear(); |
558 compiler.resolver.resolveMethodElement( | 574 compiler.resolver.resolveMethodElement( |
559 ensure(compiler, "foo", container.lookupLocalMember)); | 575 ensure(compiler, "foo", container.lookupLocalMember)); |
560 Expect.isTrue(compiler.warnings.isEmpty, | 576 Expect.isTrue(compiler.warnings.isEmpty, |
561 "Unexpected warnings: ${compiler.warnings}"); | 577 "Unexpected warnings: ${compiler.warnings}"); |
562 print('testExternalWithoutImplementationMember:${compiler.errors}'); | 578 print('testExternalWithoutImplementationMember:${compiler.errors}'); |
563 Expect.equals(1, compiler.errors.length); | 579 Expect.equals(1, compiler.errors.length); |
564 Expect.isTrue( | 580 Expect.isTrue( |
565 compiler.errors[0].message.kind == | 581 compiler.errors[0].message.kind == |
566 MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION); | 582 MessageKind.PATCH_EXTERNAL_WITHOUT_IMPLEMENTATION); |
567 Expect.stringEquals('External method without an implementation.', | 583 Expect.stringEquals('External method without an implementation.', |
568 compiler.errors[0].message.toString()); | 584 compiler.errors[0].message.toString()); |
569 })); | |
570 } | 585 } |
571 | 586 |
572 testIsSubclass() { | 587 Future testIsSubclass() async { |
573 asyncTest(() => applyPatch( | 588 var compiler = await applyPatch( |
574 """ | 589 """ |
575 class A {} | 590 class A {} |
576 """, | 591 """, |
577 """ | 592 """ |
578 @patch class A {} | 593 @patch class A {} |
579 """).then((compiler) { | 594 """); |
580 ClassElement cls = ensure(compiler, "A", compiler.coreLibrary.find, | 595 ClassElement cls = ensure(compiler, "A", compiler.coreLibrary.find, |
581 expectIsPatched: true); | 596 expectIsPatched: true); |
582 ClassElement patch = cls.patch; | 597 ClassElement patch = cls.patch; |
583 Expect.isTrue(cls != patch); | 598 Expect.isTrue(cls != patch); |
584 Expect.isTrue(cls.isSubclassOf(patch)); | 599 Expect.isTrue(cls.isSubclassOf(patch)); |
585 Expect.isTrue(patch.isSubclassOf(cls)); | 600 Expect.isTrue(patch.isSubclassOf(cls)); |
586 })); | |
587 } | 601 } |
588 | 602 |
589 testPatchNonExistingTopLevel() { | 603 Future testPatchNonExistingTopLevel() async { |
590 asyncTest(() => applyPatch( | 604 var compiler = await applyPatch( |
591 """ | 605 """ |
592 // class Class {} | 606 // class Class {} |
593 """, | 607 """, |
594 """ | 608 """ |
595 @patch class Class {} | 609 @patch class Class {} |
596 """).then((compiler) { | 610 """); |
597 Expect.isTrue(compiler.warnings.isEmpty, | 611 Expect.isTrue(compiler.warnings.isEmpty, |
598 "Unexpected warnings: ${compiler.warnings}"); | 612 "Unexpected warnings: ${compiler.warnings}"); |
599 print('testPatchNonExistingTopLevel:${compiler.errors}'); | 613 print('testPatchNonExistingTopLevel:${compiler.errors}'); |
600 Expect.equals(1, compiler.errors.length); | 614 Expect.equals(1, compiler.errors.length); |
601 Expect.isTrue( | 615 Expect.isTrue( |
602 compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXISTING); | 616 compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXISTING); |
603 })); | |
604 } | 617 } |
605 | 618 |
606 testPatchNonExistingMember() { | 619 Future testPatchNonExistingMember() async { |
607 asyncTest(() => applyPatch( | 620 var compiler = await applyPatch( |
608 """ | 621 """ |
609 class Class {} | 622 class Class {} |
610 """, | 623 """, |
611 """ | 624 """ |
612 @patch class Class { | 625 @patch class Class { |
613 @patch void foo() {} | 626 @patch void foo() {} |
614 } | 627 } |
615 """).then((compiler) { | 628 """); |
616 var container = ensure(compiler, "Class", compiler.coreLibrary.find, | 629 var container = ensure(compiler, "Class", compiler.coreLibrary.find, |
617 expectIsPatched: true); | 630 expectIsPatched: true); |
618 container.parseNode(compiler); | 631 container.parseNode(compiler); |
619 | 632 |
620 Expect.isTrue(compiler.warnings.isEmpty, | 633 Expect.isTrue(compiler.warnings.isEmpty, |
621 "Unexpected warnings: ${compiler.warnings}"); | 634 "Unexpected warnings: ${compiler.warnings}"); |
622 print('testPatchNonExistingMember:${compiler.errors}'); | 635 print('testPatchNonExistingMember:${compiler.errors}'); |
623 Expect.equals(1, compiler.errors.length); | 636 Expect.equals(1, compiler.errors.length); |
624 Expect.isTrue( | 637 Expect.isTrue( |
625 compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXISTING); | 638 compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXISTING); |
626 })); | |
627 } | 639 } |
628 | 640 |
629 testPatchNonPatchablePatch() { | 641 Future testPatchNonPatchablePatch() async { |
630 asyncTest(() => applyPatch( | 642 var compiler = await applyPatch( |
631 """ | 643 """ |
632 external get foo; | 644 external get foo; |
633 """, | 645 """, |
634 """ | 646 """ |
635 @patch var foo; | 647 @patch var foo; |
636 """).then((compiler) { | 648 """); |
637 ensure(compiler, "foo", compiler.coreLibrary.find); | 649 ensure(compiler, "foo", compiler.coreLibrary.find); |
638 | 650 |
639 Expect.isTrue(compiler.warnings.isEmpty, | 651 Expect.isTrue(compiler.warnings.isEmpty, |
640 "Unexpected warnings: ${compiler.warnings}"); | 652 "Unexpected warnings: ${compiler.warnings}"); |
641 print('testPatchNonPatchablePatch:${compiler.errors}'); | 653 print('testPatchNonPatchablePatch:${compiler.errors}'); |
642 Expect.equals(1, compiler.errors.length); | 654 Expect.equals(1, compiler.errors.length); |
643 Expect.isTrue( | 655 Expect.isTrue( |
644 compiler.errors[0].message.kind == MessageKind.PATCH_NONPATCHABLE); | 656 compiler.errors[0].message.kind == MessageKind.PATCH_NONPATCHABLE); |
645 })); | |
646 } | 657 } |
647 | 658 |
648 testPatchNonPatchableOrigin() { | 659 Future testPatchNonPatchableOrigin() async { |
649 asyncTest(() => applyPatch( | 660 var compiler = await applyPatch( |
650 """ | 661 """ |
651 external var foo; | 662 external var foo; |
652 """, | 663 """, |
653 """ | 664 """ |
654 @patch get foo => 0; | 665 @patch get foo => 0; |
655 """).then((compiler) { | 666 """); |
656 ensure(compiler, "foo", compiler.coreLibrary.find); | 667 ensure(compiler, "foo", compiler.coreLibrary.find); |
657 | 668 |
658 Expect.isTrue(compiler.warnings.isEmpty, | 669 Expect.isTrue(compiler.warnings.isEmpty, |
659 "Unexpected warnings: ${compiler.warnings}"); | 670 "Unexpected warnings: ${compiler.warnings}"); |
660 print('testPatchNonPatchableOrigin:${compiler.errors}'); | 671 print('testPatchNonPatchableOrigin:${compiler.errors}'); |
661 Expect.equals(2, compiler.errors.length); | 672 Expect.equals(2, compiler.errors.length); |
662 Expect.equals( | 673 Expect.equals( |
663 MessageKind.EXTRANEOUS_MODIFIER, compiler.errors[0].message.kind); | 674 MessageKind.EXTRANEOUS_MODIFIER, compiler.errors[0].message.kind); |
664 Expect.equals( | 675 Expect.equals( |
665 // TODO(ahe): Eventually, this error should be removed as it will be | 676 // TODO(ahe): Eventually, this error should be removed as it will be |
666 // handled by the regular parser. | 677 // handled by the regular parser. |
667 MessageKind.PATCH_NONPATCHABLE, compiler.errors[1].message.kind); | 678 MessageKind.PATCH_NONPATCHABLE, compiler.errors[1].message.kind); |
668 })); | |
669 } | 679 } |
670 | 680 |
671 testPatchNonExternalTopLevel() { | 681 Future testPatchNonExternalTopLevel() async { |
672 asyncTest(() => applyPatch( | 682 var compiler = await applyPatch( |
673 """ | 683 """ |
674 void foo() {} | 684 void foo() {} |
675 """, | 685 """, |
676 """ | 686 """ |
677 @patch void foo() {} | 687 @patch void foo() {} |
678 """).then((compiler) { | 688 """); |
679 print('testPatchNonExternalTopLevel.errors:${compiler.errors}'); | 689 print('testPatchNonExternalTopLevel.errors:${compiler.errors}'); |
680 print('testPatchNonExternalTopLevel.warnings:${compiler.warnings}'); | 690 print('testPatchNonExternalTopLevel.warnings:${compiler.warnings}'); |
681 Expect.equals(1, compiler.errors.length); | 691 Expect.equals(1, compiler.errors.length); |
682 Expect.isTrue( | 692 Expect.isTrue( |
683 compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXTERNAL); | 693 compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXTERNAL); |
684 Expect.equals(0, compiler.warnings.length); | 694 Expect.equals(0, compiler.warnings.length); |
685 Expect.equals(1, compiler.infos.length); | 695 Expect.equals(1, compiler.infos.length); |
686 Expect.isTrue(compiler.infos[0].message.kind == | 696 Expect.isTrue(compiler.infos[0].message.kind == |
687 MessageKind.PATCH_POINT_TO_FUNCTION); | 697 MessageKind.PATCH_POINT_TO_FUNCTION); |
688 })); | |
689 } | 698 } |
690 | 699 |
691 testPatchNonExternalMember() { | 700 Future testPatchNonExternalMember() async { |
692 asyncTest(() => applyPatch( | 701 var compiler = await applyPatch( |
693 """ | 702 """ |
694 class Class { | 703 class Class { |
695 void foo() {} | 704 void foo() {} |
696 } | 705 } |
697 """, | 706 """, |
698 """ | 707 """ |
699 @patch class Class { | 708 @patch class Class { |
700 @patch void foo() {} | 709 @patch void foo() {} |
701 } | 710 } |
702 """).then((compiler) { | 711 """); |
703 var container = ensure(compiler, "Class", compiler.coreLibrary.find, | 712 var container = ensure(compiler, "Class", compiler.coreLibrary.find, |
704 expectIsPatched: true); | 713 expectIsPatched: true); |
705 container.parseNode(compiler); | 714 container.parseNode(compiler); |
706 | 715 |
707 print('testPatchNonExternalMember.errors:${compiler.errors}'); | 716 print('testPatchNonExternalMember.errors:${compiler.errors}'); |
708 print('testPatchNonExternalMember.warnings:${compiler.warnings}'); | 717 print('testPatchNonExternalMember.warnings:${compiler.warnings}'); |
709 Expect.equals(1, compiler.errors.length); | 718 Expect.equals(1, compiler.errors.length); |
710 Expect.isTrue( | 719 Expect.isTrue( |
711 compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXTERNAL); | 720 compiler.errors[0].message.kind == MessageKind.PATCH_NON_EXTERNAL); |
712 Expect.equals(0, compiler.warnings.length); | 721 Expect.equals(0, compiler.warnings.length); |
713 Expect.equals(1, compiler.infos.length); | 722 Expect.equals(1, compiler.infos.length); |
714 Expect.isTrue(compiler.infos[0].message.kind == | 723 Expect.isTrue(compiler.infos[0].message.kind == |
715 MessageKind.PATCH_POINT_TO_FUNCTION); | 724 MessageKind.PATCH_POINT_TO_FUNCTION); |
716 })); | |
717 } | 725 } |
718 | 726 |
719 testPatchNonClass() { | 727 Future testPatchNonClass() async { |
720 asyncTest(() => applyPatch( | 728 var compiler = await applyPatch( |
721 """ | 729 """ |
722 external void Class() {} | 730 external void Class() {} |
723 """, | 731 """, |
724 """ | 732 """ |
725 @patch class Class {} | 733 @patch class Class {} |
726 """).then((compiler) { | 734 """); |
727 print('testPatchNonClass.errors:${compiler.errors}'); | 735 print('testPatchNonClass.errors:${compiler.errors}'); |
728 print('testPatchNonClass.warnings:${compiler.warnings}'); | 736 print('testPatchNonClass.warnings:${compiler.warnings}'); |
729 Expect.equals(1, compiler.errors.length); | 737 Expect.equals(1, compiler.errors.length); |
730 Expect.isTrue( | 738 Expect.isTrue( |
731 compiler.errors[0].message.kind == MessageKind.PATCH_NON_CLASS); | 739 compiler.errors[0].message.kind == MessageKind.PATCH_NON_CLASS); |
732 Expect.equals(0, compiler.warnings.length); | 740 Expect.equals(0, compiler.warnings.length); |
733 Expect.equals(1, compiler.infos.length); | 741 Expect.equals(1, compiler.infos.length); |
734 Expect.isTrue( | 742 Expect.isTrue( |
735 compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_CLASS); | 743 compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_CLASS); |
736 })); | |
737 } | 744 } |
738 | 745 |
739 testPatchNonGetter() { | 746 Future testPatchNonGetter() async { |
740 asyncTest(() => applyPatch( | 747 var compiler = await applyPatch( |
741 """ | 748 """ |
742 external void foo() {} | 749 external void foo() {} |
743 """, | 750 """, |
744 """ | 751 """ |
745 @patch get foo => 0; | 752 @patch get foo => 0; |
746 """).then((compiler) { | 753 """); |
747 print('testPatchNonClass.errors:${compiler.errors}'); | 754 print('testPatchNonClass.errors:${compiler.errors}'); |
748 print('testPatchNonClass.warnings:${compiler.warnings}'); | 755 print('testPatchNonClass.warnings:${compiler.warnings}'); |
749 Expect.equals(1, compiler.errors.length); | 756 Expect.equals(1, compiler.errors.length); |
750 Expect.isTrue( | 757 Expect.isTrue( |
751 compiler.errors[0].message.kind == MessageKind.PATCH_NON_GETTER); | 758 compiler.errors[0].message.kind == MessageKind.PATCH_NON_GETTER); |
752 Expect.equals(0, compiler.warnings.length); | 759 Expect.equals(0, compiler.warnings.length); |
753 Expect.equals(1, compiler.infos.length); | 760 Expect.equals(1, compiler.infos.length); |
754 Expect.isTrue( | 761 Expect.isTrue( |
755 compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER); | 762 compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER); |
756 })); | |
757 } | 763 } |
758 | 764 |
759 testPatchNoGetter() { | 765 Future testPatchNoGetter() async { |
760 asyncTest(() => applyPatch( | 766 var compiler = await applyPatch( |
761 """ | 767 """ |
762 external set foo(var value) {} | 768 external set foo(var value) {} |
763 """, | 769 """, |
764 """ | 770 """ |
765 @patch get foo => 0; | 771 @patch get foo => 0; |
766 """).then((compiler) { | 772 """); |
767 print('testPatchNonClass.errors:${compiler.errors}'); | 773 print('testPatchNonClass.errors:${compiler.errors}'); |
768 print('testPatchNonClass.warnings:${compiler.warnings}'); | 774 print('testPatchNonClass.warnings:${compiler.warnings}'); |
769 Expect.equals(1, compiler.errors.length); | 775 Expect.equals(1, compiler.errors.length); |
770 Expect.isTrue( | 776 Expect.isTrue( |
771 compiler.errors[0].message.kind == MessageKind.PATCH_NO_GETTER); | 777 compiler.errors[0].message.kind == MessageKind.PATCH_NO_GETTER); |
772 Expect.equals(0, compiler.warnings.length); | 778 Expect.equals(0, compiler.warnings.length); |
773 Expect.equals(1, compiler.infos.length); | 779 Expect.equals(1, compiler.infos.length); |
774 Expect.isTrue( | 780 Expect.isTrue( |
775 compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER); | 781 compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_GETTER); |
776 })); | |
777 } | 782 } |
778 | 783 |
779 testPatchNonSetter() { | 784 Future testPatchNonSetter() async { |
780 asyncTest(() => applyPatch( | 785 var compiler = await applyPatch( |
781 """ | 786 """ |
782 external void foo() {} | 787 external void foo() {} |
783 """, | 788 """, |
784 """ | 789 """ |
785 @patch set foo(var value) {} | 790 @patch set foo(var value) {} |
786 """).then((compiler) { | 791 """); |
787 print('testPatchNonClass.errors:${compiler.errors}'); | 792 print('testPatchNonClass.errors:${compiler.errors}'); |
788 print('testPatchNonClass.warnings:${compiler.warnings}'); | 793 print('testPatchNonClass.warnings:${compiler.warnings}'); |
789 Expect.equals(1, compiler.errors.length); | 794 Expect.equals(1, compiler.errors.length); |
790 Expect.isTrue( | 795 Expect.isTrue( |
791 compiler.errors[0].message.kind == MessageKind.PATCH_NON_SETTER); | 796 compiler.errors[0].message.kind == MessageKind.PATCH_NON_SETTER); |
792 Expect.equals(0, compiler.warnings.length); | 797 Expect.equals(0, compiler.warnings.length); |
793 Expect.equals(1, compiler.infos.length); | 798 Expect.equals(1, compiler.infos.length); |
794 Expect.isTrue( | 799 Expect.isTrue( |
795 compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER); | 800 compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER); |
796 })); | |
797 } | 801 } |
798 | 802 |
799 testPatchNoSetter() { | 803 Future testPatchNoSetter() async { |
800 asyncTest(() => applyPatch( | 804 var compiler = await applyPatch( |
801 """ | 805 """ |
802 external get foo; | 806 external get foo; |
803 """, | 807 """, |
804 """ | 808 """ |
805 @patch set foo(var value) {} | 809 @patch set foo(var value) {} |
806 """).then((compiler) { | 810 """); |
807 print('testPatchNonClass.errors:${compiler.errors}'); | 811 print('testPatchNonClass.errors:${compiler.errors}'); |
808 print('testPatchNonClass.warnings:${compiler.warnings}'); | 812 print('testPatchNonClass.warnings:${compiler.warnings}'); |
809 Expect.equals(1, compiler.errors.length); | 813 Expect.equals(1, compiler.errors.length); |
810 Expect.isTrue( | 814 Expect.isTrue( |
811 compiler.errors[0].message.kind == MessageKind.PATCH_NO_SETTER); | 815 compiler.errors[0].message.kind == MessageKind.PATCH_NO_SETTER); |
812 Expect.equals(0, compiler.warnings.length); | 816 Expect.equals(0, compiler.warnings.length); |
813 Expect.equals(1, compiler.infos.length); | 817 Expect.equals(1, compiler.infos.length); |
814 Expect.isTrue( | 818 Expect.isTrue( |
815 compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER); | 819 compiler.infos[0].message.kind == MessageKind.PATCH_POINT_TO_SETTER); |
816 })); | |
817 } | 820 } |
818 | 821 |
819 testPatchNonFunction() { | 822 Future testPatchNonFunction() async { |
820 asyncTest(() => applyPatch( | 823 var compiler = await applyPatch( |
821 """ | 824 """ |
822 external get foo; | 825 external get foo; |
823 """, | 826 """, |
824 """ | 827 """ |
825 @patch void foo() {} | 828 @patch void foo() {} |
826 """).then((compiler) { | 829 """); |
827 print('testPatchNonClass.errors:${compiler.errors}'); | 830 print('testPatchNonClass.errors:${compiler.errors}'); |
828 print('testPatchNonClass.warnings:${compiler.warnings}'); | 831 print('testPatchNonClass.warnings:${compiler.warnings}'); |
829 Expect.equals(1, compiler.errors.length); | 832 Expect.equals(1, compiler.errors.length); |
830 Expect.isTrue( | 833 Expect.isTrue( |
831 compiler.errors[0].message.kind == MessageKind.PATCH_NON_FUNCTION); | 834 compiler.errors[0].message.kind == MessageKind.PATCH_NON_FUNCTION); |
832 Expect.equals(0, compiler.warnings.length); | 835 Expect.equals(0, compiler.warnings.length); |
833 Expect.equals(1, compiler.infos.length); | 836 Expect.equals(1, compiler.infos.length); |
834 Expect.isTrue( | 837 Expect.isTrue( |
835 compiler.infos[0].message.kind == | 838 compiler.infos[0].message.kind == |
836 MessageKind.PATCH_POINT_TO_FUNCTION); | 839 MessageKind.PATCH_POINT_TO_FUNCTION); |
837 })); | |
838 } | 840 } |
839 | 841 |
840 testPatchAndSelector() { | 842 Future testPatchAndSelector() async { |
841 asyncTest(() => applyPatch( | 843 var compiler = await applyPatch( |
842 """ | 844 """ |
843 class A { | 845 class A { |
844 external void clear(); | 846 external void clear(); |
845 } | 847 } |
846 class B extends A { | 848 class B extends A { |
847 } | 849 } |
848 """, | 850 """, |
849 """ | 851 """ |
850 @patch class A { | 852 @patch class A { |
851 int method() => 0; | 853 int method() => 0; |
852 @patch void clear() {} | 854 @patch void clear() {} |
853 } | 855 } |
854 """, | 856 """, |
855 main: """ | 857 main: """ |
856 main () { | 858 main () { |
857 new A(); // ensure A and B are instantiated | 859 new A(); // ensure A and B are instantiated |
858 new B(); | 860 new B(); |
859 } | 861 } |
860 """, | 862 """, |
861 runCompiler: true, analyzeOnly: true).then((Compiler compiler) { | 863 runCompiler: true, analyzeOnly: true); |
862 World world = compiler.world; | 864 World world = compiler.world; |
863 | 865 |
864 ClassElement cls = ensure(compiler, "A", compiler.coreLibrary.find, | 866 ClassElement cls = ensure(compiler, "A", compiler.coreLibrary.find, |
865 expectIsPatched: true); | 867 expectIsPatched: true); |
866 cls.ensureResolved(compiler); | 868 cls.ensureResolved(compiler); |
867 | 869 |
868 ensure(compiler, "method", cls.patch.lookupLocalMember, | 870 ensure(compiler, "method", cls.patch.lookupLocalMember, |
869 checkHasBody: true, expectIsRegular: true); | 871 checkHasBody: true, expectIsRegular: true); |
870 | 872 |
871 ensure(compiler, "clear", cls.lookupLocalMember, | 873 ensure(compiler, "clear", cls.lookupLocalMember, |
872 checkHasBody: true, expectIsPatched: true); | 874 checkHasBody: true, expectIsPatched: true); |
873 | 875 |
874 compiler.phase = Compiler.PHASE_DONE_RESOLVING; | 876 compiler.phase = Compiler.PHASE_DONE_RESOLVING; |
875 | 877 |
876 // Check that a method just in the patch class is a target for a | 878 // Check that a method just in the patch class is a target for a |
877 // typed selector. | 879 // typed selector. |
878 Selector selector = | 880 Selector selector = |
879 new Selector.call(const PublicName('method'), CallStructure.NO_ARGS); | 881 new Selector.call(const PublicName('method'), CallStructure.NO_ARGS); |
880 TypeMask typeMask = new TypeMask.exact(cls, world); | 882 TypeMask typeMask = new TypeMask.exact(cls, world); |
881 FunctionElement method = cls.implementation.lookupLocalMember('method'); | 883 FunctionElement method = cls.implementation.lookupLocalMember('method'); |
882 method.computeType(compiler); | 884 method.computeType(compiler); |
883 Expect.isTrue(selector.applies(method, world)); | 885 Expect.isTrue(selector.applies(method, world)); |
884 Expect.isTrue(typeMask.canHit(method, selector, world)); | 886 Expect.isTrue(typeMask.canHit(method, selector, world)); |
885 | 887 |
886 // Check that the declaration method in the declaration class is a target | 888 // Check that the declaration method in the declaration class is a target |
887 // for a typed selector. | 889 // for a typed selector. |
888 selector = | 890 selector = |
889 new Selector.call(const PublicName('clear'), CallStructure.NO_ARGS); | 891 new Selector.call(const PublicName('clear'), CallStructure.NO_ARGS); |
890 typeMask = new TypeMask.exact(cls, world); | 892 typeMask = new TypeMask.exact(cls, world); |
891 method = cls.lookupLocalMember('clear'); | 893 method = cls.lookupLocalMember('clear'); |
892 method.computeType(compiler); | 894 method.computeType(compiler); |
893 Expect.isTrue(selector.applies(method, world)); | 895 Expect.isTrue(selector.applies(method, world)); |
894 Expect.isTrue(typeMask.canHit(method, selector, world)); | 896 Expect.isTrue(typeMask.canHit(method, selector, world)); |
895 | 897 |
896 // Check that the declaration method in the declaration class is a target | 898 // Check that the declaration method in the declaration class is a target |
897 // for a typed selector on a subclass. | 899 // for a typed selector on a subclass. |
898 cls = ensure(compiler, "B", compiler.coreLibrary.find); | 900 cls = ensure(compiler, "B", compiler.coreLibrary.find); |
899 cls.ensureResolved(compiler); | 901 cls.ensureResolved(compiler); |
900 typeMask = new TypeMask.exact(cls, world); | 902 typeMask = new TypeMask.exact(cls, world); |
901 Expect.isTrue(selector.applies(method, world)); | 903 Expect.isTrue(selector.applies(method, world)); |
902 Expect.isTrue(typeMask.canHit(method, selector, world)); | 904 Expect.isTrue(typeMask.canHit(method, selector, world)); |
903 })); | |
904 } | 905 } |
905 | 906 |
906 void testAnalyzeAllInjectedMembers() { | 907 Future testAnalyzeAllInjectedMembers() async { |
907 void expect(String patchText, [expectedWarnings]) { | 908 Future expect(String patchText, [expectedWarnings]) async { |
908 if (expectedWarnings == null) expectedWarnings = []; | 909 if (expectedWarnings == null) expectedWarnings = []; |
909 if (expectedWarnings is! List) { | 910 if (expectedWarnings is! List) { |
910 expectedWarnings = <MessageKind>[expectedWarnings]; | 911 expectedWarnings = <MessageKind>[expectedWarnings]; |
911 } | 912 } |
912 | 913 |
913 asyncTest(() => applyPatch('', patchText, analyzeAll: true, | 914 var compiler = await applyPatch('', patchText, analyzeAll: true, |
914 analyzeOnly: true).then((compiler) { | 915 analyzeOnly: true); |
915 compiler.librariesToAnalyzeWhenRun = [Uri.parse('dart:core')]; | 916 compiler.librariesToAnalyzeWhenRun = [Uri.parse('dart:core')]; |
916 return compiler.runCompiler(null).then((_) { | 917 await compiler.runCompiler(null); |
917 compareWarningKinds(patchText, expectedWarnings, compiler.warnings); | 918 compareWarningKinds(patchText, expectedWarnings, compiler.warnings); |
918 }); | |
919 })); | |
920 } | 919 } |
921 | 920 |
922 expect('String s = 0;', MessageKind.NOT_ASSIGNABLE); | 921 await expect('String s = 0;', MessageKind.NOT_ASSIGNABLE); |
923 expect('void method() { String s = 0; }', MessageKind.NOT_ASSIGNABLE); | 922 await expect('void method() { String s = 0; }', MessageKind.NOT_ASSIGNABLE); |
924 expect(''' | 923 await expect(''' |
925 class Class { | 924 class Class { |
926 String s = 0; | 925 String s = 0; |
927 } | 926 } |
928 ''', | 927 ''', |
929 MessageKind.NOT_ASSIGNABLE); | 928 MessageKind.NOT_ASSIGNABLE); |
930 expect(''' | 929 await expect(''' |
931 class Class { | 930 class Class { |
932 void method() { | 931 void method() { |
933 String s = 0; | 932 String s = 0; |
934 } | 933 } |
935 } | 934 } |
936 ''', | 935 ''', |
937 MessageKind.NOT_ASSIGNABLE); | 936 MessageKind.NOT_ASSIGNABLE); |
938 } | 937 } |
939 | 938 |
940 void testEffectiveTarget() { | 939 Future testEffectiveTarget() async { |
941 String origin = """ | 940 String origin = """ |
942 class A { | 941 class A { |
943 A() : super(); | 942 A() : super(); |
944 factory A.forward() = B.patchTarget; | 943 factory A.forward() = B.patchTarget; |
945 factory A.forwardTwo() = B.reflectBack; | 944 factory A.forwardTwo() = B.reflectBack; |
946 } | 945 } |
947 class B extends A { | 946 class B extends A { |
948 B() : super(); | 947 B() : super(); |
949 external B.patchTarget(); | 948 external B.patchTarget(); |
950 external factory B.reflectBack(); | 949 external factory B.reflectBack(); |
951 B.originTarget() : super(); | 950 B.originTarget() : super(); |
952 } | 951 } |
953 """; | 952 """; |
954 String patch = """ | 953 String patch = """ |
955 @patch class B { | 954 @patch class B { |
956 B.patchTarget() : super(); | 955 B.patchTarget() : super(); |
957 factory B.reflectBack() = B.originTarget; | 956 factory B.reflectBack() = B.originTarget; |
958 } | 957 } |
959 """; | 958 """; |
960 | 959 |
961 asyncTest(() => applyPatch(origin, patch, analyzeAll: true, | 960 var compiler = await applyPatch(origin, patch, analyzeAll: true, |
962 analyzeOnly: true, runCompiler: true).then((compiler) { | 961 analyzeOnly: true, runCompiler: true); |
963 ClassElement clsA = compiler.coreLibrary.find("A"); | 962 ClassElement clsA = compiler.coreLibrary.find("A"); |
964 ClassElement clsB = compiler.coreLibrary.find("B"); | 963 ClassElement clsB = compiler.coreLibrary.find("B"); |
965 | 964 |
966 ConstructorElement forward = clsA.lookupConstructor("forward"); | 965 ConstructorElement forward = clsA.lookupConstructor("forward"); |
967 ConstructorElement target = forward.effectiveTarget; | 966 ConstructorElement target = forward.effectiveTarget; |
968 Expect.isTrue(target.isPatch); | 967 Expect.isTrue(target.isPatch); |
969 Expect.equals("patchTarget", target.name); | 968 Expect.equals("patchTarget", target.name); |
970 | 969 |
971 ConstructorElement forwardTwo = clsA.lookupConstructor("forwardTwo"); | 970 ConstructorElement forwardTwo = clsA.lookupConstructor("forwardTwo"); |
972 target = forwardTwo.effectiveTarget; | 971 target = forwardTwo.effectiveTarget; |
973 Expect.isFalse(forwardTwo.isErroneous); | 972 Expect.isFalse(forwardTwo.isErroneous); |
974 Expect.isFalse(target.isPatch); | 973 Expect.isFalse(target.isPatch); |
975 Expect.equals("originTarget", target.name); | 974 Expect.equals("originTarget", target.name); |
976 })); | |
977 } | 975 } |
978 | 976 |
979 void testTypecheckPatchedMembers() { | 977 Future testTypecheckPatchedMembers() async { |
980 String originText = "external void method();"; | 978 String originText = "external void method();"; |
981 String patchText = """ | 979 String patchText = """ |
982 @patch void method() { | 980 @patch void method() { |
983 String s = 0; | 981 String s = 0; |
984 } | 982 } |
985 """; | 983 """; |
986 asyncTest(() => applyPatch(originText, patchText, | 984 var compiler = await applyPatch(originText, patchText, |
987 analyzeAll: true, analyzeOnly: true).then((compiler) { | 985 analyzeAll: true, analyzeOnly: true); |
988 compiler.librariesToAnalyzeWhenRun = [Uri.parse('dart:core')]; | 986 compiler.librariesToAnalyzeWhenRun = [Uri.parse('dart:core')]; |
989 return compiler.runCompiler(null).then((_) { | 987 await compiler.runCompiler(null); |
990 compareWarningKinds(patchText, | 988 compareWarningKinds(patchText, |
991 [MessageKind.NOT_ASSIGNABLE], compiler.warnings); | 989 [MessageKind.NOT_ASSIGNABLE], compiler.warnings); |
992 }); | |
993 })); | |
994 } | 990 } |
995 | 991 |
996 main() { | 992 main() { |
997 testPatchConstructor(); | 993 asyncTest(() async { |
998 testPatchRedirectingConstructor(); | 994 await testPatchConstructor(); |
999 testPatchFunction(); | 995 await testPatchRedirectingConstructor(); |
1000 testPatchMember(); | 996 await testPatchFunction(); |
1001 testPatchGetter(); | 997 await testPatchFunctionMetadata(); |
1002 testRegularMember(); | 998 await testPatchMember(); |
1003 testGhostMember(); | 999 await testPatchGetter(); |
1004 testInjectFunction(); | 1000 await testRegularMember(); |
1005 testPatchSignatureCheck(); | 1001 await testGhostMember(); |
| 1002 await testInjectFunction(); |
| 1003 await testPatchSignatureCheck(); |
1006 | 1004 |
1007 testPatchVersioned(); | 1005 await testPatchVersioned(); |
1008 | 1006 |
1009 testExternalWithoutImplementationTopLevel(); | 1007 await testExternalWithoutImplementationTopLevel(); |
1010 testExternalWithoutImplementationMember(); | 1008 await testExternalWithoutImplementationMember(); |
1011 | 1009 |
1012 testIsSubclass(); | 1010 await testIsSubclass(); |
1013 | 1011 |
1014 testPatchNonExistingTopLevel(); | 1012 await testPatchNonExistingTopLevel(); |
1015 testPatchNonExistingMember(); | 1013 await testPatchNonExistingMember(); |
1016 testPatchNonPatchablePatch(); | 1014 await testPatchNonPatchablePatch(); |
1017 testPatchNonPatchableOrigin(); | 1015 await testPatchNonPatchableOrigin(); |
1018 testPatchNonExternalTopLevel(); | 1016 await testPatchNonExternalTopLevel(); |
1019 testPatchNonExternalMember(); | 1017 await testPatchNonExternalMember(); |
1020 testPatchNonClass(); | 1018 await testPatchNonClass(); |
1021 testPatchNonGetter(); | 1019 await testPatchNonGetter(); |
1022 testPatchNoGetter(); | 1020 await testPatchNoGetter(); |
1023 testPatchNonSetter(); | 1021 await testPatchNonSetter(); |
1024 testPatchNoSetter(); | 1022 await testPatchNoSetter(); |
1025 testPatchNonFunction(); | 1023 await testPatchNonFunction(); |
1026 | 1024 |
1027 testPatchAndSelector(); | 1025 await testPatchAndSelector(); |
1028 | 1026 |
1029 testEffectiveTarget(); /// bug: ok | 1027 await testEffectiveTarget(); /// bug: ok |
1030 | 1028 |
1031 testAnalyzeAllInjectedMembers(); | 1029 await testAnalyzeAllInjectedMembers(); |
1032 testTypecheckPatchedMembers(); | 1030 await testTypecheckPatchedMembers(); |
| 1031 }); |
1033 } | 1032 } |
OLD | NEW |