protected virtual MappingElement TryToCreateMappingExpression(MappingElement source, ITypeSymbol targetType, MappingPath mappingPath) { //TODO: If source expression is method or constructor invocation then we should extract local variable and use it im mappings as a reference var namedTargetType = targetType as INamedTypeSymbol; if (namedTargetType != null) { var directlyMappingConstructor = namedTargetType.Constructors.FirstOrDefault(c => c.Parameters.Length == 1 && c.Parameters[0].Type.Equals(source.ExpressionType)); if (directlyMappingConstructor != null) { var constructorParameters = SyntaxFactory.ArgumentList().AddArguments(SyntaxFactory.Argument(source.Expression)); var creationExpression = syntaxGenerator.ObjectCreationExpression(targetType, constructorParameters.Arguments); return(new MappingElement() { ExpressionType = targetType, Expression = (ExpressionSyntax)creationExpression }); } } if (MappingHelper.IsMappingBetweenCollections(targetType, source.ExpressionType)) { return(new MappingElement() { ExpressionType = targetType, Expression = MapCollections(source.Expression, source.ExpressionType, targetType, mappingPath.Clone()) as ExpressionSyntax }); } var subMappingSourceFinder = new ObjectMembersMappingSourceFinder(source.ExpressionType, source.Expression, syntaxGenerator); if (namedTargetType != null) { //maybe there is constructor that accepts parameter matching source properties var constructorOverloadParameterSets = namedTargetType.Constructors.Select(x => x.Parameters); var matchedOverload = MethodHelper.FindBestParametersMatch(subMappingSourceFinder, constructorOverloadParameterSets); if (matchedOverload != null) { var creationExpression = syntaxGenerator.ObjectCreationExpression(targetType, matchedOverload.ToArgumentListSyntax(this).Arguments); return(new MappingElement() { ExpressionType = targetType, Expression = (ExpressionSyntax)creationExpression }); } } var objectCreationExpressionSyntax = ((ObjectCreationExpressionSyntax)syntaxGenerator.ObjectCreationExpression(targetType)); return(new MappingElement() { ExpressionType = targetType, Expression = AddInitializerWithMapping(objectCreationExpressionSyntax, subMappingSourceFinder, targetType, mappingPath) }); }
private static IEnumerable<SyntaxNode> GenerateMappingCode(IMethodSymbol methodSymbol, SyntaxGenerator generator, SemanticModel semanticModel) { var mappingEngine = new MappingEngine(semanticModel, generator); if (SymbolHelper.IsPureMappingFunction(methodSymbol)) { var source = methodSymbol.Parameters[0]; var targetType = methodSymbol.ReturnType; var newExpression = mappingEngine.MapExpression((ExpressionSyntax)generator.IdentifierName(source.Name), source.Type, targetType); return new[] { generator.ReturnStatement(newExpression) }; } //TODO: Pure mapping with multiple parameters if (SymbolHelper.IsUpdateParameterFunction(methodSymbol)) { var source = methodSymbol.Parameters[0]; var target = methodSymbol.Parameters[1]; var targets = ObjectHelper.GetFieldsThaCanBeSetPublicly(target.Type); var sourceFinder = new ObjectMembersMappingSourceFinder(source.Type, generator.IdentifierName(source.Name), generator); return MappingHelper.MapUsingSimpleAssignment(generator, semanticModel, targets, sourceFinder, globalTargetAccessor: generator.IdentifierName(target.Name)); } if (SymbolHelper.IsUpdateThisObjectFunction(methodSymbol)) { var source = methodSymbol.Parameters[0]; var sourceFinder = new ObjectMembersMappingSourceFinder(source.Type, generator.IdentifierName(source.Name), generator); var targets = ObjectHelper.GetFieldsThaCanBeSetPrivately(methodSymbol.ContainingType); return MappingHelper.MapUsingSimpleAssignment(generator, semanticModel, targets, sourceFinder); } if (SymbolHelper.IsMultiParameterUpdateThisObjectFunction(methodSymbol)) { var sourceFinder = new LocalScopeMappingSourceFinder(semanticModel, methodSymbol.Parameters); var targets = ObjectHelper.GetFieldsThaCanBeSetPrivately(methodSymbol.ContainingType); return MappingHelper.MapUsingSimpleAssignment(generator, semanticModel, targets, sourceFinder); } if (SymbolHelper.IsMappingConstructor(methodSymbol)) { var source = methodSymbol.Parameters[0]; var sourceFinder = new ObjectMembersMappingSourceFinder(source.Type, generator.IdentifierName(source.Name), generator); var targets = ObjectHelper.GetFieldsThaCanBeSetFromConstructor(methodSymbol.ContainingType); return MappingHelper.MapUsingSimpleAssignment(generator, semanticModel, targets, sourceFinder); } if (SymbolHelper.IsMultiParameterMappingConstructor(methodSymbol)) { var sourceFinder = new LocalScopeMappingSourceFinder(semanticModel, methodSymbol.Parameters); var targets = ObjectHelper.GetFieldsThaCanBeSetFromConstructor(methodSymbol.ContainingType); return MappingHelper.MapUsingSimpleAssignment(generator, semanticModel, targets, sourceFinder); } return Enumerable.Empty<SyntaxNode>(); }
private async Task <Document> InitizalizeWithLambdaParameter(Document document, LambdaExpressionSyntax lambdaSyntax, InitializerExpressionSyntax objectInitializer, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var generator = SyntaxGenerator.GetGenerator(document); var lambdaSymbol = semanticModel.GetSymbolInfo(lambdaSyntax).Symbol as IMethodSymbol; var firstArgument = lambdaSymbol.Parameters.First(); var mappingSourceFinder = new ObjectMembersMappingSourceFinder(firstArgument.Type, generator.IdentifierName(firstArgument.Name), generator); return(await ReplaceEmptyInitializationBlock(document, objectInitializer, cancellationToken, semanticModel, mappingSourceFinder, generator)); }
public IEnumerable <SyntaxNode> MapTypes(ITypeSymbol sourceType, ITypeSymbol targetType, SyntaxNode globalSourceAccessor, SyntaxNode globbalTargetAccessor = null, bool targetExists = false, bool generatorContext = false, bool isConstructorContext = 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 ObjectMembersMappingSourceFinder(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 (CanBeSet(targetProperty, globbalTargetAccessor, isConstructorContext) == false) { continue; } var mappingSource = mappingSourceFinder.FindMappingSource(targetProperty.Name, targetProperty.Type); if (mappingSource == null) { continue; } var mappingTarget = new MappingElement() { Expression = (ExpressionSyntax)generator.MemberAccessExpression(localTargetIdentifier, targetProperty.Name), ExpressionType = targetProperty.Type }; foreach (var syntaxNode in Map(mappingSource, mappingTarget)) { yield return(syntaxNode); } } if (globbalTargetAccessor == null) { yield return(generator.ContextualReturnStatement(localTargetIdentifier, generatorContext)); } else if (targetExists == false) { yield return(generator.CompleteAssignmentStatement(globbalTargetAccessor, localTargetIdentifier)); } }
private ArgumentListSyntax FindMappingConstructorParameters(ITypeSymbol targetType, ITypeSymbol sourceType, ObjectMembersMappingSourceFinder mappingSourceFinder, ExpressionSyntax globalSourceAccessor) { if (targetType is INamedTypeSymbol namedType) { var directlyMappingConstructor = namedType.Constructors.FirstOrDefault(c => c.Parameters.Length == 1 && c.Parameters[0].Type == sourceType); if (directlyMappingConstructor != null) { return(SyntaxFactory.ArgumentList().AddArguments(SyntaxFactory.Argument(globalSourceAccessor))); } var constructorOverloadParameterSets = namedType.Constructors.Select(x => x.Parameters); return(MethodHelper.FindBestParametersMatch(mappingSourceFinder, constructorOverloadParameterSets)?.ToArgumentListSyntax(generator)); } return(null); }
private static IEnumerable <SyntaxNode> GenerateMappingCode(IMethodSymbol methodSymbol, SyntaxGenerator generator, SemanticModel semanticModel) { if (SymbolHelper.IsIdentityMappingFunction(methodSymbol)) { var cloneMappingEngine = new CloneMappingEngine(semanticModel, generator, methodSymbol.ContainingAssembly); var source = methodSymbol.Parameters[0]; var targetType = methodSymbol.ReturnType; var newExpression = cloneMappingEngine.MapExpression((ExpressionSyntax)generator.IdentifierName(source.Name), source.Type, targetType); return(new[] { generator.ReturnStatement(newExpression).WithAdditionalAnnotations(Formatter.Annotation) }); } var mappingEngine = new MappingEngine(semanticModel, generator, methodSymbol.ContainingAssembly); if (SymbolHelper.IsPureMappingFunction(methodSymbol)) { var source = methodSymbol.Parameters[0]; var targetType = methodSymbol.ReturnType; var newExpression = mappingEngine.MapExpression((ExpressionSyntax)generator.IdentifierName(source.Name), source.Type, targetType); return(new[] { generator.ReturnStatement(newExpression).WithAdditionalAnnotations(Formatter.Annotation) }); } if (SymbolHelper.IsMultiParameterPureFunction(methodSymbol)) { var targetType = methodSymbol.ReturnType; var sourceFinder = new LocalScopeMappingSourceFinder(semanticModel, methodSymbol); var newExpression = mappingEngine.AddInitializerWithMapping((ObjectCreationExpressionSyntax)generator.ObjectCreationExpression(targetType), sourceFinder, targetType); return(new[] { generator.ReturnStatement(newExpression).WithAdditionalAnnotations(Formatter.Annotation) }); } if (SymbolHelper.IsUpdateParameterFunction(methodSymbol)) { var source = methodSymbol.Parameters[0]; var target = methodSymbol.Parameters[1]; var targets = ObjectHelper.GetFieldsThaCanBeSetPublicly(target.Type, methodSymbol.ContainingAssembly); var sourceFinder = new ObjectMembersMappingSourceFinder(source.Type, generator.IdentifierName(source.Name), generator); return(mappingEngine.MapUsingSimpleAssignment(generator, targets, sourceFinder, globalTargetAccessor: generator.IdentifierName(target.Name))); } if (SymbolHelper.IsUpdateThisObjectFunction(methodSymbol)) { var source = methodSymbol.Parameters[0]; var sourceFinder = new ObjectMembersMappingSourceFinder(source.Type, generator.IdentifierName(source.Name), generator); var targets = ObjectHelper.GetFieldsThaCanBeSetPrivately(methodSymbol.ContainingType); return(mappingEngine.MapUsingSimpleAssignment(generator, targets, sourceFinder)); } if (SymbolHelper.IsMultiParameterUpdateThisObjectFunction(methodSymbol)) { var sourceFinder = new LocalScopeMappingSourceFinder(semanticModel, methodSymbol.Parameters); var targets = ObjectHelper.GetFieldsThaCanBeSetPrivately(methodSymbol.ContainingType); return(mappingEngine.MapUsingSimpleAssignment(generator, targets, sourceFinder)); } if (SymbolHelper.IsMappingConstructor(methodSymbol)) { var source = methodSymbol.Parameters[0]; var sourceFinder = new ObjectMembersMappingSourceFinder(source.Type, generator.IdentifierName(source.Name), generator); var targets = ObjectHelper.GetFieldsThaCanBeSetFromConstructor(methodSymbol.ContainingType); return(mappingEngine.MapUsingSimpleAssignment(generator, targets, sourceFinder)); } if (SymbolHelper.IsMultiParameterMappingConstructor(methodSymbol)) { var sourceFinder = new LocalScopeMappingSourceFinder(semanticModel, methodSymbol.Parameters); var targets = ObjectHelper.GetFieldsThaCanBeSetFromConstructor(methodSymbol.ContainingType); return(mappingEngine.MapUsingSimpleAssignment(generator, targets, sourceFinder)); } return(Enumerable.Empty <SyntaxNode>()); }