From 9393aae3933b8e33c3339cb3e017984247f8625c Mon Sep 17 00:00:00 2001 From: Srujan Gaddam <58529443+srujzs@users.noreply.github.com> Date: Fri, 14 Feb 2025 11:57:53 -0800 Subject: [PATCH] Align web terminal messages with the VM (#163268) - Adds better instructions for hot reload (if using the right flags), hot restart, quitting, clearing, and more. These were already being printed when using the VM, so this aligns with that. - Adds an extra parameter for `CommandHelp` to `ResidentRunner` so `ResidentWebRunner` can pass a version of it that uses its separate logger and not `globals`. In order to support this, classes up the stack also provide a `Terminal`, `Platform`, and `OutputPreferences`. - Fixes up use of `globals` from an earlier change to implement hot reload to use the logger instead. Same with `globals.platform`. - Adds tests to check that only hot restart is printed when not using the extra front-end flags, and both hot restart and hot reload is printed when you are. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. --- packages/flutter_tools/lib/executable.dart | 2 + .../lib/src/base/command_help.dart | 4 +- .../lib/src/commands/daemon.dart | 3 + .../flutter_tools/lib/src/commands/drive.dart | 9 +++ .../flutter_tools/lib/src/commands/run.dart | 3 + .../lib/src/drive/drive_service.dart | 9 +++ .../lib/src/drive/web_driver_service.dart | 12 ++- .../lib/src/isolated/resident_web_runner.dart | 57 +++++++++------ .../lib/src/resident_runner.dart | 55 +++++++++++--- packages/flutter_tools/lib/src/run_cold.dart | 20 +---- packages/flutter_tools/lib/src/run_hot.dart | 25 +------ .../flutter_tools/lib/src/web/web_runner.dart | 5 ++ .../commands.shard/hermetic/attach_test.dart | 2 +- .../commands.shard/hermetic/drive_test.dart | 37 ++++++++++ .../drive/web_driver_service_test.dart | 8 +- .../general.shard/resident_runner_test.dart | 4 +- .../resident_web_runner_cold_test.dart | 17 +++++ .../resident_web_runner_test.dart | 73 ++++++++++++++++++- .../general.shard/terminal_handler_test.dart | 7 +- .../web.shard/web_driver_service_test.dart | 5 +- 20 files changed, 276 insertions(+), 81 deletions(-) diff --git a/packages/flutter_tools/lib/executable.dart b/packages/flutter_tools/lib/executable.dart index 889a84bad7..4cebf976da 100644 --- a/packages/flutter_tools/lib/executable.dart +++ b/packages/flutter_tools/lib/executable.dart @@ -218,6 +218,8 @@ List generateCommands({required bool verboseHelp, required bool fileSystem: globals.fs, logger: globals.logger, platform: globals.platform, + terminal: globals.terminal, + outputPreferences: globals.outputPreferences, signals: globals.signals, ), EmulatorsCommand(), diff --git a/packages/flutter_tools/lib/src/base/command_help.dart b/packages/flutter_tools/lib/src/base/command_help.dart index c0fad23fe2..26ca81913c 100644 --- a/packages/flutter_tools/lib/src/base/command_help.dart +++ b/packages/flutter_tools/lib/src/base/command_help.dart @@ -15,7 +15,7 @@ const int maxLineWidth = 84; class CommandHelp { CommandHelp({ required Logger logger, - required AnsiTerminal terminal, + required Terminal terminal, required Platform platform, required OutputPreferences outputPreferences, }) : _logger = logger, @@ -25,7 +25,7 @@ class CommandHelp { final Logger _logger; - final AnsiTerminal _terminal; + final Terminal _terminal; final Platform _platform; diff --git a/packages/flutter_tools/lib/src/commands/daemon.dart b/packages/flutter_tools/lib/src/commands/daemon.dart index cd90b08d90..eeac6d4871 100644 --- a/packages/flutter_tools/lib/src/commands/daemon.dart +++ b/packages/flutter_tools/lib/src/commands/daemon.dart @@ -710,6 +710,9 @@ class AppDomain extends Domain { analytics: globals.analytics, systemClock: globals.systemClock, logger: globals.logger, + terminal: globals.terminal, + platform: globals.platform, + outputPreferences: globals.outputPreferences, fileSystem: globals.fs, ); } else if (enableHotReload) { diff --git a/packages/flutter_tools/lib/src/commands/drive.dart b/packages/flutter_tools/lib/src/commands/drive.dart index 29825d909b..09df5fdb48 100644 --- a/packages/flutter_tools/lib/src/commands/drive.dart +++ b/packages/flutter_tools/lib/src/commands/drive.dart @@ -17,6 +17,7 @@ import '../base/io.dart'; import '../base/logger.dart'; import '../base/platform.dart'; import '../base/signals.dart'; +import '../base/terminal.dart'; import '../base/utils.dart'; import '../build_info.dart'; import '../dart/package_map.dart'; @@ -60,11 +61,15 @@ class DriveCommand extends RunCommandBase { required FileSystem fileSystem, required Logger logger, required Platform platform, + required Terminal terminal, + required OutputPreferences outputPreferences, required this.signals, }) : _flutterDriverFactory = flutterDriverFactory, _fileSystem = fileSystem, _logger = logger, _platform = platform, + _terminal = terminal, + _outputPreferences = outputPreferences, _fsUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform), super(verboseHelp: verboseHelp) { requiresPubspecYaml(); @@ -200,6 +205,8 @@ class DriveCommand extends RunCommandBase { final FileSystem _fileSystem; final Logger _logger; final Platform _platform; + final Terminal _terminal; + final OutputPreferences _outputPreferences; final FileSystemUtils _fsUtils; Timer? timeoutTimer; Map? screenshotTokens; @@ -298,6 +305,8 @@ class DriveCommand extends RunCommandBase { applicationPackageFactory: ApplicationPackageFactory.instance!, logger: _logger, platform: _platform, + terminal: _terminal, + outputPreferences: _outputPreferences, processUtils: globals.processUtils, dartSdkPath: globals.artifacts!.getArtifactPath(Artifact.engineDartBinary), devtoolsLauncher: DevtoolsLauncher.instance!, diff --git a/packages/flutter_tools/lib/src/commands/run.dart b/packages/flutter_tools/lib/src/commands/run.dart index 3cb2f34e8f..d7ae1f4748 100644 --- a/packages/flutter_tools/lib/src/commands/run.dart +++ b/packages/flutter_tools/lib/src/commands/run.dart @@ -720,6 +720,9 @@ class RunCommand extends RunCommandBase { fileSystem: globals.fs, analytics: globals.analytics, logger: globals.logger, + terminal: globals.terminal, + platform: globals.platform, + outputPreferences: globals.outputPreferences, systemClock: globals.systemClock, ); } diff --git a/packages/flutter_tools/lib/src/drive/drive_service.dart b/packages/flutter_tools/lib/src/drive/drive_service.dart index b6c93db134..d22bc789a7 100644 --- a/packages/flutter_tools/lib/src/drive/drive_service.dart +++ b/packages/flutter_tools/lib/src/drive/drive_service.dart @@ -15,6 +15,7 @@ import '../base/dds.dart'; import '../base/logger.dart'; import '../base/platform.dart'; import '../base/process.dart'; +import '../base/terminal.dart'; import '../build_info.dart'; import '../device.dart'; import '../resident_runner.dart'; @@ -26,12 +27,16 @@ class FlutterDriverFactory { required ApplicationPackageFactory applicationPackageFactory, required Platform platform, required Logger logger, + required Terminal terminal, + required OutputPreferences outputPreferences, required ProcessUtils processUtils, required String dartSdkPath, required DevtoolsLauncher devtoolsLauncher, }) : _applicationPackageFactory = applicationPackageFactory, _platform = platform, _logger = logger, + _terminal = terminal, + _outputPreferences = outputPreferences, _processUtils = processUtils, _dartSdkPath = dartSdkPath, _devtoolsLauncher = devtoolsLauncher; @@ -39,6 +44,8 @@ class FlutterDriverFactory { final ApplicationPackageFactory _applicationPackageFactory; final Platform _platform; final Logger _logger; + final Terminal _terminal; + final OutputPreferences _outputPreferences; final ProcessUtils _processUtils; final String _dartSdkPath; final DevtoolsLauncher _devtoolsLauncher; @@ -48,7 +55,9 @@ class FlutterDriverFactory { if (web) { return WebDriverService( logger: _logger, + terminal: _terminal, platform: _platform, + outputPreferences: _outputPreferences, processUtils: _processUtils, dartSdkPath: _dartSdkPath, ); diff --git a/packages/flutter_tools/lib/src/drive/web_driver_service.dart b/packages/flutter_tools/lib/src/drive/web_driver_service.dart index d12b349cd3..ab2907b254 100644 --- a/packages/flutter_tools/lib/src/drive/web_driver_service.dart +++ b/packages/flutter_tools/lib/src/drive/web_driver_service.dart @@ -15,6 +15,7 @@ import '../base/io.dart'; import '../base/logger.dart'; import '../base/platform.dart'; import '../base/process.dart'; +import '../base/terminal.dart'; import '../base/utils.dart'; import '../build_info.dart'; import '../convert.dart'; @@ -32,15 +33,21 @@ class WebDriverService extends DriverService { required String dartSdkPath, required Platform platform, required Logger logger, + required Terminal terminal, + required OutputPreferences outputPreferences, }) : _processUtils = processUtils, _dartSdkPath = dartSdkPath, _platform = platform, - _logger = logger; + _logger = logger, + _terminal = terminal, + _outputPreferences = outputPreferences; final ProcessUtils _processUtils; final String _dartSdkPath; final Platform _platform; final Logger _logger; + final Terminal _terminal; + final OutputPreferences _outputPreferences; late ResidentRunner _residentRunner; Uri? _webUri; @@ -99,6 +106,9 @@ class WebDriverService extends DriverService { fileSystem: globals.fs, analytics: globals.analytics, logger: _logger, + terminal: _terminal, + platform: _platform, + outputPreferences: _outputPreferences, systemClock: globals.systemClock, ); final Completer appStartedCompleter = Completer.sync(); diff --git a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart index 3d3182a3f1..9cca8f7021 100644 --- a/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart +++ b/packages/flutter_tools/lib/src/isolated/resident_web_runner.dart @@ -12,11 +12,13 @@ import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart' hide import '../application_package.dart'; import '../base/async_guard.dart'; +import '../base/command_help.dart'; import '../base/common.dart'; import '../base/file_system.dart'; import '../base/io.dart'; import '../base/logger.dart'; import '../base/net.dart'; +import '../base/platform.dart'; import '../base/terminal.dart'; import '../base/time.dart'; import '../base/utils.dart'; @@ -52,6 +54,9 @@ class DwdsWebRunnerFactory extends WebRunnerFactory { required DebuggingOptions debuggingOptions, UrlTunneller? urlTunneller, required Logger logger, + required Terminal terminal, + required Platform platform, + required OutputPreferences outputPreferences, required FileSystem fileSystem, required SystemClock systemClock, required Analytics analytics, @@ -69,6 +74,9 @@ class DwdsWebRunnerFactory extends WebRunnerFactory { systemClock: systemClock, fileSystem: fileSystem, logger: logger, + terminal: terminal, + platform: platform, + outputPreferences: outputPreferences, ); } } @@ -88,6 +96,9 @@ class ResidentWebRunner extends ResidentRunner { required DebuggingOptions debuggingOptions, required FileSystem fileSystem, required Logger logger, + required Terminal terminal, + required Platform platform, + required OutputPreferences outputPreferences, required SystemClock systemClock, required Analytics analytics, UrlTunneller? urlTunneller, @@ -95,6 +106,7 @@ class ResidentWebRunner extends ResidentRunner { ResidentDevtoolsHandlerFactory devtoolsHandler = createDefaultHandler, }) : _fileSystem = fileSystem, _logger = logger, + _platform = platform, _systemClock = systemClock, _analytics = analytics, _urlTunneller = urlTunneller, @@ -105,10 +117,17 @@ class ResidentWebRunner extends ResidentRunner { stayResident: stayResident, machine: machine, devtoolsHandler: devtoolsHandler, + commandHelp: CommandHelp( + logger: logger, + terminal: terminal, + platform: platform, + outputPreferences: outputPreferences, + ), ); final FileSystem _fileSystem; final Logger _logger; + final Platform _platform; final SystemClock _systemClock; final Analytics _analytics; final UrlTunneller? _urlTunneller; @@ -146,6 +165,20 @@ class ResidentWebRunner extends ResidentRunner { bool get _enableDwds => debuggingEnabled; + @override + bool get reloadIsRestart => + // Web behavior when not using the DDC library bundle format is to restart + // when a reload is issued. We can't use `canHotReload` to signal this + // since we still want a reload command to succeed, but to do a hot + // restart. + debuggingOptions.buildInfo.ddcModuleFormat != DdcModuleFormat.ddc || + debuggingOptions.buildInfo.canaryFeatures != true; + + // TODO(srujzs): Return true when web supports detaching. + // https://github.com/flutter/flutter/issues/163329 + @override + bool get supportsDetach => false; + ConnectionResult? _connectionResult; StreamSubscription? _stdOutSub; StreamSubscription? _stdErrSub; @@ -205,24 +238,6 @@ class ResidentWebRunner extends ResidentRunner { appFinished(); } - @override - void printHelp({bool details = true}) { - if (details) { - return printHelpDetails(); - } - const String fire = '🔥'; - const String rawMessage = ' To hot restart changes while running, press "r" or "R".'; - final String message = _logger.terminal.color( - fire + _logger.terminal.bolden(rawMessage), - TerminalColor.red, - ); - _logger.printStatus(message); - const String quitMessage = 'To quit, press "q".'; - _logger.printStatus('For a more detailed help message, press "h". $quitMessage'); - _logger.printStatus(''); - printDebuggerList(); - } - @override Future stopEchoingDeviceLog() async { // Do nothing for ResidentWebRunner @@ -310,7 +325,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive). isWasm: debuggingOptions.webUseWasm, useLocalCanvasKit: debuggingOptions.buildInfo.useLocalCanvasKit, rootDirectory: fileSystem.directory(projectRootPath), - isWindows: globals.platform.isWindows, + isWindows: _platform.isWindows, ); Uri url = await device!.devFS!.create(); if (debuggingOptions.tlsCertKeyPath != null && debuggingOptions.tlsCertPath != null) { @@ -475,10 +490,10 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive). // has some internal error, we should still surface it to make // debugging easier. String reloadFailedMessage = 'Hot reload failed:'; - globals.printError(reloadFailedMessage); + _logger.printError(reloadFailedMessage); for (final ReasonForCancelling reason in contents.notices) { reloadFailedMessage += reason.toString(); - globals.printError(reason.toString()); + _logger.printError(reason.toString()); } return OperationResult(1, reloadFailedMessage); } diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart index 6387b07fe3..1fb6909f60 100644 --- a/packages/flutter_tools/lib/src/resident_runner.dart +++ b/packages/flutter_tools/lib/src/resident_runner.dart @@ -611,6 +611,9 @@ abstract class ResidentHandlers { /// Whether all of the connected devices support hot reload. bool get canHotReload; + /// Whether an application can be detached without being stopped. + bool get supportsDetach; + // TODO(bkonyi): remove when ready to serve DevTools from DDS. ResidentDevtoolsHandler? get residentDevtoolsHandler; @@ -621,6 +624,8 @@ abstract class ResidentHandlers { FileSystem? get fileSystem; /// Called to print help to the terminal. + /// + /// If [details] is true, prints out extra help information. void printHelp({required bool details}); /// Perform a hot reload or hot restart of all attached applications. @@ -992,6 +997,7 @@ abstract class ResidentRunner extends ResidentHandlers { String? dillOutputPath, this.machine = false, ResidentDevtoolsHandlerFactory devtoolsHandler = createDefaultHandler, + CommandHelp? commandHelp, }) : mainPath = globals.fs.file(target).absolute.path, packagesFilePath = debuggingOptions.buildInfo.packageConfigPath, projectRootPath = projectRootPath ?? globals.fs.currentDirectory.path, @@ -1001,12 +1007,14 @@ abstract class ResidentRunner extends ResidentHandlers { ? globals.fs.systemTempDirectory.createTempSync('flutter_tool.') : globals.fs.file(dillOutputPath).parent, assetBundle = AssetBundleFactory.instance.createBundle(), - commandHelp = CommandHelp( - logger: globals.logger, - terminal: globals.terminal, - platform: globals.platform, - outputPreferences: globals.outputPreferences, - ) { + commandHelp = + commandHelp ?? + CommandHelp( + logger: globals.logger, + terminal: globals.terminal, + platform: globals.platform, + outputPreferences: globals.outputPreferences, + ) { if (!artifactDirectory.existsSync()) { artifactDirectory.createSync(recursive: true); } @@ -1132,6 +1140,9 @@ abstract class ResidentRunner extends ResidentHandlers { @override bool get canHotReload => hotMode; + /// Whether the hot reload support is implemented as hot restart. + bool get reloadIsRestart => false; + /// Start the app and keep the process running during its lifetime. /// /// Returns the exit code that we should use for the flutter tool process; 0 @@ -1426,7 +1437,7 @@ abstract class ResidentRunner extends ResidentHandlers { } if (includeVmService) { // Caution: This log line is parsed by device lab tests. - globals.printStatus( + logger.printStatus( 'A Dart VM Service on ${device.device!.displayName} ' 'is available at: ${device.vmService!.httpAddress}', ); @@ -1435,14 +1446,14 @@ abstract class ResidentRunner extends ResidentHandlers { if (_residentDevtoolsHandler!.printDtdUri) { final Uri? dtdUri = residentDevtoolsHandler!.dtdUri; if (dtdUri != null) { - globals.printStatus('The Dart Tooling Daemon is available at: $dtdUri\n'); + logger.printStatus('The Dart Tooling Daemon is available at: $dtdUri\n'); } } final Uri? uri = devToolsServerAddress!.uri?.replace( queryParameters: {'uri': '${device.vmService!.httpAddress}'}, ); if (uri != null) { - globals.printStatus( + logger.printStatus( 'The Flutter DevTools debugger and profiler ' 'on ${device.device!.displayName} ' 'is available at: ${urlToDisplayString(uri)}', @@ -1453,6 +1464,32 @@ abstract class ResidentRunner extends ResidentHandlers { _reportedDebuggers = true; } + @override + void printHelp({required bool details}) { + logger.printStatus('Flutter run key commands.'); + // Don't print the command in the case where the runner implements reload as + // restart since it's misleading. + if (canHotReload && !reloadIsRestart) { + commandHelp.r.print(); + } + if (supportsRestart) { + commandHelp.R.print(); + } + if (details) { + printHelpDetails(); + commandHelp.hWithDetails.print(); + } else { + commandHelp.hWithoutDetails.print(); + } + if (supportsDetach) { + commandHelp.d.print(); + } + commandHelp.c.print(); + commandHelp.q.print(); + logger.printStatus(''); + printDebuggerList(); + } + void printHelpDetails() { commandHelp.v.print(); if (flutterDevices.any((FlutterDevice? d) => d!.device!.supportsScreenshot)) { diff --git a/packages/flutter_tools/lib/src/run_cold.dart b/packages/flutter_tools/lib/src/run_cold.dart index ecc4f6844b..e07e8c4408 100644 --- a/packages/flutter_tools/lib/src/run_cold.dart +++ b/packages/flutter_tools/lib/src/run_cold.dart @@ -41,6 +41,9 @@ class ColdRunner extends ResidentRunner { @override FileSystem get fileSystem => globals.fs; + @override + bool get supportsDetach => _didAttach; + @override Future run({ Completer? connectionInfoCompleter, @@ -187,23 +190,6 @@ class ColdRunner extends ResidentRunner { await stopEchoingDeviceLog(); } - @override - void printHelp({required bool details}) { - globals.printStatus('Flutter run key commands.'); - if (details) { - printHelpDetails(); - commandHelp.hWithDetails.print(); - } else { - commandHelp.hWithoutDetails.print(); - } - if (_didAttach) { - commandHelp.d.print(); - } - commandHelp.c.print(); - commandHelp.q.print(); - printDebuggerList(); - } - @override Future preExit() async { for (final FlutterDevice? device in flutterDevices) { diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart index 20bb245d6b..16407fed99 100644 --- a/packages/flutter_tools/lib/src/run_hot.dart +++ b/packages/flutter_tools/lib/src/run_hot.dart @@ -133,6 +133,9 @@ class HotRunner extends ResidentRunner { String? flavor; + @override + bool get supportsDetach => stopAppDuringCleanup; + Future _calculateTargetPlatform() async { if (_targetPlatform != null) { return; @@ -1156,28 +1159,6 @@ class HotRunner extends ResidentRunner { ); } - @override - void printHelp({required bool details}) { - globals.printStatus('Flutter run key commands.'); - commandHelp.r.print(); - if (supportsRestart) { - commandHelp.R.print(); - } - if (details) { - printHelpDetails(); - commandHelp.hWithDetails.print(); - } else { - commandHelp.hWithoutDetails.print(); - } - if (stopAppDuringCleanup) { - commandHelp.d.print(); - } - commandHelp.c.print(); - commandHelp.q.print(); - globals.printStatus(''); - printDebuggerList(); - } - @visibleForTesting Future evictDirtyAssets() async { final List> futures = >[]; diff --git a/packages/flutter_tools/lib/src/web/web_runner.dart b/packages/flutter_tools/lib/src/web/web_runner.dart index cd22c83c24..a4c7e1f49c 100644 --- a/packages/flutter_tools/lib/src/web/web_runner.dart +++ b/packages/flutter_tools/lib/src/web/web_runner.dart @@ -8,6 +8,8 @@ import '../base/context.dart'; import '../base/file_system.dart'; import '../base/logger.dart'; import '../base/net.dart'; +import '../base/platform.dart'; +import '../base/terminal.dart'; import '../base/time.dart'; import '../device.dart'; import '../project.dart'; @@ -28,6 +30,9 @@ abstract class WebRunnerFactory { required DebuggingOptions debuggingOptions, UrlTunneller? urlTunneller, required Logger logger, + required Terminal terminal, + required Platform platform, + required OutputPreferences outputPreferences, required FileSystem fileSystem, required SystemClock systemClock, required Analytics analytics, diff --git a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart index b01032afe6..de6b1544fc 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/attach_test.dart @@ -1515,7 +1515,7 @@ class FakeHotRunner extends Fake implements HotRunner { bool stayResident = true; @override - void printHelp({required bool details}) {} + void printHelp({required bool details, bool reloadIsRestart = false}) {} } class FakeHotRunnerFactory extends Fake implements HotRunnerFactory { diff --git a/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart b/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart index 45357b9bfb..7f1ba0635b 100644 --- a/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart +++ b/packages/flutter_tools/test/commands.shard/hermetic/drive_test.dart @@ -15,6 +15,7 @@ import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/signals.dart'; +import 'package:flutter_tools/src/base/terminal.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/cache.dart'; import 'package:flutter_tools/src/commands/drive.dart'; @@ -34,6 +35,8 @@ void main() { late FileSystem fileSystem; late BufferLogger logger; late Platform platform; + late Terminal terminal; + late OutputPreferences outputPreferences; late FakeDeviceManager fakeDeviceManager; late FakeSignals signals; @@ -41,6 +44,8 @@ void main() { fileSystem = MemoryFileSystem.test(); logger = BufferLogger.test(); platform = FakePlatform(); + terminal = Terminal.test(); + outputPreferences = OutputPreferences.test(); fakeDeviceManager = FakeDeviceManager(); signals = FakeSignals(); }); @@ -60,6 +65,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, ); fileSystem.file('lib/main.dart').createSync(recursive: true); @@ -89,6 +96,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, ); fileSystem.file('lib/app.dart').createSync(recursive: true); @@ -116,6 +125,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, ); fileSystem.file('lib/main.dart').createSync(recursive: true); @@ -148,6 +159,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, ); fileSystem.file('lib/main.dart').createSync(recursive: true); @@ -188,6 +201,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, flutterDriverFactory: FailingFakeFlutterDriverFactory(), ); @@ -229,6 +244,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, ); fileSystem.file('lib/main.dart').createSync(recursive: true); @@ -269,6 +286,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, flutterDriverFactory: FailingFakeFlutterDriverFactory(), ); @@ -321,6 +340,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, ); @@ -365,6 +386,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: Signals.test(), flutterDriverFactory: NeverEndingFlutterDriverFactory(() {}), ); @@ -430,6 +453,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: Signals.test(), flutterDriverFactory: NeverEndingFlutterDriverFactory(() { signal.controller.add(signal); @@ -485,6 +510,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, ); @@ -522,6 +549,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, ); @@ -582,6 +611,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, ); @@ -616,6 +647,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, ); @@ -650,6 +683,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, ); @@ -684,6 +719,8 @@ void main() { fileSystem: fileSystem, logger: logger, platform: platform, + terminal: terminal, + outputPreferences: outputPreferences, signals: signals, ); diff --git a/packages/flutter_tools/test/general.shard/drive/web_driver_service_test.dart b/packages/flutter_tools/test/general.shard/drive/web_driver_service_test.dart index 9a398c38c0..0f96fe2245 100644 --- a/packages/flutter_tools/test/general.shard/drive/web_driver_service_test.dart +++ b/packages/flutter_tools/test/general.shard/drive/web_driver_service_test.dart @@ -9,6 +9,7 @@ import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/net.dart'; import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/process.dart'; +import 'package:flutter_tools/src/base/terminal.dart'; import 'package:flutter_tools/src/base/time.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/device.dart'; @@ -346,6 +347,9 @@ class FakeWebRunnerFactory implements WebRunnerFactory { required DebuggingOptions debuggingOptions, UrlTunneller? urlTunneller, Logger? logger, + Terminal? terminal, + Platform? platform, + OutputPreferences? outputPreferences, FileSystem? fileSystem, SystemClock? systemClock, Usage? usage, @@ -410,9 +414,11 @@ WebDriverService setUpDriverService() { final BufferLogger logger = BufferLogger.test(); return WebDriverService( logger: logger, + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), processUtils: ProcessUtils(logger: logger, processManager: FakeProcessManager.any()), dartSdkPath: 'dart', - platform: FakePlatform(), ); } diff --git a/packages/flutter_tools/test/general.shard/resident_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_runner_test.dart index 460f362a69..d292bc1ea4 100644 --- a/packages/flutter_tools/test/general.shard/resident_runner_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_runner_test.dart @@ -1390,7 +1390,7 @@ flutter: commandHelp.hWithDetails, commandHelp.c, commandHelp.q, - '', + '\n', ].join('\n'), ), ); @@ -1425,7 +1425,7 @@ flutter: commandHelp.hWithoutDetails, commandHelp.c, commandHelp.q, - '', + '\n', ].join('\n'), ), ); diff --git a/packages/flutter_tools/test/general.shard/resident_web_runner_cold_test.dart b/packages/flutter_tools/test/general.shard/resident_web_runner_cold_test.dart index 5bbfd0e88d..44f0d93604 100644 --- a/packages/flutter_tools/test/general.shard/resident_web_runner_cold_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_web_runner_cold_test.dart @@ -8,6 +8,8 @@ import 'package:file/memory.dart'; import 'package:flutter_tools/src/application_package.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; +import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/base/terminal.dart'; import 'package:flutter_tools/src/base/time.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_system/build_system.dart'; @@ -62,6 +64,9 @@ void main() { debuggingOptions: DebuggingOptions.disabled(BuildInfo.release), fileSystem: fileSystem, logger: BufferLogger.test(), + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), systemClock: SystemClock.fixed(DateTime(0, 0, 0)), analytics: getInitializedFakeAnalyticsInstance( fs: fileSystem, @@ -96,6 +101,9 @@ void main() { debuggingOptions: DebuggingOptions.disabled(BuildInfo.release), fileSystem: fileSystem, logger: BufferLogger.test(), + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), systemClock: SystemClock.fixed(DateTime(0, 0, 0)), analytics: getInitializedFakeAnalyticsInstance( fs: fileSystem, @@ -126,6 +134,9 @@ void main() { debuggingOptions: DebuggingOptions.disabled(BuildInfo.release), fileSystem: fileSystem, logger: BufferLogger.test(), + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), systemClock: SystemClock.fixed(DateTime(0, 0, 0)), analytics: getInitializedFakeAnalyticsInstance( fs: fileSystem, @@ -155,6 +166,9 @@ void main() { debuggingOptions: DebuggingOptions.disabled(BuildInfo.release), fileSystem: fileSystem, logger: BufferLogger.test(), + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), systemClock: SystemClock.fixed(DateTime(0, 0, 0)), analytics: getInitializedFakeAnalyticsInstance( fs: fileSystem, @@ -188,6 +202,9 @@ void main() { debuggingOptions: DebuggingOptions.disabled(BuildInfo.release), fileSystem: fileSystem, logger: BufferLogger.test(), + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), systemClock: SystemClock.fixed(DateTime(0, 0, 0)), analytics: getInitializedFakeAnalyticsInstance( fs: fileSystem, diff --git a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart index b81ad10957..5fef0e1354 100644 --- a/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart +++ b/packages/flutter_tools/test/general.shard/resident_web_runner_test.dart @@ -14,6 +14,7 @@ import 'package:flutter_tools/src/base/dds.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/platform.dart'; +import 'package:flutter_tools/src/base/terminal.dart'; import 'package:flutter_tools/src/base/time.dart'; import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_system/tools/scene_importer.dart'; @@ -143,6 +144,9 @@ void main() { debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), fileSystem: fileSystem, logger: BufferLogger.test(), + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), analytics: globals.analytics, systemClock: globals.systemClock, ); @@ -172,6 +176,9 @@ void main() { debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, startPaused: true), fileSystem: fileSystem, logger: BufferLogger.test(), + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), analytics: globals.analytics, systemClock: globals.systemClock, ); @@ -193,6 +200,9 @@ void main() { debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), fileSystem: fileSystem, logger: BufferLogger.test(), + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), analytics: globals.analytics, systemClock: globals.systemClock, ); @@ -204,6 +214,9 @@ void main() { debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile), fileSystem: fileSystem, logger: BufferLogger.test(), + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), analytics: globals.analytics, systemClock: globals.systemClock, ); @@ -343,6 +356,9 @@ void main() { stayResident: false, fileSystem: fileSystem, logger: logger, + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), analytics: globals.analytics, systemClock: globals.systemClock, devtoolsHandler: createNoOpHandler, @@ -371,6 +387,9 @@ void main() { stayResident: false, fileSystem: fileSystem, logger: BufferLogger.test(), + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), analytics: globals.analytics, systemClock: globals.systemClock, devtoolsHandler: createNoOpHandler, @@ -586,6 +605,9 @@ void main() { debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, startPaused: true), fileSystem: fileSystem, logger: BufferLogger.test(), + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), analytics: globals.analytics, systemClock: globals.systemClock, devtoolsHandler: createNoOpHandler, @@ -990,14 +1012,46 @@ void main() { ); testUsingContext( - 'printHelp without details shows hot restart help message', + 'printHelp without details shows only hot restart help message', () async { final BufferLogger logger = BufferLogger.test(); final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice, logger: logger); fakeVmServiceHost = FakeVmServiceHost(requests: []); residentWebRunner.printHelp(details: false); - expect(logger.statusText, contains('To hot restart changes')); + expect(logger.statusText, contains('Hot restart')); + expect(logger.statusText.contains('Hot reload'), false); + }, + overrides: { + FileSystem: () => fileSystem, + ProcessManager: () => processManager, + }, + ); + + testUsingContext( + 'printHelp without details shows hot restart and hot reload help message ' + 'if using DDC library bundle format', + () async { + final BufferLogger logger = BufferLogger.test(); + final ResidentRunner residentWebRunner = setUpResidentRunner( + flutterDevice, + logger: logger, + debuggingOptions: DebuggingOptions.enabled( + const BuildInfo( + BuildMode.debug, + null, + trackWidgetCreation: true, + treeShakeIcons: false, + packageConfigPath: '.dart_tool/package_config.json', + extraFrontEndOptions: ['--dartdevc-module-format=ddc', '--dartdevc-canary'], + ), + ), + ); + fakeVmServiceHost = FakeVmServiceHost(requests: []); + residentWebRunner.printHelp(details: false); + + expect(logger.statusText, contains('Hot restart')); + expect(logger.statusText, contains('Hot reload')); }, overrides: { FileSystem: () => fileSystem, @@ -1130,6 +1184,9 @@ void main() { debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), fileSystem: fileSystem, logger: logger, + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), analytics: globals.analytics, systemClock: globals.systemClock, devtoolsHandler: createNoOpHandler, @@ -1175,6 +1232,9 @@ void main() { debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug), fileSystem: fileSystem, logger: logger, + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), analytics: globals.analytics, systemClock: globals.systemClock, devtoolsHandler: createNoOpHandler, @@ -1217,6 +1277,9 @@ void main() { stayResident: false, fileSystem: fileSystem, logger: BufferLogger.test(), + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), analytics: globals.analytics, systemClock: globals.systemClock, devtoolsHandler: createNoOpHandler, @@ -1512,6 +1575,9 @@ ResidentRunner setUpResidentRunner( systemClock: systemClock ?? SystemClock.fixed(DateTime.now()), fileSystem: globals.fs, logger: logger ?? BufferLogger.test(), + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), devtoolsHandler: createNoOpHandler, ); } @@ -1533,6 +1599,9 @@ class FakeDevice extends Fake implements Device { @override late DartDevelopmentService dds; + @override + bool get supportsHotRestart => true; + @override Future startApp( ApplicationPackage? package, { diff --git a/packages/flutter_tools/test/general.shard/terminal_handler_test.dart b/packages/flutter_tools/test/general.shard/terminal_handler_test.dart index 31f31d7210..8a1868a924 100644 --- a/packages/flutter_tools/test/general.shard/terminal_handler_test.dart +++ b/packages/flutter_tools/test/general.shard/terminal_handler_test.dart @@ -1229,6 +1229,9 @@ class FakeResidentRunner extends ResidentHandlers { @override bool supportsRestart = true; + @override + bool supportsDetach = true; + @override bool supportsServiceProtocol = true; @@ -1246,7 +1249,7 @@ class FakeResidentRunner extends ResidentHandlers { } @override - void printHelp({required bool details}) { + void printHelp({required bool details, bool reloadIsRestart = false}) { if (details) { calledPrintWithDetails = true; } else { @@ -1398,7 +1401,7 @@ class TestRunner extends Fake implements ResidentRunner { Future cleanupAtFinish() async {} @override - void printHelp({bool? details}) { + void printHelp({bool? details, bool reloadIsRestart = false}) { hasHelpBeenPrinted = true; } diff --git a/packages/flutter_tools/test/web.shard/web_driver_service_test.dart b/packages/flutter_tools/test/web.shard/web_driver_service_test.dart index d5b7bd14f6..836f2fc588 100644 --- a/packages/flutter_tools/test/web.shard/web_driver_service_test.dart +++ b/packages/flutter_tools/test/web.shard/web_driver_service_test.dart @@ -6,6 +6,7 @@ import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/process.dart'; +import 'package:flutter_tools/src/base/terminal.dart'; import 'package:flutter_tools/src/drive/web_driver_service.dart'; import 'package:package_config/package_config_types.dart'; @@ -19,9 +20,11 @@ void main() { final BufferLogger logger = BufferLogger.test(); final WebDriverService service = WebDriverService( logger: logger, + terminal: Terminal.test(), + platform: FakePlatform(), + outputPreferences: OutputPreferences.test(), processUtils: ProcessUtils(logger: logger, processManager: FakeProcessManager.empty()), dartSdkPath: 'dart', - platform: FakePlatform(), ); const String link = 'https://flutter.dev/to/integration-test-on-web'; try {