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

Unified Diff: lib/compiler/implementation/patch_parser.dart

Issue 10824347: Make top-level patch injections be compilation unit under library. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Offline discussed changes. Created 8 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: lib/compiler/implementation/patch_parser.dart
diff --git a/lib/compiler/implementation/patch_parser.dart b/lib/compiler/implementation/patch_parser.dart
index 3d25e2e191b3ae0f8df6a9911a18d43da522478c..efae70656beb7e8c864cdf66c568f49c19f0a877 100644
--- a/lib/compiler/implementation/patch_parser.dart
+++ b/lib/compiler/implementation/patch_parser.dart
@@ -10,42 +10,50 @@
#import("apiimpl.dart");
#import("scanner/scannerlib.dart"); // Scanner, Parsers, Listeners
#import("elements/elements.dart");
-#import('native_handler.dart', prefix: 'native');
+#import('util/util.dart');
class PatchParserTask extends leg.CompilerTask {
PatchParserTask(leg.Compiler compiler): super(compiler);
final String name = "Patching Parser";
- LibraryElement loadPatchLibrary(Uri uri) {
- bool newLibrary = false;
- LibraryElement library =
- compiler.libraries.putIfAbsent(uri.toString(), () {
- newLibrary = true;
- leg.Script script = compiler.readScript(uri, null);
- LibraryElement element =
- new LibraryElement(script);
- native.maybeEnableNative(compiler, element, uri);
- return element;
- });
- if (newLibrary) {
- compiler.withCurrentElement(library, () {
- scanLibraryElements(library);
- compiler.onLibraryLoaded(library, uri);
- });
+ /**
+ * Scans a library patch file, applies the method patches and
+ * injections to the library, and returns a list of class
+ * patches.
+ */
+ void patchLibrary(Uri patchUri, LibraryElement library) {
+ leg.Script script = compiler.readScript(patchUri, null);
+ CompilationUnitElement compilationUnit =
+ new CompilationUnitElement(script, library);
+ library.addCompilationUnit(compilationUnit);
+ LinkBuilder<tree.ScriptTag> imports = new LinkBuilder<tree.ScriptTag>();
+ compiler.withCurrentElement(compilationUnit, () {
+ // This patches the elements of the patch library into [library].
+ // Injected elements are added directly under the compilation unit.
+ // Patche elements are stored on the patched functions or classes.
+ scanLibraryElements(compilationUnit, imports);
+ });
+ // After scanning declarations, we handle the import tags in the patch.
+ // TODO(lrn): These imports end up in the original library and are in
+ // scope for the original methods too. This should be fixed.
+ for (tree.ScriptTag tag in imports.toLink()) {
+ compiler.scanner.importLibraryFromTag(tag, compilationUnit);
}
- return library;
}
- void scanLibraryElements(LibraryElement library) {
+ void scanLibraryElements(
+ CompilationUnitElement compilationUnit,
+ LinkBuilder<tree.ScriptTag> imports) {
measure(() {
// TODO(lrn): Possibly recursively handle #source directives in patch.
- leg.Script script = library.entryCompilationUnit.script;
+ leg.Script script = compilationUnit.script;
Token tokens = new StringScanner(script.text).tokenize();
Function idGenerator = compiler.getNextFreeClassId;
PatchListener patchListener =
new PatchElementListener(compiler,
- library.entryCompilationUnit,
- idGenerator);
+ compilationUnit,
+ idGenerator,
+ imports);
new PatchParser(patchListener).parseUnit(tokens);
});
}
@@ -149,11 +157,14 @@ class PatchClassElementParser extends PatchParser {
* Extension of [ElementListener] for parsing patch files.
*/
class PatchElementListener extends ElementListener implements PatchListener {
+ final LinkBuilder<tree.ScriptTag> imports;
bool isMemberPatch = false;
bool isClassPatch = false;
+
PatchElementListener(leg.DiagnosticListener listener,
CompilationUnitElement patchElement,
- int idGenerator())
+ int idGenerator(),
+ this.imports)
: super(listener, patchElement, idGenerator);
void beginPatch(Token token) {
@@ -173,9 +184,63 @@ class PatchElementListener extends ElementListener implements PatchListener {
}
}
+ /**
+ * Allow script tags (import only, the parser rejects the rest for now) in
+ * patch files. The import tags will be added to the library.
+ */
+ bool allowScriptTags() => true;
+
+ void addScriptTag(tree.ScriptTag tag) {
+ super.addScriptTag(tag);
+ imports.addLast(tag);
+ }
+
void pushElement(Element element) {
if (isMemberPatch || (isClassPatch && element is ClassElement)) {
+ // Apply patch.
element.addMetadata(popNode());
+ LibraryElement library = compilationUnitElement.getLibrary();
+ Element existing = library.localLookup(element.name);
+ if (isMemberPatch) {
+ if (element is! FunctionElement) {
+ listener.internalErrorOnElement(element,
+ "Member patch is not a function.");
+ }
+ if (existing.kind === ElementKind.ABSTRACT_FIELD) {
+ if (!element.isAccessor()) {
+ listener.internalErrorOnElement(
+ element, "Patching non-accessor with accessor");
+ }
+ AbstractField field = existing;
+ if (element.isGetter()) {
+ existing = field.getter;
+ } else {
+ existing = field.setter;
+ }
+ }
+ if (existing is! FunctionElement) {
+ listener.internalErrorOnElement(element,
+ "No corresponding method for patch.");
+ }
+ FunctionElement function = existing;
+ if (function.isPatched) {
+ listener.internalErrorOnElement(
+ element, "Patching the same function more than once.");
+ }
+ function.patch = element;
+ } else {
+ if (existing is! ClassElement) {
+ listener.internalErrorOnElement(
+ element, "Patching a non-class with a class patch.");
+ }
+ ClassElement classElement = existing;
+ if (classElement.isPatched) {
+ listener.internalErrorOnElement(
+ element, "Patching the same class more than once.");
+ }
+ classElement.patch = element;
+ }
+ return;
}
super.pushElement(element);
}
« no previous file with comments | « lib/compiler/implementation/elements/elements.dart ('k') | lib/compiler/implementation/scanner/listener.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698