Unverified Commit f5c268a7 authored by Jenn Magder's avatar Jenn Magder Committed by GitHub

Migrate android_workflow to null safety (#79806)

parent 9a2d9c81
...@@ -2,9 +2,6 @@ ...@@ -2,9 +2,6 @@
// 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.
// @dart = 2.8
import 'package:meta/meta.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
import '../base/common.dart'; import '../base/common.dart';
...@@ -26,9 +23,9 @@ const int kAndroidSdkMinVersion = 29; ...@@ -26,9 +23,9 @@ const int kAndroidSdkMinVersion = 29;
final Version kAndroidJavaMinVersion = Version(1, 8, 0); final Version kAndroidJavaMinVersion = Version(1, 8, 0);
final Version kAndroidSdkBuildToolsMinVersion = Version(28, 0, 3); final Version kAndroidSdkBuildToolsMinVersion = Version(28, 0, 3);
AndroidWorkflow get androidWorkflow => context.get<AndroidWorkflow>(); AndroidWorkflow? get androidWorkflow => context.get<AndroidWorkflow>();
AndroidValidator get androidValidator => context.get<AndroidValidator>(); AndroidValidator? get androidValidator => context.get<AndroidValidator>();
AndroidLicenseValidator get androidLicenseValidator => context.get<AndroidLicenseValidator>(); AndroidLicenseValidator? get androidLicenseValidator => context.get<AndroidLicenseValidator>();
enum LicensesAccepted { enum LicensesAccepted {
none, none,
...@@ -43,14 +40,14 @@ final RegExp licenseAccepted = RegExp(r'All SDK package licenses accepted.'); ...@@ -43,14 +40,14 @@ final RegExp licenseAccepted = RegExp(r'All SDK package licenses accepted.');
class AndroidWorkflow implements Workflow { class AndroidWorkflow implements Workflow {
AndroidWorkflow({ AndroidWorkflow({
@required AndroidSdk androidSdk, required AndroidSdk? androidSdk,
@required FeatureFlags featureFlags, required FeatureFlags featureFlags,
@required OperatingSystemUtils operatingSystemUtils, required OperatingSystemUtils operatingSystemUtils,
}) : _androidSdk = androidSdk, }) : _androidSdk = androidSdk,
_featureFlags = featureFlags, _featureFlags = featureFlags,
_operatingSystemUtils = operatingSystemUtils; _operatingSystemUtils = operatingSystemUtils;
final AndroidSdk _androidSdk; final AndroidSdk? _androidSdk;
final FeatureFlags _featureFlags; final FeatureFlags _featureFlags;
final OperatingSystemUtils _operatingSystemUtils; final OperatingSystemUtils _operatingSystemUtils;
...@@ -61,17 +58,17 @@ class AndroidWorkflow implements Workflow { ...@@ -61,17 +58,17 @@ class AndroidWorkflow implements Workflow {
@override @override
bool get canListDevices => _androidSdk != null bool get canListDevices => _androidSdk != null
&& _androidSdk.adbPath != null; && _androidSdk?.adbPath != null;
@override @override
bool get canLaunchDevices => _androidSdk != null bool get canLaunchDevices => _androidSdk != null
&& _androidSdk.adbPath != null && _androidSdk?.adbPath != null
&& _androidSdk.validateSdkWellFormed().isEmpty; && _androidSdk?.validateSdkWellFormed().isEmpty == true;
@override @override
bool get canListEmulators => _androidSdk != null bool get canListEmulators => _androidSdk != null
&& _androidSdk.adbPath != null && _androidSdk?.adbPath != null
&& _androidSdk.emulatorPath != null; && _androidSdk?.emulatorPath != null;
} }
/// A validator that checks if the Android SDK and Java SDK are available and /// A validator that checks if the Android SDK and Java SDK are available and
...@@ -83,13 +80,13 @@ class AndroidWorkflow implements Workflow { ...@@ -83,13 +80,13 @@ class AndroidWorkflow implements Workflow {
/// Android Studio. /// Android Studio.
class AndroidValidator extends DoctorValidator { class AndroidValidator extends DoctorValidator {
AndroidValidator({ AndroidValidator({
@required AndroidSdk androidSdk, required AndroidSdk? androidSdk,
@required AndroidStudio androidStudio, required AndroidStudio? androidStudio,
@required FileSystem fileSystem, required FileSystem fileSystem,
@required Logger logger, required Logger logger,
@required Platform platform, required Platform platform,
@required ProcessManager processManager, required ProcessManager processManager,
@required UserMessages userMessages, required UserMessages userMessages,
}) : _androidSdk = androidSdk, }) : _androidSdk = androidSdk,
_androidStudio = androidStudio, _androidStudio = androidStudio,
_fileSystem = fileSystem, _fileSystem = fileSystem,
...@@ -105,8 +102,8 @@ class AndroidValidator extends DoctorValidator { ...@@ -105,8 +102,8 @@ class AndroidValidator extends DoctorValidator {
_userMessages = userMessages, _userMessages = userMessages,
super('Android toolchain - develop for Android devices'); super('Android toolchain - develop for Android devices');
final AndroidSdk _androidSdk; final AndroidSdk? _androidSdk;
final AndroidStudio _androidStudio; final AndroidStudio? _androidStudio;
final FileSystem _fileSystem; final FileSystem _fileSystem;
final Logger _logger; final Logger _logger;
final OperatingSystemUtils _operatingSystemUtils; final OperatingSystemUtils _operatingSystemUtils;
...@@ -116,7 +113,7 @@ class AndroidValidator extends DoctorValidator { ...@@ -116,7 +113,7 @@ class AndroidValidator extends DoctorValidator {
@override @override
String get slowWarning => '${_task ?? 'This'} is taking a long time...'; String get slowWarning => '${_task ?? 'This'} is taking a long time...';
String _task; String? _task;
/// Finds the semantic version anywhere in a text. /// Finds the semantic version anywhere in a text.
static final RegExp _javaVersionPattern = RegExp(r'(\d+)(\.(\d+)(\.(\d+))?)?'); static final RegExp _javaVersionPattern = RegExp(r'(\d+)(\.(\d+)(\.(\d+))?)?');
...@@ -124,9 +121,15 @@ class AndroidValidator extends DoctorValidator { ...@@ -124,9 +121,15 @@ class AndroidValidator extends DoctorValidator {
/// `java -version` response is not only a number, but also includes other /// `java -version` response is not only a number, but also includes other
/// information eg. `openjdk version "1.7.0_212"`. /// information eg. `openjdk version "1.7.0_212"`.
/// This method extracts only the semantic version from from that response. /// This method extracts only the semantic version from from that response.
static String _extractJavaVersion(String text) { static String? _extractJavaVersion(String? text) {
final Match match = _javaVersionPattern.firstMatch(text ?? ''); if (text == null || text.isEmpty) {
return text?.substring(match.start, match.end); return null;
}
final Match? match = _javaVersionPattern.firstMatch(text);
if (match == null) {
return null;
}
return text.substring(match.start, match.end);
} }
/// Returns false if we cannot determine the Java version or if the version /// Returns false if we cannot determine the Java version or if the version
...@@ -138,7 +141,7 @@ class AndroidValidator extends DoctorValidator { ...@@ -138,7 +141,7 @@ class AndroidValidator extends DoctorValidator {
messages.add(ValidationMessage.error(_userMessages.androidCantRunJavaBinary(javaBinary))); messages.add(ValidationMessage.error(_userMessages.androidCantRunJavaBinary(javaBinary)));
return false; return false;
} }
String javaVersionText; String? javaVersionText;
try { try {
_logger.printTrace('java -version'); _logger.printTrace('java -version');
final ProcessResult result = await _processManager.run(<String>[javaBinary, '-version']); final ProcessResult result = await _processManager.run(<String>[javaBinary, '-version']);
...@@ -149,12 +152,12 @@ class AndroidValidator extends DoctorValidator { ...@@ -149,12 +152,12 @@ class AndroidValidator extends DoctorValidator {
} on Exception catch (error) { } on Exception catch (error) {
_logger.printTrace(error.toString()); _logger.printTrace(error.toString());
} }
if (javaVersionText == null || javaVersionText.isEmpty) { final Version? javaVersion = Version.parse(_extractJavaVersion(javaVersionText));
if (javaVersionText == null || javaVersionText.isEmpty || javaVersion == null) {
// Could not determine the java version. // Could not determine the java version.
messages.add(ValidationMessage.error(_userMessages.androidUnknownJavaVersion)); messages.add(ValidationMessage.error(_userMessages.androidUnknownJavaVersion));
return false; return false;
} }
final Version javaVersion = Version.parse(_extractJavaVersion(javaVersionText));
if (javaVersion < kAndroidJavaMinVersion) { if (javaVersion < kAndroidJavaMinVersion) {
messages.add(ValidationMessage.error(_userMessages.androidJavaMinimumVersion(javaVersionText))); messages.add(ValidationMessage.error(_userMessages.androidJavaMinimumVersion(javaVersionText)));
return false; return false;
...@@ -169,11 +172,11 @@ class AndroidValidator extends DoctorValidator { ...@@ -169,11 +172,11 @@ class AndroidValidator extends DoctorValidator {
@override @override
Future<ValidationResult> validate() async { Future<ValidationResult> validate() async {
final List<ValidationMessage> messages = <ValidationMessage>[]; final List<ValidationMessage> messages = <ValidationMessage>[];
final AndroidSdk? androidSdk = _androidSdk;
if (_androidSdk == null) { if (androidSdk == null) {
// No Android SDK found. // No Android SDK found.
if (_platform.environment.containsKey(kAndroidHome)) { if (_platform.environment.containsKey(kAndroidHome)) {
final String androidHomeDir = _platform.environment[kAndroidHome]; final String androidHomeDir = _platform.environment[kAndroidHome]!;
messages.add(ValidationMessage.error(_userMessages.androidBadSdkDir(kAndroidHome, androidHomeDir))); messages.add(ValidationMessage.error(_userMessages.androidBadSdkDir(kAndroidHome, androidHomeDir)));
} else { } else {
// Instruct user to set [kAndroidSdkRoot] and not deprecated [kAndroidHome] // Instruct user to set [kAndroidSdkRoot] and not deprecated [kAndroidHome]
...@@ -183,19 +186,20 @@ class AndroidValidator extends DoctorValidator { ...@@ -183,19 +186,20 @@ class AndroidValidator extends DoctorValidator {
return ValidationResult(ValidationType.missing, messages); return ValidationResult(ValidationType.missing, messages);
} }
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);
} }
messages.add(ValidationMessage(_userMessages.androidSdkLocation(_androidSdk.directory?.path))); messages.add(ValidationMessage(_userMessages.androidSdkLocation(androidSdk.directory.path)));
String sdkVersionText; String? sdkVersionText;
if (_androidSdk.latestVersion != null) { final AndroidSdkVersion? androidSdkLatestVersion = androidSdk.latestVersion;
if (_androidSdk.latestVersion.sdkLevel < kAndroidSdkMinVersion || _androidSdk.latestVersion.buildToolsVersion < kAndroidSdkBuildToolsMinVersion) { if (androidSdkLatestVersion != null) {
if (androidSdkLatestVersion.sdkLevel < kAndroidSdkMinVersion || androidSdkLatestVersion.buildToolsVersion < kAndroidSdkBuildToolsMinVersion) {
messages.add(ValidationMessage.error( messages.add(ValidationMessage.error(
_userMessages.androidSdkBuildToolsOutdated( _userMessages.androidSdkBuildToolsOutdated(
_androidSdk.sdkManagerPath, _androidSdk!.sdkManagerPath,
kAndroidSdkMinVersion, kAndroidSdkMinVersion,
kAndroidSdkBuildToolsMinVersion.toString(), kAndroidSdkBuildToolsMinVersion.toString(),
_platform, _platform,
...@@ -203,25 +207,25 @@ class AndroidValidator extends DoctorValidator { ...@@ -203,25 +207,25 @@ class AndroidValidator extends DoctorValidator {
); );
return ValidationResult(ValidationType.missing, messages); return ValidationResult(ValidationType.missing, messages);
} }
sdkVersionText = _userMessages.androidStatusInfo(_androidSdk.latestVersion.buildToolsVersionName); sdkVersionText = _userMessages.androidStatusInfo(androidSdkLatestVersion.buildToolsVersionName);
messages.add(ValidationMessage(_userMessages.androidSdkPlatformToolsVersion( messages.add(ValidationMessage(_userMessages.androidSdkPlatformToolsVersion(
_androidSdk.latestVersion.platformName, androidSdkLatestVersion.platformName,
_androidSdk.latestVersion.buildToolsVersionName))); androidSdkLatestVersion.buildToolsVersionName)));
} else { } else {
messages.add(ValidationMessage.error(_userMessages.androidMissingSdkInstructions(_platform))); messages.add(ValidationMessage.error(_userMessages.androidMissingSdkInstructions(_platform)));
} }
if (_platform.environment.containsKey(kAndroidHome)) { if (_platform.environment.containsKey(kAndroidHome)) {
final String androidHomeDir = _platform.environment[kAndroidHome]; final String androidHomeDir = _platform.environment[kAndroidHome]!;
messages.add(ValidationMessage('$kAndroidHome = $androidHomeDir')); messages.add(ValidationMessage('$kAndroidHome = $androidHomeDir'));
} }
if (_platform.environment.containsKey(kAndroidSdkRoot)) { if (_platform.environment.containsKey(kAndroidSdkRoot)) {
final String androidSdkRoot = _platform.environment[kAndroidSdkRoot]; final String androidSdkRoot = _platform.environment[kAndroidSdkRoot]!;
messages.add(ValidationMessage('$kAndroidSdkRoot = $androidSdkRoot')); messages.add(ValidationMessage('$kAndroidSdkRoot = $androidSdkRoot'));
} }
final List<String> validationResult = _androidSdk.validateSdkWellFormed(); final List<String> validationResult = androidSdk.validateSdkWellFormed();
if (validationResult.isNotEmpty) { if (validationResult.isNotEmpty) {
// Android SDK is not functional. // Android SDK is not functional.
...@@ -233,7 +237,7 @@ class AndroidValidator extends DoctorValidator { ...@@ -233,7 +237,7 @@ class AndroidValidator extends DoctorValidator {
} }
// Now check for the JDK. // Now check for the JDK.
final String javaBinary = AndroidSdk.findJavaBinary( final String? javaBinary = AndroidSdk.findJavaBinary(
androidStudio: _androidStudio, androidStudio: _androidStudio,
fileSystem: _fileSystem, fileSystem: _fileSystem,
operatingSystemUtils: _operatingSystemUtils, operatingSystemUtils: _operatingSystemUtils,
...@@ -259,15 +263,15 @@ class AndroidValidator extends DoctorValidator { ...@@ -259,15 +263,15 @@ class AndroidValidator extends DoctorValidator {
/// SDK have been accepted. /// SDK have been accepted.
class AndroidLicenseValidator extends DoctorValidator { class AndroidLicenseValidator extends DoctorValidator {
AndroidLicenseValidator({ AndroidLicenseValidator({
@required AndroidSdk androidSdk, required AndroidSdk androidSdk,
@required Platform platform, required Platform platform,
@required OperatingSystemUtils operatingSystemUtils, required OperatingSystemUtils operatingSystemUtils,
@required FileSystem fileSystem, required FileSystem fileSystem,
@required ProcessManager processManager, required ProcessManager processManager,
@required Logger logger, required Logger logger,
@required AndroidStudio androidStudio, required AndroidStudio? androidStudio,
@required Stdio stdio, required Stdio stdio,
@required UserMessages userMessages, required UserMessages userMessages,
}) : _androidSdk = androidSdk, }) : _androidSdk = androidSdk,
_platform = platform, _platform = platform,
_operatingSystemUtils = operatingSystemUtils, _operatingSystemUtils = operatingSystemUtils,
...@@ -280,7 +284,7 @@ class AndroidLicenseValidator extends DoctorValidator { ...@@ -280,7 +284,7 @@ class AndroidLicenseValidator extends DoctorValidator {
super('Android license subvalidator'); super('Android license subvalidator');
final AndroidSdk _androidSdk; final AndroidSdk _androidSdk;
final AndroidStudio _androidStudio; final AndroidStudio? _androidStudio;
final Stdio _stdio; final Stdio _stdio;
final OperatingSystemUtils _operatingSystemUtils; final OperatingSystemUtils _operatingSystemUtils;
final Platform _platform; final Platform _platform;
...@@ -303,7 +307,7 @@ class AndroidLicenseValidator extends DoctorValidator { ...@@ -303,7 +307,7 @@ class AndroidLicenseValidator extends DoctorValidator {
return ValidationResult(ValidationType.missing, messages); return ValidationResult(ValidationType.missing, messages);
} }
final String sdkVersionText = _userMessages.androidStatusInfo(_androidSdk.latestVersion.buildToolsVersionName); final String sdkVersionText = _userMessages.androidStatusInfo(_androidSdk.latestVersion!.buildToolsVersionName);
// Check for licenses. // Check for licenses.
switch (await licensesAccepted) { switch (await licensesAccepted) {
...@@ -324,7 +328,7 @@ class AndroidLicenseValidator extends DoctorValidator { ...@@ -324,7 +328,7 @@ class AndroidLicenseValidator extends DoctorValidator {
} }
Future<bool> _checkJavaVersionNoOutput() async { Future<bool> _checkJavaVersionNoOutput() async {
final String javaBinary = AndroidSdk.findJavaBinary( final String? javaBinary = AndroidSdk.findJavaBinary(
androidStudio: _androidStudio, androidStudio: _androidStudio,
fileSystem: _fileSystem, fileSystem: _fileSystem,
operatingSystemUtils: _operatingSystemUtils, operatingSystemUtils: _operatingSystemUtils,
...@@ -336,7 +340,7 @@ class AndroidLicenseValidator extends DoctorValidator { ...@@ -336,7 +340,7 @@ class AndroidLicenseValidator extends DoctorValidator {
if (!_processManager.canRun(javaBinary)) { if (!_processManager.canRun(javaBinary)) {
return false; return false;
} }
String javaVersion; String? javaVersion;
try { try {
final ProcessResult result = await _processManager.run(<String>[javaBinary, '-version']); final ProcessResult result = await _processManager.run(<String>[javaBinary, '-version']);
if (result.exitCode == 0) { if (result.exitCode == 0) {
...@@ -354,12 +358,12 @@ class AndroidLicenseValidator extends DoctorValidator { ...@@ -354,12 +358,12 @@ class AndroidLicenseValidator extends DoctorValidator {
} }
Future<LicensesAccepted> get licensesAccepted async { Future<LicensesAccepted> get licensesAccepted async {
LicensesAccepted status; LicensesAccepted? status;
void _handleLine(String line) { void _handleLine(String line) {
if (licenseCounts.hasMatch(line)) { if (licenseCounts.hasMatch(line)) {
final Match match = licenseCounts.firstMatch(line); final Match? match = licenseCounts.firstMatch(line);
if (match.group(1) != match.group(2)) { if (match?.group(1) != match?.group(2)) {
status = LicensesAccepted.some; status = LicensesAccepted.some;
} else { } else {
status = LicensesAccepted.none; status = LicensesAccepted.none;
......
...@@ -297,6 +297,7 @@ void main() { ...@@ -297,6 +297,7 @@ void main() {
// Test with invalid SDK and build tools // Test with invalid SDK and build tools
when(mockSdkVersion.sdkLevel).thenReturn(28); when(mockSdkVersion.sdkLevel).thenReturn(28);
when(mockSdkVersion.buildToolsVersion).thenReturn(Version(26, 0, 3)); when(mockSdkVersion.buildToolsVersion).thenReturn(Version(26, 0, 3));
when(sdk.directory).thenReturn(fileSystem.directory('/foo/bar'));
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager'); when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager');
when(sdk.latestVersion).thenReturn(mockSdkVersion); when(sdk.latestVersion).thenReturn(mockSdkVersion);
when(sdk.validateSdkWellFormed()).thenReturn(<String>[]); when(sdk.validateSdkWellFormed()).thenReturn(<String>[]);
...@@ -357,6 +358,7 @@ void main() { ...@@ -357,6 +358,7 @@ void main() {
when(sdk.platformToolsAvailable).thenReturn(true); when(sdk.platformToolsAvailable).thenReturn(true);
when(mockSdkVersion.sdkLevel).thenReturn(29); when(mockSdkVersion.sdkLevel).thenReturn(29);
when(mockSdkVersion.buildToolsVersion).thenReturn(Version(28, 0, 3)); when(mockSdkVersion.buildToolsVersion).thenReturn(Version(28, 0, 3));
when(sdk.directory).thenReturn(fileSystem.directory('/foo/bar'));
when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager'); when(sdk.sdkManagerPath).thenReturn('/foo/bar/sdkmanager');
when(sdk.latestVersion).thenReturn(mockSdkVersion); when(sdk.latestVersion).thenReturn(mockSdkVersion);
when(sdk.validateSdkWellFormed()).thenReturn(<String>[]); when(sdk.validateSdkWellFormed()).thenReturn(<String>[]);
......
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