public static async Task<Document> TransformAsync(Document inputDocument, IProgressAndErrors progress, bool simplify = false)
        {
            Requires.NotNull(inputDocument, "inputDocument");

            var workspace = inputDocument.Project.Solution.Workspace;
            var inputSemanticModel = await inputDocument.GetSemanticModelAsync();
            var inputSyntaxTree = inputSemanticModel.SyntaxTree;

            var inputFileLevelUsingDirectives = inputSyntaxTree.GetRoot().ChildNodes().OfType<UsingDirectiveSyntax>();

            var memberNodes = from syntax in inputSyntaxTree.GetRoot().DescendantNodes(n => n is CompilationUnitSyntax || n is NamespaceDeclarationSyntax || n is TypeDeclarationSyntax).OfType<MemberDeclarationSyntax>()
                              select syntax;

            var emittedMembers = new List<MemberDeclarationSyntax>();
            foreach (var memberNode in memberNodes)
            {
                var namespaceNode = memberNode.Parent as NamespaceDeclarationSyntax;

                var generators = FindCodeGenerators(inputSemanticModel, memberNode);
                foreach (var generator in generators)
                {
                    var generatedTypes = await generator.GenerateAsync(memberNode, inputDocument, progress, CancellationToken.None);
                    if (namespaceNode != null)
                    {
                        emittedMembers.Add(SyntaxFactory.NamespaceDeclaration(namespaceNode.Name)
                            .WithUsings(SyntaxFactory.List(namespaceNode.ChildNodes().OfType<UsingDirectiveSyntax>()))
                            .WithMembers(SyntaxFactory.List(generatedTypes)));
                    }
                    else
                    {
                        emittedMembers.AddRange(generatedTypes);
                    }
                }
            }

            var emittedTree = SyntaxFactory.CompilationUnit()
                .WithUsings(SyntaxFactory.List(inputFileLevelUsingDirectives).Add(
                    SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName("ImmutableObjectGraph"))))
                .WithMembers(SyntaxFactory.List(emittedMembers))
                .WithLeadingTrivia(SyntaxFactory.Comment(GeneratedByAToolPreamble))
                .WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed);

            // Format the tree to get reasonably good whitespace.
            var formattedTree = Formatter.Format(emittedTree, workspace, workspace.Options);

            // Reduce the document to get rid of unnecessary fully-qualified type names that just hurt readability.
            var formattedText = formattedTree.GetText();
            var document = inputDocument.Project.AddDocument("generated.cs", formattedText);
            if (simplify)
            {
                var annotatedDocument = document
                    .WithSyntaxRoot((await document.GetSyntaxRootAsync())
                    .WithAdditionalAnnotations(Simplifier.Annotation)); // allow simplification of the entire document
                document = await Simplifier.ReduceAsync(annotatedDocument);
            }

            return document;
        }
        public static async Task <Document> TransformAsync(Document inputDocument, IProgressAndErrors progress, bool simplify = false)
        {
            Requires.NotNull(inputDocument, "inputDocument");

            var workspace          = inputDocument.Project.Solution.Workspace;
            var inputSemanticModel = await inputDocument.GetSemanticModelAsync();

            var inputSyntaxTree = inputSemanticModel.SyntaxTree;

            var inputFileLevelUsingDirectives = inputSyntaxTree.GetRoot().ChildNodes().OfType <UsingDirectiveSyntax>();

            var memberNodes = from syntax in inputSyntaxTree.GetRoot().DescendantNodes(n => n is CompilationUnitSyntax || n is NamespaceDeclarationSyntax || n is TypeDeclarationSyntax).OfType <MemberDeclarationSyntax>()
                              select syntax;

            var emittedMembers = new List <MemberDeclarationSyntax>();

            foreach (var memberNode in memberNodes)
            {
                var namespaceNode = memberNode.Ancestors().OfType <NamespaceDeclarationSyntax>().FirstOrDefault();

                var generators = FindCodeGenerators(inputSemanticModel, memberNode);
                foreach (var generator in generators)
                {
                    var generatedTypes = await generator.GenerateAsync(memberNode, inputDocument, progress, CancellationToken.None);

                    if (namespaceNode != null)
                    {
                        emittedMembers.Add(SyntaxFactory.NamespaceDeclaration(namespaceNode.Name)
                                           .WithUsings(SyntaxFactory.List(namespaceNode.ChildNodes().OfType <UsingDirectiveSyntax>()))
                                           .WithMembers(SyntaxFactory.List(generatedTypes)));
                    }
                    else
                    {
                        emittedMembers.AddRange(generatedTypes);
                    }
                }
            }

            // By default, retain all the using directives that came from the input file.
            var resultFileLevelUsingDirectives = SyntaxFactory.List(inputFileLevelUsingDirectives);

            // Add a using directive for the ImmutableObjectGraph if there isn't one.
            var immutableObjectGraphName = nameof(ImmutableObjectGraph);

            if (!resultFileLevelUsingDirectives.Any(u => u.Name.ToString() == immutableObjectGraphName))
            {
                resultFileLevelUsingDirectives = resultFileLevelUsingDirectives.Add(
                    SyntaxFactory.UsingDirective(SyntaxFactory.IdentifierName(immutableObjectGraphName)));
            }

            var emittedTree = SyntaxFactory.CompilationUnit()
                              .WithUsings(resultFileLevelUsingDirectives)
                              .WithMembers(SyntaxFactory.List(emittedMembers))
                              .WithLeadingTrivia(SyntaxFactory.Comment(GeneratedByAToolPreamble))
                              .WithTrailingTrivia(SyntaxFactory.CarriageReturnLineFeed)
                              .NormalizeWhitespace();

            // Format the tree to get reasonably good whitespace.
            var formattedTree = Formatter.Format(emittedTree, workspace, workspace.Options);

            // Reduce the document to get rid of unnecessary fully-qualified type names that just hurt readability.
            var formattedText = formattedTree.GetText();
            var document      = inputDocument.Project.AddDocument("generated.cs", formattedText);

            if (simplify)
            {
                var annotatedDocument = document
                                        .WithSyntaxRoot((await document.GetSyntaxRootAsync())
                                                        .WithAdditionalAnnotations(Simplifier.Annotation)); // allow simplification of the entire document
                document = await Simplifier.ReduceAsync(annotatedDocument);
            }

            return(document);
        }
 /// <summary>
 /// Create the syntax tree representing the expansion of some member to which this attribute is applied.
 /// </summary>
 /// <param name="applyTo">The syntax node this attribute is found on.</param>
 /// <param name="document">The document with the semantic model in which this attribute was found.</param>
 /// <param name="progress">A way to report progress, errors and warnings.</param>
 /// <param name="cancellationToken">A cancellation token.</param>
 /// <returns>The generated member syntax to be added to the project.</returns>
 public abstract Task <IReadOnlyList <MemberDeclarationSyntax> > GenerateAsync(MemberDeclarationSyntax applyTo, Document document, IProgressAndErrors progress, CancellationToken cancellationToken);
        public override Task <IReadOnlyList <MemberDeclarationSyntax> > GenerateAsync(MemberDeclarationSyntax applyTo, Document document, IProgressAndErrors progress, CancellationToken cancellationToken)
        {
            var options = new CodeGen.Options
            {
                GenerateBuilder              = this.GenerateBuilder,
                Delta                        = this.Delta,
                DefineInterface              = this.DefineInterface,
                DefineRootedStruct           = this.DefineRootedStruct,
                DefineWithMethodsPerProperty = this.DefineWithMethodsPerProperty,
            };

            return(CodeGen.GenerateAsync((ClassDeclarationSyntax)applyTo, document, progress, options, cancellationToken));
        }
        public Task <IReadOnlyList <MemberDeclarationSyntax> > GenerateAsync(MemberDeclarationSyntax applyTo, Document document, IProgressAndErrors progress, CancellationToken cancellationToken)
        {
            Requires.NotNull(applyTo, nameof(applyTo));

            var options = new CodeGen.Options
            {
                GenerateBuilder              = this.GetBoolData(nameof(GenerateImmutableAttribute.GenerateBuilder)),
                Delta                        = this.GetBoolData(nameof(GenerateImmutableAttribute.Delta)),
                DefineInterface              = this.GetBoolData(nameof(GenerateImmutableAttribute.DefineInterface)),
                DefineRootedStruct           = this.GetBoolData(nameof(GenerateImmutableAttribute.DefineRootedStruct)),
                DefineWithMethodsPerProperty = this.GetBoolData(nameof(GenerateImmutableAttribute.DefineWithMethodsPerProperty)),
            };

            return(CodeGen.GenerateAsync((ClassDeclarationSyntax)applyTo, document, progress, options, cancellationToken));
        }