Skip to content
Merged
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
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});
}