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

Side by Side Diff: pkg/compiler/lib/src/dart_backend/outputter.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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
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,
12 ElementAst elementAst,
12 ElementCallback<TypedefElement> typedefCallback, 13 ElementCallback<TypedefElement> typedefCallback,
13 ElementCallback<ClassElement> classCallback); 14 ElementCallback<ClassElement> classCallback);
14 typedef ElementAst ComputeElementAstFunction(AstElement element); 15 typedef ElementAst ComputeElementAstFunction(AstElement element);
15 typedef bool ElementFilter(Element element); 16 typedef bool ElementFilter(Element element);
16 typedef List<Element> ElementSorter(Iterable<Element> elements); 17 typedef List<Element> ElementSorter(Iterable<Element> elements);
17 18
18 /// Output engine for dart2dart that is shared between the dart2js and the 19 /// Output engine for dart2dart that is shared between the dart2js and the
19 /// analyzer implementations of dart2dart. 20 /// analyzer implementations of dart2dart.
20 class DartOutputter { 21 class DartOutputter {
21 final DiagnosticReporter reporter; 22 final DiagnosticReporter reporter;
22 final CompilerOutputProvider outputProvider; 23 final CompilerOutputProvider outputProvider;
23 final bool forceStripTypes; 24 final bool forceStripTypes;
24 25
25 // TODO(antonm): make available from command-line options. 26 // TODO(antonm): make available from command-line options.
26 final bool outputAst = false; 27 final bool outputAst = false;
27 final bool enableMinification; 28 final bool enableMinification;
28 29
29 /// If `true`, libraries are generated into separate files. 30 /// If `true`, libraries are generated into separate files.
30 final bool multiFile; 31 final bool multiFile;
31 32
32 /// Internal structures accessible for tests and logging. 33 /// Internal structures accessible for tests and logging.
33 // TODO(johnniwinther): Clean this up. 34 // TODO(johnniwinther): Clean this up.
34 PlaceholderRenamer renamer; 35 PlaceholderRenamer renamer;
35 MainOutputGenerator output; 36 MainOutputGenerator output;
36 LibraryInfo libraryInfo; 37 LibraryInfo libraryInfo;
37 ElementInfo elementInfo; 38 ElementInfo elementInfo;
38 39
39 // TODO(johnniwinther): Support recompilation. 40 // TODO(johnniwinther): Support recompilation.
40 DartOutputter(this.reporter, this.outputProvider, 41 DartOutputter(this.reporter, this.outputProvider,
41 {bool this.forceStripTypes: false, 42 {bool this.forceStripTypes: false,
42 bool this.enableMinification: false, 43 bool this.enableMinification: false,
43 bool this.multiFile: false}); 44 bool this.multiFile: false});
44 45
45 /// Generate Dart code for the program starting at [mainFunction]. 46 /// Generate Dart code for the program starting at [mainFunction].
46 /// 47 ///
47 /// [libraries] is the set of all libraries (user/package/sdk) that are 48 /// [libraries] is the set of all libraries (user/package/sdk) that are
48 /// referenced in the program. 49 /// referenced in the program.
49 /// 50 ///
50 /// [instantiatedClasses] is the set of classes that are potentially 51 /// [instantiatedClasses] is the set of classes that are potentially
51 /// instantiated in the program. 52 /// instantiated in the program.
52 /// 53 ///
53 /// [resolvedElements] is the set of methods, constructors, and fields that 54 /// [resolvedElements] is the set of methods, constructors, and fields that
54 /// are potentially accessed/called in the program. 55 /// are potentially accessed/called in the program.
55 /// 56 ///
56 /// The [sortElements] function is used to sort [instantiatedClasses] and 57 /// The [sortElements] function is used to sort [instantiatedClasses] and
57 /// [resolvedElements] in the generated output. 58 /// [resolvedElements] in the generated output.
58 /// 59 ///
59 /// Returns the total size of the generated code. 60 /// Returns the total size of the generated code.
60 int assembleProgram({ 61 int assembleProgram(
61 MirrorRenamer mirrorRenamer: const MirrorRenamer(), 62 {MirrorRenamer mirrorRenamer: const MirrorRenamer(),
62 Iterable<LibraryElement> libraries, 63 Iterable<LibraryElement> libraries,
63 Iterable<Element> instantiatedClasses, 64 Iterable<Element> instantiatedClasses,
64 Iterable<Element> resolvedElements, 65 Iterable<Element> resolvedElements,
65 Iterable<ClassElement> usedTypeLiterals: const <ClassElement>[], 66 Iterable<ClassElement> usedTypeLiterals: const <ClassElement>[],
66 FunctionElement mainFunction, 67 FunctionElement mainFunction,
67 Uri outputUri, 68 Uri outputUri,
68 ElementPostProcessFunction postProcessElementAst, 69 ElementPostProcessFunction postProcessElementAst,
69 ComputeElementAstFunction computeElementAst, 70 ComputeElementAstFunction computeElementAst,
70 ElementFilter shouldOutput, 71 ElementFilter shouldOutput,
71 IsSafeToRemoveTypeDeclarations isSafeToRemoveTypeDeclarations, 72 IsSafeToRemoveTypeDeclarations isSafeToRemoveTypeDeclarations,
72 ElementSorter sortElements}) { 73 ElementSorter sortElements}) {
73
74 assert(invariant(NO_LOCATION_SPANNABLE, libraries != null, 74 assert(invariant(NO_LOCATION_SPANNABLE, libraries != null,
75 message: "'libraries' must be non-null.")); 75 message: "'libraries' must be non-null."));
76 assert(invariant(NO_LOCATION_SPANNABLE, instantiatedClasses != null, 76 assert(invariant(NO_LOCATION_SPANNABLE, instantiatedClasses != null,
77 message: "'instantiatedClasses' must be non-null.")); 77 message: "'instantiatedClasses' must be non-null."));
78 assert(invariant(NO_LOCATION_SPANNABLE, resolvedElements != null, 78 assert(invariant(NO_LOCATION_SPANNABLE, resolvedElements != null,
79 message: "'resolvedElements' must be non-null.")); 79 message: "'resolvedElements' must be non-null."));
80 assert(invariant(NO_LOCATION_SPANNABLE, mainFunction != null, 80 assert(invariant(NO_LOCATION_SPANNABLE, mainFunction != null,
81 message: "'mainFunction' must be non-null.")); 81 message: "'mainFunction' must be non-null."));
82 assert(invariant(NO_LOCATION_SPANNABLE, computeElementAst != null, 82 assert(invariant(NO_LOCATION_SPANNABLE, computeElementAst != null,
83 message: "'computeElementAst' must be non-null.")); 83 message: "'computeElementAst' must be non-null."));
84 assert(invariant(NO_LOCATION_SPANNABLE, shouldOutput != null, 84 assert(invariant(NO_LOCATION_SPANNABLE, shouldOutput != null,
85 message: "'shouldOutput' must be non-null.")); 85 message: "'shouldOutput' must be non-null."));
86 assert(invariant(NO_LOCATION_SPANNABLE, 86 assert(invariant(
87 isSafeToRemoveTypeDeclarations != null, 87 NO_LOCATION_SPANNABLE, isSafeToRemoveTypeDeclarations != null,
88 message: "'isSafeToRemoveTypeDeclarations' must be non-null.")); 88 message: "'isSafeToRemoveTypeDeclarations' must be non-null."));
89 89
90 if (sortElements == null) { 90 if (sortElements == null) {
91 // Ensure deterministic output order. 91 // Ensure deterministic output order.
92 sortElements = (Iterable<Element> elements) { 92 sortElements = (Iterable<Element> elements) {
93 List<Element> list = elements.toList(); 93 List<Element> list = elements.toList();
94 list.sort((Element a, Element b) => a.name.compareTo(b.name)); 94 list.sort((Element a, Element b) => a.name.compareTo(b.name));
95 return list; 95 return list;
96 }; 96 };
97 } 97 }
98 98
99 libraryInfo = LibraryInfo.processLibraries( 99 libraryInfo =
100 reporter, libraries, resolvedElements); 100 LibraryInfo.processLibraries(reporter, libraries, resolvedElements);
101 101
102 elementInfo = ElementInfoProcessor.createElementInfo( 102 elementInfo = ElementInfoProcessor.createElementInfo(
103 instantiatedClasses, 103 instantiatedClasses, resolvedElements, usedTypeLiterals,
104 resolvedElements,
105 usedTypeLiterals,
106 postProcessElementAst: postProcessElementAst, 104 postProcessElementAst: postProcessElementAst,
107 parseElementAst: computeElementAst, 105 parseElementAst: computeElementAst,
108 shouldOutput: shouldOutput, 106 shouldOutput: shouldOutput,
109 sortElements: sortElements); 107 sortElements: sortElements);
110 108
111 PlaceholderCollector collector = collectPlaceholders( 109 PlaceholderCollector collector = collectPlaceholders(
112 reporter, 110 reporter, mirrorRenamer, mainFunction, libraryInfo, elementInfo);
113 mirrorRenamer,
114 mainFunction,
115 libraryInfo,
116 elementInfo);
117 111
118 renamer = createRenamer( 112 renamer = createRenamer(collector, libraryInfo, elementInfo,
119 collector,
120 libraryInfo,
121 elementInfo,
122 enableMinification: enableMinification, 113 enableMinification: enableMinification,
123 forceStripTypes: forceStripTypes, 114 forceStripTypes: forceStripTypes,
124 isSafeToRemoveTypeDeclarations: isSafeToRemoveTypeDeclarations); 115 isSafeToRemoveTypeDeclarations: isSafeToRemoveTypeDeclarations);
125 116
126 if (outputAst) { 117 if (outputAst) {
127 String code = astOutput(reporter, elementInfo); 118 String code = astOutput(reporter, elementInfo);
128 outputProvider("", "dart") 119 outputProvider("", "dart")
129 ..add(code) 120 ..add(code)
130 ..close(); 121 ..close();
131 return code.length; 122 return code.length;
132 } else { 123 } else {
133 output = new MainOutputGenerator(); 124 output = new MainOutputGenerator();
134 return output.generateCode( 125 return output.generateCode(libraryInfo, elementInfo, collector, renamer,
135 libraryInfo, 126 mainFunction, outputUri, outputProvider, mirrorRenamer,
136 elementInfo,
137 collector,
138 renamer,
139 mainFunction,
140 outputUri,
141 outputProvider,
142 mirrorRenamer,
143 multiFile: multiFile, 127 multiFile: multiFile,
144 forceStripTypes: forceStripTypes, 128 forceStripTypes: forceStripTypes,
145 enableMinification: enableMinification); 129 enableMinification: enableMinification);
146 } 130 }
147 } 131 }
148 132
149 static PlaceholderCollector collectPlaceholders( 133 static PlaceholderCollector collectPlaceholders(
150 DiagnosticReporter reporter, 134 DiagnosticReporter reporter,
151 MirrorRenamer mirrorRenamer, 135 MirrorRenamer mirrorRenamer,
152 FunctionElement mainFunction, 136 FunctionElement mainFunction,
(...skipping 11 matching lines...) Expand all
164 collector.collect(element); 148 collector.collect(element);
165 149
166 if (element.isClass && !element.isEnumClass) { 150 if (element.isClass && !element.isEnumClass) {
167 elementInfo.classMembers[element].forEach(makePlaceholders); 151 elementInfo.classMembers[element].forEach(makePlaceholders);
168 } 152 }
169 } 153 }
170 elementInfo.topLevelElements.forEach(makePlaceholders); 154 elementInfo.topLevelElements.forEach(makePlaceholders);
171 return collector; 155 return collector;
172 } 156 }
173 157
174 static PlaceholderRenamer createRenamer( 158 static PlaceholderRenamer createRenamer(PlaceholderCollector collector,
175 PlaceholderCollector collector, 159 LibraryInfo libraryInfo, ElementInfo elementInfo,
176 LibraryInfo libraryInfo,
177 ElementInfo elementInfo,
178 {bool enableMinification: false, 160 {bool enableMinification: false,
179 bool forceStripTypes: false, 161 bool forceStripTypes: false,
180 isSafeToRemoveTypeDeclarations}) { 162 isSafeToRemoveTypeDeclarations}) {
181 // Create renames. 163 // Create renames.
182 bool shouldCutDeclarationTypes = forceStripTypes 164 bool shouldCutDeclarationTypes = forceStripTypes ||
183 || (enableMinification 165 (enableMinification &&
184 && isSafeToRemoveTypeDeclarations(elementInfo.classMembers)); 166 isSafeToRemoveTypeDeclarations(elementInfo.classMembers));
185 167
186 PlaceholderRenamer placeholderRenamer = new PlaceholderRenamer( 168 PlaceholderRenamer placeholderRenamer = new PlaceholderRenamer(
187 libraryInfo.fixedDynamicNames, 169 libraryInfo.fixedDynamicNames,
188 libraryInfo.fixedStaticNames, 170 libraryInfo.fixedStaticNames,
189 libraryInfo.reexportingLibraries, 171 libraryInfo.reexportingLibraries,
190 cutDeclarationTypes: shouldCutDeclarationTypes, 172 cutDeclarationTypes: shouldCutDeclarationTypes,
191 enableMinification: enableMinification); 173 enableMinification: enableMinification);
192 174
193 placeholderRenamer.computeRenames(collector); 175 placeholderRenamer.computeRenames(collector);
194 return placeholderRenamer; 176 return placeholderRenamer;
195 } 177 }
196 178
197 static String astOutput(DiagnosticReporter reporter, 179 static String astOutput(
198 ElementInfo elementInfo) { 180 DiagnosticReporter reporter, ElementInfo elementInfo) {
199 // TODO(antonm): Ideally XML should be a separate backend. 181 // TODO(antonm): Ideally XML should be a separate backend.
200 // TODO(antonm): obey renames and minification, at least as an option. 182 // TODO(antonm): obey renames and minification, at least as an option.
201 StringBuffer sb = new StringBuffer(); 183 StringBuffer sb = new StringBuffer();
202 outputElement(element) { 184 outputElement(element) {
203 sb.write(element.parseNode(reporter).toDebugString()); 185 sb.write(element.parseNode(reporter).toDebugString());
204 } 186 }
205 187
206 // Emit XML for AST instead of the program. 188 // Emit XML for AST instead of the program.
207 for (Element topLevel in elementInfo.topLevelElements) { 189 for (Element topLevel in elementInfo.topLevelElements) {
208 if (topLevel.isClass && 190 if (topLevel.isClass &&
209 !elementInfo.emitNoMembersFor.contains(topLevel)) { 191 !elementInfo.emitNoMembersFor.contains(topLevel)) {
210 // TODO(antonm): add some class info. 192 // TODO(antonm): add some class info.
211 elementInfo.classMembers[topLevel].forEach(outputElement); 193 elementInfo.classMembers[topLevel].forEach(outputElement);
212 } else { 194 } else {
213 outputElement(topLevel); 195 outputElement(topLevel);
214 } 196 }
215 } 197 }
216 return '<Program>\n$sb</Program>\n'; 198 return '<Program>\n$sb</Program>\n';
217 } 199 }
218 } 200 }
219 201
220 class LibraryInfo { 202 class LibraryInfo {
221 final Set<String> fixedStaticNames; 203 final Set<String> fixedStaticNames;
222 final Set<String> fixedDynamicNames; 204 final Set<String> fixedDynamicNames;
223 final Map<Element, LibraryElement> reexportingLibraries; 205 final Map<Element, LibraryElement> reexportingLibraries;
224 final List<LibraryElement> userLibraries; 206 final List<LibraryElement> userLibraries;
225 207
226 LibraryInfo(this.fixedStaticNames, 208 LibraryInfo(this.fixedStaticNames, this.fixedDynamicNames,
227 this.fixedDynamicNames, 209 this.reexportingLibraries, this.userLibraries);
228 this.reexportingLibraries,
229 this.userLibraries);
230 210
231 static LibraryInfo processLibraries( 211 static LibraryInfo processLibraries(
232 DiagnosticReporter reporter, 212 DiagnosticReporter reporter,
233 Iterable<LibraryElement> libraries, 213 Iterable<LibraryElement> libraries,
234 Iterable<AstElement> resolvedElements) { 214 Iterable<AstElement> resolvedElements) {
235 Set<String> fixedStaticNames = new Set<String>(); 215 Set<String> fixedStaticNames = new Set<String>();
236 Set<String> fixedDynamicNames = new Set<String>(); 216 Set<String> fixedDynamicNames = new Set<String>();
237 Map<Element, LibraryElement> reexportingLibraries = 217 Map<Element, LibraryElement> reexportingLibraries =
238 <Element, LibraryElement>{}; 218 <Element, LibraryElement>{};
239 List<LibraryElement> userLibraries = <LibraryElement>[]; 219 List<LibraryElement> userLibraries = <LibraryElement>[];
240 // Conservatively traverse all platform libraries and collect member names. 220 // Conservatively traverse all platform libraries and collect member names.
241 // TODO(antonm): ideally we should only collect names of used members, 221 // TODO(antonm): ideally we should only collect names of used members,
242 // however as of today there are problems with names of some core library 222 // however as of today there are problems with names of some core library
243 // interfaces, most probably for interfaces of literals. 223 // interfaces, most probably for interfaces of literals.
244 224
245 for (LibraryElement library in libraries) { 225 for (LibraryElement library in libraries) {
246 if (!library.isPlatformLibrary) { 226 if (!library.isPlatformLibrary) {
247 userLibraries.add(library); 227 userLibraries.add(library);
248 continue; 228 continue;
(...skipping 12 matching lines...) Expand all
261 }); 241 });
262 } 242 }
263 // Even class names are added due to a delicate problem we have: 243 // Even class names are added due to a delicate problem we have:
264 // if one imports dart:core with a prefix, we cannot tell prefix.name 244 // if one imports dart:core with a prefix, we cannot tell prefix.name
265 // from dynamic invocation (alas!). So we'd better err on preserving 245 // from dynamic invocation (alas!). So we'd better err on preserving
266 // those names. 246 // those names.
267 fixedStaticNames.add(element.name); 247 fixedStaticNames.add(element.name);
268 }); 248 });
269 249
270 library.forEachExport((Element export) { 250 library.forEachExport((Element export) {
271 if (!library.isInternalLibrary && 251 if (!library.isInternalLibrary && export.library.isInternalLibrary) {
272 export.library.isInternalLibrary) {
273 // If an element of an internal library is reexported by a platform 252 // If an element of an internal library is reexported by a platform
274 // library, we have to import the reexporting library instead of the 253 // library, we have to import the reexporting library instead of the
275 // internal library, because the internal library is an 254 // internal library, because the internal library is an
276 // implementation detail of dart2js. 255 // implementation detail of dart2js.
277 reexportingLibraries[export] = library; 256 reexportingLibraries[export] = library;
278 } 257 }
279 }); 258 });
280 } 259 }
281 260
282 // Map to keep track of names of enum classes. Since these cannot be renamed 261 // Map to keep track of names of enum classes. Since these cannot be renamed
(...skipping 10 matching lines...) Expand all
293 } 272 }
294 } 273 }
295 ClassElement cls = element.enclosingClass; 274 ClassElement cls = element.enclosingClass;
296 if (cls != null && cls.isEnumClass) { 275 if (cls != null && cls.isEnumClass) {
297 fixedDynamicNames.add('index'); 276 fixedDynamicNames.add('index');
298 277
299 ClassElement existingEnumClass = 278 ClassElement existingEnumClass =
300 enumClassMap.putIfAbsent(cls.name, () => cls); 279 enumClassMap.putIfAbsent(cls.name, () => cls);
301 if (existingEnumClass != cls) { 280 if (existingEnumClass != cls) {
302 reporter.reportError( 281 reporter.reportError(
303 reporter.createMessage( 282 reporter.createMessage(cls, MessageKind.GENERIC, {
304 cls, 283 'text': "Duplicate enum names are not supported "
305 MessageKind.GENERIC, 284 "in dart2dart."
306 {'text': "Duplicate enum names are not supported " 285 }),
307 "in dart2dart."}), 286 <DiagnosticMessage>[
308 <DiagnosticMessage>[ 287 reporter.createMessage(existingEnumClass, MessageKind.GENERIC, {
309 reporter.createMessage( 288 'text': "This is the other declaration of '${cls.name}'."
310 existingEnumClass, 289 }),
311 MessageKind.GENERIC, 290 ]);
312 {'text': "This is the other declaration of '${cls.name}'."}),
313 ]);
314 } 291 }
315 } 292 }
316 } 293 }
317 294
318 fixedStaticNames.addAll(enumClassMap.keys); 295 fixedStaticNames.addAll(enumClassMap.keys);
319 296
320 // The VM will automatically invoke the call method of objects 297 // The VM will automatically invoke the call method of objects
321 // that are invoked as functions. Make sure to not rename that. 298 // that are invoked as functions. Make sure to not rename that.
322 fixedDynamicNames.add('call'); 299 fixedDynamicNames.add('call');
323 300
324 return new LibraryInfo( 301 return new LibraryInfo(fixedStaticNames, fixedDynamicNames,
325 fixedStaticNames, fixedDynamicNames,
326 reexportingLibraries, userLibraries); 302 reexportingLibraries, userLibraries);
327 } 303 }
328 } 304 }
329 305
330 class ElementInfo { 306 class ElementInfo {
331 final Map<Element, ElementAst> elementAsts; 307 final Map<Element, ElementAst> elementAsts;
332 final Iterable<Element> topLevelElements; 308 final Iterable<Element> topLevelElements;
333 final Map<ClassElement, Iterable<Element>> classMembers; 309 final Map<ClassElement, Iterable<Element>> classMembers;
334 final Iterable<ClassElement> emitNoMembersFor; 310 final Iterable<ClassElement> emitNoMembersFor;
335 311
336 ElementInfo(this.elementAsts, 312 ElementInfo(this.elementAsts, this.topLevelElements, this.classMembers,
337 this.topLevelElements, 313 this.emitNoMembersFor);
338 this.classMembers,
339 this.emitNoMembersFor);
340 } 314 }
341 315
342 class ElementInfoProcessor implements ElementInfo { 316 class ElementInfoProcessor implements ElementInfo {
343 final Map<Element, ElementAst> elementAsts = new Map<Element, ElementAst>(); 317 final Map<Element, ElementAst> elementAsts = new Map<Element, ElementAst>();
344 final Set<Element> topLevelElements = new Set<Element>(); 318 final Set<Element> topLevelElements = new Set<Element>();
345 final Map<ClassElement, Set<Element>> classMembers = 319 final Map<ClassElement, Set<Element>> classMembers =
346 new Map<ClassElement, Set<Element>>(); 320 new Map<ClassElement, Set<Element>>();
347 final Set<ClassElement> emitNoMembersFor = new Set<ClassElement>(); 321 final Set<ClassElement> emitNoMembersFor = new Set<ClassElement>();
348 final ElementPostProcessFunction postProcessElementAst; 322 final ElementPostProcessFunction postProcessElementAst;
349 final ComputeElementAstFunction parseElementAst; 323 final ComputeElementAstFunction parseElementAst;
350 final ElementFilter shouldOutput; 324 final ElementFilter shouldOutput;
351 325
352 ElementInfoProcessor( 326 ElementInfoProcessor(
353 {this.postProcessElementAst, 327 {this.postProcessElementAst, this.parseElementAst, this.shouldOutput});
354 this.parseElementAst,
355 this.shouldOutput});
356 328
357 static ElementInfo createElementInfo( 329 static ElementInfo createElementInfo(
358 Iterable<ClassElement> instantiatedClasses, 330 Iterable<ClassElement> instantiatedClasses,
359 Iterable<AstElement> resolvedElements, 331 Iterable<AstElement> resolvedElements,
360 Iterable<ClassElement> usedTypeLiterals, 332 Iterable<ClassElement> usedTypeLiterals,
361 {ElementPostProcessFunction postProcessElementAst, 333 {ElementPostProcessFunction postProcessElementAst,
362 ComputeElementAstFunction parseElementAst, 334 ComputeElementAstFunction parseElementAst,
363 ElementFilter shouldOutput, 335 ElementFilter shouldOutput,
364 ElementSorter sortElements}) { 336 ElementSorter sortElements}) {
365 ElementInfoProcessor processor = new ElementInfoProcessor( 337 ElementInfoProcessor processor = new ElementInfoProcessor(
366 postProcessElementAst: postProcessElementAst, 338 postProcessElementAst: postProcessElementAst,
367 parseElementAst: parseElementAst, 339 parseElementAst: parseElementAst,
368 shouldOutput: shouldOutput); 340 shouldOutput: shouldOutput);
369 return processor.process( 341 return processor.process(
370 instantiatedClasses, resolvedElements, usedTypeLiterals, 342 instantiatedClasses, resolvedElements, usedTypeLiterals,
371 sortElements: sortElements); 343 sortElements: sortElements);
372 } 344 }
373 345
374 ElementInfo process(Iterable<ClassElement> instantiatedClasses, 346 ElementInfo process(
375 Iterable<AstElement> resolvedElements, 347 Iterable<ClassElement> instantiatedClasses,
376 Iterable<ClassElement> usedTypeLiterals, 348 Iterable<AstElement> resolvedElements,
377 {ElementSorter sortElements}) { 349 Iterable<ClassElement> usedTypeLiterals,
350 {ElementSorter sortElements}) {
378 // Build all top level elements to emit and necessary class members. 351 // Build all top level elements to emit and necessary class members.
379 instantiatedClasses.where(shouldOutput).forEach(addClass); 352 instantiatedClasses.where(shouldOutput).forEach(addClass);
380 resolvedElements.where(shouldOutput).forEach(addMember); 353 resolvedElements.where(shouldOutput).forEach(addMember);
381 usedTypeLiterals.forEach((ClassElement element) { 354 usedTypeLiterals.forEach((ClassElement element) {
382 if (shouldOutput(element)) { 355 if (shouldOutput(element)) {
383 if (!topLevelElements.contains(element)) { 356 if (!topLevelElements.contains(element)) {
384 // The class is only referenced by type literals. 357 // The class is only referenced by type literals.
385 emitNoMembersFor.add(element); 358 emitNoMembersFor.add(element);
386 } 359 }
387 addClass(element); 360 addClass(element);
388 } 361 }
389 }); 362 });
390 363
391 // Sort elements. 364 // Sort elements.
392 List<Element> sortedTopLevels = sortElements(topLevelElements); 365 List<Element> sortedTopLevels = sortElements(topLevelElements);
393 Map<ClassElement, List<Element>> sortedClassMembers = 366 Map<ClassElement, List<Element>> sortedClassMembers =
394 new Map<ClassElement, List<Element>>(); 367 new Map<ClassElement, List<Element>>();
395 classMembers.forEach((classElement, members) { 368 classMembers.forEach((classElement, members) {
396 sortedClassMembers[classElement] = sortElements(members); 369 sortedClassMembers[classElement] = sortElements(members);
397 }); 370 });
398 371
399 return new ElementInfo( 372 return new ElementInfo(
400 elementAsts, sortedTopLevels, sortedClassMembers, emitNoMembersFor); 373 elementAsts, sortedTopLevels, sortedClassMembers, emitNoMembersFor);
401 } 374 }
402 375
403 void processElement(Element element, ElementAst elementAst) { 376 void processElement(Element element, ElementAst elementAst) {
404 if (postProcessElementAst != null) { 377 if (postProcessElementAst != null) {
405 postProcessElementAst(element, elementAst, 378 postProcessElementAst(element, elementAst, newTypedefElementCallback,
406 newTypedefElementCallback, 379 newClassElementCallback);
407 newClassElementCallback);
408 } 380 }
409 elementAsts[element] = elementAst; 381 elementAsts[element] = elementAst;
410 } 382 }
411 383
412 void addTopLevel(AstElement element, ElementAst elementAst) { 384 void addTopLevel(AstElement element, ElementAst elementAst) {
413 if (topLevelElements.contains(element)) return; 385 if (topLevelElements.contains(element)) return;
414 topLevelElements.add(element); 386 topLevelElements.add(element);
415 processElement(element, elementAst); 387 processElement(element, elementAst);
416 } 388 }
417 389
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
452 addTopLevel(element, parseElementAst(element)); 424 addTopLevel(element, parseElementAst(element));
453 } 425 }
454 } 426 }
455 } 427 }
456 } 428 }
457 429
458 /// Main output generator for [DartOutputter] that emits dart code through a 430 /// Main output generator for [DartOutputter] that emits dart code through a
459 /// [CompilerOutputProvider]. 431 /// [CompilerOutputProvider].
460 class MainOutputGenerator { 432 class MainOutputGenerator {
461 final Map<ClassNode, List<Node>> memberNodes = 433 final Map<ClassNode, List<Node>> memberNodes =
462 new Map<ClassNode, List<Node>>(); 434 new Map<ClassNode, List<Node>>();
463 final List<Node> topLevelNodes = <Node>[]; 435 final List<Node> topLevelNodes = <Node>[];
464 436
465 /// Generates the code and returns the total size. 437 /// Generates the code and returns the total size.
466 int generateCode( 438 int generateCode(
467 LibraryInfo libraryInfo, 439 LibraryInfo libraryInfo,
468 ElementInfo elementInfo, 440 ElementInfo elementInfo,
469 PlaceholderCollector collector, 441 PlaceholderCollector collector,
470 PlaceholderRenamer placeholderRenamer, 442 PlaceholderRenamer placeholderRenamer,
471 FunctionElement mainFunction, 443 FunctionElement mainFunction,
472 Uri outputUri, 444 Uri outputUri,
473 CompilerOutputProvider outputProvider, 445 CompilerOutputProvider outputProvider,
474 MirrorRenamer mirrorRenamer, 446 MirrorRenamer mirrorRenamer,
475 {bool multiFile: false, 447 {bool multiFile: false,
476 bool forceStripTypes: false, 448 bool forceStripTypes: false,
477 bool enableMinification: false}) { 449 bool enableMinification: false}) {
478 for (Element element in elementInfo.topLevelElements) { 450 for (Element element in elementInfo.topLevelElements) {
479 topLevelNodes.add(elementInfo.elementAsts[element].ast); 451 topLevelNodes.add(elementInfo.elementAsts[element].ast);
480 if (element.isClass) { 452 if (element.isClass) {
481 ClassElement cls = element; 453 ClassElement cls = element;
482 if (cls.isMixinApplication || cls.isEnumClass) { 454 if (cls.isMixinApplication || cls.isEnumClass) {
483 continue; 455 continue;
484 } 456 }
485 final members = <Node>[]; 457 final members = <Node>[];
486 for (Element member in elementInfo.classMembers[cls]) { 458 for (Element member in elementInfo.classMembers[cls]) {
487 members.add(elementInfo.elementAsts[member].ast); 459 members.add(elementInfo.elementAsts[member].ast);
488 } 460 }
489 memberNodes[elementInfo.elementAsts[cls].ast] = members; 461 memberNodes[elementInfo.elementAsts[cls].ast] = members;
490 } 462 }
491 } 463 }
492 464
493 mirrorRenamer.addRenames(placeholderRenamer.renames, 465 mirrorRenamer.addRenames(
494 topLevelNodes, collector); 466 placeholderRenamer.renames, topLevelNodes, collector);
495 467
496 Map<LibraryElement, String> outputPaths = new Map<LibraryElement, String>(); 468 Map<LibraryElement, String> outputPaths = new Map<LibraryElement, String>();
497 Map<LibraryElement, EmitterUnparser> unparsers = 469 Map<LibraryElement, EmitterUnparser> unparsers =
498 new Map<LibraryElement, EmitterUnparser>(); 470 new Map<LibraryElement, EmitterUnparser>();
499 471
500 // The single unparser used if we collect all the output in one file. 472 // The single unparser used if we collect all the output in one file.
501 EmitterUnparser mainUnparser = multiFile 473 EmitterUnparser mainUnparser = multiFile
502 ? null 474 ? null
503 : new EmitterUnparser(placeholderRenamer.renames, 475 : new EmitterUnparser(placeholderRenamer.renames,
504 stripTypes: forceStripTypes, 476 stripTypes: forceStripTypes, minify: enableMinification);
505 minify: enableMinification);
506 477
507 if (multiFile) { 478 if (multiFile) {
508 // TODO(sigurdm): Factor handling of library-paths out from emitting. 479 // TODO(sigurdm): Factor handling of library-paths out from emitting.
509 String mainName = outputUri.pathSegments.last; 480 String mainName = outputUri.pathSegments.last;
510 String mainBaseName = mainName.endsWith(".dart") 481 String mainBaseName = mainName.endsWith(".dart")
511 ? mainName.substring(0, mainName.length - 5) 482 ? mainName.substring(0, mainName.length - 5)
512 : mainName; 483 : mainName;
513 // Map each library to a path based on the uri of the original 484 // Map each library to a path based on the uri of the original
514 // library and [compiler.options.outputUri]. 485 // library and [compiler.options.outputUri].
515 Set<String> usedLibraryPaths = new Set<String>(); 486 Set<String> usedLibraryPaths = new Set<String>();
516 for (LibraryElement library in libraryInfo.userLibraries) { 487 for (LibraryElement library in libraryInfo.userLibraries) {
517 if (library == mainFunction.library) { 488 if (library == mainFunction.library) {
518 outputPaths[library] = mainBaseName; 489 outputPaths[library] = mainBaseName;
519 } else { 490 } else {
520 List<String> names = 491 List<String> names =
521 library.canonicalUri.pathSegments.last.split("."); 492 library.canonicalUri.pathSegments.last.split(".");
522 if (names.last == "dart") { 493 if (names.last == "dart") {
523 names = names.sublist(0, names.length - 1); 494 names = names.sublist(0, names.length - 1);
524 } 495 }
525 outputPaths[library] = 496 outputPaths[library] =
526 "$mainBaseName.${makeUnique(names.join("."), usedLibraryPaths)}"; 497 "$mainBaseName.${makeUnique(names.join("."), usedLibraryPaths)}";
527 } 498 }
528 } 499 }
529 500
530 /// Rewrites imports/exports to refer to the paths given in [outputPaths]. 501 /// Rewrites imports/exports to refer to the paths given in [outputPaths].
531 for(LibraryElement outputLibrary in libraryInfo.userLibraries) { 502 for (LibraryElement outputLibrary in libraryInfo.userLibraries) {
532 EmitterUnparser unparser = new EmitterUnparser( 503 EmitterUnparser unparser = new EmitterUnparser(
533 placeholderRenamer.renames, 504 placeholderRenamer.renames,
534 stripTypes: forceStripTypes, 505 stripTypes: forceStripTypes,
535 minify: enableMinification); 506 minify: enableMinification);
536 unparsers[outputLibrary] = unparser; 507 unparsers[outputLibrary] = unparser;
537 if (outputLibrary.hasLibraryName) { 508 if (outputLibrary.hasLibraryName) {
538 unparser.unparseLibraryName(outputLibrary.libraryName); 509 unparser.unparseLibraryName(outputLibrary.libraryName);
539 } 510 }
540 for (ImportElement import in outputLibrary.imports) { 511 for (ImportElement import in outputLibrary.imports) {
541 LibraryElement libraryElement = import.importedLibrary; 512 LibraryElement libraryElement = import.importedLibrary;
542 String uri = outputPaths.containsKey(libraryElement) 513 String uri = outputPaths.containsKey(libraryElement)
543 ? "${outputPaths[libraryElement]}.dart" 514 ? "${outputPaths[libraryElement]}.dart"
544 : libraryElement.canonicalUri.toString(); 515 : libraryElement.canonicalUri.toString();
545 unparser.unparseImportTag(uri); 516 unparser.unparseImportTag(uri);
546 } 517 }
547 for (ExportElement export in outputLibrary.exports) { 518 for (ExportElement export in outputLibrary.exports) {
548 LibraryElement libraryElement = export.exportedLibrary; 519 LibraryElement libraryElement = export.exportedLibrary;
549 String uri = outputPaths.containsKey(libraryElement) 520 String uri = outputPaths.containsKey(libraryElement)
550 ? "${outputPaths[libraryElement]}.dart" 521 ? "${outputPaths[libraryElement]}.dart"
551 : libraryElement.canonicalUri.toString(); 522 : libraryElement.canonicalUri.toString();
552 unparser.unparseExportTag(uri); 523 unparser.unparseExportTag(uri);
553 } 524 }
554 } 525 }
555 } else { 526 } else {
556 placeholderRenamer.platformImports.forEach( 527 placeholderRenamer.platformImports
557 (LibraryElement library, String prefix) { 528 .forEach((LibraryElement library, String prefix) {
558 assert(library.isPlatformLibrary && !library.isInternalLibrary); 529 assert(library.isPlatformLibrary && !library.isInternalLibrary);
559 mainUnparser.unparseImportTag(library.canonicalUri.toString()); 530 mainUnparser.unparseImportTag(library.canonicalUri.toString());
560 if (prefix != null) { 531 if (prefix != null) {
561 // Adding a prefixed import because (some) top-level access need 532 // Adding a prefixed import because (some) top-level access need
562 // it to avoid shadowing. 533 // it to avoid shadowing.
563 // TODO(johnniwinther): Avoid prefix-less import if not needed. 534 // TODO(johnniwinther): Avoid prefix-less import if not needed.
564 mainUnparser.unparseImportTag(library.canonicalUri.toString(), 535 mainUnparser.unparseImportTag(library.canonicalUri.toString(),
565 prefix: prefix); 536 prefix: prefix);
566 } 537 }
567 }); 538 });
568 } 539 }
569 540
570 for (int i = 0; i < elementInfo.topLevelElements.length; i++) { 541 for (int i = 0; i < elementInfo.topLevelElements.length; i++) {
571 Element element = elementInfo.topLevelElements.elementAt(i); 542 Element element = elementInfo.topLevelElements.elementAt(i);
572 Node node = topLevelNodes[i]; 543 Node node = topLevelNodes[i];
573 Unparser unparser = multiFile ? unparsers[element.library] : mainUnparser; 544 Unparser unparser = multiFile ? unparsers[element.library] : mainUnparser;
574 if (node is ClassNode) { 545 if (node is ClassNode) {
575 // TODO(smok): Filter out default constructors here. 546 // TODO(smok): Filter out default constructors here.
576 unparser.unparseClassWithBody(node, memberNodes[node]); 547 unparser.unparseClassWithBody(node, memberNodes[node]);
577 } else { 548 } else {
578 unparser.unparse(node); 549 unparser.unparse(node);
579 } 550 }
580 unparser.newline(); 551 unparser.newline();
581 } 552 }
582 553
583 int totalSize = 0; 554 int totalSize = 0;
584 if (multiFile) { 555 if (multiFile) {
585 for(LibraryElement outputLibrary in libraryInfo.userLibraries) { 556 for (LibraryElement outputLibrary in libraryInfo.userLibraries) {
586 // TODO(sigurdm): Make the unparser output directly into the buffer 557 // TODO(sigurdm): Make the unparser output directly into the buffer
587 // instead of caching in `.result`. 558 // instead of caching in `.result`.
588 String code = unparsers[outputLibrary].result; 559 String code = unparsers[outputLibrary].result;
589 totalSize += code.length; 560 totalSize += code.length;
590 outputProvider(outputPaths[outputLibrary], "dart") 561 outputProvider(outputPaths[outputLibrary], "dart")
591 ..add(code) 562 ..add(code)
592 ..close(); 563 ..close();
593 } 564 }
594 } else { 565 } else {
595 String code = mainUnparser.result; 566 String code = mainUnparser.result;
596 outputProvider("", "dart") 567 outputProvider("", "dart")
597 ..add(code) 568 ..add(code)
598 ..close(); 569 ..close();
599 570
600 totalSize = code.length; 571 totalSize = code.length;
601 } 572 }
602 573
603 return totalSize; 574 return totalSize;
604 } 575 }
605 } 576 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/dart_backend/dart_backend.dart ('k') | pkg/compiler/lib/src/dart_backend/placeholder_collector.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698