private static async Task <Document> GenerateConstructor( Document document, ClassDeclarationSyntax classDeclarationSyntax, IList <PropertyDeclarationSyntax> properties, ConstructorDeclarationSyntax nonTrivialConstructorCandidate, CancellationToken cancellationToken) { var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); if (properties.Count == 0) { return(document); } var constructorDeclaration = ConstructorGenerationHelper.FromPropertiesWithAssignments( classDeclarationSyntax.Identifier.WithoutTrivia(), properties); var newClassDeclaration = nonTrivialConstructorCandidate != null? classDeclarationSyntax.ReplaceNode(nonTrivialConstructorCandidate, constructorDeclaration) : classDeclarationSyntax.AddMembers(constructorDeclaration); var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false); var newRoot = root.ReplaceNode(classDeclarationSyntax, newClassDeclaration); var newDocument = document.WithSyntaxRoot(newRoot); return(newDocument); }
private static async Task <Document> GenerateDiscriminatedUnion( Document document, ClassDeclarationSyntax classDeclarationSyntax, CancellationToken cancellationToken) { var rootNode = classDeclarationSyntax.Parent; if (rootNode == null) { return(document); } var duMembers = GetCandidateMethods(classDeclarationSyntax); if (duMembers.Count == 0) { return(document); } var factoryMethodRewriter = new FactoryMethodRewriter(); var newClassDeclaration = factoryMethodRewriter.Visit(classDeclarationSyntax); rootNode = rootNode.ReplaceNode(classDeclarationSyntax, newClassDeclaration); List <(MethodDeclarationSyntax method, ClassDeclarationSyntax cl)> candidates = duMembers.Select(m => (m, FindCurrentCaseDeclaration(rootNode, GetGeneratedClassName(m)))) .ToList(); var declarationsCleaner = new ClassOccurencesCleaner(candidates.Select(p => p.cl).Where(p => p != null).ToList()); rootNode = declarationsCleaner.Visit(rootNode); // TODO: Methods returning types defined in other assemblies should probably be rejected, // but lets say it is user's responsibility to use this refactoring wisely. var baseClassIdentifier = SF.IdentifierName(classDeclarationSyntax.Identifier); foreach (var(duCandidate, prevDeclaration) in candidates) { var generatedClassName = GetGeneratedClassName(duCandidate); if (generatedClassName == default) { return(document); } var properties = duCandidate.ParameterList.Parameters.Select(ToProperty).ToList(); var constructorDeclaration = properties.Count > 0 ? ConstructorGenerationHelper.FromPropertiesWithAssignments( generatedClassName, properties) : null; var members = new List <MemberDeclarationSyntax>(properties); rootNode = UpdateOrAddCaseDefinition(rootNode, generatedClassName, baseClassIdentifier, properties, constructorDeclaration, prevDeclaration); } // Update document var tree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false); var newRoot = root.ReplaceNode(classDeclarationSyntax.Parent, rootNode); var newDocument = document.WithSyntaxRoot(newRoot); return(newDocument); }