Unverified Commit 6b191841 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

Allow filtering devices to only those supported by current project (#31446)

parent 5ec33654
...@@ -535,6 +535,11 @@ class AndroidDevice extends Device { ...@@ -535,6 +535,11 @@ class AndroidDevice extends Device {
await runCheckedAsync(adbCommandForDevice(<String>['pull', remotePath, outputFile.path])); await runCheckedAsync(adbCommandForDevice(<String>['pull', remotePath, outputFile.path]));
await runCheckedAsync(adbCommandForDevice(<String>['shell', 'rm', remotePath])); await runCheckedAsync(adbCommandForDevice(<String>['shell', 'rm', remotePath]));
} }
@override
bool isSupportedForProject(FlutterProject flutterProject) {
return flutterProject.android.existsSync();
}
} }
Map<String, String> parseAdbDeviceProperties(String str) { Map<String, String> parseAdbDeviceProperties(String str) {
......
...@@ -243,6 +243,7 @@ class AttachCommand extends FlutterCommand { ...@@ -243,6 +243,7 @@ class AttachCommand extends FlutterCommand {
final bool useHot = getBuildInfo().isDebug; final bool useHot = getBuildInfo().isDebug;
final FlutterDevice flutterDevice = await FlutterDevice.create( final FlutterDevice flutterDevice = await FlutterDevice.create(
device, device,
flutterProject: flutterProject,
trackWidgetCreation: argResults['track-widget-creation'], trackWidgetCreation: argResults['track-widget-creation'],
dillOutputPath: argResults['output-dill'], dillOutputPath: argResults['output-dill'],
fileSystemRoots: argResults['filesystem-root'], fileSystemRoots: argResults['filesystem-root'],
......
...@@ -19,6 +19,7 @@ import '../convert.dart'; ...@@ -19,6 +19,7 @@ import '../convert.dart';
import '../device.dart'; import '../device.dart';
import '../emulator.dart'; import '../emulator.dart';
import '../globals.dart'; import '../globals.dart';
import '../project.dart';
import '../resident_runner.dart'; import '../resident_runner.dart';
import '../run_cold.dart'; import '../run_cold.dart';
import '../run_hot.dart'; import '../run_hot.dart';
...@@ -344,9 +345,11 @@ class AppDomain extends Domain { ...@@ -344,9 +345,11 @@ class AppDomain extends Domain {
// We change the current working directory for the duration of the `start` command. // We change the current working directory for the duration of the `start` command.
final Directory cwd = fs.currentDirectory; final Directory cwd = fs.currentDirectory;
fs.currentDirectory = fs.directory(projectDirectory); fs.currentDirectory = fs.directory(projectDirectory);
final FlutterProject flutterProject = await FlutterProject.current();
final FlutterDevice flutterDevice = await FlutterDevice.create( final FlutterDevice flutterDevice = await FlutterDevice.create(
device, device,
flutterProject: flutterProject,
trackWidgetCreation: trackWidgetCreation, trackWidgetCreation: trackWidgetCreation,
dillOutputPath: dillOutputPath, dillOutputPath: dillOutputPath,
viewFilter: isolateFilter, viewFilter: isolateFilter,
......
...@@ -13,6 +13,7 @@ import '../cache.dart'; ...@@ -13,6 +13,7 @@ import '../cache.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart'; import '../globals.dart';
import '../ios/mac.dart'; import '../ios/mac.dart';
import '../project.dart';
import '../resident_runner.dart'; import '../resident_runner.dart';
import '../run_cold.dart'; import '../run_cold.dart';
import '../run_hot.dart'; import '../run_hot.dart';
...@@ -364,9 +365,11 @@ class RunCommand extends RunCommandBase { ...@@ -364,9 +365,11 @@ class RunCommand extends RunCommandBase {
expFlags = argResults[FlutterOptions.kEnableExperiment]; expFlags = argResults[FlutterOptions.kEnableExperiment];
} }
final List<FlutterDevice> flutterDevices = <FlutterDevice>[]; final List<FlutterDevice> flutterDevices = <FlutterDevice>[];
final FlutterProject flutterProject = await FlutterProject.current();
for (Device device in devices) { for (Device device in devices) {
final FlutterDevice flutterDevice = await FlutterDevice.create( final FlutterDevice flutterDevice = await FlutterDevice.create(
device, device,
flutterProject: flutterProject,
trackWidgetCreation: argResults['track-widget-creation'], trackWidgetCreation: argResults['track-widget-creation'],
dillOutputPath: argResults['output-dill'], dillOutputPath: argResults['output-dill'],
fileSystemRoots: argResults['filesystem-root'], fileSystemRoots: argResults['filesystem-root'],
......
...@@ -19,6 +19,7 @@ import 'ios/devices.dart'; ...@@ -19,6 +19,7 @@ import 'ios/devices.dart';
import 'ios/simulators.dart'; import 'ios/simulators.dart';
import 'linux/linux_device.dart'; import 'linux/linux_device.dart';
import 'macos/macos_device.dart'; import 'macos/macos_device.dart';
import 'project.dart';
import 'tester/flutter_tester.dart'; import 'tester/flutter_tester.dart';
import 'web/web_device.dart'; import 'web/web_device.dart';
import 'windows/windows_device.dart'; import 'windows/windows_device.dart';
...@@ -235,6 +236,9 @@ abstract class Device { ...@@ -235,6 +236,9 @@ abstract class Device {
} }
} }
/// Whether the device is supported for the current project directory.
bool isSupportedForProject(FlutterProject flutterProject);
/// Check if a version of the given app is already installed /// Check if a version of the given app is already installed
Future<bool> isAppInstalled(ApplicationPackage app); Future<bool> isAppInstalled(ApplicationPackage app);
......
...@@ -17,6 +17,7 @@ import '../base/time.dart'; ...@@ -17,6 +17,7 @@ import '../base/time.dart';
import '../build_info.dart'; import '../build_info.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart'; import '../globals.dart';
import '../project.dart';
import '../vmservice.dart'; import '../vmservice.dart';
import 'fuchsia_sdk.dart'; import 'fuchsia_sdk.dart';
...@@ -302,6 +303,9 @@ class FuchsiaDevice extends Device { ...@@ -302,6 +303,9 @@ class FuchsiaDevice extends Device {
} }
FuchsiaIsolateDiscoveryProtocol getIsolateDiscoveryProtocol(String isolateName) => FuchsiaIsolateDiscoveryProtocol(this, isolateName); FuchsiaIsolateDiscoveryProtocol getIsolateDiscoveryProtocol(String isolateName) => FuchsiaIsolateDiscoveryProtocol(this, isolateName);
@override
bool isSupportedForProject(FlutterProject flutterProject) => true;
} }
class FuchsiaIsolateDiscoveryProtocol { class FuchsiaIsolateDiscoveryProtocol {
......
...@@ -17,6 +17,7 @@ import '../build_info.dart'; ...@@ -17,6 +17,7 @@ import '../build_info.dart';
import '../convert.dart'; import '../convert.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart'; import '../globals.dart';
import '../project.dart';
import '../protocol_discovery.dart'; import '../protocol_discovery.dart';
import 'code_signing.dart'; import 'code_signing.dart';
import 'ios_workflow.dart'; import 'ios_workflow.dart';
...@@ -401,6 +402,11 @@ class IOSDevice extends Device { ...@@ -401,6 +402,11 @@ class IOSDevice extends Device {
Future<void> takeScreenshot(File outputFile) async { Future<void> takeScreenshot(File outputFile) async {
await iMobileDevice.takeScreenshot(outputFile); await iMobileDevice.takeScreenshot(outputFile);
} }
@override
bool isSupportedForProject(FlutterProject flutterProject) {
return flutterProject.ios.existsSync();
}
} }
/// Decodes a vis-encoded syslog string to a UTF-8 representation. /// Decodes a vis-encoded syslog string to a UTF-8 representation.
......
...@@ -19,6 +19,7 @@ import '../bundle.dart' as bundle; ...@@ -19,6 +19,7 @@ import '../bundle.dart' as bundle;
import '../convert.dart'; import '../convert.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart'; import '../globals.dart';
import '../project.dart';
import '../protocol_discovery.dart'; import '../protocol_discovery.dart';
import 'ios_workflow.dart'; import 'ios_workflow.dart';
import 'mac.dart'; import 'mac.dart';
...@@ -473,6 +474,11 @@ class IOSSimulator extends Device { ...@@ -473,6 +474,11 @@ class IOSSimulator extends Device {
Future<void> takeScreenshot(File outputFile) { Future<void> takeScreenshot(File outputFile) {
return SimControl.instance.takeScreenshot(id, outputFile.path); return SimControl.instance.takeScreenshot(id, outputFile.path);
} }
@override
bool isSupportedForProject(FlutterProject flutterProject) {
return flutterProject.ios.existsSync();
}
} }
/// Launches the device log reader process on the host. /// Launches the device log reader process on the host.
......
...@@ -108,6 +108,11 @@ class LinuxDevice extends Device { ...@@ -108,6 +108,11 @@ class LinuxDevice extends Device {
@override @override
Future<bool> uninstallApp(ApplicationPackage app) async => true; Future<bool> uninstallApp(ApplicationPackage app) async => true;
@override
bool isSupportedForProject(FlutterProject flutterProject) {
return flutterProject.linux.existsSync();
}
// Track the last built mode from startApp. // Track the last built mode from startApp.
BuildMode _lastBuiltMode; BuildMode _lastBuiltMode;
} }
......
...@@ -117,6 +117,11 @@ class MacOSDevice extends Device { ...@@ -117,6 +117,11 @@ class MacOSDevice extends Device {
// to uninstall the application. // to uninstall the application.
@override @override
Future<bool> uninstallApp(ApplicationPackage app) async => true; Future<bool> uninstallApp(ApplicationPackage app) async => true;
@override
bool isSupportedForProject(FlutterProject flutterProject) {
return flutterProject.macos.existsSync();
}
} }
class MacOSDevices extends PollingDeviceDiscovery { class MacOSDevices extends PollingDeviceDiscovery {
......
...@@ -208,8 +208,6 @@ class IosProject { ...@@ -208,8 +208,6 @@ class IosProject {
Directory get _ephemeralDirectory => parent.directory.childDirectory('.ios'); Directory get _ephemeralDirectory => parent.directory.childDirectory('.ios');
Directory get _editableDirectory => parent.directory.childDirectory('ios'); Directory get _editableDirectory => parent.directory.childDirectory('ios');
bool existsSync() => parent.isModule || _editableDirectory.existsSync();
/// This parent folder of `Runner.xcodeproj`. /// This parent folder of `Runner.xcodeproj`.
Directory get hostAppRoot { Directory get hostAppRoot {
if (!isModule || _editableDirectory.existsSync()) if (!isModule || _editableDirectory.existsSync())
...@@ -264,6 +262,11 @@ class IosProject { ...@@ -264,6 +262,11 @@ class IosProject {
/// Xcode workspace shared workspace settings file for the host app. /// Xcode workspace shared workspace settings file for the host app.
File get xcodeWorkspaceSharedSettings => xcodeWorkspaceSharedData.childFile('WorkspaceSettings.xcsettings'); File get xcodeWorkspaceSharedSettings => xcodeWorkspaceSharedData.childFile('WorkspaceSettings.xcsettings');
/// Whether the current flutter project has an iOS subproject.
bool existsSync() {
return parent.isModule || _editableDirectory.existsSync();
}
/// The product bundle identifier of the host app, or null if not set or if /// The product bundle identifier of the host app, or null if not set or if
/// iOS tooling needed to read it is not installed. /// iOS tooling needed to read it is not installed.
String get productBundleIdentifier { String get productBundleIdentifier {
...@@ -391,8 +394,6 @@ class AndroidProject { ...@@ -391,8 +394,6 @@ class AndroidProject {
return _ephemeralDirectory; return _ephemeralDirectory;
} }
bool existsSync() => parent.isModule || _flutterLibGradleRoot.existsSync();
/// The Gradle root directory of the Android wrapping of Flutter and plugins. /// The Gradle root directory of the Android wrapping of Flutter and plugins.
/// This is the same as [hostAppGradleRoot] except when the project is /// This is the same as [hostAppGradleRoot] except when the project is
/// a Flutter module with an editable host app. /// a Flutter module with an editable host app.
...@@ -420,6 +421,11 @@ class AndroidProject { ...@@ -420,6 +421,11 @@ class AndroidProject {
return fs.directory(fs.path.join(hostAppGradleRoot.path, 'app', 'build', 'outputs', 'bundle')); return fs.directory(fs.path.join(hostAppGradleRoot.path, 'app', 'build', 'outputs', 'bundle'));
} }
/// Whether the current flutter project has an Android sub-project.
bool existsSync() {
return parent.isModule || _editableHostAppDirectory.existsSync();
}
bool get isUsingGradle { bool get isUsingGradle {
return hostAppGradleRoot.childFile('build.gradle').existsSync(); return hostAppGradleRoot.childFile('build.gradle').existsSync();
} }
...@@ -498,7 +504,10 @@ class WebProject { ...@@ -498,7 +504,10 @@ class WebProject {
final FlutterProject parent; final FlutterProject parent;
bool existsSync() => parent.directory.childDirectory('web').existsSync(); /// Whether this flutter project has a web sub-project.
bool existsSync() {
return parent.directory.childDirectory('web').existsSync();
}
Future<void> ensureReadyForPlatformSpecificTooling() async { Future<void> ensureReadyForPlatformSpecificTooling() async {
/// Generate index.html in build/web. Eventually we could support /// Generate index.html in build/web. Eventually we could support
...@@ -590,4 +599,4 @@ class LinuxProject { ...@@ -590,4 +599,4 @@ class LinuxProject {
/// The Linux project makefile. /// The Linux project makefile.
File get makeFile => editableHostAppDirectory.childFile('Makefile'); File get makeFile => editableHostAppDirectory.childFile('Makefile');
} }
\ No newline at end of file
...@@ -52,6 +52,7 @@ class FlutterDevice { ...@@ -52,6 +52,7 @@ class FlutterDevice {
/// Create a [FlutterDevice] with optional code generation enabled. /// Create a [FlutterDevice] with optional code generation enabled.
static Future<FlutterDevice> create( static Future<FlutterDevice> create(
Device device, { Device device, {
@required FlutterProject flutterProject,
@required bool trackWidgetCreation, @required bool trackWidgetCreation,
String dillOutputPath, String dillOutputPath,
List<String> fileSystemRoots, List<String> fileSystemRoots,
...@@ -64,7 +65,6 @@ class FlutterDevice { ...@@ -64,7 +65,6 @@ class FlutterDevice {
@required BuildMode buildMode, @required BuildMode buildMode,
}) async { }) async {
ResidentCompiler generator; ResidentCompiler generator;
final FlutterProject flutterProject = await FlutterProject.current();
if (flutterProject.hasBuilders) { if (flutterProject.hasBuilders) {
generator = await CodeGeneratingResidentCompiler.create( generator = await CodeGeneratingResidentCompiler.create(
flutterProject: flutterProject, flutterProject: flutterProject,
......
...@@ -527,6 +527,13 @@ abstract class FlutterCommand extends Command<void> { ...@@ -527,6 +527,13 @@ abstract class FlutterCommand extends Command<void> {
} }
devices = devices.where((Device device) => device.isSupported()).toList(); devices = devices.where((Device device) => device.isSupported()).toList();
// If the user has not specified all devices and has multiple connected
// then filter then list by those supported in the current project. If
// this ends up with a single device we can proceed as normal.
if (devices.length > 1 && !deviceManager.hasSpecifiedAllDevices && !deviceManager.hasSpecifiedDeviceId) {
final FlutterProject flutterProject = await FlutterProject.current();
devices.removeWhere((Device device) => !device.isSupportedForProject(flutterProject));
}
if (devices.isEmpty) { if (devices.isEmpty) {
printStatus(userMessages.flutterNoSupportedDevices); printStatus(userMessages.flutterNoSupportedDevices);
......
...@@ -18,6 +18,7 @@ import '../convert.dart'; ...@@ -18,6 +18,7 @@ import '../convert.dart';
import '../dart/package_map.dart'; import '../dart/package_map.dart';
import '../device.dart'; import '../device.dart';
import '../globals.dart'; import '../globals.dart';
import '../project.dart';
import '../protocol_discovery.dart'; import '../protocol_discovery.dart';
import '../version.dart'; import '../version.dart';
...@@ -192,6 +193,9 @@ class FlutterTesterDevice extends Device { ...@@ -192,6 +193,9 @@ class FlutterTesterDevice extends Device {
@override @override
Future<bool> uninstallApp(ApplicationPackage app) async => true; Future<bool> uninstallApp(ApplicationPackage app) async => true;
@override
bool isSupportedForProject(FlutterProject flutterProject) => true;
} }
class FlutterTesterDevices extends PollingDeviceDiscovery { class FlutterTesterDevices extends PollingDeviceDiscovery {
......
...@@ -166,6 +166,11 @@ class WebDevice extends Device { ...@@ -166,6 +166,11 @@ class WebDevice extends Device {
await request.response.addStream(file.openRead()); await request.response.addStream(file.openRead());
await request.response.close(); await request.response.close();
} }
@override
bool isSupportedForProject(FlutterProject flutterProject) {
return flutterProject.web.existsSync();
}
} }
class WebDevices extends PollingDeviceDiscovery { class WebDevices extends PollingDeviceDiscovery {
......
...@@ -114,6 +114,11 @@ class WindowsDevice extends Device { ...@@ -114,6 +114,11 @@ class WindowsDevice extends Device {
// to uninstall the application. // to uninstall the application.
@override @override
Future<bool> uninstallApp(ApplicationPackage app) async => true; Future<bool> uninstallApp(ApplicationPackage app) async => true;
@override
bool isSupportedForProject(FlutterProject flutterProject) {
return flutterProject.windows.existsSync();
}
} }
class WindowsDevices extends PollingDeviceDiscovery { class WindowsDevices extends PollingDeviceDiscovery {
......
...@@ -10,6 +10,7 @@ import 'package:flutter_tools/src/android/android_sdk.dart'; ...@@ -10,6 +10,7 @@ import 'package:flutter_tools/src/android/android_sdk.dart';
import 'package:flutter_tools/src/base/config.dart'; import 'package:flutter_tools/src/base/config.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
...@@ -157,6 +158,44 @@ Use the 'android' tool to install them: ...@@ -157,6 +158,44 @@ Use the 'android' tool to install them:
ProcessManager: () => mockProcessManager, ProcessManager: () => mockProcessManager,
}); });
}); });
testUsingContext('isSupportedForProject is true on module project', () async {
fs.file('pubspec.yaml')
..createSync()
..writeAsStringSync(r'''
name: example
flutter:
module: {}
''');
fs.file('.packages').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(AndroidDevice('test').isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
testUsingContext('isSupportedForProject is true with editable host app', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
fs.directory('android').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(AndroidDevice('test').isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
testUsingContext('isSupportedForProject is false with no host app and no module', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(AndroidDevice('test').isSupportedForProject(flutterProject), false);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
} }
class MockProcessManager extends Mock implements ProcessManager {} class MockProcessManager extends Mock implements ProcessManager {}
......
...@@ -53,6 +53,7 @@ void main() { ...@@ -53,6 +53,7 @@ void main() {
expect(device.supportsHotReload, true); expect(device.supportsHotReload, true);
expect(device.supportsHotRestart, false); expect(device.supportsHotRestart, false);
expect(device.supportsStopApp, false); expect(device.supportsStopApp, false);
expect(device.isSupportedForProject(null), true);
expect(await device.stopApp(null), false); expect(await device.stopApp(null), false);
}); });
}); });
......
...@@ -5,12 +5,14 @@ ...@@ -5,12 +5,14 @@
import 'dart:async'; import 'dart:async';
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/application_package.dart'; import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/ios/devices.dart'; import 'package:flutter_tools/src/ios/devices.dart';
import 'package:flutter_tools/src/ios/mac.dart'; import 'package:flutter_tools/src/ios/mac.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
...@@ -183,4 +185,42 @@ f577a7903cc54959be2e34bc4f7f80b7009efcf4 ...@@ -183,4 +185,42 @@ f577a7903cc54959be2e34bc4f7f80b7009efcf4
IMobileDevice: () => mockIMobileDevice, IMobileDevice: () => mockIMobileDevice,
}); });
}); });
testUsingContext('IOSDevice.isSupportedForProject is true on module project', () async {
fs.file('pubspec.yaml')
..createSync()
..writeAsStringSync(r'''
name: example
flutter:
module: {}
''');
fs.file('.packages').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(IOSDevice('test').isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
testUsingContext('IOSDevice.isSupportedForProject is true with editable host app', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
fs.directory('ios').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(IOSDevice('test').isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
testUsingContext('IOSDevice.isSupportedForProject is false with no host app and no module', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(IOSDevice('test').isSupportedForProject(flutterProject), false);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
} }
...@@ -6,11 +6,13 @@ import 'dart:async'; ...@@ -6,11 +6,13 @@ import 'dart:async';
import 'dart:io' show ProcessResult, Process; import 'dart:io' show ProcessResult, Process;
import 'package:file/file.dart'; import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/application_package.dart'; import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/ios/mac.dart'; import 'package:flutter_tools/src/ios/mac.dart';
import 'package:flutter_tools/src/ios/simulators.dart'; import 'package:flutter_tools/src/ios/simulators.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart'; import 'package:platform/platform.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
...@@ -414,4 +416,42 @@ void main() { ...@@ -414,4 +416,42 @@ void main() {
SimControl: () => simControl, SimControl: () => simControl,
}); });
}); });
testUsingContext('IOSDevice.isSupportedForProject is true on module project', () async {
fs.file('pubspec.yaml')
..createSync()
..writeAsStringSync(r'''
name: example
flutter:
module: {}
''');
fs.file('.packages').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(IOSSimulator('test').isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
testUsingContext('IOSDevice.isSupportedForProject is true with editable host app', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
fs.directory('ios').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(IOSSimulator('test').isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
testUsingContext('IOSDevice.isSupportedForProject is false with no host app and no module', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(IOSSimulator('test').isSupportedForProject(flutterProject), false);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
} }
...@@ -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 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
...@@ -9,6 +10,7 @@ import 'package:flutter_tools/src/build_info.dart'; ...@@ -9,6 +10,7 @@ import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/linux/application_package.dart'; import 'package:flutter_tools/src/linux/application_package.dart';
import 'package:flutter_tools/src/linux/linux_device.dart'; import 'package:flutter_tools/src/linux/linux_device.dart';
import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
...@@ -59,6 +61,27 @@ void main() { ...@@ -59,6 +61,27 @@ void main() {
Platform: () => notLinux, Platform: () => notLinux,
}); });
}); });
testUsingContext('LinuxDevice.isSupportedForProject is true with editable host app', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
fs.directory('linux').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(LinuxDevice().isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
testUsingContext('LinuxDevice.isSupportedForProject is false with no host app', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(LinuxDevice().isSupportedForProject(flutterProject), false);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
} }
class MockPlatform extends Mock implements Platform {} class MockPlatform extends Mock implements Platform {}
......
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
import 'dart:convert'; import 'dart:convert';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/context.dart'; import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:mockito/mockito.dart'; import 'package:mockito/mockito.dart';
import 'package:process/process.dart'; import 'package:process/process.dart';
...@@ -106,6 +108,27 @@ tester 17193 0.0 0.2 4791128 37820 ?? S 2:27PM 0:00.09 /Applica ...@@ -106,6 +108,27 @@ tester 17193 0.0 0.2 4791128 37820 ?? S 2:27PM 0:00.09 /Applica
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Platform: () => notMac, Platform: () => notMac,
}); });
testUsingContext('isSupportedForProject is true with editable host app', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
fs.directory('macos').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(MacOSDevice().isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
testUsingContext('isSupportedForProject is false with no host app', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(MacOSDevice().isSupportedForProject(flutterProject), false);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
}); });
} }
......
...@@ -379,6 +379,9 @@ class MockAndroidDevice extends Mock implements AndroidDevice { ...@@ -379,6 +379,9 @@ class MockAndroidDevice extends Mock implements AndroidDevice {
@override @override
bool isSupported() => true; bool isSupported() => true;
@override
bool isSupportedForProject(FlutterProject flutterProject) => true;
} }
class MockIOSDevice extends Mock implements IOSDevice { class MockIOSDevice extends Mock implements IOSDevice {
...@@ -387,6 +390,9 @@ class MockIOSDevice extends Mock implements IOSDevice { ...@@ -387,6 +390,9 @@ class MockIOSDevice extends Mock implements IOSDevice {
@override @override
bool isSupported() => true; bool isSupported() => true;
@override
bool isSupportedForProject(FlutterProject flutterProject) => true;
} }
class MockIOSSimulator extends Mock implements IOSSimulator { class MockIOSSimulator extends Mock implements IOSSimulator {
...@@ -395,6 +401,9 @@ class MockIOSSimulator extends Mock implements IOSSimulator { ...@@ -395,6 +401,9 @@ class MockIOSSimulator extends Mock implements IOSSimulator {
@override @override
bool isSupported() => true; bool isSupported() => true;
@override
bool isSupportedForProject(FlutterProject flutterProject) => true;
} }
class MockDeviceLogReader extends DeviceLogReader { class MockDeviceLogReader extends DeviceLogReader {
......
...@@ -2,10 +2,12 @@ ...@@ -2,10 +2,12 @@
// 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 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart'; import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart'; import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/windows/application_package.dart'; import 'package:flutter_tools/src/windows/application_package.dart';
import 'package:flutter_tools/src/windows/windows_device.dart'; import 'package:flutter_tools/src/windows/windows_device.dart';
import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device.dart';
...@@ -58,6 +60,27 @@ void main() { ...@@ -58,6 +60,27 @@ void main() {
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Platform: () => notWindows, Platform: () => notWindows,
}); });
testUsingContext('isSupportedForProject is true with editable host app', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
fs.directory('windows').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(WindowsDevice().isSupportedForProject(flutterProject), true);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
testUsingContext('isSupportedForProject is false with no host app', () async {
fs.file('pubspec.yaml').createSync();
fs.file('.packages').createSync();
final FlutterProject flutterProject = await FlutterProject.current();
expect(WindowsDevice().isSupportedForProject(flutterProject), false);
}, overrides: <Type, Generator>{
FileSystem: () => MemoryFileSystem(),
});
}); });
} }
...@@ -71,4 +94,4 @@ class MockProcessManager extends Mock implements ProcessManager {} ...@@ -71,4 +94,4 @@ class MockProcessManager extends Mock implements ProcessManager {}
class MockProcess extends Mock implements Process {} class MockProcess extends Mock implements Process {}
class MockProcessResult extends Mock implements ProcessResult {} class MockProcessResult extends Mock implements ProcessResult {}
\ No newline at end of file
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