Skip to content
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
50 changes: 50 additions & 0 deletions example/lib/static_mapping/function_mapping_static.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import 'package:smartstruct/smartstruct.dart';

part 'function_mapping_static.mapper.g.dart';

// TARGET

class Dog {
final String name;
final String breed;
final int age;
late AgeHolderTarget? model;

Dog(this.name, this.breed, this.age);
}

// SOURCE

class DogModel {
final String name;
final int age;

DogModel(this.name, this.age);
}

class AgeHolderSource {
final int age;
AgeHolderSource(this.age);
}

class AgeHolderTarget {
late int age;
}

// This example uses static helper methods to map inner fields
@Mapper(useStaticMapping: false)
abstract class DogMapper {
static String breedCustom(DogModel model) => 'customBreed';

static AgeHolderSource? toAgeHolderSource(DogModel model) =>
AgeHolderSource(model.age);

static String fullNameWithAge(DogModel model) => model.name + '${model.age}';

@Mapping(source: fullNameWithAge, target: 'name')
@Mapping(source: breedCustom, target: 'breed')
@Mapping(source: toAgeHolderSource, target: 'model')
Dog fromDogModel(DogModel model);

AgeHolderTarget fromAgeHolderSource(AgeHolderSource model);
}
29 changes: 29 additions & 0 deletions example/lib/static_mapping/function_mapping_static.mapper.g.dart

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

12 changes: 6 additions & 6 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ description: example
version: 1.0.1
# homepage: https://www.example.com
environment:
sdk: ">=2.12.0 <3.0.0"
sdk: ">=2.17.0 <3.0.0"

publish_to: none
dependencies:
freezed_annotation: ^2.1.0
injectable: ^1.5.3
smartstruct: ^1.3.0
smartstruct: ^1.4.0
dev_dependencies:
build_runner: ^2.1.7
freezed: ^2.1.0+1
injectable_generator: ^1.5.3
smartstruct_generator: ^1.3.0
smartstruct_generator: ^1.4.0
#smartstruct_generator:
# path: ../generator
dependency_overrides:
smartstruct:
path: ../smartstruct
# dependency_overrides:
# smartstruct:
# path: ../smartstruct
4 changes: 0 additions & 4 deletions generator/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
include: package:lints/recommended.yaml

# For lint rules and documentation, see http://dart-lang.github.io/linter/lints.

