mirror of https://github.com/AMT-Cheif/drift.git
Add `fatal_warnings` build option
This commit is contained in:
parent
c72f2131f7
commit
4411e0c459
|
@ -76,6 +76,8 @@ At the moment, drift supports these options:
|
||||||
The possible values are `preserve`, `camelCase`, `CONSTANT_CASE`, `snake_case`, `PascalCase`, `lowercase` and `UPPERCASE` (default: `snake_case`).
|
The possible values are `preserve`, `camelCase`, `CONSTANT_CASE`, `snake_case`, `PascalCase`, `lowercase` and `UPPERCASE` (default: `snake_case`).
|
||||||
* `write_to_columns_mixins`: Whether the `toColumns` method should be written as a mixin instead of being added directly to the data class.
|
* `write_to_columns_mixins`: Whether the `toColumns` method should be written as a mixin instead of being added directly to the data class.
|
||||||
This is useful when using [existing row classes]({{ 'custom_row_classes.md' | pageUrl }}), as the mixin is generated for those as well.
|
This is useful when using [existing row classes]({{ 'custom_row_classes.md' | pageUrl }}), as the mixin is generated for those as well.
|
||||||
|
* `fatal_warnings`: When enabled (defaults to `false`), warnings found by `drift_dev` in the build process (like syntax errors in SQL queries or
|
||||||
|
unresolved references in your Dart tables) will cause the build to fail.
|
||||||
|
|
||||||
## Assumed SQL environment
|
## Assumed SQL environment
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ targets:
|
||||||
write_from_json_string_constructor: true
|
write_from_json_string_constructor: true
|
||||||
raw_result_set_data: true
|
raw_result_set_data: true
|
||||||
named_parameters: true
|
named_parameters: true
|
||||||
|
fatal_warnings: true
|
||||||
sql:
|
sql:
|
||||||
dialect: sqlite
|
dialect: sqlite
|
||||||
options:
|
options:
|
||||||
|
@ -33,6 +34,7 @@ targets:
|
||||||
builders:
|
builders:
|
||||||
drift_dev:
|
drift_dev:
|
||||||
options:
|
options:
|
||||||
|
fatal_warnings: true
|
||||||
store_date_time_values_as_text: true
|
store_date_time_values_as_text: true
|
||||||
# Dart doesn't support YAML merge tags yet, https://github.com/dart-lang/yaml/issues/121
|
# Dart doesn't support YAML merge tags yet, https://github.com/dart-lang/yaml/issues/121
|
||||||
override_hash_and_equals_in_result_sets: true
|
override_hash_and_equals_in_result_sets: true
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
// Mocks generated by Mockito 5.4.1 from annotations
|
// Mocks generated by Mockito 5.4.2 from annotations
|
||||||
// in drift/test/test_utils/test_utils.dart.
|
// in drift/test/test_utils/test_utils.dart.
|
||||||
// Do not manually edit this file.
|
// Do not manually edit this file.
|
||||||
|
|
||||||
// @dart=2.19
|
|
||||||
|
|
||||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||||
import 'dart:async' as _i4;
|
import 'dart:async' as _i4;
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,9 @@ class DriftOptions {
|
||||||
@JsonKey(name: 'write_to_columns_mixins', defaultValue: false)
|
@JsonKey(name: 'write_to_columns_mixins', defaultValue: false)
|
||||||
final bool writeToColumnsMixins;
|
final bool writeToColumnsMixins;
|
||||||
|
|
||||||
|
@JsonKey(name: 'fatal_warnings', defaultValue: false)
|
||||||
|
final bool fatalWarnings;
|
||||||
|
|
||||||
@internal
|
@internal
|
||||||
const DriftOptions.defaults({
|
const DriftOptions.defaults({
|
||||||
this.generateFromJsonStringConstructor = false,
|
this.generateFromJsonStringConstructor = false,
|
||||||
|
@ -124,6 +127,7 @@ class DriftOptions {
|
||||||
this.dialect = const DialectOptions(SqlDialect.sqlite, null),
|
this.dialect = const DialectOptions(SqlDialect.sqlite, null),
|
||||||
this.caseFromDartToSql = CaseFromDartToSql.snake,
|
this.caseFromDartToSql = CaseFromDartToSql.snake,
|
||||||
this.writeToColumnsMixins = false,
|
this.writeToColumnsMixins = false,
|
||||||
|
this.fatalWarnings = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
DriftOptions({
|
DriftOptions({
|
||||||
|
@ -146,6 +150,7 @@ class DriftOptions {
|
||||||
required this.storeDateTimeValuesAsText,
|
required this.storeDateTimeValuesAsText,
|
||||||
required this.caseFromDartToSql,
|
required this.caseFromDartToSql,
|
||||||
required this.writeToColumnsMixins,
|
required this.writeToColumnsMixins,
|
||||||
|
required this.fatalWarnings,
|
||||||
this.dialect,
|
this.dialect,
|
||||||
}) {
|
}) {
|
||||||
// ignore: deprecated_member_use_from_same_package
|
// ignore: deprecated_member_use_from_same_package
|
||||||
|
|
|
@ -9,6 +9,7 @@ import '../../analysis/options.dart';
|
||||||
import '../../writer/import_manager.dart';
|
import '../../writer/import_manager.dart';
|
||||||
import '../../writer/writer.dart';
|
import '../../writer/writer.dart';
|
||||||
import 'backend.dart';
|
import 'backend.dart';
|
||||||
|
import 'exception.dart';
|
||||||
|
|
||||||
class DriftAnalyzer extends Builder {
|
class DriftAnalyzer extends Builder {
|
||||||
final DriftOptions options;
|
final DriftOptions options;
|
||||||
|
@ -34,15 +35,18 @@ class DriftAnalyzer extends Builder {
|
||||||
final driver = DriftAnalysisDriver(backend, options);
|
final driver = DriftAnalysisDriver(backend, options);
|
||||||
|
|
||||||
final results = await driver.resolveElements(buildStep.inputId.uri);
|
final results = await driver.resolveElements(buildStep.inputId.uri);
|
||||||
|
var hadWarnings = false;
|
||||||
|
|
||||||
for (final parseError in results.errorsDuringDiscovery) {
|
for (final parseError in results.errorsDuringDiscovery) {
|
||||||
log.warning(parseError.toString());
|
log.warning(parseError.toString());
|
||||||
|
hadWarnings = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.analysis.isNotEmpty) {
|
if (results.analysis.isNotEmpty) {
|
||||||
for (final result in results.analysis.values) {
|
for (final result in results.analysis.values) {
|
||||||
for (final error in result.errorsDuringAnalysis) {
|
for (final error in result.errorsDuringAnalysis) {
|
||||||
log.warning(error.toString());
|
log.warning(error.toString());
|
||||||
|
hadWarnings = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +90,10 @@ class DriftAnalyzer extends Builder {
|
||||||
await buildStep.writeAsString(typesOutput, writer.writeGenerated());
|
await buildStep.writeAsString(typesOutput, writer.writeGenerated());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hadWarnings && options.fatalWarnings) {
|
||||||
|
throw const FatalWarningException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static final _languageVersionForGeneralizedTypedefs = LanguageVersion(2, 13);
|
static final _languageVersionForGeneralizedTypedefs = LanguageVersion(2, 13);
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:build/build.dart';
|
import 'package:build/build.dart';
|
||||||
import 'package:dart_style/dart_style.dart';
|
import 'package:dart_style/dart_style.dart';
|
||||||
import 'package:drift_dev/src/writer/tables/table_writer.dart';
|
|
||||||
import 'package:pub_semver/pub_semver.dart';
|
import 'package:pub_semver/pub_semver.dart';
|
||||||
|
|
||||||
import '../../analysis/custom_result_class.dart';
|
import '../../analysis/custom_result_class.dart';
|
||||||
|
@ -14,9 +13,11 @@ import '../../writer/drift_accessor_writer.dart';
|
||||||
import '../../writer/function_stubs_writer.dart';
|
import '../../writer/function_stubs_writer.dart';
|
||||||
import '../../writer/import_manager.dart';
|
import '../../writer/import_manager.dart';
|
||||||
import '../../writer/modules.dart';
|
import '../../writer/modules.dart';
|
||||||
|
import '../../writer/tables/table_writer.dart';
|
||||||
import '../../writer/tables/view_writer.dart';
|
import '../../writer/tables/view_writer.dart';
|
||||||
import '../../writer/writer.dart';
|
import '../../writer/writer.dart';
|
||||||
import 'backend.dart';
|
import 'backend.dart';
|
||||||
|
import 'exception.dart';
|
||||||
|
|
||||||
class _BuilderFlags {
|
class _BuilderFlags {
|
||||||
bool didWarnAboutDeprecatedOptions = false;
|
bool didWarnAboutDeprecatedOptions = false;
|
||||||
|
@ -125,6 +126,7 @@ class _DriftBuildRun {
|
||||||
late Writer writer;
|
late Writer writer;
|
||||||
|
|
||||||
Set<Uri> analyzedUris = {};
|
Set<Uri> analyzedUris = {};
|
||||||
|
bool _didPrintWarning = false;
|
||||||
|
|
||||||
_DriftBuildRun(this.options, this.mode, this.buildStep)
|
_DriftBuildRun(this.options, this.mode, this.buildStep)
|
||||||
: driver = DriftAnalysisDriver(DriftBuildBackend(buildStep), options)
|
: driver = DriftAnalysisDriver(DriftBuildBackend(buildStep), options)
|
||||||
|
@ -152,6 +154,10 @@ class _DriftBuildRun {
|
||||||
await _generateModular(fileResult);
|
await _generateModular(fileResult);
|
||||||
}
|
}
|
||||||
await _emitCode();
|
await _emitCode();
|
||||||
|
|
||||||
|
if (_didPrintWarning && options.fatalWarnings) {
|
||||||
|
throw const FatalWarningException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<FileState> _analyze(Uri uri, {bool isEntrypoint = false}) async {
|
Future<FileState> _analyze(Uri uri, {bool isEntrypoint = false}) async {
|
||||||
|
@ -162,8 +168,11 @@ class _DriftBuildRun {
|
||||||
final printErrors =
|
final printErrors =
|
||||||
isEntrypoint || (mode.isMonolithic && analyzedUris.add(result.ownUri));
|
isEntrypoint || (mode.isMonolithic && analyzedUris.add(result.ownUri));
|
||||||
if (printErrors) {
|
if (printErrors) {
|
||||||
|
// Only printing errors from the fileAnalysis step here. The analyzer
|
||||||
|
// builder will print errors from earlier analysis steps.
|
||||||
for (final error in result.fileAnalysis?.analysisErrors ?? const []) {
|
for (final error in result.fileAnalysis?.analysisErrors ?? const []) {
|
||||||
log.warning(error);
|
log.warning(error);
|
||||||
|
_didPrintWarning = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
class FatalWarningException implements Exception {
|
||||||
|
const FatalWarningException();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'Drift emitted warnings and the `fatal_warnings` build option is '
|
||||||
|
'enabled.';
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,7 +32,8 @@ DriftOptions _$DriftOptionsFromJson(Map json) => $checkedCreate(
|
||||||
'scoped_dart_components',
|
'scoped_dart_components',
|
||||||
'store_date_time_values_as_text',
|
'store_date_time_values_as_text',
|
||||||
'case_from_dart_to_sql',
|
'case_from_dart_to_sql',
|
||||||
'write_to_columns_mixins'
|
'write_to_columns_mixins',
|
||||||
|
'fatal_warnings'
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
final val = DriftOptions(
|
final val = DriftOptions(
|
||||||
|
@ -86,6 +87,8 @@ DriftOptions _$DriftOptionsFromJson(Map json) => $checkedCreate(
|
||||||
CaseFromDartToSql.snake),
|
CaseFromDartToSql.snake),
|
||||||
writeToColumnsMixins: $checkedConvert(
|
writeToColumnsMixins: $checkedConvert(
|
||||||
'write_to_columns_mixins', (v) => v as bool? ?? false),
|
'write_to_columns_mixins', (v) => v as bool? ?? false),
|
||||||
|
fatalWarnings:
|
||||||
|
$checkedConvert('fatal_warnings', (v) => v as bool? ?? false),
|
||||||
dialect: $checkedConvert('sql',
|
dialect: $checkedConvert('sql',
|
||||||
(v) => v == null ? null : DialectOptions.fromJson(v as Map)),
|
(v) => v == null ? null : DialectOptions.fromJson(v as Map)),
|
||||||
);
|
);
|
||||||
|
@ -114,6 +117,7 @@ DriftOptions _$DriftOptionsFromJson(Map json) => $checkedCreate(
|
||||||
'storeDateTimeValuesAsText': 'store_date_time_values_as_text',
|
'storeDateTimeValuesAsText': 'store_date_time_values_as_text',
|
||||||
'caseFromDartToSql': 'case_from_dart_to_sql',
|
'caseFromDartToSql': 'case_from_dart_to_sql',
|
||||||
'writeToColumnsMixins': 'write_to_columns_mixins',
|
'writeToColumnsMixins': 'write_to_columns_mixins',
|
||||||
|
'fatalWarnings': 'fatal_warnings',
|
||||||
'dialect': 'sql'
|
'dialect': 'sql'
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -147,6 +151,7 @@ Map<String, dynamic> _$DriftOptionsToJson(DriftOptions instance) =>
|
||||||
'case_from_dart_to_sql':
|
'case_from_dart_to_sql':
|
||||||
_$CaseFromDartToSqlEnumMap[instance.caseFromDartToSql]!,
|
_$CaseFromDartToSqlEnumMap[instance.caseFromDartToSql]!,
|
||||||
'write_to_columns_mixins': instance.writeToColumnsMixins,
|
'write_to_columns_mixins': instance.writeToColumnsMixins,
|
||||||
|
'fatal_warnings': instance.fatalWarnings,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _$SqlModuleEnumMap = {
|
const _$SqlModuleEnumMap = {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:build/build.dart';
|
import 'package:build/build.dart';
|
||||||
import 'package:build_test/build_test.dart';
|
import 'package:build_test/build_test.dart';
|
||||||
|
import 'package:drift_dev/src/backends/build/exception.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:test/test.dart';
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
@ -380,4 +381,52 @@ q: SELECT 1;
|
||||||
)
|
)
|
||||||
}, result.dartOutputs, result);
|
}, result.dartOutputs, result);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('reports issues', () {
|
||||||
|
for (final fatalWarnings in [false, true]) {
|
||||||
|
group('fatalWarnings: $fatalWarnings', () {
|
||||||
|
final options = BuilderOptions(
|
||||||
|
{'fatal_warnings': fatalWarnings},
|
||||||
|
isRoot: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<void> runTest(String source, expectedMessage) async {
|
||||||
|
final build = emulateDriftBuild(
|
||||||
|
inputs: {'a|lib/a.drift': source},
|
||||||
|
logger: loggerThat(emits(isA<LogRecord>()
|
||||||
|
.having((e) => e.message, 'message', expectedMessage))),
|
||||||
|
modularBuild: true,
|
||||||
|
options: options,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (fatalWarnings) {
|
||||||
|
await expectLater(build, throwsA(isA<FatalWarningException>()));
|
||||||
|
} else {
|
||||||
|
await build;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('syntax', () async {
|
||||||
|
await runTest(
|
||||||
|
'foo: SELECT;', contains('Could not parse this expression'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('semantic in analysis', () async {
|
||||||
|
await runTest('''
|
||||||
|
CREATE TABLE foo (
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY,
|
||||||
|
unknown INTEGER NOT NULL REFERENCES another ("table")
|
||||||
|
);
|
||||||
|
''', contains('could not be found in any import.'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('file analysis', () async {
|
||||||
|
await runTest(
|
||||||
|
r'a($x = 2): SELECT 1, 2, 3 ORDER BY $x;',
|
||||||
|
contains('This placeholder has a default value, which is only '
|
||||||
|
'supported for expressions.'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue