Skip to content

Commit 924f362

Browse files
authored
fix(cli): Improve reload handling (#466)
- When compilation errors are flagged, accept the result from the frontend server so that we can call `compile` again - Reload all isolates when performing a hot reload
1 parent d77c3e3 commit 924f362

File tree

3 files changed

+21
-17
lines changed

3 files changed

+21
-17
lines changed

apps/cli/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## NEXT
2+
3+
- fix: Improved reload handling
4+
15
## 1.0.14
26

37
- feat: Allow overriding client environment with Dart define

apps/cli/lib/src/compiler/api/local_api_runner.dart

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import 'package:celest_cli/src/utils/error.dart';
1111
import 'package:celest_cli/src/utils/json.dart';
1212
import 'package:celest_cli/src/utils/process.dart';
1313
import 'package:celest_cli/src/utils/run.dart';
14-
import 'package:collection/collection.dart';
1514
import 'package:logging/logging.dart';
1615
import 'package:meta/meta.dart';
1716
import 'package:vm_service/vm_service.dart';
@@ -39,7 +38,6 @@ final class LocalApiRunner {
3938
final FrontendServerClient _client;
4039
final Process _localApiProcess;
4140
VmService? _vmService;
42-
late final String _vmIsolateId;
4341

4442
/// The WebSocket URI of the running Celest server.
4543
String get wsUri => _vmService!.wsUri!;
@@ -53,7 +51,6 @@ final class LocalApiRunner {
5351
required String environmentId,
5452
required Map<String, String> configValues,
5553
required bool verbose,
56-
List<String> additionalSources = const [],
5754
int? port,
5855
@visibleForTesting Duration? vmServiceTimeout,
5956
@visibleForTesting StringSink? stdoutPipe,
@@ -269,7 +266,7 @@ final class LocalApiRunner {
269266
);
270267

271268
/// Waits for the main Isolate to be available, resume it, then return its ID.
272-
static Future<String> _waitForIsolatesAndResume(VmService vmService) async {
269+
static Future<void> _waitForIsolatesAndResume(VmService vmService) async {
273270
var vm = await vmService.getVM();
274271
var isolates = vm.isolates;
275272
final stopwatch = Stopwatch()..start();
@@ -288,14 +285,6 @@ final class LocalApiRunner {
288285
'VM started in ${stopwatch.elapsedMilliseconds}ms. '
289286
'Isolates: $isolates',
290287
);
291-
var isolateRef = isolates.firstWhereOrNull(
292-
(isolate) => isolate.isSystemIsolate ?? false,
293-
);
294-
isolateRef ??= isolates.firstOrNull;
295-
if (isolateRef == null) {
296-
throw StateError('Could not determine main isolate ID.');
297-
}
298-
return isolateRef.id!;
299288
}
300289

301290
// Doesn't seem that we need pause-on-start anymore, but keeping code around
@@ -447,7 +436,7 @@ final class LocalApiRunner {
447436
});
448437
await _vmService!.streamListen(EventStreams.kLogging);
449438

450-
_vmIsolateId = await _waitForIsolatesAndResume(_vmService!);
439+
await _waitForIsolatesAndResume(_vmService!);
451440

452441
await Future.any([
453442
serverStartedCompleter.future,
@@ -480,7 +469,11 @@ final class LocalApiRunner {
480469
]);
481470
final dillOutput = _client.expectOutput(result);
482471
_logger.fine('Hot reloading local API with entrypoint: $dillOutput');
483-
await _vmService!.reloadSources(_vmIsolateId, rootLibUri: dillOutput);
472+
473+
final isolates = await _vmService!.getVM().then((vm) => vm.isolates!);
474+
for (final isolate in isolates) {
475+
await _vmService!.reloadSources(isolate.id!, rootLibUri: dillOutput);
476+
}
484477
}
485478

486479
// Copied from `package:flutter_tools/src/run_hot.dart`
@@ -546,9 +539,10 @@ final class LocalApiRunner {
546539
}
547540

548541
final class CompilationException implements Exception {
549-
CompilationException(this.message);
542+
CompilationException(this.message, [this.compilerOutput = const []]);
550543

551544
final String message;
545+
final List<String> compilerOutput;
552546

553547
@override
554548
String toString() => message;
@@ -563,8 +557,10 @@ extension on FrontendServerClient {
563557
switch (result) {
564558
case CompileResult(errorCount: > 0):
565559
_logger.finest('Error compiling local API', result.debugResult);
560+
accept(); // Always accept so we can call `compile` again.
566561
throw CompilationException(
567562
'Error compiling local API: ${result.debugResult}',
563+
result.compilerOutputLines.toList(),
568564
);
569565
case CompileResult(:final dillOutput?):
570566
accept();

apps/cli/lib/src/frontend/celest_frontend.dart

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,10 +391,14 @@ final class CelestFrontend with CloudRepository {
391391
)).port,
392392
);
393393
} on CompilationException catch (e, st) {
394+
currentProgress!.fail();
394395
cliLogger.err(
395396
'Project has errors. Please fix them and save the '
396397
'corresponding files.',
397398
);
399+
for (final compilerLine in e.compilerOutput) {
400+
cliLogger.err(compilerLine);
401+
}
398402
performance.captureError(e, stackTrace: st);
399403
break;
400404
}
@@ -453,8 +457,8 @@ final class CelestFrontend with CloudRepository {
453457
// there is one.
454458
final exitCode = await Future.any<int?>([
455459
_nextChangeSet().then((_) => null),
456-
if (childProcess case final childProcess?)
457-
Future.value(childProcess.exitCode),
460+
if (childProcess case final childProcess? when childProcess.isStarted)
461+
childProcess.exitCode,
458462
]);
459463
if (exitCode != null) {
460464
return exitCode;

0 commit comments

Comments
 (0)