using EdjCase.ICP.Candid.Mapping.Mappers; using EdjCase.ICP.Candid.Models; using EdjCase.ICP.Candid.Models.Types; using EdjCase.ICP.Candid.Models.Values; using EdjCase.ICP.ClientGenerator; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Options; using Microsoft.VisualBasic; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace EdjCase.ICP.ClientGenerator { /// /// A model containing the client code to be rendered /// public class ClientSyntax { /// /// The name of the client /// public string Name { get; } /// /// The syntax of the client file /// public CompilationUnitSyntax ClientFile { get; } /// /// The syntax of different declared types for the client /// public List<(string Name, CompilationUnitSyntax Syntax)> TypeFiles { get; } /// The name of the client /// The syntax of the client file /// The syntax of different declared types for the client public ClientSyntax(string name, CompilationUnitSyntax clientFile, List<(string Name, CompilationUnitSyntax Syntax)> typeFiles) { this.Name = name ?? throw new ArgumentNullException(nameof(name)); this.ClientFile = clientFile ?? throw new ArgumentNullException(nameof(clientFile)); this.TypeFiles = typeFiles ?? throw new ArgumentNullException(nameof(typeFiles)); } /// /// Rewrites the syntax with the specified `CSharpSyntaxRewriter` /// /// A `CSharpSyntaxRewriter` to rewrite the csharp syntax /// Updated client syntax public ClientSyntax Rewrite(CSharpSyntaxRewriter rewriter) { CompilationUnitSyntax updatedClientFile = (CompilationUnitSyntax)rewriter.Visit(this.ClientFile); List<(string Name, CompilationUnitSyntax updatedSyntax)> updatedTypeFiles = this.TypeFiles .Select((typeFile) => { CompilationUnitSyntax updatedSyntax = (CompilationUnitSyntax)rewriter.Visit(typeFile.Syntax); return (typeFile.Name, updatedSyntax); }) .ToList(); return new ClientSyntax(this.Name, updatedClientFile, updatedTypeFiles); } /// /// Converts the file syntax objects into source code string values to use as a file /// /// Client and type source code file contents public (string ClientFile, List<(string Name, string Contents)> TypeFiles) GenerateFileContents() { string clientFile = GenerateFileContents(this.ClientFile); List<(string Name, string Contents)> typeFileContents = this.TypeFiles .Select((typeFile) => { string contents = GenerateFileContents(typeFile.Syntax); return (typeFile.Name, contents); }) .ToList(); return (clientFile, typeFileContents); } /// /// Helper function to turn a client or type into a string of file contents /// /// The client or type file to convert to a string /// String source code of the specified syntax public static string GenerateFileContents(CompilationUnitSyntax syntax) { // Setup formatting options AdhocWorkspace workspace = new(); OptionSet options = workspace.Options .WithChangedOption(FormattingOptions.UseTabs, LanguageNames.CSharp, value: true) .WithChangedOption(FormattingOptions.NewLine, LanguageNames.CSharp, value: Environment.NewLine); return Formatter.Format(syntax, workspace, options).ToFullString(); } } }