mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[flutter_tools] warn when doctor takes long (#100805)
* warn when doctor takes long
This commit is contained in:
parent
4ece077249
commit
9c138f9c76
@ -186,11 +186,13 @@ class AndroidValidator extends DoctorValidator {
|
||||
|
||||
messages.add(ValidationMessage(_userMessages.androidSdkLocation(androidSdk.directory.path)));
|
||||
|
||||
_task = 'Validating Android SDK command line tools are available';
|
||||
if (!androidSdk.cmdlineToolsAvailable) {
|
||||
messages.add(ValidationMessage.error(_userMessages.androidMissingCmdTools));
|
||||
return ValidationResult(ValidationType.missing, messages);
|
||||
}
|
||||
|
||||
_task = 'Validating Android SDK licenses';
|
||||
if (androidSdk.licensesAvailable && !androidSdk.platformToolsAvailable) {
|
||||
messages.add(ValidationMessage.hint(_userMessages.androidSdkLicenseOnly(kAndroidHome)));
|
||||
return ValidationResult(ValidationType.partial, messages);
|
||||
@ -227,6 +229,7 @@ class AndroidValidator extends DoctorValidator {
|
||||
messages.add(ValidationMessage('$kAndroidSdkRoot = $androidSdkRoot'));
|
||||
}
|
||||
|
||||
_task = 'Validating Android SDK';
|
||||
final List<String> validationResult = androidSdk.validateSdkWellFormed();
|
||||
|
||||
if (validationResult.isNotEmpty) {
|
||||
@ -238,6 +241,7 @@ class AndroidValidator extends DoctorValidator {
|
||||
return ValidationResult(ValidationType.partial, messages, statusInfo: sdkVersionText);
|
||||
}
|
||||
|
||||
_task = 'Finding Java binary';
|
||||
// Now check for the JDK.
|
||||
final String? javaBinary = AndroidSdk.findJavaBinary(
|
||||
androidStudio: _androidStudio,
|
||||
|
@ -212,7 +212,11 @@ abstract class Logger {
|
||||
|
||||
/// A [SilentStatus] or an [AnonymousSpinnerStatus] (depending on whether the
|
||||
/// terminal is fancy enough), already started.
|
||||
Status startSpinner({ VoidCallback? onFinish });
|
||||
Status startSpinner({
|
||||
VoidCallback? onFinish,
|
||||
Duration? timeout,
|
||||
SlowWarningCallback? slowWarningCallback,
|
||||
});
|
||||
|
||||
/// Send an event to be emitted.
|
||||
///
|
||||
@ -368,8 +372,16 @@ class DelegatingLogger implements Logger {
|
||||
}
|
||||
|
||||
@override
|
||||
Status startSpinner({VoidCallback? onFinish}) {
|
||||
return _delegate.startSpinner(onFinish: onFinish);
|
||||
Status startSpinner({
|
||||
VoidCallback? onFinish,
|
||||
Duration? timeout,
|
||||
SlowWarningCallback? slowWarningCallback,
|
||||
}) {
|
||||
return _delegate.startSpinner(
|
||||
onFinish: onFinish,
|
||||
timeout: timeout,
|
||||
slowWarningCallback: slowWarningCallback,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -571,7 +583,11 @@ class StdoutLogger extends Logger {
|
||||
}
|
||||
|
||||
@override
|
||||
Status startSpinner({ VoidCallback? onFinish }) {
|
||||
Status startSpinner({
|
||||
VoidCallback? onFinish,
|
||||
Duration? timeout,
|
||||
SlowWarningCallback? slowWarningCallback,
|
||||
}) {
|
||||
if (_status != null || !supportsColor) {
|
||||
return SilentStatus(
|
||||
onFinish: onFinish,
|
||||
@ -588,6 +604,8 @@ class StdoutLogger extends Logger {
|
||||
stdio: _stdio,
|
||||
stopwatch: _stopwatchFactory.createStopwatch(),
|
||||
terminal: terminal,
|
||||
timeout: timeout,
|
||||
slowWarningCallback: slowWarningCallback,
|
||||
)..start();
|
||||
return _status!;
|
||||
}
|
||||
@ -859,7 +877,11 @@ class BufferLogger extends Logger {
|
||||
}
|
||||
|
||||
@override
|
||||
Status startSpinner({VoidCallback? onFinish}) {
|
||||
Status startSpinner({
|
||||
VoidCallback? onFinish,
|
||||
Duration? timeout,
|
||||
SlowWarningCallback? slowWarningCallback,
|
||||
}) {
|
||||
return SilentStatus(
|
||||
stopwatch: _stopwatchFactory.createStopwatch(),
|
||||
onFinish: onFinish,
|
||||
@ -1111,9 +1133,11 @@ abstract class Status {
|
||||
Status({
|
||||
this.onFinish,
|
||||
required Stopwatch stopwatch,
|
||||
this.timeout,
|
||||
}) : _stopwatch = stopwatch;
|
||||
|
||||
final VoidCallback? onFinish;
|
||||
final Duration? timeout;
|
||||
|
||||
@protected
|
||||
final Stopwatch _stopwatch;
|
||||
@ -1126,6 +1150,9 @@ abstract class Status {
|
||||
return getElapsedAsMilliseconds(_stopwatch.elapsed);
|
||||
}
|
||||
|
||||
@visibleForTesting
|
||||
bool get seemsSlow => timeout != null && _stopwatch.elapsed > timeout!;
|
||||
|
||||
/// Call to start spinning.
|
||||
void start() {
|
||||
assert(!_stopwatch.isRunning);
|
||||
@ -1247,16 +1274,21 @@ class AnonymousSpinnerStatus extends Status {
|
||||
required Stopwatch stopwatch,
|
||||
required Stdio stdio,
|
||||
required Terminal terminal,
|
||||
this.slowWarningCallback,
|
||||
Duration? timeout,
|
||||
}) : _stdio = stdio,
|
||||
_terminal = terminal,
|
||||
_animation = _selectAnimation(terminal),
|
||||
super(
|
||||
onFinish: onFinish,
|
||||
stopwatch: stopwatch,
|
||||
);
|
||||
timeout: timeout,
|
||||
);
|
||||
|
||||
final Stdio _stdio;
|
||||
final Terminal _terminal;
|
||||
String _slowWarning = '';
|
||||
final SlowWarningCallback? slowWarningCallback;
|
||||
|
||||
static const String _backspaceChar = '\b';
|
||||
static const String _clearChar = ' ';
|
||||
@ -1300,9 +1332,10 @@ class AnonymousSpinnerStatus extends Status {
|
||||
Timer? timer;
|
||||
int ticks = 0;
|
||||
int _lastAnimationFrameLength = 0;
|
||||
bool timedOut = false;
|
||||
|
||||
String get _currentAnimationFrame => _animation[ticks % _animation.length];
|
||||
int get _currentLineLength => _lastAnimationFrameLength;
|
||||
int get _currentLineLength => _lastAnimationFrameLength + _slowWarning.length;
|
||||
|
||||
void _writeToStdOut(String message) => _stdio.stdoutWrite(message);
|
||||
|
||||
@ -1332,6 +1365,16 @@ class AnonymousSpinnerStatus extends Status {
|
||||
assert(timer.isActive);
|
||||
_writeToStdOut(_backspaceChar * _lastAnimationFrameLength);
|
||||
ticks += 1;
|
||||
if (seemsSlow) {
|
||||
if (!timedOut) {
|
||||
timedOut = true;
|
||||
_clear(_currentLineLength);
|
||||
}
|
||||
if (_slowWarning == '' && slowWarningCallback != null) {
|
||||
_slowWarning = slowWarningCallback!();
|
||||
_writeToStdOut(_slowWarning);
|
||||
}
|
||||
}
|
||||
final String newFrame = _currentAnimationFrame;
|
||||
_lastAnimationFrameLength = newFrame.runes.length;
|
||||
_writeToStdOut(newFrame);
|
||||
|
@ -315,7 +315,10 @@ class Doctor {
|
||||
|
||||
for (final ValidatorTask validatorTask in startedValidatorTasks ?? startValidatorTasks()) {
|
||||
final DoctorValidator validator = validatorTask.validator;
|
||||
final Status status = _logger.startSpinner();
|
||||
final Status status = _logger.startSpinner(
|
||||
timeout: const Duration(seconds: 2),
|
||||
slowWarningCallback: () => validator.slowWarning,
|
||||
);
|
||||
ValidationResult result;
|
||||
try {
|
||||
result = await validatorTask.result;
|
||||
|
@ -631,7 +631,11 @@ class StreamLogger extends Logger {
|
||||
}
|
||||
|
||||
@override
|
||||
Status startSpinner({ VoidCallback onFinish }) {
|
||||
Status startSpinner({
|
||||
VoidCallback onFinish,
|
||||
Duration timeout,
|
||||
SlowWarningCallback slowWarningCallback,
|
||||
}) {
|
||||
return SilentStatus(
|
||||
stopwatch: Stopwatch(),
|
||||
onFinish: onFinish,
|
||||
|
@ -451,7 +451,7 @@ void main() {
|
||||
FakeAsync().run((FakeAsync time) {
|
||||
final AnonymousSpinnerStatus spinner = AnonymousSpinnerStatus(
|
||||
stdio: mockStdio,
|
||||
stopwatch: stopwatchFactory.createStopwatch(),
|
||||
stopwatch: mockStopwatch,
|
||||
terminal: terminal,
|
||||
)..start();
|
||||
doWhileAsync(time, () => spinner.ticks < 10);
|
||||
@ -479,6 +479,35 @@ void main() {
|
||||
expect(done, isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext('AnonymousSpinnerStatus logs warning after timeout', () async {
|
||||
mockStopwatch = FakeStopwatch();
|
||||
const String warningMessage = 'a warning message.';
|
||||
final bool done = FakeAsync().run<bool>((FakeAsync time) {
|
||||
final AnonymousSpinnerStatus spinner = AnonymousSpinnerStatus(
|
||||
stdio: mockStdio,
|
||||
stopwatch: mockStopwatch,
|
||||
terminal: terminal,
|
||||
slowWarningCallback: () => warningMessage,
|
||||
timeout: const Duration(milliseconds: 100),
|
||||
)..start();
|
||||
// must be greater than the spinner timer duration
|
||||
const Duration timeLapse = Duration(milliseconds: 101);
|
||||
mockStopwatch.elapsed += timeLapse;
|
||||
time.elapse(timeLapse);
|
||||
|
||||
List<String> lines = outputStdout();
|
||||
expect(
|
||||
lines.join(),
|
||||
contains(warningMessage),
|
||||
);
|
||||
|
||||
spinner.stop();
|
||||
lines = outputStdout();
|
||||
return true;
|
||||
});
|
||||
expect(done, isTrue);
|
||||
});
|
||||
|
||||
testWithoutContext('Stdout startProgress on colored terminal', () async {
|
||||
final Logger logger = StdoutLogger(
|
||||
terminal: coloredTerminal,
|
||||
|
Loading…
Reference in New Issue
Block a user