Don't use the MoorGenerator as a god class

This commit is contained in:
Simon Binder 2019-06-29 15:34:27 +02:00
parent 53d57d6a96
commit 7becfdcb85
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
8 changed files with 52 additions and 58 deletions

View File

@ -11,5 +11,5 @@ Builder moorBuilder(BuilderOptions options) {
final parsedOptions = MoorOptions(writeFromString); final parsedOptions = MoorOptions(writeFromString);
final state = SharedState(parsedOptions); final state = SharedState(parsedOptions);
return SharedPartBuilder([MoorGenerator(state), DaoGenerator()], 'moor'); return SharedPartBuilder([MoorGenerator(state), DaoGenerator(state)], 'moor');
} }

View File

@ -1,11 +1,16 @@
import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart'; import 'package:build/build.dart';
import 'package:moor_generator/src/shared_state.dart';
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
import 'package:moor/moor.dart'; import 'package:moor/moor.dart';
import 'package:moor_generator/src/model/specified_table.dart'; import 'package:moor_generator/src/model/specified_table.dart';
import 'package:source_gen/source_gen.dart'; import 'package:source_gen/source_gen.dart';
class DaoGenerator extends GeneratorForAnnotation<UseDao> { class DaoGenerator extends GeneratorForAnnotation<UseDao> {
final SharedState state;
DaoGenerator(this.state);
@override @override
generateForAnnotatedElement( generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) { Element element, ConstantReader annotation, BuildStep buildStep) {

View File

@ -1,14 +1,10 @@
import 'package:moor/moor.dart'; import 'package:moor/moor.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/src/dart/analysis/results.dart'; // ignore: implementation_imports
import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/element.dart';
import 'package:build/build.dart'; import 'package:build/build.dart';
import 'package:moor_generator/src/errors.dart'; import 'package:moor_generator/src/errors.dart';
import 'package:moor_generator/src/model/specified_database.dart'; import 'package:moor_generator/src/model/specified_database.dart';
import 'package:moor_generator/src/model/specified_table.dart'; import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/options.dart'; import 'package:moor_generator/src/options.dart';
import 'package:moor_generator/src/parser/column_parser.dart';
import 'package:moor_generator/src/parser/table_parser.dart';
import 'package:moor_generator/src/shared_state.dart'; import 'package:moor_generator/src/shared_state.dart';
import 'package:moor_generator/src/writer/database_writer.dart'; import 'package:moor_generator/src/writer/database_writer.dart';
import 'package:source_gen/source_gen.dart'; import 'package:source_gen/source_gen.dart';
@ -22,16 +18,6 @@ class MoorGenerator extends GeneratorForAnnotation<UseMoor> {
MoorGenerator(this.state); MoorGenerator(this.state);
ElementDeclarationResult loadElementDeclaration(Element element) {
/*final result = _astForLibs.putIfAbsent(element.library.name, () {
// ignore: deprecated_member_use
return ParsedLibraryResultImpl.tmp(element.library);
});*/
// ignore: deprecated_member_use
final result = ParsedLibraryResultImpl.tmp(element.library);
return result.getElementDeclaration(element);
}
@override @override
generateForAnnotatedElement( generateForAnnotatedElement(
Element element, ConstantReader annotation, BuildStep buildStep) { Element element, ConstantReader annotation, BuildStep buildStep) {
@ -44,9 +30,6 @@ class MoorGenerator extends GeneratorForAnnotation<UseMoor> {
.toList(); .toList();
final queries = annotation.peek('queries')?.listValue ?? []; final queries = annotation.peek('queries')?.listValue ?? [];
state.tableParser ??= TableParser(this);
state.columnParser ??= ColumnParser(this);
final tablesForThisDb = <SpecifiedTable>[]; final tablesForThisDb = <SpecifiedTable>[];
var resolvedQueries = <SqlQuery>[]; var resolvedQueries = <SqlQuery>[];

View File

@ -3,7 +3,7 @@ import 'package:analyzer/dart/element/element.dart';
import 'package:moor_generator/src/errors.dart'; import 'package:moor_generator/src/errors.dart';
import 'package:moor_generator/src/model/specified_column.dart'; import 'package:moor_generator/src/model/specified_column.dart';
import 'package:moor_generator/src/parser/parser.dart'; import 'package:moor_generator/src/parser/parser.dart';
import 'package:moor_generator/src/moor_generator.dart'; import 'package:moor_generator/src/shared_state.dart';
import 'package:moor_generator/src/utils/type_utils.dart'; import 'package:moor_generator/src/utils/type_utils.dart';
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
@ -37,7 +37,7 @@ const String _errorMessage = 'This getter does not create a valid column that '
'columns are formed. If you have any questions, feel free to raise an issue.'; 'columns are formed. If you have any questions, feel free to raise an issue.';
class ColumnParser extends ParserBase { class ColumnParser extends ParserBase {
ColumnParser(MoorGenerator generator) : super(generator); ColumnParser(SharedState state) : super(state);
SpecifiedColumn parse(MethodDeclaration getter, Element getterElement) { SpecifiedColumn parse(MethodDeclaration getter, Element getterElement) {
/* /*
@ -52,7 +52,7 @@ class ColumnParser extends ParserBase {
final expr = returnExpressionOfMethod(getter); final expr = returnExpressionOfMethod(getter);
if (!(expr is FunctionExpressionInvocation)) { if (!(expr is FunctionExpressionInvocation)) {
generator.state.errors.add(MoorError( state.errors.add(MoorError(
affectedElement: getter.declaredElement, affectedElement: getter.declaredElement,
message: _errorMessage, message: _errorMessage,
critical: true, critical: true,
@ -84,7 +84,7 @@ class ColumnParser extends ParserBase {
switch (methodName) { switch (methodName) {
case _methodNamed: case _methodNamed:
if (foundExplicitName != null) { if (foundExplicitName != null) {
generator.state.errors.add( state.errors.add(
MoorError( MoorError(
critical: false, critical: false,
affectedElement: getter.declaredElement, affectedElement: getter.declaredElement,
@ -97,7 +97,7 @@ class ColumnParser extends ParserBase {
foundExplicitName = foundExplicitName =
readStringLiteral(remainingExpr.argumentList.arguments.first, () { readStringLiteral(remainingExpr.argumentList.arguments.first, () {
generator.state.errors.add( state.errors.add(
MoorError( MoorError(
critical: false, critical: false,
affectedElement: getter.declaredElement, affectedElement: getter.declaredElement,
@ -133,7 +133,7 @@ class ColumnParser extends ParserBase {
case _methodCustomConstraint: case _methodCustomConstraint:
foundCustomConstraint = foundCustomConstraint =
readStringLiteral(remainingExpr.argumentList.arguments.first, () { readStringLiteral(remainingExpr.argumentList.arguments.first, () {
generator.state.errors.add( state.errors.add(
MoorError( MoorError(
critical: false, critical: false,
affectedElement: getter.declaredElement, affectedElement: getter.declaredElement,

View File

@ -1,7 +1,7 @@
import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/ast.dart';
import 'package:moor_generator/src/errors.dart'; import 'package:moor_generator/src/errors.dart';
import 'package:moor_generator/src/model/specified_table.dart'; import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/moor_generator.dart'; import 'package:moor_generator/src/shared_state.dart';
class Parser { class Parser {
List<SpecifiedTable> specifiedTables; List<SpecifiedTable> specifiedTables;
@ -10,15 +10,15 @@ class Parser {
} }
class ParserBase { class ParserBase {
final MoorGenerator generator; final SharedState state;
ParserBase(this.generator); ParserBase(this.state);
Expression returnExpressionOfMethod(MethodDeclaration method) { Expression returnExpressionOfMethod(MethodDeclaration method) {
final body = method.body; final body = method.body;
if (!(body is ExpressionFunctionBody)) { if (!(body is ExpressionFunctionBody)) {
generator.state.errors.add(MoorError( state.errors.add(MoorError(
affectedElement: method.declaredElement, affectedElement: method.declaredElement,
critical: true, critical: true,
message: message:

View File

@ -4,14 +4,14 @@ import 'package:moor_generator/src/errors.dart';
import 'package:moor_generator/src/model/specified_column.dart'; import 'package:moor_generator/src/model/specified_column.dart';
import 'package:moor_generator/src/model/specified_table.dart'; import 'package:moor_generator/src/model/specified_table.dart';
import 'package:moor_generator/src/parser/parser.dart'; import 'package:moor_generator/src/parser/parser.dart';
import 'package:moor_generator/src/shared_state.dart';
import 'package:moor_generator/src/utils/names.dart'; import 'package:moor_generator/src/utils/names.dart';
import 'package:moor_generator/src/utils/type_utils.dart'; import 'package:moor_generator/src/utils/type_utils.dart';
import 'package:moor_generator/src/moor_generator.dart'; // ignore: implementation_imports
import 'package:recase/recase.dart'; import 'package:recase/recase.dart';
import 'package:moor/sqlite_keywords.dart'; import 'package:moor/sqlite_keywords.dart';
class TableParser extends ParserBase { class TableParser extends ParserBase {
TableParser(MoorGenerator generator) : super(generator); TableParser(SharedState state) : super(state);
SpecifiedTable parse(ClassElement element) { SpecifiedTable parse(ClassElement element) {
final sqlName = _parseTableName(element); final sqlName = _parseTableName(element);
@ -52,13 +52,12 @@ class TableParser extends ParserBase {
// we expect something like get tableName => "myTableName", the getter // we expect something like get tableName => "myTableName", the getter
// must do nothing more complicated // must do nothing more complicated
final tableNameDeclaration = final tableNameDeclaration = state.loadElementDeclaration(tableNameGetter);
generator.loadElementDeclaration(tableNameGetter);
final returnExpr = returnExpressionOfMethod( final returnExpr = returnExpressionOfMethod(
tableNameDeclaration.node as MethodDeclaration); tableNameDeclaration.node as MethodDeclaration);
final tableName = readStringLiteral(returnExpr, () { final tableName = readStringLiteral(returnExpr, () {
generator.state.errors.add(MoorError( state.errors.add(MoorError(
critical: true, critical: true,
message: message:
'This getter must return a string literal, and do nothing more', 'This getter must return a string literal, and do nothing more',
@ -75,11 +74,11 @@ class TableParser extends ParserBase {
return null; return null;
} }
final ast = generator.loadElementDeclaration(primaryKeyGetter).node final ast = state.loadElementDeclaration(primaryKeyGetter).node
as MethodDeclaration; as MethodDeclaration;
final body = ast.body; final body = ast.body;
if (body is! ExpressionFunctionBody) { if (body is! ExpressionFunctionBody) {
generator.state.errors.add(MoorError( state.errors.add(MoorError(
affectedElement: primaryKeyGetter, affectedElement: primaryKeyGetter,
message: 'This must return a set literal using the => syntax!')); message: 'This must return a set literal using the => syntax!'));
return null; return null;
@ -103,7 +102,7 @@ class TableParser extends ParserBase {
} }
} }
} else { } else {
generator.state.errors.add(MoorError( state.errors.add(MoorError(
affectedElement: primaryKeyGetter, affectedElement: primaryKeyGetter,
message: 'This must return a set literal!')); message: 'This must return a set literal!'));
} }
@ -115,10 +114,10 @@ class TableParser extends ParserBase {
return element.fields return element.fields
.where((field) => isColumn(field.type) && field.getter != null) .where((field) => isColumn(field.type) && field.getter != null)
.map((field) { .map((field) {
final node = generator.loadElementDeclaration(field.getter).node final node =
as MethodDeclaration; state.loadElementDeclaration(field.getter).node as MethodDeclaration;
return generator.state.columnParser.parse(node, field.getter); return state.columnParser.parse(node, field.getter);
}).toList(); }).toList();
} }
} }

View File

@ -1,4 +1,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart'; import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/src/dart/analysis/results.dart'; // ignore: implementation_imports
import 'package:moor/moor.dart' show Table; import 'package:moor/moor.dart' show Table;
import 'package:moor_generator/src/parser/column_parser.dart'; import 'package:moor_generator/src/parser/column_parser.dart';
import 'package:moor_generator/src/parser/table_parser.dart'; import 'package:moor_generator/src/parser/table_parser.dart';
@ -21,5 +24,14 @@ class SharedState {
final Map<DartType, SpecifiedTable> foundTables = {}; final Map<DartType, SpecifiedTable> foundTables = {};
SharedState(this.options); SharedState(this.options) {
tableParser = TableParser(this);
columnParser = ColumnParser(this);
}
ElementDeclarationResult loadElementDeclaration(Element element) {
// ignore: deprecated_member_use
final result = ParsedLibraryResultImpl.tmp(element.library);
return result.getElementDeclaration(element);
}
} }

View File

@ -3,14 +3,12 @@ import 'package:moor_generator/src/model/specified_column.dart';
import 'package:moor_generator/src/options.dart'; import 'package:moor_generator/src/options.dart';
import 'package:moor_generator/src/parser/column_parser.dart'; import 'package:moor_generator/src/parser/column_parser.dart';
import 'package:moor_generator/src/parser/table_parser.dart'; import 'package:moor_generator/src/parser/table_parser.dart';
import 'package:moor_generator/src/moor_generator.dart';
import 'package:moor_generator/src/shared_state.dart'; import 'package:moor_generator/src/shared_state.dart';
import 'package:test_api/test_api.dart'; import 'package:test_api/test_api.dart';
import 'package:build_test/build_test.dart'; import 'package:build_test/build_test.dart';
void main() async { void main() async {
LibraryElement testLib; LibraryElement testLib;
MoorGenerator generator;
SharedState state; SharedState state;
setUpAll(() async { setUpAll(() async {
@ -53,29 +51,27 @@ void main() async {
}); });
setUp(() { setUp(() {
state = SharedState(const MoorOptions.defaults()); state = SharedState(const MoorOptions.defaults())
generator = MoorGenerator(state); ..columnParser = ColumnParser(state)
state ..tableParser = TableParser(state);
..columnParser = ColumnParser(generator)
..tableParser = TableParser(generator);
}); });
group('SQL table name', () { group('SQL table name', () {
test('should parse correctly when valid', () { test('should parse correctly when valid', () {
expect( expect(
TableParser(generator) TableParser(state)
.parse(testLib.getType('TableWithCustomName')) .parse(testLib.getType('TableWithCustomName'))
.sqlName, .sqlName,
equals('my-fancy-table')); equals('my-fancy-table'));
}); });
test('should use class name if table name is not specified', () { test('should use class name if table name is not specified', () {
expect(TableParser(generator).parse(testLib.getType('Users')).sqlName, expect(TableParser(state).parse(testLib.getType('Users')).sqlName,
equals('users')); equals('users'));
}); });
test('should not parse for complex methods', () async { test('should not parse for complex methods', () async {
TableParser(generator).parse(testLib.getType('WrongName')); TableParser(state).parse(testLib.getType('WrongName'));
expect(state.errors.errors, isNotEmpty); expect(state.errors.errors, isNotEmpty);
}); });
@ -83,7 +79,7 @@ void main() async {
group('Columns', () { group('Columns', () {
test('should use field name if no name has been set explicitely', () { test('should use field name if no name has been set explicitely', () {
final table = TableParser(generator).parse(testLib.getType('Users')); final table = TableParser(state).parse(testLib.getType('Users'));
final idColumn = final idColumn =
table.columns.singleWhere((col) => col.name.name == 'id'); table.columns.singleWhere((col) => col.name.name == 'id');
@ -91,7 +87,7 @@ void main() async {
}); });
test('should use explicit name, if it exists', () { test('should use explicit name, if it exists', () {
final table = TableParser(generator).parse(testLib.getType('Users')); final table = TableParser(state).parse(testLib.getType('Users'));
final idColumn = final idColumn =
table.columns.singleWhere((col) => col.name.name == 'user_name'); table.columns.singleWhere((col) => col.name.name == 'user_name');
@ -99,7 +95,7 @@ void main() async {
}); });
test('should parse min and max length for text columns', () { test('should parse min and max length for text columns', () {
final table = TableParser(generator).parse(testLib.getType('Users')); final table = TableParser(state).parse(testLib.getType('Users'));
final idColumn = final idColumn =
table.columns.singleWhere((col) => col.name.name == 'user_name'); table.columns.singleWhere((col) => col.name.name == 'user_name');
@ -108,7 +104,7 @@ void main() async {
}); });
test('should only parse max length when relevant', () { test('should only parse max length when relevant', () {
final table = TableParser(generator).parse(testLib.getType('Users')); final table = TableParser(state).parse(testLib.getType('Users'));
final idColumn = final idColumn =
table.columns.singleWhere((col) => col.dartGetterName == 'onlyMax'); table.columns.singleWhere((col) => col.dartGetterName == 'onlyMax');
@ -118,7 +114,7 @@ void main() async {
test('parses custom constraints', () { test('parses custom constraints', () {
final table = final table =
TableParser(generator).parse(testLib.getType('CustomPrimaryKey')); TableParser(state).parse(testLib.getType('CustomPrimaryKey'));
final partA = final partA =
table.columns.singleWhere((c) => c.dartGetterName == 'partA'); table.columns.singleWhere((c) => c.dartGetterName == 'partA');
@ -130,7 +126,7 @@ void main() async {
}); });
test('parsed default values', () { test('parsed default values', () {
final table = TableParser(generator).parse(testLib.getType('Users')); final table = TableParser(state).parse(testLib.getType('Users'));
final defaultsColumn = final defaultsColumn =
table.columns.singleWhere((c) => c.name.name == 'defaults'); table.columns.singleWhere((c) => c.name.name == 'defaults');
@ -139,8 +135,7 @@ void main() async {
}); });
test('parses custom primary keys', () { test('parses custom primary keys', () {
final table = final table = TableParser(state).parse(testLib.getType('CustomPrimaryKey'));
TableParser(generator).parse(testLib.getType('CustomPrimaryKey'));
expect(table.primaryKey, containsAll(table.columns)); expect(table.primaryKey, containsAll(table.columns));
expect(table.columns.any((column) => column.hasAI), isFalse); expect(table.columns.any((column) => column.hasAI), isFalse);