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.driver; | 5 library analyzer_cli.src.driver; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:convert'; | 8 import 'dart:convert'; |
| 9 import 'dart:io' as io; | 9 import 'dart:io' as io; |
| 10 | 10 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 import 'package:analyzer/src/generated/source.dart'; | 31 import 'package:analyzer/src/generated/source.dart'; |
| 32 import 'package:analyzer/src/generated/source_io.dart'; | 32 import 'package:analyzer/src/generated/source_io.dart'; |
| 33 import 'package:analyzer/src/generated/utilities_general.dart' | 33 import 'package:analyzer/src/generated/utilities_general.dart' |
| 34 show PerformanceTag; | 34 show PerformanceTag; |
| 35 import 'package:analyzer/src/lint/registry.dart'; | 35 import 'package:analyzer/src/lint/registry.dart'; |
| 36 import 'package:analyzer/src/source/source_resource.dart'; | 36 import 'package:analyzer/src/source/source_resource.dart'; |
| 37 import 'package:analyzer/src/summary/idl.dart'; | 37 import 'package:analyzer/src/summary/idl.dart'; |
| 38 import 'package:analyzer/src/summary/package_bundle_reader.dart'; | 38 import 'package:analyzer/src/summary/package_bundle_reader.dart'; |
| 39 import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk; | 39 import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk; |
| 40 import 'package:analyzer/src/task/options.dart'; | 40 import 'package:analyzer/src/task/options.dart'; |
| 41 import 'package:analyzer_cli/src/analyzer_impl.dart'; | |
| 42 import 'package:analyzer_cli/src/build_mode.dart'; | |
| 43 import 'package:analyzer_cli/src/error_formatter.dart'; | |
| 44 import 'package:analyzer_cli/src/options.dart'; | |
| 45 import 'package:analyzer_cli/src/perf_report.dart'; | |
| 46 import 'package:analyzer_cli/starter.dart'; | |
| 47 import 'package:linter/src/rules.dart' as linter; | 41 import 'package:linter/src/rules.dart' as linter; |
| 48 import 'package:package_config/discovery.dart' as pkg_discovery; | 42 import 'package:package_config/discovery.dart' as pkg_discovery; |
| 49 import 'package:package_config/packages.dart' show Packages; | 43 import 'package:package_config/packages.dart' show Packages; |
| 50 import 'package:package_config/packages_file.dart' as pkgfile show parse; | 44 import 'package:package_config/packages_file.dart' as pkgfile show parse; |
| 51 import 'package:package_config/src/packages_impl.dart' show MapPackages; | 45 import 'package:package_config/src/packages_impl.dart' show MapPackages; |
| 52 import 'package:path/path.dart' as path; | 46 import 'package:path/path.dart' as path; |
| 53 import 'package:plugin/manager.dart'; | 47 import 'package:plugin/manager.dart'; |
| 54 import 'package:plugin/plugin.dart'; | 48 import 'package:plugin/plugin.dart'; |
| 55 import 'package:yaml/yaml.dart'; | 49 import 'package:yaml/yaml.dart'; |
| 56 | 50 |
| 51 import '../starter.dart' show CommandLineStarter; | |
| 52 import 'analyzer_impl.dart'; | |
| 53 import 'build_mode.dart'; | |
| 54 import 'error_formatter.dart'; | |
| 55 import 'options.dart'; | |
| 56 import 'perf_report.dart'; | |
| 57 | |
| 57 /// Shared IO sink for standard error reporting. | 58 /// Shared IO sink for standard error reporting. |
| 58 /// | 59 /// |
| 59 /// *Visible for testing.* | 60 /// *Visible for testing.* |
| 60 StringSink errorSink = io.stderr; | 61 StringSink errorSink = io.stderr; |
| 61 | 62 |
| 62 /// Shared IO sink for standard out reporting. | 63 /// Shared IO sink for standard out reporting. |
| 63 /// | 64 /// |
| 64 /// *Visible for testing.* | 65 /// *Visible for testing.* |
| 65 StringSink outSink = io.stdout; | 66 StringSink outSink = io.stdout; |
| 66 | 67 |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 152 io.exitCode = severity.ordinal; | 153 io.exitCode = severity.ordinal; |
| 153 } | 154 } |
| 154 } | 155 } |
| 155 | 156 |
| 156 if (_context != null) { | 157 if (_context != null) { |
| 157 _analyzedFileCount += _context.sources.length; | 158 _analyzedFileCount += _context.sources.length; |
| 158 } | 159 } |
| 159 | 160 |
| 160 if (options.perfReport != null) { | 161 if (options.perfReport != null) { |
| 161 String json = makePerfReport( | 162 String json = makePerfReport( |
| 162 startTime, currentTimeMillis(), options, _analyzedFileCount, stats); | 163 startTime, currentTimeMillis, options, _analyzedFileCount, stats); |
| 163 new io.File(options.perfReport).writeAsStringSync(json); | 164 new io.File(options.perfReport).writeAsStringSync(json); |
| 164 } | 165 } |
| 165 } | 166 } |
| 166 | 167 |
| 167 Future<ErrorSeverity> _analyzeAll(CommandLineOptions options) async { | 168 Future<ErrorSeverity> _analyzeAll(CommandLineOptions options) async { |
| 168 PerformanceTag previous = _analyzeAllTag.makeCurrent(); | 169 PerformanceTag previous = _analyzeAllTag.makeCurrent(); |
| 169 try { | 170 try { |
| 170 return await _analyzeAllImpl(options); | 171 return await _analyzeAllImpl(options); |
| 171 } finally { | 172 } finally { |
| 172 previous.makeCurrent(); | 173 previous.makeCurrent(); |
| 173 } | 174 } |
| 174 } | 175 } |
| 175 | 176 |
| 176 /// Perform analysis according to the given [options]. | 177 /// Perform analysis according to the given [options]. |
| 177 Future<ErrorSeverity> _analyzeAllImpl(CommandLineOptions options) async { | 178 Future<ErrorSeverity> _analyzeAllImpl(CommandLineOptions options) async { |
| 178 if (!options.machineFormat) { | 179 if (!options.machineFormat) { |
| 179 outSink.writeln("Analyzing ${options.sourceFiles}..."); | 180 List<String> fileNames = options.sourceFiles.map((String file) { |
| 181 file = path.normalize(file); | |
| 182 if (file == '.') { | |
| 183 file = path.basename(path.current); | |
| 184 } else if (file == '..') { | |
| 185 file = path.basename(path.normalize(path.absolute(file))); | |
| 186 } | |
| 187 return file; | |
| 188 }).toList(); | |
| 189 | |
| 190 outSink.writeln("Analyzing ${fileNames.join(', ')}..."); | |
| 180 } | 191 } |
| 181 | 192 |
| 182 // Create a context, or re-use the previous one. | 193 // Create a context, or re-use the previous one. |
| 183 try { | 194 try { |
| 184 _createAnalysisContext(options); | 195 _createAnalysisContext(options); |
| 185 } on _DriverError catch (error) { | 196 } on _DriverError catch (error) { |
| 186 outSink.writeln(error.msg); | 197 outSink.writeln(error.msg); |
| 187 return ErrorSeverity.ERROR; | 198 return ErrorSeverity.ERROR; |
| 188 } | 199 } |
| 189 | 200 |
| 190 // Add all the files to be analyzed en masse to the context. Skip any | 201 // Add all the files to be analyzed en masse to the context. Skip any |
| 191 // files that were added earlier (whether explicitly or implicitly) to | 202 // files that were added earlier (whether explicitly or implicitly) to |
| 192 // avoid causing those files to be unnecessarily re-read. | 203 // avoid causing those files to be unnecessarily re-read. |
| 193 Set<Source> knownSources = context.sources.toSet(); | 204 Set<Source> knownSources = context.sources.toSet(); |
| 194 List<Source> sourcesToAnalyze = <Source>[]; | 205 Set<Source> sourcesToAnalyze = new Set<Source>(); |
| 195 ChangeSet changeSet = new ChangeSet(); | 206 ChangeSet changeSet = new ChangeSet(); |
| 196 for (String sourcePath in options.sourceFiles) { | 207 for (String sourcePath in options.sourceFiles) { |
| 197 sourcePath = sourcePath.trim(); | 208 sourcePath = sourcePath.trim(); |
| 198 | 209 |
| 199 // Collect files for analysis. | 210 // Collect files for analysis. |
| 200 // Note that these files will all be analyzed in the same context. | 211 // Note that these files will all be analyzed in the same context. |
| 201 // This should be updated when the ContextManager re-work is complete | 212 // This should be updated when the ContextManager re-work is complete |
| 202 // (See: https://github.com/dart-lang/sdk/issues/24133) | 213 // (See: https://github.com/dart-lang/sdk/issues/24133) |
| 203 Iterable<io.File> files = _collectFiles(sourcePath); | 214 Iterable<io.File> files = _collectFiles(sourcePath); |
| 204 if (files.isEmpty) { | 215 if (files.isEmpty) { |
| 205 errorSink.writeln('No dart files found at: $sourcePath'); | 216 errorSink.writeln('No dart files found at: $sourcePath'); |
| 206 io.exitCode = ErrorSeverity.ERROR.ordinal; | 217 io.exitCode = ErrorSeverity.ERROR.ordinal; |
| 207 return ErrorSeverity.ERROR; | 218 return ErrorSeverity.ERROR; |
| 208 } | 219 } |
| 209 | 220 |
| 210 for (io.File file in files) { | 221 for (io.File file in files) { |
| 211 Source source = _computeLibrarySource(file.absolute.path); | 222 Source source = _computeLibrarySource(file.absolute.path); |
| 212 if (!knownSources.contains(source)) { | 223 if (!knownSources.contains(source)) { |
| 213 changeSet.addedSource(source); | 224 changeSet.addedSource(source); |
| 214 } | 225 } |
| 215 sourcesToAnalyze.add(source); | 226 sourcesToAnalyze.add(source); |
| 216 } | 227 } |
| 217 | 228 |
| 218 if (analysisDriver != null) { | 229 files.forEach((file) { |
|
Brian Wilkerson
2017/02/19 22:52:17
It looks like this CL is also removing the non-dri
devoncarew
2017/02/21 04:30:47
No - it's unintentional. I had a fair amount of ch
| |
| 219 files.forEach((file) { | 230 analysisDriver.addFile(file.path); |
| 220 analysisDriver.addFile(file.path); | 231 }); |
| 221 }); | |
| 222 } else { | |
| 223 context.applyChanges(changeSet); | |
| 224 } | |
| 225 } | 232 } |
| 226 | 233 |
| 227 // Analyze the libraries. | 234 // Analyze the libraries. |
| 228 ErrorSeverity allResult = ErrorSeverity.NONE; | 235 ErrorSeverity allResult = ErrorSeverity.NONE; |
| 229 var libUris = <Uri>[]; | 236 List<Uri> libUris = <Uri>[]; |
| 230 var parts = <Source>[]; | 237 Set<Source> partSources = new Set<Source>(); |
| 238 | |
| 231 for (Source source in sourcesToAnalyze) { | 239 for (Source source in sourcesToAnalyze) { |
| 232 SourceKind sourceKind = analysisDriver != null | 240 SourceKind sourceKind = analysisDriver != null |
| 233 ? await analysisDriver.getSourceKind(source.fullName) | 241 ? await analysisDriver.getSourceKind(source.fullName) |
| 234 : context.computeKindOf(source); | 242 : context.computeKindOf(source); |
| 235 if (sourceKind == SourceKind.PART) { | 243 if (sourceKind == SourceKind.PART) { |
| 236 parts.add(source); | 244 partSources.add(source); |
| 237 continue; | 245 continue; |
| 238 } | 246 } |
| 247 // TODO(devoncarew): Analyzing each source individually causes errors to | |
| 248 // be reported multiple times (#25697). | |
| 239 ErrorSeverity status = await _runAnalyzer(source, options); | 249 ErrorSeverity status = await _runAnalyzer(source, options); |
| 240 allResult = allResult.max(status); | 250 allResult = allResult.max(status); |
| 241 libUris.add(source.uri); | 251 libUris.add(source.uri); |
| 242 } | 252 } |
| 243 | 253 |
| 244 // Check that each part has a corresponding source in the input list. | 254 // Check that each part has a corresponding source in the input list. |
| 245 for (Source part in parts) { | 255 for (Source partSource in partSources) { |
| 246 bool found = false; | 256 bool found = false; |
| 247 if (analysisDriver != null) { | 257 if (analysisDriver != null) { |
| 248 var partFile = analysisDriver.fsState.getFileForPath(part.fullName); | 258 var partFile = |
| 259 analysisDriver.fsState.getFileForPath(partSource.fullName); | |
| 249 if (libUris.contains(partFile.library?.uri)) { | 260 if (libUris.contains(partFile.library?.uri)) { |
| 250 found = true; | 261 found = true; |
| 251 } | 262 } |
| 252 } else { | 263 } else { |
| 253 for (var lib in context.getLibrariesContaining(part)) { | 264 for (var lib in context.getLibrariesContaining(partSource)) { |
| 254 if (libUris.contains(lib.uri)) { | 265 if (libUris.contains(lib.uri)) { |
| 255 found = true; | 266 found = true; |
| 256 } | 267 } |
| 257 } | 268 } |
| 258 } | 269 } |
| 259 if (!found) { | 270 if (!found) { |
| 260 errorSink.writeln("${part.fullName} is a part and cannot be analyzed."); | 271 errorSink.writeln( |
| 272 "${partSource.fullName} is a part and cannot be analyzed."); | |
| 261 errorSink.writeln("Please pass in a library that contains this part."); | 273 errorSink.writeln("Please pass in a library that contains this part."); |
| 262 io.exitCode = ErrorSeverity.ERROR.ordinal; | 274 io.exitCode = ErrorSeverity.ERROR.ordinal; |
| 263 allResult = allResult.max(ErrorSeverity.ERROR); | 275 allResult = allResult.max(ErrorSeverity.ERROR); |
| 264 } | 276 } |
| 265 } | 277 } |
| 266 | 278 |
| 267 if (!options.machineFormat) { | 279 if (!options.machineFormat) { |
| 268 stats.print(outSink); | 280 stats.print(outSink); |
| 269 } | 281 } |
| 270 | 282 |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 461 if (packageUriResolver != null) { | 473 if (packageUriResolver != null) { |
| 462 resolvers.add(packageUriResolver); | 474 resolvers.add(packageUriResolver); |
| 463 } | 475 } |
| 464 | 476 |
| 465 // Finally files. | 477 // Finally files. |
| 466 resolvers.add(new file_system.ResourceUriResolver(resourceProvider)); | 478 resolvers.add(new file_system.ResourceUriResolver(resourceProvider)); |
| 467 | 479 |
| 468 return new SourceFactory(resolvers, packageInfo.packages); | 480 return new SourceFactory(resolvers, packageInfo.packages); |
| 469 } | 481 } |
| 470 | 482 |
| 483 // TODO(devoncarew): This needs to respect analysis_options excludes. | |
| 484 | |
| 471 /// Collect all analyzable files at [filePath], recursively if it's a | 485 /// Collect all analyzable files at [filePath], recursively if it's a |
| 472 /// directory, ignoring links. | 486 /// directory, ignoring links. |
| 473 Iterable<io.File> _collectFiles(String filePath) { | 487 Iterable<io.File> _collectFiles(String filePath) { |
| 474 List<io.File> files = <io.File>[]; | 488 List<io.File> files = <io.File>[]; |
| 475 io.File file = new io.File(filePath); | 489 io.File file = new io.File(filePath); |
| 476 if (file.existsSync()) { | 490 if (file.existsSync()) { |
| 477 files.add(file); | 491 files.add(file); |
| 478 } else { | 492 } else { |
| 479 io.Directory directory = new io.Directory(filePath); | 493 io.Directory directory = new io.Directory(filePath); |
| 480 if (directory.existsSync()) { | 494 if (directory.existsSync()) { |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 681 | 695 |
| 682 ExtensionManager manager = new ExtensionManager(); | 696 ExtensionManager manager = new ExtensionManager(); |
| 683 manager.processPlugins(plugins); | 697 manager.processPlugins(plugins); |
| 684 | 698 |
| 685 linter.registerLintRules(); | 699 linter.registerLintRules(); |
| 686 } | 700 } |
| 687 | 701 |
| 688 /// Analyze a single source. | 702 /// Analyze a single source. |
| 689 Future<ErrorSeverity> _runAnalyzer( | 703 Future<ErrorSeverity> _runAnalyzer( |
| 690 Source source, CommandLineOptions options) async { | 704 Source source, CommandLineOptions options) async { |
| 691 int startTime = currentTimeMillis(); | 705 int startTime = currentTimeMillis; |
| 692 AnalyzerImpl analyzer = new AnalyzerImpl(_context.analysisOptions, _context, | 706 AnalyzerImpl analyzer = new AnalyzerImpl(_context.analysisOptions, _context, |
| 693 analysisDriver, source, options, stats, startTime); | 707 analysisDriver, source, options, stats, startTime); |
| 694 ErrorSeverity errorSeverity = await analyzer.analyze(); | 708 ErrorSeverity errorSeverity = await analyzer.analyze(); |
| 695 if (errorSeverity == ErrorSeverity.ERROR) { | 709 if (errorSeverity == ErrorSeverity.ERROR) { |
| 696 io.exitCode = errorSeverity.ordinal; | 710 io.exitCode = errorSeverity.ordinal; |
| 697 } | 711 } |
| 698 if (options.warningsAreFatal && errorSeverity == ErrorSeverity.WARNING) { | 712 if (options.warningsAreFatal && errorSeverity == ErrorSeverity.WARNING) { |
| 699 io.exitCode = errorSeverity.ordinal; | 713 io.exitCode = errorSeverity.ordinal; |
| 700 } | 714 } |
| 701 return errorSeverity; | 715 return errorSeverity; |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 945 for (var package in packages) { | 959 for (var package in packages) { |
| 946 var packageName = path.basename(package.path); | 960 var packageName = path.basename(package.path); |
| 947 var realPath = package.resolveSymbolicLinksSync(); | 961 var realPath = package.resolveSymbolicLinksSync(); |
| 948 result[packageName] = [ | 962 result[packageName] = [ |
| 949 PhysicalResourceProvider.INSTANCE.getFolder(realPath) | 963 PhysicalResourceProvider.INSTANCE.getFolder(realPath) |
| 950 ]; | 964 ]; |
| 951 } | 965 } |
| 952 return result; | 966 return result; |
| 953 } | 967 } |
| 954 } | 968 } |
| OLD | NEW |