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 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
527 | 527 |
528 // Copy imports from patch to original library. | 528 // Copy imports from patch to original library. |
529 Map<String, LibraryElement> delayedPatches = <LibraryElement>{}; | 529 Map<String, LibraryElement> delayedPatches = <LibraryElement>{}; |
530 Uri patchBase = patch.script.uri; | 530 Uri patchBase = patch.script.uri; |
531 for (ScriptTag tag in patch.tags.reverse()) { | 531 for (ScriptTag tag in patch.tags.reverse()) { |
532 if (tag.isImport()) { | 532 if (tag.isImport()) { |
533 StringNode argument = tag.argument; | 533 StringNode argument = tag.argument; |
534 Uri resolved = patchBase.resolve(argument.dartString.slowToString()); | 534 Uri resolved = patchBase.resolve(argument.dartString.slowToString()); |
535 LibraryElement importedLibrary = | 535 LibraryElement importedLibrary = |
536 scanner.loadLibrary(resolved, argument); | 536 scanner.loadLibrary(resolved, argument); |
537 scanner.importLibrary(original, importedLibrary, tag, patch); | 537 scanner.importLibrary(original, importedLibrary, tag, patch.script); |
538 if (resolved.scheme == "dart") { | 538 if (resolved.scheme == "dart") { |
539 delayedPatches[resolved.path] = importedLibrary; | 539 delayedPatches[resolved.path] = importedLibrary; |
540 } | 540 } |
541 } | 541 } |
542 } | 542 } |
543 | 543 |
544 // Mark library as already patched. | 544 // Mark library as already patched. |
545 original.patch = patch; | 545 original.patch = patch; |
546 | 546 |
547 // We patch imported libraries after marking the current library as | 547 // We patch imported libraries after marking the current library as |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
581 if (patchField.setter !== null) { | 581 if (patchField.setter !== null) { |
582 if (originalField === null || originalField.setter === null) { | 582 if (originalField === null || originalField.setter === null) { |
583 original.addGetterOrSetter(clonePatch(patchField.setter), | 583 original.addGetterOrSetter(clonePatch(patchField.setter), |
584 originalField, | 584 originalField, |
585 this); | 585 this); |
586 } else { | 586 } else { |
587 patchMember(originalField.setter, patchField.setter); | 587 patchMember(originalField.setter, patchField.setter); |
588 } | 588 } |
589 } | 589 } |
590 } else if (originalElement === null) { | 590 } else if (originalElement === null) { |
| 591 // The original library does not have an element with the same name |
| 592 // as the patch library element. |
| 593 // In this case, the patch library element must not be marked as |
| 594 // "patch", and its name must make it private. |
591 if (isPatchElement(patchElement)) { | 595 if (isPatchElement(patchElement)) { |
592 internalError("Cannot patch non-existing member '" | 596 internalError("Cannot patch non-existing member '" |
593 "${patchElement.name.slowToString()}'."); | 597 "${patchElement.name.slowToString()}'."); |
594 } | 598 } |
595 original.addMember(clonePatch(patchElement), this); | 599 if (!patchElement.name.isPrivate()) { |
| 600 internalError("Cannot add non-private member '" |
| 601 "${patchElement.name.slowToString()}' from patch."); |
| 602 } |
| 603 Element cloneElement = patchElement.cloneTo(original, this); |
| 604 original.addMember(cloneElement, this); |
596 } else { | 605 } else { |
597 patchMember(originalElement, patchElement); | 606 patchMember(originalElement, patchElement); |
598 } | 607 } |
599 patches = patches.tail; | 608 patches = patches.tail; |
600 } | 609 } |
601 } | 610 } |
602 | 611 |
603 bool isPatchElement(Element element) { | 612 bool isPatchElement(Element element) { |
604 // TODO(lrn): More checks needed if we introduce metadata for real. | 613 // TODO(lrn): More checks needed if we introduce metadata for real. |
605 // In that case, it must have the identifier "native" as metadata. | 614 // In that case, it must have the identifier "native" as metadata. |
606 return !element.metadata.isEmpty(); | 615 return !element.metadata.isEmpty(); |
607 } | 616 } |
608 | 617 |
609 Element clonePatch(Element patchElement) { | |
610 // The original library does not have an element with the same name | |
611 // as the patch library element. | |
612 // In this case, the patch library element must not be marked as "patch", | |
613 // and its name must make it private. | |
614 if (!patchElement.name.isPrivate()) { | |
615 internalError("Cannot add non-private member '" | |
616 "${patchElement.name.slowToString()}' from patch."); | |
617 } | |
618 // TODO(lrn): Create a copy of patchElement that isn't added to any | |
619 // object/library yet, but which takes its source from patchElement. | |
620 throw "Adding members from patch is unsupported"; | |
621 } | |
622 | |
623 void patchMember(Element originalElement, Element patchElement) { | 618 void patchMember(Element originalElement, Element patchElement) { |
624 // The original library has an element with the same name as the patch | 619 // The original library has an element with the same name as the patch |
625 // library element. | 620 // library element. |
626 // In this case, the patch library element must be a function marked as | 621 // In this case, the patch library element must be a function marked as |
627 // "patch" and it must have the same signature as the function it patches. | 622 // "patch" and it must have the same signature as the function it patches. |
628 if (!isPatchElement(patchElement)) { | 623 if (!isPatchElement(patchElement)) { |
629 internalError("Cannot overwrite existing '" | 624 internalError("Cannot overwrite existing '" |
630 "${originalElement.name.slowToString()}' with non-patch."); | 625 "${originalElement.name.slowToString()}' with non-patch."); |
631 } | 626 } |
632 if (originalElement is PartialClassElement) { | 627 if (originalElement is PartialClassElement) { |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
971 api.Diagnostic kind); | 966 api.Diagnostic kind); |
972 | 967 |
973 SourceSpan spanFromTokens(Token begin, Token end, [Uri uri]) { | 968 SourceSpan spanFromTokens(Token begin, Token end, [Uri uri]) { |
974 if (begin === null || end === null) { | 969 if (begin === null || end === null) { |
975 // TODO(ahe): We can almost always do better. Often it is only | 970 // TODO(ahe): We can almost always do better. Often it is only |
976 // end that is null. Otherwise, we probably know the current | 971 // end that is null. Otherwise, we probably know the current |
977 // URI. | 972 // URI. |
978 throw 'Cannot find tokens to produce error message.'; | 973 throw 'Cannot find tokens to produce error message.'; |
979 } | 974 } |
980 if (uri === null && currentElement !== null) { | 975 if (uri === null && currentElement !== null) { |
981 uri = currentElement.getCompilationUnit().script.uri; | 976 uri = currentElement.getScript().uri; |
982 } | 977 } |
983 return SourceSpan.withCharacterOffsets(begin, end, | 978 return SourceSpan.withCharacterOffsets(begin, end, |
984 (beginOffset, endOffset) => new SourceSpan(uri, beginOffset, endOffset)); | 979 (beginOffset, endOffset) => new SourceSpan(uri, beginOffset, endOffset)); |
985 } | 980 } |
986 | 981 |
987 SourceSpan spanFromNode(Node node, [Uri uri]) { | 982 SourceSpan spanFromNode(Node node, [Uri uri]) { |
988 return spanFromTokens(node.getBeginToken(), node.getEndToken(), uri); | 983 return spanFromTokens(node.getBeginToken(), node.getEndToken(), uri); |
989 } | 984 } |
990 | 985 |
991 SourceSpan spanFromElement(Element element) { | 986 SourceSpan spanFromElement(Element element) { |
992 if (element.position() === null) { | 987 if (element.position() === null) { |
993 // Sometimes, the backend fakes up elements that have no | 988 // Sometimes, the backend fakes up elements that have no |
994 // position. So we use the enclosing element instead. It is | 989 // position. So we use the enclosing element instead. It is |
995 // not a good error location, but cancel really is "internal | 990 // not a good error location, but cancel really is "internal |
996 // error" or "not implemented yet", so the vicinity is good | 991 // error" or "not implemented yet", so the vicinity is good |
997 // enough for now. | 992 // enough for now. |
998 element = element.enclosingElement; | 993 element = element.enclosingElement; |
999 // TODO(ahe): I plan to overhaul this infrastructure anyways. | 994 // TODO(ahe): I plan to overhaul this infrastructure anyways. |
1000 } | 995 } |
1001 if (element === null) { | 996 if (element === null) { |
1002 element = currentElement; | 997 element = currentElement; |
1003 } | 998 } |
1004 Token position = element.position(); | 999 Token position = element.position(); |
1005 Uri uri = element.getCompilationUnit().script.uri; | 1000 Uri uri = element.getScript().uri; |
1006 return (position === null) | 1001 return (position === null) |
1007 ? new SourceSpan(uri, 0, 0) | 1002 ? new SourceSpan(uri, 0, 0) |
1008 : spanFromTokens(position, position, uri); | 1003 : spanFromTokens(position, position, uri); |
1009 } | 1004 } |
1010 | 1005 |
1011 Script readScript(Uri uri, [ScriptTag node]) { | 1006 Script readScript(Uri uri, [ScriptTag node]) { |
1012 unimplemented('Compiler.readScript'); | 1007 unimplemented('Compiler.readScript'); |
1013 } | 1008 } |
1014 | 1009 |
1015 String get legDirectory() { | 1010 String get legDirectory() { |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1085 final endOffset = end.charOffset + end.slowCharCount; | 1080 final endOffset = end.charOffset + end.slowCharCount; |
1086 | 1081 |
1087 // [begin] and [end] might be the same for the same empty token. This | 1082 // [begin] and [end] might be the same for the same empty token. This |
1088 // happens for instance when scanning '$$'. | 1083 // happens for instance when scanning '$$'. |
1089 assert(endOffset >= beginOffset); | 1084 assert(endOffset >= beginOffset); |
1090 return f(beginOffset, endOffset); | 1085 return f(beginOffset, endOffset); |
1091 } | 1086 } |
1092 | 1087 |
1093 String toString() => 'SourceSpan($uri, $begin, $end)'; | 1088 String toString() => 'SourceSpan($uri, $begin, $end)'; |
1094 } | 1089 } |
OLD | NEW |