Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ linter:
rules:
- prefer_const_constructors
- prefer_const_declarations
- unawaited_futures
- cancel_subscriptions
- close_sinks
- avoid_void_async

2 changes: 1 addition & 1 deletion lib/core/database/connection_pool_lock.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class PoolEntryLock<T> {
// Ensure the pending entry is removed once the creation finishes, and
// swallow errors on the cleanup chain so they don't become unhandled.
final guarded = future.whenComplete(() => _pending.remove(key));
guarded.then((_) {}, onError: (_) {});
unawaited(guarded.then((_) {}, onError: (_) {}));
result = future;
}
} finally {
Expand Down
2 changes: 1 addition & 1 deletion lib/core/database/mongodb_connection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ class MongoConnection {
_openedDbs[databaseName] = db;
return db;
} finally {
_openingDbs.remove(databaseName);
unawaited(_openingDbs.remove(databaseName));
}
});
}
Expand Down
13 changes: 10 additions & 3 deletions lib/core/mcp/mcp_socket_host.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,18 +116,25 @@ class McpSocketHost {
unawaited(onSession(StreamChannel.withCloseGuarantee(
incoming.stream, outgoing.sink)));
},
onDone: () => _closed(socket, incoming, authed),
onError: (_) => _closed(socket, incoming, authed),
onDone: () => _closed(socket, incoming, outgoing, authed),
onError: (_) => _closed(socket, incoming, outgoing, authed),
cancelOnError: true,
);
}

