public GenerationResult(
     Document document,
     SemanticModel semanticModel,
     IReadOnlyList <Diagnostic> generatorDiagnostics,
     IReadOnlyList <Diagnostic> compilationDiagnostics)
 {
     this.Document               = document;
     this.SemanticModel          = semanticModel;
     this.Declarations           = CSharpDeclarationComputer.GetDeclarationsInSpan(semanticModel, TextSpan.FromBounds(0, semanticModel.SyntaxTree.Length), true, CancellationToken.None);
     this.GeneratorDiagnostics   = generatorDiagnostics;
     this.CompilationDiagnostics = compilationDiagnostics;
 }
예제 #2
0
 public ImmutableArray <DeclarationInfo> GetDeclarationsInSpan(SemanticModel model, TextSpan span, bool getSymbol, CancellationToken cancellationToken)
 {
     return(CSharpDeclarationComputer.GetDeclarationsInSpan(model, span, getSymbol, cancellationToken));
 }
예제 #3
0
 public GenerationResult(Document document, SemanticModel semanticModel)
 {
     this.Document      = document;
     this.SemanticModel = semanticModel;
     this.Declarations  = CSharpDeclarationComputer.GetDeclarationsInSpan(semanticModel, TextSpan.FromBounds(0, semanticModel.SyntaxTree.Length), true, CancellationToken.None);
 }
            public void Execute()
            {
                Task.Run(async delegate
                {
                    AppDomain.CurrentDomain.AssemblyResolve += (s, e) =>
                    {
                        return(this.TryLoadAssembly(new AssemblyName(e.Name)));
                    };

                    var project      = this.CreateProject();
                    var outputFiles  = new List <ITaskItem>();
                    var writtenFiles = new List <ITaskItem>();

                    string generatorAssemblyInputsFile = Path.Combine(this.IntermediateOutputDirectory, "CodeGeneration.Roslyn.InputAssemblies.txt");

                    // For incremental build, we want to consider the input->output files as well as the assemblies involved in code generation.
                    DateTime assembliesLastModified = GetLastModifiedAssemblyTime(generatorAssemblyInputsFile);

                    var explicitIncludeList = new HashSet <string>(
                        from item in this.Compile
                        where string.Equals(item.GetMetadata("Generator"), $"MSBuild:{this.TargetName}", StringComparison.OrdinalIgnoreCase)
                        select item.ItemSpec,
                        StringComparer.OrdinalIgnoreCase);

                    foreach (var inputDocument in project.Documents)
                    {
                        this.CancellationToken.ThrowIfCancellationRequested();

                        // Skip over documents that aren't on the prescribed list of files to scan.
                        if (!explicitIncludeList.Contains(inputDocument.Name))
                        {
                            continue;
                        }

                        string sourceHash     = inputDocument.Name.GetHashCode().ToString("x", CultureInfo.InvariantCulture);
                        string outputFilePath = Path.Combine(this.IntermediateOutputDirectory, Path.GetFileNameWithoutExtension(inputDocument.Name) + $".{sourceHash}.generated.cs");

                        // Code generation is relatively fast, but it's not free.
                        // And when we run the Simplifier.ReduceAsync it's dog slow.
                        // So skip files that haven't changed since we last generated them.
                        bool generated = false;
                        DateTime outputLastModified = File.GetLastWriteTime(outputFilePath);
                        if (File.GetLastWriteTime(inputDocument.Name) > outputLastModified || assembliesLastModified > outputLastModified)
                        {
                            this.Log.LogMessage(MessageImportance.Normal, "{0} -> {1}", inputDocument.Name, outputFilePath);

                            var outputDocument = await DocumentTransform.TransformAsync(
                                inputDocument,
                                new ProgressLogger(this.Log, inputDocument.Name));

                            // Only produce a new file if the generated document is not empty.
                            var semanticModel = await outputDocument.GetSemanticModelAsync(this.CancellationToken);
                            if (!CSharpDeclarationComputer.GetDeclarationsInSpan(semanticModel, TextSpan.FromBounds(0, semanticModel.SyntaxTree.Length), false, this.CancellationToken).IsEmpty)
                            {
                                var outputText = await outputDocument.GetTextAsync(this.CancellationToken);
                                using (var outputFileStream = File.OpenWrite(outputFilePath))
                                    using (var outputWriter = new StreamWriter(outputFileStream))
                                    {
                                        outputText.Write(outputWriter);

                                        // Truncate any data that may be beyond this point if the file existed previously.
                                        outputWriter.Flush();
                                        outputFileStream.SetLength(outputFileStream.Position);
                                    }

                                generated = true;
                            }
                        }
                        else
                        {
                            generated = true;
                        }

                        if (generated)
                        {
                            var outputItem = new TaskItem(outputFilePath);
                            outputFiles.Add(outputItem);
                        }
                    }

                    SaveGeneratorAssemblyList(generatorAssemblyInputsFile);
                    writtenFiles.Add(new TaskItem(generatorAssemblyInputsFile));

                    this.GeneratedCompile       = outputFiles.ToArray();
                    this.AdditionalWrittenFiles = writtenFiles.ToArray();
                }).GetAwaiter().GetResult();
            }
