private MappingElement FindSubPropertySource(string targetName, ITypeSymbol containingType, IEnumerable <IPropertySymbol> properties, SyntaxNode currentAccessor, string prefix = null) { if (ObjectHelper.IsSimpleType(containingType)) { return(null); } var subProperty = properties.FirstOrDefault(x => targetName.StartsWith($"{prefix}{x.Name}", StringComparison.OrdinalIgnoreCase)); if (subProperty != null) { var currentNamePart = $"{prefix}{subProperty.Name}"; var subPropertyAccessor = (ExpressionSyntax)generator.MemberAccessExpression(currentAccessor, subProperty.Name); if (targetName.Equals(currentNamePart, StringComparison.OrdinalIgnoreCase)) { return(new MappingElement() { Expression = subPropertyAccessor, ExpressionType = subProperty.Type }); } return(FindSubPropertySource(targetName, subProperty.Type, ObjectHelper.GetPublicPropertySymbols(subProperty.Type), subPropertyAccessor, currentNamePart)); } return(null); }
public MappingElement MapExpression(MappingElement element, ITypeSymbol targetType, MappingPath mappingPath = null) { if (element == null) { return(null); } if (mappingPath == null) { mappingPath = new MappingPath(); } if (mappingPath.AddToMapped(element.ExpressionType) == false) { return(new MappingElement() { ExpressionType = element.ExpressionType, Expression = element.Expression.WithTrailingTrivia(SyntaxFactory.Comment(" /* Stop recursing mapping */")) }); } if (IsUnrappingNeeded(targetType, element)) { return(TryToUnwrapp(targetType, element)); } if (element.ExpressionType.Equals(targetType) == false && ObjectHelper.IsSimpleType(targetType) == false && ObjectHelper.IsSimpleType(element.ExpressionType) == false) { return(TryToCreateMappingExpression(element, targetType, mappingPath)); } return(element); }
private SyntaxNode MapCollections(SyntaxNode sourceAccess, ITypeSymbol sourceListType, ITypeSymbol targetListType, MappingPath mappingPath) { var isReadolyCollection = targetListType.Name == "ReadOnlyCollection"; var sourceListElementType = MappingHelper.GetElementType(sourceListType); var targetListElementType = MappingHelper.GetElementType(targetListType); if (ObjectHelper.IsSimpleType(sourceListElementType) || sourceListElementType.Equals(targetListElementType)) { var toListInvocation = AddMaterializeCollectionInvocation(syntaxGenerator, sourceAccess, targetListType); return(WrapInReadonlyCollectionIfNecessary(isReadolyCollection, toListInvocation, syntaxGenerator)); } var selectAccess = syntaxGenerator.MemberAccessExpression(sourceAccess, "Select"); var lambdaParameterName = CreateLambdaParameterName(sourceAccess); var listElementMappingStm = MapExpression(new MappingElement() { ExpressionType = sourceListElementType, Expression = syntaxGenerator.IdentifierName(lambdaParameterName) as ExpressionSyntax }, targetListElementType, mappingPath); var selectInvocation = syntaxGenerator.InvocationExpression(selectAccess, syntaxGenerator.ValueReturningLambdaExpression(lambdaParameterName, listElementMappingStm.Expression)); var toList = AddMaterializeCollectionInvocation(syntaxGenerator, selectInvocation, targetListType); return(WrapInReadonlyCollectionIfNecessary(isReadolyCollection, toList, syntaxGenerator)); }
protected override bool ShouldCreateConversionBetweenTypes(ITypeSymbol targetType, ITypeSymbol sourceType) { if (targetType.Equals(sourceType) && SymbolHelper.IsNullable(targetType, out _)) { return(false); } return(ObjectHelper.IsSimpleType(targetType) == false && ObjectHelper.IsSimpleType(sourceType) == false); }
public MappingElement MapExpression(MappingElement element, ITypeSymbol targetType, MappingPath mappingPath = null) { if (element == null) { return(null); } if (mappingPath == null) { mappingPath = new MappingPath(); } var sourceType = element.ExpressionType; if (mappingPath.AddToMapped(sourceType) == false) { return(new MappingElement() { ExpressionType = sourceType, Expression = element.Expression.WithTrailingTrivia(SyntaxFactory.Comment(" /* Stop recursive mapping */")) }); } if (ObjectHelper.IsSimpleType(targetType) && SymbolHelper.IsNullable(sourceType, out var underlyingType)) { element = new MappingElement() { Expression = (ExpressionSyntax)syntaxGenerator.MemberAccessExpression(element.Expression, "Value"), ExpressionType = underlyingType }; } if (IsUnwrappingNeeded(targetType, element)) { return(TryToUnwrap(targetType, element)); } if (ShouldCreateConversionBetweenTypes(targetType, sourceType)) { return(TryToCreateMappingExpression(element, targetType, mappingPath)); } return(element); }
private SyntaxNode MapCollections(SyntaxNode sourceAccess, ITypeSymbol sourceListType, ITypeSymbol targetListType) { var isReadolyCollection = targetListType.Name == "ReadOnlyCollection"; var sourceListElementType = GetElementType(sourceListType); var targetListElementType = GetElementType(targetListType); if (ObjectHelper.IsSimpleType(sourceListElementType) || sourceListElementType == targetListElementType) { var toListInvocation = AddMaterializeCollectionInvocation(generator, sourceAccess, targetListType); return(WrapInReadonlyCollectionIfNecessary(isReadolyCollection, toListInvocation, generator)); } var selectAccess = generator.MemberAccessExpression(sourceAccess, "Select"); var lambdaParameterName = ToSingularLocalVariableName(ToLocalVariableName(sourceListElementType.Name)); var listElementMappingStms = MapTypes(sourceListElementType, targetListElementType, generator.IdentifierName(lambdaParameterName)); var selectInvocation = generator.InvocationExpression(selectAccess, generator.ValueReturningLambdaExpression(lambdaParameterName, listElementMappingStms)); var toList = AddMaterializeCollectionInvocation(generator, selectInvocation, targetListType); return(WrapInReadonlyCollectionIfNecessary(isReadolyCollection, toList, generator)); }
private SyntaxNode MapCollections(SyntaxNode sourceAccess, ITypeSymbol sourceListType, ITypeSymbol targetListType, MappingPath mappingPath) { var isReadonlyCollection = ObjectHelper.IsReadonlyCollection(targetListType); var sourceListElementType = MappingHelper.GetElementType(sourceListType); var targetListElementType = MappingHelper.GetElementType(targetListType); if (ObjectHelper.IsSimpleType(sourceListElementType) || sourceListElementType.Equals(targetListElementType)) { var toListInvocation = AddMaterializeCollectionInvocation(syntaxGenerator, sourceAccess, targetListType); return(MappingHelper.WrapInReadonlyCollectionIfNecessary(toListInvocation, isReadonlyCollection, syntaxGenerator)); } var selectAccess = syntaxGenerator.MemberAccessExpression(sourceAccess, "Select"); var lambdaParameterName = CreateLambdaParameterName(sourceAccess); var mappingLambda = CreateMappingLambda(lambdaParameterName, sourceListElementType, targetListElementType, mappingPath); var selectInvocation = syntaxGenerator.InvocationExpression(selectAccess, mappingLambda); var toList = AddMaterializeCollectionInvocation(syntaxGenerator, selectInvocation, targetListType); return(MappingHelper.WrapInReadonlyCollectionIfNecessary(toList, isReadonlyCollection, syntaxGenerator)); }
public IEnumerable <SyntaxNode> Map(MappingElement source, MappingElement target) { if (IsMappingBetweenCollections(target.ExpressionType, source.ExpressionType)) { var collectionMapping = MapCollections(source.Expression, source.ExpressionType, target.ExpressionType); yield return(generator.CompleteAssignmentStatement(target.Expression, collectionMapping)); } else if (ObjectHelper.IsSimpleType(target.ExpressionType) == false) { //TODO: What if both sides has the same type? //TODO: Reverse flattening foreach (var complexPropertyMappingNode in MapTypes(source.ExpressionType, target.ExpressionType, source.Expression, target.Expression)) { yield return(complexPropertyMappingNode); } } else { yield return(generator.CompleteAssignmentStatement(target.Expression, source.Expression)); } }
protected virtual bool ShouldCreateConversionBetweenTypes(ITypeSymbol targetType, ITypeSymbol sourceType) { return((sourceType.Equals(targetType) == false) && ObjectHelper.IsSimpleType(targetType) == false && ObjectHelper.IsSimpleType(sourceType) == false); }
private bool IsUnwrappingNeeded(ITypeSymbol targetType, MappingElement element) { return(targetType != element.ExpressionType && ObjectHelper.IsSimpleType(targetType)); }
public IEnumerable <SyntaxNode> MapTypes(ITypeSymbol sourceType, ITypeSymbol targetType, SyntaxNode globalSourceAccessor, SyntaxNode globbalTargetAccessor = null, bool targetExists = false, bool generatorContext = false) { if (IsMappingBetweenCollections(targetType, sourceType)) { var collectionMapping = MapCollections(globalSourceAccessor, sourceType, targetType); if (globbalTargetAccessor == null) { yield return(generator.ContextualReturnStatement(collectionMapping, generatorContext)); } else if (targetExists == false) { yield return(generator.CompleteAssignmentStatement(globbalTargetAccessor, collectionMapping)); } yield break; } var targetLocalVariableName = globbalTargetAccessor == null?ToLocalVariableName(targetType.Name) : ToLocalVariableName(globbalTargetAccessor.ToFullString()); var mappingSourceFinder = new MappingSourceFinder(sourceType, globalSourceAccessor, generator, semanticModel); if (targetExists == false) { var mappingConstructorParameters = FindMappingConstructorParameters(targetType, sourceType, mappingSourceFinder, (ExpressionSyntax)globalSourceAccessor); if (mappingConstructorParameters != null) { var init = generator.ObjectCreationExpression(targetType, mappingConstructorParameters.Arguments); if (globbalTargetAccessor == null) { yield return(generator.ContextualReturnStatement(init, generatorContext)); } else { yield return(generator.CompleteAssignmentStatement(globbalTargetAccessor, init)); } yield break; } else { var init = generator.ObjectCreationExpression(targetType); yield return(generator.LocalDeclarationStatement(targetLocalVariableName, init)); } } var localTargetIdentifier = targetExists? globbalTargetAccessor: generator.IdentifierName(targetLocalVariableName); foreach (var targetProperty in ObjectHelper.GetPublicPropertySymbols(targetType)) { if (targetProperty.SetMethod.DeclaredAccessibility != Accessibility.Public && globbalTargetAccessor.Kind() != SyntaxKind.ThisExpression) { continue; } var mappingSource = mappingSourceFinder.FindMappingSource(targetProperty.Name, targetProperty.Type); if (mappingSource == null) { continue; } if (IsMappingBetweenCollections(targetProperty.Type, mappingSource.ExpressionType)) { var targetAccess = generator.MemberAccessExpression(localTargetIdentifier, targetProperty.Name); var collectionMapping = MapCollections(mappingSource.Expression, mappingSource.ExpressionType, targetProperty.Type); yield return(generator.CompleteAssignmentStatement(targetAccess, collectionMapping)); } else if (ObjectHelper.IsSimpleType(targetProperty.Type) == false) { //TODO: What if both sides has the same type? //TODO: Reverse flattening var targetAccess = generator.MemberAccessExpression(localTargetIdentifier, targetProperty.Name); foreach (var complexPropertyMappingNode in MapTypes(mappingSource.ExpressionType, targetProperty.Type, mappingSource.Expression, targetAccess)) { yield return(complexPropertyMappingNode); } } else { var targetAccess = generator.MemberAccessExpression(localTargetIdentifier, targetProperty.Name); yield return(generator.CompleteAssignmentStatement(targetAccess, mappingSource.Expression)); } } if (globbalTargetAccessor == null) { yield return(generator.ContextualReturnStatement(localTargetIdentifier, generatorContext)); } else if (targetExists == false) { yield return(generator.CompleteAssignmentStatement(globbalTargetAccessor, localTargetIdentifier)); } }
private static bool IsUnrappingNeeded(ITypeSymbol targetType, MappingSource mappingSource) { return(targetType != mappingSource.ExpressionType && ObjectHelper.IsSimpleType(targetType)); }
protected override bool ShouldCreateConversionBetweenTypes(ITypeSymbol targetType, ITypeSymbol sourceType) { return(ObjectHelper.IsSimpleType(targetType) == false && ObjectHelper.IsSimpleType(sourceType) == false); }
private bool IsUnwrappingNeeded(ITypeSymbol targetType, MappingElement element) { return(targetType.Equals(element.ExpressionType) == false && (ObjectHelper.IsSimpleType(targetType) || SymbolHelper.IsNullable(targetType, out _))); }