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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/dart_backend/outputter.dart

Issue 548253003: First end-to-end capability in analyzer2dart. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Updated cf. comments. Created 6 years, 3 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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 part of dart_backend; 5 part of dart_backend;
6 6
7 typedef bool IsSafeToRemoveTypeDeclarations( 7 typedef bool IsSafeToRemoveTypeDeclarations(
8 Map<ClassElement, Iterable<Element>> classMembers); 8 Map<ClassElement, Iterable<Element>> classMembers);
9 typedef void ElementCallback<E>(E element); 9 typedef void ElementCallback<E>(E element);
10 typedef void ElementPostProcessFunction( 10 typedef void ElementPostProcessFunction(
11 AstElement element, ElementAst elementAst, 11 AstElement element, ElementAst elementAst,
12 ElementCallback<TypedefElement> typedefCallback, 12 ElementCallback<TypedefElement> typedefCallback,
13 ElementCallback<ClassElement> classCallback); 13 ElementCallback<ClassElement> classCallback);
14 typedef ElementAst ComputeElementAstFunction(AstElement element); 14 typedef ElementAst ComputeElementAstFunction(AstElement element);
15 typedef bool ElementFilter(Element element); 15 typedef bool ElementFilter(Element element);
16 typedef List<Element> ElementSorter(Iterable<Element> elements);
16 17
17 /// Output engine for dart2dart that is shared between the dart2js and the 18 /// Output engine for dart2dart that is shared between the dart2js and the
18 /// analyzer implementations of dart2dart. 19 /// analyzer implementations of dart2dart.
19 class DartOutputter { 20 class DartOutputter {
20 final DiagnosticListener listener; 21 final DiagnosticListener listener;
21 final CompilerOutputProvider outputProvider; 22 final CompilerOutputProvider outputProvider;
22 final bool forceStripTypes; 23 final bool forceStripTypes;
23 24
24 // TODO(antonm): make available from command-line options. 25 // TODO(antonm): make available from command-line options.
25 final bool outputAst = false; 26 final bool outputAst = false;
26 final bool enableMinification; 27 final bool enableMinification;
27 28
28 /// If `true`, libraries are generated into separate files. 29 /// If `true`, libraries are generated into separate files.
29 final bool multiFile; 30 final bool multiFile;
30 31
31 /// Internal structures accessible for tests and logging. 32 /// Internal structures accessible for tests and logging.
32 // TODO(johnniwinther): Clean this up. 33 // TODO(johnniwinther): Clean this up.
33 PlaceholderRenamer renamer; 34 PlaceholderRenamer renamer;
34 MainOutputGenerator output; 35 MainOutputGenerator output;
35 LibraryInfo libraryInfo; 36 LibraryInfo libraryInfo;
36 ElementInfo elementInfo; 37 ElementInfo elementInfo;
37 38
38 // TODO(johnniwinther): Support recompilation. 39 // TODO(johnniwinther): Support recompilation.
39 DartOutputter(this.listener, this.outputProvider, 40 DartOutputter(this.listener, this.outputProvider,
40 {bool this.forceStripTypes: false, 41 {bool this.forceStripTypes: false,
41 bool this.enableMinification: false, 42 bool this.enableMinification: false,
42 bool this.multiFile: false}); 43 bool this.multiFile: false});
43 44
44 String assembleProgram({ 45 String assembleProgram({
45 MirrorRenamer mirrorRenamer, 46 MirrorRenamer mirrorRenamer: const MirrorRenamer(),
46 Iterable<LibraryElement> libraries, 47 Iterable<LibraryElement> libraries,
47 Iterable<Element> instantiatedClasses, 48 Iterable<Element> instantiatedClasses,
48 Iterable<Element> resolvedElements, 49 Iterable<Element> resolvedElements,
49 Iterable<ClassElement> usedTypeLiterals, 50 Iterable<ClassElement> usedTypeLiterals: const <ClassElement>[],
50 LibraryElement mainLibrary,
51 FunctionElement mainFunction, 51 FunctionElement mainFunction,
52 Uri outputUri, 52 Uri outputUri,
53 ElementPostProcessFunction postProcessElementAst, 53 ElementPostProcessFunction postProcessElementAst,
54 ComputeElementAstFunction computeElementAst, 54 ComputeElementAstFunction computeElementAst,
55 ElementFilter shouldOutput, 55 ElementFilter shouldOutput,
56 IsSafeToRemoveTypeDeclarations isSafeToRemoveTypeDeclarations}) { 56 IsSafeToRemoveTypeDeclarations isSafeToRemoveTypeDeclarations,
57 ElementSorter sortElements}) {
58
59 assert(invariant(NO_LOCATION_SPANNABLE, libraries != null,
60 message: "'libraries' must be non-null."));
61 assert(invariant(NO_LOCATION_SPANNABLE, instantiatedClasses != null,
62 message: "'instantiatedClasses' must be non-null."));
63 assert(invariant(NO_LOCATION_SPANNABLE, resolvedElements != null,
64 message: "'resolvedElements' must be non-null."));
65 assert(invariant(NO_LOCATION_SPANNABLE, mainFunction != null,
66 message: "'mainFunction' must be non-null."));
67 assert(invariant(NO_LOCATION_SPANNABLE, computeElementAst != null,
68 message: "'computeElementAst' must be non-null."));
69 assert(invariant(NO_LOCATION_SPANNABLE, shouldOutput != null,
70 message: "'shouldOutput' must be non-null."));
71 assert(invariant(NO_LOCATION_SPANNABLE,
72 isSafeToRemoveTypeDeclarations != null,
73 message: "'isSafeToRemoveTypeDeclarations' must be non-null."));
74
75 if (sortElements == null) {
76 // Ensure deterministic output order.
77 sortElements = (Iterable<Element> elements) {
78 List<Element> list = elements.toList();
79 list.sort((Element a, Element b) => a.name.compareTo(b.name));
80 return list;
81 };
82 }
57 83
58 libraryInfo = LibraryInfo.processLibraries(libraries, resolvedElements); 84 libraryInfo = LibraryInfo.processLibraries(libraries, resolvedElements);
59 85
60 elementInfo = ElementInfoProcessor.createElementInfo( 86 elementInfo = ElementInfoProcessor.createElementInfo(
61 instantiatedClasses, 87 instantiatedClasses,
62 resolvedElements, 88 resolvedElements,
63 usedTypeLiterals, 89 usedTypeLiterals,
64 postProcessElementAst: postProcessElementAst, 90 postProcessElementAst: postProcessElementAst,
65 parseElementAst: computeElementAst, 91 parseElementAst: computeElementAst,
66 shouldOutput: shouldOutput); 92 shouldOutput: shouldOutput,
93 sortElements: sortElements);
67 94
68 PlaceholderCollector collector = collectPlaceholders( 95 PlaceholderCollector collector = collectPlaceholders(
69 listener, 96 listener,
70 mirrorRenamer, 97 mirrorRenamer,
71 mainFunction, 98 mainFunction,
72 libraryInfo, 99 libraryInfo,
73 elementInfo); 100 elementInfo);
74 101
75 renamer = createRenamer( 102 renamer = createRenamer(
76 collector, 103 collector,
77 libraryInfo, 104 libraryInfo,
78 elementInfo, 105 elementInfo,
79 enableMinification: enableMinification, 106 enableMinification: enableMinification,
80 forceStripTypes: forceStripTypes, 107 forceStripTypes: forceStripTypes,
81 isSafeToRemoveTypeDeclarations: isSafeToRemoveTypeDeclarations); 108 isSafeToRemoveTypeDeclarations: isSafeToRemoveTypeDeclarations);
82 109
83 String assembledCode; 110 String assembledCode;
84 if (outputAst) { 111 if (outputAst) {
85 assembledCode = astOutput(listener, elementInfo); 112 assembledCode = astOutput(listener, elementInfo);
86 } else { 113 } else {
87 output = new MainOutputGenerator(); 114 output = new MainOutputGenerator();
88 assembledCode = output.generateCode( 115 assembledCode = output.generateCode(
89 libraryInfo, 116 libraryInfo,
90 elementInfo, 117 elementInfo,
91 collector, 118 collector,
92 renamer, 119 renamer,
93 mainLibrary, 120 mainFunction,
94 outputUri, 121 outputUri,
95 outputProvider, 122 outputProvider,
96 mirrorRenamer, 123 mirrorRenamer,
97 multiFile: multiFile, 124 multiFile: multiFile,
98 forceStripTypes: forceStripTypes, 125 forceStripTypes: forceStripTypes,
99 enableMinification: enableMinification); 126 enableMinification: enableMinification);
100 } 127 }
101 return assembledCode; 128 return assembledCode;
102 } 129 }
103 130
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
140 167
141 PlaceholderRenamer placeholderRenamer = new PlaceholderRenamer( 168 PlaceholderRenamer placeholderRenamer = new PlaceholderRenamer(
142 libraryInfo.fixedMemberNames, libraryInfo.reexportingLibraries, 169 libraryInfo.fixedMemberNames, libraryInfo.reexportingLibraries,
143 cutDeclarationTypes: shouldCutDeclarationTypes, 170 cutDeclarationTypes: shouldCutDeclarationTypes,
144 enableMinification: enableMinification); 171 enableMinification: enableMinification);
145 172
146 placeholderRenamer.computeRenames(collector); 173 placeholderRenamer.computeRenames(collector);
147 return placeholderRenamer; 174 return placeholderRenamer;
148 } 175 }
149 176
150 static String astOutput(Compiler compiler, 177 static String astOutput(DiagnosticListener listener,
151 ElementInfo elementInfo) { 178 ElementInfo elementInfo) {
152 // TODO(antonm): Ideally XML should be a separate backend. 179 // TODO(antonm): Ideally XML should be a separate backend.
153 // TODO(antonm): obey renames and minification, at least as an option. 180 // TODO(antonm): obey renames and minification, at least as an option.
154 StringBuffer sb = new StringBuffer(); 181 StringBuffer sb = new StringBuffer();
155 outputElement(element) { 182 outputElement(element) {
156 sb.write(element.parseNode(compiler).toDebugString()); 183 sb.write(element.parseNode(listener).toDebugString());
157 } 184 }
158 185
159 // Emit XML for AST instead of the program. 186 // Emit XML for AST instead of the program.
160 for (Element topLevel in elementInfo.topLevelElements) { 187 for (Element topLevel in elementInfo.topLevelElements) {
161 if (topLevel.isClass && 188 if (topLevel.isClass &&
162 !elementInfo.emitNoMembersFor.contains(topLevel)) { 189 !elementInfo.emitNoMembersFor.contains(topLevel)) {
163 // TODO(antonm): add some class info. 190 // TODO(antonm): add some class info.
164 elementInfo.classMembers[topLevel].forEach(outputElement); 191 elementInfo.classMembers[topLevel].forEach(outputElement);
165 } else { 192 } else {
166 outputElement(topLevel); 193 outputElement(topLevel);
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 {this.postProcessElementAst, 308 {this.postProcessElementAst,
282 this.parseElementAst, 309 this.parseElementAst,
283 this.shouldOutput}); 310 this.shouldOutput});
284 311
285 static ElementInfo createElementInfo( 312 static ElementInfo createElementInfo(
286 Iterable<ClassElement> instantiatedClasses, 313 Iterable<ClassElement> instantiatedClasses,
287 Iterable<AstElement> resolvedElements, 314 Iterable<AstElement> resolvedElements,
288 Iterable<ClassElement> usedTypeLiterals, 315 Iterable<ClassElement> usedTypeLiterals,
289 {ElementPostProcessFunction postProcessElementAst, 316 {ElementPostProcessFunction postProcessElementAst,
290 ComputeElementAstFunction parseElementAst, 317 ComputeElementAstFunction parseElementAst,
291 ElementFilter shouldOutput}) { 318 ElementFilter shouldOutput,
319 ElementSorter sortElements}) {
292 ElementInfoProcessor processor = new ElementInfoProcessor( 320 ElementInfoProcessor processor = new ElementInfoProcessor(
293 postProcessElementAst: postProcessElementAst, 321 postProcessElementAst: postProcessElementAst,
294 parseElementAst: parseElementAst, 322 parseElementAst: parseElementAst,
295 shouldOutput: shouldOutput); 323 shouldOutput: shouldOutput);
296 return processor.process( 324 return processor.process(
297 instantiatedClasses, resolvedElements, usedTypeLiterals); 325 instantiatedClasses, resolvedElements, usedTypeLiterals,
326 sortElements: sortElements);
298 } 327 }
299 328
300 ElementInfo process(Iterable<ClassElement> instantiatedClasses, 329 ElementInfo process(Iterable<ClassElement> instantiatedClasses,
301 Iterable<AstElement> resolvedElements, 330 Iterable<AstElement> resolvedElements,
302 Iterable<ClassElement> usedTypeLiterals) { 331 Iterable<ClassElement> usedTypeLiterals,
332 {ElementSorter sortElements}) {
303 // Build all top level elements to emit and necessary class members. 333 // Build all top level elements to emit and necessary class members.
304 instantiatedClasses.where(shouldOutput).forEach(addClass); 334 instantiatedClasses.where(shouldOutput).forEach(addClass);
305 resolvedElements.where(shouldOutput).forEach(addMember); 335 resolvedElements.where(shouldOutput).forEach(addMember);
306 usedTypeLiterals.forEach((ClassElement element) { 336 usedTypeLiterals.forEach((ClassElement element) {
307 if (shouldOutput(element)) { 337 if (shouldOutput(element)) {
308 if (!topLevelElements.contains(element)) { 338 if (!topLevelElements.contains(element)) {
309 // The class is only referenced by type literals. 339 // The class is only referenced by type literals.
310 emitNoMembersFor.add(element); 340 emitNoMembersFor.add(element);
311 } 341 }
312 addClass(element); 342 addClass(element);
313 } 343 }
314 }); 344 });
315 345
316 // Sort elements. 346 // Sort elements.
317 List<Element> sortedTopLevels = sortElements(topLevelElements); 347 List<Element> sortedTopLevels = sortElements(topLevelElements);
318 Map<ClassElement, List<Element>> sortedClassMembers = 348 Map<ClassElement, List<Element>> sortedClassMembers =
319 new Map<ClassElement, List<Element>>(); 349 new Map<ClassElement, List<Element>>();
320 classMembers.forEach((classElement, members) { 350 classMembers.forEach((classElement, members) {
321 sortedClassMembers[classElement] = sortElements(members); 351 sortedClassMembers[classElement] = sortElements(members);
322 }); 352 });
323 353
324 return new ElementInfo( 354 return new ElementInfo(
325 elementAsts, sortedTopLevels, sortedClassMembers, emitNoMembersFor); 355 elementAsts, sortedTopLevels, sortedClassMembers, emitNoMembersFor);
326 } 356 }
327 357
328 void processElement(Element element, ElementAst elementAst) { 358 void processElement(Element element, ElementAst elementAst) {
329 postProcessElementAst(element, elementAst, 359 if (postProcessElementAst != null) {
330 newTypedefElementCallback, 360 postProcessElementAst(element, elementAst,
331 newClassElementCallback); 361 newTypedefElementCallback,
362 newClassElementCallback);
363 }
332 elementAsts[element] = elementAst; 364 elementAsts[element] = elementAst;
333 } 365 }
334 366
335 void addTopLevel(AstElement element, ElementAst elementAst) { 367 void addTopLevel(AstElement element, ElementAst elementAst) {
336 if (topLevelElements.contains(element)) return; 368 if (topLevelElements.contains(element)) return;
337 topLevelElements.add(element); 369 topLevelElements.add(element);
338 processElement(element, elementAst); 370 processElement(element, elementAst);
339 } 371 }
340 372
341 void addClass(ClassElement classElement) { 373 void addClass(ClassElement classElement) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 class MainOutputGenerator { 408 class MainOutputGenerator {
377 final Map<ClassNode, List<Node>> memberNodes = 409 final Map<ClassNode, List<Node>> memberNodes =
378 new Map<ClassNode, List<Node>>(); 410 new Map<ClassNode, List<Node>>();
379 final List<Node> topLevelNodes = <Node>[]; 411 final List<Node> topLevelNodes = <Node>[];
380 412
381 String generateCode( 413 String generateCode(
382 LibraryInfo libraryInfo, 414 LibraryInfo libraryInfo,
383 ElementInfo elementInfo, 415 ElementInfo elementInfo,
384 PlaceholderCollector collector, 416 PlaceholderCollector collector,
385 PlaceholderRenamer placeholderRenamer, 417 PlaceholderRenamer placeholderRenamer,
386 LibraryElement mainApp, 418 FunctionElement mainFunction,
387 Uri outputUri, 419 Uri outputUri,
388 CompilerOutputProvider outputProvider, 420 CompilerOutputProvider outputProvider,
389 MirrorRenamer mirrorRenamer, 421 MirrorRenamer mirrorRenamer,
390 {bool multiFile: false, 422 {bool multiFile: false,
391 bool forceStripTypes: false, 423 bool forceStripTypes: false,
392 bool enableMinification: false}) { 424 bool enableMinification: false}) {
393 for (Element element in elementInfo.topLevelElements) { 425 for (Element element in elementInfo.topLevelElements) {
394 topLevelNodes.add(elementInfo.elementAsts[element].ast); 426 topLevelNodes.add(elementInfo.elementAsts[element].ast);
395 if (element.isClass && !element.isMixinApplication) { 427 if (element.isClass && !element.isMixinApplication) {
396 final members = <Node>[]; 428 final members = <Node>[];
(...skipping 21 matching lines...) Expand all
418 if (multiFile) { 450 if (multiFile) {
419 // TODO(sigurdm): Factor handling of library-paths out from emitting. 451 // TODO(sigurdm): Factor handling of library-paths out from emitting.
420 String mainName = outputUri.pathSegments.last; 452 String mainName = outputUri.pathSegments.last;
421 String mainBaseName = mainName.endsWith(".dart") 453 String mainBaseName = mainName.endsWith(".dart")
422 ? mainName.substring(0, mainName.length - 5) 454 ? mainName.substring(0, mainName.length - 5)
423 : mainName; 455 : mainName;
424 // Map each library to a path based on the uri of the original 456 // Map each library to a path based on the uri of the original
425 // library and [compiler.outputUri]. 457 // library and [compiler.outputUri].
426 Set<String> usedLibraryPaths = new Set<String>(); 458 Set<String> usedLibraryPaths = new Set<String>();
427 for (LibraryElement library in libraryInfo.userLibraries) { 459 for (LibraryElement library in libraryInfo.userLibraries) {
428 if (library == mainApp) { 460 if (library == mainFunction.library) {
429 outputPaths[library] = mainBaseName; 461 outputPaths[library] = mainBaseName;
430 } else { 462 } else {
431 List<String> names = 463 List<String> names =
432 library.canonicalUri.pathSegments.last.split("."); 464 library.canonicalUri.pathSegments.last.split(".");
433 if (names.last == "dart") { 465 if (names.last == "dart") {
434 names = names.sublist(0, names.length - 1); 466 names = names.sublist(0, names.length - 1);
435 } 467 }
436 outputPaths[library] = 468 outputPaths[library] =
437 "$mainBaseName.${makeUnique(names.join("."), usedLibraryPaths)}"; 469 "$mainBaseName.${makeUnique(names.join("."), usedLibraryPaths)}";
438 } 470 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 for(LibraryElement outputLibrary in libraryInfo.userLibraries) { 523 for(LibraryElement outputLibrary in libraryInfo.userLibraries) {
492 // TODO(sigurdm): Make the unparser output directly into the buffer 524 // TODO(sigurdm): Make the unparser output directly into the buffer
493 // instead of caching in `.result`. 525 // instead of caching in `.result`.
494 String code = unparsers[outputLibrary].result; 526 String code = unparsers[outputLibrary].result;
495 totalSize += code.length; 527 totalSize += code.length;
496 outputProvider(outputPaths[outputLibrary], "dart") 528 outputProvider(outputPaths[outputLibrary], "dart")
497 ..add(code) 529 ..add(code)
498 ..close(); 530 ..close();
499 } 531 }
500 // TODO(sigurdm): We should get rid of compiler.assembledCode. 532 // TODO(sigurdm): We should get rid of compiler.assembledCode.
501 assembledCode = unparsers[mainApp].result; 533 assembledCode = unparsers[mainFunction.library].result;
502 } else { 534 } else {
503 assembledCode = mainUnparser.result; 535 assembledCode = mainUnparser.result;
504 outputProvider("", "dart") 536 outputProvider("", "dart")
505 ..add(assembledCode) 537 ..add(assembledCode)
506 ..close(); 538 ..close();
507 539
508 totalSize = assembledCode.length; 540 totalSize = assembledCode.length;
509 } 541 }
510 542
511 return assembledCode; 543 return assembledCode;
512 } 544 }
513 } 545 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698