diff --git a/floor_generator/lib/processor/entity_processor.dart b/floor_generator/lib/processor/entity_processor.dart index 4fd0090d..ce2016d3 100644 --- a/floor_generator/lib/processor/entity_processor.dart +++ b/floor_generator/lib/processor/entity_processor.dart @@ -222,28 +222,40 @@ class EntityProcessor extends Processor { @nonNull String _getConstructor(final List fields) { - final columnNames = fields.map((field) => field.columnName).toList(); final constructorParameters = _classElement.constructors.first.parameters; + final parameterValues = constructorParameters + .map((parameterElement) => _getParameterValue(parameterElement, fields)) + .where((parameterValue) => parameterValue != null) + .join(', '); - final parameterValues = []; + return '${_classElement.displayName}($parameterValues)'; + } - for (var i = 0; i < constructorParameters.length; i++) { - final parameterValue = "row['${columnNames[i]}']"; - final constructorParameter = constructorParameters[i]; + /// Returns `null` whenever field is @ignored + @nullable + String _getParameterValue( + final ParameterElement parameterElement, + final List fields, + ) { + final parameterName = parameterElement.displayName; + final field = fields.firstWhere( + (field) => field.name == parameterName, + orElse: () => null, // whenever field is @ignored + ); + if (field != null) { + final parameterValue = "row['${field.columnName}']"; final castedParameterValue = - _castParameterValue(constructorParameter.type, parameterValue); - - if (castedParameterValue == null) { - throw _processorError.parameterTypeNotSupported(constructorParameter); + _castParameterValue(parameterElement.type, parameterValue); + if (parameterElement.isNamed) { + return '$parameterName: $castedParameterValue'; } - - parameterValues.add(castedParameterValue); + return castedParameterValue; // also covers positional parameter + } else { + return null; } - - return '${_classElement.displayName}(${parameterValues.join(', ')})'; } - @nullable + @nonNull String _castParameterValue( final DartType parameterType, final String parameterValue, @@ -254,10 +266,8 @@ class EntityProcessor extends Processor { return '$parameterValue as String'; } else if (parameterType.isDartCoreInt) { return '$parameterValue as int'; - } else if (parameterType.isDartCoreDouble) { - return '$parameterValue as double'; } else { - return null; + return '$parameterValue as double'; // must be double } } } diff --git a/floor_generator/lib/processor/error/entity_processor_error.dart b/floor_generator/lib/processor/error/entity_processor_error.dart index e14f6ca7..f2428473 100644 --- a/floor_generator/lib/processor/error/entity_processor_error.dart +++ b/floor_generator/lib/processor/error/entity_processor_error.dart @@ -40,16 +40,19 @@ class EntityProcessorError { // ignore: non_constant_identifier_names InvalidGenerationSourceError get FOREIGN_KEY_DOES_NOT_REFERENCE_ENTITY { return InvalidGenerationSourceError( - "The foreign key doesn't reference an entity class.", - todo: 'Make sure to add an entity to the foreign key. ', - element: _classElement); + "The foreign key doesn't reference an entity class.", + todo: 'Make sure to add an entity to the foreign key. ', + element: _classElement, + ); } // ignore: non_constant_identifier_names InvalidGenerationSourceError get FOREIGN_KEY_NO_ENTITY { - return InvalidGenerationSourceError('No entity defined for foreign key', - todo: 'Make sure to add an entity to the foreign key. ', - element: _classElement); + return InvalidGenerationSourceError( + 'No entity defined for foreign key', + todo: 'Make sure to add an entity to the foreign key. ', + element: _classElement, + ); } // ignore: non_constant_identifier_names @@ -62,16 +65,6 @@ class EntityProcessorError { ); } - InvalidGenerationSourceError parameterTypeNotSupported( - final ParameterElement parameterElement, - ) { - return InvalidGenerationSourceError( - 'The given constrcutor parameter type is not supported.', - todo: 'Make sure to only use bool, String, int and double types.', - element: parameterElement, - ); - } - InvalidGenerationSourceError noMatchingColumn( final List columnNames, ) { diff --git a/floor_generator/test/processor/entity_processor_test.dart b/floor_generator/test/processor/entity_processor_test.dart index d51794e4..9019566b 100644 --- a/floor_generator/test/processor/entity_processor_test.dart +++ b/floor_generator/test/processor/entity_processor_test.dart @@ -120,6 +120,115 @@ void main() { expect(actual.fields.length, equals(2)); }); + group('Constructors', () { + test('generate simple constructor', () async { + final classElement = await _createClassElement(''' + @entity + class Person { + @primaryKey + final int id; + + final String name; + + Person(this.id, this.name); + } + '''); + + final actual = EntityProcessor(classElement).process().constructor; + + const expected = "Person(row['id'] as int, row['name'] as String)"; + expect(actual, equals(expected)); + }); + + test('generate constructor with named argument', () async { + final classElement = await _createClassElement(''' + @entity + class Person { + @primaryKey + final int id; + + final String name; + + final String bar; + + Person(this.id, this.name, {this.bar}); + } + '''); + + final actual = EntityProcessor(classElement).process().constructor; + + const expected = + "Person(row['id'] as int, row['name'] as String, bar: row['bar'] as String)"; + expect(actual, equals(expected)); + }); + + test('generate constructor with named arguments', () async { + final classElement = await _createClassElement(''' + @entity + class Person { + @primaryKey + final int id; + + final String name; + + final String bar; + + Person({this.id, this.name, this.bar}); + } + '''); + + final actual = EntityProcessor(classElement).process().constructor; + + const expected = + "Person(id: row['id'] as int, name: row['name'] as String, bar: row['bar'] as String)"; + expect(actual, equals(expected)); + }); + + test('generate constructor with optional argument', () async { + final classElement = await _createClassElement(''' + @entity + class Person { + @primaryKey + final int id; + + final String name; + + final String bar; + + Person(this.id, this.name, [this.bar]); + } + '''); + + final actual = EntityProcessor(classElement).process().constructor; + + const expected = + "Person(row['id'] as int, row['name'] as String, row['bar'] as String)"; + expect(actual, equals(expected)); + }); + + test('generate constructor with optional arguments', () async { + final classElement = await _createClassElement(''' + @entity + class Person { + @primaryKey + final int id; + + final String name; + + final String bar; + + Person([this.id, this.name, this.bar]); + } + '''); + + final actual = EntityProcessor(classElement).process().constructor; + + const expected = + "Person(row['id'] as int, row['name'] as String, row['bar'] as String)"; + expect(actual, equals(expected)); + }); + }); + group('foreign keys', () { test('foreign key holds correct values', () async { final classElements = await _createClassElements('''