| 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 /** | 5 /** |
| 6 * This library contains the infrastructure to parse and integrate patch files. | 6 * This library contains the infrastructure to parse and integrate patch files. |
| 7 * | 7 * |
| 8 * Three types of elements can be patched: [LibraryElement], [ClassElement], | 8 * Three types of elements can be patched: [LibraryElement], [ClassElement], |
| 9 * [FunctionElement]. Patches are introduced in patch libraries which are loaded | 9 * [FunctionElement]. Patches are introduced in patch libraries which are loaded |
| 10 * together with the corresponding origin library. Which libraries that are | 10 * together with the corresponding origin library. Which libraries that are |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 PatchMetadataAnnotation() : super(STATE_DONE); | 387 PatchMetadataAnnotation() : super(STATE_DONE); |
| 388 | 388 |
| 389 Token get beginToken => null; | 389 Token get beginToken => null; |
| 390 Token get endToken => null; | 390 Token get endToken => null; |
| 391 } | 391 } |
| 392 | 392 |
| 393 void patchElement(leg.DiagnosticListener listener, | 393 void patchElement(leg.DiagnosticListener listener, |
| 394 Element origin, | 394 Element origin, |
| 395 Element patch) { | 395 Element patch) { |
| 396 if (origin == null) { | 396 if (origin == null) { |
| 397 listener.reportMessage( | 397 listener.reportError( |
| 398 listener.spanFromSpannable(patch), | 398 patch, leg.MessageKind.PATCH_NON_EXISTING, {'name': patch.name}); |
| 399 leg.MessageKind.PATCH_NON_EXISTING.error({'name': patch.name}), | |
| 400 api.Diagnostic.ERROR); | |
| 401 return; | 399 return; |
| 402 } | 400 } |
| 403 if (!(origin.isClass() || | 401 if (!(origin.isClass() || |
| 404 origin.isConstructor() || | 402 origin.isConstructor() || |
| 405 origin.isFunction() || | 403 origin.isFunction() || |
| 406 origin.isAbstractField())) { | 404 origin.isAbstractField())) { |
| 407 listener.reportMessage( | 405 listener.reportError(origin, leg.MessageKind.PATCH_NONPATCHABLE); |
| 408 listener.spanFromSpannable(origin), | |
| 409 leg.MessageKind.PATCH_NONPATCHABLE.error(), | |
| 410 api.Diagnostic.ERROR); | |
| 411 return; | 406 return; |
| 412 } | 407 } |
| 413 if (patch.isClass()) { | 408 if (patch.isClass()) { |
| 414 tryPatchClass(listener, origin, patch); | 409 tryPatchClass(listener, origin, patch); |
| 415 } else if (patch.isGetter()) { | 410 } else if (patch.isGetter()) { |
| 416 tryPatchGetter(listener, origin, patch); | 411 tryPatchGetter(listener, origin, patch); |
| 417 } else if (patch.isSetter()) { | 412 } else if (patch.isSetter()) { |
| 418 tryPatchSetter(listener, origin, patch); | 413 tryPatchSetter(listener, origin, patch); |
| 419 } else if (patch.isConstructor()) { | 414 } else if (patch.isConstructor()) { |
| 420 tryPatchConstructor(listener, origin, patch); | 415 tryPatchConstructor(listener, origin, patch); |
| 421 } else if(patch.isFunction()) { | 416 } else if(patch.isFunction()) { |
| 422 tryPatchFunction(listener, origin, patch); | 417 tryPatchFunction(listener, origin, patch); |
| 423 } else { | 418 } else { |
| 424 listener.reportMessage( | 419 listener.reportError(patch, leg.MessageKind.PATCH_NONPATCHABLE); |
| 425 listener.spanFromSpannable(patch), | |
| 426 leg.MessageKind.PATCH_NONPATCHABLE.error(), | |
| 427 api.Diagnostic.ERROR); | |
| 428 } | 420 } |
| 429 } | 421 } |
| 430 | 422 |
| 431 void tryPatchClass(leg.DiagnosticListener listener, | 423 void tryPatchClass(leg.DiagnosticListener listener, |
| 432 Element origin, | 424 Element origin, |
| 433 ClassElement patch) { | 425 ClassElement patch) { |
| 434 if (!origin.isClass()) { | 426 if (!origin.isClass()) { |
| 435 listener.reportMessage( | 427 listener.reportError( |
| 436 listener.spanFromSpannable(origin), | 428 origin, leg.MessageKind.PATCH_NON_CLASS, {'className': patch.name}); |
| 437 leg.MessageKind.PATCH_NON_CLASS.error({'className': patch.name}), | 429 listener.reportInfo( |
| 438 api.Diagnostic.ERROR); | 430 patch, leg.MessageKind.PATCH_POINT_TO_CLASS, {'className': patch.name}); |
| 439 listener.reportMessage( | |
| 440 listener.spanFromSpannable(patch), | |
| 441 leg.MessageKind.PATCH_POINT_TO_CLASS.error({'className': patch.name}), | |
| 442 api.Diagnostic.INFO); | |
| 443 return; | 431 return; |
| 444 } | 432 } |
| 445 patchClass(listener, origin, patch); | 433 patchClass(listener, origin, patch); |
| 446 } | 434 } |
| 447 | 435 |
| 448 void patchClass(leg.DiagnosticListener listener, | 436 void patchClass(leg.DiagnosticListener listener, |
| 449 ClassElement origin, | 437 ClassElement origin, |
| 450 ClassElement patch) { | 438 ClassElement patch) { |
| 451 if (origin.isPatched) { | 439 if (origin.isPatched) { |
| 452 listener.internalErrorOnElement( | 440 listener.internalErrorOnElement( |
| 453 origin, "Patching the same class more than once."); | 441 origin, "Patching the same class more than once."); |
| 454 } | 442 } |
| 455 // TODO(johnniwinther): Change to functions on the ElementX class. | 443 // TODO(johnniwinther): Change to functions on the ElementX class. |
| 456 origin.patch = patch; | 444 origin.patch = patch; |
| 457 patch.origin = origin; | 445 patch.origin = origin; |
| 458 } | 446 } |
| 459 | 447 |
| 460 void tryPatchGetter(leg.DiagnosticListener listener, | 448 void tryPatchGetter(leg.DiagnosticListener listener, |
| 461 Element origin, | 449 Element origin, |
| 462 FunctionElement patch) { | 450 FunctionElement patch) { |
| 463 if (!origin.isAbstractField()) { | 451 if (!origin.isAbstractField()) { |
| 464 listener.reportMessage( | 452 listener.reportError( |
| 465 listener.spanFromSpannable(origin), | 453 origin, leg.MessageKind.PATCH_NON_GETTER, {'name': origin.name}); |
| 466 leg.MessageKind.PATCH_NON_GETTER.error({'name': origin.name}), | 454 listener.reportInfo( |
| 467 api.Diagnostic.ERROR); | 455 patch, |
| 468 listener.reportMessage( | 456 leg.MessageKind.PATCH_POINT_TO_GETTER, {'getterName': patch.name}); |
| 469 listener.spanFromSpannable(patch), | |
| 470 leg.MessageKind.PATCH_POINT_TO_GETTER.error({'getterName': patch.name}), | |
| 471 api.Diagnostic.INFO); | |
| 472 return; | 457 return; |
| 473 } | 458 } |
| 474 AbstractFieldElement originField = origin; | 459 AbstractFieldElement originField = origin; |
| 475 if (originField.getter == null) { | 460 if (originField.getter == null) { |
| 476 listener.reportMessage( | 461 listener.reportError( |
| 477 listener.spanFromSpannable(origin), | 462 origin, leg.MessageKind.PATCH_NO_GETTER, {'getterName': patch.name}); |
| 478 leg.MessageKind.PATCH_NO_GETTER.error({'getterName': patch.name}), | 463 listener.reportInfo( |
| 479 api.Diagnostic.ERROR); | 464 patch, |
| 480 listener.reportMessage( | 465 leg.MessageKind.PATCH_POINT_TO_GETTER, {'getterName': patch.name}); |
| 481 listener.spanFromSpannable(patch), | |
| 482 leg.MessageKind.PATCH_POINT_TO_GETTER.error({'getterName': patch.name}), | |
| 483 api.Diagnostic.INFO); | |
| 484 return; | 466 return; |
| 485 } | 467 } |
| 486 patchFunction(listener, originField.getter, patch); | 468 patchFunction(listener, originField.getter, patch); |
| 487 } | 469 } |
| 488 | 470 |
| 489 void tryPatchSetter(leg.DiagnosticListener listener, | 471 void tryPatchSetter(leg.DiagnosticListener listener, |
| 490 Element origin, | 472 Element origin, |
| 491 FunctionElement patch) { | 473 FunctionElement patch) { |
| 492 if (!origin.isAbstractField()) { | 474 if (!origin.isAbstractField()) { |
| 493 listener.reportMessage( | 475 listener.reportError( |
| 494 listener.spanFromSpannable(origin), | 476 origin, leg.MessageKind.PATCH_NON_SETTER, {'name': origin.name}); |
| 495 leg.MessageKind.PATCH_NON_SETTER.error({'name': origin.name}), | 477 listener.reportInfo( |
| 496 api.Diagnostic.ERROR); | 478 patch, |
| 497 listener.reportMessage( | 479 leg.MessageKind.PATCH_POINT_TO_SETTER, {'setterName': patch.name}); |
| 498 listener.spanFromSpannable(patch), | |
| 499 leg.MessageKind.PATCH_POINT_TO_SETTER.error({'setterName': patch.name}), | |
| 500 api.Diagnostic.INFO); | |
| 501 return; | 480 return; |
| 502 } | 481 } |
| 503 AbstractFieldElement originField = origin; | 482 AbstractFieldElement originField = origin; |
| 504 if (originField.setter == null) { | 483 if (originField.setter == null) { |
| 505 listener.reportMessage( | 484 listener.reportError( |
| 506 listener.spanFromSpannable(origin), | 485 origin, leg.MessageKind.PATCH_NO_SETTER, {'setterName': patch.name}); |
| 507 leg.MessageKind.PATCH_NO_SETTER.error({'setterName': patch.name}), | 486 listener.reportInfo( |
| 508 api.Diagnostic.ERROR); | 487 patch, |
| 509 listener.reportMessage( | 488 leg.MessageKind.PATCH_POINT_TO_SETTER, {'setterName': patch.name}); |
| 510 listener.spanFromSpannable(patch), | |
| 511 leg.MessageKind.PATCH_POINT_TO_SETTER.error({'setterName': patch.name}), | |
| 512 api.Diagnostic.INFO); | |
| 513 return; | 489 return; |
| 514 } | 490 } |
| 515 patchFunction(listener, originField.setter, patch); | 491 patchFunction(listener, originField.setter, patch); |
| 516 } | 492 } |
| 517 | 493 |
| 518 void tryPatchConstructor(leg.DiagnosticListener listener, | 494 void tryPatchConstructor(leg.DiagnosticListener listener, |
| 519 Element origin, | 495 Element origin, |
| 520 FunctionElement patch) { | 496 FunctionElement patch) { |
| 521 if (!origin.isConstructor()) { | 497 if (!origin.isConstructor()) { |
| 522 listener.reportMessage( | 498 listener.reportError( |
| 523 listener.spanFromSpannable(origin), | 499 origin, |
| 524 leg.MessageKind.PATCH_NON_CONSTRUCTOR.error( | 500 leg.MessageKind.PATCH_NON_CONSTRUCTOR, {'constructorName': patch.name}); |
| 525 {'constructorName': patch.name}), | 501 listener.reportInfo( |
| 526 api.Diagnostic.ERROR); | 502 patch, |
| 527 listener.reportMessage( | 503 leg.MessageKind.PATCH_POINT_TO_CONSTRUCTOR, |
| 528 listener.spanFromSpannable(patch), | 504 {'constructorName': patch.name}); |
| 529 leg.MessageKind.PATCH_POINT_TO_CONSTRUCTOR.error( | |
| 530 {'constructorName': patch.name}), | |
| 531 api.Diagnostic.INFO); | |
| 532 return; | 505 return; |
| 533 } | 506 } |
| 534 patchFunction(listener, origin, patch); | 507 patchFunction(listener, origin, patch); |
| 535 } | 508 } |
| 536 | 509 |
| 537 void tryPatchFunction(leg.DiagnosticListener listener, | 510 void tryPatchFunction(leg.DiagnosticListener listener, |
| 538 Element origin, | 511 Element origin, |
| 539 FunctionElement patch) { | 512 FunctionElement patch) { |
| 540 if (!origin.isFunction()) { | 513 if (!origin.isFunction()) { |
| 541 listener.reportMessage( | 514 listener.reportError( |
| 542 listener.spanFromSpannable(origin), | 515 origin, |
| 543 leg.MessageKind.PATCH_NON_FUNCTION.error({'functionName': patch.name}), | 516 leg.MessageKind.PATCH_NON_FUNCTION, {'functionName': patch.name}); |
| 544 api.Diagnostic.ERROR); | 517 listener.reportInfo( |
| 545 listener.reportMessage( | 518 patch, |
| 546 listener.spanFromSpannable(patch), | 519 leg.MessageKind.PATCH_POINT_TO_FUNCTION, {'functionName': patch.name}); |
| 547 leg.MessageKind.PATCH_POINT_TO_FUNCTION.error( | |
| 548 {'functionName': patch.name}), | |
| 549 api.Diagnostic.INFO); | |
| 550 return; | 520 return; |
| 551 } | 521 } |
| 552 patchFunction(listener, origin, patch); | 522 patchFunction(listener, origin, patch); |
| 553 } | 523 } |
| 554 | 524 |
| 555 void patchFunction(leg.DiagnosticListener listener, | 525 void patchFunction(leg.DiagnosticListener listener, |
| 556 FunctionElement origin, | 526 FunctionElement origin, |
| 557 FunctionElement patch) { | 527 FunctionElement patch) { |
| 558 if (!origin.modifiers.isExternal()) { | 528 if (!origin.modifiers.isExternal()) { |
| 559 listener.reportMessage( | 529 listener.reportError(origin, leg.MessageKind.PATCH_NON_EXTERNAL); |
| 560 listener.spanFromSpannable(origin), | 530 listener.reportInfo( |
| 561 leg.MessageKind.PATCH_NON_EXTERNAL.error(), | 531 patch, |
| 562 api.Diagnostic.ERROR); | 532 leg.MessageKind.PATCH_POINT_TO_FUNCTION, {'functionName': patch.name}); |
| 563 listener.reportMessage( | |
| 564 listener.spanFromSpannable(patch), | |
| 565 leg.MessageKind.PATCH_POINT_TO_FUNCTION.error( | |
| 566 {'functionName': patch.name}), | |
| 567 api.Diagnostic.INFO); | |
| 568 return; | 533 return; |
| 569 } | 534 } |
| 570 if (origin.isPatched) { | 535 if (origin.isPatched) { |
| 571 listener.internalErrorOnElement(origin, | 536 listener.internalErrorOnElement(origin, |
| 572 "Trying to patch a function more than once."); | 537 "Trying to patch a function more than once."); |
| 573 } | 538 } |
| 574 if (origin.cachedNode != null) { | 539 if (origin.cachedNode != null) { |
| 575 listener.internalErrorOnElement(origin, | 540 listener.internalErrorOnElement(origin, |
| 576 "Trying to patch an already compiled function."); | 541 "Trying to patch an already compiled function."); |
| 577 } | 542 } |
| 578 // Don't just assign the patch field. This also updates the cachedNode. | 543 // Don't just assign the patch field. This also updates the cachedNode. |
| 579 // TODO(johnniwinther): Change to functions on the ElementX class. | 544 // TODO(johnniwinther): Change to functions on the ElementX class. |
| 580 origin.setPatch(patch); | 545 origin.setPatch(patch); |
| 581 patch.origin = origin; | 546 patch.origin = origin; |
| 582 } | 547 } |
| 583 | 548 |
| 584 // TODO(johnniwinther): Add unittest when patch is (real) metadata. | 549 // TODO(johnniwinther): Add unittest when patch is (real) metadata. |
| 585 bool isPatchElement(Element element) { | 550 bool isPatchElement(Element element) { |
| 586 // TODO(lrn): More checks needed if we introduce metadata for real. | 551 // TODO(lrn): More checks needed if we introduce metadata for real. |
| 587 // In that case, it must have the identifier "native" as metadata. | 552 // In that case, it must have the identifier "native" as metadata. |
| 588 for (Link link = element.metadata; !link.isEmpty; link = link.tail) { | 553 for (Link link = element.metadata; !link.isEmpty; link = link.tail) { |
| 589 if (link.head is PatchMetadataAnnotation) return true; | 554 if (link.head is PatchMetadataAnnotation) return true; |
| 590 } | 555 } |
| 591 return false; | 556 return false; |
| 592 } | 557 } |
| OLD | NEW |