Skip to content

Commit

Permalink
Ignore Attribute in Mapping (#44)
Browse files Browse the repository at this point in the history
* Ignore Attribute in Mapping

* Add missing Annotation
  • Loading branch information
smotastic authored Jan 27, 2022
1 parent 30f22b2 commit 8cf5e97
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 27 deletions.
22 changes: 22 additions & 0 deletions example/lib/ignore/ignore.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import 'package:smartstruct/smartstruct.dart';
part 'ignore.mapper.g.dart';

class IgnoreSource {
final String ignoreMe;
final String doNotIgnoreMe;

IgnoreSource(this.ignoreMe, this.doNotIgnoreMe);
}

class IgnoreTarget {
String? ignoreMe;
final String doNotIgnoreMe;

IgnoreTarget(this.doNotIgnoreMe);
}

@Mapper()
abstract class IgnoreMapper {
@Mapping(target: 'ignoreMe', ignore: true)
IgnoreTarget fromIgnore(IgnoreSource source);
}
17 changes: 17 additions & 0 deletions example/lib/ignore/ignore.mapper.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 18 additions & 12 deletions generator/lib/code_builders/method_builder.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'dart:collection';

import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:code_builder/code_builder.dart';
import 'package:smartstruct_generator/code_builders/parameter_copy.dart';
Expand Down Expand Up @@ -175,19 +174,26 @@ List<HashMap<String, SourceAssignment>> _targetToSource(

/// If there are Mapping Annotations on the method, the source attribute of the source mapping class,
/// will be replaced with the source attribute of the given mapping config.
mappingConfig.forEach((sourceField, targetField) {
if (sourceField.toFunctionValue() != null) {
targetToSource[targetField] = SourceAssignment.fromFunction(
sourceField.toFunctionValue()!, [...sources]);
}
if (sourceField.toStringValue() != null) {
final sourceFieldString = sourceField.toStringValue()!;
if (targetToSource.containsKey(sourceFieldString)) {
targetToSource.putIfAbsent(
targetField, () => targetToSource[sourceFieldString]!);
targetToSource.remove(sourceFieldString);
mappingConfig.forEach((targetField, mappingConfig) {
final sourceField = mappingConfig.source;
if (sourceField != null) {
if (sourceField.toFunctionValue() != null) {
targetToSource[targetField] = SourceAssignment.fromFunction(
sourceField.toFunctionValue()!, [...sources]);
} else if (sourceField.toStringValue() != null) {
final sourceFieldString = sourceField.toStringValue()!;
if (targetToSource.containsKey(sourceFieldString)) {
targetToSource.putIfAbsent(
targetField, () => targetToSource[sourceFieldString]!);

targetToSource.remove(sourceFieldString);
}
}
}

if (mappingConfig.ignore) {
targetToSource.remove(targetField);
}
});

return [targetToSource, customTargetToSource];
Expand Down
12 changes: 9 additions & 3 deletions generator/lib/generators/mapper_generator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,14 @@ class MapperGenerator extends GeneratorForAnnotation<Mapper> {

var config = MapperConfig.readMapperConfig(annotation, element);

final mapperImpl = buildMapperClass(element, config);
final emitter = DartEmitter();
return '${mapperImpl.accept(emitter)}';
try {
final mapperImpl = buildMapperClass(element, config);
final emitter = DartEmitter();
return '${mapperImpl.accept(emitter)}';
} on Error catch (e) {
print(e);
print(e.stackTrace);
rethrow;
}
}
}
30 changes: 20 additions & 10 deletions generator/lib/mapper_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,34 @@ class MapperConfig {
var mapper =
mappingClass.metadata[0].element!.enclosingElement as ClassElement;
final config = <String, dynamic>{};
mapper.fields.forEach((field) {

for (final field in mapper.fields) {
final configField = annotation.read(field.name).literalValue;
config.putIfAbsent(field.name, () => configField);
});
}
return config;
}

/// Reads the attributes of the [Mapping] annotations of a given Method,
/// and returns key value pairs, where the key is the source, and the value is the target attribute of the read Mapping
static Map<DartObject, String> readMappingConfig(MethodElement method) {
final config = <DartObject, String>{};
/// and returns key value pairs, where the key is the target, and the value is an instance of [MappingConfig] containing the source and other meta attributes
static Map<String, MappingConfig> readMappingConfig(MethodElement method) {
final config = <String, MappingConfig>{};
final annotations = TypeChecker.fromRuntime(Mapping).annotationsOf(method);

annotations.forEach((element) {
var reader = ConstantReader(element);
config[reader.read('source').objectValue] =
reader.read('target').stringValue;
});
for (final element in annotations) {
final reader = ConstantReader(element);
final sourceReader = reader.read('source');
config[reader.read('target').stringValue] = MappingConfig(
sourceReader.isNull ? null : sourceReader.objectValue,
reader.read('ignore').boolValue);
}
return config;
}
}

class MappingConfig {
final DartObject? source;
final bool ignore;

MappingConfig(this.source, this.ignore);
}
3 changes: 2 additions & 1 deletion generator/test/mapper_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,6 @@ const _expectedAnnotatedTests = {
'ConstructorMapper',
'FunctionFieldMapper',
'InheritanceMapper',
'MultipleSourceMapper'
'MultipleSourceMapper',
'IgnoreMapper'
};
32 changes: 32 additions & 0 deletions generator/test/src/ignore_field_mapper_input.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
part of 'mapper_test_input.dart';

class IgnoreSource {
final String ignoreMe;
final String doNotIgnoreMe;

IgnoreSource(this.ignoreMe, this.doNotIgnoreMe);
}

class IgnoreTarget {
String? ignoreMe;
final String doNotIgnoreMe;

IgnoreTarget(this.doNotIgnoreMe);
}

@Mapper()
@ShouldGenerate(r'''
class IgnoreMapperImpl extends IgnoreMapper {
IgnoreMapperImpl() : super();
@override
IgnoreTarget fromIgnore(IgnoreSource source) {
final ignoretarget = IgnoreTarget(source.doNotIgnoreMe);
return ignoretarget;
}
}
''')
abstract class IgnoreMapper {
@Mapping(target: 'ignoreMe', ignore: true)
IgnoreTarget fromIgnore(IgnoreSource source);
}
1 change: 1 addition & 0 deletions generator/test/src/mapper_test_input.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ part 'constructor_mapper_input.dart';
part 'function_mapper_input.dart';
part 'inheritance_mapper_input.dart';
part 'multiple_source_mapper_input.dart';
part 'ignore_field_mapper_input.dart';

@ShouldThrow('theAnswer is not a class and cannot be annotated with @Mapper')
@Mapper()
Expand Down
3 changes: 2 additions & 1 deletion smartstruct/lib/src/annotations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ const mapper = Mapper();
class Mapping {
final dynamic source;
final String target;
const Mapping({required this.source, required this.target});
final bool ignore;
const Mapping({required this.target, this.source, this.ignore = false});
}

0 comments on commit 8cf5e97

Please sign in to comment.