Commit bedd8e91 authored by Ian Hickson's avatar Ian Hickson

Merge pull request #2650 from Hixie/always_always_specify_types

Even more types
parents 5fb31514 62f3124e
...@@ -500,10 +500,11 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> { ...@@ -500,10 +500,11 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
return fling(scrollVelocity.clamp(-kMaxFlingVelocity, kMaxFlingVelocity)).then(_endScroll); return fling(scrollVelocity.clamp(-kMaxFlingVelocity, kMaxFlingVelocity)).then(_endScroll);
} }
void _endScroll([_]) { Null _endScroll([Null _]) {
_numberOfInProgressScrolls -= 1; _numberOfInProgressScrolls -= 1;
if (_numberOfInProgressScrolls == 0) if (_numberOfInProgressScrolls == 0)
dispatchOnScrollEnd(); dispatchOnScrollEnd();
return null;
} }
/// Calls the dispatchOnScrollEnd callback. /// Calls the dispatchOnScrollEnd callback.
......
...@@ -64,7 +64,7 @@ class FlutterDriver { ...@@ -64,7 +64,7 @@ class FlutterDriver {
// Attempts to resume the isolate, but does not crash if it fails because // Attempts to resume the isolate, but does not crash if it fails because
// the isolate is already resumed. There could be a race with other tools, // the isolate is already resumed. There could be a race with other tools,
// such as a debugger, any of which could have resumed the isolate. // such as a debugger, any of which could have resumed the isolate.
Future<Null> resumeLeniently() { Future<dynamic> resumeLeniently() {
_log.trace('Attempting to resume isolate'); _log.trace('Attempting to resume isolate');
return isolate.resume().catchError((dynamic e) { return isolate.resume().catchError((dynamic e) {
const int vmMustBePausedCode = 101; const int vmMustBePausedCode = 101;
...@@ -87,7 +87,7 @@ class FlutterDriver { ...@@ -87,7 +87,7 @@ class FlutterDriver {
_log.trace('Isolate is paused at start.'); _log.trace('Isolate is paused at start.');
// Waits for a signal from the VM service that the extension is registered // Waits for a signal from the VM service that the extension is registered
Future<Null> waitForServiceExtension() { Future<String> waitForServiceExtension() {
return isolate.onExtensionAdded.firstWhere((String extension) { return isolate.onExtensionAdded.firstWhere((String extension) {
return extension == _kFlutterExtensionMethod; return extension == _kFlutterExtensionMethod;
}); });
...@@ -96,8 +96,8 @@ class FlutterDriver { ...@@ -96,8 +96,8 @@ class FlutterDriver {
// If the isolate is paused at the start, e.g. via the --start-paused // If the isolate is paused at the start, e.g. via the --start-paused
// option, then the VM service extension is not registered yet. Wait for // option, then the VM service extension is not registered yet. Wait for
// it to be registered. // it to be registered.
Future<Null> whenResumed = resumeLeniently(); Future<dynamic> whenResumed = resumeLeniently();
Future<Null> whenServiceExtensionReady = Future.any(<Future<dynamic>>[ Future<dynamic> whenServiceExtensionReady = Future.any/*<dynamic>*/(<Future<dynamic>>[
waitForServiceExtension(), waitForServiceExtension(),
// We will never receive the extension event if the user does not // We will never receive the extension event if the user does not
// register it. If that happens time out. // register it. If that happens time out.
...@@ -180,7 +180,7 @@ class FlutterDriver { ...@@ -180,7 +180,7 @@ class FlutterDriver {
} }
Future<Null> tap(ObjectRef ref) async { Future<Null> tap(ObjectRef ref) async {
return await _sendCommand(new Tap(ref)).then((_) => null); return await _sendCommand(new Tap(ref)).then((Map<String, dynamic> _) => null);
} }
/// Tell the driver to perform a scrolling action. /// Tell the driver to perform a scrolling action.
...@@ -197,7 +197,7 @@ class FlutterDriver { ...@@ -197,7 +197,7 @@ class FlutterDriver {
/// The move events are generated at a given [frequency] in Hz (or events per /// The move events are generated at a given [frequency] in Hz (or events per
/// second). It defaults to 60Hz. /// second). It defaults to 60Hz.
Future<Null> scroll(ObjectRef ref, double dx, double dy, Duration duration, {int frequency: 60}) async { Future<Null> scroll(ObjectRef ref, double dx, double dy, Duration duration, {int frequency: 60}) async {
return await _sendCommand(new Scroll(ref, dx, dy, duration, frequency)).then((_) => null); return await _sendCommand(new Scroll(ref, dx, dy, duration, frequency)).then((Map<String, dynamic> _) => null);
} }
Future<String> getText(ObjectRef ref) async { Future<String> getText(ObjectRef ref) async {
......
...@@ -16,13 +16,13 @@ import 'package:vm_service_client/vm_service_client.dart'; ...@@ -16,13 +16,13 @@ import 'package:vm_service_client/vm_service_client.dart';
void main() { void main() {
group('FlutterDriver.connect', () { group('FlutterDriver.connect', () {
List<LogRecord> log; List<LogRecord> log;
StreamSubscription logSub; StreamSubscription<LogRecord> logSub;
MockVMServiceClient mockClient; MockVMServiceClient mockClient;
MockVM mockVM; MockVM mockVM;
MockIsolate mockIsolate; MockIsolate mockIsolate;
void expectLogContains(String message) { void expectLogContains(String message) {
expect(log.map((r) => '$r'), anyElement(contains(message))); expect(log.map((LogRecord r) => '$r'), anyElement(contains(message)));
} }
setUp(() { setUp(() {
...@@ -35,8 +35,8 @@ void main() { ...@@ -35,8 +35,8 @@ void main() {
when(mockVM.isolates).thenReturn([mockIsolate]); when(mockVM.isolates).thenReturn([mockIsolate]);
when(mockIsolate.loadRunnable()).thenReturn(mockIsolate); when(mockIsolate.loadRunnable()).thenReturn(mockIsolate);
when(mockIsolate.invokeExtension(any, any)) when(mockIsolate.invokeExtension(any, any))
.thenReturn(new Future.value({'status': 'ok'})); .thenReturn(new Future<Map<String, dynamic>>.value(<String, String>{'status': 'ok'}));
vmServiceConnectFunction = (_) => new Future.value(mockClient); vmServiceConnectFunction = (String url) => new Future<VMServiceClient>.value(mockClient);
}); });
tearDown(() async { tearDown(() async {
...@@ -46,9 +46,8 @@ void main() { ...@@ -46,9 +46,8 @@ void main() {
test('connects to isolate paused at start', () async { test('connects to isolate paused at start', () async {
when(mockIsolate.pauseEvent).thenReturn(new MockVMPauseStartEvent()); when(mockIsolate.pauseEvent).thenReturn(new MockVMPauseStartEvent());
when(mockIsolate.resume()).thenReturn(new Future.value()); when(mockIsolate.resume()).thenReturn(new Future<Null>.value());
when(mockIsolate.onExtensionAdded) when(mockIsolate.onExtensionAdded).thenReturn(new Stream<String>.fromIterable(<String>['ext.flutter_driver']));
.thenReturn(new Stream.fromIterable(['ext.flutter_driver']));
FlutterDriver driver = await FlutterDriver.connect(); FlutterDriver driver = await FlutterDriver.connect();
expect(driver, isNotNull); expect(driver, isNotNull);
...@@ -57,7 +56,7 @@ void main() { ...@@ -57,7 +56,7 @@ void main() {
test('connects to isolate paused mid-flight', () async { test('connects to isolate paused mid-flight', () async {
when(mockIsolate.pauseEvent).thenReturn(new MockVMPauseBreakpointEvent()); when(mockIsolate.pauseEvent).thenReturn(new MockVMPauseBreakpointEvent());
when(mockIsolate.resume()).thenReturn(new Future.value()); when(mockIsolate.resume()).thenReturn(new Future<Null>.value());
FlutterDriver driver = await FlutterDriver.connect(); FlutterDriver driver = await FlutterDriver.connect();
expect(driver, isNotNull); expect(driver, isNotNull);
...@@ -73,7 +72,7 @@ void main() { ...@@ -73,7 +72,7 @@ void main() {
when(mockIsolate.resume()).thenAnswer((_) { when(mockIsolate.resume()).thenAnswer((_) {
// This needs to be wrapped in a closure to not be considered uncaught // This needs to be wrapped in a closure to not be considered uncaught
// by package:test // by package:test
return new Future.error(new rpc.RpcException(101, '')); return new Future<Null>.error(new rpc.RpcException(101, ''));
}); });
FlutterDriver driver = await FlutterDriver.connect(); FlutterDriver driver = await FlutterDriver.connect();
...@@ -101,7 +100,7 @@ void main() { ...@@ -101,7 +100,7 @@ void main() {
}); });
test('checks the health of the driver extension', () async { test('checks the health of the driver extension', () async {
when(mockIsolate.invokeExtension(any, any)).thenReturn(new Future.value({ when(mockIsolate.invokeExtension(any, any)).thenReturn(new Future<Map<String, dynamic>>.value(<String, dynamic>{
'status': 'ok', 'status': 'ok',
})); }));
Health result = await driver.checkHealth(); Health result = await driver.checkHealth();
...@@ -109,7 +108,7 @@ void main() { ...@@ -109,7 +108,7 @@ void main() {
}); });
test('closes connection', () async { test('closes connection', () async {
when(mockClient.close()).thenReturn(new Future.value()); when(mockClient.close()).thenReturn(new Future<Null>.value());
await driver.close(); await driver.close();
}); });
...@@ -127,7 +126,7 @@ void main() { ...@@ -127,7 +126,7 @@ void main() {
'keyValueString': 'foo', 'keyValueString': 'foo',
'keyValueType': 'String' 'keyValueType': 'String'
}); });
return new Future.value({ return new Future<Map<String, dynamic>>.value(<String, dynamic>{
'objectReferenceKey': '123', 'objectReferenceKey': '123',
}); });
}); });
...@@ -149,11 +148,11 @@ void main() { ...@@ -149,11 +148,11 @@ void main() {
test('sends the tap command', () async { test('sends the tap command', () async {
when(mockIsolate.invokeExtension(any, any)).thenAnswer((Invocation i) { when(mockIsolate.invokeExtension(any, any)).thenAnswer((Invocation i) {
expect(i.positionalArguments[1], { expect(i.positionalArguments[1], <String, dynamic>{
'command': 'tap', 'command': 'tap',
'targetRef': '123' 'targetRef': '123'
}); });
return new Future.value(); return new Future<Map<String, dynamic>>.value();
}); });
await driver.tap(new ObjectRef('123')); await driver.tap(new ObjectRef('123'));
}); });
...@@ -171,11 +170,11 @@ void main() { ...@@ -171,11 +170,11 @@ void main() {
test('sends the getText command', () async { test('sends the getText command', () async {
when(mockIsolate.invokeExtension(any, any)).thenAnswer((Invocation i) { when(mockIsolate.invokeExtension(any, any)).thenAnswer((Invocation i) {
expect(i.positionalArguments[1], { expect(i.positionalArguments[1], <String, dynamic>{
'command': 'get_text', 'command': 'get_text',
'targetRef': '123' 'targetRef': '123'
}); });
return new Future.value({ return new Future<Map<String, dynamic>>.value({
'text': 'hello' 'text': 'hello'
}); });
}); });
...@@ -188,7 +187,7 @@ void main() { ...@@ -188,7 +187,7 @@ void main() {
test('waits for a condition', () { test('waits for a condition', () {
expect( expect(
driver.waitFor(() { driver.waitFor(() {
return new Future.delayed( return new Future<int>.delayed(
new Duration(milliseconds: 50), new Duration(milliseconds: 50),
() => 123 () => 123
); );
...@@ -228,7 +227,7 @@ void main() { ...@@ -228,7 +227,7 @@ void main() {
equals(2), equals(2),
timeout: new Duration(milliseconds: 10), timeout: new Duration(milliseconds: 10),
pauseBetweenRetries: new Duration(milliseconds: 2) pauseBetweenRetries: new Duration(milliseconds: 2)
).catchError((err, stack) { ).catchError((dynamic err, dynamic stack) {
timedOut = true; timedOut = true;
}); });
......
...@@ -62,7 +62,7 @@ void main() { ...@@ -62,7 +62,7 @@ void main() {
() async => retryCount++, () async => retryCount++,
new Duration(milliseconds: 30), new Duration(milliseconds: 30),
new Duration(milliseconds: 10), new Duration(milliseconds: 10),
predicate: (value) => value == 2 predicate: (int value) => value == 2
), ),
completion(2) completion(2)
); );
...@@ -85,7 +85,7 @@ void main() { ...@@ -85,7 +85,7 @@ void main() {
}, },
new Duration(milliseconds: 7), new Duration(milliseconds: 7),
new Duration(milliseconds: 2) new Duration(milliseconds: 2)
).catchError((error, stackTrace) { ).catchError((dynamic error, dynamic stackTrace) {
timedOut = true; timedOut = true;
lastError = error; lastError = error;
lastStackTrace = stackTrace; lastStackTrace = stackTrace;
......
...@@ -16,14 +16,13 @@ analyzer: ...@@ -16,14 +16,13 @@ analyzer:
strong_mode_static_type_error: ignore strong_mode_static_type_error: ignore
strong_mode_down_cast_composite: ignore strong_mode_down_cast_composite: ignore
type_argument_not_matching_bounds: ignore type_argument_not_matching_bounds: ignore
argument_type_not_assignable: ignore
# we allow having TODOs in the code # we allow having TODOs in the code
todo: ignore todo: ignore
linter: linter:
rules: rules:
- avoid_empty_else - avoid_empty_else
- always_declare_return_types - always_declare_return_types
# - always_specify_types # still a lot of work to do before enabling this one - always_specify_types
# - annotate_overrides # still a lot of work to do before enabling this one # - annotate_overrides # still a lot of work to do before enabling this one
# - avoid_as # https://github.com/dart-lang/linter/issues/195 # - avoid_as # https://github.com/dart-lang/linter/issues/195
- avoid_init_to_null - avoid_init_to_null
......
...@@ -10,17 +10,17 @@ import 'src/flx.dart' as flx; ...@@ -10,17 +10,17 @@ import 'src/flx.dart' as flx;
/// Assembles a Flutter .flx file from a pre-existing manifest descriptor and a /// Assembles a Flutter .flx file from a pre-existing manifest descriptor and a
/// pre-compiled snapshot. /// pre-compiled snapshot.
Future<int> assembleFlx({ Future<int> assembleFlx({
Map manifestDescriptor: const {}, Map<String, dynamic> manifestDescriptor: const <String, dynamic>{},
File snapshotFile: null, File snapshotFile: null,
String assetBasePath: flx.defaultAssetBasePath, String assetBasePath: flx.defaultAssetBasePath,
String outputPath: flx.defaultFlxOutputPath, String outputPath: flx.defaultFlxOutputPath,
String privateKeyPath: flx.defaultPrivateKeyPath String privateKeyPath: flx.defaultPrivateKeyPath
}) async { }) async {
return flx.assemble( return flx.assemble(
manifestDescriptor: manifestDescriptor, manifestDescriptor: manifestDescriptor,
snapshotFile: snapshotFile, snapshotFile: snapshotFile,
assetBasePath: assetBasePath, assetBasePath: assetBasePath,
outputPath: outputPath, outputPath: outputPath,
privateKeyPath: privateKeyPath privateKeyPath: privateKeyPath
); );
} }
...@@ -82,7 +82,7 @@ class Adb { ...@@ -82,7 +82,7 @@ class Adb {
Socket socket; Socket socket;
bool isFirstNotification = true; bool isFirstNotification = true;
controller = new StreamController( controller = new StreamController<List<AdbDevice>>(
onListen: () async { onListen: () async {
socket = await Socket.connect(InternetAddress.LOOPBACK_IP_V4, adbServerPort); socket = await Socket.connect(InternetAddress.LOOPBACK_IP_V4, adbServerPort);
printTrace('--> host:track-devices'); printTrace('--> host:track-devices');
...@@ -121,7 +121,7 @@ class Adb { ...@@ -121,7 +121,7 @@ class Adb {
return controller.stream; return controller.stream;
} }
Future _populateDeviceNames(List<AdbDevice> devices) async { Future<Null> _populateDeviceNames(List<AdbDevice> devices) async {
for (AdbDevice device in devices) { for (AdbDevice device in devices) {
if (device.modelID == null) { if (device.modelID == null) {
// If we don't have a name of a device in our cache, call `device -l` to populate it. // If we don't have a name of a device in our cache, call `device -l` to populate it.
...@@ -135,7 +135,7 @@ class Adb { ...@@ -135,7 +135,7 @@ class Adb {
} }
} }
Future _populateDeviceCache() async { Future<Null> _populateDeviceCache() async {
List<AdbDevice> devices = await listDevices(); List<AdbDevice> devices = await listDevices();
for (AdbDevice device in devices) for (AdbDevice device in devices)
_idToNameCache[device.id] = device.modelID; _idToNameCache[device.id] = device.modelID;
......
...@@ -180,7 +180,7 @@ class AndroidDevice extends Device { ...@@ -180,7 +180,7 @@ class AndroidDevice extends Device {
return true; return true;
} }
Future _forwardObservatoryPort(int port) async { Future<Null> _forwardObservatoryPort(int port) async {
bool portWasZero = port == 0; bool portWasZero = port == 0;
try { try {
...@@ -485,8 +485,8 @@ class _AdbLogReader extends DeviceLogReader { ...@@ -485,8 +485,8 @@ class _AdbLogReader extends DeviceLogReader {
new StreamController<String>.broadcast(); new StreamController<String>.broadcast();
Process _process; Process _process;
StreamSubscription _stdoutSubscription; StreamSubscription<String> _stdoutSubscription;
StreamSubscription _stderrSubscription; StreamSubscription<String> _stderrSubscription;
Stream<String> get lines => _linesStreamController.stream; Stream<String> get lines => _linesStreamController.stream;
...@@ -494,9 +494,9 @@ class _AdbLogReader extends DeviceLogReader { ...@@ -494,9 +494,9 @@ class _AdbLogReader extends DeviceLogReader {
bool get isReading => _process != null; bool get isReading => _process != null;
Future get finished => _process != null ? _process.exitCode : new Future.value(0); Future<int> get finished => _process != null ? _process.exitCode : new Future<int>.value(0);
Future start() async { Future<Null> start() async {
if (_process != null) if (_process != null)
throw new StateError('_AdbLogReader must be stopped before it can be started.'); throw new StateError('_AdbLogReader must be stopped before it can be started.');
...@@ -516,7 +516,7 @@ class _AdbLogReader extends DeviceLogReader { ...@@ -516,7 +516,7 @@ class _AdbLogReader extends DeviceLogReader {
_process.exitCode.then(_onExit); _process.exitCode.then(_onExit);
} }
Future stop() async { Future<Null> stop() async {
if (_process == null) if (_process == null)
throw new StateError('_AdbLogReader must be started before it can be stopped.'); throw new StateError('_AdbLogReader must be started before it can be stopped.');
...@@ -604,7 +604,7 @@ class _AndroidDevicePortForwarder extends DevicePortForwarder { ...@@ -604,7 +604,7 @@ class _AndroidDevicePortForwarder extends DevicePortForwarder {
return hostPort; return hostPort;
} }
Future unforward(ForwardedPort forwardedPort) async { Future<Null> unforward(ForwardedPort forwardedPort) async {
runCheckedSync(device.adbCommandForDevice( runCheckedSync(device.adbCommandForDevice(
<String>['forward', '--remove', 'tcp:${forwardedPort.hostPort}'] <String>['forward', '--remove', 'tcp:${forwardedPort.hostPort}']
)); ));
......
...@@ -235,7 +235,7 @@ class ArtifactStore { ...@@ -235,7 +235,7 @@ class ArtifactStore {
/// Download a file from the given url and write it to the cache. /// Download a file from the given url and write it to the cache.
/// If [unzip] is true, treat the url as a zip file, and unzip it to the /// If [unzip] is true, treat the url as a zip file, and unzip it to the
/// directory given. /// directory given.
static Future _downloadFileToCache(Uri url, FileSystemEntity cachedFile, bool unzip) async { static Future<Null> _downloadFileToCache(Uri url, FileSystemEntity cachedFile, bool unzip) async {
if (!cachedFile.parent.existsSync()) if (!cachedFile.parent.existsSync())
cachedFile.parent.createSync(recursive: true); cachedFile.parent.createSync(recursive: true);
......
...@@ -46,7 +46,7 @@ void restoreFileSystem() { ...@@ -46,7 +46,7 @@ void restoreFileSystem() {
} }
/// Uses in-memory replacments for `dart:io` functionality. Useful in tests. /// Uses in-memory replacments for `dart:io` functionality. Useful in tests.
void useInMemoryFileSystem({ cwd: '/', ExitFunction exitFunction }) { void useInMemoryFileSystem({ String cwd: '/', ExitFunction exitFunction }) {
MemoryFileSystem memFs = new MemoryFileSystem(); MemoryFileSystem memFs = new MemoryFileSystem();
fs = memFs; fs = memFs;
syncFs = new SyncMemoryFileSystem(backedBy: memFs.storage); syncFs = new SyncMemoryFileSystem(backedBy: memFs.storage);
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
import 'dart:io'; import 'dart:io';
final _terminal = new _AnsiTerminal(); final _AnsiTerminal _terminal = new _AnsiTerminal();
abstract class Logger { abstract class Logger {
bool get isVerbose => false; bool get isVerbose => false;
......
...@@ -57,9 +57,9 @@ Future<int> runCommandAndStreamOutput(List<String> cmd, { ...@@ -57,9 +57,9 @@ Future<int> runCommandAndStreamOutput(List<String> cmd, {
return await process.exitCode; return await process.exitCode;
} }
Future runAndKill(List<String> cmd, Duration timeout) { Future<Null> runAndKill(List<String> cmd, Duration timeout) {
Future<Process> proc = runDetached(cmd); Future<Process> proc = runDetached(cmd);
return new Future.delayed(timeout, () async { return new Future<Null>.delayed(timeout, () async {
printTrace('Intentionally killing ${cmd[0]}'); printTrace('Intentionally killing ${cmd[0]}');
Process.killPid((await proc).pid); Process.killPid((await proc).pid);
}); });
......
...@@ -223,7 +223,7 @@ class AnalyzeCommand extends FlutterCommand { ...@@ -223,7 +223,7 @@ class AnalyzeCommand extends FlutterCommand {
// determine what all the various .packages files depend on // determine what all the various .packages files depend on
PackageDependencyTracker dependencies = new PackageDependencyTracker(); PackageDependencyTracker dependencies = new PackageDependencyTracker();
for (Directory directory in pubSpecDirectories.map((path) => new Directory(path))) { for (Directory directory in pubSpecDirectories.map((String path) => new Directory(path))) {
String pubSpecYamlPath = path.join(directory.path, 'pubspec.yaml'); String pubSpecYamlPath = path.join(directory.path, 'pubspec.yaml');
File pubSpecYamlFile = new File(pubSpecYamlPath); File pubSpecYamlFile = new File(pubSpecYamlPath);
if (pubSpecYamlFile.existsSync()) { if (pubSpecYamlFile.existsSync()) {
...@@ -242,8 +242,8 @@ class AnalyzeCommand extends FlutterCommand { ...@@ -242,8 +242,8 @@ class AnalyzeCommand extends FlutterCommand {
dotPackages dotPackages
.readAsStringSync() .readAsStringSync()
.split('\n') .split('\n')
.where((line) => !line.startsWith(new RegExp(r'^ *#'))) .where((String line) => !line.startsWith(new RegExp(r'^ *#')))
.forEach((line) { .forEach((String line) {
int colon = line.indexOf(':'); int colon = line.indexOf(':');
if (colon > 0) if (colon > 0)
dependencies.add(line.substring(0, colon), path.normalize(path.absolute(directory.path, path.fromUri(line.substring(colon+1)))), dotPackagesPath); dependencies.add(line.substring(0, colon), path.normalize(path.absolute(directory.path, path.fromUri(line.substring(colon+1)))), dotPackagesPath);
...@@ -634,7 +634,7 @@ class AnalysisServer { ...@@ -634,7 +634,7 @@ class AnalysisServer {
int _id = 0; int _id = 0;
Future start() async { Future<Null> start() async {
String snapshot = path.join(sdk, 'bin/snapshots/analysis_server.dart.snapshot'); String snapshot = path.join(sdk, 'bin/snapshots/analysis_server.dart.snapshot');
List<String> args = <String>[snapshot, '--sdk', sdk]; List<String> args = <String>[snapshot, '--sdk', sdk];
...@@ -687,12 +687,12 @@ class AnalysisServer { ...@@ -687,12 +687,12 @@ class AnalysisServer {
dynamic response = JSON.decode(line); dynamic response = JSON.decode(line);
if (response is Map) { if (response is Map<dynamic, dynamic>) {
if (response['event'] != null) { if (response['event'] != null) {
String event = response['event']; String event = response['event'];
dynamic params = response['params']; dynamic params = response['params'];
if (params is Map) { if (params is Map<dynamic, dynamic>) {
if (event == 'server.status') if (event == 'server.status')
_handleStatus(response['params']); _handleStatus(response['params']);
else if (event == 'analysis.errors') else if (event == 'analysis.errors')
...@@ -725,7 +725,7 @@ class AnalysisServer { ...@@ -725,7 +725,7 @@ class AnalysisServer {
_errorsController.add(new FileAnalysisErrors(file, errors)); _errorsController.add(new FileAnalysisErrors(file, errors));
} }
Future dispose() async => _process?.kill(); Future<bool> dispose() async => _process?.kill();
} }
class FileAnalysisErrors { class FileAnalysisErrors {
......
...@@ -135,7 +135,7 @@ All done! In order to run your application, type: ...@@ -135,7 +135,7 @@ All done! In order to run your application, type:
printStatus('Creating project ${path.basename(projectName)}:'); printStatus('Creating project ${path.basename(projectName)}:');
Map templateContext = <String, dynamic>{ Map<String, dynamic> templateContext = <String, dynamic>{
'projectName': projectName, 'projectName': projectName,
'androidIdentifier': _createAndroidIdentifier(projectName), 'androidIdentifier': _createAndroidIdentifier(projectName),
'iosIdentifier': _createUTIIdentifier(projectName), 'iosIdentifier': _createUTIIdentifier(projectName),
......
...@@ -53,7 +53,7 @@ class DaemonCommand extends FlutterCommand { ...@@ -53,7 +53,7 @@ class DaemonCommand extends FlutterCommand {
return JSON.decode(line); return JSON.decode(line);
}); });
Daemon daemon = new Daemon(commandStream, (Map command) { Daemon daemon = new Daemon(commandStream, (Map<String, dynamic> command) {
stdout.writeln('[${JSON.encode(command, toEncodable: _jsonEncodeObject)}]'); stdout.writeln('[${JSON.encode(command, toEncodable: _jsonEncodeObject)}]');
}, daemonCommand: this, notifyingLogger: notifyingLogger); }, daemonCommand: this, notifyingLogger: notifyingLogger);
...@@ -73,7 +73,7 @@ typedef void DispatchComand(Map<String, dynamic> command); ...@@ -73,7 +73,7 @@ typedef void DispatchComand(Map<String, dynamic> command);
typedef Future<dynamic> CommandHandler(dynamic args); typedef Future<dynamic> CommandHandler(dynamic args);
class Daemon { class Daemon {
Daemon(Stream<Map> commandStream, this.sendCommand, { Daemon(Stream<Map<String, dynamic>> commandStream, this.sendCommand, {
this.daemonCommand, this.daemonCommand,
this.notifyingLogger this.notifyingLogger
}) { }) {
...@@ -84,7 +84,7 @@ class Daemon { ...@@ -84,7 +84,7 @@ class Daemon {
// Start listening. // Start listening.
commandStream.listen( commandStream.listen(
(Map request) => _handleRequest(request), (Map<String, dynamic> request) => _handleRequest(request),
onDone: () => _onExitCompleter.complete(0) onDone: () => _onExitCompleter.complete(0)
); );
} }
...@@ -106,7 +106,7 @@ class Daemon { ...@@ -106,7 +106,7 @@ class Daemon {
Future<int> get onExit => _onExitCompleter.future; Future<int> get onExit => _onExitCompleter.future;
void _handleRequest(Map request) { void _handleRequest(Map<String, dynamic> request) {
// {id, method, params} // {id, method, params}
// [id] is an opaque type to us. // [id] is an opaque type to us.
...@@ -133,7 +133,7 @@ class Daemon { ...@@ -133,7 +133,7 @@ class Daemon {
} }
} }
void _send(Map map) => sendCommand(map); void _send(Map<String, dynamic> map) => sendCommand(map);
void shutdown() { void shutdown() {
_domainMap.values.forEach((Domain domain) => domain.dispose()); _domainMap.values.forEach((Domain domain) => domain.dispose());
...@@ -147,7 +147,7 @@ abstract class Domain { ...@@ -147,7 +147,7 @@ abstract class Domain {
final Daemon daemon; final Daemon daemon;
final String name; final String name;
final Map<String, CommandHandler> _handlers = {}; final Map<String, CommandHandler> _handlers = <String, CommandHandler>{};
void registerHandler(String name, CommandHandler handler) { void registerHandler(String name, CommandHandler handler) {
_handlers[name] = handler; _handlers[name] = handler;
...@@ -158,18 +158,18 @@ abstract class Domain { ...@@ -158,18 +158,18 @@ abstract class Domain {
String toString() => name; String toString() => name;
void handleCommand(String command, dynamic id, dynamic args) { void handleCommand(String command, dynamic id, dynamic args) {
new Future.sync(() { new Future<dynamic>.sync(() {
if (_handlers.containsKey(command)) if (_handlers.containsKey(command))
return _handlers[command](args); return _handlers[command](args);
throw 'command not understood: $name.$command'; throw 'command not understood: $name.$command';
}).then((result) { }).then((dynamic result) {
if (result == null) { if (result == null) {
_send({'id': id}); _send(<String, dynamic>{'id': id});
} else { } else {
_send({'id': id, 'result': _toJsonable(result)}); _send(<String, dynamic>{'id': id, 'result': _toJsonable(result)});
} }
}).catchError((error, trace) { }).catchError((dynamic error, dynamic trace) {
_send({'id': id, 'error': _toJsonable(error)}); _send(<String, dynamic>{'id': id, 'error': _toJsonable(error)});
}); });
} }
...@@ -180,7 +180,7 @@ abstract class Domain { ...@@ -180,7 +180,7 @@ abstract class Domain {
_send(map); _send(map);
} }
void _send(Map map) => daemon._send(map); void _send(Map<String, dynamic> map) => daemon._send(map);
void dispose() { } void dispose() { }
} }
...@@ -212,12 +212,12 @@ class DaemonDomain extends Domain { ...@@ -212,12 +212,12 @@ class DaemonDomain extends Domain {
StreamSubscription<LogMessage> _subscription; StreamSubscription<LogMessage> _subscription;
Future<String> version(dynamic args) { Future<String> version(dynamic args) {
return new Future.value(protocolVersion); return new Future<String>.value(protocolVersion);
} }
Future shutdown(dynamic args) { Future<Null> shutdown(dynamic args) {
Timer.run(() => daemon.shutdown()); Timer.run(() => daemon.shutdown());
return new Future.value(); return new Future<Null>.value();
} }
void dispose() { void dispose() {
...@@ -352,23 +352,23 @@ class DeviceDomain extends Domain { ...@@ -352,23 +352,23 @@ class DeviceDomain extends Domain {
List<Device> devices = _discoverers.expand((PollingDeviceDiscovery discoverer) { List<Device> devices = _discoverers.expand((PollingDeviceDiscovery discoverer) {
return discoverer.devices; return discoverer.devices;
}).toList(); }).toList();
return new Future.value(devices); return new Future<List<Device>>.value(devices);
} }
/// Enable device events. /// Enable device events.
Future enable(dynamic args) { Future<Null> enable(dynamic args) {
for (PollingDeviceDiscovery discoverer in _discoverers) { for (PollingDeviceDiscovery discoverer in _discoverers) {
discoverer.startPolling(); discoverer.startPolling();
} }
return new Future.value(); return new Future<Null>.value();
} }
/// Disable device events. /// Disable device events.
Future disable(dynamic args) { Future<Null> disable(dynamic args) {
for (PollingDeviceDiscovery discoverer in _discoverers) { for (PollingDeviceDiscovery discoverer in _discoverers) {
discoverer.stopPolling(); discoverer.stopPolling();
} }
return new Future.value(); return new Future<Null>.value();
} }
void dispose() { void dispose() {
...@@ -398,7 +398,7 @@ String _enumToString(dynamic enumValue) { ...@@ -398,7 +398,7 @@ String _enumToString(dynamic enumValue) {
} }
dynamic _toJsonable(dynamic obj) { dynamic _toJsonable(dynamic obj) {
if (obj is String || obj is int || obj is bool || obj is Map || obj is List || obj == null) if (obj is String || obj is int || obj is bool || obj is Map<dynamic, dynamic> || obj is List<dynamic> || obj == null)
return obj; return obj;
if (obj is Device) if (obj is Device)
return obj; return obj;
......
...@@ -106,7 +106,7 @@ class DriveCommand extends RunCommandBase { ...@@ -106,7 +106,7 @@ class DriveCommand extends RunCommandBase {
try { try {
return await testRunner([testFile]) return await testRunner([testFile])
.then((_) => 0) .then((_) => 0)
.catchError((error, stackTrace) { .catchError((dynamic error, dynamic stackTrace) {
printError('CAUGHT EXCEPTION: $error\n$stackTrace'); printError('CAUGHT EXCEPTION: $error\n$stackTrace');
return 1; return 1;
}); });
...@@ -182,9 +182,9 @@ Future<Device> findTargetDevice() async { ...@@ -182,9 +182,9 @@ Future<Device> findTargetDevice() async {
// we look for an Android device. If there's one, we use that. Otherwise, // we look for an Android device. If there's one, we use that. Otherwise,
// we launch a new iOS Simulator. // we launch a new iOS Simulator.
Device reusableDevice = devices.firstWhere( Device reusableDevice = devices.firstWhere(
(d) => d.isLocalEmulator, (Device d) => d.isLocalEmulator,
orElse: () { orElse: () {
return devices.firstWhere((d) => d is AndroidDevice, return devices.firstWhere((Device d) => d is AndroidDevice,
orElse: () => null); orElse: () => null);
} }
); );
...@@ -210,7 +210,7 @@ Future<Device> findTargetDevice() async { ...@@ -210,7 +210,7 @@ Future<Device> findTargetDevice() async {
return null; return null;
} else if (devices.length > 1) { } else if (devices.length > 1) {
printStatus('Found multiple connected devices:'); printStatus('Found multiple connected devices:');
printStatus(devices.map((d) => ' - ${d.name}\n').join('')); printStatus(devices.map((Device d) => ' - ${d.name}\n').join(''));
} }
printStatus('Using device ${devices.first.name}.'); printStatus('Using device ${devices.first.name}.');
return devices.first; return devices.first;
......
...@@ -38,7 +38,7 @@ class LogsCommand extends FlutterCommand { ...@@ -38,7 +38,7 @@ class LogsCommand extends FlutterCommand {
if (!logReader.isReading) if (!logReader.isReading)
await logReader.start(); await logReader.start();
StreamSubscription subscription = logReader.lines.listen(printStatus); StreamSubscription<String> subscription = logReader.lines.listen(printStatus);
// Wait for the log reader to be finished. // Wait for the log reader to be finished.
int result = await logReader.finished; int result = await logReader.finished;
......
...@@ -185,7 +185,7 @@ Future<int> startApp( ...@@ -185,7 +185,7 @@ Future<int> startApp(
} }
// Allow any stop commands from above to start work. // Allow any stop commands from above to start work.
await new Future.delayed(Duration.ZERO); await new Future<Duration>.delayed(Duration.ZERO);
if (install) { if (install) {
printTrace('Running install command.'); printTrace('Running install command.');
...@@ -234,7 +234,7 @@ Future<int> startApp( ...@@ -234,7 +234,7 @@ Future<int> startApp(
/// ///
/// This does not fail if we're unable to connect, and times out after the given /// This does not fail if we're unable to connect, and times out after the given
/// [timeout]. /// [timeout].
Future delayUntilObservatoryAvailable(String host, int port, { Future<Null> delayUntilObservatoryAvailable(String host, int port, {
Duration timeout: const Duration(seconds: 10) Duration timeout: const Duration(seconds: 10)
}) async { }) async {
Stopwatch stopwatch = new Stopwatch()..start(); Stopwatch stopwatch = new Stopwatch()..start();
...@@ -246,10 +246,10 @@ Future delayUntilObservatoryAvailable(String host, int port, { ...@@ -246,10 +246,10 @@ Future delayUntilObservatoryAvailable(String host, int port, {
try { try {
WebSocket ws = await WebSocket.connect(url); WebSocket ws = await WebSocket.connect(url);
printTrace('Connected to the observatory port.'); printTrace('Connected to the observatory port.');
ws.close().catchError((error) => null); ws.close().catchError((dynamic error) => null);
return; return;
} catch (error) { } catch (error) {
await new Future.delayed(new Duration(milliseconds: 250)); await new Future<Null>.delayed(new Duration(milliseconds: 250));
} }
} }
......
...@@ -22,7 +22,7 @@ class RunMojoCommand extends FlutterCommand { ...@@ -22,7 +22,7 @@ class RunMojoCommand extends FlutterCommand {
final String description = 'Run a Flutter app in mojo (from github.com/domokit/mojo).'; final String description = 'Run a Flutter app in mojo (from github.com/domokit/mojo).';
final bool _hideCommand; final bool _hideCommand;
RunMojoCommand({ hideCommand: false }) : _hideCommand = hideCommand { RunMojoCommand({ bool hideCommand: false }) : _hideCommand = hideCommand {
argParser.addFlag('android', negatable: false, help: 'Run on an Android device'); argParser.addFlag('android', negatable: false, help: 'Run on an Android device');
argParser.addFlag('checked', negatable: false, help: 'Run Flutter in checked mode'); argParser.addFlag('checked', negatable: false, help: 'Run Flutter in checked mode');
argParser.addFlag('mojo-debug', negatable: false, help: 'Use Debug build of mojo'); argParser.addFlag('mojo-debug', negatable: false, help: 'Use Debug build of mojo');
...@@ -64,7 +64,7 @@ class RunMojoCommand extends FlutterCommand { ...@@ -64,7 +64,7 @@ class RunMojoCommand extends FlutterCommand {
} }
String _getMojoShellPath() { String _getMojoShellPath() {
final mojoBuildType = argResults['mojo-debug'] ? 'Debug' : 'Release'; final String mojoBuildType = argResults['mojo-debug'] ? 'Debug' : 'Release';
return _makePathAbsolute(path.join(argResults['mojo-path'], 'out', mojoBuildType, 'mojo_shell')); return _makePathAbsolute(path.join(argResults['mojo-path'], 'out', mojoBuildType, 'mojo_shell'));
} }
......
...@@ -41,7 +41,7 @@ class TraceCommand extends FlutterCommand { ...@@ -41,7 +41,7 @@ class TraceCommand extends FlutterCommand {
// Setting neither flags or both flags means do both commands and wait // Setting neither flags or both flags means do both commands and wait
// duration seconds in between. // duration seconds in between.
device.startTracing(androidApp); device.startTracing(androidApp);
await new Future.delayed( await new Future<Null>.delayed(
new Duration(seconds: int.parse(argResults['duration'])), new Duration(seconds: int.parse(argResults['duration'])),
() => _stopTracing(device, androidApp) () => _stopTracing(device, androidApp)
); );
...@@ -53,7 +53,7 @@ class TraceCommand extends FlutterCommand { ...@@ -53,7 +53,7 @@ class TraceCommand extends FlutterCommand {
return 0; return 0;
} }
Future _stopTracing(AndroidDevice android, AndroidApk androidApp) async { Future<Null> _stopTracing(AndroidDevice android, AndroidApk androidApp) async {
String tracePath = await android.stopTracing(androidApp, outPath: argResults['out']); String tracePath = await android.stopTracing(androidApp, outPath: argResults['out']);
if (tracePath == null) { if (tracePath == null) {
printError('No trace file saved.'); printError('No trace file saved.');
......
...@@ -24,7 +24,7 @@ Future<int> _runPub(Directory directory, { bool upgrade: false }) async { ...@@ -24,7 +24,7 @@ Future<int> _runPub(Directory directory, { bool upgrade: false }) async {
} }
class UpdatePackagesCommand extends FlutterCommand { class UpdatePackagesCommand extends FlutterCommand {
UpdatePackagesCommand({ hideCommand: false }) : _hideCommand = hideCommand { UpdatePackagesCommand({ bool hideCommand: false }) : _hideCommand = hideCommand {
argParser.addFlag( argParser.addFlag(
'upgrade', 'upgrade',
help: 'Run "pub upgrade" rather than "pub get".', help: 'Run "pub upgrade" rather than "pub get".',
......
...@@ -240,7 +240,7 @@ abstract class DevicePortForwarder { ...@@ -240,7 +240,7 @@ abstract class DevicePortForwarder {
Future<int> forward(int devicePort, {int hostPort: null}); Future<int> forward(int devicePort, {int hostPort: null});
/// Stops forwarding [forwardedPort]. /// Stops forwarding [forwardedPort].
Future unforward(ForwardedPort forwardedPort); Future<Null> unforward(ForwardedPort forwardedPort);
} }
/// Read the log for a particular device. Subclasses must implement `hashCode` /// Read the log for a particular device. Subclasses must implement `hashCode`
...@@ -255,16 +255,16 @@ abstract class DeviceLogReader { ...@@ -255,16 +255,16 @@ abstract class DeviceLogReader {
Stream<String> get lines; Stream<String> get lines;
/// Start reading logs from the device. /// Start reading logs from the device.
Future start(); Future<Null> start();
/// Actively reading lines from the log? /// Actively reading lines from the log?
bool get isReading; bool get isReading;
/// Actively stop reading logs from the device. /// Actively stop reading logs from the device.
Future stop(); Future<Null> stop();
/// Completes when the log is finished. /// Completes when the log is finished.
Future get finished; Future<int> get finished;
int get hashCode; int get hashCode;
bool operator ==(dynamic other); bool operator ==(dynamic other);
......
...@@ -38,7 +38,7 @@ class _Asset { ...@@ -38,7 +38,7 @@ class _Asset {
const String _kMaterialIconsKey = 'fonts/MaterialIcons-Regular.ttf'; const String _kMaterialIconsKey = 'fonts/MaterialIcons-Regular.ttf';
List _getMaterialFonts() { List<Map<String, dynamic>> _getMaterialFonts() {
return [{ return [{
'family': 'MaterialIcons', 'family': 'MaterialIcons',
'fonts': [{ 'fonts': [{
...@@ -57,7 +57,7 @@ List<_Asset> _getMaterialAssets() { ...@@ -57,7 +57,7 @@ List<_Asset> _getMaterialAssets() {
]; ];
} }
Map<_Asset, List<_Asset>> _parseAssets(Map manifestDescriptor, String assetBase) { Map<_Asset, List<_Asset>> _parseAssets(Map<String, dynamic> manifestDescriptor, String assetBase) {
Map<_Asset, List<_Asset>> result = <_Asset, List<_Asset>>{}; Map<_Asset, List<_Asset>> result = <_Asset, List<_Asset>>{};
if (manifestDescriptor == null) if (manifestDescriptor == null)
return result; return result;
...@@ -112,8 +112,8 @@ ZipEntry _createAssetManifest(Map<_Asset, List<_Asset>> assets) { ...@@ -112,8 +112,8 @@ ZipEntry _createAssetManifest(Map<_Asset, List<_Asset>> assets) {
return new ZipEntry.fromString('AssetManifest.json', JSON.encode(json)); return new ZipEntry.fromString('AssetManifest.json', JSON.encode(json));
} }
ZipEntry _createFontManifest(Map manifestDescriptor, List additionalFonts) { ZipEntry _createFontManifest(Map<String, dynamic> manifestDescriptor, List<Map<String, dynamic>> additionalFonts) {
List fonts = []; List<Map<String, dynamic>> fonts = <Map<String, dynamic>>[];
if (additionalFonts != null) if (additionalFonts != null)
fonts.addAll(additionalFonts); fonts.addAll(additionalFonts);
if (manifestDescriptor != null && manifestDescriptor.containsKey('fonts')) if (manifestDescriptor != null && manifestDescriptor.containsKey('fonts'))
...@@ -167,7 +167,7 @@ Future<int> build( ...@@ -167,7 +167,7 @@ Future<int> build(
String workingDirPath: defaultWorkingDirPath, String workingDirPath: defaultWorkingDirPath,
bool precompiledSnapshot: false bool precompiledSnapshot: false
}) async { }) async {
Map manifestDescriptor = _loadManifest(manifestPath); Map<String, dynamic> manifestDescriptor = _loadManifest(manifestPath);
String assetBasePath = path.dirname(path.absolute(manifestPath)); String assetBasePath = path.dirname(path.absolute(manifestPath));
File snapshotFile; File snapshotFile;
...@@ -197,7 +197,7 @@ Future<int> build( ...@@ -197,7 +197,7 @@ Future<int> build(
} }
Future<int> assemble({ Future<int> assemble({
Map manifestDescriptor: const {}, Map<String, dynamic> manifestDescriptor: const <String, dynamic>{},
File snapshotFile, File snapshotFile,
String assetBasePath: defaultAssetBasePath, String assetBasePath: defaultAssetBasePath,
String outputPath: defaultFlxOutputPath, String outputPath: defaultFlxOutputPath,
...@@ -244,7 +244,7 @@ Future<int> assemble({ ...@@ -244,7 +244,7 @@ Future<int> assemble({
if (fontManifest != null) if (fontManifest != null)
zipBuilder.addEntry(fontManifest); zipBuilder.addEntry(fontManifest);
AsymmetricKeyPair keyPair = keyPairFromPrivateKeyFileSync(privateKeyPath); AsymmetricKeyPair<PublicKey, PrivateKey> keyPair = keyPairFromPrivateKeyFileSync(privateKeyPath);
printTrace('KeyPair from $privateKeyPath: $keyPair.'); printTrace('KeyPair from $privateKeyPath: $keyPair.');
if (keyPair != null) { if (keyPair != null) {
......
...@@ -253,8 +253,8 @@ class _IOSDeviceLogReader extends DeviceLogReader { ...@@ -253,8 +253,8 @@ class _IOSDeviceLogReader extends DeviceLogReader {
new StreamController<String>.broadcast(); new StreamController<String>.broadcast();
Process _process; Process _process;
StreamSubscription _stdoutSubscription; StreamSubscription<String> _stdoutSubscription;
StreamSubscription _stderrSubscription; StreamSubscription<String> _stderrSubscription;
Stream<String> get lines => _linesStreamController.stream; Stream<String> get lines => _linesStreamController.stream;
...@@ -262,13 +262,15 @@ class _IOSDeviceLogReader extends DeviceLogReader { ...@@ -262,13 +262,15 @@ class _IOSDeviceLogReader extends DeviceLogReader {
bool get isReading => _process != null; bool get isReading => _process != null;
Future get finished => Future<int> get finished {
_process != null ? _process.exitCode : new Future.value(0); return _process != null ? _process.exitCode : new Future<int>.value(0);
}
Future start() async { Future<Null> start() async {
if (_process != null) { if (_process != null) {
throw new StateError( throw new StateError(
'_IOSDeviceLogReader must be stopped before it can be started.'); '_IOSDeviceLogReader must be stopped before it can be started.'
);
} }
_process = await runCommand(<String>[device.loggerPath]); _process = await runCommand(<String>[device.loggerPath]);
_stdoutSubscription = _stdoutSubscription =
...@@ -280,10 +282,11 @@ class _IOSDeviceLogReader extends DeviceLogReader { ...@@ -280,10 +282,11 @@ class _IOSDeviceLogReader extends DeviceLogReader {
_process.exitCode.then(_onExit); _process.exitCode.then(_onExit);
} }
Future stop() async { Future<Null> stop() async {
if (_process == null) { if (_process == null) {
throw new StateError( throw new StateError(
'_IOSDeviceLogReader must be started before it can be stopped.'); '_IOSDeviceLogReader must be started before it can be stopped.'
);
} }
_stdoutSubscription?.cancel(); _stdoutSubscription?.cancel();
_stdoutSubscription = null; _stdoutSubscription = null;
...@@ -341,7 +344,7 @@ class _IOSDevicePortForwarder extends DevicePortForwarder { ...@@ -341,7 +344,7 @@ class _IOSDevicePortForwarder extends DevicePortForwarder {
return hostPort; return hostPort;
} }
Future unforward(ForwardedPort forwardedPort) async { Future<Null> unforward(ForwardedPort forwardedPort) async {
// TODO(chinmaygarde): Implement. // TODO(chinmaygarde): Implement.
} }
} }
...@@ -181,7 +181,7 @@ String _getIOSEngineRevision(ApplicationPackage app) { ...@@ -181,7 +181,7 @@ String _getIOSEngineRevision(ApplicationPackage app) {
} }
} }
Future _addServicesToBundle(Directory bundle) async { Future<Null> _addServicesToBundle(Directory bundle) async {
List<Map<String, String>> services = []; List<Map<String, String>> services = [];
printTrace("Trying to resolve native pub services."); printTrace("Trying to resolve native pub services.");
...@@ -200,7 +200,7 @@ Future _addServicesToBundle(Directory bundle) async { ...@@ -200,7 +200,7 @@ Future _addServicesToBundle(Directory bundle) async {
_copyServiceDefinitionsManifest(services, manifestFile); _copyServiceDefinitionsManifest(services, manifestFile);
} }
Future _copyServiceFrameworks(List<Map<String, String>> services, Directory frameworksDirectory) async { Future<Null> _copyServiceFrameworks(List<Map<String, String>> services, Directory frameworksDirectory) async {
printTrace("Copying service frameworks to '${path.absolute(frameworksDirectory.path)}'."); printTrace("Copying service frameworks to '${path.absolute(frameworksDirectory.path)}'.");
frameworksDirectory.createSync(recursive: true); frameworksDirectory.createSync(recursive: true);
for (Map<String, String> service in services) { for (Map<String, String> service in services) {
......
...@@ -79,7 +79,7 @@ class SimControl { ...@@ -79,7 +79,7 @@ class SimControl {
connected = await _isAnyConnected(); connected = await _isAnyConnected();
if (!connected) { if (!connected) {
printStatus('Still waiting for iOS Simulator to boot...'); printStatus('Still waiting for iOS Simulator to boot...');
await new Future.delayed(new Duration(seconds: 1)); await new Future<Null>.delayed(new Duration(seconds: 1));
} }
attempted++; attempted++;
} }
...@@ -106,7 +106,7 @@ class SimControl { ...@@ -106,7 +106,7 @@ class SimControl {
// Delete any old test devices // Delete any old test devices
getDevices() getDevices()
.where((d) => d.name == _kFlutterTestDevice) .where((SimDevice d) => d.name == _kFlutterTestDevice)
.forEach(_deleteDevice); .forEach(_deleteDevice);
// Create new device // Create new device
...@@ -114,15 +114,15 @@ class SimControl { ...@@ -114,15 +114,15 @@ class SimControl {
printTrace(args.join(' ')); printTrace(args.join(' '));
runCheckedSync(args); runCheckedSync(args);
return getDevices().firstWhere((d) => d.name == _kFlutterTestDevice); return getDevices().firstWhere((SimDevice d) => d.name == _kFlutterTestDevice);
} }
String _findSuitableDeviceType() { String _findSuitableDeviceType() {
List<Map<String, dynamic>> allTypes = _list(SimControlListSection.devicetypes); List<Map<String, dynamic>> allTypes = _list(SimControlListSection.devicetypes);
List<Map<String, dynamic>> usableTypes = allTypes List<Map<String, dynamic>> usableTypes = allTypes
.where((info) => info['name'].startsWith('iPhone')) .where((Map<String, dynamic> info) => info['name'].startsWith('iPhone'))
.toList() .toList()
..sort((r1, r2) => -compareIphoneVersions(r1['identifier'], r2['identifier'])); ..sort((Map<String, dynamic> r1, Map<String, dynamic> r2) => -compareIphoneVersions(r1['identifier'], r2['identifier']));
if (usableTypes.isEmpty) { if (usableTypes.isEmpty) {
printError( printError(
...@@ -139,9 +139,9 @@ class SimControl { ...@@ -139,9 +139,9 @@ class SimControl {
String _findSuitableRuntime() { String _findSuitableRuntime() {
List<Map<String, dynamic>> allRuntimes = _list(SimControlListSection.runtimes); List<Map<String, dynamic>> allRuntimes = _list(SimControlListSection.runtimes);
List<Map<String, dynamic>> usableRuntimes = allRuntimes List<Map<String, dynamic>> usableRuntimes = allRuntimes
.where((info) => info['name'].startsWith('iOS')) .where((Map<String, dynamic> info) => info['name'].startsWith('iOS'))
.toList() .toList()
..sort((r1, r2) => -compareIosVersions(r1['version'], r2['version'])); ..sort((Map<String, dynamic> r1, Map<String, dynamic> r2) => -compareIosVersions(r1['version'], r2['version']));
if (usableRuntimes.isEmpty) { if (usableRuntimes.isEmpty) {
printError( printError(
...@@ -206,7 +206,7 @@ class SimControl { ...@@ -206,7 +206,7 @@ class SimControl {
Map<String, dynamic> devicesSection = _list(SimControlListSection.devices); Map<String, dynamic> devicesSection = _list(SimControlListSection.devices);
for (String deviceCategory in devicesSection.keys) { for (String deviceCategory in devicesSection.keys) {
List<dynamic> devicesData = devicesSection[deviceCategory]; List<Map<String, String>> devicesData = devicesSection[deviceCategory];
for (Map<String, String> data in devicesData) { for (Map<String, String> data in devicesData) {
devices.add(new SimDevice(deviceCategory, data)); devices.add(new SimDevice(deviceCategory, data));
...@@ -232,15 +232,12 @@ class SimControl { ...@@ -232,15 +232,12 @@ class SimControl {
if (_trackDevicesControler == null) { if (_trackDevicesControler == null) {
Timer timer; Timer timer;
Set<String> deviceIds = new Set<String>(); Set<String> deviceIds = new Set<String>();
_trackDevicesControler = new StreamController<List<SimDevice>>.broadcast(
_trackDevicesControler = new StreamController.broadcast(
onListen: () { onListen: () {
timer = new Timer.periodic(new Duration(seconds: 4), (Timer timer) { timer = new Timer.periodic(new Duration(seconds: 4), (Timer timer) {
List<SimDevice> devices = getConnectedDevices(); List<SimDevice> devices = getConnectedDevices();
if (_updateDeviceIds(devices, deviceIds))
if (_updateDeviceIds(devices, deviceIds)) {
_trackDevicesControler.add(devices); _trackDevicesControler.add(devices);
}
}); });
}, onCancel: () { }, onCancel: () {
timer?.cancel(); timer?.cancel();
...@@ -290,13 +287,14 @@ class SimControl { ...@@ -290,13 +287,14 @@ class SimControl {
/// Enumerates all data sections of `xcrun simctl list --json` command. /// Enumerates all data sections of `xcrun simctl list --json` command.
class SimControlListSection { class SimControlListSection {
static const devices = const SimControlListSection._('devices'); const SimControlListSection._(this.name);
static const devicetypes = const SimControlListSection._('devicetypes');
static const runtimes = const SimControlListSection._('runtimes');
static const pairs = const SimControlListSection._('pairs');
final String name; final String name;
const SimControlListSection._(this.name);
static const SimControlListSection devices = const SimControlListSection._('devices');
static const SimControlListSection devicetypes = const SimControlListSection._('devicetypes');
static const SimControlListSection runtimes = const SimControlListSection._('runtimes');
static const SimControlListSection pairs = const SimControlListSection._('pairs');
} }
class SimDevice { class SimDevice {
...@@ -580,12 +578,12 @@ class _IOSSimulatorLogReader extends DeviceLogReader { ...@@ -580,12 +578,12 @@ class _IOSSimulatorLogReader extends DeviceLogReader {
// We log from two logs: the device and the system log. // We log from two logs: the device and the system log.
Process _deviceProcess; Process _deviceProcess;
StreamSubscription _deviceStdoutSubscription; StreamSubscription<String> _deviceStdoutSubscription;
StreamSubscription _deviceStderrSubscription; StreamSubscription<String> _deviceStderrSubscription;
Process _systemProcess; Process _systemProcess;
StreamSubscription _systemStdoutSubscription; StreamSubscription<String> _systemStdoutSubscription;
StreamSubscription _systemStderrSubscription; StreamSubscription<String> _systemStderrSubscription;
Stream<String> get lines => _linesStreamController.stream; Stream<String> get lines => _linesStreamController.stream;
...@@ -593,13 +591,15 @@ class _IOSSimulatorLogReader extends DeviceLogReader { ...@@ -593,13 +591,15 @@ class _IOSSimulatorLogReader extends DeviceLogReader {
bool get isReading => (_deviceProcess != null) && (_systemProcess != null); bool get isReading => (_deviceProcess != null) && (_systemProcess != null);
Future get finished => Future<int> get finished {
(_deviceProcess != null) ? _deviceProcess.exitCode : new Future.value(0); return (_deviceProcess != null) ? _deviceProcess.exitCode : new Future<int>.value(0);
}
Future start() async { Future<Null> start() async {
if (isReading) { if (isReading) {
throw new StateError( throw new StateError(
'_IOSSimulatorLogReader must be stopped before it can be started.'); '_IOSSimulatorLogReader must be stopped before it can be started.'
);
} }
// TODO(johnmccutchan): Add a ProcessSet abstraction that handles running // TODO(johnmccutchan): Add a ProcessSet abstraction that handles running
...@@ -630,10 +630,11 @@ class _IOSSimulatorLogReader extends DeviceLogReader { ...@@ -630,10 +630,11 @@ class _IOSSimulatorLogReader extends DeviceLogReader {
_systemProcess.exitCode.then(_onSystemExit); _systemProcess.exitCode.then(_onSystemExit);
} }
Future stop() async { Future<Null> stop() async {
if (!isReading) { if (!isReading) {
throw new StateError( throw new StateError(
'_IOSSimulatorLogReader must be started before it can be stopped.'); '_IOSSimulatorLogReader must be started before it can be stopped.'
);
} }
if (_deviceProcess != null) { if (_deviceProcess != null) {
await _deviceProcess.kill(); await _deviceProcess.kill();
...@@ -774,7 +775,7 @@ int compareIphoneVersions(String id1, String id2) { ...@@ -774,7 +775,7 @@ int compareIphoneVersions(String id1, String id2) {
return v1.compareTo(v2); return v1.compareTo(v2);
// Sorted in the least preferred first order. // Sorted in the least preferred first order.
const qualifiers = const <String>['-Plus', '', 's-Plus', 's']; const List<String> qualifiers = const <String>['-Plus', '', 's-Plus', 's'];
int q1 = qualifiers.indexOf(m1[2]); int q1 = qualifiers.indexOf(m1[2]);
int q2 = qualifiers.indexOf(m2[2]); int q2 = qualifiers.indexOf(m2[2]);
...@@ -801,7 +802,7 @@ class _IOSSimulatorDevicePortForwarder extends DevicePortForwarder { ...@@ -801,7 +802,7 @@ class _IOSSimulatorDevicePortForwarder extends DevicePortForwarder {
return hostPort; return hostPort;
} }
Future unforward(ForwardedPort forwardedPort) async { Future<Null> unforward(ForwardedPort forwardedPort) async {
_ports.remove(forwardedPort); _ports.remove(forwardedPort);
} }
} }
...@@ -35,11 +35,11 @@ abstract class FlutterCommand extends Command { ...@@ -35,11 +35,11 @@ abstract class FlutterCommand extends Command {
List<BuildConfiguration> get buildConfigurations => runner.buildConfigurations; List<BuildConfiguration> get buildConfigurations => runner.buildConfigurations;
Future downloadToolchain() async { Future<Null> downloadToolchain() async {
toolchain ??= await Toolchain.forConfigs(buildConfigurations); toolchain ??= await Toolchain.forConfigs(buildConfigurations);
} }
Future downloadApplicationPackages() async { Future<Null> downloadApplicationPackages() async {
applicationPackages ??= await ApplicationPackageStore.forConfigs(buildConfigurations); applicationPackages ??= await ApplicationPackageStore.forConfigs(buildConfigurations);
} }
...@@ -126,7 +126,7 @@ abstract class FlutterCommand extends Command { ...@@ -126,7 +126,7 @@ abstract class FlutterCommand extends Command {
void addTargetOption() { void addTargetOption() {
argParser.addOption('target', argParser.addOption('target',
abbr: 't', abbr: 't',
callback: (val) => _targetSpecified = true, callback: (dynamic val) => _targetSpecified = true,
defaultsTo: flx.defaultMainPath, defaultsTo: flx.defaultMainPath,
help: 'Target app path / main entry-point file.'); help: 'Target app path / main entry-point file.');
_targetOptionSpecified = true; _targetOptionSpecified = true;
......
...@@ -19,7 +19,7 @@ class ServiceProtocolDiscovery { ...@@ -19,7 +19,7 @@ class ServiceProtocolDiscovery {
} }
final DeviceLogReader _logReader; final DeviceLogReader _logReader;
Completer _completer = new Completer(); Completer<int> _completer = new Completer<int>();
/// The [Future] returned by this function will complete when the next /// The [Future] returned by this function will complete when the next
/// service protocol port is found. /// service protocol port is found.
...@@ -32,21 +32,20 @@ class ServiceProtocolDiscovery { ...@@ -32,21 +32,20 @@ class ServiceProtocolDiscovery {
if (line.startsWith('Observatory listening on http://')) { if (line.startsWith('Observatory listening on http://')) {
try { try {
RegExp portExp = new RegExp(r"\d+.\d+.\d+.\d+:(\d+)"); RegExp portExp = new RegExp(r"\d+.\d+.\d+.\d+:(\d+)");
var port = portExp.firstMatch(line).group(1); String port = portExp.firstMatch(line).group(1);
portNumber = int.parse(port); portNumber = int.parse(port);
} catch (_) { } catch (_) {
// Ignore errors. // Ignore errors.
} }
} }
if (portNumber != 0) { if (portNumber != 0)
_located(portNumber); _located(portNumber);
}
} }
void _located(int port) { void _located(int port) {
assert(_completer != null); assert(_completer != null);
assert(!_completer.isCompleted); assert(!_completer.isCompleted);
_completer.complete(port); _completer.complete(port);
_completer = new Completer(); _completer = new Completer<int>();
} }
} }
...@@ -25,7 +25,7 @@ dynamic _loadYamlFile(String path) { ...@@ -25,7 +25,7 @@ dynamic _loadYamlFile(String path) {
/// Loads all services specified in `flutter.yaml`. Parses each service config file, /// Loads all services specified in `flutter.yaml`. Parses each service config file,
/// storing metadata in [services] and the list of jar files in [jars]. /// storing metadata in [services] and the list of jar files in [jars].
Future parseServiceConfigs( Future<Null> parseServiceConfigs(
List<Map<String, String>> services, { List<File> jars } List<Map<String, String>> services, { List<File> jars }
) async { ) async {
if (!ArtifactStore.isPackageRootValid) { if (!ArtifactStore.isPackageRootValid) {
......
...@@ -55,11 +55,11 @@ Future<Process> _startProcess(String mainPath, { String packageRoot }) { ...@@ -55,11 +55,11 @@ Future<Process> _startProcess(String mainPath, { String packageRoot }) {
} }
class FlutterPlatform extends PlatformPlugin { class FlutterPlatform extends PlatformPlugin {
StreamChannel loadChannel(String mainPath, TestPlatform platform) { StreamChannel<String> loadChannel(String mainPath, TestPlatform platform) {
return StreamChannelCompleter.fromFuture(_startTest(mainPath)); return StreamChannelCompleter.fromFuture(_startTest(mainPath));
} }
Future<StreamChannel> _startTest(String mainPath) async { Future<StreamChannel<String>> _startTest(String mainPath) async {
_ServerInfo info = await _startServer(); _ServerInfo info = await _startServer();
Directory tempDir = Directory.systemTemp.createTempSync( Directory tempDir = Directory.systemTemp.createTempSync(
'dart_test_listener'); 'dart_test_listener');
...@@ -108,19 +108,19 @@ void main() { ...@@ -108,19 +108,19 @@ void main() {
try { try {
WebSocket socket = await info.socket; WebSocket socket = await info.socket;
StreamChannel channel = new StreamChannel(socket.map(JSON.decode), socket); StreamChannel<String> channel = new StreamChannel<String>(socket.map(JSON.decode), socket);
return channel.transformStream( return channel.transformStream(
new StreamTransformer.fromHandlers( new StreamTransformer<String, String>.fromHandlers(
handleDone: (sink) { handleDone: (EventSink<String> sink) {
finalize(); finalize();
sink.close(); sink.close();
} }
) )
).transformSink(new StreamSinkTransformer.fromHandlers( ).transformSink(new StreamSinkTransformer<String, String>.fromHandlers(
handleData: (data, StreamSink sink) { handleData: (String data, StreamSink<String> sink) {
sink.add(JSON.encode(data)); sink.add(JSON.encode(data));
}, },
handleDone: (sink) { handleDone: (EventSink<String> sink) {
finalize(); finalize();
sink.close(); sink.close();
} }
......
...@@ -36,7 +36,7 @@ void main() { ...@@ -36,7 +36,7 @@ void main() {
server = new AnalysisServer(dartSdkPath, <String>[tempDir.path]); server = new AnalysisServer(dartSdkPath, <String>[tempDir.path]);
int errorCount = 0; int errorCount = 0;
Future onDone = server.onAnalyzing.where((bool analyzing) => analyzing == false).first; Future<bool> onDone = server.onAnalyzing.where((bool analyzing) => analyzing == false).first;
server.onErrors.listen((FileAnalysisErrors errors) => errorCount += errors.errors.length); server.onErrors.listen((FileAnalysisErrors errors) => errorCount += errors.errors.length);
await server.start(); await server.start();
...@@ -55,7 +55,7 @@ void main() { ...@@ -55,7 +55,7 @@ void main() {
server = new AnalysisServer(dartSdkPath, <String>[tempDir.path]); server = new AnalysisServer(dartSdkPath, <String>[tempDir.path]);
int errorCount = 0; int errorCount = 0;
Future onDone = server.onAnalyzing.where((bool analyzing) => analyzing == false).first; Future<bool> onDone = server.onAnalyzing.where((bool analyzing) => analyzing == false).first;
server.onErrors.listen((FileAnalysisErrors errors) => errorCount += errors.errors.length); server.onErrors.listen((FileAnalysisErrors errors) => errorCount += errors.errors.length);
await server.start(); await server.start();
......
...@@ -45,15 +45,15 @@ void main() { ...@@ -45,15 +45,15 @@ void main() {
}); });
_testUsingContext('daemon.version', () async { _testUsingContext('daemon.version', () async {
StreamController<Map<String, dynamic>> commands = new StreamController(); StreamController<Map<String, dynamic>> commands = new StreamController<Map<String, dynamic>>();
StreamController<Map<String, dynamic>> responses = new StreamController(); StreamController<Map<String, dynamic>> responses = new StreamController<Map<String, dynamic>>();
daemon = new Daemon( daemon = new Daemon(
commands.stream, commands.stream,
(Map<String, dynamic> result) => responses.add(result), (Map<String, dynamic> result) => responses.add(result),
notifyingLogger: notifyingLogger notifyingLogger: notifyingLogger
); );
commands.add({'id': 0, 'method': 'daemon.version'}); commands.add(<String, dynamic>{'id': 0, 'method': 'daemon.version'});
Map response = await responses.stream.where(_notEvent).first; Map<String, dynamic> response = await responses.stream.where(_notEvent).first;
expect(response['id'], 0); expect(response['id'], 0);
expect(response['result'], isNotEmpty); expect(response['result'], isNotEmpty);
expect(response['result'] is String, true); expect(response['result'] is String, true);
...@@ -61,8 +61,8 @@ void main() { ...@@ -61,8 +61,8 @@ void main() {
_testUsingContext('daemon.logMessage', () { _testUsingContext('daemon.logMessage', () {
return appContext.runInZone(() async { return appContext.runInZone(() async {
StreamController<Map<String, dynamic>> commands = new StreamController(); StreamController<Map<String, dynamic>> commands = new StreamController<Map<String, dynamic>>();
StreamController<Map<String, dynamic>> responses = new StreamController(); StreamController<Map<String, dynamic>> responses = new StreamController<Map<String, dynamic>>();
daemon = new Daemon( daemon = new Daemon(
commands.stream, commands.stream,
(Map<String, dynamic> result) => responses.add(result), (Map<String, dynamic> result) => responses.add(result),
...@@ -81,8 +81,8 @@ void main() { ...@@ -81,8 +81,8 @@ void main() {
}); });
_testUsingContext('daemon.shutdown', () async { _testUsingContext('daemon.shutdown', () async {
StreamController<Map<String, dynamic>> commands = new StreamController(); StreamController<Map<String, dynamic>> commands = new StreamController<Map<String, dynamic>>();
StreamController<Map<String, dynamic>> responses = new StreamController(); StreamController<Map<String, dynamic>> responses = new StreamController<Map<String, dynamic>>();
daemon = new Daemon( daemon = new Daemon(
commands.stream, commands.stream,
(Map<String, dynamic> result) => responses.add(result), (Map<String, dynamic> result) => responses.add(result),
...@@ -98,8 +98,8 @@ void main() { ...@@ -98,8 +98,8 @@ void main() {
DaemonCommand command = new DaemonCommand(); DaemonCommand command = new DaemonCommand();
applyMocksToCommand(command); applyMocksToCommand(command);
StreamController<Map<String, dynamic>> commands = new StreamController(); StreamController<Map<String, dynamic>> commands = new StreamController<Map<String, dynamic>>();
StreamController<Map<String, dynamic>> responses = new StreamController(); StreamController<Map<String, dynamic>> responses = new StreamController<Map<String, dynamic>>();
daemon = new Daemon( daemon = new Daemon(
commands.stream, commands.stream,
(Map<String, dynamic> result) => responses.add(result), (Map<String, dynamic> result) => responses.add(result),
...@@ -108,21 +108,21 @@ void main() { ...@@ -108,21 +108,21 @@ void main() {
); );
commands.add(<String, dynamic>{ 'id': 0, 'method': 'app.stop' }); commands.add(<String, dynamic>{ 'id': 0, 'method': 'app.stop' });
Map response = await responses.stream.where(_notEvent).first; Map<String, dynamic> response = await responses.stream.where(_notEvent).first;
expect(response['id'], 0); expect(response['id'], 0);
expect(response['error'], contains('deviceId is required')); expect(response['error'], contains('deviceId is required'));
}); });
_testUsingContext('device.getDevices', () async { _testUsingContext('device.getDevices', () async {
StreamController<Map<String, dynamic>> commands = new StreamController(); StreamController<Map<String, dynamic>> commands = new StreamController<Map<String, dynamic>>();
StreamController<Map<String, dynamic>> responses = new StreamController(); StreamController<Map<String, dynamic>> responses = new StreamController<Map<String, dynamic>>();
daemon = new Daemon( daemon = new Daemon(
commands.stream, commands.stream,
(Map<String, dynamic> result) => responses.add(result), (Map<String, dynamic> result) => responses.add(result),
notifyingLogger: notifyingLogger notifyingLogger: notifyingLogger
); );
commands.add({'id': 0, 'method': 'device.getDevices'}); commands.add({'id': 0, 'method': 'device.getDevices'});
Map response = await responses.stream.where(_notEvent).first; Map<String, dynamic> response = await responses.stream.where(_notEvent).first;
expect(response['id'], 0); expect(response['id'], 0);
expect(response['result'], isList); expect(response['result'], isList);
}); });
......
...@@ -16,7 +16,7 @@ void main() { ...@@ -16,7 +16,7 @@ void main() {
ServiceProtocolDiscovery discoverer = ServiceProtocolDiscovery discoverer =
new ServiceProtocolDiscovery(logReader); new ServiceProtocolDiscovery(logReader);
// Get next port future. // Get next port future.
Future nextPort = discoverer.nextPort(); Future<int> nextPort = discoverer.nextPort();
expect(nextPort, isNotNull); expect(nextPort, isNotNull);
// Inject some lines. // Inject some lines.
logReader.addLine('HELLO WORLD'); logReader.addLine('HELLO WORLD');
......
...@@ -72,11 +72,11 @@ class MockDeviceManager implements DeviceManager { ...@@ -72,11 +72,11 @@ class MockDeviceManager implements DeviceManager {
String specifiedDeviceId; String specifiedDeviceId;
bool get hasSpecifiedDeviceId => specifiedDeviceId != null; bool get hasSpecifiedDeviceId => specifiedDeviceId != null;
Future<List<Device>> getAllConnectedDevices() => new Future.value(devices); Future<List<Device>> getAllConnectedDevices() => new Future<List<Device>>.value(devices);
Future<Device> getDeviceById(String deviceId) { Future<Device> getDeviceById(String deviceId) {
Device device = devices.firstWhere((Device device) => device.id == deviceId, orElse: () => null); Device device = devices.firstWhere((Device device) => device.id == deviceId, orElse: () => null);
return new Future.value(device); return new Future<Device>.value(device);
} }
Future<List<Device>> getDevices() async { Future<List<Device>> getDevices() async {
......
...@@ -52,7 +52,7 @@ class MockDeviceLogReader extends DeviceLogReader { ...@@ -52,7 +52,7 @@ class MockDeviceLogReader extends DeviceLogReader {
final StreamController<String> _linesStreamController = final StreamController<String> _linesStreamController =
new StreamController<String>.broadcast(); new StreamController<String>.broadcast();
final Completer _finishedCompleter = new Completer(); final Completer<int> _finishedCompleter = new Completer<int>();
Stream<String> get lines => _linesStreamController.stream; Stream<String> get lines => _linesStreamController.stream;
...@@ -62,21 +62,20 @@ class MockDeviceLogReader extends DeviceLogReader { ...@@ -62,21 +62,20 @@ class MockDeviceLogReader extends DeviceLogReader {
bool _started = false; bool _started = false;
Future start() { Future<Null> start() async {
assert(!_started); assert(!_started);
_started = true; _started = true;
return new Future.value(this);
} }
bool get isReading => _started; bool get isReading => _started;
Future stop() { Future<Null> stop() {
assert(_started); assert(_started);
_started = false; _started = false;
return new Future.value(this); return new Future<Null>.value();
} }
Future get finished => _finishedCompleter.future; Future<int> get finished => _finishedCompleter.future;
} }
void applyMocksToCommand(FlutterCommand command) { void applyMocksToCommand(FlutterCommand command) {
......
...@@ -18,7 +18,7 @@ void main() { ...@@ -18,7 +18,7 @@ void main() {
StopCommand command = new StopCommand(); StopCommand command = new StopCommand();
applyMocksToCommand(command); applyMocksToCommand(command);
MockAndroidDevice device = new MockAndroidDevice(); MockAndroidDevice device = new MockAndroidDevice();
when(device.stopApp(any)).thenReturn(new Future.value(true)); when(device.stopApp(any)).thenReturn(new Future<bool>.value(true));
testDeviceManager.addDevice(device); testDeviceManager.addDevice(device);
return createTestCommandRunner(command).run(['stop']).then((int code) { return createTestCommandRunner(command).run(['stop']).then((int code) {
expect(code, equals(0)); expect(code, equals(0));
...@@ -29,7 +29,7 @@ void main() { ...@@ -29,7 +29,7 @@ void main() {
StopCommand command = new StopCommand(); StopCommand command = new StopCommand();
applyMocksToCommand(command); applyMocksToCommand(command);
MockIOSDevice device = new MockIOSDevice(); MockIOSDevice device = new MockIOSDevice();
when(device.stopApp(any)).thenReturn(new Future.value(true)); when(device.stopApp(any)).thenReturn(new Future<bool>.value(true));
testDeviceManager.addDevice(device); testDeviceManager.addDevice(device);
return createTestCommandRunner(command).run(['stop']).then((int code) { return createTestCommandRunner(command).run(['stop']).then((int code) {
......
...@@ -72,14 +72,14 @@ class Bundle { ...@@ -72,14 +72,14 @@ class Bundle {
this.path, this.path,
this.manifest, this.manifest,
List<int> contentBytes, List<int> contentBytes,
AsymmetricKeyPair keyPair AsymmetricKeyPair<PublicKey, PrivateKey> keyPair
}) : _contentBytes = contentBytes { }) : _contentBytes = contentBytes {
assert(path != null); assert(path != null);
assert(manifest != null); assert(manifest != null);
assert(_contentBytes != null); assert(_contentBytes != null);
manifestBytes = serializeManifest(manifest, keyPair?.publicKey, _contentBytes); manifestBytes = serializeManifest(manifest, keyPair?.publicKey, _contentBytes);
signatureBytes = signManifest(manifestBytes, keyPair?.privateKey); signatureBytes = signManifest(manifestBytes, keyPair?.privateKey);
_openContentStream = () => new Stream.fromIterable(<List<int>>[_contentBytes]); _openContentStream = () => new Stream<List<int>>.fromIterable(<List<int>>[_contentBytes]);
} }
final String path; final String path;
......
...@@ -12,7 +12,7 @@ import 'package:bignum/bignum.dart'; ...@@ -12,7 +12,7 @@ import 'package:bignum/bignum.dart';
import 'package:crypto/crypto.dart'; import 'package:crypto/crypto.dart';
import 'package:pointycastle/pointycastle.dart'; import 'package:pointycastle/pointycastle.dart';
export 'package:pointycastle/pointycastle.dart' show AsymmetricKeyPair; export 'package:pointycastle/pointycastle.dart' show AsymmetricKeyPair, PublicKey, PrivateKey;
// The ECDSA algorithm parameters we're using. These match the parameters used // The ECDSA algorithm parameters we're using. These match the parameters used
// by the Flutter updater package. // by the Flutter updater package.
...@@ -50,7 +50,7 @@ class CipherParameters { ...@@ -50,7 +50,7 @@ class CipherParameters {
SecureRandom _random; SecureRandom _random;
void _initRandom(Uint8List key, Uint8List iv) { void _initRandom(Uint8List key, Uint8List iv) {
KeyParameter keyParam = new KeyParameter(key); KeyParameter keyParam = new KeyParameter(key);
ParametersWithIV params = new ParametersWithIV(keyParam, iv); ParametersWithIV<KeyParameter> params = new ParametersWithIV<KeyParameter>(keyParam, iv);
_random = new SecureRandom('AES/CTR/AUTO-SEED-PRNG') _random = new SecureRandom('AES/CTR/AUTO-SEED-PRNG')
..seed(params); ..seed(params);
} }
...@@ -65,7 +65,7 @@ final CipherParameters _params = CipherParameters._init(); ...@@ -65,7 +65,7 @@ final CipherParameters _params = CipherParameters._init();
// Returns a serialized manifest, with the public key and hash of the content // Returns a serialized manifest, with the public key and hash of the content
// included. // included.
Uint8List serializeManifest(Map manifestDescriptor, ECPublicKey publicKey, Uint8List zipBytes) { Uint8List serializeManifest(Map<String, dynamic> manifestDescriptor, ECPublicKey publicKey, Uint8List zipBytes) {
if (manifestDescriptor == null) if (manifestDescriptor == null)
return null; return null;
final List<String> kSavedKeys = <String>[ final List<String> kSavedKeys = <String>[
...@@ -73,8 +73,8 @@ Uint8List serializeManifest(Map manifestDescriptor, ECPublicKey publicKey, Uint8 ...@@ -73,8 +73,8 @@ Uint8List serializeManifest(Map manifestDescriptor, ECPublicKey publicKey, Uint8
'version', 'version',
'update-url' 'update-url'
]; ];
Map outputManifest = new Map(); Map<String, dynamic> outputManifest = new Map<String, dynamic>();
manifestDescriptor.forEach((key, value) { manifestDescriptor.forEach((String key, dynamic value) {
if (kSavedKeys.contains(key)) if (kSavedKeys.contains(key))
outputManifest[key] = value; outputManifest[key] = value;
}); });
...@@ -97,8 +97,8 @@ Uint8List signManifest(Uint8List manifestBytes, ECPrivateKey privateKey) { ...@@ -97,8 +97,8 @@ Uint8List signManifest(Uint8List manifestBytes, ECPrivateKey privateKey) {
if (manifestBytes == null || privateKey == null) if (manifestBytes == null || privateKey == null)
return new Uint8List(0); return new Uint8List(0);
Signer signer = new Signer(_params.signerAlgorithm); Signer signer = new Signer(_params.signerAlgorithm);
PrivateKeyParameter params = new PrivateKeyParameter(privateKey); PrivateKeyParameter<PrivateKey> params = new PrivateKeyParameter<PrivateKey>(privateKey);
signer.init(true, new ParametersWithRandom(params, _params.random)); signer.init(true, new ParametersWithRandom<PrivateKeyParameter<PrivateKey>>(params, _params.random));
ECSignature signature = signer.generateSignature(manifestBytes); ECSignature signature = signer.generateSignature(manifestBytes);
ASN1Sequence asn1 = new ASN1Sequence() ASN1Sequence asn1 = new ASN1Sequence()
..add(new ASN1Integer(signature.r)) ..add(new ASN1Integer(signature.r))
...@@ -115,10 +115,10 @@ bool verifyManifestSignature(Map<String, dynamic> manifest, ...@@ -115,10 +115,10 @@ bool verifyManifestSignature(Map<String, dynamic> manifest,
List<int> keyBytes = BASE64.decode(manifest['key']); List<int> keyBytes = BASE64.decode(manifest['key']);
ECPoint q = _params.domain.curve.decodePoint(keyBytes); ECPoint q = _params.domain.curve.decodePoint(keyBytes);
ECPublicKey publicKey = new ECPublicKey(q, _params.domain); PublicKey publicKey = new ECPublicKey(q, _params.domain);
Signer signer = new Signer(_params.signerAlgorithm); Signer signer = new Signer(_params.signerAlgorithm);
signer.init(false, new PublicKeyParameter(publicKey)); signer.init(false, new PublicKeyParameter<PublicKey>(publicKey));
return signer.verifySignature(manifestBytes, signature); return signer.verifySignature(manifestBytes, signature);
} }
...@@ -166,24 +166,24 @@ ECSignature _asn1ParseSignature(Uint8List signature) { ...@@ -166,24 +166,24 @@ ECSignature _asn1ParseSignature(Uint8List signature) {
} }
} }
ECPublicKey _publicKeyFromPrivateKey(ECPrivateKey privateKey) { PublicKey _publicKeyFromPrivateKey(ECPrivateKey privateKey) {
ECPoint Q = privateKey.parameters.G * privateKey.d; ECPoint Q = privateKey.parameters.G * privateKey.d;
return new ECPublicKey(Q, privateKey.parameters); return new ECPublicKey(Q, privateKey.parameters);
} }
AsymmetricKeyPair keyPairFromPrivateKeyFileSync(String privateKeyPath) { AsymmetricKeyPair<PublicKey, PrivateKey> keyPairFromPrivateKeyFileSync(String privateKeyPath) {
File file = new File(privateKeyPath); File file = new File(privateKeyPath);
if (!file.existsSync()) if (!file.existsSync())
return null; return null;
return keyPairFromPrivateKeyBytes(file.readAsBytesSync()); return keyPairFromPrivateKeyBytes(file.readAsBytesSync());
} }
AsymmetricKeyPair keyPairFromPrivateKeyBytes(List<int> privateKeyBytes) { AsymmetricKeyPair<PublicKey, PrivateKey> keyPairFromPrivateKeyBytes(List<int> privateKeyBytes) {
ECPrivateKey privateKey = _asn1ParsePrivateKey( ECPrivateKey privateKey = _asn1ParsePrivateKey(
_params.domain, new Uint8List.fromList(privateKeyBytes)); _params.domain, new Uint8List.fromList(privateKeyBytes));
if (privateKey == null) if (privateKey == null)
return null; return null;
ECPublicKey publicKey = _publicKeyFromPrivateKey(privateKey); PublicKey publicKey = _publicKeyFromPrivateKey(privateKey);
return new AsymmetricKeyPair(publicKey, privateKey); return new AsymmetricKeyPair<PublicKey, PrivateKey>(publicKey, privateKey);
} }
...@@ -8,7 +8,7 @@ import 'package:flx/bundle.dart'; ...@@ -8,7 +8,7 @@ import 'package:flx/bundle.dart';
import 'package:flx/signing.dart'; import 'package:flx/signing.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
Future main() async { Future<Null> main() async {
// The following constant was generated via the openssl shell commands: // The following constant was generated via the openssl shell commands:
// openssl ecparam -genkey -name prime256v1 -out privatekey.pem // openssl ecparam -genkey -name prime256v1 -out privatekey.pem
// openssl ec -in privatekey.pem -outform DER | base64 // openssl ec -in privatekey.pem -outform DER | base64
...@@ -28,9 +28,10 @@ Future main() async { ...@@ -28,9 +28,10 @@ Future main() async {
Directory tempDir = await Directory.systemTemp.createTempSync('bundle_test'); Directory tempDir = await Directory.systemTemp.createTempSync('bundle_test');
String bundlePath = tempDir.path + '/bundle.flx'; String bundlePath = tempDir.path + '/bundle.flx';
AsymmetricKeyPair keyPair = keyPairFromPrivateKeyBytes(kPrivateKeyDER); AsymmetricKeyPair<PublicKey, PrivateKey> keyPair = keyPairFromPrivateKeyBytes(kPrivateKeyDER);
Map<String, dynamic> manifest = JSON.decode(UTF8.decode( Map<String, dynamic> manifest = JSON.decode(UTF8.decode(
serializeManifest(kManifest, keyPair.publicKey, kTestBytes))); serializeManifest(kManifest, keyPair.publicKey, kTestBytes)
));
test('verifyContent works', () async { test('verifyContent works', () async {
Bundle bundle = new Bundle.fromContent( Bundle bundle = new Bundle.fromContent(
......
...@@ -8,7 +8,7 @@ import 'package:crypto/crypto.dart'; ...@@ -8,7 +8,7 @@ import 'package:crypto/crypto.dart';
import 'package:flx/signing.dart'; import 'package:flx/signing.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
Future main() async { Future<Null> main() async {
// The following constant was generated via the openssl shell commands: // The following constant was generated via the openssl shell commands:
// openssl ecparam -genkey -name prime256v1 -out privatekey.pem // openssl ecparam -genkey -name prime256v1 -out privatekey.pem
// openssl ec -in privatekey.pem -outform DER | base64 // openssl ec -in privatekey.pem -outform DER | base64
...@@ -42,18 +42,21 @@ Future main() async { ...@@ -42,18 +42,21 @@ Future main() async {
keyGenerator.init(keyGeneratorParams); keyGenerator.init(keyGeneratorParams);
test('can read openssl key pair', () { test('can read openssl key pair', () {
AsymmetricKeyPair keyPair = keyPairFromPrivateKeyBytes(kPrivateKeyDER); AsymmetricKeyPair<PublicKey, PrivateKey> keyPair = keyPairFromPrivateKeyBytes(kPrivateKeyDER);
expect(keyPair != null, equals(true)); expect(keyPair != null, equals(true));
expect(keyPair.privateKey.d.intValue(), equals(kPrivateKeyD)); ECPrivateKey keyPairPrivateKey = keyPair.privateKey;
expect(keyPair.publicKey.Q.x.toBigInteger().intValue(), equals(kPublicKeyQx)); ECPublicKey keyPairPublicKey = keyPair.publicKey;
expect(keyPair.publicKey.Q.y.toBigInteger().intValue(), equals(kPublicKeyQy)); expect(keyPairPrivateKey.d.intValue(), equals(kPrivateKeyD));
expect(keyPairPublicKey.Q.x.toBigInteger().intValue(), equals(kPublicKeyQx));
expect(keyPairPublicKey.Q.y.toBigInteger().intValue(), equals(kPublicKeyQy));
}); });
test('serializeManifest adds key and content-hash', () { test('serializeManifest adds key and content-hash', () {
AsymmetricKeyPair keyPair = keyPairFromPrivateKeyBytes(kPrivateKeyDER); AsymmetricKeyPair<PublicKey, PrivateKey> keyPair = keyPairFromPrivateKeyBytes(kPrivateKeyDER);
Uint8List manifestBytes = serializeManifest(kManifest, keyPair.publicKey, kTestBytes); ECPublicKey keyPairPublicKey = keyPair.publicKey;
Uint8List manifestBytes = serializeManifest(kManifest, keyPairPublicKey, kTestBytes);
Map<String, dynamic> decodedManifest = JSON.decode(UTF8.decode(manifestBytes)); Map<String, dynamic> decodedManifest = JSON.decode(UTF8.decode(manifestBytes));
String expectedKey = BASE64.encode(keyPair.publicKey.Q.getEncoded()); String expectedKey = BASE64.encode(keyPairPublicKey.Q.getEncoded());
expect(decodedManifest != null, equals(true)); expect(decodedManifest != null, equals(true));
expect(decodedManifest['name'], equals(kManifest['name'])); expect(decodedManifest['name'], equals(kManifest['name']));
expect(decodedManifest['version'], equals(kManifest['version'])); expect(decodedManifest['version'], equals(kManifest['version']));
...@@ -62,10 +65,13 @@ Future main() async { ...@@ -62,10 +65,13 @@ Future main() async {
}); });
test('signManifest and verifyManifestSignature work', () { test('signManifest and verifyManifestSignature work', () {
AsymmetricKeyPair keyPair = keyPairFromPrivateKeyBytes(kPrivateKeyDER); AsymmetricKeyPair<PublicKey, PrivateKey> keyPair = keyPairFromPrivateKeyBytes(kPrivateKeyDER);
ECPrivateKey keyPairPrivateKey = keyPair.privateKey;
ECPublicKey keyPairPublicKey = keyPair.publicKey;
Map<String, dynamic> manifest = JSON.decode(UTF8.decode( Map<String, dynamic> manifest = JSON.decode(UTF8.decode(
serializeManifest(kManifest, keyPair.publicKey, kTestBytes))); serializeManifest(kManifest, keyPairPublicKey, kTestBytes))
Uint8List signatureBytes = signManifest(kTestBytes, keyPair.privateKey); );
Uint8List signatureBytes = signManifest(kTestBytes, keyPairPrivateKey);
bool verifies = verifyManifestSignature(manifest, kTestBytes, signatureBytes); bool verifies = verifyManifestSignature(manifest, kTestBytes, signatureBytes);
expect(verifies, equals(true)); expect(verifies, equals(true));
...@@ -79,11 +85,14 @@ Future main() async { ...@@ -79,11 +85,14 @@ Future main() async {
}); });
test('signing works with arbitrary key', () { test('signing works with arbitrary key', () {
AsymmetricKeyPair keyPair = keyGenerator.generateKeyPair(); AsymmetricKeyPair<PublicKey, PrivateKey> keyPair = keyGenerator.generateKeyPair();
String failReason = 'offending private key: ${keyPair.privateKey.d}'; ECPrivateKey keyPairPrivateKey = keyPair.privateKey;
ECPublicKey keyPairPublicKey = keyPair.publicKey;
String failReason = 'offending private key: ${keyPairPrivateKey.d}';
Map<String, dynamic> manifest = JSON.decode(UTF8.decode( Map<String, dynamic> manifest = JSON.decode(UTF8.decode(
serializeManifest(kManifest, keyPair.publicKey, kTestBytes))); serializeManifest(kManifest, keyPairPublicKey, kTestBytes))
Uint8List signatureBytes = signManifest(kTestBytes, keyPair.privateKey); );
Uint8List signatureBytes = signManifest(kTestBytes, keyPairPrivateKey);
bool verifies = verifyManifestSignature(manifest, kTestBytes, signatureBytes); bool verifies = verifyManifestSignature(manifest, kTestBytes, signatureBytes);
expect(verifies, equals(true), reason: failReason); expect(verifies, equals(true), reason: failReason);
...@@ -97,17 +106,18 @@ Future main() async { ...@@ -97,17 +106,18 @@ Future main() async {
}); });
test('verifyContentHash works', () async { test('verifyContentHash works', () async {
Stream contentStream = new Stream.fromIterable(kTestBytesList); Stream<Uint8List> contentStream = new Stream<Uint8List>.fromIterable(kTestBytesList);
bool verifies = await verifyContentHash(new BigInteger(kTestHash), contentStream); bool verifies = await verifyContentHash(new BigInteger(kTestHash), contentStream);
expect(verifies, equals(true)); expect(verifies, equals(true));
// Ensure it fails with invalid hash or content. // Ensure it fails with invalid hash or content.
contentStream = new Stream.fromIterable(kTestBytesList); contentStream = new Stream<Uint8List>.fromIterable(kTestBytesList);
verifies = await verifyContentHash(new BigInteger(0xdeadbeef), contentStream); verifies = await verifyContentHash(new BigInteger(0xdeadbeef), contentStream);
expect(verifies, equals(false)); expect(verifies, equals(false));
Stream badContentStream = Stream<Uint8List> badContentStream = new Stream<Uint8List>.fromIterable(
new Stream.fromIterable([new Uint8List.fromList(<int>[42])]); <Uint8List>[new Uint8List.fromList(<int>[42])]
);
verifies = await verifyContentHash(new BigInteger(kTestHash), badContentStream); verifies = await verifyContentHash(new BigInteger(kTestHash), badContentStream);
expect(verifies, equals(false)); expect(verifies, equals(false));
}); });
......
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