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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
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 #library("patchparser"); 5 #library("patchparser");
6 #import("dart:uri"); 6 #import("dart:uri");
7 7
8 #import("tree/tree.dart", prefix: "tree"); 8 #import("tree/tree.dart", prefix: "tree");
9 #import("leg.dart", prefix: 'leg'); // CompilerTask, Compiler. 9 #import("leg.dart", prefix: 'leg'); // CompilerTask, Compiler.
10 #import("apiimpl.dart"); 10 #import("apiimpl.dart");
11 #import("scanner/scannerlib.dart"); // Scanner, Parsers, Listeners 11 #import("scanner/scannerlib.dart"); // Scanner, Parsers, Listeners
12 #import("elements/elements.dart"); 12 #import("elements/elements.dart");
13 #import('native_handler.dart', prefix: 'native'); 13 #import('util/util.dart');
14 14
15 class PatchParserTask extends leg.CompilerTask { 15 class PatchParserTask extends leg.CompilerTask {
16 PatchParserTask(leg.Compiler compiler): super(compiler); 16 PatchParserTask(leg.Compiler compiler): super(compiler);
17 final String name = "Patching Parser"; 17 final String name = "Patching Parser";
18 18
19 LibraryElement loadPatchLibrary(Uri uri) { 19 /**
20 bool newLibrary = false; 20 * Scans a library patch file, applies the method patches and
21 LibraryElement library = 21 * injections to the library, and returns a list of class
22 compiler.libraries.putIfAbsent(uri.toString(), () { 22 * patches.
23 newLibrary = true; 23 */
24 leg.Script script = compiler.readScript(uri, null); 24 void patchLibrary(Uri patchUri, LibraryElement library) {
25 LibraryElement element = 25 leg.Script script = compiler.readScript(patchUri, null);
26 new LibraryElement(script); 26 CompilationUnitElement compilationUnit =
27 native.maybeEnableNative(compiler, element, uri); 27 new CompilationUnitElement(script, library);
28 return element; 28 library.addCompilationUnit(compilationUnit);
29 }); 29 LinkBuilder<tree.ScriptTag> imports = new LinkBuilder<tree.ScriptTag>();
30 if (newLibrary) { 30 compiler.withCurrentElement(compilationUnit, () {
31 compiler.withCurrentElement(library, () { 31 // This patches the elements of the patch library into [library].
32 scanLibraryElements(library); 32 // Injected elements are added directly under the compilation unit.
33 compiler.onLibraryLoaded(library, uri); 33 // Patche elements are stored on the patched functions or classes.
34 }); 34 scanLibraryElements(compilationUnit, imports);
35 });
36 // After scanning declarations, we handle the import tags in the patch.
37 // TODO(lrn): These imports end up in the original library and are in
38 // scope for the original methods too. This should be fixed.
39 for (tree.ScriptTag tag in imports.toLink()) {
40 compiler.scanner.importLibraryFromTag(tag, compilationUnit);
35 } 41 }
36 return library;
37 } 42 }
38 43
39 void scanLibraryElements(LibraryElement library) { 44 void scanLibraryElements(
45 CompilationUnitElement compilationUnit,
46 LinkBuilder<tree.ScriptTag> imports) {
40 measure(() { 47 measure(() {
41 // TODO(lrn): Possibly recursively handle #source directives in patch. 48 // TODO(lrn): Possibly recursively handle #source directives in patch.
42 leg.Script script = library.entryCompilationUnit.script; 49 leg.Script script = compilationUnit.script;
43 Token tokens = new StringScanner(script.text).tokenize(); 50 Token tokens = new StringScanner(script.text).tokenize();
44 Function idGenerator = compiler.getNextFreeClassId; 51 Function idGenerator = compiler.getNextFreeClassId;
45 PatchListener patchListener = 52 PatchListener patchListener =
46 new PatchElementListener(compiler, 53 new PatchElementListener(compiler,
47 library.entryCompilationUnit, 54 compilationUnit,
48 idGenerator); 55 idGenerator,
56 imports);
49 new PatchParser(patchListener).parseUnit(tokens); 57 new PatchParser(patchListener).parseUnit(tokens);
50 }); 58 });
51 } 59 }
52 60
53 tree.ClassNode parsePatchClassNode(PartialClassElement element) { 61 tree.ClassNode parsePatchClassNode(PartialClassElement element) {
54 // Parse [PartialClassElement] using a "patch"-aware parser instead 62 // Parse [PartialClassElement] using a "patch"-aware parser instead
55 // of calling its [parseNode] method. 63 // of calling its [parseNode] method.
56 if (element.cachedNode != null) return element.cachedNode; 64 if (element.cachedNode != null) return element.cachedNode;
57 PatchMemberListener listener = 65 PatchMemberListener listener =
58 new PatchMemberListener(compiler, element); 66 new PatchMemberListener(compiler, element);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 PatchClassElementParser(PatchListener listener) : super(listener); 150 PatchClassElementParser(PatchListener listener) : super(listener);
143 151
144 Token parseClassBody(Token token) => fullParseClassBody(token); 152 Token parseClassBody(Token token) => fullParseClassBody(token);
145 } 153 }
146 154
147 155
148 /** 156 /**
149 * Extension of [ElementListener] for parsing patch files. 157 * Extension of [ElementListener] for parsing patch files.
150 */ 158 */
151 class PatchElementListener extends ElementListener implements PatchListener { 159 class PatchElementListener extends ElementListener implements PatchListener {
160 final LinkBuilder<tree.ScriptTag> imports;
152 bool isMemberPatch = false; 161 bool isMemberPatch = false;
153 bool isClassPatch = false; 162 bool isClassPatch = false;
163
154 PatchElementListener(leg.DiagnosticListener listener, 164 PatchElementListener(leg.DiagnosticListener listener,
155 CompilationUnitElement patchElement, 165 CompilationUnitElement patchElement,
156 int idGenerator()) 166 int idGenerator(),
167 this.imports)
157 : super(listener, patchElement, idGenerator); 168 : super(listener, patchElement, idGenerator);
158 169
159 void beginPatch(Token token) { 170 void beginPatch(Token token) {
160 if (token.next.stringValue === "class") { 171 if (token.next.stringValue === "class") {
161 isClassPatch = true; 172 isClassPatch = true;
162 } else { 173 } else {
163 isMemberPatch = true; 174 isMemberPatch = true;
164 } 175 }
165 handleIdentifier(token); 176 handleIdentifier(token);
166 } 177 }
167 178
168 void endPatch(Token token) { 179 void endPatch(Token token) {
169 if (token.next.stringValue === "class") { 180 if (token.next.stringValue === "class") {
170 isClassPatch = false; 181 isClassPatch = false;
171 } else { 182 } else {
172 isMemberPatch = false; 183 isMemberPatch = false;
173 } 184 }
174 } 185 }
175 186
187 /**
188 * Allow script tags (import only, the parser rejects the rest for now) in
189 * patch files. The import tags will be added to the library.
190 */
191 bool allowScriptTags() => true;
192
193 void addScriptTag(tree.ScriptTag tag) {
194 super.addScriptTag(tag);
195 imports.addLast(tag);
196 }
197
176 void pushElement(Element element) { 198 void pushElement(Element element) {
177 if (isMemberPatch || (isClassPatch && element is ClassElement)) { 199 if (isMemberPatch || (isClassPatch && element is ClassElement)) {
200 // Apply patch.
178 element.addMetadata(popNode()); 201 element.addMetadata(popNode());
202 LibraryElement library = compilationUnitElement.getLibrary();
203 Element existing = library.localLookup(element.name);
204 if (isMemberPatch) {
205 if (element is! FunctionElement) {
206 listener.internalErrorOnElement(element,
207 "Member patch is not a function.");
208 }
209 if (existing.kind === ElementKind.ABSTRACT_FIELD) {
210 if (!element.isAccessor()) {
211 listener.internalErrorOnElement(
212 element, "Patching non-accessor with accessor");
213 }
214 AbstractField field = existing;
215 if (element.isGetter()) {
216 existing = field.getter;
217 } else {
218 existing = field.setter;
219 }
220 }
221 if (existing is! FunctionElement) {
222 listener.internalErrorOnElement(element,
223 "No corresponding method for patch.");
224 }
225 FunctionElement function = existing;
226 if (function.isPatched) {
227 listener.internalErrorOnElement(
228 element, "Patching the same function more than once.");
229 }
230 function.patch = element;
231 } else {
232 if (existing is! ClassElement) {
233 listener.internalErrorOnElement(
234 element, "Patching a non-class with a class patch.");
235 }
236 ClassElement classElement = existing;
237 if (classElement.isPatched) {
238 listener.internalErrorOnElement(
239 element, "Patching the same class more than once.");
240 }
241 classElement.patch = element;
242 }
243 return;
179 } 244 }
180 super.pushElement(element); 245 super.pushElement(element);
181 } 246 }
182 } 247 }
183 248
184 249
185 /** 250 /**
186 * Extension of [MemberListener] for parsing patch class bodies. 251 * Extension of [MemberListener] for parsing patch class bodies.
187 */ 252 */
188 class PatchMemberListener extends MemberListener implements PatchListener { 253 class PatchMemberListener extends MemberListener implements PatchListener {
(...skipping 20 matching lines...) Expand all
209 } 274 }
210 } 275 }
211 276
212 void addMember(Element element) { 277 void addMember(Element element) {
213 if (isMemberPatch || (isClassPatch && element is ClassElement)) { 278 if (isMemberPatch || (isClassPatch && element is ClassElement)) {
214 element.addMetadata(popNode()); 279 element.addMetadata(popNode());
215 } 280 }
216 super.addMember(element); 281 super.addMember(element);
217 } 282 }
218 } 283 }
OLDNEW
« 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