OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 analyzer.src.summary.summary_file_builder; | 5 library analyzer.src.summary.summary_file_builder; |
6 | 6 |
7 import 'dart:collection'; | 7 import 'dart:collection'; |
8 import 'dart:io' as io; | |
9 | 8 |
10 import 'package:analyzer/dart/ast/ast.dart'; | |
11 import 'package:analyzer/dart/element/element.dart'; | 9 import 'package:analyzer/dart/element/element.dart'; |
12 import 'package:analyzer/file_system/file_system.dart'; | 10 import 'package:analyzer/file_system/file_system.dart'; |
13 import 'package:analyzer/file_system/physical_file_system.dart'; | 11 import 'package:analyzer/file_system/physical_file_system.dart'; |
14 import 'package:analyzer/src/dart/sdk/sdk.dart'; | 12 import 'package:analyzer/src/dart/sdk/sdk.dart'; |
15 import 'package:analyzer/src/generated/engine.dart'; | 13 import 'package:analyzer/src/generated/engine.dart'; |
16 import 'package:analyzer/src/generated/sdk.dart'; | 14 import 'package:analyzer/src/generated/sdk.dart'; |
17 import 'package:analyzer/src/generated/source.dart'; | 15 import 'package:analyzer/src/generated/source.dart'; |
18 import 'package:analyzer/src/summary/flat_buffers.dart' as fb; | |
19 import 'package:analyzer/src/summary/index_unit.dart'; | |
20 import 'package:analyzer/src/summary/summarize_elements.dart'; | 16 import 'package:analyzer/src/summary/summarize_elements.dart'; |
21 import 'package:path/path.dart'; | |
22 | 17 |
23 const int FIELD_SPEC_INDEX = 1; | 18 class SummaryBuilder { |
24 const int FIELD_SPEC_SUM = 0; | 19 final Iterable<Source> librarySources; |
25 const int FIELD_STRONG_INDEX = 3; | 20 final AnalysisContext context; |
26 const int FIELD_STRONG_SUM = 2; | 21 final bool strong; |
27 | |
28 class BuilderOutput { | |
29 final List<int> sum; | |
30 final List<int> index; | |
31 | |
32 BuilderOutput(this.sum, this.index); | |
33 | |
34 void writeMultiple(String outputDirectoryPath, String modeName) { | |
35 // Write summary. | |
36 { | |
37 String outputPath = join(outputDirectoryPath, '$modeName.sum'); | |
38 io.File file = new io.File(outputPath); | |
39 file.writeAsBytesSync(sum, mode: io.FileMode.WRITE_ONLY); | |
40 } | |
41 // Write index. | |
42 { | |
43 String outputPath = join(outputDirectoryPath, '$modeName.index'); | |
44 io.File file = new io.File(outputPath); | |
45 file.writeAsBytesSync(index, mode: io.FileMode.WRITE_ONLY); | |
46 } | |
47 } | |
48 } | |
49 | |
50 /** | |
51 * Summary build configuration. | |
52 */ | |
53 class SummaryBuildConfig { | |
54 /** | |
55 * Whether to use exclude informative data from created summaries. | |
56 */ | |
57 final bool buildSummaryExcludeInformative; | |
58 | 22 |
59 /** | 23 /** |
60 * Whether to output a summary in "fallback mode". | 24 * Create a summary builder for these [librarySources] and [context]. |
61 */ | 25 */ |
62 final bool buildSummaryFallback; | 26 SummaryBuilder(this.librarySources, this.context, this.strong); |
63 | 27 |
64 /** | 28 /** |
65 * Whether to create summaries directly from ASTs, i.e. don't create a | 29 * Create an SDK summary builder for the dart SDK at the given [sdkPath]. |
66 * full element model. | |
67 */ | 30 */ |
68 final bool buildSummaryOnlyAst; | 31 factory SummaryBuilder.forSdk(String sdkPath, bool strong) { |
69 | |
70 /** | |
71 * Path to the dart SDK summary file. | |
72 */ | |
73 final String dartSdkSummaryPath; | |
74 | |
75 /** | |
76 * Whether to use strong static checking. | |
77 */ | |
78 final bool strongMode; | |
79 | |
80 /** | |
81 * List of summary input file paths. | |
82 */ | |
83 final Iterable<String> summaryInputs; | |
84 | |
85 /** | |
86 * Create a build configuration with the given set options. | |
87 */ | |
88 SummaryBuildConfig( | |
89 {this.strongMode: false, | |
90 this.summaryInputs, | |
91 this.dartSdkSummaryPath, | |
92 this.buildSummaryExcludeInformative: false, | |
93 this.buildSummaryFallback: false, | |
94 this.buildSummaryOnlyAst: false}); | |
95 } | |
96 | |
97 class SummaryBuilder { | |
98 final AnalysisContext context; | |
99 final Iterable<Source> librarySources; | |
100 final SummaryBuildConfig config; | |
101 | |
102 /** | |
103 * Create a summary builder for these [librarySources] and [context] using the | |
104 * given [config]. | |
105 */ | |
106 SummaryBuilder(this.librarySources, this.context, this.config); | |
107 | |
108 /** | |
109 * Create an SDK summary builder for the dart SDK at the given [sdkPath], | |
110 * using this [config]. | |
111 */ | |
112 factory SummaryBuilder.forSdk(String sdkPath, SummaryBuildConfig config) { | |
113 bool strongMode = config.strongMode; | |
114 | |
115 // | 32 // |
116 // Prepare SDK. | 33 // Prepare SDK. |
117 // | 34 // |
118 ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE; | 35 ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE; |
119 FolderBasedDartSdk sdk = new FolderBasedDartSdk( | 36 FolderBasedDartSdk sdk = new FolderBasedDartSdk( |
120 resourceProvider, resourceProvider.getFolder(sdkPath), strongMode); | 37 resourceProvider, resourceProvider.getFolder(sdkPath), strong); |
121 sdk.useSummary = false; | 38 sdk.useSummary = false; |
122 sdk.analysisOptions = new AnalysisOptionsImpl()..strongMode = strongMode; | 39 sdk.analysisOptions = new AnalysisOptionsImpl()..strongMode = strong; |
123 | 40 |
124 // | 41 // |
125 // Prepare 'dart:' URIs to serialize. | 42 // Prepare 'dart:' URIs to serialize. |
126 // | 43 // |
127 Set<String> uriSet = | 44 Set<String> uriSet = |
128 sdk.sdkLibraries.map((SdkLibrary library) => library.shortName).toSet(); | 45 sdk.sdkLibraries.map((SdkLibrary library) => library.shortName).toSet(); |
129 if (!strongMode) { | 46 if (!strong) { |
130 uriSet.add('dart:html/nativewrappers.dart'); | 47 uriSet.add('dart:html/nativewrappers.dart'); |
131 } | 48 } |
132 uriSet.add('dart:html_common/html_common_dart2js.dart'); | 49 uriSet.add('dart:html_common/html_common_dart2js.dart'); |
133 | 50 |
134 Set<Source> librarySources = new HashSet<Source>(); | 51 Set<Source> librarySources = new HashSet<Source>(); |
135 for (String uri in uriSet) { | 52 for (String uri in uriSet) { |
136 librarySources.add(sdk.mapDartUri(uri)); | 53 librarySources.add(sdk.mapDartUri(uri)); |
137 } | 54 } |
138 | 55 |
139 return new SummaryBuilder(librarySources, sdk.context, config); | 56 return new SummaryBuilder(librarySources, sdk.context, strong); |
140 } | 57 } |
141 | 58 |
142 BuilderOutput build() => new _Builder(context, librarySources).build(); | |
143 } | |
144 | |
145 /** | |
146 * Intermediary summary output result. | |
147 */ | |
148 class SummaryOutput { | |
149 final BuilderOutput spec; | |
150 final BuilderOutput strong; | |
151 SummaryOutput(this.spec, this.strong); | |
152 | |
153 /** | 59 /** |
154 * Write this summary output to the given [outputPath] and return the | 60 * Build the linked bundle and return its bytes. |
155 * created file. | |
156 */ | 61 */ |
157 io.File write(String outputPath) { | 62 List<int> build() => new _Builder(context, librarySources).build(); |
158 fb.Builder builder = new fb.Builder(); | |
159 fb.Offset specSumOffset = builder.writeListUint8(spec.sum); | |
160 fb.Offset specIndexOffset = builder.writeListUint8(spec.index); | |
161 fb.Offset strongSumOffset = builder.writeListUint8(strong.sum); | |
162 fb.Offset strongIndexOffset = builder.writeListUint8(strong.index); | |
163 builder.startTable(); | |
164 builder.addOffset(FIELD_SPEC_SUM, specSumOffset); | |
165 builder.addOffset(FIELD_SPEC_INDEX, specIndexOffset); | |
166 builder.addOffset(FIELD_STRONG_SUM, strongSumOffset); | |
167 builder.addOffset(FIELD_STRONG_INDEX, strongIndexOffset); | |
168 fb.Offset offset = builder.endTable(); | |
169 return new io.File(outputPath) | |
170 ..writeAsBytesSync(builder.finish(offset), mode: io.FileMode.WRITE_ONLY); | |
171 } | |
172 } | 63 } |
173 | 64 |
174 class _Builder { | 65 class _Builder { |
175 final Set<Source> processedSources = new Set<Source>(); | |
176 | |
177 final PackageBundleAssembler bundleAssembler = new PackageBundleAssembler(); | |
178 final PackageIndexAssembler indexAssembler = new PackageIndexAssembler(); | |
179 | |
180 final AnalysisContext context; | 66 final AnalysisContext context; |
181 final Iterable<Source> librarySources; | 67 final Iterable<Source> librarySources; |
182 | 68 |
| 69 final Set<Source> processedSources = new Set<Source>(); |
| 70 final PackageBundleAssembler bundleAssembler = new PackageBundleAssembler(); |
| 71 |
183 _Builder(this.context, this.librarySources); | 72 _Builder(this.context, this.librarySources); |
184 | 73 |
185 /** | 74 /** |
186 * Build summary output. | 75 * Build the linked bundle and return its bytes. |
187 */ | 76 */ |
188 BuilderOutput build() { | 77 List<int> build() { |
189 // | 78 librarySources.forEach(_serializeLibrary); |
190 // Serialize each source. | 79 return bundleAssembler.assemble().toBuffer(); |
191 // | |
192 for (Source source in librarySources) { | |
193 _serializeLibrary(source); | |
194 } | |
195 // | |
196 // Assemble the output. | |
197 // | |
198 List<int> sumBytes = bundleAssembler.assemble().toBuffer(); | |
199 List<int> indexBytes = indexAssembler.assemble().toBuffer(); | |
200 return new BuilderOutput(sumBytes, indexBytes); | |
201 } | 80 } |
202 | 81 |
203 /** | 82 /** |
204 * Serialize the library with the given [source] and all its direct or | 83 * Serialize the library with the given [source] and all its direct or |
205 * indirect imports and exports. | 84 * indirect imports and exports. |
206 */ | 85 */ |
207 void _serializeLibrary(Source source) { | 86 void _serializeLibrary(Source source) { |
208 if (!processedSources.add(source)) { | 87 if (!processedSources.add(source)) { |
209 return; | 88 return; |
210 } | 89 } |
211 LibraryElement element = context.computeLibraryElement(source); | 90 LibraryElement element = context.computeLibraryElement(source); |
212 bundleAssembler.serializeLibraryElement(element); | 91 bundleAssembler.serializeLibraryElement(element); |
213 element.importedLibraries.forEach((e) => _serializeLibrary(e.source)); | 92 element.importedLibraries.forEach((e) => _serializeLibrary(e.source)); |
214 element.exportedLibraries.forEach((e) => _serializeLibrary(e.source)); | 93 element.exportedLibraries.forEach((e) => _serializeLibrary(e.source)); |
215 // Index every unit of the library. | |
216 for (CompilationUnitElement unitElement in element.units) { | |
217 Source unitSource = unitElement.source; | |
218 CompilationUnit unit = | |
219 context.resolveCompilationUnit2(unitSource, source); | |
220 indexAssembler.indexUnit(unit); | |
221 } | |
222 } | 94 } |
223 } | 95 } |
OLD | NEW |