Generate type converters for views

This commit is contained in:
Simon Binder 2023-01-06 17:16:18 +01:00
parent 1d7e656e30
commit a6bede2aaa
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
5 changed files with 88 additions and 37 deletions

View File

@ -22,15 +22,17 @@ class DriftViewResolver extends DriftElementResolver<DiscoveredDriftView> {
final engine = newEngineWithTables(references);
final source = (file.discovery as DiscoveredDriftFile).originalSource;
final resolveTypes = allReferences.dartTypes.isEmpty
? null
: await createTypeResolver(
allReferences,
await resolver.driver.loadKnownTypes(),
);
final context = engine.analyzeNode(
stmt,
source,
stmtOptions: AnalyzeStatementOptions(
resolveTypeFromText: await createTypeResolver(
allReferences,
await resolver.driver.loadKnownTypes(),
),
),
stmtOptions: AnalyzeStatementOptions(resolveTypeFromText: resolveTypes),
);
reportLints(context, references);

View File

@ -154,6 +154,36 @@ abstract class TableOrViewWriter {
);
}
void writeConvertersAsStaticFields() {
for (final converter in tableOrView.appliedConverters) {
if (converter.owningColumn?.owner != tableOrView) continue;
final typeName =
emitter.dartCode(emitter.writer.converterType(converter));
final code = emitter.dartCode(converter.expression);
buffer.write('static $typeName ${converter.fieldName} = $code;');
// Generate wrappers for non-nullable type converters that are applied to
// nullable converters.
final column = converter.owningColumn!;
if (converter.canBeSkippedForNulls && column.nullable) {
final nullableTypeName = emitter.dartCode(
emitter.writer.converterType(converter, makeNullable: true));
final wrap = converter.alsoAppliesToJsonConversion
? emitter.drift('JsonTypeConverter2.asNullable')
: emitter.drift('NullAwareTypeConverter.wrap');
final code = '$wrap(${converter.fieldName})';
buffer
.write('static $nullableTypeName ${converter.nullableFieldName} = '
'$code;');
}
}
}
void writeMappingMethod(Scope scope) {
if (!scope.generationOptions.writeDataClasses) {
buffer.writeln('''
@ -359,7 +389,7 @@ class TableWriter extends TableOrViewWriter {
_writeAliasGenerator();
_writeConvertersAsStaticFields();
writeConvertersAsStaticFields();
_overrideFieldsIfNeeded();
// close class
@ -384,34 +414,6 @@ class TableWriter extends TableOrViewWriter {
buffer.write('}');
}
void _writeConvertersAsStaticFields() {
for (final converter in table.appliedConverters) {
final typeName =
emitter.dartCode(emitter.writer.converterType(converter));
final code = emitter.dartCode(converter.expression);
buffer.write('static $typeName ${converter.fieldName} = $code;');
// Generate wrappers for non-nullable type converters that are applied to
// nullable converters.
final column = converter.owningColumn!;
if (converter.canBeSkippedForNulls && column.nullable) {
final nullableTypeName = emitter.dartCode(
emitter.writer.converterType(converter, makeNullable: true));
final wrap = converter.alsoAppliesToJsonConversion
? emitter.drift('JsonTypeConverter2.asNullable')
: emitter.drift('NullAwareTypeConverter.wrap');
final code = '$wrap(${converter.fieldName})';
buffer
.write('static $nullableTypeName ${converter.nullableFieldName} = '
'$code;');
}
}
}
void _writeColumnVerificationMeta(DriftColumn column) {
if (!_skipVerification) {
final meta = emitter.drift('VerificationMeta');

View File

@ -107,6 +107,7 @@ class ViewWriter extends TableOrViewWriter {
Set<String> get readTables => const {$readTables};
''');
writeConvertersAsStaticFields();
buffer.writeln('}');
}

View File

@ -32,7 +32,7 @@ class Users extends Table {
}
''',
'a|lib/main.drift': '''
import 'main.dart';
import 'json.dart';
CREATE TABLE users (
foo TEXT MAPPED BY `withoutJson()`,
@ -93,5 +93,5 @@ CREATE TABLE users (
test('json converters in drift files', () {
return testWith('package:a/main.drift');
}, skip: 'Reading Dart expressions not currently supported in tests');
});
}

View File

@ -273,4 +273,50 @@ class ADrift extends i1.ModularAccessor {
''')),
}, results.dartOutputs, results);
});
test('generates type converters for views', () async {
final result = await emulateDriftBuild(
inputs: {
'a|lib/a.drift': '''
import 'converter.dart';
CREATE VIEW my_view AS SELECT
CAST(1 AS ENUM(MyEnum)) AS c1,
CAST('bar' AS ENUMNAME(MyEnum)) AS c2,
1 MAPPED BY `myConverter()` AS c3,
NULLIF(1, 2) MAPPED BY `myConverter()` AS c4
;
''',
'a|lib/converter.dart': '''
import 'package:drift/drift.dart';
enum MyEnum {
foo, bar
}
TypeConverter<Object, int> myConverter() => throw UnimplementedError();
''',
},
modularBuild: true,
logger: loggerThat(neverEmits(anything)),
);
checkOutputs(
{
'a|lib/a.drift.dart': decodedMatches(
allOf(
contains(
''''CREATE VIEW my_view AS SELECT CAST(1 AS INT) AS c1, CAST(\\'bar\\' AS TEXT) AS c2, 1 AS c3, NULLIF(1, 2) AS c4';'''),
contains(r'$converterc1 ='),
contains(r'$converterc2 ='),
contains(r'$converterc3 ='),
contains(r'$converterc4 ='),
contains(r'$converterc4n ='),
),
),
},
result.dartOutputs,
result,
);
});
}