Commit 9f673ad4 authored by Dan Rubel's avatar Dan Rubel Committed by GitHub

flutter analyze --watch (#6093)

parent 67f97b45
...@@ -45,7 +45,7 @@ SRC_ROOT=$PWD ...@@ -45,7 +45,7 @@ SRC_ROOT=$PWD
# generate and analyze our large sample app # generate and analyze our large sample app
dart dev/tools/mega_gallery.dart dart dev/tools/mega_gallery.dart
(cd dev/benchmarks/mega_gallery; flutter watch --benchmark) (cd dev/benchmarks/mega_gallery; flutter analyze --watch --benchmark)
if [ -n "$COVERAGE_FLAG" ]; then if [ -n "$COVERAGE_FLAG" ]; then
GSUTIL=$HOME/google-cloud-sdk/bin/gsutil GSUTIL=$HOME/google-cloud-sdk/bin/gsutil
......
...@@ -38,7 +38,6 @@ import 'src/commands/test.dart'; ...@@ -38,7 +38,6 @@ import 'src/commands/test.dart';
import 'src/commands/trace.dart'; import 'src/commands/trace.dart';
import 'src/commands/update_packages.dart'; import 'src/commands/update_packages.dart';
import 'src/commands/upgrade.dart'; import 'src/commands/upgrade.dart';
import 'src/commands/watch.dart';
import 'src/device.dart'; import 'src/device.dart';
import 'src/doctor.dart'; import 'src/doctor.dart';
import 'src/globals.dart'; import 'src/globals.dart';
...@@ -85,8 +84,7 @@ Future<Null> main(List<String> args) async { ...@@ -85,8 +84,7 @@ Future<Null> main(List<String> args) async {
..addCommand(new TestCommand()) ..addCommand(new TestCommand())
..addCommand(new TraceCommand()) ..addCommand(new TraceCommand())
..addCommand(new UpdatePackagesCommand(hidden: !verboseHelp)) ..addCommand(new UpdatePackagesCommand(hidden: !verboseHelp))
..addCommand(new UpgradeCommand()) ..addCommand(new UpgradeCommand());
..addCommand(new WatchCommand(verboseHelp: verboseHelp));
return Chain.capture/*<Future<Null>>*/(() async { return Chain.capture/*<Future<Null>>*/(() async {
// Initialize globals. // Initialize globals.
......
...@@ -2,40 +2,25 @@ ...@@ -2,40 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:args/args.dart';
import 'package:path/path.dart' as path;
import '../base/utils.dart'; import '../base/utils.dart';
import '../cache.dart';
import '../globals.dart'; import '../globals.dart';
import '../runner/flutter_command.dart';
/// Common behavior for `flutter analyze` and `flutter watch`
abstract class AnalysisCommand extends FlutterCommand {
AnalysisCommand({bool verboseHelp: false}) {
argParser.addFlag('flutter-repo', help: 'Include all the examples and tests from the Flutter repository.', defaultsTo: false);
argParser.addFlag('current-directory', help: 'Include all the Dart files in the current directory, if any.', defaultsTo: true);
argParser.addFlag('current-package', help: 'Include the lib/main.dart file from the current directory, if any.', defaultsTo: true);
argParser.addFlag('dartdocs', help: 'List every public member that is lacking documentation (only examines files in the Flutter repository).', defaultsTo: false);
argParser.addOption('write', valueHelp: 'file', help: 'Also output the results to a file.');
argParser.addOption('dart-sdk', valueHelp: 'path-to-sdk', help: 'The path to the Dart SDK.', hide: !verboseHelp);
// Hidden option to enable a benchmarking mode.
argParser.addFlag('benchmark', negatable: false, hide: !verboseHelp, help: 'Also output the analysis time');
usesPubOption();
}
@override /// Common behavior for `flutter analyze` and `flutter analyze --watch`
bool get shouldRunPub { abstract class AnalyzeBase {
// If they're not analyzing the current project. /// The parsed argument results for execution.
if (!argResults['current-package']) final ArgResults argResults;
return false;
// Or we're not in a project directory. AnalyzeBase(this.argResults);
if (!new File('pubspec.yaml').existsSync())
return false;
return super.shouldRunPub; /// Called by [AnalyzeCommand] to start the analysis process.
} Future<int> analyze();
void dumpErrors(Iterable<String> errors) { void dumpErrors(Iterable<String> errors) {
if (argResults['write'] != null) { if (argResults['write'] != null) {
...@@ -65,4 +50,19 @@ abstract class AnalysisCommand extends FlutterCommand { ...@@ -65,4 +50,19 @@ abstract class AnalysisCommand extends FlutterCommand {
} }
bool get isBenchmarking => argResults['benchmark']; bool get isBenchmarking => argResults['benchmark'];
}
/// Return `true` if [fileList] contains a path that resides inside the Flutter repository.
/// If [fileList] is empty, then return `true` if the current directory resides inside the Flutter repository.
bool inRepo(List<String> fileList) {
if (fileList == null || fileList.isEmpty)
fileList = <String>[path.current];
String root = path.normalize(path.absolute(Cache.flutterRoot));
String prefix = root + Platform.pathSeparator;
for (String file in fileList) {
file = path.normalize(path.absolute(file));
if (file == root || file.startsWith(prefix))
return true;
}
return false;
} }
\ No newline at end of file
...@@ -6,6 +6,7 @@ import 'dart:async'; ...@@ -6,6 +6,7 @@ import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:args/args.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import '../base/logger.dart'; import '../base/logger.dart';
...@@ -13,16 +14,12 @@ import '../base/utils.dart'; ...@@ -13,16 +14,12 @@ import '../base/utils.dart';
import '../cache.dart'; import '../cache.dart';
import '../dart/sdk.dart'; import '../dart/sdk.dart';
import '../globals.dart'; import '../globals.dart';
import 'analysis_common.dart'; import 'analyze_base.dart';
class WatchCommand extends AnalysisCommand { class AnalyzeContinuously extends AnalyzeBase {
WatchCommand({bool verboseHelp: false}) : super(verboseHelp: verboseHelp); final List<Directory> repoAnalysisEntryPoints;
@override AnalyzeContinuously(ArgResults argResults, this.repoAnalysisEntryPoints) : super(argResults);
String get name => 'watch';
@override
String get description => 'Analyze the project\'s Dart code continuously, watching the filesystem for changes.';
String analysisTarget; String analysisTarget;
bool firstAnalysis = true; bool firstAnalysis = true;
...@@ -33,11 +30,11 @@ class WatchCommand extends AnalysisCommand { ...@@ -33,11 +30,11 @@ class WatchCommand extends AnalysisCommand {
Status analysisStatus; Status analysisStatus;
@override @override
Future<int> runCommand() async { Future<int> analyze() async {
List<String> directories; List<String> directories;
if (argResults['flutter-repo']) { if (argResults['flutter-repo']) {
directories = runner.getRepoAnalysisEntryPoints().map((Directory dir) => dir.path).toList(); directories = repoAnalysisEntryPoints.map((Directory dir) => dir.path).toList();
analysisTarget = 'Flutter repository'; analysisTarget = 'Flutter repository';
printTrace('Analyzing Flutter repository:'); printTrace('Analyzing Flutter repository:');
for (String projectPath in directories) for (String projectPath in directories)
......
This diff is collapsed.
...@@ -6,7 +6,7 @@ import 'dart:async'; ...@@ -6,7 +6,7 @@ import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/commands/watch.dart'; import 'package:flutter_tools/src/commands/analyze_continuously.dart';
import 'package:flutter_tools/src/dart/pub.dart'; import 'package:flutter_tools/src/dart/pub.dart';
import 'package:flutter_tools/src/dart/sdk.dart'; import 'package:flutter_tools/src/dart/sdk.dart';
import 'package:flutter_tools/src/runner/flutter_command_runner.dart'; import 'package:flutter_tools/src/runner/flutter_command_runner.dart';
...@@ -29,7 +29,7 @@ void main() { ...@@ -29,7 +29,7 @@ void main() {
return server?.dispose(); return server?.dispose();
}); });
group('watch', () { group('analyze --watch', () {
testUsingContext('AnalysisServer success', () async { testUsingContext('AnalysisServer success', () async {
_createSampleProject(tempDir); _createSampleProject(tempDir);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
import 'dart:io'; import 'dart:io';
import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/analyze.dart'; import 'package:flutter_tools/src/commands/analyze_base.dart';
import 'package:flutter_tools/src/runner/flutter_command_runner.dart'; import 'package:flutter_tools/src/runner/flutter_command_runner.dart';
import 'package:path/path.dart' as path; import 'package:path/path.dart' as path;
import 'package:test/test.dart'; import 'package:test/test.dart';
...@@ -27,27 +27,26 @@ void main() { ...@@ -27,27 +27,26 @@ void main() {
group('analyze', () { group('analyze', () {
testUsingContext('inRepo', () { testUsingContext('inRepo', () {
AnalyzeCommand cmd = new AnalyzeCommand();
// Absolute paths // Absolute paths
expect(cmd.inRepo(<String>[tempDir.path]), isFalse); expect(inRepo(<String>[tempDir.path]), isFalse);
expect(cmd.inRepo(<String>[path.join(tempDir.path, 'foo')]), isFalse); expect(inRepo(<String>[path.join(tempDir.path, 'foo')]), isFalse);
expect(cmd.inRepo(<String>[Cache.flutterRoot]), isTrue); expect(inRepo(<String>[Cache.flutterRoot]), isTrue);
expect(cmd.inRepo(<String>[path.join(Cache.flutterRoot, 'foo')]), isTrue); expect(inRepo(<String>[path.join(Cache.flutterRoot, 'foo')]), isTrue);
// Relative paths // Relative paths
String oldWorkingDirectory = path.current; String oldWorkingDirectory = path.current;
try { try {
Directory.current = Cache.flutterRoot; Directory.current = Cache.flutterRoot;
expect(cmd.inRepo(<String>['.']), isTrue); expect(inRepo(<String>['.']), isTrue);
expect(cmd.inRepo(<String>['foo']), isTrue); expect(inRepo(<String>['foo']), isTrue);
Directory.current = tempDir.path; Directory.current = tempDir.path;
expect(cmd.inRepo(<String>['.']), isFalse); expect(inRepo(<String>['.']), isFalse);
expect(cmd.inRepo(<String>['foo']), isFalse); expect(inRepo(<String>['foo']), isFalse);
} finally { } finally {
Directory.current = oldWorkingDirectory; Directory.current = oldWorkingDirectory;
} }
// Ensure no exceptions // Ensure no exceptions
cmd.inRepo(null); inRepo(null);
cmd.inRepo(<String>[]); inRepo(<String>[]);
}); });
}); });
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment