Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(refactor) Pull out query method return type into own class #3

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions floor_generator/lib/misc/change_method_processor_helper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:floor_generator/misc/type_utils.dart';
import 'package:floor_generator/processor/error/change_method_processor_error.dart';
import 'package:floor_generator/value_object/entity.dart';
import 'package:source_gen/source_gen.dart';

Expand All @@ -10,11 +11,14 @@ class ChangeMethodProcessorHelper {
final MethodElement _methodElement;
final List<Entity> _entities;

const ChangeMethodProcessorHelper(
final ChangeMethodProcessorError processorError;

ChangeMethodProcessorHelper(
final MethodElement methodElement,
final List<Entity> entities,
) : _methodElement = methodElement,
_entities = entities;
_entities = entities,
processorError = ChangeMethodProcessorError(methodElement);

ParameterElement getParameterElement() {
final parameters = _methodElement.parameters;
Expand All @@ -32,7 +36,7 @@ class ChangeMethodProcessorHelper {
return parameters.first;
}

DartType getFlattenedParameterType(
DartType _getFlattenedParameterType(
final ParameterElement parameterElement,
) {
final changesMultipleItems = parameterElement.type.isDartCoreList;
Expand All @@ -42,13 +46,30 @@ class ChangeMethodProcessorHelper {
: parameterElement.type;
}

Entity getEntity(final DartType flattenedParameterType) {
Entity getEntity(final ParameterElement parameterElement) {
final flattenedParameterType = _getFlattenedParameterType(parameterElement);
return _entities.firstWhere(
(entity) =>
entity.classElement.displayName ==
entity.className ==
flattenedParameterType.getDisplayString(withNullability: false),
orElse: () => throw InvalidGenerationSourceError(
'You are trying to change an object which is not an entity.',
element: _methodElement));
}

DartType getFlattenedReturnType() {
return _methodElement.library.typeSystem.flatten(_methodElement.returnType);
}

void assertMethodReturnsFuture(String methodType) {
if (!_methodElement.returnType.isDartAsyncFuture) {
throw processorError.changeMustReturnIntOrVoidFuture(methodType);
}
}

void assertMethodReturnsIntOrVoid(String methodType, final DartType flat) {
if (!flat.isVoid && !flat.isDartCoreInt) {
throw processorError.changeMustReturnIntOrVoidFuture(methodType);
}
}
}
4 changes: 2 additions & 2 deletions floor_generator/lib/processor/dao_processor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ class DaoProcessor extends Processor<Dao> {
final transactionMethods = _getTransactionMethods(methods);

final streamQueryables = queryMethods
.where((method) => method.returnsStream)
.map((method) => method.queryable);
.where((method) => method.returnType.isStream)
.map((method) => method.returnType.queryable);
final streamEntities = streamQueryables.whereType<Entity>().toSet();
final streamViews = streamQueryables.whereType<View>().toSet();

Expand Down
61 changes: 10 additions & 51 deletions floor_generator/lib/processor/deletion_method_processor.dart
Original file line number Diff line number Diff line change
@@ -1,79 +1,38 @@
// ignore_for_file: import_of_legacy_library_into_null_safe
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:floor_generator/misc/change_method_processor_helper.dart';
import 'package:floor_generator/processor/processor.dart';
import 'package:floor_generator/value_object/deletion_method.dart';
import 'package:floor_generator/value_object/entity.dart';
import 'package:source_gen/source_gen.dart';

class DeletionMethodProcessor implements Processor<DeletionMethod> {
final MethodElement _methodElement;
final ChangeMethodProcessorHelper _helper;

DeletionMethodProcessor(
final MethodElement methodElement,
this._methodElement,
final List<Entity> entities, [
final ChangeMethodProcessorHelper? changeMethodProcessorHelper,
]) : _methodElement = methodElement,
_helper = changeMethodProcessorHelper ??
ChangeMethodProcessorHelper(methodElement, entities);
]) : _helper = changeMethodProcessorHelper ??
ChangeMethodProcessorHelper(_methodElement, entities);

@override
DeletionMethod process() {
final name = _methodElement.name;
final returnType = _methodElement.returnType;
_helper.assertMethodReturnsFuture('Deletion');

_assertMethodReturnsFuture(returnType);
final flattenedReturnType = _helper.getFlattenedReturnType();

final flattenedReturnType = _getFlattenedReturnType(returnType);
_assertMethodReturnsNoList(flattenedReturnType);

final returnsVoid = flattenedReturnType.isVoid;
final returnsInt = flattenedReturnType.isDartCoreInt;

if (!returnsVoid && !returnsInt) {
throw InvalidGenerationSourceError(
'Deletion methods have to return a Future of either void or int.',
element: _methodElement,
);
}
_helper.assertMethodReturnsIntOrVoid('Deletion', flattenedReturnType);

final parameterElement = _helper.getParameterElement();
final flattenedParameterType =
_helper.getFlattenedParameterType(parameterElement);

final entity = _helper.getEntity(flattenedParameterType);
final entity = _helper.getEntity(parameterElement);

return DeletionMethod(
_methodElement,
name,
returnType,
flattenedReturnType,
_methodElement.name,
_methodElement.returnType,
flattenedReturnType.isVoid,
parameterElement,
entity,
);
}

DartType _getFlattenedReturnType(final DartType returnType) {
return _methodElement.library.typeSystem.flatten(returnType);
}

void _assertMethodReturnsNoList(final DartType flattenedReturnType) {
if (flattenedReturnType.isDartCoreList) {
throw InvalidGenerationSourceError(
'Deletion methods have to return a Future of either void or int but not a list.',
element: _methodElement,
);
}
}

void _assertMethodReturnsFuture(final DartType returnType) {
if (!returnType.isDartAsyncFuture) {
throw InvalidGenerationSourceError(
'Deletion methods have to return a Future.',
element: _methodElement,
);
}
}
}
2 changes: 1 addition & 1 deletion floor_generator/lib/processor/entity_processor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class EntityProcessor extends QueryableProcessor<Entity> {
}

return Entity(
classElement,
classElement.displayName,
name,
fields,
_getPrimaryKey(fields),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import 'package:analyzer/dart/element/element.dart';
import 'package:floor_generator/processor/error/processor_error.dart';

class ChangeMethodProcessorError {
final MethodElement _methodElement;

const ChangeMethodProcessorError(final MethodElement methodElement)
: _methodElement = methodElement;

ProcessorError changeMustReturnIntOrVoidFuture(String type) {
return ProcessorError(
message: '$type methods have to return a Future of either void or int.',
todo:
'Give the method a return type of either `Future<void>` or `Future<int>`.',
element: _methodElement,
);
}

ProcessorError get insertMustReturnIntOrVoidFutureList {
return ProcessorError(
message:
'Insertion methods have to return a Future of either void or int or List<int>.',
todo:
'Give the method a return type of either `Future<void>`, `Future<int>` or `Future<List<int>>`.',
element: _methodElement,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ class QueryMethodProcessorError {
);
}

InvalidGenerationSourceError get doesNotReturnFutureVoid {
return InvalidGenerationSourceError(
'A query returning `void` has to return exactly `Future<void>`.',
todo:
'Define the return type as `Future<void>` or return a non-empty value.',
element: _methodElement,
);
}

ProcessorError get doesNotReturnNullableStream {
return ProcessorError(
message: 'Queries returning streams of single elements might emit null.',
Expand Down
75 changes: 26 additions & 49 deletions floor_generator/lib/processor/insertion_method_processor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,66 +17,32 @@ class InsertionMethodProcessor implements Processor<InsertionMethod> {
final ChangeMethodProcessorHelper _helper;

InsertionMethodProcessor(
final MethodElement methodElement,
this._methodElement,
final List<Entity> entities, [
final ChangeMethodProcessorHelper? changeMethodProcessorHelper,
]) : _methodElement = methodElement,
_helper = changeMethodProcessorHelper ??
ChangeMethodProcessorHelper(methodElement, entities);
]) : _helper = changeMethodProcessorHelper ??
ChangeMethodProcessorHelper(_methodElement, entities);

@override
InsertionMethod process() {
final name = _methodElement.name;
final returnType = _methodElement.returnType;
_assertMethodReturnsFuture();

_assertMethodReturnsFuture(returnType);

final returnsList = _getReturnsList(returnType);
final flattenedReturnType =
_getFlattenedReturnType(returnType, returnsList);

final returnsVoid = flattenedReturnType.isVoid;
final returnsInt = flattenedReturnType.isDartCoreInt;
final returnsIntList = returnsList && flattenedReturnType.isDartCoreInt;

if (!returnsVoid && !returnsIntList && !returnsInt) {
throw InvalidGenerationSourceError(
'Insertion methods have to return a Future of either void, int or List<int>.',
element: _methodElement,
);
}
final flattenedReturnType = _getAndCheckFlatReturnType();

final parameterElement = _helper.getParameterElement();
final flattenedParameterType =
_helper.getFlattenedParameterType(parameterElement);

final entity = _helper.getEntity(flattenedParameterType);
final entity = _helper.getEntity(parameterElement);
final onConflict = _getOnConflictStrategy();

return InsertionMethod(
_methodElement,
name,
returnType,
flattenedReturnType,
_methodElement.name,
_methodElement.returnType,
flattenedReturnType.isVoid,
parameterElement,
entity,
onConflict,
);
}

bool _getReturnsList(final DartType returnType) {
final type = _methodElement.library.typeSystem.flatten(returnType);
return type.isDartCoreList;
}

DartType _getFlattenedReturnType(
final DartType returnType,
final bool returnsList,
) {
final type = _methodElement.library.typeSystem.flatten(returnType);
return returnsList ? type.flatten() : type;
}

String _getOnConflictStrategy() {
final onConflictStrategy = _methodElement
.getAnnotation(annotations.Insert)
Expand All @@ -93,12 +59,23 @@ class InsertionMethodProcessor implements Processor<InsertionMethod> {
}
}

void _assertMethodReturnsFuture(final DartType returnType) {
if (!returnType.isDartAsyncFuture) {
throw InvalidGenerationSourceError(
'Insertion methods have to return a Future.',
element: _methodElement,
);
void _assertMethodReturnsFuture() {
if (!_methodElement.returnType.isDartAsyncFuture) {
throw _helper.processorError.insertMustReturnIntOrVoidFutureList;
}
}

DartType _getAndCheckFlatReturnType() {
DartType flattened = _helper.getFlattenedReturnType();
if (flattened.isVoid || flattened.isDartCoreInt) {
return flattened;
}
if (flattened.isDartCoreList) {
flattened = flattened.flatten();
if (flattened.isDartCoreInt) {
return flattened;
}
}
throw _helper.processorError.insertMustReturnIntOrVoidFutureList;
}
}
Loading