diff --git a/docs/analysis_options.yaml b/docs/analysis_options.yaml index 4c1b5e9f..990f7b54 100644 --- a/docs/analysis_options.yaml +++ b/docs/analysis_options.yaml @@ -1,7 +1,7 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true exclude: - "**/*.g.dart" diff --git a/docs/pages/docs/Using SQL/sql_ide.md b/docs/pages/docs/Using SQL/sql_ide.md index 31e47b5d..874a7c8c 100644 --- a/docs/pages/docs/Using SQL/sql_ide.md +++ b/docs/pages/docs/Using SQL/sql_ide.md @@ -3,6 +3,7 @@ data: title: "Experimental IDE" weight: 5 description: Get real-time feedback as you type sql + hidden: true template: layouts/docs/single --- diff --git a/docs/pubspec.yaml b/docs/pubspec.yaml index 3f93fd1c..21fee5fb 100644 --- a/docs/pubspec.yaml +++ b/docs/pubspec.yaml @@ -3,12 +3,12 @@ description: Documentation website for the drift project. publish_to: none environment: - sdk: '>=2.15.0 <3.0.0' + sdk: '>=2.19.0 <4.0.0' dependencies: drift: path: ^1.8.2 - json_annotation: ^4.7.0 + json_annotation: ^4.8.1 docsy: hosted: https://simonbinder.eu version: ^0.2.2 @@ -31,11 +31,11 @@ dev_dependencies: build: ^2.1.0 build_runner: ^2.0.5 build_runner_core: ^7.2.7 - build_web_compilers: ^3.2.0 + build_web_compilers: ^4.0.0 built_site: hosted: https://simonbinder.eu - version: ^0.2.10 - linkcheck: ^2.0.19 + version: ^0.2.15 + linkcheck: ^3.0.0 json_serializable: ^6.1.6 shelf: ^1.2.0 shelf_static: ^1.1.0 @@ -50,3 +50,10 @@ dependency_overrides: git: url: https://github.com/simolus3/mime.git ref: woff2 + # The bootstrap_sass on pub.dev doesn't support null safety, so I'm hosting + # https://github.com/dart-league/bootstrap_sass/pull/13. + # Hopefully this can change soon once docsy migrates to bootstrap 5 + bootstrap_sass: + hosted: + url: https://simonbinder.eu + version: "4.6.0" diff --git a/docs/tool/ci_check.dart b/docs/tool/ci_check.dart deleted file mode 100644 index 80d2d222..00000000 --- a/docs/tool/ci_check.dart +++ /dev/null @@ -1,62 +0,0 @@ -// Waiting for linkcheck to migrate... -// @dart=2.9 -import 'dart:async'; -import 'dart:io'; - -import 'package:linkcheck/linkcheck.dart' as check; -import 'package:linkcheck/src/parsers/url_skipper.dart'; -import 'package:shelf/shelf_io.dart' as io; -import 'package:shelf_static/shelf_static.dart'; - -/// Checks that the content in `deploy/` only contains valid links. -Future main() async { - final done = Completer(); - - await _startServer(done.future); - check.CrawlResult results; - try { - results = await check.crawl( - [ - Uri.parse('http://localhost:8080/'), - Uri.parse('http://localhost:8080/api/') - ], - {'http://localhost:8080/**'}, - // todo: Re-enable. Current problem is that we link new pages to their - // final url (under drift.simonbinder.eu) before they're deployed. - false, - UrlSkipper( - '', ['github.com', 'pub.dev', 'api.dart.dev', 'fonts.gstatic.com']), - false, - false, - const Stream.empty(), - stdout, - ); - } finally { - done.complete(); - } - - var hasBrokenLinks = false; - - for (final result in results.destinations) { - // todo: Remove !result.isExternal after external links work again - if (result.isBroken && !result.isExternal) { - print('Broken: $result (${result.toMap()})'); - hasBrokenLinks = true; - } - } - - if (!hasBrokenLinks) { - print('No broken links found!'); - } else { - exit(1); - } -} - -Future _startServer(Future completeSignal) async { - final handler = createStaticHandler('deploy/', defaultDocument: 'index.html'); - final server = await io.serve(handler, 'localhost', 8080); - - print('Started server - listening on :8080'); - - completeSignal.then((_) => server.close()).ignore(); -} diff --git a/drift/analysis_options.yaml b/drift/analysis_options.yaml index 964a03af..c2c8d7fb 100644 --- a/drift/analysis_options.yaml +++ b/drift/analysis_options.yaml @@ -1,8 +1,9 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true + strict-inference: true exclude: - "**/*.g.dart" diff --git a/drift/lib/src/isolate.dart b/drift/lib/src/isolate.dart index 1eed0a9d..ff669526 100644 --- a/drift/lib/src/isolate.dart +++ b/drift/lib/src/isolate.dart @@ -18,7 +18,7 @@ StreamChannel connectToServer(SendPort serverConnectPort, bool serialize) { serverConnectPort.send([receive.sendPort, serialize]); final controller = - StreamChannelController(allowForeignErrors: false, sync: true); + StreamChannelController(allowForeignErrors: false, sync: true); receive.listen((message) { if (message is SendPort) { controller.local.stream.listen(message.send, onDone: () { @@ -72,8 +72,8 @@ class RunningDriftServer { ReceivePort('drift channel #${_counter++}'); sendPort.send(receiveForConnection.sendPort); - final controller = - StreamChannelController(allowForeignErrors: false, sync: true); + final controller = StreamChannelController( + allowForeignErrors: false, sync: true); receiveForConnection.listen((message) { if (message == disconnectMessage) { // Client closed the connection diff --git a/drift/lib/src/remote/client_impl.dart b/drift/lib/src/remote/client_impl.dart index 2078b242..93eeaefe 100644 --- a/drift/lib/src/remote/client_impl.dart +++ b/drift/lib/src/remote/client_impl.dart @@ -165,7 +165,7 @@ class _RemoteQueryExecutor extends _BaseExecutor { if (!channel.isClosed) { if (client._singleClientMode) { return channel - .request(NoArgsRequest.terminateAll) + .request(NoArgsRequest.terminateAll) .onError((error, stackTrace) => null) .whenComplete(channel.close); } else { diff --git a/drift/lib/src/remote/server_impl.dart b/drift/lib/src/remote/server_impl.dart index 6a18cedd..f04a5b96 100644 --- a/drift/lib/src/remote/server_impl.dart +++ b/drift/lib/src/remote/server_impl.dart @@ -143,7 +143,7 @@ class ServerImplementation implements DriftServer { final executor = await _loadExecutor(transactionId); // Give cancellations more time to come in - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); checkIfCancelled(); switch (method) { @@ -277,7 +277,7 @@ class _ServerDbUser implements QueryExecutorUser { QueryExecutor executor, OpeningDetails details) async { final id = _server._putExecutor(executor, beforeCurrent: true); try { - await connection.request(RunBeforeOpen(details, id)); + await connection.request(RunBeforeOpen(details, id)); } finally { _server._releaseExecutor(id); } diff --git a/drift/lib/src/runtime/executor/delayed_stream_queries.dart b/drift/lib/src/runtime/executor/delayed_stream_queries.dart index b3d6fac6..12743019 100644 --- a/drift/lib/src/runtime/executor/delayed_stream_queries.dart +++ b/drift/lib/src/runtime/executor/delayed_stream_queries.dart @@ -27,7 +27,7 @@ class DelayedStreamQueryStore implements StreamQueryStore { } @override - void markAsClosed(QueryStream stream, Function() whenRemoved) { + void markAsClosed(QueryStream stream, void Function() whenRemoved) { throw UnimplementedError('The stream will call this on the delegate'); } diff --git a/drift/lib/src/runtime/executor/executor.dart b/drift/lib/src/runtime/executor/executor.dart index 474fac11..7152ea73 100644 --- a/drift/lib/src/runtime/executor/executor.dart +++ b/drift/lib/src/runtime/executor/executor.dart @@ -76,7 +76,7 @@ abstract class QueryExecutorUser { Future beforeOpen(QueryExecutor executor, OpeningDetails details); } -const _equality = ListEquality(); +const _equality = ListEquality(); /// Stores information needed to run batched statements in the order they were /// issued without preparing statements multiple times. diff --git a/drift/lib/src/runtime/executor/stream_queries.dart b/drift/lib/src/runtime/executor/stream_queries.dart index 32210d31..941639e3 100644 --- a/drift/lib/src/runtime/executor/stream_queries.dart +++ b/drift/lib/src/runtime/executor/stream_queries.dart @@ -119,7 +119,7 @@ class StreamQueryStore { _tableUpdates.add(updates); } - void markAsClosed(QueryStream stream, Function() whenRemoved) { + void markAsClosed(QueryStream stream, void Function() whenRemoved) { if (_isShuttingDown) return; final key = stream._fetcher.key; diff --git a/drift/lib/src/runtime/executor/transactions.dart b/drift/lib/src/runtime/executor/transactions.dart index 0d876c2e..83e1c9b2 100644 --- a/drift/lib/src/runtime/executor/transactions.dart +++ b/drift/lib/src/runtime/executor/transactions.dart @@ -68,7 +68,7 @@ class _TransactionStreamStore extends StreamQueryStore { } @override - void markAsClosed(QueryStream stream, Function() whenRemoved) { + void markAsClosed(QueryStream stream, void Function() whenRemoved) { super.markAsClosed(stream, whenRemoved); _queriesWithoutKey.add(stream); diff --git a/drift/lib/src/runtime/query_builder/expressions/aggregate.dart b/drift/lib/src/runtime/query_builder/expressions/aggregate.dart index 61a7fb0f..2921b3c5 100644 --- a/drift/lib/src/runtime/query_builder/expressions/aggregate.dart +++ b/drift/lib/src/runtime/query_builder/expressions/aggregate.dart @@ -218,8 +218,8 @@ class _AggregateExpression extends Expression { @override int get hashCode { - return Object.hash( - functionName, distinct, const ListEquality().hash(parameter), filter); + return Object.hash(functionName, distinct, + const ListEquality().hash(parameter), filter); } @override @@ -232,7 +232,7 @@ class _AggregateExpression extends Expression { final typedOther = other as _AggregateExpression; return typedOther.functionName == functionName && typedOther.distinct == distinct && - const ListEquality().equals(typedOther.parameter, parameter) && + const ListEquality().equals(typedOther.parameter, parameter) && typedOther.filter == filter; } } diff --git a/drift/lib/src/runtime/query_builder/expressions/exists.dart b/drift/lib/src/runtime/query_builder/expressions/exists.dart index 2b48dbe1..7172073f 100644 --- a/drift/lib/src/runtime/query_builder/expressions/exists.dart +++ b/drift/lib/src/runtime/query_builder/expressions/exists.dart @@ -11,7 +11,7 @@ Expression notExistsQuery(BaseSelectStatement select) { return _ExistsExpression(select, true); } -class _ExistsExpression extends Expression { +class _ExistsExpression extends Expression { final BaseSelectStatement _select; final bool _not; diff --git a/drift/lib/src/runtime/query_builder/expressions/expression.dart b/drift/lib/src/runtime/query_builder/expressions/expression.dart index b4f78763..fb3680af 100644 --- a/drift/lib/src/runtime/query_builder/expressions/expression.dart +++ b/drift/lib/src/runtime/query_builder/expressions/expression.dart @@ -1,6 +1,6 @@ part of '../query_builder.dart'; -const _equality = ListEquality(); +const _equality = ListEquality(); /// Base class for everything that can be used as a function parameter in sql. /// diff --git a/drift/lib/src/runtime/query_builder/schema/column_impl.dart b/drift/lib/src/runtime/query_builder/schema/column_impl.dart index 75520c20..8847a25d 100644 --- a/drift/lib/src/runtime/query_builder/schema/column_impl.dart +++ b/drift/lib/src/runtime/query_builder/schema/column_impl.dart @@ -251,7 +251,8 @@ class GeneratedColumn extends Column { /// the constraint does not depend on the dialect. /// /// Used by generated code. - static Function(GenerationContext) constraintIsAlways(String constraint) => + static void Function(GenerationContext) constraintIsAlways( + String constraint) => (context) => context.buffer ..write(' ') ..write(constraint); @@ -260,7 +261,7 @@ class GeneratedColumn extends Column { /// the constraint depends on the dialect. /// /// Used by generated code. - static Function(GenerationContext) constraintsDependsOnDialect( + static void Function(GenerationContext) constraintsDependsOnDialect( Map constraints, ) => (context) { diff --git a/drift/lib/src/web/channel.dart b/drift/lib/src/web/channel.dart index feac1213..d1cd21ac 100644 --- a/drift/lib/src/web/channel.dart +++ b/drift/lib/src/web/channel.dart @@ -11,7 +11,7 @@ extension PortToChannel on MessagePort { /// This can be used to implement a remote database connection over service /// workers. StreamChannel channel() { - final controller = StreamChannelController(); + final controller = StreamChannelController(); onMessage.map((event) => event.data).pipe(controller.local.sink); controller.local.stream.listen(postMessage, onDone: close); diff --git a/drift/test/database/batch_test.dart b/drift/test/database/batch_test.dart index 7b46456d..dcf1d51c 100644 --- a/drift/test/database/batch_test.dart +++ b/drift/test/database/batch_test.dart @@ -186,7 +186,7 @@ void main() { batch.insert( db.categories, CategoriesCompanion.insert(description: 'first')); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); batch.insert( db.categories, CategoriesCompanion.insert(description: 'second')); diff --git a/drift/test/database/data_class_test.dart b/drift/test/database/data_class_test.dart index dac8738b..e3784421 100644 --- a/drift/test/database/data_class_test.dart +++ b/drift/test/database/data_class_test.dart @@ -158,7 +158,7 @@ void main() { }); test("don't equal when one value is absent and the other one is null", () { - const first = Value.absent(); + const first = Value.absent(); const different = Value(null); expect(first.hashCode, isNot(equals(different.hashCode))); diff --git a/drift/test/database/statements/join_test.dart b/drift/test/database/statements/join_test.dart index 4824360a..aa270977 100644 --- a/drift/test/database/statements/join_test.dart +++ b/drift/test/database/statements/join_test.dart @@ -167,11 +167,11 @@ void main() { .join([innerJoin(categories, todos.category.equalsExp(categories.id))]); final queue = StreamQueue(query.watch()); - expect(await queue.next, []); + expect(await queue.next, isEmpty); db.markTablesUpdated({todos}); db.markTablesUpdated({categories}); - expect(await queue.next, []); + expect(await queue.next, isEmpty); }); test('updates when any queried table changes in transaction', () { @@ -188,7 +188,7 @@ void main() { ..groupBy([b.description]); final stream = query.watch(); - expectLater(stream, emitsInOrder([[], []])); + expectLater(stream, emitsInOrder([[], []])); return db.transaction(() async { db.markTablesUpdated({b}); diff --git a/drift/test/database/streams_test.dart b/drift/test/database/streams_test.dart index 92d8eed3..91efdd7a 100644 --- a/drift/test/database/streams_test.dart +++ b/drift/test/database/streams_test.dart @@ -82,7 +82,7 @@ void main() { test('does not emit cached data when resuming and data did not change', () async { final stream = db.select(db.users).watch(); - final completer = Completer(); + final completer = Completer(); final subscription = stream.listen(expectAsync1((data) { completer.complete(); @@ -102,7 +102,7 @@ void main() { test('emits new data if it changed during a paused subscription', () async { final stream = db.select(db.users).watch(); - final completer = Completer(); + final completer = Completer(); final subscription = stream.listen(expectAsync1((data) { if (!completer.isCompleted) completer.complete(); @@ -177,7 +177,8 @@ void main() { await first.first; // will listen to stream, then cancel await pumpEventQueue(times: 1); // give cancel event time to propagate - final checkEmits = expectLater(second, emitsInOrder([[], []])); + final checkEmits = + expectLater(second, emitsInOrder([[], []])); db.markTablesUpdated({db.users}); await pumpEventQueue(times: 1); @@ -271,7 +272,7 @@ void main() { clearInteractions(executor); // The stream is kept open for the rest of this event iteration - final completer = Completer.sync(); + final completer = Completer.sync(); Timer.run(completer.complete); await completer.future; @@ -282,7 +283,7 @@ void main() { test('when all listeners are paused', () async { when(executor.runSelect(any, any)).thenAnswer((i) => Future.value([])); - final isPaused = Completer(); + final isPaused = Completer(); final subscription = db.select(db.categories).watch().listen(null); subscription.onData((rows) { @@ -307,7 +308,7 @@ void main() { ])); db.markTablesUpdated([db.categories]); await pumpEventQueue(); - final hadData = Completer(); + final hadData = Completer(); subscription.onData((rows) { expect(rows, hasLength(1)); diff --git a/drift/test/database/transactions_test.dart b/drift/test/database/transactions_test.dart index 817ad035..0b670b15 100644 --- a/drift/test/database/transactions_test.dart +++ b/drift/test/database/transactions_test.dart @@ -231,7 +231,7 @@ void main() { .thenAnswer((_) => Future.error(rollbackException)); return expectLater( - db.transaction(() => Future.error(cause)), + db.transaction(() => Future.error(cause)), throwsA(isA() .having((e) => e.cause, 'cause', cause) .having((e) => e.exception, 'exception', rollbackException)), diff --git a/drift/test/engines/delegated_database_test.dart b/drift/test/engines/delegated_database_test.dart index f0c053d4..9fd0de96 100644 --- a/drift/test/engines/delegated_database_test.dart +++ b/drift/test/engines/delegated_database_test.dart @@ -191,7 +191,8 @@ void main() { test('when the database supports transactions', () async { final transactionDelegate = MockSupportedTransactionDelegate(); when(transactionDelegate.startTransaction(any)).thenAnswer((i) { - (i.positionalArguments.single as Function(QueryDelegate))(delegate); + (i.positionalArguments.single as void Function( + QueryDelegate))(delegate); }); when(transactionDelegate.managesLockInternally).thenReturn(true); @@ -232,7 +233,7 @@ void main() { final exception = Exception('expected'); when(transactionDelegate.startTransaction(any)).thenAnswer((i) async { - await (i.positionalArguments.single as Function( + await (i.positionalArguments.single as Future Function( QueryDelegate))(delegate); throw exception; }); diff --git a/drift/test/integration_tests/migrations_integration_test.dart b/drift/test/integration_tests/migrations_integration_test.dart index 6ec2fd97..6d74f84e 100644 --- a/drift/test/integration_tests/migrations_integration_test.dart +++ b/drift/test/integration_tests/migrations_integration_test.dart @@ -365,7 +365,7 @@ void main() { await db.customStatement('pragma user_version = 3'); await db.transaction( - () => Future.error('Error after partial migration')); + () => Future.error('Error after partial migration')); }), ), ); diff --git a/drift/test/integration_tests/regress_1232_test.dart b/drift/test/integration_tests/regress_1232_test.dart index 13bc1144..1d699770 100644 --- a/drift/test/integration_tests/regress_1232_test.dart +++ b/drift/test/integration_tests/regress_1232_test.dart @@ -19,7 +19,7 @@ void main() { .watchSingle(); expect(await watchValue().first, 1); - await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); watchValue().listen(null); diff --git a/drift/test/isolate_test.dart b/drift/test/isolate_test.dart index 5622c167..2e08b44a 100644 --- a/drift/test/isolate_test.dart +++ b/drift/test/isolate_test.dart @@ -357,7 +357,7 @@ void _runTests(FutureOr Function() spawner, bool terminateIsolate, rowInserted.complete(); // Hold transaction open for expectRowCount() outside the transaction to // finish - await Future.delayed(const Duration(seconds: 1)); + await Future.delayed(const Duration(seconds: 1)); await database.customStatement('delete from tbl'); await expectRowCount(database, 0); }); diff --git a/drift/test/remote_test.dart b/drift/test/remote_test.dart index b65f5be4..fba747e5 100644 --- a/drift/test/remote_test.dart +++ b/drift/test/remote_test.dart @@ -17,7 +17,7 @@ void main() { preferLocalSqlite3(); test('closes channel in shutdown', () async { - final controller = StreamChannelController(); + final controller = StreamChannelController(); final server = DriftServer(testInMemoryDatabase(), allowRemoteShutdown: true); server.serve(controller.foreign); @@ -26,7 +26,7 @@ void main() { }); test('can shutdown server on close', () async { - final controller = StreamChannelController(); + final controller = StreamChannelController(); final server = DriftServer(testInMemoryDatabase(), allowRemoteShutdown: true); server.serve(controller.foreign); @@ -47,7 +47,7 @@ void main() { () async { final server = DriftServer(testInMemoryDatabase(), allowRemoteShutdown: true); - final controller = StreamChannelController(); + final controller = StreamChannelController(); server.serve(controller.foreign, serialize: false); final client = await connectToRemoteAndInitialize( @@ -116,7 +116,7 @@ void main() { final server = DriftServer(DatabaseConnection(executor)); addTearDown(server.shutdown); - final channelController = StreamChannelController(); + final channelController = StreamChannelController(); server.serve(channelController.foreign.changeStream(_checkStreamOfSimple), serialize: true); @@ -153,7 +153,7 @@ void main() { }); test('nested transactions', () async { - final controller = StreamChannelController(); + final controller = StreamChannelController(); final executor = MockExecutor(); final outerTransaction = executor.transactions; // avoid this object being created implicitly in the beginTransaction() when @@ -207,7 +207,7 @@ void main() { final executor = MockExecutor(); when(executor.dialect).thenReturn(SqlDialect.postgres); - final controller = StreamChannelController(); + final controller = StreamChannelController(); final server = DriftServer(DatabaseConnection(executor)) ..serve(controller.foreign); diff --git a/drift/test/test_utils/matchers.dart b/drift/test/test_utils/matchers.dart index 476d3baa..3226e821 100644 --- a/drift/test/test_utils/matchers.dart +++ b/drift/test/test_utils/matchers.dart @@ -83,14 +83,14 @@ class _GeneratesSqlMatcher extends Matcher { var matches = true; - final sqlMatchState = {}; + final sqlMatchState = {}; if (!_matchSql.matches(ctx.sql, sqlMatchState)) { matchState['sql'] = ctx.sql; matchState['sql_match'] = sqlMatchState; matches = false; } - final argsMatchState = {}; + final argsMatchState = {}; if (_matchVariables != null && !_matchVariables!.matches(ctx.boundVariables, argsMatchState)) { matchState['vars'] = ctx.boundVariables; diff --git a/drift/test/utils/single_transformer_test.dart b/drift/test/utils/single_transformer_test.dart index 0dfbb399..42acda74 100644 --- a/drift/test/utils/single_transformer_test.dart +++ b/drift/test/utils/single_transformer_test.dart @@ -42,7 +42,7 @@ void main() { }); test('singleElementsOrNull() emits null for empty data', () { - final stream = Stream.value([]); + final stream = Stream.value([]); expect(stream.transform(singleElementsOrNull()), emits(isNull)); }); diff --git a/drift_dev/analysis_options.yaml b/drift_dev/analysis_options.yaml index 4c1b5e9f..990f7b54 100644 --- a/drift_dev/analysis_options.yaml +++ b/drift_dev/analysis_options.yaml @@ -1,7 +1,7 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true exclude: - "**/*.g.dart" diff --git a/drift_dev/lib/src/analysis/serializer.dart b/drift_dev/lib/src/analysis/serializer.dart index 33e1ffd8..b37ad797 100644 --- a/drift_dev/lib/src/analysis/serializer.dart +++ b/drift_dev/lib/src/analysis/serializer.dart @@ -438,7 +438,7 @@ class ElementDeserializer { final id = DriftElementId.fromJson(json['id'] as Map); final declaration = DriftDeclaration.fromJson(json['declaration'] as Map); final references = [ - for (final reference in json['references']) + for (final reference in json.list('references')) await _readElementReference(reference as Map), ]; @@ -489,7 +489,7 @@ class ElementDeserializer { id.libraryUri, json['existing_data_class'] as Map) : null, tableConstraints: [ - for (final constraint in json['table_constraints']) + for (final constraint in json.list('table_constraints')) await _readTableConstraint(constraint as Map, columnByName), ], customParentClass: json['custom_parent_class'] != null @@ -575,7 +575,7 @@ class ElementDeserializer { on: on, onWrite: UpdateKind.values.byName(json['onWrite'] as String), writes: [ - for (final write in json['writes']) + for (final write in json.list('writes').cast()) WrittenDriftTable( await _readElementReference(write['table'] as Map) as DriftTable, @@ -609,7 +609,7 @@ class ElementDeserializer { ? readReference(serializedSource['primaryFrom'] as Map) : null, [ - for (final element in serializedSource['staticReferences']) + for (final element in serializedSource.list('staticReferences')) readReference(element as Map) ], ); @@ -640,11 +640,11 @@ class ElementDeserializer { }; final tables = [ - for (final tableId in json['tables']) + for (final tableId in json.list('tables')) referenceById[DriftElementId.fromJson(tableId as Map)] as DriftTable ]; final views = [ - for (final tableId in json['views']) + for (final tableId in json.list('views')) referenceById[DriftElementId.fromJson(tableId as Map)] as DriftView ]; final includes = @@ -664,7 +664,7 @@ class ElementDeserializer { declaredQueries: queries, schemaVersion: json['schema_version'] as int?, accessors: [ - for (final dao in json['daos']) + for (final dao in json.list('daos')) await readDriftElement(DriftElementId.fromJson(dao as Map)) as DatabaseAccessor, ], @@ -803,21 +803,21 @@ class ElementDeserializer { switch (type) { case 'unique': return UniqueColumns({ - for (final ref in json['columns']) localColumns[ref]!, + for (final ref in json.list('columns')) localColumns[ref]!, }); case 'primary_key': return PrimaryKeyColumns( - {for (final ref in json['columns']) localColumns[ref]!}, + {for (final ref in json.list('columns')) localColumns[ref]!}, ); case 'foreign': return ForeignKeyTable( localColumns: [ - for (final ref in json['local']) localColumns[ref]!, + for (final ref in json.list('local')) localColumns[ref]!, ], otherTable: await _readElementReference(json['table'] as Map) as DriftTable, otherColumns: [ - for (final ref in json['foreign']) + for (final ref in json.list('foreign')) await _readDriftColumnReference(ref as Map) ], onUpdate: _readAction(json['onUpdate'] as String?), @@ -829,6 +829,10 @@ class ElementDeserializer { } } +extension on Map { + Iterable list(String key) => this[key] as Iterable; +} + class CouldNotDeserializeException implements Exception { final String message; diff --git a/drift_dev/lib/src/services/schema/schema_files.dart b/drift_dev/lib/src/services/schema/schema_files.dart index 5efb966b..03c17dfb 100644 --- a/drift_dev/lib/src/services/schema/schema_files.dart +++ b/drift_dev/lib/src/services/schema/schema_files.dart @@ -346,9 +346,9 @@ class SchemaReader { List> uniqueKeys = []; if (content.containsKey('unique_keys')) { - for (final key in content['unique_keys']) { + for (final key in content['unique_keys'] as Iterable) { uniqueKeys.add({ - for (final columnName in key) + for (final columnName in key as Iterable) columns.singleWhere((c) => c.nameInSql == columnName) }); } @@ -380,7 +380,7 @@ class SchemaReader { _id(name), _declaration, columns: [ - for (final column in content['columns']) + for (final column in content['columns'] as Iterable) _readColumn(column as Map) ], source: SqlViewSource(content['sql'] as String), diff --git a/drift_dev/tool/debug_plugin.dart b/drift_dev/tool/debug_plugin.dart index e328e10a..c892c0c1 100644 --- a/drift_dev/tool/debug_plugin.dart +++ b/drift_dev/tool/debug_plugin.dart @@ -1,4 +1,3 @@ -// @dart=2.9 import 'dart:async'; import 'dart:convert'; import 'dart:io'; @@ -7,6 +6,7 @@ import 'package:analyzer_plugin/channel/channel.dart'; import 'package:analyzer_plugin/protocol/protocol.dart'; import 'package:args/args.dart'; import 'package:drift_dev/src/backends/plugin/plugin.dart'; +import 'package:stream_transform/stream_transform.dart'; void main(List args) { final parser = ArgParser() @@ -32,10 +32,10 @@ class _WebSocketPluginServer implements PluginCommunicationChannel { final dynamic address; final int port; - HttpServer server; + late HttpServer server; - WebSocket _currentClient; - final StreamController _clientStream = + WebSocket? _currentClient; + final StreamController _clientStream = StreamController.broadcast(); _WebSocketPluginServer({dynamic address, this.port = 9999}) @@ -50,15 +50,17 @@ class _WebSocketPluginServer implements PluginCommunicationChannel { } void _handleClientAdded(WebSocket socket) { - if (_currentClient != null) { + var client = _currentClient; + + if (client != null) { print('ignoring connection attempt because an active client already ' 'exists'); socket.close(); } else { print('client connected'); - _currentClient = socket; - _clientStream.add(_currentClient); - _currentClient.done.then((_) { + client = _currentClient = socket; + _clientStream.add(client); + client.done.then((_) { print('client disconnected'); _currentClient = null; _clientStream.add(null); @@ -68,23 +70,23 @@ class _WebSocketPluginServer implements PluginCommunicationChannel { @override void close() { - server?.close(force: true); + server.close(force: true); } @override void listen(void Function(Request request) onRequest, - {Function onError, void Function() onDone}) { + {Function? onError, void Function()? onDone}) { final stream = _clientStream.stream; // wait until we're connected - stream.firstWhere((socket) => socket != null).then((_) { - _currentClient.listen((data) { + stream.whereType().first.then((socket) { + socket.listen((data) { print('I: $data'); onRequest(Request.fromJson( json.decode(data as String) as Map)); }); }); - stream.firstWhere((socket) => socket == null).then((_) => onDone()); + stream.firstWhere((socket) => socket == null).then((_) => onDone?.call()); } @override diff --git a/examples/web_worker_example/pubspec.yaml b/examples/web_worker_example/pubspec.yaml index f5aa95fd..77bdb2fc 100644 --- a/examples/web_worker_example/pubspec.yaml +++ b/examples/web_worker_example/pubspec.yaml @@ -4,7 +4,7 @@ description: An absolute bare-bones web app. #homepage: https://www.example.com environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.14.0 <3.0.0' dependencies: js: ^0.6.4 diff --git a/extras/benchmarks/pubspec.yaml b/extras/benchmarks/pubspec.yaml index 0b25e366..1cd5a374 100644 --- a/extras/benchmarks/pubspec.yaml +++ b/extras/benchmarks/pubspec.yaml @@ -2,7 +2,7 @@ name: benchmarks description: Runs simple and complex benchmarks to measure performance of moor and moor_ffi environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.14.0 <3.0.0' dependencies: drift: ^1.0.0 diff --git a/extras/drift_postgres/analysis_options.yaml b/extras/drift_postgres/analysis_options.yaml index 4fa4b8d1..055ac108 100644 --- a/extras/drift_postgres/analysis_options.yaml +++ b/extras/drift_postgres/analysis_options.yaml @@ -1,5 +1,5 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true diff --git a/extras/integration_tests/ffi_on_flutter/integration_test/drift_native_test.dart b/extras/integration_tests/ffi_on_flutter/integration_test/drift_native_test.dart index e994401f..d058ef3a 100644 --- a/extras/integration_tests/ffi_on_flutter/integration_test/drift_native_test.dart +++ b/extras/integration_tests/ffi_on_flutter/integration_test/drift_native_test.dart @@ -6,7 +6,6 @@ import 'package:drift_testcases/tests.dart'; import 'package:flutter/services.dart'; import 'package:integration_test/integration_test.dart'; import 'package:path/path.dart'; -import 'package:sqflite/sqflite.dart' show getDatabasesPath; import 'package:sqlite3/sqlite3.dart' as raw; import 'package:test/test.dart'; @@ -35,11 +34,16 @@ class FfiExecutor extends TestExecutor { } } +Future get _testDbDirectory async { + final dbDirectory = + await Directory.systemTemp.createTemp('drift-ffi-flutter'); + return dbDirectory.path; +} + Future main() async { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); - final dbPath = await getDatabasesPath(); - Directory(dbPath).createSync(recursive: true); + final dbPath = await _testDbDirectory; runAllTests(FfiExecutor(dbPath)); test('supports the rtree module', () { @@ -97,12 +101,12 @@ Future main() async { }); test('can use database path in background isolate', () async { - final token = RootIsolateToken.instance; + final token = RootIsolateToken.instance!; final isolate = await DriftIsolate.spawn(() { BackgroundIsolateBinaryMessenger.ensureInitialized(token); return LazyDatabase(() async { - final path = await getDatabasesPath(); + final path = await _testDbDirectory; final file = File(join(path, 'background.db')); return NativeDatabase(file); diff --git a/extras/integration_tests/ffi_on_flutter/pubspec.yaml b/extras/integration_tests/ffi_on_flutter/pubspec.yaml index ddc36ab3..b5f3013c 100644 --- a/extras/integration_tests/ffi_on_flutter/pubspec.yaml +++ b/extras/integration_tests/ffi_on_flutter/pubspec.yaml @@ -5,8 +5,8 @@ version: 1.0.0+1 publish_to: none environment: - sdk: ">=2.1.0 <3.0.0" - flutter: ">=1.12.0" + sdk: ">=2.12.0 <3.0.0" + flutter: ">=3.10.0" dependencies: drift: ^2.0.0-0 @@ -17,7 +17,6 @@ dependencies: drift_testcases: path: ../drift_testcases sqlite3_flutter_libs: ^0.5.7 - sqflite: ^2.0.2+1 dev_dependencies: test: ^1.18.0 diff --git a/extras/plugin_example/.gitignore b/extras/plugin_example/.gitignore deleted file mode 100644 index f02eadcc..00000000 --- a/extras/plugin_example/.gitignore +++ /dev/null @@ -1,35 +0,0 @@ - -# Created by https://www.gitignore.io/api/dart,intellij -# Edit at https://www.gitignore.io/?templates=dart,intellij - -.vscode - -### Dart ### -# See https://www.dartlang.org/guides/libraries/private-files - -# Files and directories created by pub -.dart_tool/ -.packages -build/ -# If you're building an application, you may want to check-in your pubspec.lock -pubspec.lock - -# Directory created by dartdoc -# If you don't generate documentation locally you can remove this line. -doc/api/ - -# Avoid committing generated Javascript files: -*.dart.js -*.info.json # Produced by the --dump-info flag. -*.js # When generated by dart2js. Don't specify *.js if your - # project includes source files written in JavaScript. -*.js_ -*.js.deps -*.js.map - -android/ -ios/ - -### Intellij ### -.idea/**/* -# End of https://www.gitignore.io/api/dart,intellij diff --git a/extras/plugin_example/README.md b/extras/plugin_example/README.md deleted file mode 100644 index 8401487a..00000000 --- a/extras/plugin_example/README.md +++ /dev/null @@ -1,50 +0,0 @@ -Playground to test the analyzer plugin for `.moor` files. - -Currently, we support - -- showing errors in moor files -- outline -- folding -- (very, very limited) autocomplete -- some quickfixes to make columns nullable or non-null -- navigation for references in sql queries - -## Setup -To use this plugin, you'll need to perform these steps once. It is assumed that you -have already cloned the `moor` repository. - -1. Make sure you run version `3.5.0` or later of the Dart extension in VS Code. -2. In the editor settings, change `dart.additionalAnalyzerFileExtensions` - to include `moor` files: - ```json - { - "dart.additionalAnalyzerFileExtensions": ["moor"] - } - ``` -3. Uncomment the plugin lines in `analysis_options.yaml` - -## Debugging -Note: If you only want to _use_ the plugin and don't care about debugging it, follow the step -from the [user documentation](https://drift.simonbinder.eu/docs/using-sql/sql_ide/). - -After you completed the setup, these steps will open an editor instance that runs the plugin. -1. chdir into `moor_generator` and run `dart bin/moor_generator.dart debug-plugin`. - You can run that script from an IDE if you need debugging capabilities, but starting - it from the command line is fine. Keep that script running. -3. Uncomment the `plugin` lines in `analysis_options.yaml` -3. Open this folder in the code instance -4. Wait ~15s, you should start to see some log entries in the output of step 1. - As soon as they appear, the plugin is ready to go. - -_Note_: `bin/moor_generator.dart` doesn't support multiple clients. Whenever you close or reload the -editor, that script needs to be restarted as well. That script should also be running before -starting the analysis server. - -## Troubleshooting - -If the plugin doesn't start properly, you can - -1. make sure it was picked up by the analysis server: Set the `dart.analyzerDiagnosticsPort` - to any port and see some basic information under the "plugins" tab of the website started. -2. When setting `dart.analyzerInstrumentationLogFile`, the analysis server will write the - exception that caused the plugin to stop \ No newline at end of file diff --git a/extras/plugin_example/analysis_options.yaml b/extras/plugin_example/analysis_options.yaml deleted file mode 100644 index 6069f392..00000000 --- a/extras/plugin_example/analysis_options.yaml +++ /dev/null @@ -1,8 +0,0 @@ -include: package:pedantic/analysis_options.yaml - -# The source-controlled version of this file should always have the plugin commented out. Our development version with -# the websocket proxy causes analysis errors when to plugin doesn't run - -#analyzer: -# plugins: -# - drift diff --git a/extras/plugin_example/build.yaml b/extras/plugin_example/build.yaml deleted file mode 100644 index 43a76ba1..00000000 --- a/extras/plugin_example/build.yaml +++ /dev/null @@ -1,8 +0,0 @@ -targets: - $default: - builders: - moor_generator: - options: - sqlite_modules: - - json1 - - fts5 \ No newline at end of file diff --git a/extras/plugin_example/lib/test.dart b/extras/plugin_example/lib/test.dart deleted file mode 100644 index ef22a69f..00000000 --- a/extras/plugin_example/lib/test.dart +++ /dev/null @@ -1 +0,0 @@ -class Test {} diff --git a/extras/plugin_example/lib/test.drift b/extras/plugin_example/lib/test.drift deleted file mode 100644 index d7704642..00000000 --- a/extras/plugin_example/lib/test.drift +++ /dev/null @@ -1,16 +0,0 @@ -import 'first.dart'; -import 'second.dart'; -import 'last.dart'; - -CREATE TABLE playground ( - id INT NOT NULL PRIMARY KEY AUTOINCREMENT, - name VARCHAR NOT NULL -); - -CREATE VIRTUAL TABLE email USING fts5(name); - -unknownColumn: SELECT * FROM playground WHERE bar = 'foo'; -syntaxError: SELECT 3 + FROM playground; -lints: INSERT INTO playground DEFAULT VALUES; -variables: SELECT * FROM playground WHERE id BETWEEN :foo AND :bar; -dartTemplate: SELECT * FROM playground WHERE $predicate ORDER BY $ordering; diff --git a/extras/plugin_example/lib/test.foobar b/extras/plugin_example/lib/test.foobar deleted file mode 100644 index 70ae6457..00000000 --- a/extras/plugin_example/lib/test.foobar +++ /dev/null @@ -1,3 +0,0 @@ -CREATE TABLE playground ( - id INT NOT NULL PRIMARY KEY AUTOINCREMENT -) \ No newline at end of file diff --git a/extras/plugin_example/pubspec.yaml b/extras/plugin_example/pubspec.yaml deleted file mode 100644 index 519030c5..00000000 --- a/extras/plugin_example/pubspec.yaml +++ /dev/null @@ -1,13 +0,0 @@ -name: plugin_example -description: Playground to test the analyzer plugin - -environment: - sdk: '>=2.4.0 <3.0.0' - -dependencies: - drift: - path: ../../drift - -dev_dependencies: - pedantic: ^1.7.0 - test: ^1.5.0 diff --git a/pubspec.lock b/pubspec.lock index c441dedc..7d687e21 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -290,4 +290,4 @@ packages: source: hosted version: "2.1.0" sdks: - dart: ">=2.19.0 <3.0.0" + dart: ">=2.19.0 <4.0.0" diff --git a/sqlparser/analysis_options.yaml b/sqlparser/analysis_options.yaml index 4fa4b8d1..b770289c 100644 --- a/sqlparser/analysis_options.yaml +++ b/sqlparser/analysis_options.yaml @@ -1,5 +1,6 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true +