| 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 /** | 6 /** |
| 7 * If true, print a warning for each method that was resolved, but not | 7 * If true, print a warning for each method that was resolved, but not |
| 8 * compiled. | 8 * compiled. |
| 9 */ | 9 */ |
| 10 final bool REPORT_EXCESS_RESOLUTION = false; | 10 final bool REPORT_EXCESS_RESOLUTION = false; |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 patchDartLibrary(importedLibrary, path); | 398 patchDartLibrary(importedLibrary, path); |
| 399 }); | 399 }); |
| 400 } | 400 } |
| 401 | 401 |
| 402 void applyContainerPatch(ContainerElement original, Link<Element> patches, | 402 void applyContainerPatch(ContainerElement original, Link<Element> patches, |
| 403 Element lookup(SourceString name)) { | 403 Element lookup(SourceString name)) { |
| 404 while (!patches.isEmpty()) { | 404 while (!patches.isEmpty()) { |
| 405 Element patchElement = patches.head; | 405 Element patchElement = patches.head; |
| 406 Element originalElement = lookup(patchElement.name); | 406 Element originalElement = lookup(patchElement.name); |
| 407 if (patchElement.isAccessor()) { | 407 if (patchElement.isAccessor()) { |
| 408 // Skip accessors. An accessor always has an abstract field, | 408 // TODO(lrn): When we change to always add accessors to members, and |
| 409 // representing the accessor in the lookup scope. We can thus skip the | 409 // not add abstract fields, the logic here should be reversed. |
| 410 // accessors and just handle the abstract field. | 410 // For now, access getters through the abstract field and skip |
| 411 // any accessors. |
| 411 } else if (patchElement.kind === ElementKind.ABSTRACT_FIELD) { | 412 } else if (patchElement.kind === ElementKind.ABSTRACT_FIELD) { |
| 412 // Getters and setters are kept inside a synthetic field. | 413 // Getters and setters are kept inside a synthetic field. |
| 413 if (originalElement !== null && | 414 if (originalElement !== null && |
| 414 originalElement.kind !== ElementKind.ABSTRACT_FIELD) { | 415 originalElement.kind !== ElementKind.ABSTRACT_FIELD) { |
| 415 internalError("Cannot patch non-getter/setter with getter/setter", | 416 internalError("Cannot patch non-getter/setter with getter/setter", |
| 416 element: originalElement); | 417 element: originalElement); |
| 417 } | 418 } |
| 418 AbstractFieldElement patchField = patchElement; | 419 AbstractFieldElement patchField = patchElement; |
| 419 AbstractFieldElement originalField = originalElement; | 420 AbstractFieldElement originalField = originalElement; |
| 420 if (patchField.getter !== null) { | 421 if (patchField.getter !== null) { |
| 421 if (originalField === null || originalField.getter === null) { | 422 if (originalField === null || originalField.getter === null) { |
| 422 original.addGetterOrSetter(clonePatch(patchField.getter), | 423 original.addGetterOrSetter(clonePatch(patchField.getter, original), |
| 423 originalField, | 424 originalField, |
| 424 this); | 425 this); |
| 425 if (originalField === null && patchField.setter !== null) { | 426 if (originalField === null && patchField.setter !== null) { |
| 426 // It exists now, so find it for the setter patching. | 427 // It exists now, so find it for the setter patching. |
| 427 originalField = lookup(patchElement.name); | 428 originalField = lookup(patchElement.name); |
| 428 } | 429 } |
| 429 } else { | 430 } else { |
| 430 patchMember(originalField.getter, patchField.getter); | 431 patchMember(originalField.getter, patchField.getter); |
| 431 } | 432 } |
| 432 } | 433 } |
| 433 if (patchField.setter !== null) { | 434 if (patchField.setter !== null) { |
| 434 if (originalField === null || originalField.setter === null) { | 435 if (originalField === null || originalField.setter === null) { |
| 435 original.addGetterOrSetter(clonePatch(patchField.setter), | 436 original.addGetterOrSetter(clonePatch(patchField.setter, original), |
| 436 originalField, | 437 originalField, |
| 437 this); | 438 this); |
| 438 } else { | 439 } else { |
| 439 patchMember(originalField.setter, patchField.setter); | 440 patchMember(originalField.setter, patchField.setter); |
| 440 } | 441 } |
| 441 } | 442 } |
| 442 } else if (originalElement === null) { | 443 } else if (originalElement === null) { |
| 443 if (isPatchElement(patchElement)) { | 444 if (isPatchElement(patchElement)) { |
| 444 internalError("Cannot patch non-existing member '" | 445 internalError("Cannot patch non-existing member '" |
| 445 "${patchElement.name.slowToString()}'."); | 446 "${patchElement.name.slowToString()}'."); |
| 446 } | 447 } |
| 447 original.addMember(clonePatch(patchElement), this); | 448 original.addMember(clonePatch(patchElement, original), this); |
| 448 } else { | 449 } else { |
| 449 patchMember(originalElement, patchElement); | 450 patchMember(originalElement, patchElement); |
| 450 } | 451 } |
| 451 patches = patches.tail; | 452 patches = patches.tail; |
| 452 } | 453 } |
| 453 } | 454 } |
| 454 | 455 |
| 455 bool isPatchElement(Element element) { | 456 bool isPatchElement(Element element) { |
| 456 // TODO(lrn): More checks needed if we introduce metadata for real. | 457 // TODO(lrn): More checks needed if we introduce metadata for real. |
| 457 // In that case, it must have the identifier "native" as metadata. | 458 // In that case, it must have the identifier "native" as metadata. |
| 458 return !element.metadata.isEmpty(); | 459 return !element.metadata.isEmpty(); |
| 459 } | 460 } |
| 460 | 461 |
| 461 Element clonePatch(Element patchElement) { | 462 Element clonePatch(Element patchElement, Element enclosing) { |
| 462 // The original library does not have an element with the same name | 463 // The original library does not have an element with the same name |
| 463 // as the patch library element. | 464 // as the patch library element. |
| 464 // In this case, the patch library element must not be marked as "patch", | 465 // In this case, the patch library element must not be marked as "patch", |
| 465 // and its name must make it private. | 466 // and its name must make it private. |
| 466 if (!patchElement.name.isPrivate()) { | 467 if (!patchElement.name.isPrivate()) { |
| 467 internalError("Cannot add non-private member '" | 468 internalError("Cannot add non-private member '" |
| 468 "${patchElement.name.slowToString()}' from patch."); | 469 "${patchElement.name.slowToString()}' from patch."); |
| 469 } | 470 } |
| 470 // TODO(lrn): Create a copy of patchElement that isn't added to any | 471 Element override = |
| 471 // object/library yet, but which takes its source from patchElement. | 472 new CompilationUnitOverrideElement(patchElement.getCompilationUnit(), |
| 472 throw "Adding members from patch is unsupported"; | 473 enclosing); |
| 474 return patchElement.cloneTo(override, this); |
| 473 } | 475 } |
| 474 | 476 |
| 475 void patchMember(Element originalElement, Element patchElement) { | 477 void patchMember(Element originalElement, Element patchElement) { |
| 476 // The original library has an element with the same name as the patch | 478 // The original library has an element with the same name as the patch |
| 477 // library element. | 479 // library element. |
| 478 // In this case, the patch library element must be a function marked as | 480 // In this case, the patch library element must be a function marked as |
| 479 // "patch" and it must have the same signature as the function it patches. | 481 // "patch" and it must have the same signature as the function it patches. |
| 480 if (!isPatchElement(patchElement)) { | 482 if (!isPatchElement(patchElement)) { |
| 481 internalError("Cannot overwrite existing '" | 483 internalError("Cannot overwrite existing '" |
| 482 "${originalElement.name.slowToString()}' with non-patch."); | 484 "${originalElement.name.slowToString()}' with non-patch."); |
| (...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 final endOffset = end.charOffset + end.slowCharCount; | 948 final endOffset = end.charOffset + end.slowCharCount; |
| 947 | 949 |
| 948 // [begin] and [end] might be the same for the same empty token. This | 950 // [begin] and [end] might be the same for the same empty token. This |
| 949 // happens for instance when scanning '$$'. | 951 // happens for instance when scanning '$$'. |
| 950 assert(endOffset >= beginOffset); | 952 assert(endOffset >= beginOffset); |
| 951 return f(beginOffset, endOffset); | 953 return f(beginOffset, endOffset); |
| 952 } | 954 } |
| 953 | 955 |
| 954 String toString() => 'SourceSpan($uri, $begin, $end)'; | 956 String toString() => 'SourceSpan($uri, $begin, $end)'; |
| 955 } | 957 } |
| OLD | NEW |