Commit 4a71f382 authored by Ian Hickson's avatar Ian Hickson

Merge pull request #332 from Hixie/flutter-analyze

flutter analyze command
parents 7939ec5d a0227cab
...@@ -12,16 +12,10 @@ SCRIPT_PATH="$FLUTTER_TOOLS_DIR/bin/flutter_tools.dart" ...@@ -12,16 +12,10 @@ SCRIPT_PATH="$FLUTTER_TOOLS_DIR/bin/flutter_tools.dart"
# TODO(abarth): We shouldn't require dart to be on the user's path. # TODO(abarth): We shouldn't require dart to be on the user's path.
DART=dart DART=dart
if [ "$FLUTTER_TOOLS_DIR/pubspec.yaml" -nt "$FLUTTER_TOOLS_DIR/pubspec.lock" ]; then
(cd "$FLUTTER_TOOLS_DIR"; pub get)
if [ -f "$SNAPSHOT_PATH" ]; then
rm "$SNAPSHOT_PATH"
fi
fi
REVISION=`(cd "$FLUTTER_ROOT"; git rev-parse HEAD)` REVISION=`(cd "$FLUTTER_ROOT"; git rev-parse HEAD)`
if [ ! -f "$SNAPSHOT_PATH" ] || [ ! -f "$STAMP_PATH" ] || [ `cat "$STAMP_PATH"` != $REVISION ] || [ "$FLUTTER_TOOLS_DIR/pubspec.yaml" -nt "$FLUTTER_TOOLS_DIR/pubspec.lock" ]; then
if [ ! -f "$SNAPSHOT_PATH" ] || [ ! -f "$STAMP_PATH" ] || [ `cat "$STAMP_PATH"` != $REVISION ]; then echo Updating flutter tool...
(cd "$FLUTTER_TOOLS_DIR"; pub get)
$DART --snapshot="$SNAPSHOT_PATH" --package-root="$FLUTTER_TOOLS_DIR/packages" "$SCRIPT_PATH" $DART --snapshot="$SNAPSHOT_PATH" --package-root="$FLUTTER_TOOLS_DIR/packages" "$SCRIPT_PATH"
echo -n $REVISION > "$STAMP_PATH" echo -n $REVISION > "$STAMP_PATH"
fi fi
......
...@@ -29,6 +29,7 @@ GOTO :after_snapshot ...@@ -29,6 +29,7 @@ GOTO :after_snapshot
:do_snapshot :do_snapshot
CD "%flutter_tools_dir%" CD "%flutter_tools_dir%"
ECHO Updating flutter tool...
CALL pub.bat get CALL pub.bat get
CD "%flutter_root%" CD "%flutter_root%"
CALL %dart% --snapshot="%snapshot_path%" --package-root="%flutter_tools_dir%\packages" "%script_path%" CALL %dart% --snapshot="%snapshot_path%" --package-root="%flutter_tools_dir%\packages" "%script_path%"
...@@ -42,4 +43,4 @@ CALL %dart% "%snapshot_path%" %* ...@@ -42,4 +43,4 @@ CALL %dart% "%snapshot_path%" %*
IF /I "%ERRORLEVEL%" EQU "253" ( IF /I "%ERRORLEVEL%" EQU "253" (
CALL %dart% --snapshot="%snapshot_path%" --package-root="%flutter_tools_dir%\packages" "%script_path%" CALL %dart% --snapshot="%snapshot_path%" --package-root="%flutter_tools_dir%\packages" "%script_path%"
CALL %dart% "%snapshot_path%" %* CALL %dart% "%snapshot_path%" %*
) )
\ No newline at end of file
...@@ -124,7 +124,7 @@ class FitnessAppState extends State<FitnessApp> { ...@@ -124,7 +124,7 @@ class FitnessAppState extends State<FitnessApp> {
}); });
} }
Widget build(BuildContext) { Widget build(BuildContext context) {
return new MaterialApp( return new MaterialApp(
theme: new ThemeData( theme: new ThemeData(
brightness: ThemeBrightness.light, brightness: ThemeBrightness.light,
......
...@@ -38,7 +38,7 @@ final ThemeData _theme = new ThemeData( ...@@ -38,7 +38,7 @@ final ThemeData _theme = new ThemeData(
); );
class TestAppState extends State<TestApp> { class TestAppState extends State<TestApp> {
TestApp() { TestAppState() {
_testBed = new TestBed(_labelTexts[_selectedLine]); _testBed = new TestBed(_labelTexts[_selectedLine]);
} }
......
...@@ -44,10 +44,10 @@ class TabbedNavigatorAppState extends State<TabbedNavigatorApp> { ...@@ -44,10 +44,10 @@ class TabbedNavigatorAppState extends State<TabbedNavigatorApp> {
TabNavigator _buildIconLabelsTabNavigator(int n) { TabNavigator _buildIconLabelsTabNavigator(int n) {
Iterable<TabNavigatorView> views = ["event", "home", "android", "alarm", "face", "language"] Iterable<TabNavigatorView> views = ["event", "home", "android", "alarm", "face", "language"]
.map((icon_name) { .map((String iconName) {
return new TabNavigatorView( return new TabNavigatorView(
label: new TabLabel(icon: "action/$icon_name"), label: new TabLabel(icon: "action/$iconName"),
builder: (BuildContext context) => _buildContent(icon_name) builder: (BuildContext context) => _buildContent(iconName)
); );
}); });
return _buildTabNavigator(n, views.toList(), const ValueKey<String>('iconLabelsTabNavigator')); return _buildTabNavigator(n, views.toList(), const ValueKey<String>('iconLabelsTabNavigator'));
......
...@@ -21,20 +21,20 @@ class Constraint { ...@@ -21,20 +21,20 @@ class Constraint {
switch (relation) { switch (relation) {
case Relation.equalTo: case Relation.equalTo:
buffer.write(" == 0 "); buffer.write(' == 0 ');
break; break;
case Relation.greaterThanOrEqualTo: case Relation.greaterThanOrEqualTo:
buffer.write(" >= 0 "); buffer.write(' >= 0 ');
break; break;
case Relation.lessThanOrEqualTo: case Relation.lessThanOrEqualTo:
buffer.write(" <= 0 "); buffer.write(' <= 0 ');
break; break;
} }
buffer.write(" | priority = ${priority}"); buffer.write(' | priority = $priority');
if (priority == Priority.required) { if (priority == Priority.required) {
buffer.write(" (required)"); buffer.write(' (required)');
} }
return buffer.toString(); return buffer.toString();
......
...@@ -58,7 +58,7 @@ class Expression extends _EquationMember { ...@@ -58,7 +58,7 @@ class Expression extends _EquationMember {
_createConstraint(value, Relation.lessThanOrEqualTo); _createConstraint(value, Relation.lessThanOrEqualTo);
operator ==(_EquationMember value) => operator ==(_EquationMember value) =>
_createConstraint(value, Relation.equalTo); _createConstraint(value, Relation.equalTo); // analyzer says "Type check failed" // analyzer says "The return type 'Constraint' is not a 'bool', as defined by the method '=='"
Expression operator +(_EquationMember m) { Expression operator +(_EquationMember m) {
if (m is ConstantMember) { if (m is ConstantMember) {
...@@ -140,7 +140,7 @@ class Expression extends _EquationMember { ...@@ -140,7 +140,7 @@ class Expression extends _EquationMember {
if (args == null) { if (args == null) {
throw new ParserException( throw new ParserException(
"Could not find constant multiplicand or multiplier", [this, m]); 'Could not find constant multiplicand or multiplier', [this, m]);
return null; return null;
} }
...@@ -150,7 +150,7 @@ class Expression extends _EquationMember { ...@@ -150,7 +150,7 @@ class Expression extends _EquationMember {
_EquationMember operator /(_EquationMember m) { _EquationMember operator /(_EquationMember m) {
if (!m.isConstant) { if (!m.isConstant) {
throw new ParserException( throw new ParserException(
"The divisor was not a constant expression", [this, m]); 'The divisor was not a constant expression', [this, m]);
return null; return null;
} }
...@@ -160,10 +160,10 @@ class Expression extends _EquationMember { ...@@ -160,10 +160,10 @@ class Expression extends _EquationMember {
String toString() { String toString() {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
terms.forEach((t) => buffer.write("${t}")); terms.forEach((t) => buffer.write('$t'));
if (constant != 0.0) { if (constant != 0.0) {
buffer.write(constant.sign > 0.0 ? "+" : "-"); buffer.write(constant.sign > 0.0 ? '+' : '-');
buffer.write(constant.abs()); buffer.write(constant.abs());
} }
......
...@@ -410,10 +410,10 @@ class Solver { ...@@ -410,10 +410,10 @@ class Solver {
double temp = row.coefficientForSymbol(entering); double temp = row.coefficientForSymbol(entering);
if (temp < 0.0) { if (temp < 0.0) {
double temp_ratio = -row.constant / temp; double tempRatio = -row.constant / temp;
if (temp_ratio < ratio) { if (tempRatio < ratio) {
ratio = temp_ratio; ratio = tempRatio;
result.first = symbol; result.first = symbol;
result.second = row; result.second = row;
} }
......
...@@ -13,24 +13,24 @@ class _Symbol { ...@@ -13,24 +13,24 @@ class _Symbol {
_Symbol(this.type, this.tick); _Symbol(this.type, this.tick);
String toString() { String toString() {
String typeString = "unknown"; String typeString = 'unknown';
switch (type) { switch (type) {
case _SymbolType.invalid: case _SymbolType.invalid:
typeString = "i"; typeString = 'i';
break; break;
case _SymbolType.external: case _SymbolType.external:
typeString = "v"; typeString = 'v';
break; break;
case _SymbolType.slack: case _SymbolType.slack:
typeString = "s"; typeString = 's';
break; break;
case _SymbolType.error: case _SymbolType.error:
typeString = "e"; typeString = 'e';
break; break;
case _SymbolType.dummy: case _SymbolType.dummy:
typeString = "d"; typeString = 'd';
break; break;
} }
return "${typeString}${tick}"; return '$typeString$tick';
} }
} }
...@@ -21,7 +21,7 @@ class Variable { ...@@ -21,7 +21,7 @@ class Variable {
return res; return res;
} }
String get debugName => _elvis(name, "variable${_tick}"); String get debugName => _elvis(name, 'variable$_tick');
String toString() => debugName; String toString() => debugName;
} }
...@@ -114,7 +114,7 @@ Future<String> read(url) => ...@@ -114,7 +114,7 @@ Future<String> read(url) =>
Future<Uint8List> readBytes(url) => Future<Uint8List> readBytes(url) =>
_withClient((client) => client.readBytes(url)); _withClient((client) => client.readBytes(url));
Future _withClient(Future fn(MojoClient)) { Future _withClient(Future fn(MojoClient client)) {
var client = new MojoClient(); var client = new MojoClient();
var future = fn(client); var future = fn(client);
return future.whenComplete(client.close); return future.whenComplete(client.close);
......
...@@ -132,7 +132,11 @@ class _PointerEventConverter { ...@@ -132,7 +132,11 @@ class _PointerEventConverter {
return 'mouse'; return 'mouse';
case PointerKind.STYLUS: case PointerKind.STYLUS:
return 'stylus'; return 'stylus';
case PointerKind.INVERTED_STYLUS:
return 'invertedStylus';
} }
assert(false);
return '';
} }
} }
......
...@@ -3,7 +3,7 @@ part of flutter_sprites; ...@@ -3,7 +3,7 @@ part of flutter_sprites;
// TODO: The sound effects should probably use Android's SoundPool instead of // TODO: The sound effects should probably use Android's SoundPool instead of
// MediaPlayer as it is more efficient and flexible for playing back sound effects // MediaPlayer as it is more efficient and flexible for playing back sound effects
typedef void SoundEffectStreamCallback(SoundEffectStream); typedef void SoundEffectStreamCallback(SoundEffectStream stream);
class SoundEffect { class SoundEffect {
SoundEffect(this._pipeFuture); SoundEffect(this._pipeFuture);
...@@ -137,8 +137,8 @@ class SoundEffectPlayer { ...@@ -137,8 +137,8 @@ class SoundEffectPlayer {
} }
} }
typedef void SoundTrackCallback(SoundTrack); typedef void SoundTrackCallback(SoundTrack soundTrack);
typedef void SoundTrackBufferingCallback(SoundTrack, int); typedef void SoundTrackBufferingCallback(SoundTrack soundTrack, int index);
class SoundTrack { class SoundTrack {
MediaPlayerProxy _player; MediaPlayerProxy _player;
......
...@@ -9,6 +9,7 @@ import 'package:args/command_runner.dart'; ...@@ -9,6 +9,7 @@ import 'package:args/command_runner.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:stack_trace/stack_trace.dart'; import 'package:stack_trace/stack_trace.dart';
import 'src/commands/analyze.dart';
import 'src/commands/build.dart'; import 'src/commands/build.dart';
import 'src/commands/cache.dart'; import 'src/commands/cache.dart';
import 'src/commands/daemon.dart'; import 'src/commands/daemon.dart';
...@@ -46,6 +47,7 @@ Future main(List<String> args) async { ...@@ -46,6 +47,7 @@ Future main(List<String> args) async {
}); });
FlutterCommandRunner runner = new FlutterCommandRunner() FlutterCommandRunner runner = new FlutterCommandRunner()
..addCommand(new AnalyzeCommand())
..addCommand(new BuildCommand()) ..addCommand(new BuildCommand())
..addCommand(new CacheCommand()) ..addCommand(new CacheCommand())
..addCommand(new DaemonCommand()) ..addCommand(new DaemonCommand())
......
...@@ -48,9 +48,9 @@ String _getCloudStorageBaseUrl({String category, String platform, String revisio ...@@ -48,9 +48,9 @@ String _getCloudStorageBaseUrl({String category, String platform, String revisio
// In the fullness of time, we'll have a consistent URL pattern for all of // In the fullness of time, we'll have a consistent URL pattern for all of
// our artifacts, but, for the time being, Mac OS X artifacts are stored in a // our artifacts, but, for the time being, Mac OS X artifacts are stored in a
// different cloud storage bucket. // different cloud storage bucket.
return 'https://storage.googleapis.com/mojo_infra/flutter/${platform}/${revision}/'; return 'https://storage.googleapis.com/mojo_infra/flutter/$platform/$revision/';
} }
return 'https://storage.googleapis.com/mojo/sky/${category}/${platform}/${revision}/'; return 'https://storage.googleapis.com/mojo/sky/$category/$platform/$revision/';
} }
enum ArtifactType { enum ArtifactType {
......
This diff is collapsed.
...@@ -93,7 +93,7 @@ dynamic _loadManifest(String manifestPath) { ...@@ -93,7 +93,7 @@ dynamic _loadManifest(String manifestPath) {
} }
ArchiveFile _createFile(String key, String assetBase) { ArchiveFile _createFile(String key, String assetBase) {
File file = new File('${assetBase}/${key}'); File file = new File('$assetBase/$key');
if (!file.existsSync()) if (!file.existsSync())
return null; return null;
List<int> content = file.readAsBytesSync(); List<int> content = file.readAsBytesSync();
......
...@@ -60,7 +60,7 @@ class DaemonCommand extends FlutterCommand { ...@@ -60,7 +60,7 @@ class DaemonCommand extends FlutterCommand {
stdout.writeln('[${JSON.encode(command)}]'); stdout.writeln('[${JSON.encode(command)}]');
}, daemonCommand: this); }, daemonCommand: this);
return daemon.onExit; return await daemon.onExit;
} }
} }
...@@ -98,19 +98,19 @@ class Daemon { ...@@ -98,19 +98,19 @@ class Daemon {
var id = command['id']; var id = command['id'];
if (id == null) { if (id == null) {
_logging.severe('no id for command: ${command}'); _logging.severe('no id for command: $command');
return; return;
} }
try { try {
String event = command['event']; String event = command['event'];
if (event.indexOf('.') == -1) if (event.indexOf('.') == -1)
throw 'command not understood: ${event}'; throw 'command not understood: $event';
String prefix = event.substring(0, event.indexOf('.')); String prefix = event.substring(0, event.indexOf('.'));
String name = event.substring(event.indexOf('.') + 1); String name = event.substring(event.indexOf('.') + 1);
if (_domains[prefix] == null) if (_domains[prefix] == null)
throw 'no domain for command: ${command}'; throw 'no domain for command: $command';
_domains[prefix].handleEvent(name, id, command['params']); _domains[prefix].handleEvent(name, id, command['params']);
} catch (error, trace) { } catch (error, trace) {
...@@ -144,7 +144,7 @@ abstract class Domain { ...@@ -144,7 +144,7 @@ abstract class Domain {
new Future.sync(() { new Future.sync(() {
if (_handlers.containsKey(name)) if (_handlers.containsKey(name))
return _handlers[name](args); return _handlers[name](args);
throw 'command not understood: ${name}'; throw 'command not understood: $name';
}).then((result) { }).then((result) {
if (result == null) { if (result == null) {
_send({'id': id}); _send({'id': id});
...@@ -153,7 +153,7 @@ abstract class Domain { ...@@ -153,7 +153,7 @@ abstract class Domain {
} }
}).catchError((error, trace) { }).catchError((error, trace) {
_send({'id': id, 'error': _toJsonable(error)}); _send({'id': id, 'error': _toJsonable(error)});
_logging.warning('error handling ${name}', error, trace); _logging.warning('error handling $name', error, trace);
}); });
} }
...@@ -210,5 +210,5 @@ class AppDomain extends Domain { ...@@ -210,5 +210,5 @@ class AppDomain extends Domain {
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 || obj is List || obj == null)
return obj; return obj;
return '${obj}'; return '$obj';
} }
...@@ -56,7 +56,7 @@ abstract class FlutterCommand extends Command { ...@@ -56,7 +56,7 @@ abstract class FlutterCommand extends Command {
} }
} }
return runInProject(); return await runInProject();
} }
Future<int> runInProject(); Future<int> runInProject();
......
...@@ -6,12 +6,15 @@ import 'dart:async'; ...@@ -6,12 +6,15 @@ import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:args/command_runner.dart'; import 'package:args/command_runner.dart';
import 'package:logging/logging.dart';
import 'package:mustache4dart/mustache4dart.dart' as mustache; import 'package:mustache4dart/mustache4dart.dart' as mustache;
import 'package:path/path.dart' as p; import 'package:path/path.dart' as p;
import '../artifacts.dart'; import '../artifacts.dart';
import '../process.dart'; import '../process.dart';
final Logger _logging = new Logger('sky_tools.init');
class InitCommand extends Command { class InitCommand extends Command {
final String name = 'init'; final String name = 'init';
final String description = 'Create a new Flutter project.'; final String description = 'Create a new Flutter project.';
...@@ -20,7 +23,7 @@ class InitCommand extends Command { ...@@ -20,7 +23,7 @@ class InitCommand extends Command {
argParser.addOption('out', abbr: 'o', help: 'The output directory.'); argParser.addOption('out', abbr: 'o', help: 'The output directory.');
argParser.addFlag('pub', argParser.addFlag('pub',
defaultsTo: true, defaultsTo: true,
help: 'Whether to run pub after the project has been created.'); help: 'Whether to run "pub get" after the project has been created.');
} }
@override @override
...@@ -40,7 +43,7 @@ class InitCommand extends Command { ...@@ -40,7 +43,7 @@ class InitCommand extends Command {
String flutterPackagePath = p.join(flutterRoot, 'packages', 'flutter'); String flutterPackagePath = p.join(flutterRoot, 'packages', 'flutter');
if (!FileSystemEntity.isFileSync(p.join(flutterPackagePath, 'pubspec.yaml'))) { if (!FileSystemEntity.isFileSync(p.join(flutterPackagePath, 'pubspec.yaml'))) {
print('Unable to find package:flutter in ${flutterPackagePath}'); print('Unable to find package:flutter in $flutterPackagePath');
return 2; return 2;
} }
...@@ -58,17 +61,48 @@ class InitCommand extends Command { ...@@ -58,17 +61,48 @@ class InitCommand extends Command {
'''; ''';
if (argResults['pub']) { if (argResults['pub']) {
print("Running pub get..."); int code = await pubGet(directory: out.path);
if (code != 0)
return code;
}
print(message);
return 0;
}
Future<int> pubGet({
String directory: '',
bool skipIfAbsent: false,
bool verbose: true
}) async {
File pubSpecYaml = new File(p.join(directory, 'pubspec.yaml'));
File pubSpecLock = new File(p.join(directory, 'pubspec.lock'));
File dotPackages = new File(p.join(directory, '.packages'));
if (!pubSpecYaml.existsSync()) {
if (skipIfAbsent)
return 0;
_logging.severe('$directory: no pubspec.yaml found');
return 1;
}
if (!pubSpecLock.existsSync() || pubSpecYaml.lastModifiedSync().isAfter(pubSpecLock.lastModifiedSync())) {
if (verbose)
print("Running pub get in $directory...");
int code = await runCommandAndStreamOutput( int code = await runCommandAndStreamOutput(
[sdkBinaryName('pub'), 'get'], [sdkBinaryName('pub'), 'get'],
workingDirectory: out.path workingDirectory: directory
); );
if (code != 0) if (code != 0)
return code; return code;
} }
print(message); if ((pubSpecLock.existsSync() && pubSpecLock.lastModifiedSync().isAfter(pubSpecYaml.lastModifiedSync())) &&
return 0; (dotPackages.existsSync() && dotPackages.lastModifiedSync().isAfter(pubSpecYaml.lastModifiedSync())))
return 0;
_logging.severe('$directory: pubspec.yaml, pubspec.lock, and .packages are in an inconsistent state');
return 1;
} }
} }
......
...@@ -34,7 +34,7 @@ class RunMojoCommand extends Command { ...@@ -34,7 +34,7 @@ class RunMojoCommand extends Command {
String _makePathAbsolute(String relativePath) { String _makePathAbsolute(String relativePath) {
File file = new File(relativePath); File file = new File(relativePath);
if (!file.existsSync()) { if (!file.existsSync()) {
throw new Exception("Path \"${relativePath}\" does not exist"); throw new Exception('Path "$relativePath" does not exist');
} }
return file.absolute.path; return file.absolute.path;
} }
...@@ -79,8 +79,8 @@ class RunMojoCommand extends Command { ...@@ -79,8 +79,8 @@ class RunMojoCommand extends Command {
final appPath = _makePathAbsolute(argResults['app']); final appPath = _makePathAbsolute(argResults['app']);
Artifact artifact = ArtifactStore.getArtifact(type: ArtifactType.viewer, targetPlatform: TargetPlatform.linux); Artifact artifact = ArtifactStore.getArtifact(type: ArtifactType.viewer, targetPlatform: TargetPlatform.linux);
final viewerPath = _makePathAbsolute(await ArtifactStore.getPath(artifact)); final viewerPath = _makePathAbsolute(await ArtifactStore.getPath(artifact));
args.add('file://${appPath}'); args.add('file://$appPath');
args.add('--url-mappings=mojo:sky_viewer=file://${viewerPath}'); args.add('--url-mappings=mojo:sky_viewer=file://$viewerPath');
} }
if (useDevtools) { if (useDevtools) {
...@@ -115,6 +115,6 @@ class RunMojoCommand extends Command { ...@@ -115,6 +115,6 @@ class RunMojoCommand extends Command {
return 1; return 1;
} }
return runCommandAndStreamOutput(await _getShellConfig()); return await runCommandAndStreamOutput(await _getShellConfig());
} }
} }
...@@ -68,7 +68,7 @@ class StartCommand extends FlutterCommand { ...@@ -68,7 +68,7 @@ class StartCommand extends FlutterCommand {
if (FileSystemEntity.isDirectorySync(target)) if (FileSystemEntity.isDirectorySync(target))
mainPath = path.join(target, 'lib', 'main.dart'); mainPath = path.join(target, 'lib', 'main.dart');
if (!FileSystemEntity.isFileSync(mainPath)) { if (!FileSystemEntity.isFileSync(mainPath)) {
String message = 'Tried to run ${mainPath}, but that file does not exist.'; String message = 'Tried to run $mainPath, but that file does not exist.';
if (!argResults.wasParsed('target')) if (!argResults.wasParsed('target'))
message += '\nConsider using the -t option to specify that Dart file to start.'; message += '\nConsider using the -t option to specify that Dart file to start.';
stderr.writeln(message); stderr.writeln(message);
......
...@@ -11,7 +11,6 @@ import 'package:test/src/executable.dart' as executable; ...@@ -11,7 +11,6 @@ import 'package:test/src/executable.dart' as executable;
import '../artifacts.dart'; import '../artifacts.dart';
import '../build_configuration.dart'; import '../build_configuration.dart';
import '../process.dart';
import '../test/loader.dart' as loader; import '../test/loader.dart' as loader;
import 'flutter_command.dart'; import 'flutter_command.dart';
...@@ -49,25 +48,6 @@ class TestCommand extends FlutterCommand { ...@@ -49,25 +48,6 @@ class TestCommand extends FlutterCommand {
testArgs.insert(0, '--no-color'); testArgs.insert(0, '--no-color');
List<BuildConfiguration> configs = buildConfigurations; List<BuildConfiguration> configs = buildConfigurations;
bool foundOne = false; bool foundOne = false;
File pubSpecYaml = new File(path.join(flutterDir.path, 'pubspec.yaml'));
File pubSpecLock = new File(path.join(flutterDir.path, 'pubspec.lock'));
if (!pubSpecYaml.existsSync()) {
print('${flutterDir.path} has no pubspec.yaml');
return 1;
}
if (!pubSpecLock.existsSync() || pubSpecYaml.lastModifiedSync().isAfter(pubSpecLock.lastModifiedSync())) {
print("Running pub get...");
int code = await runCommandAndStreamOutput(
[sdkBinaryName('pub'), 'get'],
workingDirectory: flutterDir.path
);
if (code != 0)
return code;
}
String currentDirectory = Directory.current.path; String currentDirectory = Directory.current.path;
Directory.current = flutterDir.path; Directory.current = flutterDir.path;
loader.installHook(); loader.installHook();
......
...@@ -19,36 +19,8 @@ abstract class Device { ...@@ -19,36 +19,8 @@ abstract class Device {
final String id; final String id;
static Map<String, Device> _deviceCache = {}; static Map<String, Device> _deviceCache = {};
factory Device._unique(String className, [String id = null]) { static Device _unique(String id, Device constructor(String id)) {
if (id == null) { return _deviceCache.putIfAbsent(id, () => constructor(id));
if (className == AndroidDevice.className) {
id = AndroidDevice.defaultDeviceID;
} else if (className == IOSDevice.className) {
id = IOSDevice.defaultDeviceID;
} else if (className == IOSSimulator.className) {
id = IOSSimulator.defaultDeviceID;
} else {
throw 'Attempted to create a Device of unknown type $className';
}
}
return _deviceCache.putIfAbsent(id, () {
if (className == AndroidDevice.className) {
final device = new AndroidDevice._(id);
_deviceCache[id] = device;
return device;
} else if (className == IOSDevice.className) {
final device = new IOSDevice._(id);
_deviceCache[id] = device;
return device;
} else if (className == IOSSimulator.className) {
final device = new IOSSimulator._(id);
_deviceCache[id] = device;
return device;
} else {
throw 'Attempted to create a Device of unknown type $className';
}
});
} }
Device._(this.id); Device._(this.id);
...@@ -74,7 +46,6 @@ abstract class Device { ...@@ -74,7 +46,6 @@ abstract class Device {
} }
class IOSDevice extends Device { class IOSDevice extends Device {
static const String className = 'IOSDevice';
static final String defaultDeviceID = 'default_ios_id'; static final String defaultDeviceID = 'default_ios_id';
static const String _macInstructions = static const String _macInstructions =
...@@ -108,7 +79,7 @@ class IOSDevice extends Device { ...@@ -108,7 +79,7 @@ class IOSDevice extends Device {
String get name => _name; String get name => _name;
factory IOSDevice({String id, String name}) { factory IOSDevice({String id, String name}) {
IOSDevice device = new Device._unique(className, id); IOSDevice device = Device._unique(id ?? defaultDeviceID, new IOSDevice#_); // analyzer doesn't like constructor tear-offs
device._name = name; device._name = name;
return device; return device;
} }
...@@ -224,14 +195,17 @@ class IOSDevice extends Device { ...@@ -224,14 +195,17 @@ class IOSDevice extends Device {
} }
// idevicedebug hangs forever after launching the app, so kill it after // idevicedebug hangs forever after launching the app, so kill it after
// giving it plenty of time to send the launch command. // giving it plenty of time to send the launch command.
return runAndKill( return await runAndKill(
[debuggerPath, 'run', app.id], new Duration(seconds: 3)).then( [debuggerPath, 'run', app.id],
(_) { new Duration(seconds: 3)
return true; ).then(
}, onError: (e) { (_) {
_logging.info('Failure running $debuggerPath: ', e); return true;
return false; }, onError: (e) {
}); _logging.info('Failure running $debuggerPath: ', e);
return false;
}
);
} }
@override @override
...@@ -274,13 +248,12 @@ class IOSDevice extends Device { ...@@ -274,13 +248,12 @@ class IOSDevice extends Device {
if (!isConnected()) { if (!isConnected()) {
return 2; return 2;
} }
return runCommandAndStreamOutput([loggerPath], return await runCommandAndStreamOutput([loggerPath],
prefix: 'iOS dev: ', filter: new RegExp(r'.*SkyShell.*')); prefix: 'iOS dev: ', filter: new RegExp(r'.*SkyShell.*'));
} }
} }
class IOSSimulator extends Device { class IOSSimulator extends Device {
static const String className = 'IOSSimulator';
static final String defaultDeviceID = 'default_ios_sim_id'; static final String defaultDeviceID = 'default_ios_sim_id';
static const String _macInstructions = static const String _macInstructions =
...@@ -299,7 +272,7 @@ class IOSSimulator extends Device { ...@@ -299,7 +272,7 @@ class IOSSimulator extends Device {
String get name => _name; String get name => _name;
factory IOSSimulator({String id, String name, String iOSSimulatorPath}) { factory IOSSimulator({String id, String name, String iOSSimulatorPath}) {
IOSSimulator device = new Device._unique(className, id); IOSSimulator device = Device._unique(id ?? defaultDeviceID, new IOSSimulator#_); // analyzer doesn't like constructor tear-offs
device._name = name; device._name = name;
if (iOSSimulatorPath == null) { if (iOSSimulatorPath == null) {
iOSSimulatorPath = path.join('/Applications', 'iOS Simulator.app', iOSSimulatorPath = path.join('/Applications', 'iOS Simulator.app',
...@@ -309,7 +282,7 @@ class IOSSimulator extends Device { ...@@ -309,7 +282,7 @@ class IOSSimulator extends Device {
return device; return device;
} }
IOSSimulator._(String id) : super._(id) {} IOSSimulator._(String id) : super._(id);
static String _getRunningSimulatorID([IOSSimulator mockIOS]) { static String _getRunningSimulatorID([IOSSimulator mockIOS]) {
String xcrunPath = mockIOS != null ? mockIOS.xcrunPath : _xcrunPath; String xcrunPath = mockIOS != null ? mockIOS.xcrunPath : _xcrunPath;
...@@ -380,7 +353,6 @@ class IOSSimulator extends Device { ...@@ -380,7 +353,6 @@ class IOSSimulator extends Device {
} }
if (id == defaultDeviceID) { if (id == defaultDeviceID) {
runDetached([iOSSimPath]); runDetached([iOSSimPath]);
Future<bool> checkConnection([int attempts = 20]) async { Future<bool> checkConnection([int attempts = 20]) async {
if (attempts == 0) { if (attempts == 0) {
_logging.info('Timed out waiting for iOS Simulator $id to boot.'); _logging.info('Timed out waiting for iOS Simulator $id to boot.');
...@@ -388,12 +360,12 @@ class IOSSimulator extends Device { ...@@ -388,12 +360,12 @@ class IOSSimulator extends Device {
} }
if (!isConnected()) { if (!isConnected()) {
_logging.info('Waiting for iOS Simulator $id to boot...'); _logging.info('Waiting for iOS Simulator $id to boot...');
return new Future.delayed(new Duration(milliseconds: 500), return await new Future.delayed(new Duration(milliseconds: 500),
() => checkConnection(attempts - 1)); () => checkConnection(attempts - 1));
} }
return true; return true;
} }
return checkConnection(); return await checkConnection();
} else { } else {
try { try {
runCheckedSync([xcrunPath, 'simctl', 'boot', id]); runCheckedSync([xcrunPath, 'simctl', 'boot', id]);
...@@ -496,7 +468,7 @@ class IOSSimulator extends Device { ...@@ -496,7 +468,7 @@ class IOSSimulator extends Device {
if (clear) { if (clear) {
runSync(['rm', logFilePath]); runSync(['rm', logFilePath]);
} }
return runCommandAndStreamOutput(['tail', '-f', logFilePath], return await runCommandAndStreamOutput(['tail', '-f', logFilePath],
prefix: 'iOS sim: ', filter: new RegExp(r'.*SkyShell.*')); prefix: 'iOS sim: ', filter: new RegExp(r'.*SkyShell.*'));
} }
} }
...@@ -505,7 +477,6 @@ class AndroidDevice extends Device { ...@@ -505,7 +477,6 @@ class AndroidDevice extends Device {
static const String _ADB_PATH = 'adb'; static const String _ADB_PATH = 'adb';
static const int _observatoryPort = 8181; static const int _observatoryPort = 8181;
static const String className = 'AndroidDevice';
static final String defaultDeviceID = 'default_android_device'; static final String defaultDeviceID = 'default_android_device';
String productID; String productID;
...@@ -522,7 +493,7 @@ class AndroidDevice extends Device { ...@@ -522,7 +493,7 @@ class AndroidDevice extends Device {
String productID: null, String productID: null,
String modelID: null, String modelID: null,
String deviceCodeName: null}) { String deviceCodeName: null}) {
AndroidDevice device = new Device._unique(className, id); AndroidDevice device = Device._unique(id ?? defaultDeviceID, new AndroidDevice#_); // analyzer doesn't like constructor tear-offs
device.productID = productID; device.productID = productID;
device.modelID = modelID; device.modelID = modelID;
device.deviceCodeName = deviceCodeName; device.deviceCodeName = deviceCodeName;
...@@ -813,7 +784,7 @@ class AndroidDevice extends Device { ...@@ -813,7 +784,7 @@ class AndroidDevice extends Device {
clearLogs(); clearLogs();
} }
return runCommandAndStreamOutput(adbCommandForDevice([ return await runCommandAndStreamOutput(adbCommandForDevice([
'logcat', 'logcat',
'-v', '-v',
'tag', // Only log the tag and the message 'tag', // Only log the tag and the message
......
...@@ -18,33 +18,35 @@ Future<int> runCommandAndStreamOutput(List<String> cmd, { ...@@ -18,33 +18,35 @@ Future<int> runCommandAndStreamOutput(List<String> cmd, {
String workingDirectory String workingDirectory
}) async { }) async {
_logging.info(cmd.join(' ')); _logging.info(cmd.join(' '));
Process proc = await Process.start( Process process = await Process.start(
cmd[0], cmd[0],
cmd.getRange(1, cmd.length).toList(), cmd.sublist(1),
workingDirectory: workingDirectory workingDirectory: workingDirectory
); );
proc.stdout.transform(UTF8.decoder).listen((String data) { process.stdout.transform(UTF8.decoder).listen((String data) {
List<String> dataLines = data.trimRight().split('\n'); List<String> dataLines = data.trimRight().split('\n');
if (filter != null) { if (filter != null) {
// TODO(ianh): This doesn't handle IO buffering (where the data might be split half-way through a line)
dataLines = dataLines.where((String s) => filter.hasMatch(s)).toList(); dataLines = dataLines.where((String s) => filter.hasMatch(s)).toList();
} }
if (dataLines.length > 0) { if (dataLines.length > 0) {
stdout.write('$prefix${dataLines.join('\n$prefix')}\n'); stdout.write('$prefix${dataLines.join('\n$prefix')}\n');
} }
}); });
proc.stderr.transform(UTF8.decoder).listen((String data) { process.stderr.transform(UTF8.decoder).listen((String data) {
List<String> dataLines = data.trimRight().split('\n'); List<String> dataLines = data.trimRight().split('\n');
if (filter != null) { if (filter != null) {
// TODO(ianh): This doesn't handle IO buffering (where the data might be split half-way through a line)
dataLines = dataLines.where((String s) => filter.hasMatch(s)); dataLines = dataLines.where((String s) => filter.hasMatch(s));
} }
if (dataLines.length > 0) { if (dataLines.length > 0) {
stderr.write('$prefix${dataLines.join('\n$prefix')}\n'); stderr.write('$prefix${dataLines.join('\n$prefix')}\n');
} }
}); });
return proc.exitCode; return await process.exitCode;
} }
Future runAndKill(List<String> cmd, Duration timeout) async { Future 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.delayed(timeout, () async {
_logging.info('Intentionally killing ${cmd[0]}'); _logging.info('Intentionally killing ${cmd[0]}');
...@@ -52,7 +54,7 @@ Future runAndKill(List<String> cmd, Duration timeout) async { ...@@ -52,7 +54,7 @@ Future runAndKill(List<String> cmd, Duration timeout) async {
}); });
} }
Future<Process> runDetached(List<String> cmd) async { Future<Process> runDetached(List<String> cmd) {
_logging.info(cmd.join(' ')); _logging.info(cmd.join(' '));
Future<Process> proc = Process.start( Future<Process> proc = Process.start(
cmd[0], cmd.getRange(1, cmd.length).toList(), cmd[0], cmd.getRange(1, cmd.length).toList(),
...@@ -97,6 +99,6 @@ String _runWithLoggingSync(List<String> cmd, {bool checked: false}) { ...@@ -97,6 +99,6 @@ String _runWithLoggingSync(List<String> cmd, {bool checked: false}) {
class ProcessExit implements Exception { class ProcessExit implements Exception {
final int exitCode; final int exitCode;
ProcessExit(this.exitCode); ProcessExit(this.exitCode);
String get message => 'ProcessExit: ${exitCode}'; String get message => 'ProcessExit: $exitCode';
String toString() => message; String toString() => message;
} }
...@@ -50,8 +50,9 @@ class BoundedFrictionSimulation extends FrictionSimulation { ...@@ -50,8 +50,9 @@ class BoundedFrictionSimulation extends FrictionSimulation {
double drag, double drag,
double position, double position,
double velocity, double velocity,
double this._minX, this._minX,
double this._maxX) : super(drag, position, velocity); this._maxX
) : super(drag, position, velocity);
final double _minX; final double _minX;
final double _maxX; final double _maxX;
......
...@@ -17,7 +17,8 @@ class SpringDescription { ...@@ -17,7 +17,8 @@ class SpringDescription {
final double damping; final double damping;
SpringDescription( SpringDescription(
{double this.mass, double this.springConstant, double this.damping}) { { this.mass, this.springConstant, this.damping }
) {
assert(mass != null); assert(mass != null);
assert(springConstant != null); assert(springConstant != null);
assert(damping != null); assert(damping != null);
......
import 'dart:ui' as ui;
import 'package:flutter/gestures.dart'; import 'package:flutter/gestures.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'velocity_tracker_data.dart'; import 'velocity_tracker_data.dart';
...@@ -45,20 +43,4 @@ void main() { ...@@ -45,20 +43,4 @@ void main() {
watch.stop(); watch.stop();
print("Dart tracker: " + watch.elapsed.toString()); print("Dart tracker: " + watch.elapsed.toString());
}); });
test('Native velocity tracker performance', () {
ui.VelocityTracker tracker = new ui.VelocityTracker();
Stopwatch watch = new Stopwatch();
watch.start();
for (int i = 0; i < kNumIters; i++) {
for (PointerInputEvent event in events) {
if (event.type == 'pointerdown' || event.type == 'pointermove')
tracker.addPosition((event.timeStamp*1000.0).toInt(), event.x, event.y);
if (event.type == 'pointerup')
tracker.getVelocity();
}
}
watch.stop();
print("Native tracker: " + watch.elapsed.toString());
});
} }
...@@ -8,16 +8,19 @@ import 'rendering_tester.dart'; ...@@ -8,16 +8,19 @@ import 'rendering_tester.dart';
class SquareImage implements ui.Image { class SquareImage implements ui.Image {
int get width => 10; int get width => 10;
int get height => 10; int get height => 10;
void dispose() { }
} }
class WideImage implements ui.Image { class WideImage implements ui.Image {
int get width => 20; int get width => 20;
int get height => 10; int get height => 10;
void dispose() { }
} }
class TallImage implements ui.Image { class TallImage implements ui.Image {
int get width => 10; int get width => 10;
int get height => 20; int get height => 20;
void dispose() { }
} }
void main() { void main() {
......
#!/bin/bash #!/bin/bash
set -ex set -ex
(cd packages/cassowary; pub global run tuneup check; pub run test -j1) # analyze all the Dart code in the repo
(cd packages/flutter_sprites; pub global run tuneup check) # No tests to run. ./bin/flutter analyze --flutter-repo --no-current-directory --no-current-package --congratulate
(cd packages/flutter_tools; pub global run tuneup check; pub run test -j1)
(cd packages/flx; pub global run tuneup check; pub run test -j1)
(cd packages/newton; pub global run tuneup check; pub run test -j1)
(cd packages/playfair; pub global run tuneup check) # No tests to run.
(cd packages/updater; pub global run tuneup check) # No tests to run.
# flutter package tests
./bin/flutter test --engine-src-path bin/cache/travis ./bin/flutter test --engine-src-path bin/cache/travis
(cd packages/cassowary; pub run test -j1)
# (cd packages/flutter_sprites; ) # No tests to run.
(cd packages/flutter_tools; pub run test -j1)
(cd packages/flx; pub run test -j1)
(cd packages/newton; pub run test -j1)
# (cd packages/playfair; ) # No tests to run.
# (cd packages/updater; ) # No tests to run.
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