Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(227)

Side by Side Diff: lib/compiler/implementation/compiler.dart

Issue 10703188: Allow patch files to add top-level declarations to the patched library. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix errors caught by editor. Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « corelib/unified/math/random.dart ('k') | lib/compiler/implementation/elements/elements.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
548 // patched, to avoid problems with cyclic dependencies. 548 // patched, to avoid problems with cyclic dependencies.
549 delayedPatches.forEach((String path, LibraryElement importedLibrary) { 549 delayedPatches.forEach((String path, LibraryElement importedLibrary) {
550 patchDartLibrary(importedLibrary, path); 550 patchDartLibrary(importedLibrary, path);
551 }); 551 });
552 } 552 }
553 553
554 void applyContainerPatch(ContainerElement original, Link<Element> patches, 554 void applyContainerPatch(ContainerElement original, Link<Element> patches,
555 Element lookup(SourceString name)) { 555 Element lookup(SourceString name)) {
556 while (!patches.isEmpty()) { 556 while (!patches.isEmpty()) {
557 Element patchElement = patches.head; 557 Element patchElement = patches.head;
558 Element originalElement = lookup(patchElement.name); 558 Element originalElement = lookup(patchElement.name);
559 // Getters and setters are kept inside a synthetic field. 559 assert(patchElement.kind !== ElementKind.ABSTRACT_FIELD);
560 if (patchElement.kind === ElementKind.ABSTRACT_FIELD) { 560 if (originalElement !== null &&
561 if (originalElement !== null && 561 originalElement.kind === ElementKind.ABSTRACT_FIELD) {
562 originalElement.kind !== ElementKind.ABSTRACT_FIELD) { 562 AbstractFieldElement originalField = originalElement;
563 internalError("Cannot patch non-getter/setter with getter/setter", 563 if (patchElement.kind === ElementKind.GETTER) {
564 element: originalElement); 564 originalElement = originalField.getter;
565 } else if (patchElement.kind === ElementKind.SETTER) {
566 originalElement = originalField.setter;
567 } else {
568 internalError("Cannot patch a getter/setter field with a "
569 "non-getter/setter patch", element: originalElement);
565 } 570 }
566 AbstractFieldElement patchField = patchElement; 571 }
567 AbstractFieldElement originalField = originalElement; 572 if (originalElement === null) {
568 if (patchField.getter !== null) { 573 // The original library does not have an element with the same name
569 if (originalField === null || originalField.getter === null) { 574 // as the patch library element.
570 original.addGetterOrSetter(clonePatch(patchField.getter), 575 // In this case, the patch library element must not be marked as
571 originalField, 576 // "patch", and its name must make it private.
572 this);
573 if (originalField === null && patchField.setter !== null) {
574 // It exists now, so find it for the setter patching.
575 originalField = lookup(patchElement.name);
576 }
577 } else {
578 patchMember(originalField.getter, patchField.getter);
579 }
580 }
581 if (patchField.setter !== null) {
582 if (originalField === null || originalField.setter === null) {
583 original.addGetterOrSetter(clonePatch(patchField.setter),
584 originalField,
585 this);
586 } else {
587 patchMember(originalField.setter, patchField.setter);
588 }
589 }
590 } else if (originalElement === null) {
591 if (isPatchElement(patchElement)) { 577 if (isPatchElement(patchElement)) {
592 internalError("Cannot patch non-existing member '" 578 internalError("Cannot patch non-existing member '"
593 "${patchElement.name.slowToString()}'."); 579 "${patchElement.name.slowToString()}'.");
594 } 580 }
595 original.addMember(clonePatch(patchElement), this); 581 if (!patchElement.name.isPrivate()) {
582 internalError("Cannot add non-private member '"
583 "${patchElement.name.slowToString()}' from patch.");
584 }
585 Element cloneElement = patchElement.cloneTo(original, this);
586 original.addMember(cloneElement, this);
596 } else { 587 } else {
597 patchMember(originalElement, patchElement); 588 patchMember(originalElement, patchElement);
598 } 589 }
599 patches = patches.tail; 590 patches = patches.tail;
600 } 591 }
601 } 592 }
602 593
603 bool isPatchElement(Element element) { 594 bool isPatchElement(Element element) {
604 // TODO(lrn): More checks needed if we introduce metadata for real. 595 // TODO(lrn): More checks needed if we introduce metadata for real.
605 // In that case, it must have the identifier "native" as metadata. 596 // In that case, it must have the identifier "native" as metadata.
606 return !element.metadata.isEmpty(); 597 return !element.metadata.isEmpty();
607 } 598 }
608 599
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) { 600 void patchMember(Element originalElement, Element patchElement) {
624 // The original library has an element with the same name as the patch 601 // The original library has an element with the same name as the patch
625 // library element. 602 // library element.
626 // In this case, the patch library element must be a function marked as 603 // 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. 604 // "patch" and it must have the same signature as the function it patches.
628 if (!isPatchElement(patchElement)) { 605 if (!isPatchElement(patchElement)) {
629 internalError("Cannot overwrite existing '" 606 internalError("Cannot overwrite existing '"
630 "${originalElement.name.slowToString()}' with non-patch."); 607 "${originalElement.name.slowToString()}' with non-patch.");
631 } 608 }
632 if (originalElement is PartialClassElement) { 609 if (originalElement is PartialClassElement) {
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 api.Diagnostic kind); 948 api.Diagnostic kind);
972 949
973 SourceSpan spanFromTokens(Token begin, Token end, [Uri uri]) { 950 SourceSpan spanFromTokens(Token begin, Token end, [Uri uri]) {
974 if (begin === null || end === null) { 951 if (begin === null || end === null) {
975 // TODO(ahe): We can almost always do better. Often it is only 952 // TODO(ahe): We can almost always do better. Often it is only
976 // end that is null. Otherwise, we probably know the current 953 // end that is null. Otherwise, we probably know the current
977 // URI. 954 // URI.
978 throw 'Cannot find tokens to produce error message.'; 955 throw 'Cannot find tokens to produce error message.';
979 } 956 }
980 if (uri === null && currentElement !== null) { 957 if (uri === null && currentElement !== null) {
981 uri = currentElement.getCompilationUnit().script.uri; 958 uri = currentElement.getScript().uri;
982 } 959 }
983 return SourceSpan.withCharacterOffsets(begin, end, 960 return SourceSpan.withCharacterOffsets(begin, end,
984 (beginOffset, endOffset) => new SourceSpan(uri, beginOffset, endOffset)); 961 (beginOffset, endOffset) => new SourceSpan(uri, beginOffset, endOffset));
985 } 962 }
986 963
987 SourceSpan spanFromNode(Node node, [Uri uri]) { 964 SourceSpan spanFromNode(Node node, [Uri uri]) {
988 return spanFromTokens(node.getBeginToken(), node.getEndToken(), uri); 965 return spanFromTokens(node.getBeginToken(), node.getEndToken(), uri);
989 } 966 }
990 967
991 SourceSpan spanFromElement(Element element) { 968 SourceSpan spanFromElement(Element element) {
992 if (element.position() === null) { 969 if (element.position() === null) {
993 // Sometimes, the backend fakes up elements that have no 970 // Sometimes, the backend fakes up elements that have no
994 // position. So we use the enclosing element instead. It is 971 // position. So we use the enclosing element instead. It is
995 // not a good error location, but cancel really is "internal 972 // not a good error location, but cancel really is "internal
996 // error" or "not implemented yet", so the vicinity is good 973 // error" or "not implemented yet", so the vicinity is good
997 // enough for now. 974 // enough for now.
998 element = element.enclosingElement; 975 element = element.enclosingElement;
999 // TODO(ahe): I plan to overhaul this infrastructure anyways. 976 // TODO(ahe): I plan to overhaul this infrastructure anyways.
1000 } 977 }
1001 if (element === null) { 978 if (element === null) {
1002 element = currentElement; 979 element = currentElement;
1003 } 980 }
1004 Token position = element.position(); 981 Token position = element.position();
1005 Uri uri = element.getCompilationUnit().script.uri; 982 Uri uri = element.getScript().uri;
1006 return (position === null) 983 return (position === null)
1007 ? new SourceSpan(uri, 0, 0) 984 ? new SourceSpan(uri, 0, 0)
1008 : spanFromTokens(position, position, uri); 985 : spanFromTokens(position, position, uri);
1009 } 986 }
1010 987
1011 Script readScript(Uri uri, [ScriptTag node]) { 988 Script readScript(Uri uri, [ScriptTag node]) {
1012 unimplemented('Compiler.readScript'); 989 unimplemented('Compiler.readScript');
1013 } 990 }
1014 991
1015 String get legDirectory() { 992 String get legDirectory() {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 final endOffset = end.charOffset + end.slowCharCount; 1062 final endOffset = end.charOffset + end.slowCharCount;
1086 1063
1087 // [begin] and [end] might be the same for the same empty token. This 1064 // [begin] and [end] might be the same for the same empty token. This
1088 // happens for instance when scanning '$$'. 1065 // happens for instance when scanning '$$'.
1089 assert(endOffset >= beginOffset); 1066 assert(endOffset >= beginOffset);
1090 return f(beginOffset, endOffset); 1067 return f(beginOffset, endOffset);
1091 } 1068 }
1092 1069
1093 String toString() => 'SourceSpan($uri, $begin, $end)'; 1070 String toString() => 'SourceSpan($uri, $begin, $end)';
1094 } 1071 }
OLDNEW
« no previous file with comments | « corelib/unified/math/random.dart ('k') | lib/compiler/implementation/elements/elements.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698