void _closed(Socket socket, StreamController<String> incoming, bool authed) {
void _closed(
Socket socket,
StreamController<String> incoming,
StreamController<String> outgoing,
bool authed,
) {
if (_sockets.remove(socket) && authed) {
_sessions--;
_changes.add(null);
}
unawaited(incoming.close());
// The channel guarantees no write after the incoming side closed.
unawaited(outgoing.close());
socket.destroy();
}

Expand Down
18 changes: 9 additions & 9 deletions lib/core/security/ssh_tunnel_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,10 @@ class _PooledTunnelSession {
await serverSocket.close();
} catch (_) {}
try {
client.close();
unawaited(client.close());
} catch (_) {}
try {
jumpClient?.close();
unawaited(jumpClient?.close());
} catch (_) {}
}
}
Expand Down Expand Up @@ -274,8 +274,8 @@ class SshTunnelManager {
try {
await client.authenticated;
} catch (e) {
client.close();
jumpClient?.close();
unawaited(client.close());
unawaited(jumpClient?.close());
if (observedFingerprint != null &&
config.knownHostFingerprint != null &&
config.knownHostFingerprint!.isNotEmpty) {
Expand Down Expand Up @@ -303,8 +303,8 @@ class SshTunnelManager {
(clientSocket) async {
try {
final forward = await client.forwardLocal(remoteHost, remotePort);
forward.stream.cast<List<int>>().pipe(clientSocket).catchError((_) {});
clientSocket.cast<List<int>>().pipe(forward.sink).catchError((_) {});
unawaited(forward.stream.cast<List<int>>().pipe(clientSocket).catchError((_) {}));
unawaited(clientSocket.cast<List<int>>().pipe(forward.sink).catchError((_) {}));
} catch (e) {
clientSocket.destroy();
}
Expand Down Expand Up @@ -461,7 +461,7 @@ class SshTunnelManager {
testRemoteHost.trim(),
testRemotePort,
);
forward.close();
unawaited(forward.close());
} catch (e) {
return SshTestResult(
ok: false,
Expand All @@ -483,8 +483,8 @@ class SshTunnelManager {
error: 'SSH Connection failed: $e',
);
} finally {
client?.close();
jumpClient?.close();
unawaited(client?.close());
unawaited(jumpClient?.close());
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import 'core/theme/theme_controller.dart';
import 'features/updater/update_controller.dart';

void main([List<String> args = const []]) async {
runZonedGuarded(() async {
unawaited(runZonedGuarded(() async {
WidgetsFlutterBinding.ensureInitialized();
FileLaunchService.instance.processLaunchArguments(args);

Expand Down Expand Up @@ -46,5 +46,5 @@ void main([List<String> args = const []]) async {
});
}, (error, stack) {
debugPrint('Unhandled async error: $error\n$stack');
});
}));
}
4 changes: 4 additions & 0 deletions test/core/extensions/harness/extension_harness_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ class _FakePlugin implements HarnessPluginProcess {
final calls = <String>[];
final _stdout = StreamController<List<int>>();
final _stderr = StreamController<List<int>>();
// The fake owns this stream for the whole test.
// ignore: close_sinks
final _stdinController = StreamController<List<int>>();
final _exit = Completer<int>();
// The fake owns this stream for the whole test.
// ignore: close_sinks
late final IOSink _stdin = IOSink(_stdinController);

void _reply(Map<String, Object?> body) {
Expand Down
2 changes: 1 addition & 1 deletion test/core/extensions/rpc/json_rpc_stdio_client_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ void main() {
var peakAhead = 0;
var handled = 0;
for (final r in replies) {
r.then((_) => handled++);
unawaited(r.then((_) => handled++));
}
final watcher = Timer.periodic(const Duration(milliseconds: 1), (_) {
peakAhead = math.max(peakAhead, produced - handled);
Expand Down
2 changes: 2 additions & 0 deletions test/core/extensions/rpc/plugin_rpc_bridge_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class _FakeProcess implements Process {
int get pid => 99;

@override
// The fake owns this stream for the whole test.
// ignore: close_sinks
late final IOSink stdin;

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class _FakeProcess implements Process {
int get pid => 4242;

@override
// The fake owns this stream for the whole test.
// ignore: close_sinks
late final IOSink stdin;

@override
Expand Down Expand Up @@ -131,6 +133,8 @@ void main() {
group('JsonRpcStdioClient', () {
test('sends request and completes with result', () async {
final stdout = StreamController<List<int>>();
// The fake owns this stream for the whole test.
// ignore: close_sinks
final stdin = StreamController<List<int>>();
final client = JsonRpcStdioClient(
stdout: stdout.stream,
Expand Down Expand Up @@ -158,6 +162,8 @@ void main() {

test('maps JSON-RPC errors', () async {
final stdout = StreamController<List<int>>();
// The fake owns this stream for the whole test.
// ignore: close_sinks
final stdin = StreamController<List<int>>();
final client = JsonRpcStdioClient(
stdout: stdout.stream,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class _FakeProcess implements Process {
int get pid => 7;

@override
// The fake owns this stream for the whole test.
// ignore: close_sinks
late final IOSink stdin;

@override
Expand Down
2 changes: 2 additions & 0 deletions test/core/extensions/sandbox/sandbox_watchdog_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class _FakeProcess implements Process {
int get pid => 4242;

@override
// The fake owns this stream for the whole test.
// ignore: close_sinks
late final IOSink stdin;

@override
Expand Down
4 changes: 4 additions & 0 deletions test/core/mcp/mcp_server_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ class _Session {
final StreamController<List<int>> _toShim;

static Future<_Session> open(File endpoint) async {
// The fake owns this stream for the whole test.
// ignore: close_sinks
final toShim = StreamController<List<int>>();
// The fake owns this stream for the whole test.
// ignore: close_sinks
final fromShim = StreamController<List<int>>();
final shimDone = runMcpShim(
input: toShim.stream,
Expand Down
5 changes: 3 additions & 2 deletions test/core/security/ssh_tunnel_manager_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
Expand Down Expand Up @@ -566,7 +567,7 @@ void main() {

test('a dropped SSH connection is replaced, not reused', () async {
final first = await open();
server.clients.single.close();
unawaited(server.clients.single.close());

final second = await open();

Expand All @@ -582,7 +583,7 @@ void main() {
test('a handle from a replaced session cannot release its successor',
() async {
final stale = await open();
server.clients.single.close();
unawaited(server.clients.single.close());
final fresh = await open();

await stale.release();
Expand Down
6 changes: 4 additions & 2 deletions test/features/workspace/save_error_description_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:flutter/material.dart' as material;
import 'package:flutter_test/flutter_test.dart';
import 'package:querya_desktop/features/workspace/save_error_description.dart';
Expand Down Expand Up @@ -111,10 +113,10 @@ void main() {
),
));

showTableViewSaveFailedDialog(
unawaited(showTableViewSaveFailedDialog(
context: ctx,
error: Exception('NOT NULL constraint failed: users.full_name'),
);
));
await tester.pumpAndSettle();

expect(find.text('Missing required value'), findsOneWidget);
Expand Down
10 changes: 6 additions & 4 deletions test/features/workspace/table_view_staging_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:flutter/material.dart' as material;
import 'package:flutter_test/flutter_test.dart';
import 'package:querya_desktop/core/database/table_mutation_engine.dart';
Expand Down Expand Up @@ -502,11 +504,11 @@ void main() {

bool? result;
// Trigger confirmation asynchronously
confirmDiscardTableEditsIfDirty(
unawaited(confirmDiscardTableEditsIfDirty(
context: ctx,
buffer: buffer,
tableTitle: 'public.users',
).then((val) => result = val);
).then((val) => result = val));

await tester.pumpAndSettle();
expect(find.text('Unsaved changes in "public.users"'), findsOneWidget);
Expand Down Expand Up @@ -544,11 +546,11 @@ void main() {
expect(buffer.isDirty, isTrue);

bool? result;
confirmDiscardTableEditsIfDirty(
unawaited(confirmDiscardTableEditsIfDirty(
context: ctx,
buffer: buffer,
tableTitle: 'Query 1',
).then((val) => result = val);
).then((val) => result = val));

await tester.pumpAndSettle();
expect(find.text('Unsaved changes in "Query 1"'), findsOneWidget);
Expand Down
17 changes: 9 additions & 8 deletions test/shared/app_dialog_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:ui' show ImageFilter;

import 'package:flutter/material.dart';
Expand Down Expand Up @@ -116,10 +117,10 @@ void main() {
(tester) async {
final ctx = await pumpHost(tester);

showAppDialog<void>(
unawaited(showAppDialog<void>(
context: ctx,
builder: (c) => const SimpleDialog(title: Text('X')),
);
));
await tester.pump();
await tester.pump(const Duration(milliseconds: 40));
expect(find.byType(BackdropFilter), findsWidgets);
Expand All @@ -146,10 +147,10 @@ void main() {
(tester) async {
final ctx = await pumpHost(tester);

showAppDialog<void>(
unawaited(showAppDialog<void>(
context: ctx,
builder: (c) => const SimpleDialog(title: Text('Blur')),
);
));
await tester.pump();
await tester.pump(const Duration(milliseconds: 40));

Expand All @@ -171,10 +172,10 @@ void main() {
testWidgets('settles at full blur and tint', (tester) async {
final ctx = await pumpHost(tester);

showAppDialog<void>(
unawaited(showAppDialog<void>(
context: ctx,
builder: (c) => const SimpleDialog(title: Text('Settled')),
);
));
await tester.pumpAndSettle();

final filter = tester.widget<BackdropFilter>(find.byType(BackdropFilter));
Expand Down Expand Up @@ -214,10 +215,10 @@ void main() {

testWidgets('enter uses standard duration under full motion', (tester) async {
final ctx = await pumpHost(tester);
showAppDialog<void>(
unawaited(showAppDialog<void>(
context: ctx,
builder: (c) => const AlertDialog(title: Text('Timed')),
);
));
await tester.pump();

final route = ModalRoute.of(tester.element(find.text('Timed')));
Expand Down
4 changes: 4 additions & 0 deletions test/support/fake_ssh.dart
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ class FakeSshServer {

/// A transport that carries nothing; the fake client never reads it.
class FakeSshSocket implements SSHSocket {
// The fake owns this stream for the whole test.
// ignore: close_sinks
final _in = StreamController<Uint8List>();
// The fake owns this stream for the whole test.
// ignore: close_sinks
final _out = StreamController<List<int>>();

@override
Expand Down
Loading