Chromium Code Reviews| 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.package_analyzer; | 5 library analyzer_cli.src.package_analyzer; |
|
scheglov
2016/03/23 01:11:50
Do you want to rename this file?
e.g. build_mode.d
Paul Berry
2016/03/23 03:28:02
Done.
| |
| 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:analyzer/dart/element/element.dart'; | 10 import 'package:analyzer/dart/element/element.dart'; |
| 11 import 'package:analyzer/file_system/file_system.dart'; | 11 import 'package:analyzer/file_system/file_system.dart'; |
| 12 import 'package:analyzer/file_system/physical_file_system.dart'; | 12 import 'package:analyzer/file_system/physical_file_system.dart'; |
| 13 import 'package:analyzer/source/package_map_resolver.dart'; | |
| 14 import 'package:analyzer/src/generated/engine.dart'; | 13 import 'package:analyzer/src/generated/engine.dart'; |
| 15 import 'package:analyzer/src/generated/error.dart'; | 14 import 'package:analyzer/src/generated/error.dart'; |
| 16 import 'package:analyzer/src/generated/java_io.dart'; | 15 import 'package:analyzer/src/generated/java_io.dart'; |
| 17 import 'package:analyzer/src/generated/sdk_io.dart'; | 16 import 'package:analyzer/src/generated/sdk_io.dart'; |
| 18 import 'package:analyzer/src/generated/source.dart'; | 17 import 'package:analyzer/src/generated/source.dart'; |
| 19 import 'package:analyzer/src/generated/source_io.dart'; | 18 import 'package:analyzer/src/generated/source_io.dart'; |
| 20 import 'package:analyzer/src/summary/format.dart'; | 19 import 'package:analyzer/src/summary/format.dart'; |
| 21 import 'package:analyzer/src/summary/package_bundle_reader.dart'; | 20 import 'package:analyzer/src/summary/package_bundle_reader.dart'; |
| 22 import 'package:analyzer/src/summary/summarize_elements.dart'; | 21 import 'package:analyzer/src/summary/summarize_elements.dart'; |
| 23 import 'package:analyzer_cli/src/analyzer_impl.dart'; | 22 import 'package:analyzer_cli/src/analyzer_impl.dart'; |
| 24 import 'package:analyzer_cli/src/driver.dart'; | 23 import 'package:analyzer_cli/src/driver.dart'; |
| 25 import 'package:analyzer_cli/src/error_formatter.dart'; | 24 import 'package:analyzer_cli/src/error_formatter.dart'; |
| 26 import 'package:analyzer_cli/src/options.dart'; | 25 import 'package:analyzer_cli/src/options.dart'; |
| 27 import 'package:path/path.dart' as pathos; | |
| 28 | 26 |
| 29 /** | 27 /** |
| 30 * The hermetic whole package analyzer. | 28 * Analyzer used when the "--build-mode" option is supplied. |
| 31 */ | 29 */ |
| 32 class PackageAnalyzer { | 30 class BuildMode { |
| 33 final CommandLineOptions options; | 31 final CommandLineOptions options; |
| 34 final AnalysisStats stats; | 32 final AnalysisStats stats; |
| 35 | 33 |
| 36 String packagePath; | |
| 37 String packageLibPath; | |
| 38 | |
| 39 final ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE; | 34 final ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE; |
| 40 InternalAnalysisContext context; | 35 InternalAnalysisContext context; |
| 36 Map<Uri, JavaFile> uriToFileMap; | |
| 41 final List<Source> explicitSources = <Source>[]; | 37 final List<Source> explicitSources = <Source>[]; |
| 42 | 38 |
| 43 PackageAnalyzer(this.options, this.stats); | 39 BuildMode(this.options, this.stats); |
| 44 | 40 |
| 45 /** | 41 /** |
| 46 * Perform package analysis according to the given [options]. | 42 * Perform package analysis according to the given [options]. |
| 47 */ | 43 */ |
| 48 ErrorSeverity analyze() { | 44 ErrorSeverity analyze() { |
| 49 packagePath = resourceProvider.pathContext.normalize(resourceProvider | 45 // Write initial progress message. |
| 50 .pathContext | 46 if (!options.machineFormat) { |
| 51 .join(io.Directory.current.absolute.path, options.packageModePath)); | 47 outSink.writeln("Analyzing sources ${options.sourceFiles}..."); |
| 52 packageLibPath = resourceProvider.pathContext.join(packagePath, 'lib'); | 48 } |
| 53 if (packageLibPath == null) { | 49 |
| 54 errorSink.writeln('--package-mode-path must be set to the root ' | 50 // Create the URI to file map. |
| 55 'folder of the package to analyze.'); | 51 uriToFileMap = _createUriToFileMap(options.sourceFiles); |
| 52 if (uriToFileMap == null) { | |
| 56 io.exitCode = ErrorSeverity.ERROR.ordinal; | 53 io.exitCode = ErrorSeverity.ERROR.ordinal; |
| 57 return ErrorSeverity.ERROR; | 54 return ErrorSeverity.ERROR; |
| 58 } | 55 } |
| 59 | 56 |
| 60 // Write the progress message. | |
| 61 if (!options.machineFormat) { | |
| 62 outSink.writeln("Analyzing sources ${options.sourceFiles}..."); | |
| 63 } | |
| 64 | |
| 65 // Prepare the analysis context. | 57 // Prepare the analysis context. |
| 66 _createContext(); | 58 _createContext(); |
| 67 | 59 |
| 68 // Add sources. | 60 // Add sources. |
| 69 ChangeSet changeSet = new ChangeSet(); | 61 ChangeSet changeSet = new ChangeSet(); |
| 70 for (String path in options.sourceFiles) { | 62 for (Uri uri in uriToFileMap.keys) { |
| 71 if (AnalysisEngine.isDartFileName(path)) { | 63 JavaFile file = uriToFileMap[uri]; |
| 72 File file = resourceProvider.getFile(path); | 64 if (!file.exists()) { |
| 73 if (!file.exists) { | 65 errorSink.writeln('File not found: ${file.getPath()}'); |
| 74 errorSink.writeln('File not found: $path'); | 66 io.exitCode = ErrorSeverity.ERROR.ordinal; |
| 75 io.exitCode = ErrorSeverity.ERROR.ordinal; | 67 return ErrorSeverity.ERROR; |
| 76 return ErrorSeverity.ERROR; | |
| 77 } | |
| 78 Source source = _createSourceInContext(file); | |
| 79 explicitSources.add(source); | |
| 80 changeSet.addedSource(source); | |
| 81 } | 68 } |
| 69 Source source = new FileBasedSource(file, uri); | |
| 70 explicitSources.add(source); | |
| 71 changeSet.addedSource(source); | |
| 82 } | 72 } |
| 83 context.applyChanges(changeSet); | 73 context.applyChanges(changeSet); |
| 84 | 74 |
| 85 if (!options.packageSummaryOnly) { | 75 if (!options.buildSummaryOnly) { |
| 86 // Perform full analysis. | 76 // Perform full analysis. |
| 87 while (true) { | 77 while (true) { |
| 88 AnalysisResult analysisResult = context.performAnalysisTask(); | 78 AnalysisResult analysisResult = context.performAnalysisTask(); |
| 89 if (!analysisResult.hasMoreWork) { | 79 if (!analysisResult.hasMoreWork) { |
| 90 break; | 80 break; |
| 91 } | 81 } |
| 92 } | 82 } |
| 93 } | 83 } |
| 94 | 84 |
| 95 // Write summary for Dart libraries. | 85 // Write summary. |
| 96 if (options.packageSummaryOutput != null) { | 86 if (options.buildSummaryOutput != null) { |
| 97 PackageBundleAssembler assembler = new PackageBundleAssembler(); | 87 PackageBundleAssembler assembler = new PackageBundleAssembler(); |
| 98 for (Source source in explicitSources) { | 88 for (Source source in explicitSources) { |
| 99 if (context.computeKindOf(source) != SourceKind.LIBRARY) { | 89 if (context.computeKindOf(source) != SourceKind.LIBRARY) { |
| 100 continue; | 90 continue; |
| 101 } | 91 } |
| 102 if (pathos.isWithin(packageLibPath, source.fullName)) { | 92 LibraryElement libraryElement = context.computeLibraryElement(source); |
| 103 LibraryElement libraryElement = context.computeLibraryElement(source); | 93 assembler.serializeLibraryElement(libraryElement); |
| 104 assembler.serializeLibraryElement(libraryElement); | |
| 105 } | |
| 106 } | 94 } |
| 107 // Write the whole package bundle. | 95 // Write the whole package bundle. |
| 108 PackageBundleBuilder sdkBundle = assembler.assemble(); | 96 PackageBundleBuilder sdkBundle = assembler.assemble(); |
| 109 io.File file = new io.File(options.packageSummaryOutput); | 97 io.File file = new io.File(options.buildSummaryOutput); |
| 110 file.writeAsBytesSync(sdkBundle.toBuffer(), mode: io.FileMode.WRITE_ONLY); | 98 file.writeAsBytesSync(sdkBundle.toBuffer(), mode: io.FileMode.WRITE_ONLY); |
| 111 } | 99 } |
| 112 | 100 |
| 113 if (options.packageSummaryOnly) { | 101 if (options.buildSummaryOnly) { |
| 114 return ErrorSeverity.NONE; | 102 return ErrorSeverity.NONE; |
| 115 } else { | 103 } else { |
| 116 // Process errors. | 104 // Process errors. |
| 117 _printErrors(); | 105 _printErrors(outputPath: options.buildAnalysisOutput); |
| 118 return _computeMaxSeverity(); | 106 return _computeMaxSeverity(); |
| 119 } | 107 } |
| 120 } | 108 } |
| 121 | 109 |
| 122 ErrorSeverity _computeMaxSeverity() { | 110 ErrorSeverity _computeMaxSeverity() { |
| 123 ErrorSeverity maxSeverity = ErrorSeverity.NONE; | 111 ErrorSeverity maxSeverity = ErrorSeverity.NONE; |
| 124 for (Source source in explicitSources) { | 112 if (!options.buildSuppressExitCode) { |
| 125 AnalysisErrorInfo errorInfo = context.getErrors(source); | 113 for (Source source in explicitSources) { |
| 126 for (AnalysisError error in errorInfo.errors) { | 114 AnalysisErrorInfo errorInfo = context.getErrors(source); |
| 127 ProcessedSeverity processedSeverity = | 115 for (AnalysisError error in errorInfo.errors) { |
| 128 AnalyzerImpl.processError(error, options, context); | 116 ProcessedSeverity processedSeverity = |
| 129 if (processedSeverity != null) { | 117 AnalyzerImpl.processError(error, options, context); |
| 130 maxSeverity = maxSeverity.max(processedSeverity.severity); | 118 if (processedSeverity != null) { |
| 119 maxSeverity = maxSeverity.max(processedSeverity.severity); | |
| 120 } | |
| 131 } | 121 } |
| 132 } | 122 } |
| 133 } | 123 } |
| 134 return maxSeverity; | 124 return maxSeverity; |
| 135 } | 125 } |
| 136 | 126 |
| 137 void _createContext() { | 127 void _createContext() { |
| 138 DirectoryBasedDartSdk sdk = | 128 DirectoryBasedDartSdk sdk = |
| 139 new DirectoryBasedDartSdk(new JavaFile(options.dartSdkPath)); | 129 new DirectoryBasedDartSdk(new JavaFile(options.dartSdkPath)); |
| 140 | 130 |
| 131 // Read the summaries. | |
| 132 SummaryDataStore summaryDataStore = | |
| 133 new SummaryDataStore(options.buildSummaryInputs); | |
| 134 | |
| 141 // Create the context. | 135 // Create the context. |
| 142 context = AnalysisEngine.instance.createAnalysisContext(); | 136 context = AnalysisEngine.instance.createAnalysisContext(); |
| 143 context.sourceFactory = new SourceFactory(<UriResolver>[ | 137 context.sourceFactory = new SourceFactory(<UriResolver>[ |
| 144 new DartUriResolver(sdk), | 138 new DartUriResolver(sdk), |
| 145 new InSummaryPackageUriResolver(options.packageSummaryInputs), | 139 new InSummaryPackageUriResolver(summaryDataStore), |
| 146 new PackageMapUriResolver(resourceProvider, <String, List<Folder>>{ | 140 new ExplicitSourceResolver(uriToFileMap) |
| 147 options.packageName: <Folder>[ | |
| 148 resourceProvider.getFolder(packageLibPath) | |
| 149 ], | |
| 150 }), | |
| 151 new FileUriResolver() | |
| 152 ]); | 141 ]); |
| 153 | 142 |
| 154 // Set context options. | 143 // Set context options. |
| 155 Driver.setAnalysisContextOptions( | 144 Driver.setAnalysisContextOptions( |
| 156 context, options, (AnalysisOptionsImpl contextOptions) {}); | 145 context, options, (AnalysisOptionsImpl contextOptions) {}); |
| 157 | 146 |
| 158 // Configure using summaries. | 147 // Configure using summaries. |
| 159 sdk.useSummary = true; | 148 sdk.useSummary = true; |
| 160 context.typeProvider = sdk.context.typeProvider; | 149 context.typeProvider = sdk.context.typeProvider; |
| 161 context.resultProvider = | 150 context.resultProvider = |
| 162 new InputPackagesResultProvider(context, options.packageSummaryInputs); | 151 new InputPackagesResultProvider(context, summaryDataStore); |
| 163 } | 152 } |
| 164 | 153 |
| 165 /** | 154 /** |
| 166 * Create and return a source representing the given [file]. | 155 * Print errors for all explicit sources. If [outputPath] is supplied, output |
| 156 * is sent to a new file at that path. | |
| 167 */ | 157 */ |
| 168 Source _createSourceInContext(File file) { | 158 void _printErrors({String outputPath}) { |
| 169 Source source = file.createSource(); | 159 StringBuffer buffer = new StringBuffer(); |
| 170 if (context == null) { | |
| 171 return source; | |
| 172 } | |
| 173 Uri uri = context.sourceFactory.restoreUri(source); | |
| 174 return file.createSource(uri); | |
| 175 } | |
| 176 | |
| 177 /** | |
| 178 * Print errors for all explicit sources. | |
| 179 */ | |
| 180 void _printErrors() { | |
| 181 StringSink sink = options.machineFormat ? errorSink : outSink; | |
| 182 ErrorFormatter formatter = new ErrorFormatter( | 160 ErrorFormatter formatter = new ErrorFormatter( |
| 183 sink, | 161 buffer, |
| 184 options, | 162 options, |
| 185 stats, | 163 stats, |
| 186 (AnalysisError error) => | 164 (AnalysisError error) => |
| 187 AnalyzerImpl.processError(error, options, context)); | 165 AnalyzerImpl.processError(error, options, context)); |
| 188 for (Source source in explicitSources) { | 166 for (Source source in explicitSources) { |
| 189 AnalysisErrorInfo errorInfo = context.getErrors(source); | 167 AnalysisErrorInfo errorInfo = context.getErrors(source); |
| 190 formatter.formatErrors([errorInfo]); | 168 formatter.formatErrors([errorInfo]); |
| 191 } | 169 } |
| 192 if (!options.machineFormat) { | 170 if (!options.machineFormat) { |
| 193 stats.print(sink); | 171 stats.print(buffer); |
| 172 } | |
| 173 if (outputPath == null) { | |
| 174 StringSink sink = options.machineFormat ? errorSink : outSink; | |
| 175 sink.write(buffer); | |
| 176 } else { | |
| 177 new io.File(outputPath).writeAsStringSync(buffer.toString()); | |
| 194 } | 178 } |
| 195 } | 179 } |
| 180 | |
| 181 /** | |
| 182 * Convert the list of input source files to a map from URI to source file | |
| 183 * path. If an error occurs, report the error and return null. | |
| 184 */ | |
| 185 static Map<Uri, JavaFile> _createUriToFileMap(List<String> sourceFiles) { | |
|
scheglov
2016/03/23 01:11:50
Naming the argument source "files" is a little mis
Paul Berry
2016/03/23 03:28:02
Done.
| |
| 186 Map<Uri, JavaFile> uriToFileMap = <Uri, JavaFile>{}; | |
| 187 for (String sourceFile in sourceFiles) { | |
| 188 int pipeIndex = sourceFile.indexOf('|'); | |
| 189 if (pipeIndex == -1) { | |
| 190 // TODO(paulberry): add the ability to guess the URI from the path. | |
| 191 errorSink.writeln( | |
| 192 'Illegal input file (must be "\$uri|\$path"): $sourceFile'); | |
| 193 return null; | |
| 194 } | |
| 195 Uri uri = Uri.parse(sourceFile.substring(0, pipeIndex)); | |
| 196 String path = sourceFile.substring(pipeIndex + 1); | |
| 197 uriToFileMap[uri] = new JavaFile(path); | |
| 198 } | |
| 199 return uriToFileMap; | |
| 200 } | |
| 196 } | 201 } |
| OLD | NEW |