| 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 * This library contains the infrastructure to parse and integrate patch files. | 6 * This library contains the infrastructure to parse and integrate patch files. |
| 7 * | 7 * |
| 8 * Three types of elements can be patched: [LibraryElement], [ClassElement], | 8 * Three types of elements can be patched: [LibraryElement], [ClassElement], |
| 9 * [FunctionElement]. Patches are introduced in patch libraries which are loaded | 9 * [FunctionElement]. Patches are introduced in patch libraries which are loaded |
| 10 * together with the corresponding origin library. Which libraries that are | 10 * together with the corresponding origin library. Which libraries that are |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 import "tree/tree.dart" as tree; | 119 import "tree/tree.dart" as tree; |
| 120 import "dart2jslib.dart" as leg; // CompilerTask, Compiler. | 120 import "dart2jslib.dart" as leg; // CompilerTask, Compiler. |
| 121 import "helpers/helpers.dart"; | 121 import "helpers/helpers.dart"; |
| 122 import "scanner/scannerlib.dart"; // Scanner, Parsers, Listeners | 122 import "scanner/scannerlib.dart"; // Scanner, Parsers, Listeners |
| 123 import "elements/elements.dart"; | 123 import "elements/elements.dart"; |
| 124 import "elements/modelx.dart" | 124 import "elements/modelx.dart" |
| 125 show LibraryElementX, | 125 show LibraryElementX, |
| 126 MetadataAnnotationX, | 126 MetadataAnnotationX, |
| 127 ClassElementX, | 127 ClassElementX, |
| 128 FunctionElementX; | 128 FunctionElementX; |
| 129 import "library_loader.dart" show LibraryLoaderCallback; |
| 129 import 'util/util.dart'; | 130 import 'util/util.dart'; |
| 130 | 131 |
| 131 class PatchParserTask extends leg.CompilerTask { | 132 class PatchParserTask extends leg.CompilerTask { |
| 132 PatchParserTask(leg.Compiler compiler): super(compiler); | 133 PatchParserTask(leg.Compiler compiler): super(compiler); |
| 133 final String name = "Patching Parser"; | 134 final String name = "Patching Parser"; |
| 134 | 135 |
| 135 /** | 136 /** |
| 136 * Scans a library patch file, applies the method patches and | 137 * Scans a library patch file, applies the method patches and |
| 137 * injections to the library, and returns a list of class | 138 * injections to the library, and returns a list of class |
| 138 * patches. | 139 * patches. |
| 139 */ | 140 */ |
| 140 Future patchLibrary(leg.LibraryDependencyHandler handler, | 141 Future patchLibrary(LibraryLoaderCallback callback, |
| 141 Uri patchUri, LibraryElement originLibrary) { | 142 Uri patchUri, LibraryElement originLibrary) { |
| 142 return compiler.readScript(originLibrary, patchUri) | 143 return compiler.readScript(originLibrary, patchUri) |
| 143 .then((leg.Script script) { | 144 .then((leg.Script script) { |
| 144 var patchLibrary = new LibraryElementX(script, null, originLibrary); | 145 var patchLibrary = new LibraryElementX(script, null, originLibrary); |
| 145 return compiler.withCurrentElement(patchLibrary, () { | 146 return compiler.withCurrentElement(patchLibrary, () { |
| 146 handler.registerNewLibrary(patchLibrary); | 147 callback.onLibraryCreated(patchLibrary); |
| 147 var imports = new LinkBuilder<tree.LibraryTag>(); | |
| 148 compiler.withCurrentElement(patchLibrary.entryCompilationUnit, () { | 148 compiler.withCurrentElement(patchLibrary.entryCompilationUnit, () { |
| 149 // This patches the elements of the patch library into [library]. | 149 // This patches the elements of the patch library into [library]. |
| 150 // Injected elements are added directly under the compilation unit. | 150 // Injected elements are added directly under the compilation unit. |
| 151 // Patch elements are stored on the patched functions or classes. | 151 // Patch elements are stored on the patched functions or classes. |
| 152 scanLibraryElements(patchLibrary.entryCompilationUnit, imports); | 152 scanLibraryElements(patchLibrary.entryCompilationUnit); |
| 153 }); | 153 }); |
| 154 // TODO(rnystrom): Remove .toList() here if #11523 is fixed. | 154 return callback.onLibraryScanned(patchLibrary); |
| 155 return Future.forEach(imports.toLink().toList(), (tag) { | |
| 156 return compiler.withCurrentElement(patchLibrary, () { | |
| 157 return compiler.libraryLoader.registerLibraryFromTag( | |
| 158 handler, patchLibrary, tag); | |
| 159 }); | |
| 160 }); | |
| 161 }); | 155 }); |
| 162 }); | 156 }); |
| 163 } | 157 } |
| 164 | 158 |
| 165 void scanLibraryElements( | 159 void scanLibraryElements(CompilationUnitElement compilationUnit) { |
| 166 CompilationUnitElement compilationUnit, | |
| 167 LinkBuilder<tree.LibraryTag> imports) { | |
| 168 measure(() { | 160 measure(() { |
| 169 // TODO(lrn): Possibly recursively handle 'part' directives in patch. | 161 // TODO(johnniwinther): Test that parts and exports are handled correctly. |
| 170 leg.Script script = compilationUnit.script; | 162 leg.Script script = compilationUnit.script; |
| 171 Token tokens = new Scanner(script.file).tokenize(); | 163 Token tokens = new Scanner(script.file).tokenize(); |
| 172 Function idGenerator = compiler.getNextFreeClassId; | 164 Function idGenerator = compiler.getNextFreeClassId; |
| 173 Listener patchListener = new PatchElementListener(compiler, | 165 Listener patchListener = new PatchElementListener(compiler, |
| 174 compilationUnit, | 166 compilationUnit, |
| 175 idGenerator, | 167 idGenerator); |
| 176 imports); | |
| 177 new PartialParser(patchListener).parseUnit(tokens); | 168 new PartialParser(patchListener).parseUnit(tokens); |
| 178 }); | 169 }); |
| 179 } | 170 } |
| 180 | 171 |
| 181 void parsePatchClassNode(PartialClassElement element) { | 172 void parsePatchClassNode(PartialClassElement element) { |
| 182 // Parse [PartialClassElement] using a "patch"-aware parser instead | 173 // Parse [PartialClassElement] using a "patch"-aware parser instead |
| 183 // of calling its [parseNode] method. | 174 // of calling its [parseNode] method. |
| 184 if (element.cachedNode != null) return; | 175 if (element.cachedNode != null) return; |
| 185 | 176 |
| 186 measure(() => compiler.withCurrentElement(element, () { | 177 measure(() => compiler.withCurrentElement(element, () { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 215 PatchClassElementParser(Listener listener) : super(listener); | 206 PatchClassElementParser(Listener listener) : super(listener); |
| 216 | 207 |
| 217 Token parseClassBody(Token token) => fullParseClassBody(token); | 208 Token parseClassBody(Token token) => fullParseClassBody(token); |
| 218 } | 209 } |
| 219 | 210 |
| 220 /** | 211 /** |
| 221 * Extension of [ElementListener] for parsing patch files. | 212 * Extension of [ElementListener] for parsing patch files. |
| 222 */ | 213 */ |
| 223 class PatchElementListener extends ElementListener implements Listener { | 214 class PatchElementListener extends ElementListener implements Listener { |
| 224 final leg.Compiler compiler; | 215 final leg.Compiler compiler; |
| 225 final LinkBuilder<tree.LibraryTag> imports; | |
| 226 | 216 |
| 227 PatchElementListener(leg.Compiler compiler, | 217 PatchElementListener(leg.Compiler compiler, |
| 228 CompilationUnitElement patchElement, | 218 CompilationUnitElement patchElement, |
| 229 int idGenerator(), | 219 int idGenerator()) |
| 230 this.imports) | |
| 231 : this.compiler = compiler, | 220 : this.compiler = compiler, |
| 232 super(compiler, patchElement, idGenerator); | 221 super(compiler, patchElement, idGenerator); |
| 233 | 222 |
| 234 /** | |
| 235 * Allow script tags (import only, the parser rejects the rest for now) in | |
| 236 * patch files. The import tags will be added to the library. | |
| 237 */ | |
| 238 bool allowLibraryTags() => true; | |
| 239 | |
| 240 void addLibraryTag(tree.LibraryTag tag) { | |
| 241 super.addLibraryTag(tag); | |
| 242 imports.addLast(tag); | |
| 243 } | |
| 244 | |
| 245 void pushElement(Element patch) { | 223 void pushElement(Element patch) { |
| 246 super.pushElement(patch); | 224 super.pushElement(patch); |
| 247 if (isPatchElement(compiler, patch)) { | 225 if (isPatchElement(compiler, patch)) { |
| 248 LibraryElement originLibrary = compilationUnitElement.library; | 226 LibraryElement originLibrary = compilationUnitElement.library; |
| 249 assert(originLibrary.isPatched); | 227 assert(originLibrary.isPatched); |
| 250 Element origin = originLibrary.localLookup(patch.name); | 228 Element origin = originLibrary.localLookup(patch.name); |
| 251 patchElement(listener, origin, patch); | 229 patchElement(listener, origin, patch); |
| 252 } | 230 } |
| 253 } | 231 } |
| 254 } | 232 } |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 annotation.ensureResolved(compiler); | 396 annotation.ensureResolved(compiler); |
| 419 if (annotation.value != compiler.patchConstant) { | 397 if (annotation.value != compiler.patchConstant) { |
| 420 compiler.internalError(annotation, 'Invalid patch annotation.'); | 398 compiler.internalError(annotation, 'Invalid patch annotation.'); |
| 421 } | 399 } |
| 422 }); | 400 }); |
| 423 return true; | 401 return true; |
| 424 } | 402 } |
| 425 } | 403 } |
| 426 return false; | 404 return false; |
| 427 } | 405 } |
| OLD | NEW |