diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart index 205ca86f7eb2f..9ea76318cff7b 100644 --- a/packages/flutter_tools/lib/executable.dart +++ b/packages/flutter_tools/lib/executable.dart @@ -51,6 +51,7 @@ import 'src/globals.dart' as globals; import 'src/isolated/mustache_template.dart'; import 'src/isolated/resident_web_runner.dart'; import 'src/pre_run_validator.dart'; +import 'src/project_validator.dart'; import 'src/resident_runner.dart'; import 'src/runner/flutter_command.dart'; import 'src/web/web_runner.dart'; @@ -141,6 +142,7 @@ List generateCommands({ logger: globals.logger, terminal: globals.terminal, artifacts: globals.artifacts!, + allProjectValidators: [], ), AssembleCommand(verboseHelp: verboseHelp, buildSystem: globals.buildSystem), AttachCommand(verboseHelp: verboseHelp), diff --git a/packages/flutter_tools/lib/src/commands/analyze.dart b/packages/flutter_tools/lib/src/commands/analyze.dart index 928c5b2079280..62c109d44dc3f 100644 --- a/packages/flutter_tools/lib/src/commands/analyze.dart +++ b/packages/flutter_tools/lib/src/commands/analyze.dart @@ -5,13 +5,17 @@ import 'package:process/process.dart'; import '../artifacts.dart'; +import '../base/common.dart'; import '../base/file_system.dart'; import '../base/logger.dart'; import '../base/platform.dart'; import '../base/terminal.dart'; +import '../project_validator.dart'; import '../runner/flutter_command.dart'; +import 'analyze_base.dart'; import 'analyze_continuously.dart'; import 'analyze_once.dart'; +import 'validate_project.dart'; class AnalyzeCommand extends FlutterCommand { AnalyzeCommand({ @@ -23,11 +27,13 @@ class AnalyzeCommand extends FlutterCommand { required Logger logger, required ProcessManager processManager, required Artifacts artifacts, + required List allProjectValidators, }) : _artifacts = artifacts, _fileSystem = fileSystem, _processManager = processManager, _logger = logger, _terminal = terminal, + _allProjectValidators = allProjectValidators, _platform = platform { argParser.addFlag('flutter-repo', negatable: false, @@ -56,6 +62,9 @@ class AnalyzeCommand extends FlutterCommand { help: 'The path to write the request and response protocol. This is ' 'only intended to be used for debugging the tooling.', hide: !verboseHelp); + argParser.addFlag('suggestions', + help: 'Show suggestions about the current flutter project.' + ); // Hidden option to enable a benchmarking mode. argParser.addFlag('benchmark', @@ -92,6 +101,7 @@ class AnalyzeCommand extends FlutterCommand { final Terminal _terminal; final ProcessManager _processManager; final Platform _platform; + final List _allProjectValidators; @override String get name => 'analyze'; @@ -119,7 +129,29 @@ class AnalyzeCommand extends FlutterCommand { @override Future runCommand() async { - if (boolArgDeprecated('watch')) { + final bool? suggestionFlag = boolArg('suggestions'); + if (suggestionFlag != null && suggestionFlag == true) { + final String directoryPath; + final bool? watchFlag = boolArg('watch'); + if (watchFlag != null && watchFlag) { + throwToolExit('flag --watch is not compatible with --suggestions'); + } + if (workingDirectory == null) { + final Set items = findDirectories(argResults!, _fileSystem); + if (items.isEmpty || items.length > 1) { + throwToolExit('The suggestions flags needs one directory path'); + } + directoryPath = items.first; + } else { + directoryPath = workingDirectory!.path; + } + return ValidateProject( + fileSystem: _fileSystem, + logger: _logger, + allProjectValidators: _allProjectValidators, + userPath: directoryPath, + ).run(); + } else if (boolArgDeprecated('watch')) { await AnalyzeContinuously( argResults!, runner!.getRepoRoots(), diff --git a/packages/flutter_tools/lib/src/commands/analyze_base.dart b/packages/flutter_tools/lib/src/commands/analyze_base.dart index dbb55c9d672ed..54a9ff6fe0582 100644 --- a/packages/flutter_tools/lib/src/commands/analyze_base.dart +++ b/packages/flutter_tools/lib/src/commands/analyze_base.dart @@ -286,3 +286,20 @@ class PackageDependencyTracker { return result; } } + +/// Find directories or files from argResults.rest. +Set findDirectories(ArgResults argResults, FileSystem fileSystem) { + final Set items = Set.of(argResults.rest + .map((String path) => fileSystem.path.canonicalize(path))); + if (items.isNotEmpty) { + for (final String item in items) { + final FileSystemEntityType type = fileSystem.typeSync(item); + + if (type == FileSystemEntityType.notFound) { + throwToolExit("You provided the path '$item', however it does not exist on disk"); + } + } + } + + return items; +} diff --git a/packages/flutter_tools/lib/src/commands/analyze_once.dart b/packages/flutter_tools/lib/src/commands/analyze_once.dart index 5af200054cf00..35808c8fd9ae2 100644 --- a/packages/flutter_tools/lib/src/commands/analyze_once.dart +++ b/packages/flutter_tools/lib/src/commands/analyze_once.dart @@ -35,19 +35,7 @@ class AnalyzeOnce extends AnalyzeBase { Future analyze() async { final String currentDirectory = (workingDirectory ?? fileSystem.currentDirectory).path; - - // find directories or files from argResults.rest - final Set items = Set.of(argResults.rest - .map((String path) => fileSystem.path.canonicalize(path))); - if (items.isNotEmpty) { - for (final String item in items) { - final FileSystemEntityType type = fileSystem.typeSync(item); - - if (type == FileSystemEntityType.notFound) { - throwToolExit("'$item' does not exist"); - } - } - } + final Set items = findDirectories(argResults, fileSystem); if (isFlutterRepo) { // check for conflicting dependencies diff --git a/packages/flutter_tools/lib/src/commands/validate_project.dart b/packages/flutter_tools/lib/src/commands/validate_project.dart index 0f7569ff635c4..9117f7cab47f2 100644 --- a/packages/flutter_tools/lib/src/commands/validate_project.dart +++ b/packages/flutter_tools/lib/src/commands/validate_project.dart @@ -9,31 +9,22 @@ import '../project_validator.dart'; import '../project_validator_result.dart'; import '../runner/flutter_command.dart'; -class ValidateProjectCommand extends FlutterCommand { - ValidateProjectCommand({ +class ValidateProject { + ValidateProject({ required this.fileSystem, required this.logger, required this.allProjectValidators, + required this.userPath, this.verbose = false }); final FileSystem fileSystem; final Logger logger; final bool verbose; + final String userPath; final List allProjectValidators; - @override - final String name = 'validate-project'; - - @override - final String description = 'Show information about the current project.'; - - @override - final String category = FlutterCommandCategory.project; - - @override - Future runCommand() async { - final String userPath = getUserPath(); + Future run() async { final Directory workingDirectory = userPath.isEmpty ? fileSystem.currentDirectory : fileSystem.directory(userPath); final FlutterProject project = FlutterProject.fromDirectory(workingDirectory); @@ -94,8 +85,4 @@ class ValidateProjectCommand extends FlutterCommand { return '$icon $result'; } - - String getUserPath(){ - return (argResults == null || argResults!.rest.isEmpty) ? '' : argResults!.rest[0]; - } } diff --git a/packages/flutter_tools/test/commands.shard/hermetic/analyze_continuously_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/analyze_continuously_test.dart index 87cd6dc6cd551..0205a9a723d92 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/analyze_continuously_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/analyze_continuously_test.dart @@ -19,6 +19,7 @@ import 'package:flutter_tools/src/commands/analyze.dart'; import 'package:flutter_tools/src/dart/analysis.dart'; import 'package:flutter_tools/src/dart/pub.dart'; import 'package:flutter_tools/src/globals.dart' as globals; +import 'package:flutter_tools/src/project_validator.dart'; import 'package:process/process.dart'; import '../../src/common.dart'; @@ -199,6 +200,7 @@ void main() { platform: FakePlatform(), fileSystem: MemoryFileSystem.test(), processManager: processManager, + allProjectValidators: [], ); final TestFlutterCommandRunner commandRunner = TestFlutterCommandRunner(); @@ -246,6 +248,7 @@ void main() { platform: FakePlatform(), fileSystem: fileSystem, processManager: processManager, + allProjectValidators: [], ); await FakeAsync().run((FakeAsync time) async { @@ -298,6 +301,7 @@ void main() { platform: FakePlatform(), fileSystem: MemoryFileSystem.test(), processManager: processManager, + allProjectValidators: [], ); await FakeAsync().run((FakeAsync time) async { diff --git a/packages/flutter_tools/test/commands.shard/hermetic/project_validator_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/analyze_suggestion_test.dart similarity index 66% rename from packages/flutter_tools/test/commands.shard/hermetic/project_validator_test.dart rename to packages/flutter_tools/test/commands.shard/hermetic/analyze_suggestion_test.dart index bc387e5516b74..1411060073e2d 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/project_validator_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/analyze_suggestion_test.dart @@ -6,13 +6,17 @@ import 'package:args/command_runner.dart'; import 'package:file/memory.dart'; +import 'package:flutter_tools/src/artifacts.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; -import 'package:flutter_tools/src/commands/validate_project.dart'; +import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/base/terminal.dart'; +import 'package:flutter_tools/src/commands/analyze.dart'; import 'package:flutter_tools/src/project.dart'; import 'package:flutter_tools/src/project_validator.dart'; import 'package:flutter_tools/src/project_validator_result.dart'; +import '../../src/common.dart'; import '../../src/context.dart'; import '../../src/test_flutter_command_runner.dart'; @@ -70,26 +74,36 @@ class ProjectValidatorCrash extends ProjectValidator { void main() { FileSystem fileSystem; + Terminal terminal; + ProcessManager processManager; + Platform platform; - group('analyze project command', () { + group('analyze --suggestions command', () { setUp(() { fileSystem = MemoryFileSystem.test(); + terminal = Terminal.test(); + processManager = FakeProcessManager.empty(); + platform = FakePlatform(); }); testUsingContext('success, error and warning', () async { final BufferLogger loggerTest = BufferLogger.test(); - final ValidateProjectCommand command = ValidateProjectCommand( - fileSystem: fileSystem, - logger: loggerTest, - allProjectValidators: [ - ProjectValidatorDummy(), - ProjectValidatorSecondDummy() - ] + final AnalyzeCommand command = AnalyzeCommand( + artifacts: Artifacts.test(), + fileSystem: fileSystem, + logger: loggerTest, + platform: platform, + terminal: terminal, + processManager: processManager, + allProjectValidators: [ + ProjectValidatorDummy(), + ProjectValidatorSecondDummy() + ] ); final CommandRunner runner = createTestCommandRunner(command); - await runner.run(['validate-project']); + await runner.run(['analyze', '--suggestions', './']); const String expected = '\n' '┌──────────────────────────────────────────┐\n' @@ -107,18 +121,41 @@ void main() { testUsingContext('crash', () async { final BufferLogger loggerTest = BufferLogger.test(); - final ValidateProjectCommand command = ValidateProjectCommand( + final AnalyzeCommand command = AnalyzeCommand( + artifacts: Artifacts.test(), fileSystem: fileSystem, logger: loggerTest, - allProjectValidators: [ProjectValidatorCrash()] + platform: platform, + terminal: terminal, + processManager: processManager, + allProjectValidators: [ + ProjectValidatorCrash(), + ] ); final CommandRunner runner = createTestCommandRunner(command); - await runner.run(['validate-project']); + await runner.run(['analyze', '--suggestions', './']); const String expected = '[☠] Exception: my exception: #0 ProjectValidatorCrash.start'; expect(loggerTest.statusText, contains(expected)); }); + + testUsingContext('--watch and --suggestions not compatible together', () async { + final BufferLogger loggerTest = BufferLogger.test(); + final AnalyzeCommand command = AnalyzeCommand( + artifacts: Artifacts.test(), + fileSystem: fileSystem, + logger: loggerTest, + platform: platform, + terminal: terminal, + processManager: processManager, + allProjectValidators: [] + ); + final CommandRunner runner = createTestCommandRunner(command); + Future result () => runner.run(['analyze', '--suggestions', '--watch']); + + expect(result, throwsToolExit(message: 'flag --watch is not compatible with --suggestions')); + }); }); } diff --git a/packages/flutter_tools/test/commands.shard/hermetic/analyze_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/analyze_test.dart index 88a9aa33f3328..b8424914fecd3 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/analyze_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/analyze_test.dart @@ -15,6 +15,7 @@ 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/dart/analysis.dart'; +import 'package:flutter_tools/src/project_validator.dart'; import '../../src/common.dart'; import '../../src/context.dart'; @@ -70,6 +71,7 @@ void main() { platform: platform, processManager: processManager, terminal: terminal, + allProjectValidators: [], ); runner = createTestCommandRunner(command); diff --git a/packages/flutter_tools/test/integration.shard/analyze_once_test.dart b/packages/flutter_tools/test/integration.shard/analyze_once_test.dart index 7fa3a6638b30f..3691058160653 100644 --- a/packages/flutter_tools/test/integration.shard/analyze_once_test.dart +++ b/packages/flutter_tools/test/integration.shard/analyze_once_test.dart @@ -160,7 +160,7 @@ void main() { testWithoutContext('file not found', () async { await runCommand( arguments: ['analyze', '--no-pub', 'not_found.abc'], - exitMessageContains: "not_found.abc' does not exist", + exitMessageContains: "not_found.abc', however it does not exist on disk", exitCode: 1 ); }); diff --git a/packages/flutter_tools/test/integration.shard/project_validator_integration_test.dart b/packages/flutter_tools/test/integration.shard/analyze_suggestions_integration_test.dart similarity index 79% rename from packages/flutter_tools/test/integration.shard/project_validator_integration_test.dart rename to packages/flutter_tools/test/integration.shard/analyze_suggestions_integration_test.dart index 33a372724c20d..52cbb17691ef3 100644 --- a/packages/flutter_tools/test/integration.shard/project_validator_integration_test.dart +++ b/packages/flutter_tools/test/integration.shard/analyze_suggestions_integration_test.dart @@ -5,7 +5,7 @@ import 'package:args/command_runner.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; -import 'package:flutter_tools/src/commands/validate_project.dart'; +import 'package:flutter_tools/src/commands/analyze.dart'; import 'package:flutter_tools/src/globals.dart' as globals; import 'package:flutter_tools/src/project_validator.dart'; @@ -15,7 +15,7 @@ import '../src/test_flutter_command_runner.dart'; void main() { late FileSystem fileSystem; - group('analyze project command', () { + group('analyze --suggestions command integration', () { setUp(() { fileSystem = globals.localFileSystem; @@ -23,14 +23,24 @@ void main() { testUsingContext('General Info Project Validator', () async { final BufferLogger loggerTest = BufferLogger.test(); - final ValidateProjectCommand command = ValidateProjectCommand( + final AnalyzeCommand command = AnalyzeCommand( + artifacts: globals.artifacts!, fileSystem: fileSystem, logger: loggerTest, - allProjectValidators: [GeneralInfoProjectValidator()] + platform: globals.platform, + terminal: globals.terminal, + processManager: globals.processManager, + allProjectValidators: [GeneralInfoProjectValidator()], ); final CommandRunner runner = createTestCommandRunner(command); - await runner.run(['validate-project', '../../dev/integration_tests/flutter_gallery']); + await runner.run([ + 'analyze', + '--no-pub', + '--no-current-package', + '--suggestions', + '../../dev/integration_tests/flutter_gallery', + ]); const String expected = '\n' '┌────────────────────────────────────────────────────────────────────────────┐\n' pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy