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