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'; | 9 import 'dart:io'; |
| 10 | 10 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 26 import 'package:analyzer/src/generated/java_engine.dart'; | 26 import 'package:analyzer/src/generated/java_engine.dart'; |
| 27 import 'package:analyzer/src/generated/java_io.dart'; | 27 import 'package:analyzer/src/generated/java_io.dart'; |
| 28 import 'package:analyzer/src/generated/sdk_io.dart'; | 28 import 'package:analyzer/src/generated/sdk_io.dart'; |
| 29 import 'package:analyzer/src/generated/source.dart'; | 29 import 'package:analyzer/src/generated/source.dart'; |
| 30 import 'package:analyzer/src/generated/source_io.dart'; | 30 import 'package:analyzer/src/generated/source_io.dart'; |
| 31 import 'package:analyzer/src/generated/utilities_general.dart' | 31 import 'package:analyzer/src/generated/utilities_general.dart' |
| 32 show PerformanceTag; | 32 show PerformanceTag; |
| 33 import 'package:analyzer/src/services/lint.dart'; | 33 import 'package:analyzer/src/services/lint.dart'; |
| 34 import 'package:analyzer/src/task/options.dart'; | 34 import 'package:analyzer/src/task/options.dart'; |
| 35 import 'package:analyzer_cli/src/analyzer_impl.dart'; | 35 import 'package:analyzer_cli/src/analyzer_impl.dart'; |
| 36 import 'package:analyzer_cli/src/error_formatter.dart'; | |
| 36 import 'package:analyzer_cli/src/options.dart'; | 37 import 'package:analyzer_cli/src/options.dart'; |
| 37 import 'package:analyzer_cli/src/package_analyzer.dart'; | 38 import 'package:analyzer_cli/src/package_analyzer.dart'; |
| 38 import 'package:analyzer_cli/src/perf_report.dart'; | 39 import 'package:analyzer_cli/src/perf_report.dart'; |
| 39 import 'package:analyzer_cli/starter.dart'; | 40 import 'package:analyzer_cli/starter.dart'; |
| 40 import 'package:linter/src/plugin/linter_plugin.dart'; | 41 import 'package:linter/src/plugin/linter_plugin.dart'; |
| 41 import 'package:package_config/discovery.dart' as pkgDiscovery; | 42 import 'package:package_config/discovery.dart' as pkgDiscovery; |
| 42 import 'package:package_config/packages.dart' show Packages; | 43 import 'package:package_config/packages.dart' show Packages; |
| 43 import 'package:package_config/packages_file.dart' as pkgfile show parse; | 44 import 'package:package_config/packages_file.dart' as pkgfile show parse; |
| 44 import 'package:package_config/src/packages_impl.dart' show MapPackages; | 45 import 'package:package_config/src/packages_impl.dart' show MapPackages; |
| 45 import 'package:path/path.dart' as path; | 46 import 'package:path/path.dart' as path; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 /// If [_context] is not `null`, the [CommandLineOptions] that guided its | 83 /// If [_context] is not `null`, the [CommandLineOptions] that guided its |
| 83 /// creation. | 84 /// creation. |
| 84 CommandLineOptions _previousOptions; | 85 CommandLineOptions _previousOptions; |
| 85 | 86 |
| 86 @override | 87 @override |
| 87 EmbeddedResolverProvider embeddedUriResolverProvider; | 88 EmbeddedResolverProvider embeddedUriResolverProvider; |
| 88 | 89 |
| 89 @override | 90 @override |
| 90 ResolverProvider packageResolverProvider; | 91 ResolverProvider packageResolverProvider; |
| 91 | 92 |
| 93 /// Collected analysis statistics. | |
| 94 final AnalysisStats stats = new AnalysisStats(); | |
| 95 | |
| 92 /// This Driver's current analysis context. | 96 /// This Driver's current analysis context. |
| 93 /// | 97 /// |
| 94 /// *Visible for testing.* | 98 /// *Visible for testing.* |
| 95 AnalysisContext get context => _context; | 99 AnalysisContext get context => _context; |
| 96 | 100 |
| 97 @override | 101 @override |
| 98 void set userDefinedPlugins(List<Plugin> plugins) { | 102 void set userDefinedPlugins(List<Plugin> plugins) { |
| 99 _userDefinedPlugins = plugins == null ? <Plugin>[] : plugins; | 103 _userDefinedPlugins = plugins ?? <Plugin>[]; |
| 100 } | 104 } |
| 101 | 105 |
| 102 @override | 106 @override |
| 103 void start(List<String> args) { | 107 void start(List<String> args) { |
| 104 int startTime = new DateTime.now().millisecondsSinceEpoch; | 108 int startTime = new DateTime.now().millisecondsSinceEpoch; |
| 105 | 109 |
| 106 StringUtilities.INTERNER = new MappedInterner(); | 110 StringUtilities.INTERNER = new MappedInterner(); |
| 107 | 111 |
| 108 _processPlugins(); | 112 _processPlugins(); |
| 109 | 113 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 try { | 159 try { |
| 156 _createAnalysisContext(options); | 160 _createAnalysisContext(options); |
| 157 } on _DriverError catch (error) { | 161 } on _DriverError catch (error) { |
| 158 outSink.writeln(error.msg); | 162 outSink.writeln(error.msg); |
| 159 return ErrorSeverity.ERROR; | 163 return ErrorSeverity.ERROR; |
| 160 } | 164 } |
| 161 | 165 |
| 162 // Add all the files to be analyzed en masse to the context. Skip any | 166 // Add all the files to be analyzed en masse to the context. Skip any |
| 163 // files that were added earlier (whether explicitly or implicitly) to | 167 // files that were added earlier (whether explicitly or implicitly) to |
| 164 // avoid causing those files to be unnecessarily re-read. | 168 // avoid causing those files to be unnecessarily re-read. |
| 165 Set<Source> knownSources = _context.sources.toSet(); | 169 Set<Source> knownSources = context.sources.toSet(); |
| 166 List<Source> sourcesToAnalyze = <Source>[]; | 170 List<Source> sourcesToAnalyze = <Source>[]; |
| 167 ChangeSet changeSet = new ChangeSet(); | 171 ChangeSet changeSet = new ChangeSet(); |
| 168 for (String sourcePath in options.sourceFiles) { | 172 for (String sourcePath in options.sourceFiles) { |
| 169 sourcePath = sourcePath.trim(); | 173 sourcePath = sourcePath.trim(); |
| 170 // Check that file exists. | 174 |
| 171 if (!new File(sourcePath).existsSync()) { | 175 // Collect files for analysis. |
| 172 errorSink.writeln('File not found: $sourcePath'); | 176 // Note that these files will all be analyzed in the same context. |
| 177 // This should be updated when the ContextManager re-work is complete | |
| 178 // (See: https://github.com/dart-lang/sdk/issues/24133) | |
| 179 Iterable<File> files = _collectFiles(sourcePath); | |
| 180 if (files.isEmpty) { | |
| 181 errorSink.writeln('No dart files found at: $sourcePath'); | |
| 173 exitCode = ErrorSeverity.ERROR.ordinal; | 182 exitCode = ErrorSeverity.ERROR.ordinal; |
| 174 //Fail fast; don't analyze more files | |
| 175 return ErrorSeverity.ERROR; | 183 return ErrorSeverity.ERROR; |
| 176 } | 184 } |
| 177 // Check that file is Dart file. | 185 |
| 178 if (!AnalysisEngine.isDartFileName(sourcePath)) { | 186 for (File file in files) { |
| 179 errorSink.writeln('$sourcePath is not a Dart file'); | 187 Source source = _computeLibrarySource(file.absolute.path); |
| 180 exitCode = ErrorSeverity.ERROR.ordinal; | 188 if (!knownSources.contains(source)) { |
| 181 // Fail fast; don't analyze more files. | 189 changeSet.addedSource(source); |
| 182 return ErrorSeverity.ERROR; | 190 sourcesToAnalyze.add(source); |
| 191 } | |
| 183 } | 192 } |
| 184 Source source = _computeLibrarySource(sourcePath); | |
| 185 if (!knownSources.contains(source)) { | |
| 186 changeSet.addedSource(source); | |
| 187 } | |
| 188 sourcesToAnalyze.add(source); | |
| 189 } | 193 } |
| 190 _context.applyChanges(changeSet); | 194 context.applyChanges(changeSet); |
| 191 | 195 |
| 192 // Analyze the libraries. | 196 // Analyze the libraries. |
| 193 ErrorSeverity allResult = ErrorSeverity.NONE; | 197 ErrorSeverity allResult = ErrorSeverity.NONE; |
| 194 var libUris = <Uri>[]; | 198 var libUris = <Uri>[]; |
| 195 var parts = <Source>[]; | 199 var parts = <Source>[]; |
| 196 for (Source source in sourcesToAnalyze) { | 200 for (Source source in sourcesToAnalyze) { |
| 197 if (context.computeKindOf(source) == SourceKind.PART) { | 201 if (context.computeKindOf(source) == SourceKind.PART) { |
| 198 parts.add(source); | 202 parts.add(source); |
| 199 continue; | 203 continue; |
| 200 } | 204 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 212 } | 216 } |
| 213 } | 217 } |
| 214 if (!found) { | 218 if (!found) { |
| 215 errorSink.writeln("${part.fullName} is a part and cannot be analyzed."); | 219 errorSink.writeln("${part.fullName} is a part and cannot be analyzed."); |
| 216 errorSink.writeln("Please pass in a library that contains this part."); | 220 errorSink.writeln("Please pass in a library that contains this part."); |
| 217 exitCode = ErrorSeverity.ERROR.ordinal; | 221 exitCode = ErrorSeverity.ERROR.ordinal; |
| 218 allResult = allResult.max(ErrorSeverity.ERROR); | 222 allResult = allResult.max(ErrorSeverity.ERROR); |
| 219 } | 223 } |
| 220 } | 224 } |
| 221 | 225 |
| 226 if (!options.machineFormat) { | |
| 227 stats.print(outSink); | |
| 228 } | |
| 229 | |
| 222 return allResult; | 230 return allResult; |
| 223 } | 231 } |
| 224 | 232 |
| 225 /// Perform package analysis according to the given [options]. | 233 /// Perform package analysis according to the given [options]. |
| 226 ErrorSeverity _analyzePackage(CommandLineOptions options) { | 234 ErrorSeverity _analyzePackage(CommandLineOptions options) { |
| 227 return _analyzeAllTag.makeCurrentWhile(() { | 235 return _analyzeAllTag.makeCurrentWhile(() { |
| 228 return new PackageAnalyzer(options).analyze(); | 236 return new PackageAnalyzer(options, stats).analyze(); |
| 229 }); | 237 }); |
| 230 } | 238 } |
| 231 | 239 |
| 232 /// Determine whether the context created during a previous call to | 240 /// Determine whether the context created during a previous call to |
| 233 /// [_analyzeAll] can be re-used in order to analyze using [options]. | 241 /// [_analyzeAll] can be re-used in order to analyze using [options]. |
| 234 bool _canContextBeReused(CommandLineOptions options) { | 242 bool _canContextBeReused(CommandLineOptions options) { |
| 235 // TODO(paulberry): add a command-line option that disables context re-use. | 243 // TODO(paulberry): add a command-line option that disables context re-use. |
| 236 if (_context == null) { | 244 if (_context == null) { |
| 237 return false; | 245 return false; |
| 238 } | 246 } |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 444 if (packageUriResolver != null) { | 452 if (packageUriResolver != null) { |
| 445 resolvers.add(packageUriResolver); | 453 resolvers.add(packageUriResolver); |
| 446 } | 454 } |
| 447 | 455 |
| 448 // Finally files. | 456 // Finally files. |
| 449 resolvers.add(new FileUriResolver()); | 457 resolvers.add(new FileUriResolver()); |
| 450 | 458 |
| 451 return new SourceFactory(resolvers, packages); | 459 return new SourceFactory(resolvers, packages); |
| 452 } | 460 } |
| 453 | 461 |
| 462 /// Collect all analyzable files at [filePath], recursively if it's a | |
| 463 /// directory, ignoring links. | |
| 464 Iterable<File> _collectFiles(String filePath) { | |
| 465 List<File> files = <File>[]; | |
| 466 File file = new File(filePath); | |
| 467 if (file.existsSync()) { | |
| 468 files.add(file); | |
| 469 } else { | |
| 470 Directory directory = new Directory(filePath); | |
| 471 if (directory.existsSync()) { | |
| 472 for (FileSystemEntity entry | |
| 473 in directory.listSync(recursive: true, followLinks: false)) { | |
| 474 String relative = path.relative(entry.path, from: directory.path); | |
| 475 if (AnalysisEngine.isDartFileName(entry.path) && | |
| 476 !_isInHiddenDir(relative)) { | |
| 477 files.add(entry); | |
| 478 } | |
| 479 } | |
| 480 } | |
| 481 } | |
| 482 return files; | |
| 483 } | |
| 484 | |
| 454 /// Convert the given [sourcePath] (which may be relative to the current | 485 /// Convert the given [sourcePath] (which may be relative to the current |
| 455 /// working directory) to a [Source] object that can be fed to the analysis | 486 /// working directory) to a [Source] object that can be fed to the analysis |
| 456 /// context. | 487 /// context. |
| 457 Source _computeLibrarySource(String sourcePath) { | 488 Source _computeLibrarySource(String sourcePath) { |
| 458 sourcePath = _normalizeSourcePath(sourcePath); | 489 sourcePath = _normalizeSourcePath(sourcePath); |
| 459 JavaFile sourceFile = new JavaFile(sourcePath); | 490 JavaFile sourceFile = new JavaFile(sourcePath); |
| 460 Source source = sdk.fromFileUri(sourceFile.toURI()); | 491 Source source = sdk.fromFileUri(sourceFile.toURI()); |
| 461 if (source != null) { | 492 if (source != null) { |
| 462 return source; | 493 return source; |
| 463 } | 494 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 518 Map<String, List<fileSystem.Folder>> folderMap = | 549 Map<String, List<fileSystem.Folder>> folderMap = |
| 519 new Map<String, List<fileSystem.Folder>>(); | 550 new Map<String, List<fileSystem.Folder>>(); |
| 520 packages.asMap().forEach((String packagePath, Uri uri) { | 551 packages.asMap().forEach((String packagePath, Uri uri) { |
| 521 folderMap[packagePath] = [ | 552 folderMap[packagePath] = [ |
| 522 PhysicalResourceProvider.INSTANCE.getFolder(path.fromUri(uri)) | 553 PhysicalResourceProvider.INSTANCE.getFolder(path.fromUri(uri)) |
| 523 ]; | 554 ]; |
| 524 }); | 555 }); |
| 525 return folderMap; | 556 return folderMap; |
| 526 } | 557 } |
| 527 | 558 |
| 559 /// Returns `true` if this relative path is a hidden directory. | |
| 560 bool _isInHiddenDir(String relative) => | |
| 561 path.split(relative).any((part) => part.startsWith(".")); | |
|
Brian Wilkerson
2016/03/16 20:42:52
Does this need to worry about having ".." as a par
pquitslund
2016/03/16 20:55:41
Good eye. In general maybe, but I think we're saf
| |
| 562 | |
| 528 void _processPlugins() { | 563 void _processPlugins() { |
| 529 List<Plugin> plugins = <Plugin>[]; | 564 List<Plugin> plugins = <Plugin>[]; |
| 530 plugins.addAll(AnalysisEngine.instance.requiredPlugins); | 565 plugins.addAll(AnalysisEngine.instance.requiredPlugins); |
| 531 plugins.add(AnalysisEngine.instance.commandLinePlugin); | 566 plugins.add(AnalysisEngine.instance.commandLinePlugin); |
| 532 plugins.add(AnalysisEngine.instance.optionsPlugin); | 567 plugins.add(AnalysisEngine.instance.optionsPlugin); |
| 533 plugins.add(linterPlugin); | 568 plugins.add(linterPlugin); |
| 534 plugins.addAll(_userDefinedPlugins); | 569 plugins.addAll(_userDefinedPlugins); |
| 535 | 570 |
| 536 ExtensionManager manager = new ExtensionManager(); | 571 ExtensionManager manager = new ExtensionManager(); |
| 537 manager.processPlugins(plugins); | 572 manager.processPlugins(plugins); |
| 538 } | 573 } |
| 539 | 574 |
| 540 /// Analyze a single source. | 575 /// Analyze a single source. |
| 541 ErrorSeverity _runAnalyzer(Source source, CommandLineOptions options) { | 576 ErrorSeverity _runAnalyzer(Source source, CommandLineOptions options) { |
| 542 int startTime = currentTimeMillis(); | 577 int startTime = currentTimeMillis(); |
| 543 AnalyzerImpl analyzer = | 578 AnalyzerImpl analyzer = |
| 544 new AnalyzerImpl(_context, source, options, startTime); | 579 new AnalyzerImpl(_context, source, options, stats, startTime); |
| 545 var errorSeverity = analyzer.analyzeSync(); | 580 var errorSeverity = analyzer.analyzeSync(); |
| 546 if (errorSeverity == ErrorSeverity.ERROR) { | 581 if (errorSeverity == ErrorSeverity.ERROR) { |
| 547 exitCode = errorSeverity.ordinal; | 582 exitCode = errorSeverity.ordinal; |
| 548 } | 583 } |
| 549 if (options.warningsAreFatal && errorSeverity == ErrorSeverity.WARNING) { | 584 if (options.warningsAreFatal && errorSeverity == ErrorSeverity.WARNING) { |
| 550 exitCode = errorSeverity.ordinal; | 585 exitCode = errorSeverity.ordinal; |
| 551 } | 586 } |
| 552 return errorSeverity; | 587 return errorSeverity; |
| 553 } | 588 } |
| 554 | 589 |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 742 for (var package in packages) { | 777 for (var package in packages) { |
| 743 var packageName = path.basename(package.path); | 778 var packageName = path.basename(package.path); |
| 744 var realPath = package.resolveSymbolicLinksSync(); | 779 var realPath = package.resolveSymbolicLinksSync(); |
| 745 result[packageName] = [ | 780 result[packageName] = [ |
| 746 PhysicalResourceProvider.INSTANCE.getFolder(realPath) | 781 PhysicalResourceProvider.INSTANCE.getFolder(realPath) |
| 747 ]; | 782 ]; |
| 748 } | 783 } |
| 749 return result; | 784 return result; |
| 750 } | 785 } |
| 751 } | 786 } |
| OLD | NEW |