예제 #5
0
            public void Execute()
            {
                Task.Run(async delegate
                {
                    var project     = this.CreateProject();
                    var outputFiles = new List <ITaskItem>();

                    // For incremental build, we want to consider the input->output files as well as the assemblies involved in code generation.
                    DateTime assembliesLastModified = GetLastModifiedAssemblyTime();

                    foreach (var inputDocument in project.Documents)
                    {
                        this.CancellationToken.ThrowIfCancellationRequested();

                        // Skip over documents that aren't on the prescribed list of files to scan.
                        if (!this.CompileToGenerateFromAttributes.Any(i => i.ItemSpec == inputDocument.Name))
                        {
                            continue;
                        }

                        string outputFilePath = Path.Combine(this.IntermediateOutputDirectory, Path.GetFileNameWithoutExtension(inputDocument.Name) + ".generated.cs");

                        // Code generation is relatively fast, but it's not free.
                        // And when we run the Simplifier.ReduceAsync it's dog slow.
                        // So skip files that haven't changed since we last generated them.
                        bool generated = false;
                        DateTime outputLastModified = File.GetLastWriteTime(outputFilePath);
                        if (File.GetLastWriteTime(inputDocument.Name) > outputLastModified || assembliesLastModified > outputLastModified)
                        {
                            this.Log.LogMessage(MessageImportance.Normal, "{0} -> {1}", inputDocument.Name, outputFilePath);

                            var outputDocument = await DocumentTransform.TransformAsync(inputDocument, new ProgressLogger(this.Log, inputDocument.Name));

                            // Only produce a new file if the generated document is not empty.
                            var semanticModel = await outputDocument.GetSemanticModelAsync(this.CancellationToken);
                            if (!CSharpDeclarationComputer.GetDeclarationsInSpan(semanticModel, TextSpan.FromBounds(0, semanticModel.SyntaxTree.Length), false, this.CancellationToken).IsEmpty)
                            {
                                var outputText = await outputDocument.GetTextAsync(this.CancellationToken);
                                using (var outputFileStream = File.OpenWrite(outputFilePath))
                                    using (var outputWriter = new StreamWriter(outputFileStream))
                                    {
                                        outputText.Write(outputWriter);

                                        // Truncate any data that may be beyond this point if the file existed previously.
                                        outputWriter.Flush();
                                        outputFileStream.SetLength(outputFileStream.Position);
                                    }

                                generated = true;
                            }
                        }
                        else
                        {
                            generated = true;
                        }

                        if (generated)
                        {
                            var outputItem = new TaskItem(outputFilePath);
                            outputFiles.Add(outputItem);
                        }
                    }

                    this.GeneratedCompile = outputFiles.ToArray();
                }).GetAwaiter().GetResult();
            }