Commit 023b7de1 authored by Dan Rubel's avatar Dan Rubel Committed by GitHub

show device list in flutter doctor output (#5697)

* show device list in flutter doctor output
fixes https://github.com/flutter/flutter/issues/5625
parent 6a323f6f
...@@ -116,26 +116,26 @@ Future<Null> main(List<String> args) async { ...@@ -116,26 +116,26 @@ Future<Null> main(List<String> args) async {
// Print the stack trace on the bots - don't write a crash report. // Print the stack trace on the bots - don't write a crash report.
stderr.writeln('$error'); stderr.writeln('$error');
stderr.writeln(chain.terse.toString()); stderr.writeln(chain.terse.toString());
_exit(1);
} else { } else {
if (error is String) if (error is String)
stderr.writeln('Oops; flutter has exited unexpectedly: "$error".'); stderr.writeln('Oops; flutter has exited unexpectedly: "$error".');
else else
stderr.writeln('Oops; flutter has exited unexpectedly.'); stderr.writeln('Oops; flutter has exited unexpectedly.');
File file = _createCrashReport(args, error, chain); _createCrashReport(args, error, chain).then((File file) {
stderr.writeln(
stderr.writeln( 'Crash report written to ${file.path};\n'
'Crash report written to ${file.path};\n' 'please let us know at https://github.com/flutter/flutter/issues.'
'please let us know at https://github.com/flutter/flutter/issues.' );
); _exit(1);
});
} }
_exit(1);
} }
}); });
} }
File _createCrashReport(List<String> args, dynamic error, Chain chain) { Future<File> _createCrashReport(List<String> args, dynamic error, Chain chain) async {
File crashFile = getUniqueFile(Directory.current, 'flutter', 'log'); File crashFile = getUniqueFile(Directory.current, 'flutter', 'log');
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
...@@ -150,21 +150,21 @@ File _createCrashReport(List<String> args, dynamic error, Chain chain) { ...@@ -150,21 +150,21 @@ File _createCrashReport(List<String> args, dynamic error, Chain chain) {
buffer.writeln('```\n${chain.terse}```\n'); buffer.writeln('```\n${chain.terse}```\n');
buffer.writeln('## flutter doctor\n'); buffer.writeln('## flutter doctor\n');
buffer.writeln('```\n${_doctorText()}```'); buffer.writeln('```\n${await _doctorText()}```');
crashFile.writeAsStringSync(buffer.toString()); crashFile.writeAsStringSync(buffer.toString());
return crashFile; return crashFile;
} }
String _doctorText() { Future<String> _doctorText() async {
try { try {
BufferLogger logger = new BufferLogger(); BufferLogger logger = new BufferLogger();
AppContext appContext = new AppContext(); AppContext appContext = new AppContext();
appContext[Logger] = logger; appContext[Logger] = logger;
appContext.runInZone(() => doctor.diagnose()); await appContext.runInZone(() => doctor.diagnose());
return logger.statusText; return logger.statusText;
} catch (error, trace) { } catch (error, trace) {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async';
import 'dart:io'; import 'dart:io';
import '../base/os.dart'; import '../base/os.dart';
...@@ -22,7 +23,7 @@ class AndroidWorkflow extends DoctorValidator implements Workflow { ...@@ -22,7 +23,7 @@ class AndroidWorkflow extends DoctorValidator implements Workflow {
bool get canLaunchDevices => androidSdk != null && androidSdk.validateSdkWellFormed().isEmpty; bool get canLaunchDevices => androidSdk != null && androidSdk.validateSdkWellFormed().isEmpty;
@override @override
ValidationResult validate() { Future<ValidationResult> validate() async {
List<ValidationMessage> messages = <ValidationMessage>[]; List<ValidationMessage> messages = <ValidationMessage>[];
ValidationType type = ValidationType.missing; ValidationType type = ValidationType.missing;
String sdkVersionText; String sdkVersionText;
......
...@@ -117,7 +117,7 @@ class CreateCommand extends FlutterCommand { ...@@ -117,7 +117,7 @@ class CreateCommand extends FlutterCommand {
// Run doctor; tell the user the next steps. // Run doctor; tell the user the next steps.
if (doctor.canLaunchAnything) { if (doctor.canLaunchAnything) {
// Let them know a summary of the state of their tooling. // Let them know a summary of the state of their tooling.
doctor.summary(); await doctor.summary();
printStatus(''' printStatus('''
All done! In order to run your application, type: All done! In order to run your application, type:
...@@ -131,7 +131,7 @@ All done! In order to run your application, type: ...@@ -131,7 +131,7 @@ All done! In order to run your application, type:
printStatus(''); printStatus('');
// Give the user more detailed analysis. // Give the user more detailed analysis.
doctor.diagnose(); await doctor.diagnose();
printStatus(''); printStatus('');
printStatus("After installing components, run 'flutter doctor' in order to " printStatus("After installing components, run 'flutter doctor' in order to "
"re-validate your setup."); "re-validate your setup.");
......
...@@ -19,7 +19,7 @@ class DoctorCommand extends FlutterCommand { ...@@ -19,7 +19,7 @@ class DoctorCommand extends FlutterCommand {
@override @override
Future<int> runInProject() async { Future<int> runInProject() async {
doctor.diagnose(); await doctor.diagnose();
return 0; return 0;
} }
} }
...@@ -88,7 +88,7 @@ class SetupCommand extends FlutterCommand { ...@@ -88,7 +88,7 @@ class SetupCommand extends FlutterCommand {
// run doctor // run doctor
printStatus('\nFlutter doctor:'); printStatus('\nFlutter doctor:');
bool goodInstall = doctor.diagnose(); bool goodInstall = await doctor.diagnose();
// Validate that flutter is available on the path. // Validate that flutter is available on the path.
if (os.which('flutter') == null) { if (os.which('flutter') == null) {
......
...@@ -236,7 +236,7 @@ abstract class Device { ...@@ -236,7 +236,7 @@ abstract class Device {
@override @override
String toString() => name; String toString() => name;
static void printDevices(List<Device> devices) { static Iterable<String> descriptions(List<Device> devices) {
int nameWidth = 0; int nameWidth = 0;
int idWidth = 0; int idWidth = 0;
...@@ -245,12 +245,16 @@ abstract class Device { ...@@ -245,12 +245,16 @@ abstract class Device {
idWidth = math.max(idWidth, device.id.length); idWidth = math.max(idWidth, device.id.length);
} }
for (Device device in devices) { return devices.map((Device device) {
String supportIndicator = device.isSupported() ? '' : ' (unsupported)'; String supportIndicator = device.isSupported() ? '' : ' (unsupported)';
printStatus('${device.name.padRight(nameWidth)} • ' return '${device.name.padRight(nameWidth)} • '
'${device.id.padRight(idWidth)} • ' '${device.id.padRight(idWidth)} • '
'${getNameForTargetPlatform(device.platform)}$supportIndicator'); '${getNameForTargetPlatform(device.platform)}$supportIndicator';
} });
}
static void printDevices(List<Device> devices) {
descriptions(devices).forEach((String msg) => printStatus(msg));
} }
} }
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async';
import 'dart:convert' show JSON; import 'dart:convert' show JSON;
import 'dart:io'; import 'dart:io';
...@@ -10,6 +11,7 @@ import 'package:path/path.dart' as path; ...@@ -10,6 +11,7 @@ import 'package:path/path.dart' as path;
import 'android/android_workflow.dart'; import 'android/android_workflow.dart';
import 'base/context.dart'; import 'base/context.dart';
import 'base/os.dart'; import 'base/os.dart';
import 'device.dart';
import 'globals.dart'; import 'globals.dart';
import 'ios/ios_workflow.dart'; import 'ios/ios_workflow.dart';
import 'version.dart'; import 'version.dart';
...@@ -38,6 +40,7 @@ class Doctor { ...@@ -38,6 +40,7 @@ class Doctor {
_validators.add(_iosWorkflow); _validators.add(_iosWorkflow);
_validators.add(new AtomValidator()); _validators.add(new AtomValidator());
_validators.add(new DeviceValidator());
} }
static void initGlobal() { static void initGlobal() {
...@@ -59,15 +62,17 @@ class Doctor { ...@@ -59,15 +62,17 @@ class Doctor {
} }
/// Print a summary of the state of the tooling, as well as how to get more info. /// Print a summary of the state of the tooling, as well as how to get more info.
void summary() => printStatus(summaryText); Future<Null> summary() async {
printStatus(await summaryText);
}
String get summaryText { Future<String> get summaryText async {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
bool allGood = true; bool allGood = true;
for (DoctorValidator validator in _validators) { for (DoctorValidator validator in _validators) {
ValidationResult result = validator.validate(); ValidationResult result = await validator.validate();
buffer.write('${result.leadingBox} ${validator.title} is '); buffer.write('${result.leadingBox} ${validator.title} is ');
if (result.type == ValidationType.missing) if (result.type == ValidationType.missing)
buffer.write('not installed.'); buffer.write('not installed.');
...@@ -94,7 +99,7 @@ class Doctor { ...@@ -94,7 +99,7 @@ class Doctor {
} }
/// Print verbose information about the state of installed tooling. /// Print verbose information about the state of installed tooling.
bool diagnose() { Future<bool> diagnose() async {
bool firstLine = true; bool firstLine = true;
bool doctorResult = true; bool doctorResult = true;
...@@ -103,7 +108,7 @@ class Doctor { ...@@ -103,7 +108,7 @@ class Doctor {
printStatus(''); printStatus('');
firstLine = false; firstLine = false;
ValidationResult result = validator.validate(); ValidationResult result = await validator.validate();
if (result.type == ValidationType.missing) if (result.type == ValidationType.missing)
doctorResult = false; doctorResult = false;
...@@ -155,7 +160,7 @@ abstract class DoctorValidator { ...@@ -155,7 +160,7 @@ abstract class DoctorValidator {
final String title; final String title;
ValidationResult validate(); Future<ValidationResult> validate();
} }
class ValidationResult { class ValidationResult {
...@@ -193,7 +198,7 @@ class _FlutterValidator extends DoctorValidator { ...@@ -193,7 +198,7 @@ class _FlutterValidator extends DoctorValidator {
_FlutterValidator() : super('Flutter'); _FlutterValidator() : super('Flutter');
@override @override
ValidationResult validate() { Future<ValidationResult> validate() async {
List<ValidationMessage> messages = <ValidationMessage>[]; List<ValidationMessage> messages = <ValidationMessage>[];
ValidationType valid = ValidationType.installed; ValidationType valid = ValidationType.installed;
...@@ -239,7 +244,7 @@ class AtomValidator extends DoctorValidator { ...@@ -239,7 +244,7 @@ class AtomValidator extends DoctorValidator {
} }
@override @override
ValidationResult validate() { Future<ValidationResult> validate() async {
List<ValidationMessage> messages = <ValidationMessage>[]; List<ValidationMessage> messages = <ValidationMessage>[];
int installCount = 0; int installCount = 0;
...@@ -291,3 +296,20 @@ class AtomValidator extends DoctorValidator { ...@@ -291,3 +296,20 @@ class AtomValidator extends DoctorValidator {
return FileSystemEntity.isDirectorySync(packagePath); return FileSystemEntity.isDirectorySync(packagePath);
} }
} }
class DeviceValidator extends DoctorValidator {
DeviceValidator() : super('Connected devices');
@override
Future<ValidationResult> validate() async {
List<Device> devices = await deviceManager.getAllConnectedDevices();
List<ValidationMessage> messages;
if (devices.isEmpty) {
messages = <ValidationMessage>[new ValidationMessage('None')];
} else {
messages = Device.descriptions(devices)
.map((String msg) => new ValidationMessage(msg)).toList();
}
return new ValidationResult(ValidationType.installed, messages);
}
}
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async';
import 'dart:io'; import 'dart:io';
import '../base/os.dart'; import '../base/os.dart';
...@@ -29,7 +30,7 @@ class IOSWorkflow extends DoctorValidator implements Workflow { ...@@ -29,7 +30,7 @@ class IOSWorkflow extends DoctorValidator implements Workflow {
bool get hasIDeviceId => exitsHappy(<String>['idevice_id', '-h']); bool get hasIDeviceId => exitsHappy(<String>['idevice_id', '-h']);
@override @override
ValidationResult validate() { Future<ValidationResult> validate() async {
List<ValidationMessage> messages = <ValidationMessage>[]; List<ValidationMessage> messages = <ValidationMessage>[];
int installCount = 0; int installCount = 0;
String xcodeVersionInfo; String xcodeVersionInfo;
......
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