# Uncomment to specify additional rules.
Expand All @@ -10,6 +9,3 @@ include: package:lints/recommended.yaml
# analyzer:
# exclude:
# - path/to/excluded/files/**
analyzer:
enable-experiment:
- non-nullable
12 changes: 6 additions & 6 deletions generator/lib/code_builders/assignment_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ Expression generateSourceFieldAssignment(SourceAssignment sourceAssignment,
.map((sourceParam) => refer(sourceParam.displayName));
Expression expr = refer(sourceFunction.name);
if (sourceFunction.isStatic &&
sourceFunction.enclosingElement3.name != null) {
expr = refer(sourceFunction.enclosingElement3.name!)
sourceFunction.enclosingElement.name != null) {
expr = refer(sourceFunction.enclosingElement.name!)
.property(sourceFunction.name);
}
sourceFieldAssignment = expr.call(
Expand Down Expand Up @@ -191,11 +191,11 @@ Iterable<MethodElement> _findMatchingMappingMethod(ClassElement classElement,
if (met.parameters.isEmpty) {
return false;
}
final metReturnElement = met.returnType.element2;
final metParameterElement = met.parameters.first.type.element2;
final metReturnElement = met.returnType.element;
final metParameterElement = met.parameters.first.type.element;

final targetReturnElement = targetReturnType.element2;
final srcParameterElement = sourceParameterType.element2;
final targetReturnElement = targetReturnType.element;
final srcParameterElement = sourceParameterType.element;

return metReturnElement == targetReturnElement &&
(metParameterElement == srcParameterElement);
Expand Down
4 changes: 3 additions & 1 deletion generator/lib/code_builders/class_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ List<Class> _generateStaticProxy(

List<Method> _generateStaticMethods(
ClassElement abstractClass, Map<String, dynamic> config) {
if (config['useStaticMapping'] == false) return [];

var staticMethods = abstractClass.methods
.where(
(method) =>
Expand All @@ -49,7 +51,7 @@ bool _shouldGenerateStaticMethod(MethodElement method) {
}

bool _isAbstractType(DartType type) {
final element = type.element2;
final element = type.element;
if (element is! ClassElement) {
return false;
}
Expand Down
29 changes: 15 additions & 14 deletions generator/lib/code_builders/method_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import 'dart:collection';
import 'package:analyzer/dart/element/element.dart';
import 'package:code_builder/code_builder.dart';
import 'package:smartstruct_generator/code_builders/parameter_copy.dart';
import 'package:smartstruct_generator/mapper_config.dart';
import 'package:smartstruct_generator/models/RefChain.dart';
import 'package:smartstruct_generator/models/source_assignment.dart';
import 'package:smartstruct_generator/mapper_config.dart';
import 'package:source_gen/source_gen.dart';

import 'assignment_builder.dart';

/// Generates the implemented mapper method by the given abstract [MethodElement].
Method buildMapperImplementation(Map<String, dynamic> config,
MethodElement method, ClassElement abstractMapper) {
if (method.returnType.element2 == null) {
if (method.returnType.element == null) {
throw InvalidGenerationSourceError(
'${method.returnType} is not a valid return type',
element: method,
Expand All @@ -28,21 +28,20 @@ Method buildMapperImplementation(Map<String, dynamic> config,
refer(method.returnType.getDisplayString(withNullability: true)));
}


/// Generates the implemented mapper method by the given abstract [MethodElement].
Method buildStaticMapperImplementation(Map<String, dynamic> config,
MethodElement method, ClassElement abstractMapper) {
return Method(
(b) => b
(b) => b
..name = '_\$${method.name}'
..requiredParameters.addAll(method.parameters.map((e) => copyParameter(e)))
..requiredParameters
.addAll(method.parameters.map((e) => copyParameter(e)))
..body = _generateBody(config, method, abstractMapper)
..returns =
refer(method.returnType.getDisplayString(withNullability: true)),
refer(method.returnType.getDisplayString(withNullability: true)),
);
}


/// Generates the body for the mapping method.
///
/// Uses the default constructor of the target mapping class to populate optional and required named and positional parameters.
Expand All @@ -51,7 +50,7 @@ Code _generateBody(Map<String, dynamic> config, MethodElement method,
ClassElement abstractMapper) {
final blockBuilder = BlockBuilder();

final targetClass = method.returnType.element2 as ClassElement;
final targetClass = method.returnType.element as ClassElement;

final sourceParams = method.parameters;

Expand Down Expand Up @@ -161,7 +160,7 @@ List<HashMap<String, SourceAssignment>> _targetToSource(
ClassElement target,
MethodElement method,
Map<String, dynamic> config) {
final sourceMap = {for (var e in sources) e.type.element2 as ClassElement: e};
final sourceMap = {for (var e in sources) e.type.element as ClassElement: e};

final caseSensitiveFields = config['caseSensitiveFields'];
final fieldMapper = caseSensitiveFields ? (a) => a : (a) => a.toUpperCase();
Expand Down Expand Up @@ -202,10 +201,11 @@ List<HashMap<String, SourceAssignment>> _targetToSource(
for (var matchedTarget in matchedSourceClazzInSourceMapping.keys) {
final sourceValueList =
matchedSourceClazzInSourceMapping[matchedTarget]!;
final fieldClazz = f.type.element2 as ClassElement;

final refChain = RefChain.byPropNames(sourceEntry.value, sourceValueList.sublist(1));
targetToSource[matchedTarget] = SourceAssignment.fromRefChain(refChain);

final refChain = RefChain.byPropNames(
sourceEntry.value, sourceValueList.sublist(1));
targetToSource[matchedTarget] =
SourceAssignment.fromRefChain(refChain);
}
} else {
targetToSource[f.name] =
Expand Down Expand Up @@ -302,13 +302,14 @@ FieldElement? _findMatchingField(
final foundField = potentielFinds.first;
// foundField is not string
if (_shouldSearchMoreFields(foundField)) {
final searchClazz = foundField.type.element2 as ClassElement;
final searchClazz = foundField.type.element as ClassElement;
return _findMatchingField(
sources.skip(1).toList(), _findFields(searchClazz));
} else {
return foundField;
}
}
return null;
}

/// A search for a potential underlying should only be continued, if the field is not a primitive type (string, int, double etc)
Expand Down
5 changes: 3 additions & 2 deletions generator/lib/mapper_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class MapperConfig {
static Map<String, dynamic> readMapperConfig(
ConstantReader annotation, ClassElement mappingClass) {
var mapper =
mappingClass.metadata[0].element!.enclosingElement3 as ClassElement;
mappingClass.metadata[0].element!.enclosingElement as ClassElement;
final config = <String, dynamic>{};

for (final field in mapper.fields) {
Expand All @@ -37,7 +37,8 @@ class MapperConfig {
}

static bool isIgnoreMapping(MethodElement method) {
final annotations = TypeChecker.fromRuntime(IgnoreMapping).annotationsOf(method);
final annotations =
TypeChecker.fromRuntime(IgnoreMapping).annotationsOf(method);
return annotations.isNotEmpty;
}
}
Expand Down
10 changes: 8 additions & 2 deletions smartstruct/lib/src/annotations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ class Mapper {
final bool useInjection;
final bool caseSensitiveFields;
final bool generateStaticProxy;
final bool useStaticMapping;

const Mapper({this.useInjection = false, this.caseSensitiveFields = false, this.generateStaticProxy = false});
const Mapper({
this.useInjection = false,
this.caseSensitiveFields = false,
this.generateStaticProxy = false,
this.useStaticMapping = true,
});
}

const mapper = Mapper();
Expand Down Expand Up @@ -35,4 +41,4 @@ class Mapping {
/// ```
class IgnoreMapping {
const IgnoreMapping();
}
}