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
# generate and analyze our large sample app
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
GSUTIL=$HOME/google-cloud-sdk/bin/gsutil
......
......@@ -38,7 +38,6 @@ import 'src/commands/test.dart';
import 'src/commands/trace.dart';
import 'src/commands/update_packages.dart';
import 'src/commands/upgrade.dart';
import 'src/commands/watch.dart';
import 'src/device.dart';
import 'src/doctor.dart';
import 'src/globals.dart';
......@@ -85,8 +84,7 @@ Future<Null> main(List<String> args) async {
..addCommand(new TestCommand())
..addCommand(new TraceCommand())
..addCommand(new UpdatePackagesCommand(hidden: !verboseHelp))
..addCommand(new UpgradeCommand())
..addCommand(new WatchCommand(verboseHelp: verboseHelp));
..addCommand(new UpgradeCommand());
return Chain.capture/*<Future<Null>>*/(() async {
// Initialize globals.
......
......@@ -2,40 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:io';
import 'package:args/args.dart';
import 'package:path/path.dart' as path;
import '../base/utils.dart';
import '../cache.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
bool get shouldRunPub {
// If they're not analyzing the current project.
if (!argResults['current-package'])
return false;
/// Common behavior for `flutter analyze` and `flutter analyze --watch`
abstract class AnalyzeBase {
/// The parsed argument results for execution.
final ArgResults argResults;
// Or we're not in a project directory.
if (!new File('pubspec.yaml').existsSync())
return false;
AnalyzeBase(this.argResults);
return super.shouldRunPub;
}
/// Called by [AnalyzeCommand] to start the analysis process.
Future<int> analyze();
void dumpErrors(Iterable<String> errors) {
if (argResults['write'] != null) {
......@@ -65,4 +50,19 @@ abstract class AnalysisCommand extends FlutterCommand {
}
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';
import 'dart:convert';
import 'dart:io';
import 'package:args/args.dart';
import 'package:path/path.dart' as path;
import '../base/logger.dart';
......@@ -13,16 +14,12 @@ import '../base/utils.dart';
import '../cache.dart';
import '../dart/sdk.dart';
import '../globals.dart';
import 'analysis_common.dart';
import 'analyze_base.dart';
class WatchCommand extends AnalysisCommand {
WatchCommand({bool verboseHelp: false}) : super(verboseHelp: verboseHelp);
class AnalyzeContinuously extends AnalyzeBase {
final List<Directory> repoAnalysisEntryPoints;
@override
String get name => 'watch';
@override
String get description => 'Analyze the project\'s Dart code continuously, watching the filesystem for changes.';
AnalyzeContinuously(ArgResults argResults, this.repoAnalysisEntryPoints) : super(argResults);
String analysisTarget;
bool firstAnalysis = true;
......@@ -33,11 +30,11 @@ class WatchCommand extends AnalysisCommand {
Status analysisStatus;
@override
Future<int> runCommand() async {
Future<int> analyze() async {
List<String> directories;
if (argResults['flutter-repo']) {
directories = runner.getRepoAnalysisEntryPoints().map((Directory dir) => dir.path).toList();
directories = repoAnalysisEntryPoints.map((Directory dir) => dir.path).toList();
analysisTarget = 'Flutter repository';
printTrace('Analyzing Flutter repository:');
for (String projectPath in directories)
......
This diff is collapsed.
......@@ -6,7 +6,7 @@ import 'dart:async';
import 'dart:io';
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/sdk.dart';
import 'package:flutter_tools/src/runner/flutter_command_runner.dart';
......@@ -29,7 +29,7 @@ void main() {
return server?.dispose();
});
group('watch', () {
group('analyze --watch', () {
testUsingContext('AnalysisServer success', () async {
_createSampleProject(tempDir);
......
......@@ -5,7 +5,7 @@
import 'dart:io';
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:path/path.dart' as path;
import 'package:test/test.dart';
......@@ -27,27 +27,26 @@ void main() {
group('analyze', () {
testUsingContext('inRepo', () {
AnalyzeCommand cmd = new AnalyzeCommand();
// Absolute paths
expect(cmd.inRepo(<String>[tempDir.path]), isFalse);
expect(cmd.inRepo(<String>[path.join(tempDir.path, 'foo')]), isFalse);
expect(cmd.inRepo(<String>[Cache.flutterRoot]), isTrue);
expect(cmd.inRepo(<String>[path.join(Cache.flutterRoot, 'foo')]), isTrue);
expect(inRepo(<String>[tempDir.path]), isFalse);
expect(inRepo(<String>[path.join(tempDir.path, 'foo')]), isFalse);
expect(inRepo(<String>[Cache.flutterRoot]), isTrue);
expect(inRepo(<String>[path.join(Cache.flutterRoot, 'foo')]), isTrue);
// Relative paths
String oldWorkingDirectory = path.current;
try {
Directory.current = Cache.flutterRoot;
expect(cmd.inRepo(<String>['.']), isTrue);
expect(cmd.inRepo(<String>['foo']), isTrue);
expect(inRepo(<String>['.']), isTrue);
expect(inRepo(<String>['foo']), isTrue);
Directory.current = tempDir.path;
expect(cmd.inRepo(<String>['.']), isFalse);
expect(cmd.inRepo(<String>['foo']), isFalse);
expect(inRepo(<String>['.']), isFalse);
expect(inRepo(<String>['foo']), isFalse);
} finally {
Directory.current = oldWorkingDirectory;
}
// Ensure no exceptions
cmd.inRepo(null);
cmd.inRepo(<String>[]);
inRepo(null);
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