public static void Generate(IEnumerable <Assembly> asms, StringBuilder output) { if (!_resolverRegistered) { throw new InvalidOperationException("please call RegisterAssemblyResolver() first so you can get better error messages when a DLL can't be loaded!"); } var(ceras, targets) = CreateSerializerAndTargets(asms); SourceFormatterGenerator.GenerateAll(targets, ceras, output); }
static void Main(string[] args) { if (args.Length < 2) { var error = "Not enough arguments. The last argument is always the .cs file output path, all arguments before that are the input assemblies (.dll files) of your unity project. Example: \"C:\\MyUnityProject\\Temp\\bin\\Debug\\Assembly-CSharp.dll C:\\MyUnityProject\\Assets\\Scripts\\GeneratedFormatters.cs\""; Console.WriteLine(error); throw new ArgumentException(error); } inputAssemblies = args.Reverse().Skip(1).Reverse().ToArray(); outputCsFileName = args.Reverse().First(); AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; var asms = inputAssemblies.Select(Assembly.LoadFrom); var(ceras, targets) = CreateSerializerAndTargets(asms); StringBuilder fullCode = new StringBuilder(25 * 1000); fullCode.AppendLine("using Ceras;"); fullCode.AppendLine("using Ceras.Formatters;"); fullCode.AppendLine("namespace Ceras.GeneratedFormatters"); fullCode.AppendLine("{"); var setCustomFormatters = targets.Select(t => $"config.ConfigType<{t.FullName}>().CustomFormatter = new {t.Name}Formatter();"); fullCode.AppendLine($@" static class GeneratedFormatters {{ internal static void UseFormatters(SerializerConfig config) {{ {string.Join("\n", setCustomFormatters)} }} }} "); foreach (var t in targets) { SourceFormatterGenerator.Generate(t, ceras, fullCode); } fullCode.AppendLine("}"); Console.WriteLine($"Parsing..."); var syntaxTree = CSharpSyntaxTree.ParseText(fullCode.ToString()); Console.WriteLine($"Formatting..."); var workspace = new AdhocWorkspace(); var options = workspace.Options .WithChangedOption(CSharpFormattingOptions.IndentBlock, true) .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInAccessors, true) .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInControlBlocks, true) .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInTypes, true) .WithChangedOption(CSharpFormattingOptions.IndentBraces, false); syntaxTree = Formatter.Format(syntaxTree.GetRoot(), workspace, options).SyntaxTree; Console.WriteLine($"Saving..."); using (var fs = File.OpenWrite(outputCsFileName)) using (var w = new StreamWriter(fs)) { fs.SetLength(0); w.WriteLine(syntaxTree.ToString()); } // todo: maybe we'll generate an assembly instead of source code at some pointlater... //GenerateFormattersAssembly(targets); Thread.Sleep(300); Console.WriteLine($"> Done!"); }
static void Main(string[] args) { if (args.Length < 2) { var error = "Not enough arguments. The last argument is always the .cs file output path, all arguments before that are the input assemblies (.dll files) of your unity project. Example: \"C:\\MyUnityProject\\Temp\\bin\\Debug\\Assembly-CSharp.dll C:\\MyUnityProject\\Assets\\Scripts\\GeneratedFormatters.cs\""; Console.WriteLine(error); throw new ArgumentException(error); } inputAssemblies = args.Reverse().Skip(1).Reverse().ToArray(); outputCsFileName = args.Reverse().First(); var marker = typeof(CerasAutoGenFormatterAttribute); AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; var asms = inputAssemblies.Select(Assembly.LoadFrom); var targets = asms.SelectMany(a => a.GetTypes()) .Where(t => t.GetCustomAttributes(true) .Any(a => a.GetType().FullName == marker.FullName)) .Where(t => !t.IsAbstract) .ToList(); Console.WriteLine($"Found: {targets.Count} targets"); // Find config method and create a SerializerConfig SerializerConfig config = new SerializerConfig(); var configMethods = asms.SelectMany(a => a.GetTypes()) .SelectMany(t => t.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) .Where(m => m.GetCustomAttribute <CerasAutoGenConfigAttribute>() != null) .ToArray(); if (configMethods.Length > 1) { throw new Exception("Found more than one config method!"); } if (configMethods.Length == 1) { config = (SerializerConfig)configMethods[0].Invoke(null, null); } targets.AddRange(config.KnownTypes); var ceras = new CerasSerializer(config); StringBuilder fullCode = new StringBuilder(25 * 1000); fullCode.AppendLine("using Ceras;"); fullCode.AppendLine("using Ceras.Formatters;"); fullCode.AppendLine("namespace Ceras.GeneratedFormatters"); fullCode.AppendLine("{"); var setCustomFormatters = targets.Select(t => $"config.ConfigType<{t.FullName}>().CustomFormatter = new {t.Name}Formatter();"); fullCode.AppendLine($@" static class GeneratedFormatters {{ internal static void UseFormatters(SerializerConfig config) {{ {string.Join("\n", setCustomFormatters)} }} }} "); foreach (var t in targets) { SourceFormatterGenerator.Generate(t, ceras, fullCode); } fullCode.AppendLine("}"); Console.WriteLine($"Parsing..."); var syntaxTree = CSharpSyntaxTree.ParseText(fullCode.ToString()); Console.WriteLine($"Formatting..."); var workspace = new AdhocWorkspace(); var options = workspace.Options .WithChangedOption(CSharpFormattingOptions.IndentBlock, true) .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInAccessors, true) .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInControlBlocks, true) .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInTypes, true) .WithChangedOption(CSharpFormattingOptions.IndentBraces, false); syntaxTree = Formatter.Format(syntaxTree.GetRoot(), workspace, options).SyntaxTree; Console.WriteLine($"Saving..."); using (var fs = File.OpenWrite(outputCsFileName)) using (var w = new StreamWriter(fs)) { fs.SetLength(0); w.WriteLine(syntaxTree.ToString()); } // todo: maybe we'll generate an assembly instead of source code at some pointlater... //GenerateFormattersAssembly(targets); Thread.Sleep(300); Console.WriteLine($"> Done!"); }
public static void Generate(IEnumerable <Assembly> asms, StringBuilder output) { var(ceras, targets) = CreateSerializerAndTargets(asms); SourceFormatterGenerator.GenerateAll(targets, ceras, output); }