public static MethodDeclarationSyntax[] CreateWithMethodsToAdd( TypeConstructorDetails typeConstructorDetails, INamedTypeSymbol doType, string[] existingWithMethodNames) { return (typeConstructorDetails.PropertyAndParameters .Select(item => new { item, newMethodName = "With" + item.Property.Name }) .Where(x => !existingWithMethodNames.Contains(x.newMethodName)) .Select(x => CreateWithMethod(doType, typeConstructorDetails, x.item)) .ToArray()); }
public static MethodDeclarationSyntax CreateWithMethod( INamedTypeSymbol doTypeSymbol, TypeConstructorDetails typeConstructorDetails, PropertyAndParameter propertyToCreateMethodFor) { var newMethodName = "With" + propertyToCreateMethodFor.Property.Name; var doFullname = Utilities.GetFullName(doTypeSymbol); var thisParameterName = "instance"; var propertyTypeFullName = Utilities.GetFullName(propertyToCreateMethodFor.Property.Type); List <SyntaxNodeOrToken> nodes = new List <SyntaxNodeOrToken>(); foreach (var property in typeConstructorDetails.PropertyAndParameters) { var propertyName = property.Property.Name; var parameterName = Utilities.MakeFirstLetterSmall(property.Parameter.Name); if (nodes.Count > 0) { nodes.Add(SyntaxFactory.Token(SyntaxKind.CommaToken)); } if (property.Property.Equals(propertyToCreateMethodFor.Property)) { nodes.Add( SyntaxFactory.Argument( SyntaxFactory.IdentifierName("newValue")) .WithNameColon( SyntaxFactory.NameColon( SyntaxFactory.IdentifierName(parameterName)))); } else { nodes.Add( SyntaxFactory.Argument( Utilities.CreateSimpleMemberAccessSyntax(thisParameterName, propertyName)) .WithNameColon( SyntaxFactory.NameColon( SyntaxFactory.IdentifierName(parameterName)))); } } var constructionExpressionSyntax = typeConstructorDetails.Constructor .Match <ExpressionSyntax>(caseNormalConstructor: () => SyntaxFactory.ObjectCreationExpression( SyntaxFactory.IdentifierName(doFullname)) .WithArgumentList( SyntaxFactory.ArgumentList( SyntaxFactory.SeparatedList <ArgumentSyntax>( nodes.ToArray()))), caseFSharpUnionCaseNewMethod: () => SyntaxFactory.CastExpression( SyntaxFactory.IdentifierName(doFullname), SyntaxFactory.InvocationExpression( Utilities.CreateSimpleMemberAccessSyntax(Utilities.GetFullName(doTypeSymbol.BaseType), "New" + doTypeSymbol.Name)) .WithArgumentList( SyntaxFactory.ArgumentList( SyntaxFactory.SeparatedList <ArgumentSyntax>( nodes.ToArray()))))); var method = SyntaxFactory.MethodDeclaration( SyntaxFactory.IdentifierName(doFullname), SyntaxFactory.Identifier(newMethodName)) .WithModifiers( SyntaxFactory.TokenList(SyntaxFactory.Token(SyntaxKind.PublicKeyword), SyntaxFactory.Token(SyntaxKind.StaticKeyword))) .WithParameterList( SyntaxFactory.ParameterList( SyntaxFactory.SeparatedList <ParameterSyntax>( new SyntaxNodeOrToken[] { SyntaxFactory.Parameter( SyntaxFactory.Identifier(thisParameterName)) .WithModifiers( SyntaxFactory.TokenList( SyntaxFactory.Token(SyntaxKind.ThisKeyword))) .WithType( SyntaxFactory.IdentifierName(doFullname)), SyntaxFactory.Token(SyntaxKind.CommaToken), SyntaxFactory.Parameter( SyntaxFactory.Identifier("newValue")) .WithType( SyntaxFactory.IdentifierName(propertyTypeFullName)) }))) .WithBody( SyntaxFactory.Block( SyntaxFactory.SingletonList <StatementSyntax>( SyntaxFactory.ReturnStatement( constructionExpressionSyntax)))); if (doTypeSymbol.IsGenericType) { var openTypeParams = Utilities.GetOpenTypeParameters(doTypeSymbol); if (openTypeParams.Any()) { method = method.WithTypeParameterList( SyntaxFactory.TypeParameterList( SyntaxFactory.SeparatedList( openTypeParams .Select(x => SyntaxFactory.TypeParameter(SyntaxFactory.Identifier(x.Name)))))); } } return(method); }