Commit fcfb2a5c authored by Devon Carew's avatar Devon Carew Committed by GitHub

Better progress (#6677)

* make showElapsedTime default to true

* support nested progresses

* improve hot reload message

* rethrow
parent 1f1adcaa
......@@ -241,7 +241,7 @@ class AndroidDevice extends Device {
Status status = logger.startProgress('Installing ${apk.apkPath}...');
String installOut = runCheckedSync(adbCommandForDevice(<String>['install', '-r', apk.apkPath]));
status.stop(showElapsedTime: true);
status.stop();
RegExp failureExp = new RegExp(r'^Failure.*$', multiLine: true);
String failure = failureExp.stringMatch(installOut);
if (failure != null) {
......
......@@ -137,7 +137,7 @@ Future<int> buildGradleProject(BuildMode buildMode) async {
workingDirectory: 'android',
allowReentrantFlutter: true
);
status.stop(showElapsedTime: true);
status.stop();
if (exitcode != 0)
return exitcode;
} catch (error) {
......@@ -159,7 +159,7 @@ Future<int> buildGradleProject(BuildMode buildMode) async {
workingDirectory: 'android',
allowReentrantFlutter: true
);
status.stop(showElapsedTime: true);
status.stop();
if (exitcode == 0) {
File apkFile = new File(gradleAppOut);
......
......@@ -37,7 +37,7 @@ abstract class Logger {
}
class Status {
void stop({ bool showElapsedTime: false }) { }
void stop({ bool showElapsedTime: true }) { }
void cancel() { }
}
......@@ -73,15 +73,17 @@ class StdoutLogger extends Logger {
@override
Status startProgress(String message) {
_status?.cancel();
_status = null;
if (supportsColor) {
_status = new _AnsiStatus(message);
return _status;
} else {
printStatus(message);
if (_status != null) {
// Ignore nested progresses; return a no-op status object.
return new Status();
} else {
if (supportsColor) {
_status = new _AnsiStatus(message);
return _status;
} else {
printStatus(message);
return new Status();
}
}
}
}
......@@ -244,13 +246,13 @@ class _AnsiStatus extends Status {
}
@override
void stop({ bool showElapsedTime: false }) {
void stop({ bool showElapsedTime: true }) {
if (!live)
return;
live = false;
if (showElapsedTime) {
print('\b\b\b\b${stopwatch.elapsedMilliseconds.toString()}ms');
print('\b\b\b\b\b${stopwatch.elapsedMilliseconds.toString().padLeft(3)}ms');
} else {
print('\b ');
}
......
......@@ -233,7 +233,7 @@ class MaterialFonts {
Uri.parse(cache.getVersionFor(kName)), fontsDir, true
).then((_) {
cache.setStampFor(kName, cache.getVersionFor(kName));
status.stop(showElapsedTime: true);
status.stop();
}).whenComplete(() {
status.cancel();
});
......@@ -346,7 +346,7 @@ class FlutterEngine {
String skyEnginePath = path.join(pkgDir.path, kSkyEngine);
buildSkyEngineSdkSummary(skyEnginePath, kSdkBundle);
} finally {
summaryStatus.stop(showElapsedTime: true);
summaryStatus.stop();
}
Directory engineDir = cache.getArtifactDirectory(kName);
......@@ -389,7 +389,7 @@ class FlutterEngine {
Future<Null> _downloadItem(String message, String url, Directory dest) {
Status status = logger.startProgress(message);
return Cache._downloadFileToCache(Uri.parse(url), dest, true).then((_) {
status.stop(showElapsedTime: true);
status.stop();
}).whenComplete(() {
status.cancel();
});
......
......@@ -66,7 +66,7 @@ class AnalyzeContinuously extends AnalyzeBase {
analyzedPaths.clear();
analysisTimer = new Stopwatch()..start();
} else {
analysisStatus?.stop(showElapsedTime: true);
analysisStatus?.stop();
analysisTimer.stop();
logger.printStatus(terminal.clearScreen(), newline: false);
......
......@@ -60,7 +60,7 @@ class BuildAotCommand extends BuildSubCommand {
outputPath: argResults['output-dir'],
interpreter: argResults['interpreter']
);
status.stop(showElapsedTime: true);
status.stop();
if (outputPath == null)
return 1;
......
......@@ -591,7 +591,7 @@ Future<int> buildAndroid(
}
int result = _buildApk(platform, buildMode, components, flxPath, keystore, outputFile);
status.stop(showElapsedTime: true);
status.stop();
if (result == 0) {
File apkFile = new File(outputFile);
......
......@@ -78,7 +78,7 @@ class BuildIOSCommand extends BuildSubCommand {
buildForDevice: !forSimulator,
codesign: shouldCodesign
);
status.stop(showElapsedTime: true);
status.stop();
if (!result.success) {
printError('Encountered error while building for $logTarget.');
......
......@@ -705,8 +705,14 @@ class _AppRunLogger extends Logger {
@override
void printTrace(String message) { }
Status _status;
@override
Status startProgress(String message) {
// Ignore nested progresses; return a no-op status object.
if (_status != null)
return new Status();
int id = _nextProgressId++;
_sendLogEvent(<String, dynamic>{
......@@ -715,7 +721,8 @@ class _AppRunLogger extends Logger {
'id': id.toString()
});
return new _AppLoggerStatus(this, id);
_status = new _AppLoggerStatus(this, id);
return _status;
}
void close() {
......@@ -737,12 +744,14 @@ class _AppLoggerStatus implements Status {
final int id;
@override
void stop({ bool showElapsedTime: false }) {
void stop({ bool showElapsedTime: true }) {
logger._status = null;
_sendFinished();
}
@override
void cancel() {
logger._status = null;
_sendFinished();
}
......
......@@ -89,7 +89,7 @@ class TestCommand extends FlutterCommand {
Future<bool> _collectCoverageData(CoverageCollector collector, { bool mergeCoverageData: false }) async {
Status status = logger.startProgress('Collecting coverage information...');
String coverageData = await collector.finalizeCoverage();
status.stop(showElapsedTime: true);
status.stop();
if (coverageData == null)
return false;
......
......@@ -42,7 +42,7 @@ class UpdatePackagesCommand extends FlutterCommand {
new File(path.join(coverageDir, 'lcov.info'))
..createSync(recursive: true)
..writeAsBytesSync(data, flush: true);
status.stop(showElapsedTime: true);
status.stop();
}
@override
......
......@@ -53,7 +53,7 @@ Future<int> pubGet({
mapFunction: _filterOverrideWarnings,
environment: <String, String>{ 'FLUTTER_ROOT': Cache.flutterRoot }
);
status.stop(showElapsedTime: true);
status.stop();
if (code != 0)
return code;
}
......
......@@ -102,7 +102,7 @@ Future<Null> _buildUnlinkedForPackage(
try {
await manager.computeUnlinkedForFolder(name, libFolder);
} finally {
status.stop(showElapsedTime: true);
status.stop();
}
}
}
......
......@@ -339,15 +339,7 @@ class HotRunner extends ResidentRunner {
Future<Null> handleTerminalCommand(String code) async {
final String lower = code.toLowerCase();
if ((lower == 'r') || (code == AnsiTerminal.KEY_F5)) {
OperationResult result = OperationResult.ok;
// F5, restart
if ((code == 'r') || (code == AnsiTerminal.KEY_F5)) {
// lower-case 'r'
result = await _reloadSources();
} else {
// upper-case 'R'.
result = await _restartFromSources();
}
OperationResult result = await restart(fullRestart: code == 'R');
if (!result.isOk) {
// TODO(johnmccutchan): Attempt to determine the number of errors that
// occurred and tighten this message.
......@@ -396,7 +388,7 @@ class HotRunner extends ResidentRunner {
bundle: bundle,
bundleDirty: rebuildBundle,
fileFilter: _dartDependencies);
devFSStatus.stop(showElapsedTime: true);
devFSStatus.stop();
// Clear the set after the sync.
_dartDependencies = null;
printTrace('Synced ${getSizeAsMB(_devFS.bytes)}.');
......@@ -461,10 +453,10 @@ class HotRunner extends ResidentRunner {
// Wait for the first frame to be rendered.
await firstFrameTimer.firstFrame();
}
restartStatus.stop(showElapsedTime: true);
restartStatus.stop();
if (waitForFrame) {
printStatus('Restart performed in '
'${getElapsedAsMilliseconds(firstFrameTimer.elapsed)}.');
printTrace('Restart performed in '
'${getElapsedAsMilliseconds(firstFrameTimer.elapsed)}.');
if (benchmarkMode) {
benchmarkData['hotRestartMillisecondsToFrame'] =
firstFrameTimer.elapsed.inMilliseconds;
......@@ -476,25 +468,41 @@ class HotRunner extends ResidentRunner {
}
/// Returns [true] if the reload was successful.
bool _printReloadReport(Map<String, dynamic> reloadReport) {
bool _validateReloadReport(Map<String, dynamic> reloadReport) {
if (!reloadReport['success']) {
printError('Hot reload was rejected:');
for (Map<String, dynamic> notice in reloadReport['details']['notices'])
printError('${notice['message']}');
return false;
}
int loadedLibraryCount = reloadReport['details']['loadedLibraryCount'];
int finalLibraryCount = reloadReport['details']['finalLibraryCount'];
printStatus('Reloaded $loadedLibraryCount of $finalLibraryCount libraries.');
return true;
}
@override
Future<OperationResult> restart({ bool fullRestart: false, bool pauseAfterRestart: false }) async {
if (fullRestart) {
return _restartFromSources();
Status status = logger.startProgress('Performing full restart...');
try {
await _restartFromSources();
status.stop();
printStatus('Restart complete.');
return OperationResult.ok;
} catch (error) {
status.stop();
rethrow;
}
} else {
return _reloadSources(pause: pauseAfterRestart);
Status status = logger.startProgress('Performing hot reload...');
try {
OperationResult result = await _reloadSources(pause: pauseAfterRestart);
status.stop();
if (result.isOk)
printStatus("${result.message}.");
return result;
} catch (error) {
status.stop();
rethrow;
}
}
}
......@@ -508,24 +516,23 @@ class HotRunner extends ResidentRunner {
if (!updatedDevFS)
return new OperationResult(1, 'Dart Source Error');
}
Status reloadStatus = logger.startProgress('Performing hot reload...');
String reloadMessage;
try {
Map<String, dynamic> reloadReport =
await currentView.uiIsolate.reloadSources(pause: pause);
reloadStatus.stop(showElapsedTime: true);
if (!_printReloadReport(reloadReport)) {
if (!_validateReloadReport(reloadReport)) {
// Reload failed.
flutterUsage.sendEvent('hot', 'reload-reject');
return new OperationResult(1, 'reload rejected');
} else {
flutterUsage.sendEvent('hot', 'reload');
int loadedLibraryCount = reloadReport['details']['loadedLibraryCount'];
int finalLibraryCount = reloadReport['details']['finalLibraryCount'];
reloadMessage = 'Reloaded $loadedLibraryCount of $finalLibraryCount libraries';
}
} catch (error, st) {
int errorCode = error['code'];
String errorMessage = error['message'];
reloadStatus.stop(showElapsedTime: true);
if (errorCode == Isolate.kIsolateReloadBarred) {
printError('Unable to hot reload app due to an unrecoverable error in '
'the source code. Please address the error and then use '
......@@ -565,15 +572,15 @@ class HotRunner extends ResidentRunner {
// When the framework is present, we can wait for the first frame
// event and measure reload time.
await firstFrameTimer.firstFrame();
printStatus('Hot reload performed in '
'${getElapsedAsMilliseconds(firstFrameTimer.elapsed)}.');
printTrace('Hot reload performed in '
'${getElapsedAsMilliseconds(firstFrameTimer.elapsed)}.');
if (benchmarkMode) {
benchmarkData['hotReloadMillisecondsToFrame'] =
firstFrameTimer.elapsed.inMilliseconds;
}
flutterUsage.sendTiming('hot', 'reload', firstFrameTimer.elapsed);
}
return OperationResult.ok;
return new OperationResult(OperationResult.ok.code, reloadMessage);
}
@override
......
......@@ -89,7 +89,7 @@ class RunAndStayResident extends ResidentRunner {
prebuiltApplication: prebuiltMode
);
status.stop(showElapsedTime: true);
status.stop();
if (result && extensionAddedEvent != null) {
await extensionAddedEvent;
......
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