Unverified Commit 09dec7f5 authored by Devon Carew's avatar Devon Carew Committed by GitHub

re-write flutter analyze to use the analysis server (#16979)

re-write flutter analyze (the single-shot and --flutter-repo) to use the analysis server
parent ca94bfdf
...@@ -79,7 +79,7 @@ analyzer. There are two main ways to run it. In either case you will ...@@ -79,7 +79,7 @@ analyzer. There are two main ways to run it. In either case you will
want to run `flutter update-packages` first, or you will get bogus want to run `flutter update-packages` first, or you will get bogus
error messages about core classes like Offset from `dart:ui`. error messages about core classes like Offset from `dart:ui`.
For a one-off, use `flutter analyze --flutter-repo`. This uses the `analysis_options_repo.yaml` file For a one-off, use `flutter analyze --flutter-repo`. This uses the `analysis_options.yaml` file
at the root of the repository for its configuration. at the root of the repository for its configuration.
For continuous analysis, use `flutter analyze --flutter-repo --watch`. This uses normal For continuous analysis, use `flutter analyze --flutter-repo --watch`. This uses normal
......
...@@ -9,22 +9,18 @@ ...@@ -9,22 +9,18 @@
# #
# There are four similar analysis options files in the flutter repos: # There are four similar analysis options files in the flutter repos:
# - analysis_options.yaml (this file) # - analysis_options.yaml (this file)
# - analysis_options_repo.yaml
# - packages/flutter/lib/analysis_options_user.yaml # - packages/flutter/lib/analysis_options_user.yaml
# - https://github.com/flutter/plugins/blob/master/analysis_options.yaml # - https://github.com/flutter/plugins/blob/master/analysis_options.yaml
# - https://github.com/flutter/engine/blob/master/analysis_options.yaml
# #
# This file contains the analysis options used by Flutter tools, such as IntelliJ, # This file contains the analysis options used by Flutter tools, such as IntelliJ,
# Android Studio, and the `flutter analyze` command. # Android Studio, and the `flutter analyze` command.
# It is very similar to the analysis_options_repo.yaml file in this same directory;
# the only difference (currently) is the public_member_api_docs option,
# which triggers too many messages to be used in editors.
# #
# The flutter/plugins repo contains a copy of this file, which should be kept # The flutter/plugins repo contains a copy of this file, which should be kept
# in sync with this file. # in sync with this file.
analyzer: analyzer:
language: language:
enableStrictCallChecks: true
enableSuperMixins: true enableSuperMixins: true
strong-mode: strong-mode:
implicit-dynamic: false implicit-dynamic: false
...@@ -131,7 +127,6 @@ linter: ...@@ -131,7 +127,6 @@ linter:
- prefer_is_not_empty - prefer_is_not_empty
- prefer_single_quotes - prefer_single_quotes
- prefer_typing_uninitialized_variables - prefer_typing_uninitialized_variables
# - public_member_api_docs # this is the only difference from analysis_options_repo.yaml
- recursive_getters - recursive_getters
- slash_for_doc_comments - slash_for_doc_comments
- sort_constructors_first - sort_constructors_first
......
...@@ -189,6 +189,8 @@ Future<Null> main() async { ...@@ -189,6 +189,8 @@ Future<Null> main() async {
} }
} }
buffer.add(''); buffer.add('');
buffer.add('// ignore_for_file: unused_element');
buffer.add('');
final List<Line> lines = new List<Line>.filled(buffer.length, null, growable: true); final List<Line> lines = new List<Line>.filled(buffer.length, null, growable: true);
for (Section section in sections) { for (Section section in sections) {
buffer.addAll(section.strings); buffer.addAll(section.strings);
...@@ -207,7 +209,7 @@ dependencies: ...@@ -207,7 +209,7 @@ dependencies:
print('Found $sampleCodeSections sample code sections.'); print('Found $sampleCodeSections sample code sections.');
final Process process = await Process.start( final Process process = await Process.start(
_flutter, _flutter,
<String>['analyze', '--no-preamble', mainDart.path], <String>['analyze', '--no-preamble', '--no-congratulate', mainDart.parent.path],
workingDirectory: temp.path, workingDirectory: temp.path,
); );
stderr.addStream(process.stderr); stderr.addStream(process.stderr);
...@@ -216,10 +218,6 @@ dependencies: ...@@ -216,10 +218,6 @@ dependencies:
errors.removeAt(0); errors.removeAt(0);
if (errors.first.startsWith('Running "flutter packages get" in ')) if (errors.first.startsWith('Running "flutter packages get" in '))
errors.removeAt(0); errors.removeAt(0);
if (errors.first.startsWith('Analyzing '))
errors.removeAt(0);
if (errors.last.endsWith(' issues found.') || errors.last.endsWith(' issue found.'))
errors.removeLast();
int errorCount = 0; int errorCount = 0;
for (String error in errors) { for (String error in errors) {
final String kBullet = Platform.isWindows ? ' - ' : ' • '; final String kBullet = Platform.isWindows ? ' - ' : ' • ';
......
...@@ -21,21 +21,24 @@ Future<Null> main() async { ...@@ -21,21 +21,24 @@ Future<Null> main() async {
int publicMembers = 0; int publicMembers = 0;
int otherErrors = 0; int otherErrors = 0;
int otherLines = 0; int otherLines = 0;
await for (String entry in analysis.stderr.transform(utf8.decoder).transform(const LineSplitter())) { await for (String entry in analysis.stdout.transform(utf8.decoder).transform(const LineSplitter())) {
print('analyzer stderr: $entry'); entry = entry.trim();
if (entry.startsWith('[lint] Document all public members')) { print('analyzer stdout: $entry');
if (entry == 'Building flutter tool...') {
// ignore this line
} else if (entry.startsWith('info • Document all public members •')) {
publicMembers += 1; publicMembers += 1;
} else if (entry.startsWith('[')) { } else if (entry.startsWith('info •') || entry.startsWith('warning •') || entry.startsWith('error •')) {
otherErrors += 1; otherErrors += 1;
} else if (entry.startsWith('(Ran in ')) { } else if (entry.contains(' (ran in ')) {
// ignore this line // ignore this line
} else { } else if (entry.isNotEmpty) {
otherLines += 1; otherLines += 1;
} }
} }
await for (String entry in analysis.stdout.transform(utf8.decoder).transform(const LineSplitter())) { await for (String entry in analysis.stderr.transform(utf8.decoder).transform(const LineSplitter())) {
print('analyzer stdout: $entry'); print('analyzer stderr: $entry');
if (entry == 'Building flutter tool...') { if (entry.startsWith('[lint] ')) {
// ignore this line // ignore this line
} else { } else {
otherLines += 1; otherLines += 1;
......
# Take our settings from the repo's main analysis_options.yaml file, but include
# an additional rule to validate that public members are documented.
include: ../analysis_options.yaml
linter:
rules:
- public_member_api_docs
...@@ -7,21 +7,21 @@ ...@@ -7,21 +7,21 @@
# See the configuration guide for more # See the configuration guide for more
# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer # https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer
# #
# There are three similar analysis options files in the flutter repo: # There are four similar analysis options files in the flutter repos:
# - analysis_options.yaml # - analysis_options.yaml
# - analysis_options_repo.yaml
# - packages/flutter/lib/analysis_options_user.yaml (this file) # - packages/flutter/lib/analysis_options_user.yaml (this file)
# - https://github.com/flutter/plugins/blob/master/analysis_options.yaml
# - https://github.com/flutter/engine/blob/master/analysis_options.yaml
# #
# This file contains the analysis options used by "flutter analyze" # This file contains the analysis options used by "flutter analyze" and the
# and the dartanalyzer when analyzing code outside the flutter repository. # dartanalyzer when analyzing code outside the flutter repository. It isn't named
# It isn't named 'analysis_options.yaml' because otherwise editors like Atom # 'analysis_options.yaml' because otherwise editors would use it when analyzing
# would use it when analyzing the flutter tool itself. # the flutter tool itself.
# #
# When editing, make sure you keep /analysis_options.yaml consistent. # When editing, make sure you keep this and /analysis_options.yaml consistent.
analyzer: analyzer:
language: language:
enableStrictCallChecks: true
enableSuperMixins: true enableSuperMixins: true
strong-mode: true strong-mode: true
errors: errors:
......
# Use the analysis options settings from the top level of the repo (not
# the ones from above, which include the `public_member_api_docs` rule).
include: ../../analysis_options.yaml
# Use the analysis options settings from the top level of the repo (not
# the ones from above, which include the `public_member_api_docs` rule).
include: ../../analysis_options.yaml
...@@ -9,28 +9,51 @@ import '../runner/flutter_command.dart'; ...@@ -9,28 +9,51 @@ import '../runner/flutter_command.dart';
import 'analyze_continuously.dart'; import 'analyze_continuously.dart';
import 'analyze_once.dart'; import 'analyze_once.dart';
bool isDartFile(FileSystemEntity entry) => entry is File && entry.path.endsWith('.dart');
typedef bool FileFilter(FileSystemEntity entity);
class AnalyzeCommand extends FlutterCommand { class AnalyzeCommand extends FlutterCommand {
AnalyzeCommand({ bool verboseHelp: false, this.workingDirectory }) { AnalyzeCommand({bool verboseHelp: false, this.workingDirectory}) {
argParser.addFlag('flutter-repo', help: 'Include all the examples and tests from the Flutter repository.', defaultsTo: false); argParser.addFlag('flutter-repo',
argParser.addFlag('current-package', help: 'Include the lib/main.dart file from the current directory, if any.', defaultsTo: true); negatable: false,
argParser.addFlag('dartdocs', help: 'List every public member that is lacking documentation (only works with --flutter-repo and without --watch).', defaultsTo: false, hide: !verboseHelp); help: 'Include all the examples and tests from the Flutter repository.',
argParser.addFlag('watch', help: 'Run analysis continuously, watching the filesystem for changes.', negatable: false); defaultsTo: false,
argParser.addFlag('preview-dart-2', defaultsTo: true, help: 'Preview Dart 2.0 functionality.'); hide: !verboseHelp);
argParser.addOption('write', valueHelp: 'file', help: 'Also output the results to a file. This is useful with --watch if you want a file to always contain the latest results.'); argParser.addFlag('current-package',
argParser.addOption('dart-sdk', valueHelp: 'path-to-sdk', help: 'The path to the Dart SDK.', hide: !verboseHelp); help: 'Analyze the current project, if applicable.', defaultsTo: true);
argParser.addFlag('dartdocs',
negatable: false,
help: 'List every public member that is lacking documentation '
'(only works with --flutter-repo).',
hide: !verboseHelp);
argParser.addFlag('watch',
help: 'Run analysis continuously, watching the filesystem for changes.',
negatable: false);
argParser.addFlag('preview-dart-2',
defaultsTo: true, help: 'Preview Dart 2.0 functionality.');
argParser.addOption('write',
valueHelp: 'file',
help: 'Also output the results to a file. This is useful with --watch '
'if you want a file to always contain the latest results.');
argParser.addOption('dart-sdk',
valueHelp: 'path-to-sdk',
help: 'The path to the Dart SDK.',
hide: !verboseHelp);
// Hidden option to enable a benchmarking mode. // Hidden option to enable a benchmarking mode.
argParser.addFlag('benchmark', negatable: false, hide: !verboseHelp, help: 'Also output the analysis time.'); argParser.addFlag('benchmark',
negatable: false,
hide: !verboseHelp,
help: 'Also output the analysis time.');
usesPubOption(); usesPubOption();
// Not used by analyze --watch // Not used by analyze --watch
argParser.addFlag('congratulate', help: 'When analyzing the flutter repository, show output even when there are no errors, warnings, hints, or lints.', defaultsTo: true); argParser.addFlag('congratulate',
argParser.addFlag('preamble', help: 'When analyzing the flutter repository, display the number of files that will be analyzed.', defaultsTo: true); help: 'When analyzing the flutter repository, show output even when '
'there are no errors, warnings, hints, or lints.',
defaultsTo: true);
argParser.addFlag('preamble',
defaultsTo: true,
help: 'When analyzing the flutter repository, display the number of '
'files that will be analyzed.');
} }
/// The working directory for testing analysis using dartanalyzer. /// The working directory for testing analysis using dartanalyzer.
...@@ -40,17 +63,19 @@ class AnalyzeCommand extends FlutterCommand { ...@@ -40,17 +63,19 @@ class AnalyzeCommand extends FlutterCommand {
String get name => 'analyze'; String get name => 'analyze';
@override @override
String get description => 'Analyze the project\'s Dart code.'; String get description => "Analyze the project's Dart code.";
@override @override
bool get shouldRunPub { bool get shouldRunPub {
// If they're not analyzing the current project. // If they're not analyzing the current project.
if (!argResults['current-package']) if (!argResults['current-package']) {
return false; return false;
}
// Or we're not in a project directory. // Or we're not in a project directory.
if (!fs.file('pubspec.yaml').existsSync()) if (!fs.file('pubspec.yaml').existsSync()) {
return false; return false;
}
return super.shouldRunPub; return super.shouldRunPub;
} }
...@@ -59,11 +84,15 @@ class AnalyzeCommand extends FlutterCommand { ...@@ -59,11 +84,15 @@ class AnalyzeCommand extends FlutterCommand {
Future<Null> runCommand() { Future<Null> runCommand() {
if (argResults['watch']) { if (argResults['watch']) {
return new AnalyzeContinuously( return new AnalyzeContinuously(
argResults, runner.getRepoPackages(), previewDart2: argResults['preview-dart-2'] argResults,
runner.getRepoRoots(),
runner.getRepoPackages(),
previewDart2: argResults['preview-dart-2'],
).analyze(); ).analyze();
} else { } else {
return new AnalyzeOnce( return new AnalyzeOnce(
argResults, argResults,
runner.getRepoRoots(),
runner.getRepoPackages(), runner.getRepoPackages(),
workingDirectory: workingDirectory, workingDirectory: workingDirectory,
previewDart2: argResults['preview-dart-2'], previewDart2: argResults['preview-dart-2'],
......
...@@ -383,12 +383,19 @@ class FlutterCommandRunner extends CommandRunner<Null> { ...@@ -383,12 +383,19 @@ class FlutterCommandRunner extends CommandRunner<Null> {
Cache.flutterRoot ??= _defaultFlutterRoot; Cache.flutterRoot ??= _defaultFlutterRoot;
} }
/// Get all pub packages in the Flutter repo. /// Get the root directories of the repo - the directories containing Dart packages.
List<Directory> getRepoPackages() { List<String> getRepoRoots() {
final String root = fs.path.absolute(Cache.flutterRoot); final String root = fs.path.absolute(Cache.flutterRoot);
// not bin, and not the root // not bin, and not the root
return <String>['dev', 'examples', 'packages'] return <String>['dev', 'examples', 'packages'].map((String item) {
.expand<String>((String path) => _gatherProjectPaths(fs.path.join(root, path))) return fs.path.join(root, item);
}).toList();
}
/// Get all pub packages in the Flutter repo.
List<Directory> getRepoPackages() {
return getRepoRoots()
.expand<String>((String root) => _gatherProjectPaths(root))
.map((String dir) => fs.directory(dir)) .map((String dir) => fs.directory(dir))
.toList(); .toList();
} }
......
...@@ -6,7 +6,7 @@ import 'dart:async'; ...@@ -6,7 +6,7 @@ import 'dart:async';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/commands/analyze_continuously.dart'; import 'package:flutter_tools/src/dart/analysis.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';
......
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/commands/analyze.dart';
import 'package:test/test.dart';
import '../src/common.dart';
import '../src/context.dart';
import '../src/mocks.dart';
void main() {
Directory tempDir;
setUpAll(() {
Cache.disableLocking();
});
setUp(() {
tempDir = fs.systemTempDirectory.createTempSync('analysis_duplicate_names_test');
});
tearDown(() {
tempDir?.deleteSync(recursive: true);
});
group('analyze', () {
testUsingContext('flutter analyze with two files with the same name', () async {
final File dartFileA = fs.file(fs.path.join(tempDir.path, 'a.dart'));
dartFileA.parent.createSync();
dartFileA.writeAsStringSync('library test;');
final File dartFileB = fs.file(fs.path.join(tempDir.path, 'b.dart'));
dartFileB.writeAsStringSync('library test;');
final AnalyzeCommand command = new AnalyzeCommand();
applyMocksToCommand(command);
return createTestCommandRunner(command).run(
<String>['analyze', '--no-current-package', dartFileA.path, dartFileB.path]
).then<Null>((Null value) {
expect(testLogger.statusText, contains('Analyzing'));
expect(testLogger.statusText, contains('No issues found!'));
});
});
});
}
...@@ -17,7 +17,6 @@ import '../src/common.dart'; ...@@ -17,7 +17,6 @@ import '../src/common.dart';
import '../src/context.dart'; import '../src/context.dart';
void main() { void main() {
final String analyzerSeparator = platform.isWindows ? '-' : '•'; final String analyzerSeparator = platform.isWindows ? '-' : '•';
group('analyze once', () { group('analyze once', () {
...@@ -55,7 +54,7 @@ void main() { ...@@ -55,7 +54,7 @@ void main() {
}, timeout: allowForRemotePubInvocation); }, timeout: allowForRemotePubInvocation);
// Analyze in the current directory - no arguments // Analyze in the current directory - no arguments
testUsingContext('flutter analyze working directory', () async { testUsingContext('working directory', () async {
await runCommand( await runCommand(
command: new AnalyzeCommand(workingDirectory: fs.directory(projectPath)), command: new AnalyzeCommand(workingDirectory: fs.directory(projectPath)),
arguments: <String>['analyze'], arguments: <String>['analyze'],
...@@ -64,17 +63,17 @@ void main() { ...@@ -64,17 +63,17 @@ void main() {
}); });
// Analyze a specific file outside the current directory // Analyze a specific file outside the current directory
testUsingContext('flutter analyze one file', () async { testUsingContext('passing one file throws', () async {
await runCommand( await runCommand(
command: new AnalyzeCommand(), command: new AnalyzeCommand(),
arguments: <String>['analyze', libMain.path], arguments: <String>['analyze', libMain.path],
statusTextContains: <String>['No issues found!'], toolExit: true,
exitMessageContains: 'is not a directory',
); );
}); });
// Analyze in the current directory - no arguments // Analyze in the current directory - no arguments
testUsingContext('flutter analyze working directory with errors', () async { testUsingContext('working directory with errors', () async {
// Break the code to produce the "The parameter 'onPressed' is required" hint // Break the code to produce the "The parameter 'onPressed' is required" hint
// that is upgraded to a warning in package:flutter/analysis_options_user.yaml // that is upgraded to a warning in package:flutter/analysis_options_user.yaml
// to assert that we are using the default Flutter analysis options. // to assert that we are using the default Flutter analysis options.
...@@ -98,22 +97,7 @@ void main() { ...@@ -98,22 +97,7 @@ void main() {
statusTextContains: <String>[ statusTextContains: <String>[
'Analyzing', 'Analyzing',
'warning $analyzerSeparator The parameter \'onPressed\' is required', 'warning $analyzerSeparator The parameter \'onPressed\' is required',
'hint $analyzerSeparator The method \'_incrementCounter\' isn\'t used', 'info $analyzerSeparator The method \'_incrementCounter\' isn\'t used',
'2 issues found.',
],
toolExit: true,
);
});
// Analyze a specific file outside the current directory
testUsingContext('flutter analyze one file with errors', () async {
await runCommand(
command: new AnalyzeCommand(),
arguments: <String>['analyze', libMain.path],
statusTextContains: <String>[
'Analyzing',
'warning $analyzerSeparator The parameter \'onPressed\' is required',
'hint $analyzerSeparator The method \'_incrementCounter\' isn\'t used',
'2 issues found.', '2 issues found.',
], ],
toolExit: true, toolExit: true,
...@@ -121,8 +105,7 @@ void main() { ...@@ -121,8 +105,7 @@ void main() {
}); });
// Analyze in the current directory - no arguments // Analyze in the current directory - no arguments
testUsingContext('flutter analyze working directory with local options', () async { testUsingContext('working directory with local options', () async {
// Insert an analysis_options.yaml file in the project // Insert an analysis_options.yaml file in the project
// which will trigger a lint for broken code that was inserted earlier // which will trigger a lint for broken code that was inserted earlier
final File optionsFile = fs.file(fs.path.join(projectPath, 'analysis_options.yaml')); final File optionsFile = fs.file(fs.path.join(projectPath, 'analysis_options.yaml'));
...@@ -140,15 +123,15 @@ void main() { ...@@ -140,15 +123,15 @@ void main() {
statusTextContains: <String>[ statusTextContains: <String>[
'Analyzing', 'Analyzing',
'warning $analyzerSeparator The parameter \'onPressed\' is required', 'warning $analyzerSeparator The parameter \'onPressed\' is required',
'hint $analyzerSeparator The method \'_incrementCounter\' isn\'t used', 'info $analyzerSeparator The method \'_incrementCounter\' isn\'t used',
'lint $analyzerSeparator Only throw instances of classes extending either Exception or Error', 'info $analyzerSeparator Only throw instances of classes extending either Exception or Error',
'3 issues found.', '3 issues found.',
], ],
toolExit: true, toolExit: true,
); );
}); });
testUsingContext('flutter analyze no duplicate issues', () async { testUsingContext('no duplicate issues', () async {
final Directory tempDir = fs.systemTempDirectory.createTempSync('analyze_once_test_').absolute; final Directory tempDir = fs.systemTempDirectory.createTempSync('analyze_once_test_').absolute;
try { try {
...@@ -182,22 +165,6 @@ void bar() { ...@@ -182,22 +165,6 @@ void bar() {
} }
}); });
// Analyze a specific file outside the current directory
testUsingContext('flutter analyze one file with local options', () async {
await runCommand(
command: new AnalyzeCommand(),
arguments: <String>['analyze', libMain.path],
statusTextContains: <String>[
'Analyzing',
'warning $analyzerSeparator The parameter \'onPressed\' is required',
'hint $analyzerSeparator The method \'_incrementCounter\' isn\'t used',
'lint $analyzerSeparator Only throw instances of classes extending either Exception or Error',
'3 issues found.',
],
toolExit: true,
);
});
testUsingContext('--preview-dart-2', () async { testUsingContext('--preview-dart-2', () async {
const String contents = ''' const String contents = '''
StringBuffer bar = StringBuffer('baz'); StringBuffer bar = StringBuffer('baz');
...@@ -255,18 +222,23 @@ Future<Null> runCommand({ ...@@ -255,18 +222,23 @@ Future<Null> runCommand({
List<String> statusTextContains, List<String> statusTextContains,
List<String> errorTextContains, List<String> errorTextContains,
bool toolExit: false, bool toolExit: false,
String exitMessageContains,
}) async { }) async {
try { try {
arguments.insert(0, '--flutter-root=${Cache.flutterRoot}'); arguments.insert(0, '--flutter-root=${Cache.flutterRoot}');
await createTestCommandRunner(command).run(arguments); await createTestCommandRunner(command).run(arguments);
expect(toolExit, isFalse, reason: 'Expected ToolExit exception'); expect(toolExit, isFalse, reason: 'Expected ToolExit exception');
} on ToolExit { } on ToolExit catch (e) {
if (!toolExit) { if (!toolExit) {
testLogger.clear(); testLogger.clear();
rethrow; rethrow;
} }
if (exitMessageContains != null) {
expect(e.message, contains(exitMessageContains));
}
} }
assertContains(testLogger.statusText, statusTextContains); assertContains(testLogger.statusText, statusTextContains);
assertContains(testLogger.errorText, errorTextContains); assertContains(testLogger.errorText, errorTextContains);
testLogger.clear(); testLogger.clear();
} }
...@@ -436,14 +436,13 @@ Future<Null> _createAndAnalyzeProject( ...@@ -436,14 +436,13 @@ Future<Null> _createAndAnalyzeProject(
{ List<String> unexpectedPaths = const <String>[], bool plugin = false }) async { { List<String> unexpectedPaths = const <String>[], bool plugin = false }) async {
await _createProject(dir, createArgs, expectedPaths, unexpectedPaths: unexpectedPaths, plugin: plugin); await _createProject(dir, createArgs, expectedPaths, unexpectedPaths: unexpectedPaths, plugin: plugin);
if (plugin) { if (plugin) {
await _analyzeProject(dir.path, target: fs.path.join(dir.path, 'lib', 'flutter_project.dart')); await _analyzeProject(dir.path);
await _analyzeProject(fs.path.join(dir.path, 'example'));
} else { } else {
await _analyzeProject(dir.path); await _analyzeProject(dir.path);
} }
} }
Future<Null> _analyzeProject(String workingDir, {String target}) async { Future<Null> _analyzeProject(String workingDir) async {
final String flutterToolsPath = fs.path.absolute(fs.path.join( final String flutterToolsPath = fs.path.absolute(fs.path.join(
'bin', 'bin',
'flutter_tools.dart', 'flutter_tools.dart',
...@@ -453,8 +452,6 @@ Future<Null> _analyzeProject(String workingDir, {String target}) async { ...@@ -453,8 +452,6 @@ Future<Null> _analyzeProject(String workingDir, {String target}) async {
..addAll(dartVmFlags) ..addAll(dartVmFlags)
..add(flutterToolsPath) ..add(flutterToolsPath)
..add('analyze'); ..add('analyze');
if (target != null)
args.add(target);
final ProcessResult exec = await Process.run( final ProcessResult exec = await Process.run(
'$dartSdkPath/bin/dart', '$dartSdkPath/bin/dart',
......
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