From 9367b86abebdbf65b6a56625e076b4642620a8c3 Mon Sep 17 00:00:00 2001 From: Devon Carew Date: Tue, 23 Feb 2016 10:25:14 -0800 Subject: [PATCH] add a validator for Atom --- .../lib/src/android/android_workflow.dart | 8 +- .../lib/src/application_package.dart | 3 +- packages/flutter_tools/lib/src/doctor.dart | 98 ++++++++++++++----- .../lib/src/ios/ios_workflow.dart | 28 +++--- 4 files changed, 95 insertions(+), 42 deletions(-) diff --git a/packages/flutter_tools/lib/src/android/android_workflow.dart b/packages/flutter_tools/lib/src/android/android_workflow.dart index 52b994219b..4554093b3f 100644 --- a/packages/flutter_tools/lib/src/android/android_workflow.dart +++ b/packages/flutter_tools/lib/src/android/android_workflow.dart @@ -7,7 +7,7 @@ import '../globals.dart'; import 'android_sdk.dart'; class AndroidWorkflow extends Workflow { - AndroidWorkflow() : super('Android'); + String get label => 'Android toolchain'; bool get appliesToHostPlatform => true; @@ -17,11 +17,11 @@ class AndroidWorkflow extends Workflow { ValidationResult validate() { Validator androidValidator = new Validator( - '$name toolchain', + label, description: 'develop for Android devices' ); - Function _sdkExists = () { + ValidationType sdkExists() { return androidSdk == null ? ValidationType.missing : ValidationType.installed; }; @@ -29,7 +29,7 @@ class AndroidWorkflow extends Workflow { 'Android SDK', description: 'enable development for Android devices', resolution: 'Download at https://developer.android.com/sdk/', - validatorFunction: _sdkExists + validatorFunction: sdkExists )); return androidValidator.validate(); diff --git a/packages/flutter_tools/lib/src/application_package.dart b/packages/flutter_tools/lib/src/application_package.dart index 3cb8d846ca..2f77972ec2 100644 --- a/packages/flutter_tools/lib/src/application_package.dart +++ b/packages/flutter_tools/lib/src/application_package.dart @@ -146,8 +146,7 @@ class ApplicationPackageStore { case TargetPlatform.iOS: case TargetPlatform.iOSSimulator: - if (iOS == null) - iOS = new IOSApp.fromBuildConfiguration(config); + iOS ??= new IOSApp.fromBuildConfiguration(config); break; case TargetPlatform.mac: diff --git a/packages/flutter_tools/lib/src/doctor.dart b/packages/flutter_tools/lib/src/doctor.dart index d5f1d99ede..b98bc401e3 100644 --- a/packages/flutter_tools/lib/src/doctor.dart +++ b/packages/flutter_tools/lib/src/doctor.dart @@ -2,20 +2,27 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:io'; + import 'android/android_workflow.dart'; import 'base/context.dart'; +import 'base/process.dart'; import 'globals.dart'; import 'ios/ios_workflow.dart'; +// TODO(devoncarew): Make it easy to add version information to the `doctor` printout. + class Doctor { Doctor() { _iosWorkflow = new IOSWorkflow(); if (_iosWorkflow.appliesToHostPlatform) - _workflows.add(_iosWorkflow); + _validators.add(_iosWorkflow); _androidWorkflow = new AndroidWorkflow(); if (_androidWorkflow.appliesToHostPlatform) - _workflows.add(_androidWorkflow); + _validators.add(_androidWorkflow); + + _validators.add(new _AtomValidator()); } static void initGlobal() { @@ -30,9 +37,9 @@ class Doctor { AndroidWorkflow get androidWorkflow => _androidWorkflow; - List _workflows = []; + List _validators = []; - List get workflows => _workflows; + Iterable get workflows => _validators.where((DoctorValidator validator) => validator is Workflow); /// Print a summary of the state of the tooling, as well as how to get more info. void summary() => printStatus(summaryText); @@ -42,9 +49,9 @@ class Doctor { bool allGood = true; - for (Workflow workflow in workflows) { - ValidationResult result = workflow.validate(); - buffer.write('${result.leadingBox} The ${workflow.name} toolchain is '); + for (DoctorValidator validator in _validators) { + ValidationResult result = validator.validate(); + buffer.write('${result.leadingBox} The ${validator.label} is '); if (result.type == ValidationType.missing) buffer.writeln('not installed.'); else if (result.type == ValidationType.partial) @@ -65,10 +72,12 @@ class Doctor { /// Print verbose information about the state of installed tooling. void diagnose() { - for (int i = 0; i < workflows.length; i++) { - if (i > 0) + bool firstLine = true; + for (DoctorValidator validator in _validators) { + if (!firstLine) printStatus(''); - workflows[i].diagnose(); + firstLine = false; + validator.diagnose(); } } @@ -77,12 +86,17 @@ class Doctor { bool get canLaunchAnything => workflows.any((Workflow workflow) => workflow.canLaunchDevices); } +abstract class DoctorValidator { + String get label; + + ValidationResult validate(); + + /// Print verbose information about the state of the workflow. + void diagnose(); +} + /// A series of tools and required install steps for a target platform (iOS or Android). -abstract class Workflow { - Workflow(this.name); - - final String name; - +abstract class Workflow extends DoctorValidator { /// Whether the workflow applies to this platform (as in, should we ever try and use it). bool get appliesToHostPlatform; @@ -91,13 +105,6 @@ abstract class Workflow { /// Could this thing launch *something*? It may still have minor issues. bool get canLaunchDevices; - - ValidationResult validate(); - - /// Print verbose information about the state of the workflow. - void diagnose(); - - String toString() => name; } enum ValidationType { @@ -206,3 +213,50 @@ class ValidationResult { return results; } } + +class _AtomValidator extends DoctorValidator { + String get label => 'Atom development environment'; + + ValidationResult validate() { + Validator atomValidator = new Validator( + label, + description: 'a lightweight development environment for Flutter' + ); + + ValidationType atomExists() { + return exitsHappy(['atom', '--version']) ? ValidationType.installed : ValidationType.missing; + }; + + ValidationType flutterPluginExists() { + try { + // apm list -b -p -i + ProcessResult result = Process.runSync('apm', ['list', '-b', '-p', '-i']); + if (result.exitCode != 0) + return ValidationType.missing; + bool available = (result.stdout as String).split('\n').any((String line) { + return line.startsWith('flutter@'); + }); + return available ? ValidationType.installed : ValidationType.missing; + } catch (error) { + return ValidationType.missing; + } + }; + + atomValidator.addValidator(new Validator( + 'Atom editor', + resolution: 'Download at https://atom.io', + validatorFunction: atomExists + )); + + atomValidator.addValidator(new Validator( + 'Flutter plugin', + description: 'adds Flutter specific functionality to Atom', + resolution: "Install the 'flutter' plugin in Atom or run 'apm install flutter'", + validatorFunction: flutterPluginExists + )); + + return atomValidator.validate(); + } + + void diagnose() => validate().print(); +} diff --git a/packages/flutter_tools/lib/src/ios/ios_workflow.dart b/packages/flutter_tools/lib/src/ios/ios_workflow.dart index 87fd043a88..4a1d047f1e 100644 --- a/packages/flutter_tools/lib/src/ios/ios_workflow.dart +++ b/packages/flutter_tools/lib/src/ios/ios_workflow.dart @@ -10,7 +10,7 @@ import '../globals.dart'; import 'mac.dart'; class IOSWorkflow extends Workflow { - IOSWorkflow() : super('iOS'); + String get label => 'iOS toolchain'; bool get appliesToHostPlatform => Platform.isMacOS; @@ -23,33 +23,33 @@ class IOSWorkflow extends Workflow { ValidationResult validate() { Validator iosValidator = new Validator( - '$name toolchain', + label, description: 'develop for iOS devices' ); - Function _xcodeExists = () { + ValidationType xcodeExists() { return xcode.isInstalled ? ValidationType.installed : ValidationType.missing; }; - Function _xcodeVersionSatisfactory = () { + ValidationType xcodeVersionSatisfactory() { return xcode.isInstalledAndMeetsVersionCheck ? ValidationType.installed : ValidationType.missing; }; - Function _xcodeEulaSigned = () { + ValidationType xcodeEulaSigned() { return xcode.eulaSigned ? ValidationType.installed : ValidationType.missing; }; - Function _brewExists = () { + ValidationType brewExists() { return exitsHappy(['brew', '-v']) ? ValidationType.installed : ValidationType.missing; }; - Function _ideviceinstallerExists = () { + ValidationType ideviceinstallerExists() { return exitsHappy(['ideviceinstaller', '-h']) ? ValidationType.installed : ValidationType.missing; }; - Function _iosdeployExists = () { + ValidationType iosdeployExists() { return hasIdeviceId ? ValidationType.installed : ValidationType.missing; }; @@ -57,7 +57,7 @@ class IOSWorkflow extends Workflow { 'XCode', description: 'enable development for iOS devices', resolution: 'Download at https://developer.apple.com/xcode/download/', - validatorFunction: _xcodeExists + validatorFunction: xcodeExists ); iosValidator.addValidator(xcodeValidator); @@ -66,21 +66,21 @@ class IOSWorkflow extends Workflow { 'version', description: 'Xcode minimum version of $kXcodeRequiredVersionMajor.$kXcodeRequiredVersionMinor.0', resolution: 'Download the latest version or update via the Mac App Store', - validatorFunction: _xcodeVersionSatisfactory + validatorFunction: xcodeVersionSatisfactory )); xcodeValidator.addValidator(new Validator( 'EULA', description: 'XCode end user license agreement', resolution: "Open XCode or run the command 'sudo xcodebuild -license'", - validatorFunction: _xcodeEulaSigned + validatorFunction: xcodeEulaSigned )); Validator brewValidator = new Validator( 'brew', description: 'install additional development packages', resolution: 'Download at http://brew.sh/', - validatorFunction: _brewExists + validatorFunction: brewExists ); iosValidator.addValidator(brewValidator); @@ -89,14 +89,14 @@ class IOSWorkflow extends Workflow { 'ideviceinstaller', description: 'discover connected iOS devices', resolution: "Install via 'brew install ideviceinstaller'", - validatorFunction: _ideviceinstallerExists + validatorFunction: ideviceinstallerExists )); brewValidator.addValidator(new Validator( 'ios-deploy', description: 'deploy to connected iOS devices', resolution: "Install via 'brew install ios-deploy'", - validatorFunction: _iosdeployExists + validatorFunction: iosdeployExists )); return iosValidator.validate();