private static int Process(Options options) { try { Console.WriteLine("Start Process!"); // Resolve options var basePath = Path.GetFullPath(options.Path ?? "."); var sources = options.Sources.Where(p => string.IsNullOrWhiteSpace(p) == false && p.ToLower().IndexOf(".codegen.cs") == -1) .Select(p => MakeFullPath(p, basePath)) .ToArray(); var references = options.References.Where(p => string.IsNullOrWhiteSpace(p) == false) .Select(p => MakeFullPath(p, basePath)) .ToArray(); var targetDefaultPath = @".\Properties\TrackableData.CodeGen.cs"; var targetPath = MakeFullPath(options.TargetFile ?? targetDefaultPath, basePath); // Parse sources and extract interfaces Console.WriteLine("- Parse sources"); var syntaxTrees = sources.Select( file => CSharpSyntaxTree.ParseText(File.ReadAllText(file), path: file)).ToArray(); var interfaceDeclarations = syntaxTrees.SelectMany( st => st.GetRoot().DescendantNodes().OfType<InterfaceDeclarationSyntax>()).ToArray(); // Generate code Console.WriteLine("- Generate code"); var writer = new TextCodeGenWriter(); var relatedSourceTrees = new HashSet<SyntaxNode>(); // TrackablePoco var pocoCodeGen = new TrackablePocoCodeGenerator() { Options = options }; foreach (var idecl in interfaceDeclarations) { var baseType = idecl.GetGenericBase("TrackableData.ITrackablePoco"); if (baseType != null) { var pocoType = baseType.TypeArgumentList.Arguments[0].ToString(); if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), pocoType) == false) { throw new Exception($"Invalid base type of ITrackablePoco<{pocoType}>"); } pocoCodeGen.GenerateCode(idecl, writer); relatedSourceTrees.Add(idecl.GetRootNode()); } } // TrackableContainer var containerCodeGen = new TrackableContainerCodeGenerator() { Options = options }; foreach (var idecl in interfaceDeclarations) { var baseType = idecl.GetGenericBase("TrackableData.ITrackableContainer"); if (baseType != null) { var containerType = baseType.TypeArgumentList.Arguments[0].ToString(); if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), containerType) == false) { throw new Exception($"Invalid base type of ITrackableContainer<{containerType}>"); } containerCodeGen.GenerateCode(idecl, writer); relatedSourceTrees.Add(idecl.GetRootNode()); } } // Resolve referenced using var usingDirectives = new HashSet<string>(relatedSourceTrees.SelectMany( st => st.DescendantNodes().OfType<UsingDirectiveSyntax>()).Select(x => x.Name.ToString())); usingDirectives.Add("System"); usingDirectives.Add("System.Collections.Generic"); usingDirectives.Add("System.Reflection"); usingDirectives.Add("System.Runtime.Serialization"); usingDirectives.Add("System.Linq"); usingDirectives.Add("System.Text"); usingDirectives.Add("TrackableData"); foreach (var usingDirective in usingDirectives) writer.AddUsing(usingDirective); // Save generated code Console.WriteLine("- Save code"); if (SaveFileIfChanged(targetPath, writer.ToString()) == false) Console.WriteLine("Nothing changed. Skip writing."); return 0; } catch (Exception e) { Console.WriteLine("Exception in processing:\n" + e); return 1; } }
private static int Process(Options options) { try { Console.WriteLine("Start Process!"); // Resolve options var basePath = Path.GetFullPath(options.Path ?? "."); var sources = options.Sources.Where(p => string.IsNullOrWhiteSpace(p) == false && p.ToLower().IndexOf(".codegen.cs") == -1) .Select(p => MakeFullPath(p, basePath)) .ToArray(); var references = options.References.Where(p => string.IsNullOrWhiteSpace(p) == false) .Select(p => MakeFullPath(p, basePath)) .ToArray(); var targetDefaultPath = @".\Properties\TrackableData.CodeGen.cs"; var targetPath = MakeFullPath(options.TargetFile ?? targetDefaultPath, basePath); // Parse sources and extract interfaces Console.WriteLine("- Parse sources"); var syntaxTrees = sources.Select( file => CSharpSyntaxTree.ParseText(File.ReadAllText(file), path: file)).ToArray(); var interfaceDeclarations = syntaxTrees.SelectMany( st => st.GetRoot().DescendantNodes().OfType<InterfaceDeclarationSyntax>()).ToArray(); // Generate code Console.WriteLine("- Generate code"); var settings = new CodeWriterSettings(CodeWriterSettings.CSharpDefault); settings.TranslationMapping["`"] = "\""; var w = new CodeWriter.CodeWriter(settings); var relatedSourceTrees = new HashSet<SyntaxNode>(); w.HeadLines = new List<string> { "// ------------------------------------------------------------------------------", "// <auto-generated>", "// This code was generated by TrackableData.CodeGenerator.", "//", "// Changes to this file may cause incorrect behavior and will be lost if", "// the code is regenerated.", "// </auto-generated>", "// ------------------------------------------------------------------------------", "", "using System;", "using System.Collections.Generic;", "using System.Reflection;", "using System.Runtime.Serialization;", "using System.Linq;", "using System.Text;", "using TrackableData;", "" }; // TrackablePoco var pocoCodeGen = new TrackablePocoCodeGenerator() { Options = options }; foreach (var idecl in interfaceDeclarations) { var baseType = idecl.GetGenericBase("TrackableData.ITrackablePoco"); if (baseType != null) { var pocoType = baseType.TypeArgumentList.Arguments[0].ToString(); if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), pocoType) == false) { throw new Exception($"Invalid base type of ITrackablePoco<{pocoType}>"); } pocoCodeGen.GenerateCode(idecl, w); relatedSourceTrees.Add(idecl.GetRootNode()); } } // TrackableContainer var containerCodeGen = new TrackableContainerCodeGenerator() { Options = options }; foreach (var idecl in interfaceDeclarations) { var baseType = idecl.GetGenericBase("TrackableData.ITrackableContainer"); if (baseType != null) { var containerType = baseType.TypeArgumentList.Arguments[0].ToString(); if (CodeAnalaysisExtensions.CompareTypeName(idecl.Identifier.ToString(), containerType) == false) { throw new Exception($"Invalid base type of ITrackableContainer<{containerType}>"); } containerCodeGen.GenerateCode(idecl, w); relatedSourceTrees.Add(idecl.GetRootNode()); } } // Resolve referenced using var usingDirectives = new HashSet<string>(relatedSourceTrees.SelectMany( st => st.DescendantNodes().OfType<UsingDirectiveSyntax>()).Select(x => x.Name.ToString())); foreach (var usingDirective in usingDirectives) EnsureUsing(w, usingDirective); // Save generated code Console.WriteLine("- Save code"); if (w.WriteAllText(targetPath, true) == false) Console.WriteLine("Nothing changed. Skip writing."); return 0; } catch (Exception e) { Console.WriteLine("Exception in processing:\n" + e); return 1; } }