OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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_cli.src.build_mode; | 5 library analyzer_cli.src.build_mode; |
6 | 6 |
7 import 'dart:core' hide Resource; | 7 import 'dart:core' hide Resource; |
8 import 'dart:io' as io; | 8 import 'dart:io' as io; |
9 | 9 |
10 import 'package:protobuf/protobuf.dart'; | |
11 | |
12 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit; | 10 import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit; |
13 import 'package:analyzer/dart/element/element.dart'; | 11 import 'package:analyzer/dart/element/element.dart'; |
14 import 'package:analyzer/file_system/file_system.dart'; | 12 import 'package:analyzer/file_system/file_system.dart'; |
15 import 'package:analyzer/file_system/physical_file_system.dart'; | 13 import 'package:analyzer/file_system/physical_file_system.dart'; |
16 import 'package:analyzer/src/generated/engine.dart'; | 14 import 'package:analyzer/src/generated/engine.dart'; |
17 import 'package:analyzer/src/generated/error.dart'; | 15 import 'package:analyzer/src/generated/error.dart'; |
18 import 'package:analyzer/src/generated/java_io.dart'; | 16 import 'package:analyzer/src/generated/java_io.dart'; |
19 import 'package:analyzer/src/generated/sdk_io.dart'; | 17 import 'package:analyzer/src/generated/sdk_io.dart'; |
20 import 'package:analyzer/src/generated/source.dart'; | 18 import 'package:analyzer/src/generated/source.dart'; |
21 import 'package:analyzer/src/generated/source_io.dart'; | 19 import 'package:analyzer/src/generated/source_io.dart'; |
22 import 'package:analyzer/src/summary/format.dart'; | 20 import 'package:analyzer/src/summary/format.dart'; |
23 import 'package:analyzer/src/summary/idl.dart'; | 21 import 'package:analyzer/src/summary/idl.dart'; |
| 22 import 'package:analyzer/src/summary/link.dart'; |
24 import 'package:analyzer/src/summary/package_bundle_reader.dart'; | 23 import 'package:analyzer/src/summary/package_bundle_reader.dart'; |
25 import 'package:analyzer/src/summary/prelink.dart'; | |
26 import 'package:analyzer/src/summary/summarize_ast.dart'; | 24 import 'package:analyzer/src/summary/summarize_ast.dart'; |
27 import 'package:analyzer/src/summary/summarize_elements.dart'; | 25 import 'package:analyzer/src/summary/summarize_elements.dart'; |
28 import 'package:analyzer/task/dart.dart'; | 26 import 'package:analyzer/task/dart.dart'; |
29 import 'package:analyzer_cli/src/analyzer_impl.dart'; | 27 import 'package:analyzer_cli/src/analyzer_impl.dart'; |
30 import 'package:analyzer_cli/src/driver.dart'; | 28 import 'package:analyzer_cli/src/driver.dart'; |
31 import 'package:analyzer_cli/src/error_formatter.dart'; | 29 import 'package:analyzer_cli/src/error_formatter.dart'; |
32 import 'package:analyzer_cli/src/options.dart'; | 30 import 'package:analyzer_cli/src/options.dart'; |
| 31 import 'package:protobuf/protobuf.dart'; |
33 | 32 |
34 import 'message_grouper.dart'; | 33 import 'message_grouper.dart'; |
35 import 'worker_protocol.pb.dart'; | 34 import 'worker_protocol.pb.dart'; |
36 | 35 |
37 /** | 36 /** |
38 * Analyzer used when the "--build-mode" option is supplied. | 37 * Analyzer used when the "--build-mode" option is supplied. |
39 */ | 38 */ |
40 class BuildMode { | 39 class BuildMode { |
41 final CommandLineOptions options; | 40 final CommandLineOptions options; |
42 final AnalysisStats stats; | 41 final AnalysisStats stats; |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 while (true) { | 91 while (true) { |
93 AnalysisResult analysisResult = context.performAnalysisTask(); | 92 AnalysisResult analysisResult = context.performAnalysisTask(); |
94 if (!analysisResult.hasMoreWork) { | 93 if (!analysisResult.hasMoreWork) { |
95 break; | 94 break; |
96 } | 95 } |
97 } | 96 } |
98 } | 97 } |
99 | 98 |
100 // Write summary. | 99 // Write summary. |
101 if (options.buildSummaryOutput != null) { | 100 if (options.buildSummaryOutput != null) { |
102 for (Source source in explicitSources) { | 101 if (options.buildSummaryOnlyAst && !options.buildSummaryFallback) { |
103 if (context.computeKindOf(source) == SourceKind.LIBRARY) { | 102 _serializeAstBasedSummary(explicitSources); |
| 103 } else { |
| 104 for (Source source in explicitSources) { |
| 105 if (context.computeKindOf(source) == SourceKind.LIBRARY) { |
| 106 if (options.buildSummaryFallback) { |
| 107 assembler.addFallbackLibrary(source); |
| 108 } else { |
| 109 LibraryElement libraryElement = |
| 110 context.computeLibraryElement(source); |
| 111 assembler.serializeLibraryElement(libraryElement); |
| 112 } |
| 113 } |
104 if (options.buildSummaryFallback) { | 114 if (options.buildSummaryFallback) { |
105 assembler.addFallbackLibrary(source); | 115 assembler.addFallbackUnit(source); |
106 } else if (options.buildSummaryOnlyAst) { | |
107 _serializeAstBasedSummary(source); | |
108 } else { | |
109 LibraryElement libraryElement = | |
110 context.computeLibraryElement(source); | |
111 assembler.serializeLibraryElement(libraryElement); | |
112 } | 116 } |
113 } | 117 } |
114 if (options.buildSummaryFallback) { | |
115 assembler.addFallbackUnit(source); | |
116 } | |
117 } | 118 } |
118 // Write the whole package bundle. | 119 // Write the whole package bundle. |
119 PackageBundleBuilder sdkBundle = assembler.assemble(); | 120 PackageBundleBuilder sdkBundle = assembler.assemble(); |
120 if (options.buildSummaryExcludeInformative) { | 121 if (options.buildSummaryExcludeInformative) { |
121 sdkBundle.flushInformative(); | 122 sdkBundle.flushInformative(); |
122 sdkBundle.unlinkedUnitHashes = null; | 123 sdkBundle.unlinkedUnitHashes = null; |
123 } | 124 } |
124 io.File file = new io.File(options.buildSummaryOutput); | 125 io.File file = new io.File(options.buildSummaryOutput); |
125 file.writeAsBytesSync(sdkBundle.toBuffer(), mode: io.FileMode.WRITE_ONLY); | 126 file.writeAsBytesSync(sdkBundle.toBuffer(), mode: io.FileMode.WRITE_ONLY); |
126 } | 127 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 } | 210 } |
210 if (outputPath == null) { | 211 if (outputPath == null) { |
211 StringSink sink = options.machineFormat ? errorSink : outSink; | 212 StringSink sink = options.machineFormat ? errorSink : outSink; |
212 sink.write(buffer); | 213 sink.write(buffer); |
213 } else { | 214 } else { |
214 new io.File(outputPath).writeAsStringSync(buffer.toString()); | 215 new io.File(outputPath).writeAsStringSync(buffer.toString()); |
215 } | 216 } |
216 } | 217 } |
217 | 218 |
218 /** | 219 /** |
219 * Serialize the library with the given [source] into [assembler] using only | 220 * Serialize the package with the given [sources] into [assembler] using only |
220 * its AST, [UnlinkedUnit]s of input packages and ASTs (via [UnlinkedUnit]s) | 221 * their ASTs and [LinkedUnit]s of input packages. |
221 * of package sources. | |
222 */ | 222 */ |
223 void _serializeAstBasedSummary(Source source) { | 223 void _serializeAstBasedSummary(List<Source> sources) { |
224 Source resolveRelativeUri(String relativeUri) { | 224 Set<String> sourceUris = |
225 Source resolvedSource = | 225 sources.map((Source s) => s.uri.toString()).toSet(); |
226 context.sourceFactory.resolveUri(source, relativeUri); | |
227 if (resolvedSource == null) { | |
228 context.sourceFactory.resolveUri(source, relativeUri); | |
229 throw new StateError('Could not resolve $relativeUri in the context of ' | |
230 '$source (${source.runtimeType})'); | |
231 } | |
232 return resolvedSource; | |
233 } | |
234 | 226 |
235 UnlinkedUnit _getUnlinkedUnit(Source source) { | 227 LinkedLibrary _getDependency(String absoluteUri) => |
| 228 summaryDataStore.linkedMap[absoluteUri]; |
| 229 |
| 230 UnlinkedUnit _getUnit(String absoluteUri) { |
236 // Maybe an input package contains the source. | 231 // Maybe an input package contains the source. |
237 { | 232 { |
238 String uriStr = source.uri.toString(); | 233 UnlinkedUnit unlinkedUnit = summaryDataStore.unlinkedMap[absoluteUri]; |
239 UnlinkedUnit unlinkedUnit = summaryDataStore.unlinkedMap[uriStr]; | |
240 if (unlinkedUnit != null) { | 234 if (unlinkedUnit != null) { |
241 return unlinkedUnit; | 235 return unlinkedUnit; |
242 } | 236 } |
243 } | 237 } |
244 // Parse the source and serialize its AST. | 238 // Parse the source and serialize its AST. |
245 return uriToUnit.putIfAbsent(source.uri, () { | 239 Uri uri = Uri.parse(absoluteUri); |
| 240 Source source = context.sourceFactory.forUri2(uri); |
| 241 return uriToUnit.putIfAbsent(uri, () { |
246 CompilationUnit unit = context.computeResult(source, PARSED_UNIT); | 242 CompilationUnit unit = context.computeResult(source, PARSED_UNIT); |
247 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit); | 243 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit); |
248 assembler.addUnlinkedUnit(source, unlinkedUnit); | 244 assembler.addUnlinkedUnit(source, unlinkedUnit); |
249 return unlinkedUnit; | 245 return unlinkedUnit; |
250 }); | 246 }); |
251 } | 247 } |
252 | 248 |
253 UnlinkedUnit getPart(String relativeUri) { | 249 Map<String, LinkedLibraryBuilder> linkResult = |
254 return _getUnlinkedUnit(resolveRelativeUri(relativeUri)); | 250 link(sourceUris, _getDependency, _getUnit, options.strongMode); |
255 } | 251 linkResult.forEach(assembler.addLinkedLibrary); |
256 | |
257 UnlinkedPublicNamespace getImport(String relativeUri) { | |
258 return getPart(relativeUri).publicNamespace; | |
259 } | |
260 | |
261 UnlinkedUnitBuilder definingUnit = _getUnlinkedUnit(source); | |
262 LinkedLibraryBuilder linkedLibrary = | |
263 prelink(definingUnit, getPart, getImport); | |
264 assembler.addLinkedLibrary(source.uri.toString(), linkedLibrary); | |
265 } | 252 } |
266 | 253 |
267 /** | 254 /** |
268 * Convert [sourceEntities] (a list of file specifications of the form | 255 * Convert [sourceEntities] (a list of file specifications of the form |
269 * "$uri|$path") to a map from URI to path. If an error occurs, report the | 256 * "$uri|$path") to a map from URI to path. If an error occurs, report the |
270 * error and return null. | 257 * error and return null. |
271 */ | 258 */ |
272 static Map<Uri, JavaFile> _createUriToFileMap(List<String> sourceEntities) { | 259 static Map<Uri, JavaFile> _createUriToFileMap(List<String> sourceEntities) { |
273 Map<Uri, JavaFile> uriToFileMap = <Uri, JavaFile>{}; | 260 Map<Uri, JavaFile> uriToFileMap = <Uri, JavaFile>{}; |
274 for (String sourceFile in sourceEntities) { | 261 for (String sourceFile in sourceEntities) { |
275 int pipeIndex = sourceFile.indexOf('|'); | 262 int pipeIndex = sourceFile.indexOf('|'); |
276 if (pipeIndex == -1) { | 263 if (pipeIndex == -1) { |
277 // TODO(paulberry): add the ability to guess the URI from the path. | 264 // TODO(paulberry): add the ability to guess the URI from the path. |
278 errorSink.writeln( | 265 errorSink.writeln( |
279 'Illegal input file (must be "\$uri|\$path"): $sourceFile'); | 266 'Illegal input file (must be "\$uri|\$path"): $sourceFile'); |
280 return null; | 267 return null; |
281 } | 268 } |
282 Uri uri = Uri.parse(sourceFile.substring(0, pipeIndex)); | 269 Uri uri = Uri.parse(sourceFile.substring(0, pipeIndex)); |
283 String path = sourceFile.substring(pipeIndex + 1); | 270 String path = sourceFile.substring(pipeIndex + 1); |
284 uriToFileMap[uri] = new JavaFile(path); | 271 uriToFileMap[uri] = new JavaFile(path); |
285 } | 272 } |
286 return uriToFileMap; | 273 return uriToFileMap; |
287 } | 274 } |
288 } | 275 } |
289 | 276 |
290 /** | 277 /** |
| 278 * Default implementation of [WorkerConnection] that works with stdio. |
| 279 */ |
| 280 class StdWorkerConnection implements WorkerConnection { |
| 281 final MessageGrouper _messageGrouper; |
| 282 final io.Stdout _stdoutStream; |
| 283 |
| 284 StdWorkerConnection(io.Stdin stdinStream, this._stdoutStream) |
| 285 : _messageGrouper = new MessageGrouper(stdinStream); |
| 286 |
| 287 @override |
| 288 WorkRequest readRequest() { |
| 289 var buffer = _messageGrouper.next; |
| 290 if (buffer == null) return null; |
| 291 |
| 292 return new WorkRequest.fromBuffer(buffer); |
| 293 } |
| 294 |
| 295 @override |
| 296 void writeResponse(WorkResponse response) { |
| 297 var responseBuffer = response.writeToBuffer(); |
| 298 |
| 299 var writer = new CodedBufferWriter(); |
| 300 writer.writeInt32NoTag(responseBuffer.length); |
| 301 writer.writeRawBytes(responseBuffer); |
| 302 |
| 303 _stdoutStream.add(writer.toBuffer()); |
| 304 } |
| 305 } |
| 306 |
| 307 /** |
291 * Connection between a worker and input / output. | 308 * Connection between a worker and input / output. |
292 */ | 309 */ |
293 abstract class WorkerConnection { | 310 abstract class WorkerConnection { |
294 /** | 311 /** |
295 * Read a new [WorkRequest]. Returns [null] when there are no more requests. | 312 * Read a new [WorkRequest]. Returns [null] when there are no more requests. |
296 */ | 313 */ |
297 WorkRequest readRequest(); | 314 WorkRequest readRequest(); |
298 | 315 |
299 /** | 316 /** |
300 * Write the given [response] as bytes to the output. | 317 * Write the given [response] as bytes to the output. |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
388 String msg = ''; | 405 String msg = ''; |
389 if (errorBuffer.isNotEmpty) { | 406 if (errorBuffer.isNotEmpty) { |
390 msg += errorBuffer.toString() + '\n'; | 407 msg += errorBuffer.toString() + '\n'; |
391 } | 408 } |
392 if (outBuffer.isNotEmpty) { | 409 if (outBuffer.isNotEmpty) { |
393 msg += outBuffer.toString() + '\n'; | 410 msg += outBuffer.toString() + '\n'; |
394 } | 411 } |
395 return msg; | 412 return msg; |
396 } | 413 } |
397 } | 414 } |
398 | |
399 /** | |
400 * Default implementation of [WorkerConnection] that works with stdio. | |
401 */ | |
402 class StdWorkerConnection implements WorkerConnection { | |
403 final MessageGrouper _messageGrouper; | |
404 final io.Stdout _stdoutStream; | |
405 | |
406 StdWorkerConnection(io.Stdin stdinStream, this._stdoutStream) | |
407 : _messageGrouper = new MessageGrouper(stdinStream); | |
408 | |
409 @override | |
410 WorkRequest readRequest() { | |
411 var buffer = _messageGrouper.next; | |
412 if (buffer == null) return null; | |
413 | |
414 return new WorkRequest.fromBuffer(buffer); | |
415 } | |
416 | |
417 @override | |
418 void writeResponse(WorkResponse response) { | |
419 var responseBuffer = response.writeToBuffer(); | |
420 | |
421 var writer = new CodedBufferWriter(); | |
422 writer.writeInt32NoTag(responseBuffer.length); | |
423 writer.writeRawBytes(responseBuffer); | |
424 | |
425 _stdoutStream.add(writer.toBuffer()); | |
426 } | |
427 } | |
OLD | NEW |