Unverified Commit 07148525 authored by Devon Carew's avatar Devon Carew Committed by GitHub

Revert "re-write flutter analyze (the single-shot and --flutter-repo) to use...

Revert "re-write flutter analyze (the single-shot and --flutter-repo) to use the analysis server (#16281)" (#16482)

This reverts commit 2f41ea54.
parent 2f41ea54
......@@ -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
error messages about core classes like Offset from `dart:ui`.
For a one-off, use `flutter analyze --flutter-repo`. This uses the `analysis_options.yaml` file
For a one-off, use `flutter analyze --flutter-repo`. This uses the `analysis_options_repo.yaml` file
at the root of the repository for its configuration.
For continuous analysis, use `flutter analyze --flutter-repo --watch`. This uses normal
......
......@@ -9,18 +9,22 @@
#
# There are four similar analysis options files in the flutter repos:
# - analysis_options.yaml (this file)
# - analysis_options_repo.yaml
# - packages/flutter/lib/analysis_options_user.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,
# 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
# in sync with this file.
analyzer:
language:
enableStrictCallChecks: true
enableSuperMixins: true
strong-mode:
implicit-dynamic: false
......@@ -127,6 +131,7 @@ linter:
- prefer_is_not_empty
- prefer_single_quotes
- prefer_typing_uninitialized_variables
# - public_member_api_docs # this is the only difference from analysis_options_repo.yaml
- recursive_getters
- slash_for_doc_comments
- sort_constructors_first
......
# Specify analysis options.
#
# Until there are meta linter rules, each desired lint must be explicitly enabled.
# See: https://github.com/dart-lang/linter/issues/288
#
# For a list of lints, see: http://dart-lang.github.io/linter/lints/
# See the configuration guide for more
# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer
#
# There are three similar analysis options files in the flutter repo:
# - analysis_options.yaml
# - analysis_options_repo.yaml (this file)
# - packages/flutter/lib/analysis_options_user.yaml
#
# This file contains the analysis options used by 'flutter analyze' when analyzing
# the flutter repository. It is very similar to analysis_options.yaml;
# the only difference (currently) is the public_member_api_docs option,
# which is turned on and programmatically reduced to a single output line
# indicating the # of violations for that rule.
analyzer:
language:
enableStrictCallChecks: true
enableSuperMixins: true
strong-mode:
implicit-dynamic: false
errors:
# treat missing required parameters as a warning (not a hint)
missing_required_param: warning
# treat missing returns as a warning (not a hint)
missing_return: warning
# allow having TODOs in the code
todo: ignore
# `flutter analyze` (without `--watch`) just ignores directories
# that contain a .dartignore file, and this file does not have any
# effect on what files are actually analyzed.
linter:
rules:
# these rules are documented on and in the same order as
# the Dart Lint rules page to make maintenance easier
# https://github.com/dart-lang/linter/blob/master/example/all.yaml
- always_declare_return_types
- always_put_control_body_on_new_line
# - always_put_required_named_parameters_first # we prefer having parameters in the same order as fields https://github.com/flutter/flutter/issues/10219
- always_require_non_null_named_parameters
- always_specify_types
- annotate_overrides
# - avoid_annotating_with_dynamic # conflicts with always_specify_types
- avoid_as
# - avoid_bool_literals_in_conditional_expressions # not yet tested
# - avoid_catches_without_on_clauses # we do this commonly
# - avoid_catching_errors # we do this commonly
- avoid_classes_with_only_static_members
- avoid_empty_else
- avoid_function_literals_in_foreach_calls
- avoid_init_to_null
- avoid_null_checks_in_equality_operators
# - avoid_positional_boolean_parameters # not yet tested
# - avoid_private_typedef_functions # not yet tested
- avoid_relative_lib_imports
- avoid_renaming_method_parameters
- avoid_return_types_on_setters
# - avoid_returning_null # we do this commonly
# - avoid_returning_this # https://github.com/dart-lang/linter/issues/842
# - avoid_setters_without_getters # not yet tested
# - avoid_single_cascade_in_expression_statements # not yet tested
- avoid_slow_async_io
# - avoid_types_as_parameter_names # https://github.com/dart-lang/linter/pull/954/files
# - avoid_types_on_closure_parameters # conflicts with always_specify_types
# - avoid_unused_constructor_parameters # https://github.com/dart-lang/linter/pull/847
- await_only_futures
- camel_case_types
- cancel_subscriptions
# - cascade_invocations # not yet tested
# - close_sinks # https://github.com/flutter/flutter/issues/5789
# - comment_references # blocked on https://github.com/dart-lang/dartdoc/issues/1153
# - constant_identifier_names # https://github.com/dart-lang/linter/issues/204
- control_flow_in_finally
- directives_ordering
- empty_catches
- empty_constructor_bodies
- empty_statements
- hash_and_equals
- implementation_imports
# - invariant_booleans # https://github.com/flutter/flutter/issues/5790
- iterable_contains_unrelated_type
# - join_return_with_assignment # not yet tested
- library_names
- library_prefixes
- list_remove_unrelated_type
# - literal_only_boolean_expressions # https://github.com/flutter/flutter/issues/5791
- no_adjacent_strings_in_list
- no_duplicate_case_values
- non_constant_identifier_names
# - omit_local_variable_types # opposite of always_specify_types
# - one_member_abstracts # too many false positives
# - only_throw_errors # https://github.com/flutter/flutter/issues/5792
- overridden_fields
- package_api_docs
- package_names
- package_prefixed_library_names
# - parameter_assignments # we do this commonly
- prefer_adjacent_string_concatenation
- prefer_asserts_in_initializer_lists
- prefer_bool_in_asserts
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_const_constructors
- prefer_const_constructors_in_immutables
- prefer_const_declarations
- prefer_const_literals_to_create_immutables
# - prefer_constructors_over_static_methods # not yet tested
- prefer_contains
# - prefer_equal_for_default_values # not yet tested
# - prefer_expression_function_bodies # conflicts with https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#consider-using--for-short-functions-and-methods
- prefer_final_fields
- prefer_final_locals
- prefer_foreach
# - prefer_function_declarations_over_variables # not yet tested
- prefer_initializing_formals
# - prefer_interpolation_to_compose_strings # not yet tested
- prefer_is_empty
- prefer_is_not_empty
- prefer_single_quotes
- prefer_typing_uninitialized_variables
- public_member_api_docs # this is the only difference from analysis_options.yaml
- recursive_getters
- slash_for_doc_comments
- sort_constructors_first
- sort_unnamed_constructors_first
- super_goes_last
- test_types_in_equals
- throw_in_finally
# - type_annotate_public_apis # subset of always_specify_types
- type_init_formals
# - unawaited_futures # https://github.com/flutter/flutter/issues/5793
- unnecessary_brace_in_string_interps
- unnecessary_getters_setters
# - unnecessary_lambdas # https://github.com/dart-lang/linter/issues/498
- unnecessary_null_aware_assignments
- unnecessary_null_in_if_null_operators
- unnecessary_overrides
- unnecessary_parenthesis
# - unnecessary_statements # not yet tested
- unnecessary_this
- unrelated_type_equality_checks
- use_rethrow_when_possible
# - use_setters_to_change_properties # not yet tested
# - use_string_buffers # https://github.com/dart-lang/linter/pull/664
# - use_to_and_as_if_applicable # has false positives, so we prefer to catch this by code-review
- valid_regexps
......@@ -185,8 +185,6 @@ Future<Null> main() async {
}
}
buffer.add('');
buffer.add('// ignore_for_file: unused_element');
buffer.add('');
final List<Line> lines = new List<Line>.filled(buffer.length, null, growable: true);
for (Section section in sections) {
buffer.addAll(section.strings);
......@@ -205,7 +203,7 @@ dependencies:
print('Found $sampleCodeSections sample code sections.');
final Process process = await Process.start(
_flutter,
<String>['analyze', '--no-preamble', '--no-congratulate', mainDart.parent.path],
<String>['analyze', '--no-preamble', mainDart.path],
workingDirectory: temp.path,
);
stderr.addStream(process.stderr);
......@@ -214,6 +212,10 @@ dependencies:
errors.removeAt(0);
if (errors.first.startsWith('Running "flutter packages get" in '))
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;
for (String error in errors) {
final String kBullet = Platform.isWindows ? ' - ' : ' • ';
......
......@@ -21,24 +21,21 @@ Future<Null> main() async {
int publicMembers = 0;
int otherErrors = 0;
int otherLines = 0;
await for (String entry in analysis.stdout.transform(utf8.decoder).transform(const LineSplitter())) {
entry = entry.trim();
print('analyzer stdout: $entry');
if (entry == 'Building flutter tool...') {
// ignore this line
} else if (entry.startsWith('info • Document all public members •')) {
await for (String entry in analysis.stderr.transform(utf8.decoder).transform(const LineSplitter())) {
print('analyzer stderr: $entry');
if (entry.startsWith('[lint] Document all public members')) {
publicMembers += 1;
} else if (entry.startsWith('info •') || entry.startsWith('warning •') || entry.startsWith('error •')) {
} else if (entry.startsWith('[')) {
otherErrors += 1;
} else if (entry.contains(' (ran in ')) {
} else if (entry.startsWith('(Ran in ')) {
// ignore this line
} else if (entry.isNotEmpty) {
} else {
otherLines += 1;
}
}
await for (String entry in analysis.stderr.transform(utf8.decoder).transform(const LineSplitter())) {
print('analyzer stderr: $entry');
if (entry.startsWith('[lint] ')) {
await for (String entry in analysis.stdout.transform(utf8.decoder).transform(const LineSplitter())) {
print('analyzer stdout: $entry');
if (entry == 'Building flutter tool...') {
// ignore this line
} else {
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 @@
# See the configuration guide for more
# https://github.com/dart-lang/sdk/tree/master/pkg/analyzer#configuring-the-analyzer
#
# There are four similar analysis options files in the flutter repos:
# There are three similar analysis options files in the flutter repo:
# - analysis_options.yaml
# - analysis_options_repo.yaml
# - 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" and the
# dartanalyzer when analyzing code outside the flutter repository. It isn't named
# 'analysis_options.yaml' because otherwise editors would use it when analyzing
# the flutter tool itself.
# This file contains the analysis options used by "flutter analyze"
# and the dartanalyzer when analyzing code outside the flutter repository.
# It isn't named 'analysis_options.yaml' because otherwise editors like Atom
# would use it when analyzing the flutter tool itself.
#
# When editing, make sure you keep this and /analysis_options.yaml consistent.
# When editing, make sure you keep /analysis_options.yaml consistent.
analyzer:
language:
enableStrictCallChecks: true
enableSuperMixins: true
strong-mode: true
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
......@@ -9,47 +9,28 @@ import '../runner/flutter_command.dart';
import 'analyze_continuously.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 {
AnalyzeCommand({bool verboseHelp: false, this.workingDirectory}) {
argParser.addFlag('flutter-repo',
negatable: false,
help: 'Include all the examples and tests from the Flutter repository.',
defaultsTo: false,
hide: !verboseHelp);
argParser.addFlag('current-package',
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.');
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('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 works with --flutter-repo and without --watch).', defaultsTo: false, 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.
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();
// 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('preamble',
defaultsTo: true,
help: 'When analyzing the flutter repository, display the number of '
'files that will be analyzed.');
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('preamble', help: 'When analyzing the flutter repository, display the number of files that will be analyzed.', defaultsTo: true);
}
/// The working directory for testing analysis using dartanalyzer.
......@@ -59,19 +40,17 @@ class AnalyzeCommand extends FlutterCommand {
String get name => 'analyze';
@override
String get description => "Analyze the project's Dart code.";
String get description => 'Analyze the project\'s Dart code.';
@override
bool get shouldRunPub {
// If they're not analyzing the current project.
if (!argResults['current-package']) {
if (!argResults['current-package'])
return false;
}
// Or we're not in a project directory.
if (!fs.file('pubspec.yaml').existsSync()) {
if (!fs.file('pubspec.yaml').existsSync())
return false;
}
return super.shouldRunPub;
}
......@@ -80,15 +59,11 @@ class AnalyzeCommand extends FlutterCommand {
Future<Null> runCommand() {
if (argResults['watch']) {
return new AnalyzeContinuously(
argResults,
runner.getRepoRoots(),
runner.getRepoPackages(),
previewDart2: argResults['preview-dart-2'],
argResults, runner.getRepoPackages(), previewDart2: argResults['preview-dart-2']
).analyze();
} else {
return new AnalyzeOnce(
argResults,
runner.getRepoRoots(),
runner.getRepoPackages(),
workingDirectory: workingDirectory,
previewDart2: argResults['preview-dart-2'],
......
......@@ -383,19 +383,12 @@ class FlutterCommandRunner extends CommandRunner<Null> {
Cache.flutterRoot ??= _defaultFlutterRoot;
}
/// Get the root directories of the repo - the directories containing Dart packages.
List<String> getRepoRoots() {
final String root = fs.path.absolute(Cache.flutterRoot);
// not bin, and not the root
return <String>['dev', 'examples', 'packages'].map((String item) {
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))
final String root = fs.path.absolute(Cache.flutterRoot);
// not bin, and not the root
return <String>['dev', 'examples', 'packages']
.expand<String>((String path) => _gatherProjectPaths(fs.path.join(root, path)))
.map((String dir) => fs.directory(dir))
.toList();
}
......
......@@ -6,7 +6,7 @@ import 'dart:async';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/dart/analysis.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';
......
// 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,6 +17,7 @@ import '../src/common.dart';
import '../src/context.dart';
void main() {
final String analyzerSeparator = platform.isWindows ? '-' : '•';
group('analyze once', () {
......@@ -32,11 +33,7 @@ void main() {
});
tearDownAll(() {
try {
tempDir?.deleteSync(recursive: true);
} catch (e) {
// ignore errors deleting the temporary directory
}
tempDir?.deleteSync(recursive: true);
});
// Create a project to be analyzed
......@@ -53,7 +50,7 @@ void main() {
}, timeout: allowForRemotePubInvocation);
// Analyze in the current directory - no arguments
testUsingContext('working directory', () async {
testUsingContext('flutter analyze working directory', () async {
await runCommand(
command: new AnalyzeCommand(workingDirectory: fs.directory(projectPath)),
arguments: <String>['analyze'],
......@@ -62,17 +59,17 @@ void main() {
});
// Analyze a specific file outside the current directory
testUsingContext('passing one file throws', () async {
testUsingContext('flutter analyze one file', () async {
await runCommand(
command: new AnalyzeCommand(),
arguments: <String>['analyze', libMain.path],
toolExit: true,
exitMessageContains: 'is not a directory',
statusTextContains: <String>['No issues found!'],
);
});
// Analyze in the current directory - no arguments
testUsingContext('working directory with errors', () async {
testUsingContext('flutter analyze working directory with errors', () async {
// 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
// to assert that we are using the default Flutter analysis options.
......@@ -96,7 +93,22 @@ void main() {
statusTextContains: <String>[
'Analyzing',
'warning $analyzerSeparator The parameter \'onPressed\' is required',
'info $analyzerSeparator The method \'_incrementCounter\' isn\'t used',
'hint $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.',
],
toolExit: true,
......@@ -104,7 +116,8 @@ void main() {
});
// Analyze in the current directory - no arguments
testUsingContext('working directory with local options', () async {
testUsingContext('flutter analyze working directory with local options', () async {
// Insert an analysis_options.yaml file in the project
// which will trigger a lint for broken code that was inserted earlier
final File optionsFile = fs.file(fs.path.join(projectPath, 'analysis_options.yaml'));
......@@ -122,15 +135,15 @@ void main() {
statusTextContains: <String>[
'Analyzing',
'warning $analyzerSeparator The parameter \'onPressed\' is required',
'info $analyzerSeparator The method \'_incrementCounter\' isn\'t used',
'info $analyzerSeparator Only throw instances of classes extending either Exception or Error',
'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('no duplicate issues', () async {
testUsingContext('flutter analyze no duplicate issues', () async {
final Directory tempDir = fs.systemTempDirectory.createTempSync('analyze_once_test_').absolute;
try {
......@@ -164,6 +177,22 @@ 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 {
const String contents = '''
StringBuffer bar = StringBuffer('baz');
......@@ -221,23 +250,18 @@ Future<Null> runCommand({
List<String> statusTextContains,
List<String> errorTextContains,
bool toolExit: false,
String exitMessageContains,
}) async {
try {
arguments.insert(0, '--flutter-root=${Cache.flutterRoot}');
await createTestCommandRunner(command).run(arguments);
expect(toolExit, isFalse, reason: 'Expected ToolExit exception');
} on ToolExit catch (e) {
} on ToolExit {
if (!toolExit) {
testLogger.clear();
rethrow;
}
if (exitMessageContains != null) {
expect(e.message, contains(exitMessageContains));
}
}
assertContains(testLogger.statusText, statusTextContains);
assertContains(testLogger.errorText, errorTextContains);
testLogger.clear();
}
......@@ -431,13 +431,14 @@ Future<Null> _createAndAnalyzeProject(
{ List<String> unexpectedPaths = const <String>[], bool plugin = false }) async {
await _createProject(dir, createArgs, expectedPaths, unexpectedPaths: unexpectedPaths, plugin: plugin);
if (plugin) {
await _analyzeProject(dir.path);
await _analyzeProject(dir.path, target: fs.path.join(dir.path, 'lib', 'flutter_project.dart'));
await _analyzeProject(fs.path.join(dir.path, 'example'));
} else {
await _analyzeProject(dir.path);
}
}
Future<Null> _analyzeProject(String workingDir) async {
Future<Null> _analyzeProject(String workingDir, {String target}) async {
final String flutterToolsPath = fs.path.absolute(fs.path.join(
'bin',
'flutter_tools.dart',
......@@ -447,6 +448,8 @@ Future<Null> _analyzeProject(String workingDir) async {
..addAll(dartVmFlags)
..add(flutterToolsPath)
..add('analyze');
if (target != null)
args.add(target);
final ProcessResult exec = await Process.run(
'$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