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`).
|
||||
* `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.
|
||||
* `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
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ targets:
|
|||
write_from_json_string_constructor: true
|
||||
raw_result_set_data: true
|
||||
named_parameters: true
|
||||
fatal_warnings: true
|
||||
sql:
|
||||
dialect: sqlite
|
||||
options:
|
||||
|
@ -33,6 +34,7 @@ targets:
|
|||
builders:
|
||||
drift_dev:
|
||||
options:
|
||||
fatal_warnings: true
|
||||
store_date_time_values_as_text: true
|
||||
# Dart doesn't support YAML merge tags yet, https://github.com/dart-lang/yaml/issues/121
|
||||
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.
|
||||
// Do not manually edit this file.
|
||||
|
||||
// @dart=2.19
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:async' as _i4;
|
||||
|
||||
|
|
|
@ -102,6 +102,9 @@ class DriftOptions {
|
|||
@JsonKey(name: 'write_to_columns_mixins', defaultValue: false)
|
||||
final bool writeToColumnsMixins;
|
||||
|
||||
@JsonKey(name: 'fatal_warnings', defaultValue: false)
|
||||
final bool fatalWarnings;
|
||||
|
||||
@internal
|
||||
const DriftOptions.defaults({
|
||||
this.generateFromJsonStringConstructor = false,
|
||||
|
@ -124,6 +127,7 @@ class DriftOptions {
|
|||
this.dialect = const DialectOptions(SqlDialect.sqlite, null),
|
||||
this.caseFromDartToSql = CaseFromDartToSql.snake,
|
||||
this.writeToColumnsMixins = false,
|
||||
this.fatalWarnings = false,
|
||||
});
|
||||
|
||||
DriftOptions({
|
||||
|
@ -146,6 +150,7 @@ class DriftOptions {
|
|||
required this.storeDateTimeValuesAsText,
|
||||
required this.caseFromDartToSql,
|
||||
required this.writeToColumnsMixins,
|
||||
required this.fatalWarnings,
|
||||
this.dialect,
|
||||
}) {
|
||||
// ignore: deprecated_member_use_from_same_package
|
||||
|
|
|
@ -9,6 +9,7 @@ import '../../analysis/options.dart';
|
|||
import '../../writer/import_manager.dart';
|
||||
import '../../writer/writer.dart';
|
||||
import 'backend.dart';
|
||||
import 'exception.dart';
|
||||
|
||||
class DriftAnalyzer extends Builder {
|
||||
final DriftOptions options;
|
||||
|
@ -34,15 +35,18 @@ class DriftAnalyzer extends Builder {
|
|||
final driver = DriftAnalysisDriver(backend, options);
|
||||
|
||||
final results = await driver.resolveElements(buildStep.inputId.uri);
|
||||
var hadWarnings = false;
|
||||
|
||||
for (final parseError in results.errorsDuringDiscovery) {
|
||||
log.warning(parseError.toString());
|
||||
hadWarnings = true;
|
||||
}
|
||||
|
||||
if (results.analysis.isNotEmpty) {
|
||||
for (final result in results.analysis.values) {
|
||||
for (final error in result.errorsDuringAnalysis) {
|
||||
log.warning(error.toString());
|
||||
hadWarnings = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,6 +90,10 @@ class DriftAnalyzer extends Builder {
|
|||
await buildStep.writeAsString(typesOutput, writer.writeGenerated());
|
||||
}
|
||||
}
|
||||
|
||||
if (hadWarnings && options.fatalWarnings) {
|
||||
throw const FatalWarningException();
|
||||
}
|
||||
}
|
||||
|
||||
static final _languageVersionForGeneralizedTypedefs = LanguageVersion(2, 13);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:build/build.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 '../../analysis/custom_result_class.dart';
|
||||
|
@ -14,9 +13,11 @@ import '../../writer/drift_accessor_writer.dart';
|
|||
import '../../writer/function_stubs_writer.dart';
|
||||
import '../../writer/import_manager.dart';
|
||||
import '../../writer/modules.dart';
|
||||
import '../../writer/tables/table_writer.dart';
|
||||
import '../../writer/tables/view_writer.dart';
|
||||
import '../../writer/writer.dart';
|
||||
import 'backend.dart';
|
||||
import 'exception.dart';
|
||||
|
||||
class _BuilderFlags {
|
||||
bool didWarnAboutDeprecatedOptions = false;
|
||||
|
@ -125,6 +126,7 @@ class _DriftBuildRun {
|
|||
late Writer writer;
|
||||
|
||||
Set<Uri> analyzedUris = {};
|
||||
bool _didPrintWarning = false;
|
||||
|
||||
_DriftBuildRun(this.options, this.mode, this.buildStep)
|
||||
: driver = DriftAnalysisDriver(DriftBuildBackend(buildStep), options)
|
||||
|
@ -152,6 +154,10 @@ class _DriftBuildRun {
|
|||
await _generateModular(fileResult);
|
||||
}
|
||||
await _emitCode();
|
||||
|
||||
if (_didPrintWarning && options.fatalWarnings) {
|
||||
throw const FatalWarningException();
|
||||
}
|
||||
}
|
||||
|
||||
Future<FileState> _analyze(Uri uri, {bool isEntrypoint = false}) async {
|
||||
|
@ -162,8 +168,11 @@ class _DriftBuildRun {
|
|||
final printErrors =
|
||||
isEntrypoint || (mode.isMonolithic && analyzedUris.add(result.ownUri));
|
||||
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 []) {
|
||||
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',
|
||||
'store_date_time_values_as_text',
|
||||
'case_from_dart_to_sql',
|
||||
'write_to_columns_mixins'
|
||||
'write_to_columns_mixins',
|
||||
'fatal_warnings'
|
||||
],
|
||||
);
|
||||
final val = DriftOptions(
|
||||
|
@ -86,6 +87,8 @@ DriftOptions _$DriftOptionsFromJson(Map json) => $checkedCreate(
|
|||
CaseFromDartToSql.snake),
|
||||
writeToColumnsMixins: $checkedConvert(
|
||||
'write_to_columns_mixins', (v) => v as bool? ?? false),
|
||||
fatalWarnings:
|
||||
$checkedConvert('fatal_warnings', (v) => v as bool? ?? false),
|
||||
dialect: $checkedConvert('sql',
|
||||
(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',
|
||||
'caseFromDartToSql': 'case_from_dart_to_sql',
|
||||
'writeToColumnsMixins': 'write_to_columns_mixins',
|
||||
'fatalWarnings': 'fatal_warnings',
|
||||
'dialect': 'sql'
|
||||
},
|
||||
);
|
||||
|
@ -147,6 +151,7 @@ Map<String, dynamic> _$DriftOptionsToJson(DriftOptions instance) =>
|
|||
'case_from_dart_to_sql':
|
||||
_$CaseFromDartToSqlEnumMap[instance.caseFromDartToSql]!,
|
||||
'write_to_columns_mixins': instance.writeToColumnsMixins,
|
||||
'fatal_warnings': instance.fatalWarnings,
|
||||
};
|
||||
|
||||
const _$SqlModuleEnumMap = {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:build/build.dart';
|
||||
import 'package:build_test/build_test.dart';
|
||||
import 'package:drift_dev/src/backends/build/exception.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
|
@ -380,4 +381,52 @@ q: SELECT 1;
|
|||
)
|
||||
}, 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