diff --git a/src/lib/exceptions/field_parse_exception.dart b/src/lib/exceptions/field_parse_exception.dart new file mode 100644 index 0000000..0e22a6f --- /dev/null +++ b/src/lib/exceptions/field_parse_exception.dart @@ -0,0 +1,22 @@ +class FieldParseException implements Exception { + dynamic inner; + + String fieldName; + + String message; + + StackTrace trace; + + FieldParseException(this.fieldName, this.inner, this.trace, {this.message}); + + String toString() { + StringBuffer stringBuffer = StringBuffer(); + stringBuffer.writeln('Exception while parsing field: $fieldName!'); + if (message != null) { + stringBuffer.writeln("Message: $message"); + } + stringBuffer.writeln(inner); + stringBuffer.writeln(trace); + return stringBuffer.toString(); + } +} diff --git a/src/lib/generator/emitted_entity.dart b/src/lib/generator/emitted_entity.dart index 2aa93ce..dbafdfa 100644 --- a/src/lib/generator/emitted_entity.dart +++ b/src/lib/generator/emitted_entity.dart @@ -1 +1,8 @@ -class EmittedEntity {} +import 'package:flutter_sqlite_m8_generator/generator/utils/utils.dart'; + +class EmittedEntity { + final String modelName; + final String entityName; + final Map attributes; + EmittedEntity(this.modelName, this.entityName, this.attributes); +} diff --git a/src/lib/generator/model_parser.dart b/src/lib/generator/model_parser.dart index 956c232..9658405 100644 --- a/src/lib/generator/model_parser.dart +++ b/src/lib/generator/model_parser.dart @@ -1,22 +1,37 @@ +import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; +import 'package:flutter_sqlite_m8_generator/exceptions/field_parse_exception.dart'; import 'package:flutter_sqlite_m8_generator/generator/emitted_entity.dart'; import 'package:flutter_sqlite_m8_generator/generator/utils/utils.dart'; import 'package:source_gen/source_gen.dart'; class ModelParser { String modelName; - final ClassElement modelClassElement; EntityType entityType; - ConstantReader reader; - ModelParser(this.modelClassElement) { + final ClassElement modelClassElement; + final String entityName; + + final Map entityAttributes = + {}; + + ModelParser(this.modelClassElement, this.entityName) { modelName = this.modelClassElement.name; } + EmittedEntity getEmittedEntity() { + _extractEntityMeta(); + _extractEntityAttributes(); + + final EmittedEntity resultEntity = + EmittedEntity(modelName, entityName, entityAttributes); + + return resultEntity; + } + void _extractEntityMeta() { - /// Guard only DbEntity implementations if (!isDbEntity.isAssignableFromType(modelClassElement.type)) { throw Exception("Database models must implement `DbEntity` interface!"); } @@ -26,7 +41,7 @@ class ModelParser { (meta) => isDataTable.isExactlyType(meta.computeConstantValue().type), orElse: () => throw Exception( - "Cannot find or parse `DataTable` annotation!")); + "The DbEntity implementations must be annotated with `@DataTable`!")); reader = ConstantReader(elementAnnotationMetadata.computeConstantValue()); @@ -42,11 +57,40 @@ class ModelParser { } } - EmittedEntity getEmittedEntity() { - _extractEntityMeta(); + void _extractEntityAttributes() { + modelClassElement.fields.forEach((f) { + _parseModelField(f); + }); + } - final resultEntity = EmittedEntity(); + void _parseModelField(FieldElement field) { + try { + if (field.displayName == 'hashCode' || + field.displayName == 'runtimeType' || + field.isStatic || + field.getter == null) return; + //todo final or synthetic - return resultEntity; + List rawEntityAttributes = field.metadata + .map((ElementAnnotation annot) => annot.computeConstantValue()) + .where((DartObject d) => isDataColumn.isExactlyType(d.type)) + .map((DartObject obj) => EntityAttribute( + field.type.name, field.name, obj.getField('name').toStringValue(), + metadataLevel: obj.getField('metadataLevel').toIntValue())) + .toList(); + + if (rawEntityAttributes.length > 1) { + throw Exception('Only one Column annotation is allowed on a Field!'); + } + + if (rawEntityAttributes.length == 0) return; + + var firstField = rawEntityAttributes.first; + if (firstField is EntityAttribute) { + entityAttributes[firstField.modelName] = firstField; + } + } catch (exception, stack) { + throw FieldParseException(field.name, exception, stack); + } } } diff --git a/src/lib/generator/orm_m8_generator_for_annotation.dart b/src/lib/generator/orm_m8_generator_for_annotation.dart index 024b204..5526816 100644 --- a/src/lib/generator/orm_m8_generator_for_annotation.dart +++ b/src/lib/generator/orm_m8_generator_for_annotation.dart @@ -25,7 +25,7 @@ class OrmM8GeneratorForAnnotation extends GeneratorForAnnotation { annotation.objectValue.getField('name').toStringValue(); print("Generating entity for $modelName ... $entityName"); - ModelParser modelParser = ModelParser(element); + ModelParser modelParser = ModelParser(element, entityName); final EmittedEntity emittedEntity = modelParser.getEmittedEntity(); final entityWriter = EntityWriter(emittedEntity); diff --git a/src/lib/generator/utils/entity_attribute.dart b/src/lib/generator/utils/entity_attribute.dart new file mode 100644 index 0000000..c493749 --- /dev/null +++ b/src/lib/generator/utils/entity_attribute.dart @@ -0,0 +1,9 @@ +class EntityAttribute { + final String modelTypeName; + final String modelName; + + final String attributeName; + + EntityAttribute(this.modelTypeName, this.modelName, this.attributeName, + {int metadataLevel}); +} diff --git a/src/lib/generator/utils/type_utils.dart b/src/lib/generator/utils/type_utils.dart index 5331bbc..f47653f 100644 --- a/src/lib/generator/utils/type_utils.dart +++ b/src/lib/generator/utils/type_utils.dart @@ -53,3 +53,7 @@ bool isIndexed(int value) { bool isUnique(int value) { return value & ColumnMetadata.Unique == ColumnMetadata.Unique; } + +bool mustIgnore(int value) { + return value & ColumnMetadata.Ignore == ColumnMetadata.Ignore; +} diff --git a/src/lib/generator/utils/utils.dart b/src/lib/generator/utils/utils.dart index 74e5396..4bcad6d 100644 --- a/src/lib/generator/utils/utils.dart +++ b/src/lib/generator/utils/utils.dart @@ -2,3 +2,4 @@ library orm_m8_generator.core.utils; export 'package:flutter_sqlite_m8_generator/generator/utils/type_utils.dart'; export 'package:flutter_sqlite_m8_generator/generator/utils/db_entity_type_enum.dart'; +export 'package:flutter_sqlite_m8_generator/generator/utils/entity_attribute.dart';