Fix tests with new generator

This commit is contained in:
Simon Binder 2022-11-19 16:19:02 +01:00
parent c77fc3612f
commit 72a85b799c
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
11 changed files with 254 additions and 103 deletions

View File

@ -7,7 +7,10 @@ targets:
# the checks the default serialization builder runs on.
auto_apply_builders: false
sources:
- "lib/src/analysis/**"
include:
- "lib/src/analysis/**"
exclude:
- "lib/src/analysis/options.dart"
builders:
json_serializable:
enabled: true
@ -32,8 +35,7 @@ targets:
field_rename: snake
explicit_to_json: true
generate_for:
exclude:
- "lib/src/analysis/**" # using different options for those files
include: ["lib/src/analysis/options.dart"]
# https://simonbinder.eu/posts/build_directory_moves/#generating-into-a-directory-with-source_gen
source_gen:combining_builder:
options:

View File

@ -1,5 +1,6 @@
import 'package:build/build.dart';
import 'package:dart_style/dart_style.dart';
import 'package:pub_semver/pub_semver.dart';
import '../../analysis/custom_result_class.dart';
import '../../analysis/driver/driver.dart';
@ -34,6 +35,8 @@ enum DriftGenerationMode {
bool get isMonolithic => true;
bool get isPartFile => true;
/// Whether the analysis happens in the generating build step.
///
/// For most generation modes, we run analysis work in a previous build step.
@ -44,6 +47,8 @@ enum DriftGenerationMode {
}
class DriftBuilder extends Builder {
static final Version _minimalDartLanguageVersion = Version(2, 12, 0);
final DriftOptions options;
final DriftGenerationMode generationMode;
@ -96,6 +101,29 @@ class DriftBuilder extends Builder {
}
}
// Ok, we actually have something to generate. We're generating code
// needing version 2.12 (or later) of the Dart _language_. This property is
// inherited from the main file, so let's check that.
Version? overriddenLanguageVersion;
if (generationMode.isPartFile) {
final library = await buildStep.inputLibrary;
overriddenLanguageVersion = library.languageVersion.override;
final effectiveVersion = library.languageVersion.effective;
if (effectiveVersion < _minimalDartLanguageVersion) {
final effective = effectiveVersion.majorMinor;
final minimum = _minimalDartLanguageVersion.majorMinor;
log.warning(
'The language version of this file is Dart $effective. '
'Drift generates code for Dart $minimum or later. Please consider '
'raising the minimum SDK version in your pubspec.yaml to at least '
'$minimum, or add a `// @dart=$minimum` comment at the top of this '
'file.',
);
}
}
Set<Uri> analyzedUris = {};
Future<FileState> analyze(Uri uri) async {
final fileResult = await driver.fullyAnalyze(uri);
@ -167,6 +195,12 @@ class DriftBuilder extends Builder {
if (generationMode == DriftGenerationMode.monolithicPart) {
final originalFile = buildStep.inputId.pathSegments.last;
if (overriddenLanguageVersion != null) {
// Part files need to have the same version as the main library.
output.writeln('// @dart=${overriddenLanguageVersion.majorMinor}');
}
output.writeln('part of ${asDartLiteral(originalFile)};');
}
output.write(writer.writeGenerated());
@ -182,3 +216,7 @@ class DriftBuilder extends Builder {
await buildStep.writeAsString(buildStep.allowedOutputs.single, generated);
}
}
extension on Version {
String get majorMinor => '$major.$minor';
}

View File

@ -6,43 +6,105 @@ part of '../../analysis/options.dart';
// JsonSerializableGenerator
// **************************************************************************
DriftOptions _$DriftOptionsFromJson(Map json) => DriftOptions(
generateFromJsonStringConstructor:
json['write_from_json_string_constructor'] as bool? ?? false,
overrideHashAndEqualsInResultSets:
json['override_hash_and_equals_in_result_sets'] as bool? ?? false,
skipVerificationCode: json['skip_verification_code'] as bool? ?? false,
useDataClassNameForCompanions:
json['use_data_class_name_for_companions'] as bool? ?? false,
useColumnNameAsJsonKeyWhenDefinedInMoorFile:
json['use_column_name_as_json_key_when_defined_in_moor_file']
as bool? ??
true,
generateConnectConstructor:
json['generate_connect_constructor'] as bool? ?? false,
dataClassToCompanions: json['data_class_to_companions'] as bool? ?? true,
generateMutableClasses: json['mutable_classes'] as bool? ?? false,
rawResultSetData: json['raw_result_set_data'] as bool? ?? false,
applyConvertersOnVariables:
json['apply_converters_on_variables'] as bool? ?? true,
generateValuesInCopyWith:
json['generate_values_in_copy_with'] as bool? ?? true,
generateNamedParameters: json['named_parameters'] as bool? ?? false,
namedParametersAlwaysRequired:
json['named_parameters_always_required'] as bool? ?? false,
scopedDartComponents: json['scoped_dart_components'] as bool? ?? true,
modules: (json['sqlite_modules'] as List<dynamic>?)
?.map((e) => $enumDecode(_$SqlModuleEnumMap, e))
.toList() ??
[],
sqliteAnalysisOptions: json['sqlite'] == null
? null
: SqliteAnalysisOptions.fromJson(json['sqlite'] as Map),
storeDateTimeValuesAsText:
json['store_date_time_values_as_text'] as bool? ?? false,
dialect: json['sql'] == null
? null
: DialectOptions.fromJson(json['sql'] as Map),
DriftOptions _$DriftOptionsFromJson(Map json) => $checkedCreate(
'DriftOptions',
json,
($checkedConvert) {
$checkKeys(
json,
allowedKeys: const [
'write_from_json_string_constructor',
'override_hash_and_equals_in_result_sets',
'skip_verification_code',
'use_data_class_name_for_companions',
'use_column_name_as_json_key_when_defined_in_moor_file',
'generate_connect_constructor',
'sqlite_modules',
'sqlite',
'sql',
'data_class_to_companions',
'mutable_classes',
'raw_result_set_data',
'apply_converters_on_variables',
'generate_values_in_copy_with',
'named_parameters',
'named_parameters_always_required',
'scoped_dart_components',
'store_date_time_values_as_text'
],
);
final val = DriftOptions(
generateFromJsonStringConstructor: $checkedConvert(
'write_from_json_string_constructor', (v) => v as bool? ?? false),
overrideHashAndEqualsInResultSets: $checkedConvert(
'override_hash_and_equals_in_result_sets',
(v) => v as bool? ?? false),
skipVerificationCode: $checkedConvert(
'skip_verification_code', (v) => v as bool? ?? false),
useDataClassNameForCompanions: $checkedConvert(
'use_data_class_name_for_companions', (v) => v as bool? ?? false),
useColumnNameAsJsonKeyWhenDefinedInMoorFile: $checkedConvert(
'use_column_name_as_json_key_when_defined_in_moor_file',
(v) => v as bool? ?? true),
generateConnectConstructor: $checkedConvert(
'generate_connect_constructor', (v) => v as bool? ?? false),
dataClassToCompanions: $checkedConvert(
'data_class_to_companions', (v) => v as bool? ?? true),
generateMutableClasses:
$checkedConvert('mutable_classes', (v) => v as bool? ?? false),
rawResultSetData: $checkedConvert(
'raw_result_set_data', (v) => v as bool? ?? false),
applyConvertersOnVariables: $checkedConvert(
'apply_converters_on_variables', (v) => v as bool? ?? true),
generateValuesInCopyWith: $checkedConvert(
'generate_values_in_copy_with', (v) => v as bool? ?? true),
generateNamedParameters:
$checkedConvert('named_parameters', (v) => v as bool? ?? false),
namedParametersAlwaysRequired: $checkedConvert(
'named_parameters_always_required', (v) => v as bool? ?? false),
scopedDartComponents: $checkedConvert(
'scoped_dart_components', (v) => v as bool? ?? true),
modules: $checkedConvert(
'sqlite_modules',
(v) =>
(v as List<dynamic>?)
?.map((e) => $enumDecode(_$SqlModuleEnumMap, e))
.toList() ??
[]),
sqliteAnalysisOptions: $checkedConvert(
'sqlite',
(v) =>
v == null ? null : SqliteAnalysisOptions.fromJson(v as Map)),
storeDateTimeValuesAsText: $checkedConvert(
'store_date_time_values_as_text', (v) => v as bool? ?? false),
dialect: $checkedConvert('sql',
(v) => v == null ? null : DialectOptions.fromJson(v as Map)),
);
return val;
},
fieldKeyMap: const {
'generateFromJsonStringConstructor':
'write_from_json_string_constructor',
'overrideHashAndEqualsInResultSets':
'override_hash_and_equals_in_result_sets',
'skipVerificationCode': 'skip_verification_code',
'useDataClassNameForCompanions': 'use_data_class_name_for_companions',
'useColumnNameAsJsonKeyWhenDefinedInMoorFile':
'use_column_name_as_json_key_when_defined_in_moor_file',
'generateConnectConstructor': 'generate_connect_constructor',
'dataClassToCompanions': 'data_class_to_companions',
'generateMutableClasses': 'mutable_classes',
'rawResultSetData': 'raw_result_set_data',
'applyConvertersOnVariables': 'apply_converters_on_variables',
'generateValuesInCopyWith': 'generate_values_in_copy_with',
'generateNamedParameters': 'named_parameters',
'namedParametersAlwaysRequired': 'named_parameters_always_required',
'scopedDartComponents': 'scoped_dart_components',
'modules': 'sqlite_modules',
'sqliteAnalysisOptions': 'sqlite',
'storeDateTimeValuesAsText': 'store_date_time_values_as_text',
'dialect': 'sql'
},
);
Map<String, dynamic> _$DriftOptionsToJson(DriftOptions instance) =>
@ -82,11 +144,24 @@ const _$SqlModuleEnumMap = {
SqlModule.spellfix1: 'spellfix1',
};
DialectOptions _$DialectOptionsFromJson(Map json) => DialectOptions(
$enumDecode(_$SqlDialectEnumMap, json['dialect']),
json['options'] == null
? null
: SqliteAnalysisOptions.fromJson(json['options'] as Map),
DialectOptions _$DialectOptionsFromJson(Map json) => $checkedCreate(
'DialectOptions',
json,
($checkedConvert) {
$checkKeys(
json,
allowedKeys: const ['dialect', 'options'],
);
final val = DialectOptions(
$checkedConvert(
'dialect', (v) => $enumDecode(_$SqlDialectEnumMap, v)),
$checkedConvert(
'options',
(v) =>
v == null ? null : SqliteAnalysisOptions.fromJson(v as Map)),
);
return val;
},
);
Map<String, dynamic> _$DialectOptionsToJson(DialectOptions instance) =>
@ -102,13 +177,29 @@ const _$SqlDialectEnumMap = {
};
SqliteAnalysisOptions _$SqliteAnalysisOptionsFromJson(Map json) =>
SqliteAnalysisOptions(
modules: (json['modules'] as List<dynamic>?)
?.map((e) => $enumDecode(_$SqlModuleEnumMap, e))
.toList() ??
const [],
version: _$JsonConverterFromJson<String, SqliteVersion>(
json['version'], const _SqliteVersionConverter().fromJson),
$checkedCreate(
'SqliteAnalysisOptions',
json,
($checkedConvert) {
$checkKeys(
json,
allowedKeys: const ['modules', 'version'],
);
final val = SqliteAnalysisOptions(
modules: $checkedConvert(
'modules',
(v) =>
(v as List<dynamic>?)
?.map((e) => $enumDecode(_$SqlModuleEnumMap, e))
.toList() ??
const []),
version: $checkedConvert(
'version',
(v) => _$JsonConverterFromJson<String, SqliteVersion>(
v, const _SqliteVersionConverter().fromJson)),
);
return val;
},
);
Map<String, dynamic> _$SqliteAnalysisOptionsToJson(

View File

@ -61,6 +61,7 @@ class MyDatabase2 extends _$MyDatabase {
}
''',
'a|lib/foo.drift': '',
});
await backend.driver.fullyAnalyze(mainUri);

View File

@ -75,7 +75,8 @@ class Foo extends Table {
final result = file.analysis.values.single;
expect(result.result, isA<DriftTable>());
expect(result.errorsDuringAnalysis, [
isDriftError('The referenced element is not understood by drift.')
isDriftError('The referenced element, OtherTable, is not understood by '
'drift.')
.withSpan('OtherTable'),
]);
});

View File

@ -219,7 +219,7 @@ class InvalidConstraints extends Table {
final pkFromTable =
table.tableConstraints.whereType<PrimaryKeyColumns>().first;
expect(pkFromTable, containsAll(table.columns));
expect(pkFromTable.primaryKey, containsAll(table.columns));
expect(
table.columns.any(
(column) => column.constraints.any((c) => c is PrimaryKeyColumn)),

View File

@ -36,7 +36,7 @@ CREATE TABLE b (
expect(aFoo.sqlType, DriftSqlType.int);
expect(aFoo.nullable, isFalse);
expect(aFoo.constraints, [isA<PrimaryKeyColumn>()]);
expect(aFoo.customConstraints, isNull);
expect(aFoo.customConstraints, 'PRIMARY KEY');
expect(aBar.sqlType, DriftSqlType.int);
expect(aBar.nullable, isTrue);
@ -46,12 +46,12 @@ CREATE TABLE b (
.having((e) => e.onUpdate, 'onUpdate', isNull)
.having((e) => e.onDelete, 'onDelete', isNull)
]);
expect(aBar.customConstraints, isNull);
expect(aBar.customConstraints, 'REFERENCES b(bar)');
expect(bBar.sqlType, DriftSqlType.int);
expect(bBar.nullable, isFalse);
expect(bBar.constraints, isEmpty);
expect(bBar.customConstraints, isNull);
expect(bBar.customConstraints, 'NOT NULL');
});
test('recognizes aliases to rowid', () async {

View File

@ -69,7 +69,7 @@ void main() {
foo(x) AS (SELECT 2 * 3 UNION ALL SELECT 3)
SELECT x FROM foo;
''',
'WITH foo(x) AS (SELECT 2 * 3 UNION ALL SELECT 3) '
'WITH foo (x) AS (SELECT 2 * 3 UNION ALL SELECT 3) '
'SELECT x FROM foo',
);
});

View File

@ -0,0 +1,53 @@
@Tags(['analyzer'])
import 'package:build_test/build_test.dart';
import 'package:logging/logging.dart';
import 'package:test/test.dart';
import '../../utils.dart';
void main() {
test('emits warning about outdated language version', () async {
final logger = Logger.detached('test');
expect(
logger.onRecord.map((e) => e.message),
emitsThrough(
allOf(
contains('Dart 2.11'),
contains('Please consider raising the minimum SDK version'),
),
),
);
await emulateDriftBuild(inputs: {
'foo|lib/a.dart': '''
// @dart = 2.11
import 'package:drift/drift.dart';
@DriftDatabase(tables: [])
class Database {}
''',
}, logger: logger);
});
test('includes version override in part file mode', () async {
final writer = await emulateDriftBuild(inputs: {
'foo|lib/a.dart': '''
// @dart = 2.13
import 'package:drift/drift.dart';
@DriftDatabase(tables: [])
class Database {}
''',
});
checkOutputs(
{
'foo|lib/a.drift.dart': decodedMatches(contains('// @dart=2.13')),
},
writer.dartOutputs,
writer,
);
});
}

View File

@ -1,44 +0,0 @@
@Tags(['analyzer'])
import 'dart:async';
import 'package:build/build.dart';
import 'package:build_test/build_test.dart';
import 'package:drift_dev/integrations/build.dart';
import 'package:test/test.dart';
void main() {
test('generator emits warning about wrong language version', () async {
final logs = StreamController<String>();
final expectation = expectLater(
logs.stream,
emitsThrough(
allOf(
contains('Dart 2.11'),
contains('Please consider raising the minimum SDK version'),
),
),
);
await testBuilder(
driftBuilder(BuilderOptions.empty),
{
'foo|lib/a.dart': '''
// @dart = 2.11
import 'package:drift/drift.dart';
@DriftDatabase(tables: [])
class Database {}
''',
},
reader: await PackageAssetReader.currentIsolate(),
onLog: (log) {
logs.add(log.message);
},
);
await expectation;
await logs.close();
});
}

View File

@ -2,12 +2,14 @@ import 'package:build/build.dart';
import 'package:build_resolvers/build_resolvers.dart';
import 'package:build_test/build_test.dart';
import 'package:drift_dev/integrations/build.dart';
import 'package:logging/logging.dart';
final _resolvers = AnalyzerResolvers();
Future<RecordingAssetWriter> emulateDriftBuild({
required Map<String, String> inputs,
BuilderOptions options = const BuilderOptions({}),
Logger? logger,
}) async {
_resolvers.reset();
@ -31,9 +33,16 @@ Future<RecordingAssetWriter> emulateDriftBuild({
for (final stage in stages) {
await runBuilder(
stage, inputs.keys.map(makeAssetId), reader, writer, _resolvers);
stage,
inputs.keys.map(makeAssetId),
reader,
writer,
_resolvers,
logger: logger,
);
}
logger?.clearListeners();
return writer;
}