mirror of https://github.com/AMT-Cheif/drift.git
Merge remote-tracking branch 'simolus3/develop' into fix-lint-warning
This commit is contained in:
commit
40554c8166
|
@ -288,6 +288,12 @@ describes how to migrate stored columns between the format:
|
|||
|
||||
{% assign snippets = "package:drift_docs/snippets/migrations/datetime_conversion.dart.excerpt.json" | readString | json_decode %}
|
||||
|
||||
Note that the JSON serialization generated by default is not affected by the
|
||||
datetime mode chosen. By default, drift will serialize `DateTime` values to a
|
||||
unix timestamp in milliseconds. You can change this by creating a
|
||||
`ValueSerializer.defaults(serializeDateTimeValuesAsString: true)` and assigning
|
||||
it to `driftRuntimeOptions.defaultSerializer`.
|
||||
|
||||
##### Migrating from unix timestamps to text
|
||||
|
||||
To migrate from using timestamps (the default option) to storing datetimes as
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
data:
|
||||
data:
|
||||
title: "Documentation & Guides"
|
||||
description: Welcome to drift's documentation. This site shows you what drift can do and how to use it.
|
||||
template: layouts/docs/list
|
||||
|
@ -8,7 +8,7 @@ template: layouts/docs/list
|
|||
## Welcome to drift
|
||||
|
||||
Drift is a reactive persistence library for Dart and Flutter applications. It's built on top
|
||||
of database libraries like [sqflite](https://pub.dev/packages/sqflite) or [sql.js](https://github.com/sql-js/sql.js/)
|
||||
of database libraries like [the sqlite3 package](https://pub.dev/packages/sqlite3), [sqflite](https://pub.dev/packages/sqflite) or [sql.js](https://github.com/sql-js/sql.js/)
|
||||
and provides additional features, like:
|
||||
|
||||
- __Type safety__: Instead of writing sql queries manually and parsing the `List<Map<String, dynamic>>` that they
|
||||
|
|
|
@ -7,47 +7,76 @@ data:
|
|||
show_favorites: true
|
||||
---
|
||||
|
||||
{% block "blocks/cover.html" title="Drift: Persistence library for Dart" image_anchor="top" height="med" color="indigo" %}
|
||||
{% block "blocks/cover.html" title="Drift: Persistence library for Dart" image_anchor="top" height="med" %}
|
||||
<div class="mx-auto">
|
||||
<p class="h4">
|
||||
Drift is <em>the</em> relational persistence library for your Dart and Flutter apps.
|
||||
Write type-safe queries in Dart or SQL, enjoy auto-updating streams, easily managed transactions
|
||||
and so much more to make persistence fun.
|
||||
</p>
|
||||
<a class="btn btn-lg btn-primary mr-3 mb-4" href="{{ 'docs/index' | pageUrl }}">
|
||||
Learn more <i class="fas fa-arrow-alt-circle-right ml-2"></i>
|
||||
</a>
|
||||
<a class="btn btn-lg btn-secondary mr-3 mb-4" href="https://pub.dev/packages/drift">
|
||||
Get from pub <i class="fas fa-code ml-2 "></i>
|
||||
Get started <i class="fas fa-code ml-2 "></i>
|
||||
</a>
|
||||
|
||||
<p class="lead mt-5">
|
||||
With a fluent query api, a powerful sql analyzer, auto-updating streams and much more,
|
||||
drift makes persistence fun. Scroll down to learn about its key features, or visit the
|
||||
<a href="{{ 'docs/Getting started/index' | pageUrl }}">getting started guide</a> for a step-by-step guide on using drift.
|
||||
</p>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block "blocks/lead.html" color="dark" %}
|
||||
Drift is an easy to use, reactive persistence library for Flutter apps. Define tables in Dart or
|
||||
SQL and enjoy a fluent query API, auto-updating streams and more!
|
||||
{% endblock %}
|
||||
|
||||
{% block "blocks/section.html" color="primary" %}
|
||||
|
||||
{% block "blocks/feature.html" icon="fas fa-lightbulb" title="Declarative tables, fluent queries" %}
|
||||
{% block "blocks/markdown.html" %}
|
||||
With drift, you can write your database tables in pure Dart without having to miss out on
|
||||
advanced sqlite features. Drift will take care of creating the tables and generate code
|
||||
With drift, you can declare your database tables and queries in pure Dart without having to miss out on
|
||||
advanced SQL features. Drift will take care of creating the tables and generate code
|
||||
that allows you run fluent queries on your data.
|
||||
|
||||
[Get started now]({{ "docs/Getting started/index.md" | pageUrl }})
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block "blocks/feature.html" icon="fas fa-database" title="Prefer SQL? Drift got you covered!" %}
|
||||
{% block "blocks/feature.html" icon="fas fa-database" title="Definitely relational" %}
|
||||
{% block "blocks/markdown.html" %}
|
||||
Drift contains a powerful sql parser and analyzer, allowing it to create typesafe APIs for all your sql queries. All sql queries are
|
||||
Drift is not the kind of ORM that tries to hide SQL away and then breaks down at the first
|
||||
aggregation or non-obvious join.
|
||||
|
||||
Instead, drift embraces relational databases with an Dart API that's easy to learn
|
||||
while still being close to SQL. Advanced expressions or subqueries are supported out of
|
||||
the box.
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block "blocks/feature.html" icon="fas fa-lightbulb" title="Safe schemas" %}
|
||||
{% block "blocks/markdown.html" %}
|
||||
A well-chosen SQL schema enables type-safe queries and avoids hard-to-spot mistakes.
|
||||
Thanks to drift's extensive support for schema migrations, changing schemas is a safe
|
||||
and easy process.
|
||||
Further, drift provides a complete test toolkit to help you test migrations
|
||||
between all your revisions.
|
||||
|
||||
[All about schema migrations]({{ "docs/Advanced Features/migrations.md" | pageUrl }})
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block "blocks/feature.html" icon="fas fa-database" title="Prefer SQL? Drift's got you covered!" %}
|
||||
{% block "blocks/markdown.html" %}
|
||||
Drift ships a powerful sql parser and analyzer, allowing it to create typesafe methods for all your sql queries. All sql queries are
|
||||
validated and analyzed during build-time, so drift can provide hints about potential errors quickly and generate efficient mapping
|
||||
code.
|
||||
Of course, you can mix SQL and Dart to your liking.
|
||||
|
||||
[Learn more]({{ 'docs/Using SQL/index.md' | pageUrl }})
|
||||
[Using SQL with Drift]({{ 'docs/Using SQL/index.md' | pageUrl }})
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block "blocks/feature.html" icon="fas fa-lightbulb" title="Supported on your favorite platform" %}
|
||||
{% block "blocks/markdown.html" %}
|
||||
Drift's core APIs are written to support a range of database libraries as backends, it doesn't even require Flutter.
|
||||
Drift has primary first-class support for Android, iOS, macOS, Linux Windows and the web.
|
||||
|
||||
Other database libraries can easily be integrated into drift as well.
|
||||
|
||||
[All platforms]({{ "docs/platforms.md" | pageUrl }})
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
|
@ -60,25 +89,3 @@ When using drift, working with databases in Dart is fun!
|
|||
{% endblock %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block "blocks/section.html" color="light" type="section" %}
|
||||
{% block "blocks/markdown.html" %}
|
||||
## Key features
|
||||
|
||||
Here are some of the many ways drift helps you write awesome database code:
|
||||
|
||||
* __Auto-updating streams__: With drift, any query - no matter how complex - can be turned into a stream that emits new data as the underlying data changes.
|
||||
* __Polyglot__: Drift lets you write queries in a fluent Dart api or directly in SQL - you can even embed Dart expressions in SQL.
|
||||
* __Boilerplate-free__: Stop writing mapping code yourself - drift can take of that. Drift generates Dart code around your data so you can focus
|
||||
on building great apps.
|
||||
* __Flexible__: Want to write queries in SQL? Drift verifies them at compile time and generates Dart apis for them. Prefer to write them in Dart?
|
||||
Drift will generate efficient SQL for Dart queries too.
|
||||
* __Easy to learn__: Instead of having to learn yet another ORM, drift lets you write queries in SQL and generates typesafe wrappers. Queries and tables
|
||||
can also be written in Dart that looks similar to SQL without loosing type-safety.
|
||||
* __Fast _and_ powerful__: With the new `ffi` backend, drift can outperform key-value stores without putting any compromises on the integrity
|
||||
and flexibility that relational databases provide. Drift is the only major persistence library with builtin support for multiple isolates.
|
||||
* __Well tested and production ready__: Each component of drift is verified by a wide range of unit and integration tests. Drift powers many Flutter apps
|
||||
in production.
|
||||
* __Cross-Platform__: Drift works on iOS, Android, Linux, macOS, Windows and on the web. It doesn't even require Flutter. See [supported platforms]({{ "docs/platforms.md" | pageUrl }}).
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -38,8 +38,6 @@ dev_dependencies:
|
|||
drift_dev:
|
||||
|
||||
dependency_overrides:
|
||||
# Waiting for dartdoc, https://github.com/dart-lang/dartdoc/pull/3033
|
||||
analyzer: ^4.0.0
|
||||
moor_generator:
|
||||
path: ../moor_generator
|
||||
drift:
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
{% assign links = site.links %}
|
||||
<footer class="bg-dark py-5 row d-print-none">
|
||||
<div class="container-fluid mx-sm-5">
|
||||
<div class="row">
|
||||
<div class="col-6 col-sm-4 text-xs-center order-sm-2">
|
||||
{% if links.user %}
|
||||
{% assign links = links.user %}
|
||||
{% include "partials/footer-links-block.html" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-6 col-sm-4 text-right text-xs-center order-sm-3">
|
||||
{% if links.developer %}
|
||||
{% assign links = links.developer %}
|
||||
{% include "partials/footer-links-block.html" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-12 col-sm-4 text-center py-2 order-sm-2">
|
||||
{% if site.copyright %}
|
||||
<small class="text-white"><div>© {{ site.copyright }}</div>
|
||||
Except where otherwise noted, content on this site is licensed under a <a href="https://creativecommons.org/licenses/by/4.0/" target="_blank" rel="license noopener noreferrer">CC BY 4.0</a> license.
|
||||
Code snippets are marked with <a href="http://creativecommons.org/publicdomain/zero/1.0" target="_blank" rel="license noopener noreferrer">CC0 1.0</a>,
|
||||
drift itself is <a href="https://github.com/simolus3/drift/blob/develop/LICENSE" rel="license" target="_blank">MIT-licensed</a>.
|
||||
</small>
|
||||
{% endif %}
|
||||
{% if site.privacy_policy %}
|
||||
<small class="ml-1"><a href="{{ site.privacy_policy }}" target="_blank">{{ "footer_privacy_policy" | i18n }}</a></small>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
|
@ -158,11 +158,19 @@ abstract class Table extends HasResultSet {
|
|||
ColumnBuilder<bool> boolean() => _isGenerated();
|
||||
|
||||
/// Use this as the body of a getter to declare a column that holds date and
|
||||
/// time. Note that [DateTime] values are stored on a second-accuracy.
|
||||
/// time.
|
||||
///
|
||||
/// Drift supports two modes for storing date times: As unix timestamp with
|
||||
/// second accuracy (the default) and as ISO 8601 string with microsecond
|
||||
/// accuracy. For more information between the modes, and information on how
|
||||
/// to change them, see [the documentation].
|
||||
///
|
||||
/// Note that [DateTime] values are stored on a second-accuracy.
|
||||
/// Example (inside the body of a table class):
|
||||
/// ```
|
||||
/// DateTimeColumn get accountCreatedAt => dateTime()();
|
||||
/// ```
|
||||
/// [the documentation]: https://drift.simonbinder.eu/docs/getting-started/advanced_dart_tables/#supported-column-types
|
||||
@protected
|
||||
ColumnBuilder<DateTime> dateTime() => _isGenerated();
|
||||
|
||||
|
|
|
@ -188,7 +188,14 @@ abstract class ValueSerializer {
|
|||
///
|
||||
/// To override the default serializer drift uses, you can change the
|
||||
/// [DriftRuntimeOptions.defaultSerializer] field.
|
||||
const factory ValueSerializer.defaults() = _DefaultValueSerializer;
|
||||
///
|
||||
/// The [serializeDateTimeValuesAsString] option (which defaults to `false`)
|
||||
/// describes whether [DateTime] values should be serialized to a unix
|
||||
/// timestamp ([DateTime.millisecondsSinceEpoch]) or a string
|
||||
/// ([DateTime.toIso8601String]).
|
||||
/// In either case, date time values can be _deserialized_ from both formats.
|
||||
const factory ValueSerializer.defaults(
|
||||
{bool serializeDateTimeValuesAsString}) = _DefaultValueSerializer;
|
||||
|
||||
/// Converts the [value] to something that can be passed to
|
||||
/// [JsonCodec.encode].
|
||||
|
@ -200,7 +207,9 @@ abstract class ValueSerializer {
|
|||
}
|
||||
|
||||
class _DefaultValueSerializer extends ValueSerializer {
|
||||
const _DefaultValueSerializer();
|
||||
final bool serializeDateTimeValuesAsString;
|
||||
|
||||
const _DefaultValueSerializer({this.serializeDateTimeValuesAsString = false});
|
||||
|
||||
@override
|
||||
T fromJson<T>(dynamic json) {
|
||||
|
@ -211,7 +220,11 @@ class _DefaultValueSerializer extends ValueSerializer {
|
|||
final _typeList = <T>[];
|
||||
|
||||
if (_typeList is List<DateTime?>) {
|
||||
return DateTime.fromMillisecondsSinceEpoch(json as int) as T;
|
||||
if (json is int) {
|
||||
return DateTime.fromMillisecondsSinceEpoch(json) as T;
|
||||
} else {
|
||||
return DateTime.parse(json.toString()) as T;
|
||||
}
|
||||
}
|
||||
|
||||
if (_typeList is List<double?> && json is int) {
|
||||
|
@ -231,7 +244,9 @@ class _DefaultValueSerializer extends ValueSerializer {
|
|||
@override
|
||||
dynamic toJson<T>(T value) {
|
||||
if (value is DateTime) {
|
||||
return value.millisecondsSinceEpoch;
|
||||
return serializeDateTimeValuesAsString
|
||||
? value.toIso8601String()
|
||||
: value.millisecondsSinceEpoch;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
|
|
@ -48,6 +48,12 @@ void _testWith(TodoDb Function() openDb, {bool dateTimeAsText = false}) {
|
|||
expect(await eval(Variable(local)), local);
|
||||
},
|
||||
);
|
||||
|
||||
test('preserves milliseconds', () async {
|
||||
final local = DateTime(2020, 09, 03, 23, 55, 0, 123);
|
||||
|
||||
expect(await eval(Variable(local)), local);
|
||||
});
|
||||
}
|
||||
|
||||
test('plus and minus', () async {
|
||||
|
|
|
@ -17,8 +17,8 @@ void main() {
|
|||
|
||||
await expectLater(
|
||||
db.validateDatabaseSchema(),
|
||||
throwsA(isA<SchemaMismatch>().having(
|
||||
(e) => e.toString(), 'toString()', contains('TEXT and INTEGER'))),
|
||||
throwsA(isA<SchemaMismatch>().having((e) => e.toString(), 'toString()',
|
||||
contains('Expected TEXT, got INTEGER'))),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,29 +2,37 @@ import 'package:drift/drift.dart';
|
|||
import 'package:test/test.dart';
|
||||
import 'generated/todos.dart';
|
||||
|
||||
final DateTime someDate = DateTime(2019, 06, 08);
|
||||
final DateTime _someDate = DateTime(2019, 06, 08);
|
||||
|
||||
final TodoEntry someTodoEntry = TodoEntry(
|
||||
final TodoEntry _someTodoEntry = TodoEntry(
|
||||
id: 3,
|
||||
title: null,
|
||||
content: 'content',
|
||||
targetDate: someDate,
|
||||
targetDate: _someDate,
|
||||
category: 3,
|
||||
);
|
||||
|
||||
final Map<String, dynamic> regularSerialized = {
|
||||
final Map<String, dynamic> _regularSerialized = {
|
||||
'id': 3,
|
||||
'title': null,
|
||||
'content': 'content',
|
||||
'target_date': someDate.millisecondsSinceEpoch,
|
||||
'target_date': _someDate.millisecondsSinceEpoch,
|
||||
'category': 3,
|
||||
};
|
||||
|
||||
final Map<String, dynamic> customSerialized = {
|
||||
final Map<String, dynamic> _asTextSerialized = {
|
||||
'id': 3,
|
||||
'title': null,
|
||||
'content': 'content',
|
||||
'target_date': _someDate.toIso8601String(),
|
||||
'category': 3,
|
||||
};
|
||||
|
||||
final Map<String, dynamic> _customSerialized = {
|
||||
'id': 3,
|
||||
'title': 'set to null',
|
||||
'content': 'content',
|
||||
'target_date': someDate.toIso8601String(),
|
||||
'target_date': _someDate.toIso8601String(),
|
||||
'category': 3,
|
||||
};
|
||||
|
||||
|
@ -61,7 +69,16 @@ void main() {
|
|||
|
||||
group('serialization', () {
|
||||
test('with defaults', () {
|
||||
expect(someTodoEntry.toJson(), equals(regularSerialized));
|
||||
expect(_someTodoEntry.toJson(), equals(_regularSerialized));
|
||||
});
|
||||
|
||||
test('with default serializer, date as text', () {
|
||||
expect(
|
||||
_someTodoEntry.toJson(
|
||||
serializer: const ValueSerializer.defaults(
|
||||
serializeDateTimeValuesAsString: true)),
|
||||
equals(_asTextSerialized),
|
||||
);
|
||||
});
|
||||
|
||||
test('applies json type converter', () {
|
||||
|
@ -71,20 +88,31 @@ void main() {
|
|||
});
|
||||
|
||||
test('with custom serializer', () {
|
||||
expect(someTodoEntry.toJson(serializer: CustomSerializer()),
|
||||
equals(customSerialized));
|
||||
expect(_someTodoEntry.toJson(serializer: CustomSerializer()),
|
||||
equals(_customSerialized));
|
||||
});
|
||||
});
|
||||
|
||||
group('deserialization', () {
|
||||
test('with defaults', () {
|
||||
expect(TodoEntry.fromJson(regularSerialized), equals(someTodoEntry));
|
||||
expect(TodoEntry.fromJson(_regularSerialized), equals(_someTodoEntry));
|
||||
expect(TodoEntry.fromJson(_asTextSerialized), equals(_someTodoEntry));
|
||||
});
|
||||
|
||||
test('with date-as-text serializer', () {
|
||||
const serializer =
|
||||
ValueSerializer.defaults(serializeDateTimeValuesAsString: true);
|
||||
|
||||
expect(TodoEntry.fromJson(_regularSerialized, serializer: serializer),
|
||||
equals(_someTodoEntry));
|
||||
expect(TodoEntry.fromJson(_asTextSerialized, serializer: serializer),
|
||||
equals(_someTodoEntry));
|
||||
});
|
||||
|
||||
test('with custom serializer', () {
|
||||
expect(
|
||||
TodoEntry.fromJson(customSerialized, serializer: CustomSerializer()),
|
||||
equals(someTodoEntry));
|
||||
TodoEntry.fromJson(_customSerialized, serializer: CustomSerializer()),
|
||||
equals(_someTodoEntry));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -337,7 +337,7 @@ class ColumnParser {
|
|||
if (foundExplicitName != null) {
|
||||
name = ColumnName.explicitly(foundExplicitName);
|
||||
} else {
|
||||
name = ColumnName.implicitly(ReCase(getter.name.name).snakeCase);
|
||||
name = ColumnName.implicitly(ReCase(getter.name2.lexeme).snakeCase);
|
||||
}
|
||||
|
||||
final columnType = _startMethodToColumnType(foundStartMethod);
|
||||
|
@ -424,7 +424,7 @@ class ColumnParser {
|
|||
getter.documentationComment?.tokens.map((t) => t.toString()).join('\n');
|
||||
return DriftColumn(
|
||||
type: columnType,
|
||||
dartGetterName: getter.name.name,
|
||||
dartGetterName: getter.name2.lexeme,
|
||||
name: name,
|
||||
overriddenJsonName: _readJsonKey(element),
|
||||
customConstraints: foundCustomConstraint,
|
||||
|
@ -456,9 +456,11 @@ class ColumnParser {
|
|||
final annotations = getter.metadata;
|
||||
final object = annotations.firstWhereOrNull((e) {
|
||||
final value = e.computeConstantValue();
|
||||
return value != null &&
|
||||
isFromMoor(value.type!) &&
|
||||
value.type!.element!.name == 'JsonKey';
|
||||
final valueType = value?.type;
|
||||
|
||||
return valueType is InterfaceType &&
|
||||
isFromDrift(valueType) &&
|
||||
valueType.element2.name == 'JsonKey';
|
||||
});
|
||||
|
||||
if (object == null) return null;
|
||||
|
|
|
@ -85,7 +85,7 @@ class TableParser {
|
|||
|
||||
for (final annotation in element.metadata) {
|
||||
final computed = annotation.computeConstantValue();
|
||||
final annotationClass = computed!.type!.element!.name;
|
||||
final annotationClass = computed!.type!.nameIfInterfaceType;
|
||||
|
||||
if (annotationClass == 'DataClassName') {
|
||||
dataClassName = computed;
|
||||
|
@ -124,8 +124,8 @@ class TableParser {
|
|||
useRowClass.getField('generateInsertable')!.toBoolValue()!;
|
||||
|
||||
if (type is InterfaceType) {
|
||||
existingClass = FoundDartClass(type.element, type.typeArguments);
|
||||
name = type.element.name;
|
||||
existingClass = FoundDartClass(type.element2, type.typeArguments);
|
||||
name = type.element2.name;
|
||||
} else {
|
||||
base.step.reportError(ErrorInDartCode(
|
||||
message: 'The @UseRowClass annotation must be used with a class',
|
||||
|
@ -309,7 +309,7 @@ class TableParser {
|
|||
|
||||
Future<Iterable<DriftColumn>> _parseColumns(ClassElement element) async {
|
||||
final columnNames = element.allSupertypes
|
||||
.map((t) => t.element)
|
||||
.map((t) => t.element2)
|
||||
.followedBy([element])
|
||||
.expand((e) => e.fields)
|
||||
.where((field) =>
|
||||
|
@ -350,10 +350,10 @@ class _DataClassInformation {
|
|||
|
||||
extension on Element {
|
||||
bool get isFromDefaultTable {
|
||||
final parent = enclosingElement2;
|
||||
final parent = enclosingElement3;
|
||||
|
||||
return parent is ClassElement &&
|
||||
parent.name == 'Table' &&
|
||||
isFromMoor(parent.thisType);
|
||||
isFromDrift(parent.thisType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ class UseDaoParser {
|
|||
/// declared by that class and the referenced tables.
|
||||
Future<Dao?> parseDao(ClassElement element, ConstantReader annotation) async {
|
||||
final dbType = element.allSupertypes
|
||||
.firstWhereOrNull((i) => i.element.name == 'DatabaseAccessor');
|
||||
.firstWhereOrNull((i) => i.element2.name == 'DatabaseAccessor');
|
||||
|
||||
if (dbType == null) {
|
||||
step.reportError(ErrorInDartCode(
|
||||
|
|
|
@ -41,7 +41,7 @@ class ViewParser {
|
|||
|
||||
for (final annotation in element.metadata) {
|
||||
final computed = annotation.computeConstantValue();
|
||||
final annotationClass = computed!.type!.element!.name;
|
||||
final annotationClass = computed!.type!.nameIfInterfaceType;
|
||||
|
||||
if (annotationClass == 'DriftView') {
|
||||
driftView = computed;
|
||||
|
@ -80,8 +80,8 @@ class ViewParser {
|
|||
useRowClass.getField('generateInsertable')!.toBoolValue()!;
|
||||
|
||||
if (type is InterfaceType) {
|
||||
existingClass = FoundDartClass(type.element, type.typeArguments);
|
||||
name = type.element.name;
|
||||
existingClass = FoundDartClass(type.element2, type.typeArguments);
|
||||
name = type.element2.name;
|
||||
} else {
|
||||
base.step.reportError(ErrorInDartCode(
|
||||
message: 'The @UseRowClass annotation must be used with a class',
|
||||
|
@ -100,7 +100,7 @@ class ViewParser {
|
|||
Future<String> _parseViewName(ClassElement element) async {
|
||||
for (final annotation in element.metadata) {
|
||||
final computed = annotation.computeConstantValue();
|
||||
final annotationClass = computed!.type!.element!.name;
|
||||
final annotationClass = computed!.type!.nameIfInterfaceType;
|
||||
|
||||
if (annotationClass == 'DriftView') {
|
||||
final name = computed.getField('name')?.toStringValue();
|
||||
|
@ -116,7 +116,7 @@ class ViewParser {
|
|||
|
||||
Future<Iterable<DriftColumn>> _parseColumns(ClassElement element) async {
|
||||
final columnNames = element.allSupertypes
|
||||
.map((t) => t.element)
|
||||
.map((t) => t.element2)
|
||||
.followedBy([element])
|
||||
.expand((e) => e.fields)
|
||||
.where((field) =>
|
||||
|
@ -134,7 +134,7 @@ class ViewParser {
|
|||
|
||||
final results = await Future.wait(fields.map((field) async {
|
||||
final dartType = (field.type as InterfaceType).typeArguments[0];
|
||||
final typeName = dartType.element!.name!;
|
||||
final typeName = dartType.nameIfInterfaceType!;
|
||||
final sqlType = _dartTypeToColumnType(typeName);
|
||||
|
||||
if (sqlType == null) {
|
||||
|
@ -181,7 +181,7 @@ class ViewParser {
|
|||
Future<List<TableReferenceInDartView>> _parseStaticReferences(
|
||||
ClassElement element, List<DriftTable> tables) async {
|
||||
return await Stream.fromIterable(element.allSupertypes
|
||||
.map((t) => t.element)
|
||||
.map((t) => t.element2)
|
||||
.followedBy([element]).expand((e) => e.fields))
|
||||
.asyncMap((field) => _getStaticReference(field, tables))
|
||||
.where((ref) => ref != null)
|
||||
|
@ -198,7 +198,7 @@ class ViewParser {
|
|||
final type = tables.firstWhereOrNull(
|
||||
(tbl) => tbl.fromClass!.name == node.returnType.toString());
|
||||
if (type != null) {
|
||||
final name = node.name.toString();
|
||||
final name = node.name2.lexeme;
|
||||
return TableReferenceInDartView(type, name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import 'package:drift_dev/src/analyzer/runner/steps.dart';
|
|||
import 'helper.dart';
|
||||
|
||||
class FoundDartClass {
|
||||
final ClassElement classElement;
|
||||
final InterfaceElement classElement;
|
||||
|
||||
/// The instantiation of the [classElement], if the found type was a generic
|
||||
/// typedef.
|
||||
|
@ -230,8 +230,8 @@ void _checkType(
|
|||
final isAllowedUint8List = typeConverter == null &&
|
||||
columnType == DriftSqlType.blob &&
|
||||
typeToCheck is InterfaceType &&
|
||||
typeToCheck.element.name == 'Uint8List' &&
|
||||
typeToCheck.element.library.name == 'dart.typed_data';
|
||||
typeToCheck.element2.name == 'Uint8List' &&
|
||||
typeToCheck.element2.library.name == 'dart.typed_data';
|
||||
|
||||
if (!typeSystem.isAssignableTo(expectedDartType.type, typeToCheck) &&
|
||||
!isAllowedUint8List) {
|
||||
|
@ -246,14 +246,14 @@ extension on TypeProvider {
|
|||
case DriftSqlType.int:
|
||||
return intType;
|
||||
case DriftSqlType.bigInt:
|
||||
return intElement.library.getType('BigInt')!.instantiate(
|
||||
return intElement.library.getClass('BigInt')!.instantiate(
|
||||
typeArguments: const [], nullabilitySuffix: NullabilitySuffix.none);
|
||||
case DriftSqlType.string:
|
||||
return stringType;
|
||||
case DriftSqlType.bool:
|
||||
return boolType;
|
||||
case DriftSqlType.dateTime:
|
||||
return intElement.library.getType('DateTime')!.instantiate(
|
||||
return intElement.library.getClass('DateTime')!.instantiate(
|
||||
typeArguments: const [], nullabilitySuffix: NullabilitySuffix.none);
|
||||
case DriftSqlType.blob:
|
||||
return listType(intType);
|
||||
|
|
|
@ -28,8 +28,8 @@ String? parseCustomParentClass(String dartTypeName, DartObject dataClassName,
|
|||
if (extending != null && !extending.isNull) {
|
||||
final extendingType = extending.toTypeValue();
|
||||
if (extendingType is InterfaceType) {
|
||||
final superType = extendingType.allSupertypes
|
||||
.any((type) => isFromMoor(type) && type.element.name == 'DataClass');
|
||||
final superType = extendingType.allSupertypes.any(
|
||||
(type) => isFromDrift(type) && type.element2.name == 'DataClass');
|
||||
if (!superType) {
|
||||
base.step.reportError(
|
||||
ErrorInDartCode(
|
||||
|
@ -52,10 +52,10 @@ String? parseCustomParentClass(String dartTypeName, DartObject dataClassName,
|
|||
return null;
|
||||
}
|
||||
|
||||
final className = extendingType.element.name;
|
||||
final className = extendingType.nameIfInterfaceType;
|
||||
if (extendingType.typeArguments.length == 1) {
|
||||
final genericType = extendingType.typeArguments[0].element?.name;
|
||||
if (genericType == 'Object' || genericType == 'dynamic') {
|
||||
final genericType = extendingType.typeArguments[0];
|
||||
if (genericType.isDartCoreObject || genericType.isDynamic) {
|
||||
return '$className<$dartTypeName>';
|
||||
} else {
|
||||
base.step.reportError(
|
||||
|
|
|
@ -28,7 +28,7 @@ Future<FoundDartClass?> findDartClass(
|
|||
} else if (foundElement is TypeAliasElement) {
|
||||
final innerType = foundElement.aliasedType;
|
||||
if (innerType is InterfaceType) {
|
||||
return FoundDartClass(innerType.element, innerType.typeArguments);
|
||||
return FoundDartClass(innerType.element2, innerType.typeArguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -122,7 +122,7 @@ class ParseDartStep extends Step {
|
|||
Future<List<DriftTable>> parseTables(
|
||||
Iterable<DartType> types, Element initializedBy) {
|
||||
return Future.wait(types.map((type) {
|
||||
if (!_tableTypeChecker.isAssignableFrom(type.element!)) {
|
||||
if (!_tableTypeChecker.isAssignableFromType(type)) {
|
||||
reportError(ErrorInDartCode(
|
||||
severity: Severity.criticalError,
|
||||
message: 'The type $type is not a moor table',
|
||||
|
@ -130,7 +130,7 @@ class ParseDartStep extends Step {
|
|||
));
|
||||
return Future.value(null);
|
||||
} else {
|
||||
return _parseTable(type.element as ClassElement);
|
||||
return _parseTable((type as InterfaceType).element2 as ClassElement);
|
||||
}
|
||||
})).then((list) {
|
||||
// only keep tables that were resolved successfully
|
||||
|
@ -145,7 +145,7 @@ class ParseDartStep extends Step {
|
|||
Future<List<MoorView>> parseViews(Iterable<DartType> types,
|
||||
Element initializedBy, List<DriftTable> tables) {
|
||||
return Future.wait(types.map((type) {
|
||||
if (!_viewTypeChecker.isAssignableFrom(type.element!)) {
|
||||
if (!_viewTypeChecker.isAssignableFromType(type)) {
|
||||
reportError(ErrorInDartCode(
|
||||
severity: Severity.criticalError,
|
||||
message: 'The type $type is not a drift view',
|
||||
|
@ -153,7 +153,8 @@ class ParseDartStep extends Step {
|
|||
));
|
||||
return Future.value(null);
|
||||
} else {
|
||||
return _parseView(type.element as ClassElement, tables);
|
||||
return _parseView(
|
||||
(type as InterfaceType).element2 as ClassElement, tables);
|
||||
}
|
||||
})).then((list) {
|
||||
// only keep tables that were resolved successfully
|
||||
|
|
|
@ -21,7 +21,7 @@ class DaoGenerator extends Generator implements BaseGenerator {
|
|||
|
||||
final daoName = element!.displayName;
|
||||
|
||||
final dbTypeName = dao.dbClass.codeString(writer.generationOptions);
|
||||
final dbTypeName = dao.dbClass.codeString();
|
||||
classScope.leaf().write('mixin _\$${daoName}Mixin on '
|
||||
'DatabaseAccessor<$dbTypeName> {\n');
|
||||
|
||||
|
|
|
@ -413,7 +413,8 @@ class _Moor2DriftDartRewriter extends GeneralizingAstVisitor<void> {
|
|||
|
||||
if (type is! InterfaceType) continue;
|
||||
|
||||
if (type.element.library.isDartCore && type.element.name == 'pragma') {
|
||||
if (type.element2.library.isDartCore &&
|
||||
type.element2.name == 'pragma') {
|
||||
final name = value.getField('name')!.toStringValue()!;
|
||||
|
||||
if (name == 'moor2drift') {
|
||||
|
@ -452,8 +453,8 @@ class _Moor2DriftDartRewriter extends GeneralizingAstVisitor<void> {
|
|||
if (type is! InterfaceType ||
|
||||
// note that even old moor code uses these names since UseMoor/UseDao
|
||||
// are type aliases to the new interfaces.
|
||||
(type.element.name != 'DriftDatabase' &&
|
||||
type.element.name != 'DriftAccessor')) {
|
||||
(type.element2.name != 'DriftDatabase' &&
|
||||
type.element2.name != 'DriftAccessor')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ abstract class DriftEntityWithResultSet extends DriftSchemaEntity {
|
|||
/// The type name of the Dart row class for this result set.
|
||||
///
|
||||
/// This may contain generics.
|
||||
String dartTypeCode([GenerationOptions options = const GenerationOptions()]);
|
||||
String dartTypeCode();
|
||||
|
||||
/// The name of the Dart class storing additional properties like type
|
||||
/// converters.
|
||||
|
@ -65,7 +65,7 @@ abstract class DriftEntityWithResultSet extends DriftSchemaEntity {
|
|||
/// Information used by the generator to generate code for a custom data class
|
||||
/// written by users.
|
||||
class ExistingRowClass {
|
||||
final ClassElement targetClass;
|
||||
final InterfaceElement targetClass;
|
||||
|
||||
/// The Dart types that should be used to instantiate the [targetClass].
|
||||
final List<DartType> typeInstantiation;
|
||||
|
|
|
@ -142,11 +142,11 @@ abstract class SqlQuery {
|
|||
}
|
||||
|
||||
if (resultSet.matchingTable != null) {
|
||||
return resultSet.matchingTable!.table.dartTypeCode(options);
|
||||
return resultSet.matchingTable!.table.dartTypeCode();
|
||||
}
|
||||
|
||||
if (resultSet.singleColumn) {
|
||||
return resultSet.columns.single.dartTypeCode(options);
|
||||
return resultSet.columns.single.dartTypeCode();
|
||||
}
|
||||
|
||||
return resultClassName;
|
||||
|
@ -593,7 +593,7 @@ abstract class FoundElement {
|
|||
bool get hidden => false;
|
||||
|
||||
/// Dart code for a type representing tis element.
|
||||
String dartTypeCode([GenerationOptions options = const GenerationOptions()]);
|
||||
String dartTypeCode();
|
||||
}
|
||||
|
||||
/// A semantic interpretation of a [Variable] in a sql statement.
|
||||
|
@ -676,8 +676,8 @@ class FoundVariable extends FoundElement implements HasType {
|
|||
}
|
||||
|
||||
@override
|
||||
String dartTypeCode([GenerationOptions options = const GenerationOptions()]) {
|
||||
return OperationOnTypes(this).dartTypeCode(options);
|
||||
String dartTypeCode() {
|
||||
return OperationOnTypes(this).dartTypeCode();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'package:analyzer/dart/element/nullability_suffix.dart';
|
|||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:drift_dev/src/model/model.dart';
|
||||
import 'package:drift_dev/src/utils/type_utils.dart';
|
||||
import 'package:drift_dev/writer.dart';
|
||||
|
||||
/// Something that has a type.
|
||||
///
|
||||
|
@ -60,14 +59,14 @@ class DriftDartType {
|
|||
return type.getDisplayString(withNullability: withNullability);
|
||||
}
|
||||
|
||||
String codeString([GenerationOptions options = const GenerationOptions()]) {
|
||||
String codeString() {
|
||||
if (overiddenSource != null) {
|
||||
if (nullabilitySuffix == NullabilitySuffix.star) {
|
||||
return getDisplayString(withNullability: false);
|
||||
}
|
||||
return getDisplayString(withNullability: true);
|
||||
} else {
|
||||
return type.codeString(options);
|
||||
return type.codeString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,10 +126,10 @@ extension OperationOnTypes on HasType {
|
|||
/// The dart type that matches the values of this column. For instance, if a
|
||||
/// table has declared an `IntColumn`, the matching dart type name would be
|
||||
/// [int].
|
||||
String dartTypeCode([GenerationOptions options = const GenerationOptions()]) {
|
||||
String dartTypeCode() {
|
||||
final converter = typeConverter;
|
||||
if (converter != null) {
|
||||
var inner = converter.dartType.codeString(options);
|
||||
var inner = converter.dartType.codeString();
|
||||
if (converter.canBeSkippedForNulls && nullable) inner += '?';
|
||||
return isArray ? 'List<$inner>' : inner;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import 'package:analyzer/dart/element/type.dart';
|
|||
import 'package:analyzer/dart/element/type_provider.dart';
|
||||
import 'package:drift_dev/src/model/table.dart';
|
||||
import 'package:drift_dev/src/utils/type_utils.dart';
|
||||
import 'package:drift_dev/src/writer/writer.dart';
|
||||
|
||||
import 'types.dart';
|
||||
|
||||
|
@ -92,12 +91,12 @@ class UsedTypeConverter {
|
|||
bool nullable,
|
||||
TypeProvider typeProvider,
|
||||
) {
|
||||
if (enumType.element is! ClassElement) {
|
||||
if (enumType is! InterfaceType) {
|
||||
throw InvalidTypeForEnumConverterException('Not a class', enumType);
|
||||
}
|
||||
|
||||
final creatingClass = enumType.element as ClassElement;
|
||||
if (!creatingClass.isEnum) {
|
||||
final creatingClass = enumType.element2;
|
||||
if (creatingClass is! EnumElement) {
|
||||
throw InvalidTypeForEnumConverterException('Not an enum', enumType);
|
||||
}
|
||||
|
||||
|
@ -132,23 +131,22 @@ class UsedTypeConverter {
|
|||
return dartTypeIsNullable || (canBeSkippedForNulls && nullableInSql);
|
||||
}
|
||||
|
||||
String dartTypeCode(GenerationOptions options, bool nullableInSql) {
|
||||
var type = dartType.codeString(options);
|
||||
String dartTypeCode(bool nullableInSql) {
|
||||
var type = dartType.codeString();
|
||||
if (canBeSkippedForNulls && nullableInSql) type += '?';
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/// A suitable typename to store an instance of the type converter used here.
|
||||
String converterNameInCode(GenerationOptions options,
|
||||
{bool makeNullable = false}) {
|
||||
String converterNameInCode({bool makeNullable = false}) {
|
||||
var sqlDartType = sqlType.getDisplayString(withNullability: true);
|
||||
if (makeNullable) sqlDartType += '?';
|
||||
|
||||
final className =
|
||||
alsoAppliesToJsonConversion ? 'JsonTypeConverter' : 'TypeConverter';
|
||||
|
||||
return '$className<${dartTypeCode(options, makeNullable)}, $sqlDartType>';
|
||||
return '$className<${dartTypeCode(makeNullable)}, $sqlDartType>';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -166,7 +166,7 @@ class FindSchemaDifferences {
|
|||
|
||||
if (refType != actType) {
|
||||
return FoundDifference(
|
||||
'Different types: ${ref.typeName} and ${act.typeName}');
|
||||
'Different types: Expected ${ref.typeName}, got ${act.typeName}');
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -174,19 +174,20 @@ class FindSchemaDifferences {
|
|||
} catch (e) {
|
||||
final firstSpan = ref.constraints.spanOrNull?.text ?? '';
|
||||
final secondSpan = act.constraints.spanOrNull?.text ?? '';
|
||||
return FoundDifference('Not equal: `$firstSpan` and `$secondSpan`');
|
||||
return FoundDifference(
|
||||
'Not equal: `$firstSpan` (expected) and `$secondSpan` (actual)');
|
||||
}
|
||||
|
||||
return const Success();
|
||||
}
|
||||
|
||||
CompareResult _compareByAst(AstNode a, AstNode b) {
|
||||
CompareResult _compareByAst(AstNode reference, AstNode actual) {
|
||||
try {
|
||||
enforceEqual(a, b);
|
||||
enforceEqual(reference, actual);
|
||||
return const Success();
|
||||
} catch (e) {
|
||||
return FoundDifference(
|
||||
'Not equal: `${a.span?.text}` and `${b.span?.text}`');
|
||||
return FoundDifference('Not equal: Expected `${reference.span?.text}`, '
|
||||
'got `${actual.span?.text}`');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,34 +1,40 @@
|
|||
import 'package:analyzer/dart/element/nullability_suffix.dart';
|
||||
import 'package:analyzer/dart/element/type.dart';
|
||||
import 'package:drift_dev/src/writer/writer.dart';
|
||||
|
||||
bool isFromMoor(DartType type) {
|
||||
final firstComponent = type.element?.library?.location?.components.first;
|
||||
bool isFromDrift(DartType type) {
|
||||
if (type is! InterfaceType) return false;
|
||||
|
||||
final firstComponent = type.element2.library.location?.components.first;
|
||||
if (firstComponent == null) return false;
|
||||
|
||||
return firstComponent.contains('drift') || firstComponent.contains('moor');
|
||||
}
|
||||
|
||||
bool isColumn(DartType type) {
|
||||
final name = type.element?.name ?? '';
|
||||
final name = type.nameIfInterfaceType;
|
||||
|
||||
return isFromMoor(type) &&
|
||||
return isFromDrift(type) &&
|
||||
name != null &&
|
||||
name.contains('Column') &&
|
||||
!name.contains('Builder');
|
||||
}
|
||||
|
||||
bool isExpression(DartType type) {
|
||||
final name = type.element?.name ?? '';
|
||||
final name = type.nameIfInterfaceType;
|
||||
|
||||
return isFromMoor(type) && name.startsWith('Expression');
|
||||
return name != null && isFromDrift(type) && name.startsWith('Expression');
|
||||
}
|
||||
|
||||
extension TypeUtils on DartType {
|
||||
String? get nameIfInterfaceType {
|
||||
final $this = this;
|
||||
return $this is InterfaceType ? $this.element2.name : null;
|
||||
}
|
||||
|
||||
String get userVisibleName => getDisplayString(withNullability: true);
|
||||
|
||||
/// How this type should look like in generated code.
|
||||
String codeString([GenerationOptions options = const GenerationOptions()]) {
|
||||
String codeString() {
|
||||
if (nullabilitySuffix == NullabilitySuffix.star) {
|
||||
// We can't actually use the legacy star in code, so don't show it.
|
||||
return getDisplayString(withNullability: false);
|
||||
|
|
|
@ -99,7 +99,7 @@ class DatabaseWriter {
|
|||
|
||||
// Write fields to access an dao. We use a lazy getter for that.
|
||||
for (final dao in db.daos) {
|
||||
final typeName = dao.codeString(scope.generationOptions);
|
||||
final typeName = dao.codeString();
|
||||
final getterName = ReCase(typeName).camelCase;
|
||||
final databaseImplName = db.fromClass!.name;
|
||||
|
||||
|
|
|
@ -293,7 +293,7 @@ class QueryWriter {
|
|||
final namedElements = <FoundElement>[];
|
||||
|
||||
String typeFor(FoundElement element) {
|
||||
var type = element.dartTypeCode(scope.generationOptions);
|
||||
var type = element.dartTypeCode();
|
||||
|
||||
if (element is FoundDartPlaceholder &&
|
||||
element.writeAsScopedFunction(options)) {
|
||||
|
|
|
@ -30,7 +30,7 @@ class ResultSetWriter {
|
|||
// write fields
|
||||
for (final column in resultSet.columns) {
|
||||
final name = resultSet.dartNameFor(column);
|
||||
final runtimeType = column.dartTypeCode(scope.generationOptions);
|
||||
final runtimeType = column.dartTypeCode();
|
||||
|
||||
into.write('$modifier $runtimeType $name\n;');
|
||||
|
||||
|
@ -40,7 +40,7 @@ class ResultSetWriter {
|
|||
|
||||
for (final nested in resultSet.nestedResults) {
|
||||
if (nested is NestedResultTable) {
|
||||
var typeName = nested.table.dartTypeCode(scope.generationOptions);
|
||||
var typeName = nested.table.dartTypeCode();
|
||||
final fieldName = nested.dartFieldName;
|
||||
|
||||
if (nested.isNullable) {
|
||||
|
|
|
@ -48,7 +48,7 @@ class DataClassWriter {
|
|||
_buffer.write('${column.documentationComment}\n');
|
||||
}
|
||||
final modifier = scope.options.fieldModifier;
|
||||
_buffer.write('$modifier ${column.dartTypeCode(scope.generationOptions)} '
|
||||
_buffer.write('$modifier ${column.dartTypeCode()} '
|
||||
'${column.dartGetterName}; \n');
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ class DataClassWriter {
|
|||
typeConverter.tableAndField(forNullableColumn: column.nullable);
|
||||
deserialized = '$converterField.fromJson($fromConverter)';
|
||||
} else {
|
||||
final type = column.dartTypeCode(scope.generationOptions);
|
||||
final type = column.dartTypeCode();
|
||||
|
||||
deserialized = "serializer.fromJson<$type>(json['$jsonKey'])";
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ class DataClassWriter {
|
|||
final getter = column.dartGetterName;
|
||||
final needsThis = getter == 'serializer';
|
||||
var value = needsThis ? 'this.$getter' : getter;
|
||||
var dartType = column.dartTypeCode(scope.generationOptions);
|
||||
var dartType = column.dartTypeCode();
|
||||
|
||||
final typeConverter = column.typeConverter;
|
||||
if (typeConverter != null && typeConverter.alsoAppliesToJsonConversion) {
|
||||
|
@ -177,7 +177,7 @@ class DataClassWriter {
|
|||
final last = i == columns.length - 1;
|
||||
final isNullable = column.nullableInDart;
|
||||
|
||||
final typeName = column.dartTypeCode(scope.generationOptions);
|
||||
final typeName = column.dartTypeCode();
|
||||
if (wrapNullableInValue && isNullable) {
|
||||
_buffer
|
||||
..write('Value<$typeName> ${column.dartGetterName} ')
|
||||
|
|
|
@ -100,7 +100,7 @@ abstract class TableOrViewWriter {
|
|||
if (converter != null) {
|
||||
// Generate a GeneratedColumnWithTypeConverter instance, as it has
|
||||
// additional methods to check for equality against a mapped value.
|
||||
final mappedType = converter.dartTypeCode(options, column.nullable);
|
||||
final mappedType = converter.dartTypeCode(column.nullable);
|
||||
|
||||
final converterCode =
|
||||
converter.tableAndField(forNullableColumn: column.nullable);
|
||||
|
@ -134,7 +134,7 @@ abstract class TableOrViewWriter {
|
|||
return;
|
||||
}
|
||||
|
||||
final dataClassName = tableOrView.dartTypeCode(scope.generationOptions);
|
||||
final dataClassName = tableOrView.dartTypeCode();
|
||||
|
||||
buffer
|
||||
..write('@override\n$dataClassName map(Map<String, dynamic> data, '
|
||||
|
@ -321,7 +321,7 @@ class TableWriter extends TableOrViewWriter {
|
|||
|
||||
void _writeConvertersAsStaticFields() {
|
||||
for (final converter in table.converters) {
|
||||
final typeName = converter.converterNameInCode(scope.generationOptions);
|
||||
final typeName = converter.converterNameInCode();
|
||||
final code = converter.expression;
|
||||
|
||||
buffer.write('static $typeName ${converter.fieldName} = $code;');
|
||||
|
@ -334,8 +334,8 @@ class TableWriter extends TableOrViewWriter {
|
|||
if (converter != null &&
|
||||
converter.canBeSkippedForNulls &&
|
||||
column.nullable) {
|
||||
final nullableTypeName = converter
|
||||
.converterNameInCode(scope.generationOptions, makeNullable: true);
|
||||
final nullableTypeName =
|
||||
converter.converterNameInCode(makeNullable: true);
|
||||
|
||||
final wrap = converter.alsoAppliesToJsonConversion
|
||||
? 'JsonTypeConverter.asNullable'
|
||||
|
|
|
@ -43,7 +43,7 @@ class UpdateCompanionWriter {
|
|||
void _writeFields() {
|
||||
for (final column in columns) {
|
||||
final modifier = scope.options.fieldModifier;
|
||||
final type = column.dartTypeCode(scope.generationOptions);
|
||||
final type = column.dartTypeCode();
|
||||
_buffer.write('$modifier Value<$type> ${column.dartGetterName};\n');
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ class UpdateCompanionWriter {
|
|||
|
||||
if (table.isColumnRequiredForInsert(column)) {
|
||||
requiredColumns.add(column);
|
||||
final typeName = column.dartTypeCode(scope.generationOptions);
|
||||
final typeName = column.dartTypeCode();
|
||||
|
||||
_buffer.write('required $typeName $param,');
|
||||
} else {
|
||||
|
@ -151,7 +151,7 @@ class UpdateCompanionWriter {
|
|||
}
|
||||
first = false;
|
||||
|
||||
final typeName = column.dartTypeCode(scope.generationOptions);
|
||||
final typeName = column.dartTypeCode();
|
||||
_buffer.write('Value<$typeName>? ${column.dartGetterName}');
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ dependencies:
|
|||
sqlparser: ^0.22.0
|
||||
|
||||
# Dart analysis
|
||||
analyzer: "^4.3.0"
|
||||
analyzer: "^4.4.0"
|
||||
analyzer_plugin: ^0.11.0
|
||||
source_span: ^1.5.5
|
||||
package_config: ^2.0.0
|
||||
|
|
|
@ -44,7 +44,7 @@ void main() {
|
|||
expect(parser.returnExpressionOfMethod(node)!.toSource(), source);
|
||||
}
|
||||
|
||||
final testClass = library.getType('Test');
|
||||
final testClass = library.getClass('Test');
|
||||
|
||||
await _verifyReturnExpressionMatches(
|
||||
testClass!.getGetter('getter')!, "'foo'");
|
||||
|
|
|
@ -146,7 +146,7 @@ void main() {
|
|||
});
|
||||
|
||||
Future<DriftTable?> parse(String name) async {
|
||||
return parser.parseTable(dartStep.library.getType(name)!);
|
||||
return parser.parseTable(dartStep.library.getClass(name)!);
|
||||
}
|
||||
|
||||
group('table names', () {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
@Tags(['analyzer'])
|
||||
import 'package:drift_dev/src/analyzer/runner/results.dart';
|
||||
import 'package:drift_dev/src/utils/type_utils.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../utils.dart';
|
||||
|
@ -48,7 +49,7 @@ class ProductsDao extends BaseProductsDao with _$ProductDaoMixin {
|
|||
expect(file.errors.errors, isEmpty);
|
||||
|
||||
final dao = (file.currentResult as ParsedDartFile).declaredDaos.single;
|
||||
expect(dao.dbClass.element!.name, 'MyDatabase');
|
||||
expect(dao.dbClass.nameIfInterfaceType, 'MyDatabase');
|
||||
|
||||
state.close();
|
||||
});
|
||||
|
|
|
@ -70,7 +70,7 @@ void main() {
|
|||
expect(result, hasChanges);
|
||||
expect(
|
||||
result.describe(),
|
||||
contains('Different types: TEXT and INTEGER'),
|
||||
contains('Different types: Expected TEXT, got INTEGER'),
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -83,7 +83,8 @@ void main() {
|
|||
expect(result, hasChanges);
|
||||
expect(
|
||||
result.describe(),
|
||||
contains('Not equal: `PRIMARY KEY NOT NULL` and ``'),
|
||||
contains(
|
||||
'Not equal: `PRIMARY KEY NOT NULL` (expected) and `` (actual)'),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@ import 'package:analyzer/dart/ast/ast.dart';
|
|||
import 'package:analyzer/file_system/memory_file_system.dart';
|
||||
import 'package:build/build.dart';
|
||||
import 'package:build_test/build_test.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:drift_dev/src/backends/build/drift_builder.dart';
|
||||
import 'package:pub_semver/pub_semver.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
@ -81,15 +82,18 @@ class _GeneratesConstDataClasses extends Matcher {
|
|||
|
||||
final definedClasses = parsed.declarations.whereType<ClassDeclaration>();
|
||||
for (final definedClass in definedClasses) {
|
||||
if (expectedWithConstConstructor.contains(definedClass.name.name)) {
|
||||
final constructor = definedClass.getConstructor(null);
|
||||
if (expectedWithConstConstructor.contains(definedClass.name2.lexeme)) {
|
||||
final constructor = definedClass.members
|
||||
.whereType<ConstructorDeclaration>()
|
||||
.firstWhereOrNull((e) => e.name2 == null);
|
||||
if (constructor?.constKeyword == null) {
|
||||
matchState['desc'] = 'Constructor ${definedClass.name.name} is not '
|
||||
matchState['desc'] =
|
||||
'Constructor ${definedClass.name2.lexeme} is not '
|
||||
'const.';
|
||||
return false;
|
||||
}
|
||||
|
||||
remaining.remove(definedClass.name.name);
|
||||
remaining.remove(definedClass.name2.lexeme);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,25 +80,26 @@ class _GeneratesWithoutFinalFields extends Matcher {
|
|||
|
||||
final definedClasses = parsed.declarations.whereType<ClassDeclaration>();
|
||||
for (final definedClass in definedClasses) {
|
||||
if (expectedWithoutFinals.contains(definedClass.name.name)) {
|
||||
final definedClassName = definedClass.name2.lexeme;
|
||||
if (expectedWithoutFinals.contains(definedClassName)) {
|
||||
for (final member in definedClass.members) {
|
||||
if (member is FieldDeclaration) {
|
||||
if (member.fields.isFinal) {
|
||||
matchState['desc'] =
|
||||
'Field ${member.fields.variables.first.name.name} in '
|
||||
'${definedClass.name.name} is final.';
|
||||
'Field ${member.fields.variables.first.name2.lexeme} in '
|
||||
'$definedClassName is final.';
|
||||
return false;
|
||||
}
|
||||
} else if (member is ConstructorDeclaration) {
|
||||
if (member.constKeyword != null) {
|
||||
matchState['desc'] = 'Constructor ${member.name?.name ?? ''} in '
|
||||
'${definedClass.name.name} is constant.';
|
||||
matchState['desc'] = 'Constructor ${member.name2?.lexeme ?? ''} '
|
||||
'in $definedClassName is constant.';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remaining.remove(definedClass.name.name);
|
||||
remaining.remove(definedClassName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue