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:async'; | 7 import 'dart:async'; |
8 import 'dart:io' as io; | 8 import 'dart:io' as io; |
9 | 9 |
10 import 'package:analyzer/error/error.dart'; | 10 import 'package:analyzer/error/error.dart'; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 /** | 127 /** |
128 * Analyzer used when the "--build-mode" option is supplied. | 128 * Analyzer used when the "--build-mode" option is supplied. |
129 */ | 129 */ |
130 class BuildMode { | 130 class BuildMode { |
131 final ResourceProvider resourceProvider; | 131 final ResourceProvider resourceProvider; |
132 final CommandLineOptions options; | 132 final CommandLineOptions options; |
133 final AnalysisStats stats; | 133 final AnalysisStats stats; |
134 | 134 |
135 SummaryDataStore summaryDataStore; | 135 SummaryDataStore summaryDataStore; |
136 AnalysisOptions analysisOptions; | 136 AnalysisOptions analysisOptions; |
137 AnalysisDriver analysisDriver; | |
138 Map<Uri, File> uriToFileMap; | 137 Map<Uri, File> uriToFileMap; |
139 final List<Source> explicitSources = <Source>[]; | 138 final List<Source> explicitSources = <Source>[]; |
140 final List<PackageBundle> unlinkedBundles = <PackageBundle>[]; | 139 final List<PackageBundle> unlinkedBundles = <PackageBundle>[]; |
141 | 140 |
| 141 PerformanceLog logger = new PerformanceLog(null); |
| 142 AnalysisDriver analysisDriver; |
| 143 |
142 PackageBundleAssembler assembler; | 144 PackageBundleAssembler assembler; |
143 final Set<Source> processedSources = new Set<Source>(); | 145 final Set<Source> processedSources = new Set<Source>(); |
144 final Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{}; | 146 final Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{}; |
145 | 147 |
146 BuildMode(this.resourceProvider, this.options, this.stats); | 148 BuildMode(this.resourceProvider, this.options, this.stats); |
147 | 149 |
148 bool get _shouldOutputSummary => | 150 bool get _shouldOutputSummary => |
149 options.buildSummaryOutput != null || | 151 options.buildSummaryOutput != null || |
150 options.buildSummaryOutputSemantic != null; | 152 options.buildSummaryOutputSemantic != null; |
151 | 153 |
152 /** | 154 /** |
153 * Perform package analysis according to the given [options]. | 155 * Perform package analysis according to the given [options]. |
154 */ | 156 */ |
155 Future<ErrorSeverity> analyze() async { | 157 Future<ErrorSeverity> analyze() async { |
156 // Write initial progress message. | 158 return await logger.runAsync('Analyze', () async { |
157 if (!options.machineFormat) { | 159 // Write initial progress message. |
158 outSink.writeln("Analyzing ${options.sourceFiles.join(', ')}..."); | 160 if (!options.machineFormat) { |
159 } | 161 outSink.writeln("Analyzing ${options.sourceFiles.join(', ')}..."); |
| 162 } |
160 | 163 |
161 // Create the URI to file map. | 164 // Create the URI to file map. |
162 uriToFileMap = _createUriToFileMap(options.sourceFiles); | 165 uriToFileMap = _createUriToFileMap(options.sourceFiles); |
163 if (uriToFileMap == null) { | 166 if (uriToFileMap == null) { |
164 io.exitCode = ErrorSeverity.ERROR.ordinal; | |
165 return ErrorSeverity.ERROR; | |
166 } | |
167 | |
168 // BuildMode expects sourceFiles in the format "<uri>|<filepath>", | |
169 // but the rest of the code base does not understand this format. | |
170 // Rewrite sourceFiles, stripping the "<uri>|" prefix, so that it | |
171 // does not cause problems with code that does not expect this format. | |
172 options.rewriteSourceFiles(options.sourceFiles | |
173 .map((String uriPipePath) => | |
174 uriPipePath.substring(uriPipePath.indexOf('|') + 1)) | |
175 .toList()); | |
176 | |
177 // Prepare the analysis driver. | |
178 try { | |
179 _createAnalysisDriver(); | |
180 } on ConflictingSummaryException catch (e) { | |
181 errorSink.writeln('$e'); | |
182 io.exitCode = ErrorSeverity.ERROR.ordinal; | |
183 return ErrorSeverity.ERROR; | |
184 } | |
185 | |
186 // Add sources. | |
187 for (Uri uri in uriToFileMap.keys) { | |
188 File file = uriToFileMap[uri]; | |
189 if (!file.exists) { | |
190 errorSink.writeln('File not found: ${file.path}'); | |
191 io.exitCode = ErrorSeverity.ERROR.ordinal; | 167 io.exitCode = ErrorSeverity.ERROR.ordinal; |
192 return ErrorSeverity.ERROR; | 168 return ErrorSeverity.ERROR; |
193 } | 169 } |
194 Source source = new FileSource(file, uri); | |
195 explicitSources.add(source); | |
196 } | |
197 | 170 |
198 // Write summary. | 171 // BuildMode expects sourceFiles in the format "<uri>|<filepath>", |
199 assembler = new PackageBundleAssembler(); | 172 // but the rest of the code base does not understand this format. |
200 if (_shouldOutputSummary) { | 173 // Rewrite sourceFiles, stripping the "<uri>|" prefix, so that it |
201 // Prepare all unlinked units. | 174 // does not cause problems with code that does not expect this format. |
202 for (var src in explicitSources) { | 175 options.rewriteSourceFiles(options.sourceFiles |
203 await _prepareUnlinkedUnit('${src.uri}'); | 176 .map((String uriPipePath) => |
| 177 uriPipePath.substring(uriPipePath.indexOf('|') + 1)) |
| 178 .toList()); |
| 179 |
| 180 // Prepare the analysis driver. |
| 181 try { |
| 182 logger.run('Prepare analysis driver', () { |
| 183 _createAnalysisDriver(); |
| 184 }); |
| 185 } on ConflictingSummaryException catch (e) { |
| 186 errorSink.writeln('$e'); |
| 187 io.exitCode = ErrorSeverity.ERROR.ordinal; |
| 188 return ErrorSeverity.ERROR; |
204 } | 189 } |
205 | 190 |
206 // Build and assemble linked libraries. | 191 // Add sources. |
207 if (!options.buildSummaryOnlyUnlinked) { | 192 for (Uri uri in uriToFileMap.keys) { |
208 // Prepare URIs of unlinked units that should be linked. | 193 File file = uriToFileMap[uri]; |
209 var unlinkedUris = new Set<String>(); | 194 if (!file.exists) { |
210 for (var bundle in unlinkedBundles) { | 195 errorSink.writeln('File not found: ${file.path}'); |
211 unlinkedUris.addAll(bundle.unlinkedUnitUris); | 196 io.exitCode = ErrorSeverity.ERROR.ordinal; |
| 197 return ErrorSeverity.ERROR; |
212 } | 198 } |
213 for (var src in explicitSources) { | 199 Source source = new FileSource(file, uri); |
214 unlinkedUris.add('${src.uri}'); | 200 explicitSources.add(source); |
215 } | |
216 // Perform linking. | |
217 _computeLinkedLibraries(unlinkedUris); | |
218 assembler.recordDependencies(summaryDataStore); | |
219 } | 201 } |
220 | 202 |
221 // Write the whole package bundle. | 203 // Write summary. |
222 PackageBundleBuilder bundle = assembler.assemble(); | 204 assembler = new PackageBundleAssembler(); |
223 if (options.buildSummaryOutput != null) { | 205 if (_shouldOutputSummary) { |
224 io.File file = new io.File(options.buildSummaryOutput); | 206 await logger.runAsync('Build and write output summary', () async { |
225 file.writeAsBytesSync(bundle.toBuffer(), mode: io.FileMode.WRITE_ONLY); | 207 // Prepare all unlinked units. |
| 208 await logger.runAsync('Prepare unlinked units', () async { |
| 209 for (var src in explicitSources) { |
| 210 await _prepareUnlinkedUnit('${src.uri}'); |
| 211 } |
| 212 }); |
| 213 |
| 214 // Build and assemble linked libraries. |
| 215 if (!options.buildSummaryOnlyUnlinked) { |
| 216 // Prepare URIs of unlinked units that should be linked. |
| 217 var unlinkedUris = new Set<String>(); |
| 218 for (var bundle in unlinkedBundles) { |
| 219 unlinkedUris.addAll(bundle.unlinkedUnitUris); |
| 220 } |
| 221 for (var src in explicitSources) { |
| 222 unlinkedUris.add('${src.uri}'); |
| 223 } |
| 224 // Perform linking. |
| 225 _computeLinkedLibraries(unlinkedUris); |
| 226 assembler.recordDependencies(summaryDataStore); |
| 227 } |
| 228 |
| 229 // Write the whole package bundle. |
| 230 PackageBundleBuilder bundle = assembler.assemble(); |
| 231 if (options.buildSummaryOutput != null) { |
| 232 io.File file = new io.File(options.buildSummaryOutput); |
| 233 file.writeAsBytesSync(bundle.toBuffer(), |
| 234 mode: io.FileMode.WRITE_ONLY); |
| 235 } |
| 236 if (options.buildSummaryOutputSemantic != null) { |
| 237 bundle.flushInformative(); |
| 238 io.File file = new io.File(options.buildSummaryOutputSemantic); |
| 239 file.writeAsBytesSync(bundle.toBuffer(), |
| 240 mode: io.FileMode.WRITE_ONLY); |
| 241 } |
| 242 }); |
226 } | 243 } |
227 if (options.buildSummaryOutputSemantic != null) { | 244 |
228 bundle.flushInformative(); | 245 if (options.buildSummaryOnly) { |
229 io.File file = new io.File(options.buildSummaryOutputSemantic); | 246 return ErrorSeverity.NONE; |
230 file.writeAsBytesSync(bundle.toBuffer(), mode: io.FileMode.WRITE_ONLY); | 247 } else { |
| 248 // Process errors. |
| 249 await _printErrors(outputPath: options.buildAnalysisOutput); |
| 250 return await _computeMaxSeverity(); |
231 } | 251 } |
232 } | 252 }); |
233 | |
234 if (options.buildSummaryOnly) { | |
235 return ErrorSeverity.NONE; | |
236 } else { | |
237 // Process errors. | |
238 await _printErrors(outputPath: options.buildAnalysisOutput); | |
239 return await _computeMaxSeverity(); | |
240 } | |
241 } | 253 } |
242 | 254 |
243 /** | 255 /** |
244 * Compute linked libraries for the given [libraryUris] using the linked | 256 * Compute linked libraries for the given [libraryUris] using the linked |
245 * libraries of the [summaryDataStore] and unlinked units in [uriToUnit], and | 257 * libraries of the [summaryDataStore] and unlinked units in [uriToUnit], and |
246 * add them to the [assembler]. | 258 * add them to the [assembler]. |
247 */ | 259 */ |
248 void _computeLinkedLibraries(Set<String> libraryUris) { | 260 void _computeLinkedLibraries(Set<String> libraryUris) { |
249 LinkedLibrary getDependency(String absoluteUri) => | 261 logger.run('Link output summary', () { |
250 summaryDataStore.linkedMap[absoluteUri]; | 262 LinkedLibrary getDependency(String absoluteUri) => |
| 263 summaryDataStore.linkedMap[absoluteUri]; |
251 | 264 |
252 UnlinkedUnit getUnit(String absoluteUri) => | 265 UnlinkedUnit getUnit(String absoluteUri) => |
253 summaryDataStore.unlinkedMap[absoluteUri] ?? uriToUnit[absoluteUri]; | 266 summaryDataStore.unlinkedMap[absoluteUri] ?? uriToUnit[absoluteUri]; |
254 | 267 |
255 Map<String, LinkedLibraryBuilder> linkResult = link( | 268 Map<String, LinkedLibraryBuilder> linkResult = link( |
256 libraryUris, | 269 libraryUris, |
257 getDependency, | 270 getDependency, |
258 getUnit, | 271 getUnit, |
259 analysisDriver.declaredVariables.get, | 272 analysisDriver.declaredVariables.get, |
260 options.strongMode); | 273 options.strongMode); |
261 linkResult.forEach(assembler.addLinkedLibrary); | 274 linkResult.forEach(assembler.addLinkedLibrary); |
| 275 }); |
262 } | 276 } |
263 | 277 |
264 Future<ErrorSeverity> _computeMaxSeverity() async { | 278 Future<ErrorSeverity> _computeMaxSeverity() async { |
265 ErrorSeverity maxSeverity = ErrorSeverity.NONE; | 279 ErrorSeverity maxSeverity = ErrorSeverity.NONE; |
266 if (!options.buildSuppressExitCode) { | 280 if (!options.buildSuppressExitCode) { |
267 for (Source source in explicitSources) { | 281 for (Source source in explicitSources) { |
268 ErrorsResult result = await analysisDriver.getErrors(source.fullName); | 282 ErrorsResult result = await analysisDriver.getErrors(source.fullName); |
269 for (AnalysisError error in result.errors) { | 283 for (AnalysisError error in result.errors) { |
270 ErrorSeverity processedSeverity = determineProcessedSeverity( | 284 ErrorSeverity processedSeverity = determineProcessedSeverity( |
271 error, options, analysisDriver.analysisOptions); | 285 error, options, analysisDriver.analysisOptions); |
(...skipping 12 matching lines...) Expand all Loading... |
284 recordDependencyInfo: _shouldOutputSummary); | 298 recordDependencyInfo: _shouldOutputSummary); |
285 | 299 |
286 // Adds a bundle at `path` to `summaryDataStore`. | 300 // Adds a bundle at `path` to `summaryDataStore`. |
287 PackageBundle addBundle(String path) { | 301 PackageBundle addBundle(String path) { |
288 var bundle = | 302 var bundle = |
289 new PackageBundle.fromBuffer(new io.File(path).readAsBytesSync()); | 303 new PackageBundle.fromBuffer(new io.File(path).readAsBytesSync()); |
290 summaryDataStore.addBundle(path, bundle); | 304 summaryDataStore.addBundle(path, bundle); |
291 return bundle; | 305 return bundle; |
292 } | 306 } |
293 | 307 |
294 for (var path in options.buildSummaryInputs) { | 308 int numInputs = options.buildSummaryInputs.length + |
295 var bundle = addBundle(path); | 309 options.buildSummaryUnlinkedInputs.length; |
296 if (bundle.linkedLibraryUris.isEmpty && | 310 logger.run('Add $numInputs input summaries', () { |
297 bundle.unlinkedUnitUris.isNotEmpty) { | 311 for (var path in options.buildSummaryInputs) { |
298 throw new ArgumentError( | 312 var bundle = addBundle(path); |
299 'Got an unlinked summary for --build-summary-input at `$path`. ' | 313 if (bundle.linkedLibraryUris.isEmpty && |
300 'Unlinked summaries should be provided with the ' | 314 bundle.unlinkedUnitUris.isNotEmpty) { |
301 '--build-summary-unlinked-input argument.'); | 315 throw new ArgumentError( |
| 316 'Got an unlinked summary for --build-summary-input at `$path`. ' |
| 317 'Unlinked summaries should be provided with the ' |
| 318 '--build-summary-unlinked-input argument.'); |
| 319 } |
302 } | 320 } |
303 } | |
304 | 321 |
305 for (var path in options.buildSummaryUnlinkedInputs) { | 322 for (var path in options.buildSummaryUnlinkedInputs) { |
306 var bundle = addBundle(path); | 323 var bundle = addBundle(path); |
307 unlinkedBundles.add(bundle); | 324 unlinkedBundles.add(bundle); |
308 if (bundle.linkedLibraryUris.isNotEmpty) { | 325 if (bundle.linkedLibraryUris.isNotEmpty) { |
309 throw new ArgumentError( | 326 throw new ArgumentError( |
310 'Got a linked summary for --build-summary-input-unlinked at `$path`' | 327 'Got a linked summary for --build-summary-input-unlinked at `$path
`' |
311 '. Linked bundles should be provided with the ' | 328 '. Linked bundles should be provided with the ' |
312 '--build-summary-input argument.'); | 329 '--build-summary-input argument.'); |
| 330 } |
313 } | 331 } |
314 } | 332 }); |
315 | 333 |
316 DartSdk sdk; | 334 DartSdk sdk; |
317 PackageBundle sdkBundle; | 335 logger.run('Add SDK bundle', () { |
318 if (options.dartSdkSummaryPath != null) { | 336 PackageBundle sdkBundle; |
319 SummaryBasedDartSdk summarySdk = new SummaryBasedDartSdk( | 337 if (options.dartSdkSummaryPath != null) { |
320 options.dartSdkSummaryPath, options.strongMode); | 338 SummaryBasedDartSdk summarySdk = new SummaryBasedDartSdk( |
321 sdk = summarySdk; | 339 options.dartSdkSummaryPath, options.strongMode); |
322 sdkBundle = summarySdk.bundle; | 340 sdk = summarySdk; |
323 } else { | 341 sdkBundle = summarySdk.bundle; |
324 FolderBasedDartSdk dartSdk = new FolderBasedDartSdk(resourceProvider, | 342 } else { |
325 resourceProvider.getFolder(options.dartSdkPath), options.strongMode); | 343 FolderBasedDartSdk dartSdk = new FolderBasedDartSdk( |
326 dartSdk.analysisOptions = | 344 resourceProvider, |
327 Driver.createAnalysisOptionsForCommandLineOptions( | 345 resourceProvider.getFolder(options.dartSdkPath), |
328 resourceProvider, options); | 346 options.strongMode); |
329 dartSdk.useSummary = !options.buildSummaryOnly; | 347 dartSdk.analysisOptions = |
330 sdk = dartSdk; | 348 Driver.createAnalysisOptionsForCommandLineOptions( |
331 sdkBundle = dartSdk.getSummarySdkBundle(options.strongMode); | 349 resourceProvider, options); |
332 } | 350 dartSdk.useSummary = !options.buildSummaryOnly; |
| 351 sdk = dartSdk; |
| 352 sdkBundle = dartSdk.getSummarySdkBundle(options.strongMode); |
| 353 } |
333 | 354 |
334 // Include SDK bundle to avoid parsing SDK sources. | 355 // Include SDK bundle to avoid parsing SDK sources. |
335 summaryDataStore.addBundle(null, sdkBundle); | 356 summaryDataStore.addBundle(null, sdkBundle); |
| 357 }); |
336 | 358 |
337 var sourceFactory = new SourceFactory(<UriResolver>[ | 359 var sourceFactory = new SourceFactory(<UriResolver>[ |
338 new DartUriResolver(sdk), | 360 new DartUriResolver(sdk), |
339 new InSummaryUriResolver(resourceProvider, summaryDataStore), | 361 new InSummaryUriResolver(resourceProvider, summaryDataStore), |
340 new ExplicitSourceResolver(uriToFileMap) | 362 new ExplicitSourceResolver(uriToFileMap) |
341 ]); | 363 ]); |
342 | 364 |
343 analysisOptions = Driver.createAnalysisOptionsForCommandLineOptions( | 365 analysisOptions = Driver.createAnalysisOptionsForCommandLineOptions( |
344 resourceProvider, options); | 366 resourceProvider, options); |
345 | 367 |
346 PerformanceLog logger = new PerformanceLog(null); | |
347 AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler(logger); | 368 AnalysisDriverScheduler scheduler = new AnalysisDriverScheduler(logger); |
348 analysisDriver = new AnalysisDriver( | 369 analysisDriver = new AnalysisDriver( |
349 scheduler, | 370 scheduler, |
350 logger, | 371 logger, |
351 resourceProvider, | 372 resourceProvider, |
352 new MemoryByteStore(), | 373 new MemoryByteStore(), |
353 new FileContentOverlay(), | 374 new FileContentOverlay(), |
354 null, | 375 null, |
355 sourceFactory, | 376 sourceFactory, |
356 analysisOptions, | 377 analysisOptions, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(result.unit); | 427 UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(result.unit); |
407 uriToUnit[absoluteUri] = unlinkedUnit; | 428 uriToUnit[absoluteUri] = unlinkedUnit; |
408 assembler.addUnlinkedUnit(source, unlinkedUnit); | 429 assembler.addUnlinkedUnit(source, unlinkedUnit); |
409 } | 430 } |
410 | 431 |
411 /** | 432 /** |
412 * Print errors for all explicit sources. If [outputPath] is supplied, output | 433 * Print errors for all explicit sources. If [outputPath] is supplied, output |
413 * is sent to a new file at that path. | 434 * is sent to a new file at that path. |
414 */ | 435 */ |
415 Future<Null> _printErrors({String outputPath}) async { | 436 Future<Null> _printErrors({String outputPath}) async { |
416 StringBuffer buffer = new StringBuffer(); | 437 await logger.runAsync('Compute and print analysis errors', () async { |
417 var severityProcessor = (AnalysisError error) => | 438 StringBuffer buffer = new StringBuffer(); |
418 determineProcessedSeverity(error, options, analysisOptions); | 439 var severityProcessor = (AnalysisError error) => |
419 ErrorFormatter formatter = options.machineFormat | 440 determineProcessedSeverity(error, options, analysisOptions); |
420 ? new MachineErrorFormatter(buffer, options, stats, | 441 ErrorFormatter formatter = options.machineFormat |
421 severityProcessor: severityProcessor) | 442 ? new MachineErrorFormatter(buffer, options, stats, |
422 : new HumanErrorFormatter(buffer, options, stats, | 443 severityProcessor: severityProcessor) |
423 severityProcessor: severityProcessor); | 444 : new HumanErrorFormatter(buffer, options, stats, |
424 for (Source source in explicitSources) { | 445 severityProcessor: severityProcessor); |
425 var result = await analysisDriver.getErrors(source.fullName); | 446 for (Source source in explicitSources) { |
426 var errorInfo = new AnalysisErrorInfoImpl(result.errors, result.lineInfo); | 447 var result = await analysisDriver.getErrors(source.fullName); |
427 formatter.formatErrors([errorInfo]); | 448 var errorInfo = |
428 } | 449 new AnalysisErrorInfoImpl(result.errors, result.lineInfo); |
429 formatter.flush(); | 450 formatter.formatErrors([errorInfo]); |
430 if (!options.machineFormat) { | 451 } |
431 stats.print(buffer); | 452 formatter.flush(); |
432 } | 453 if (!options.machineFormat) { |
433 if (outputPath == null) { | 454 stats.print(buffer); |
434 StringSink sink = options.machineFormat ? errorSink : outSink; | 455 } |
435 sink.write(buffer); | 456 if (outputPath == null) { |
436 } else { | 457 StringSink sink = options.machineFormat ? errorSink : outSink; |
437 new io.File(outputPath).writeAsStringSync(buffer.toString()); | 458 sink.write(buffer); |
438 } | 459 } else { |
| 460 new io.File(outputPath).writeAsStringSync(buffer.toString()); |
| 461 } |
| 462 }); |
439 } | 463 } |
440 } | 464 } |
441 | 465 |
442 /** | 466 /** |
443 * Instances of the class [ExplicitSourceResolver] map URIs to files on disk | 467 * Instances of the class [ExplicitSourceResolver] map URIs to files on disk |
444 * using a fixed mapping provided at construction time. | 468 * using a fixed mapping provided at construction time. |
445 */ | 469 */ |
446 class ExplicitSourceResolver extends UriResolver { | 470 class ExplicitSourceResolver extends UriResolver { |
447 final Map<Uri, File> uriToFileMap; | 471 final Map<Uri, File> uriToFileMap; |
448 final Map<String, Uri> pathToUriMap; | 472 final Map<String, Uri> pathToUriMap; |
(...skipping 26 matching lines...) Expand all Loading... |
475 * Build the inverse mapping of [uriToSourceMap]. | 499 * Build the inverse mapping of [uriToSourceMap]. |
476 */ | 500 */ |
477 static Map<String, Uri> _computePathToUriMap(Map<Uri, File> uriToSourceMap) { | 501 static Map<String, Uri> _computePathToUriMap(Map<Uri, File> uriToSourceMap) { |
478 Map<String, Uri> pathToUriMap = <String, Uri>{}; | 502 Map<String, Uri> pathToUriMap = <String, Uri>{}; |
479 uriToSourceMap.forEach((Uri uri, File file) { | 503 uriToSourceMap.forEach((Uri uri, File file) { |
480 pathToUriMap[file.path] = uri; | 504 pathToUriMap[file.path] = uri; |
481 }); | 505 }); |
482 return pathToUriMap; | 506 return pathToUriMap; |
483 } | 507 } |
484 } | 508 } |
OLD | NEW |