mirror of https://github.com/AMT-Cheif/drift.git
Respect transitive imports when resolving moor converters
Might fix an error discovered in #482
This commit is contained in:
parent
af5333db3c
commit
72e65611a7
|
@ -1203,7 +1203,7 @@ abstract class _$CustomTablesDb extends GeneratedDatabase {
|
||||||
Selectable<MultipleResult> multiple(Expression<bool> predicate) {
|
Selectable<MultipleResult> multiple(Expression<bool> predicate) {
|
||||||
final generatedpredicate = $write(predicate, hasMultipleTables: true);
|
final generatedpredicate = $write(predicate, hasMultipleTables: true);
|
||||||
return customSelect(
|
return customSelect(
|
||||||
'SELECT d.*, "c.a" AS "nested_0.a", "c.b" AS "nested_0.b", "c.c" AS "nested_0.c" FROM with_constraints c\n INNER JOIN with_defaults d\n ON d.a = c.a AND d.b = c.b\n WHERE ${generatedpredicate.sql}',
|
'SELECT d.*, "c"."a" AS "nested_0.a", "c"."b" AS "nested_0.b", "c"."c" AS "nested_0.c" FROM with_constraints c\n INNER JOIN with_defaults d\n ON d.a = c.a AND d.b = c.b\n WHERE ${generatedpredicate.sql}',
|
||||||
variables: [...generatedpredicate.introducedVariables],
|
variables: [...generatedpredicate.introducedVariables],
|
||||||
readsFrom: {withConstraints, withDefaults}).map(_rowToMultipleResult);
|
readsFrom: {withConstraints, withDefaults}).map(_rowToMultipleResult);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,26 +38,51 @@ class PreprocessBuilder extends Builder {
|
||||||
final moorFileContent = await buildStep.readAsString(input);
|
final moorFileContent = await buildStep.readAsString(input);
|
||||||
final engine = SqlEngine(EngineOptions(useMoorExtensions: true));
|
final engine = SqlEngine(EngineOptions(useMoorExtensions: true));
|
||||||
|
|
||||||
final parsed = engine.parseMoorFile(moorFileContent);
|
final parsedInput = engine.parseMoorFile(moorFileContent);
|
||||||
|
|
||||||
final dartLexemes = parsed.tokens
|
final dartLexemes = parsedInput.tokens
|
||||||
.whereType<InlineDartToken>()
|
.whereType<InlineDartToken>()
|
||||||
.map((token) => token.dartCode)
|
.map((token) => token.dartCode)
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (dartLexemes.isEmpty) return; // nothing to do, no Dart in this moor file
|
if (dartLexemes.isEmpty) return; // nothing to do, no Dart in this moor file
|
||||||
|
|
||||||
final importedFiles = parsed.rootNode.allDescendants
|
// Crawl through transitive imports and find all Dart libraries
|
||||||
.whereType<ImportStatement>()
|
final seenFiles = <AssetId>{};
|
||||||
.map((stmt) => stmt.importedFile)
|
final queue = <AssetId>[input];
|
||||||
.where((import) => import.endsWith('.dart'));
|
|
||||||
|
while (queue.isNotEmpty) {
|
||||||
|
final asset = queue.removeLast();
|
||||||
|
|
||||||
|
if (!seenFiles.contains(asset)) {
|
||||||
|
seenFiles.add(asset);
|
||||||
|
|
||||||
|
if (asset.extension == '.moor') {
|
||||||
|
final parsed = asset == input
|
||||||
|
? parsedInput
|
||||||
|
: engine.parseMoorFile(await buildStep.readAsString(asset));
|
||||||
|
|
||||||
|
parsed.rootNode.allDescendants
|
||||||
|
.whereType<ImportStatement>()
|
||||||
|
.map((stmt) => AssetId.resolve(stmt.importedFile, from: asset))
|
||||||
|
.where((importedId) =>
|
||||||
|
!seenFiles.contains(importedId) &&
|
||||||
|
!queue.contains(importedId))
|
||||||
|
.forEach(queue.add);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final importedDartFiles =
|
||||||
|
seenFiles.where((asset) => asset.extension == '.dart');
|
||||||
|
|
||||||
// to analyze the expressions, generate a fake Dart file that declares each
|
// to analyze the expressions, generate a fake Dart file that declares each
|
||||||
// expression in a `var`, we can then read the static type.
|
// expression in a `var`, we can then read the static type.
|
||||||
|
|
||||||
final dartBuffer = StringBuffer();
|
final dartBuffer = StringBuffer();
|
||||||
for (final import in importedFiles) {
|
for (final import in importedDartFiles) {
|
||||||
dartBuffer.write('import ${asDartLiteral(import)};\n');
|
final importUri = import.uri.toString();
|
||||||
|
dartBuffer.write('import ${asDartLiteral(importUri)};\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 0; i < dartLexemes.length; i++) {
|
for (var i = 0; i < dartLexemes.length; i++) {
|
||||||
|
|
|
@ -24,6 +24,54 @@ CREATE TABLE foo (
|
||||||
'foo|converter.dart': '''
|
'foo|converter.dart': '''
|
||||||
import 'package:moor/moor.dart';
|
import 'package:moor/moor.dart';
|
||||||
|
|
||||||
|
class MyConverter extends TypeConverter<DateTime, int> {
|
||||||
|
const MyConverter();
|
||||||
|
|
||||||
|
int mapToSql(DateTime time) => time?.millisecondsSinceEpoch;
|
||||||
|
|
||||||
|
DateTime mapToDart(int fromSql) {
|
||||||
|
if (fromSql == null) return null;
|
||||||
|
return DateTime.fromMillisecondsSinceEpoch(fromSql);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
''',
|
||||||
|
},
|
||||||
|
writer: writer,
|
||||||
|
reader: reader,
|
||||||
|
);
|
||||||
|
|
||||||
|
final output =
|
||||||
|
utf8.decode(writer.assets[AssetId.parse('foo|main.dart_in_moor')]);
|
||||||
|
final serialized = json.decode(output);
|
||||||
|
|
||||||
|
expect(serialized['const MyConverter()'], {
|
||||||
|
'type': 'interface',
|
||||||
|
'library': 'asset:foo/converter.dart',
|
||||||
|
'class_name': 'MyConverter',
|
||||||
|
'type_args': [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('finds dart files over transitive imports', () async {
|
||||||
|
final writer = InMemoryAssetWriter();
|
||||||
|
final reader = await PackageAssetReader.currentIsolate();
|
||||||
|
|
||||||
|
await testBuilder(
|
||||||
|
PreprocessBuilder(),
|
||||||
|
{
|
||||||
|
'foo|main.moor': '''
|
||||||
|
import 'indirection.moor';
|
||||||
|
|
||||||
|
CREATE TABLE foo (
|
||||||
|
id INT NOT NULL MAPPED BY `const MyConverter()`
|
||||||
|
);
|
||||||
|
''',
|
||||||
|
'foo|indirection.moor': '''
|
||||||
|
import 'converter.dart';
|
||||||
|
''',
|
||||||
|
'foo|converter.dart': '''
|
||||||
|
import 'package:moor/moor.dart';
|
||||||
|
|
||||||
class MyConverter extends TypeConverter<DateTime, int> {
|
class MyConverter extends TypeConverter<DateTime, int> {
|
||||||
const MyConverter();
|
const MyConverter();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue