| 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.script); | 537         scanner.importLibrary(original, importedLibrary, tag, patch); | 
| 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       assert(patchElement.kind !== ElementKind.ABSTRACT_FIELD); | 559       // Getters and setters are kept inside a synthetic field. | 
| 560       if (originalElement !== null && | 560       if (patchElement.kind === ElementKind.ABSTRACT_FIELD) { | 
| 561           originalElement.kind === ElementKind.ABSTRACT_FIELD) { | 561         if (originalElement !== null && | 
|  | 562             originalElement.kind !== ElementKind.ABSTRACT_FIELD) { | 
|  | 563           internalError("Cannot patch non-getter/setter with getter/setter", | 
|  | 564                         element: originalElement); | 
|  | 565         } | 
|  | 566         AbstractFieldElement patchField = patchElement; | 
| 562         AbstractFieldElement originalField = originalElement; | 567         AbstractFieldElement originalField = originalElement; | 
| 563         if (patchElement.kind === ElementKind.GETTER) { | 568         if (patchField.getter !== null) { | 
| 564           originalElement = originalField.getter; | 569           if (originalField === null || originalField.getter === null) { | 
| 565         } else if (patchElement.kind === ElementKind.SETTER) { | 570             original.addGetterOrSetter(clonePatch(patchField.getter), | 
| 566           originalElement = originalField.setter; | 571                                        originalField, | 
| 567         } else { | 572                                        this); | 
| 568           internalError("Cannot patch a getter/setter field with a " | 573             if (originalField === null && patchField.setter !== null) { | 
| 569                         "non-getter/setter patch", element: originalElement); | 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           } | 
| 570         } | 580         } | 
| 571       } | 581         if (patchField.setter !== null) { | 
| 572       if (originalElement === null) { | 582           if (originalField === null || originalField.setter === null) { | 
| 573         // The original library does not have an element with the same name | 583             original.addGetterOrSetter(clonePatch(patchField.setter), | 
| 574         // as the patch library element. | 584                                        originalField, | 
| 575         // In this case, the patch library element must not be marked as | 585                                        this); | 
| 576         // "patch", and its name must make it private. | 586           } else { | 
|  | 587             patchMember(originalField.setter, patchField.setter); | 
|  | 588           } | 
|  | 589         } | 
|  | 590       } else if (originalElement === null) { | 
| 577         if (isPatchElement(patchElement)) { | 591         if (isPatchElement(patchElement)) { | 
| 578           internalError("Cannot patch non-existing member '" | 592           internalError("Cannot patch non-existing member '" | 
| 579                         "${patchElement.name.slowToString()}'."); | 593                         "${patchElement.name.slowToString()}'."); | 
| 580         } | 594         } | 
| 581         if (!patchElement.name.isPrivate()) { | 595         original.addMember(clonePatch(patchElement), this); | 
| 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); |  | 
| 587       } else { | 596       } else { | 
| 588         patchMember(originalElement, patchElement); | 597         patchMember(originalElement, patchElement); | 
| 589       } | 598       } | 
| 590       patches = patches.tail; | 599       patches = patches.tail; | 
| 591     } | 600     } | 
| 592   } | 601   } | 
| 593 | 602 | 
| 594   bool isPatchElement(Element element) { | 603   bool isPatchElement(Element element) { | 
| 595     // TODO(lrn): More checks needed if we introduce metadata for real. | 604     // TODO(lrn): More checks needed if we introduce metadata for real. | 
| 596     // In that case, it must have the identifier "native" as metadata. | 605     // In that case, it must have the identifier "native" as metadata. | 
| 597     return !element.metadata.isEmpty(); | 606     return !element.metadata.isEmpty(); | 
| 598   } | 607   } | 
| 599 | 608 | 
|  | 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 | 
| 600   void patchMember(Element originalElement, Element patchElement) { | 623   void patchMember(Element originalElement, Element patchElement) { | 
| 601     // The original library has an element with the same name as the patch | 624     // The original library has an element with the same name as the patch | 
| 602     // library element. | 625     // library element. | 
| 603     // In this case, the patch library element must be a function marked as | 626     // In this case, the patch library element must be a function marked as | 
| 604     // "patch" and it must have the same signature as the function it patches. | 627     // "patch" and it must have the same signature as the function it patches. | 
| 605     if (!isPatchElement(patchElement)) { | 628     if (!isPatchElement(patchElement)) { | 
| 606       internalError("Cannot overwrite existing '" | 629       internalError("Cannot overwrite existing '" | 
| 607                     "${originalElement.name.slowToString()}' with non-patch."); | 630                     "${originalElement.name.slowToString()}' with non-patch."); | 
| 608     } | 631     } | 
| 609     if (originalElement is PartialClassElement) { | 632     if (originalElement is PartialClassElement) { | 
| (...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 948                                  api.Diagnostic kind); | 971                                  api.Diagnostic kind); | 
| 949 | 972 | 
| 950   SourceSpan spanFromTokens(Token begin, Token end, [Uri uri]) { | 973   SourceSpan spanFromTokens(Token begin, Token end, [Uri uri]) { | 
| 951     if (begin === null || end === null) { | 974     if (begin === null || end === null) { | 
| 952       // TODO(ahe): We can almost always do better. Often it is only | 975       // TODO(ahe): We can almost always do better. Often it is only | 
| 953       // end that is null. Otherwise, we probably know the current | 976       // end that is null. Otherwise, we probably know the current | 
| 954       // URI. | 977       // URI. | 
| 955       throw 'Cannot find tokens to produce error message.'; | 978       throw 'Cannot find tokens to produce error message.'; | 
| 956     } | 979     } | 
| 957     if (uri === null && currentElement !== null) { | 980     if (uri === null && currentElement !== null) { | 
| 958       uri = currentElement.getScript().uri; | 981       uri = currentElement.getCompilationUnit().script.uri; | 
| 959     } | 982     } | 
| 960     return SourceSpan.withCharacterOffsets(begin, end, | 983     return SourceSpan.withCharacterOffsets(begin, end, | 
| 961       (beginOffset, endOffset) => new SourceSpan(uri, beginOffset, endOffset)); | 984       (beginOffset, endOffset) => new SourceSpan(uri, beginOffset, endOffset)); | 
| 962   } | 985   } | 
| 963 | 986 | 
| 964   SourceSpan spanFromNode(Node node, [Uri uri]) { | 987   SourceSpan spanFromNode(Node node, [Uri uri]) { | 
| 965     return spanFromTokens(node.getBeginToken(), node.getEndToken(), uri); | 988     return spanFromTokens(node.getBeginToken(), node.getEndToken(), uri); | 
| 966   } | 989   } | 
| 967 | 990 | 
| 968   SourceSpan spanFromElement(Element element) { | 991   SourceSpan spanFromElement(Element element) { | 
| 969     if (element.position() === null) { | 992     if (element.position() === null) { | 
| 970       // Sometimes, the backend fakes up elements that have no | 993       // Sometimes, the backend fakes up elements that have no | 
| 971       // position. So we use the enclosing element instead. It is | 994       // position. So we use the enclosing element instead. It is | 
| 972       // not a good error location, but cancel really is "internal | 995       // not a good error location, but cancel really is "internal | 
| 973       // error" or "not implemented yet", so the vicinity is good | 996       // error" or "not implemented yet", so the vicinity is good | 
| 974       // enough for now. | 997       // enough for now. | 
| 975       element = element.enclosingElement; | 998       element = element.enclosingElement; | 
| 976       // TODO(ahe): I plan to overhaul this infrastructure anyways. | 999       // TODO(ahe): I plan to overhaul this infrastructure anyways. | 
| 977     } | 1000     } | 
| 978     if (element === null) { | 1001     if (element === null) { | 
| 979       element = currentElement; | 1002       element = currentElement; | 
| 980     } | 1003     } | 
| 981     Token position = element.position(); | 1004     Token position = element.position(); | 
| 982     Uri uri = element.getScript().uri; | 1005     Uri uri = element.getCompilationUnit().script.uri; | 
| 983     return (position === null) | 1006     return (position === null) | 
| 984         ? new SourceSpan(uri, 0, 0) | 1007         ? new SourceSpan(uri, 0, 0) | 
| 985         : spanFromTokens(position, position, uri); | 1008         : spanFromTokens(position, position, uri); | 
| 986   } | 1009   } | 
| 987 | 1010 | 
| 988   Script readScript(Uri uri, [ScriptTag node]) { | 1011   Script readScript(Uri uri, [ScriptTag node]) { | 
| 989     unimplemented('Compiler.readScript'); | 1012     unimplemented('Compiler.readScript'); | 
| 990   } | 1013   } | 
| 991 | 1014 | 
| 992   String get legDirectory() { | 1015   String get legDirectory() { | 
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1062     final endOffset = end.charOffset + end.slowCharCount; | 1085     final endOffset = end.charOffset + end.slowCharCount; | 
| 1063 | 1086 | 
| 1064     // [begin] and [end] might be the same for the same empty token. This | 1087     // [begin] and [end] might be the same for the same empty token. This | 
| 1065     // happens for instance when scanning '$$'. | 1088     // happens for instance when scanning '$$'. | 
| 1066     assert(endOffset >= beginOffset); | 1089     assert(endOffset >= beginOffset); | 
| 1067     return f(beginOffset, endOffset); | 1090     return f(beginOffset, endOffset); | 
| 1068   } | 1091   } | 
| 1069 | 1092 | 
| 1070   String toString() => 'SourceSpan($uri, $begin, $end)'; | 1093   String toString() => 'SourceSpan($uri, $begin, $end)'; | 
| 1071 } | 1094 } | 
| OLD | NEW | 
|---|