diff --git a/mROA.Codegen/MethodRepo.cstmpl b/mROA.Codegen/MethodRepo.cstmpl index 2c52517..b20123c 100644 --- a/mROA.Codegen/MethodRepo.cstmpl +++ b/mROA.Codegen/MethodRepo.cstmpl @@ -11,7 +11,8 @@ namespace mROA.Codegen public class CoCodegenMethodRepository : IMethodRepository { private readonly List _methods = new () { - + , + }; public IMethodInvoker GetMethod(int id) diff --git a/mROA.Codegen/RemoteEndpoint.cstmpl b/mROA.Codegen/RemoteEndpoint.cstmpl new file mode 100644 index 0000000..f703b0a --- /dev/null +++ b/mROA.Codegen/RemoteEndpoint.cstmpl @@ -0,0 +1,19 @@ +// +using mROA; +using System; +using mROA.Implementation; +using System.Collections.Generic; +using mROA.Abstract; + +namespace +{ + partial class : RemoteObjectBase, + { + public (int id, IRepresentationModule representationModule) : base(id, representationModule) + { + } + + + + } +} \ No newline at end of file diff --git a/mROA.Codegen/Tools/DefineTemplateSection.cs b/mROA.Codegen/Tools/DefineTemplateSection.cs new file mode 100644 index 0000000..fcc926e --- /dev/null +++ b/mROA.Codegen/Tools/DefineTemplateSection.cs @@ -0,0 +1,32 @@ +using System; + +namespace mROA.CodegenTools +{ + public class DefineTemplateSection : ITagged + { + public TemplateDocument Context { get; set; } + public string StoredText { get; } + private readonly string _tag; + + public DefineTemplateSection(string storedText, string tag, TemplateDocument context) + { + StoredText = storedText; + _tag = tag; + Context = context; + } + + public string Tag => _tag; + public int TargetLength => StoredText.Length; + + + public override string ToString() + { + return StoredText; + } + + public object Clone() + { + return new DefineTemplateSection(StoredText, _tag, Context); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Tools/ITemplateSection.cs b/mROA.Codegen/Tools/ITemplateSection.cs new file mode 100644 index 0000000..7712282 --- /dev/null +++ b/mROA.Codegen/Tools/ITemplateSection.cs @@ -0,0 +1,21 @@ +using System; + +namespace mROA.CodegenTools +{ + public interface ITemplateSection : ICloneable + { + TemplateDocument Context { get; set; } + int TargetLength { get; } + } + + public interface IBaking + { + string Bake(); + } + + + public interface ITagged : ITemplateSection + { + string Tag { get; } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Tools/InnerTemplateSection.cs b/mROA.Codegen/Tools/InnerTemplateSection.cs new file mode 100644 index 0000000..f347086 --- /dev/null +++ b/mROA.Codegen/Tools/InnerTemplateSection.cs @@ -0,0 +1,25 @@ +namespace mROA.CodegenTools +{ + public class InnerTemplateSection : ITemplateSection, ITagged + { + private readonly string _tag; + public TemplateDocument Context { get; set; } + public int TargetLength => 0; + + public string Tag => _tag; + + public TemplateDocument InnerTemplate { get; } + + public InnerTemplateSection(string tag, TemplateDocument innerTemplate, TemplateDocument context) + { + _tag = tag; + Context = context; + InnerTemplate = innerTemplate; + } + + public object Clone() + { + return new InnerTemplateSection(_tag, InnerTemplate, Context); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Tools/InsertTemplatePart.cs b/mROA.Codegen/Tools/InsertTemplatePart.cs new file mode 100644 index 0000000..54c4391 --- /dev/null +++ b/mROA.Codegen/Tools/InsertTemplatePart.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace mROA.CodegenTools +{ + public class InsertTemplatePart : ITagged, IBaking + { + private object _insertedValue; + private string _tag; + public string Tag => _tag; + public TemplateDocument Context { get; set; } + public readonly List Parameters; + + public InsertTemplatePart(string tag, TemplateDocument context, params string[] parameters) + { + _tag = tag; + Parameters = parameters.ToList(); + Context = context; + } + + private bool IsInserted(object value) + { + if (Parameters.IndexOf("r") == -1) return false; + + ProduceInserted(value); + + return true; + } + + private void ProduceInserted(object value) + { + var currentIndex = Context.Parts.IndexOf(this); + var clone = (InsertTemplatePart)MemberwiseClone(); + clone._tag += "+"; + + clone._insertedValue = value; + + Context.Parts.Insert(currentIndex, clone); + + InsertSeparator(currentIndex + 1); + } + + private void InsertSeparator(int currentIndex) + { + var sepIndex = Parameters.IndexOf("sep"); + if (sepIndex == -1) + return; + + Context.Parts.Insert(currentIndex, new LiteralTemplateSection(Context[Parameters[sepIndex + 1]].ToString(), Context)); + + } + + + public void Setup(object value) + { + if (!(value is string) && !(value is ITemplateSection) ) + return; + if (IsInserted(value)) + return; + + _insertedValue = value; + } + + + public int TargetLength => 0; + + public string Bake() + { + switch (_insertedValue) + { + case null: + return string.Empty; + case string s: + return s; + default: + return ((ITemplateSection)_insertedValue).ToString(); + } + } + + public object Clone() + { + return new InsertTemplatePart(_tag, Context, Parameters.ToArray()); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Tools/LinkTemplateSection.cs b/mROA.Codegen/Tools/LinkTemplateSection.cs new file mode 100644 index 0000000..8870674 --- /dev/null +++ b/mROA.Codegen/Tools/LinkTemplateSection.cs @@ -0,0 +1,43 @@ +using System.Linq; + +namespace mROA.CodegenTools +{ + public class LinkTemplateSection : ITemplateSection, IBaking + { + private readonly string _linkedTag; + + public LinkTemplateSection(string linkedTag, TemplateDocument context) + { + _linkedTag = linkedTag; + Context = context; + } + + public TemplateDocument Context { get; set; } + + public string LinkedTag => _linkedTag; + + public int TargetLength + { + get + { + var attached = Context[_linkedTag]; + return attached?.TargetLength ?? 0; + } + } + + public string Bake() + { + return Context[_linkedTag]?.ToString(); + } + + public override string ToString() + { + return $"{nameof(LinkedTag)}: {_linkedTag}"; + } + + public object Clone() + { + return new LinkTemplateSection(_linkedTag, Context); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Tools/LiteralTemplateSection.cs b/mROA.Codegen/Tools/LiteralTemplateSection.cs new file mode 100644 index 0000000..b28fe72 --- /dev/null +++ b/mROA.Codegen/Tools/LiteralTemplateSection.cs @@ -0,0 +1,31 @@ +namespace mROA.CodegenTools +{ + public class LiteralTemplateSection : ITemplateSection, IBaking + { + private string _internalText; + + public LiteralTemplateSection(string internalText, TemplateDocument context) + { + _internalText = internalText; + Context = context; + } + + public TemplateDocument Context { get; set; } + public int TargetLength => _internalText.Length; + + public string Bake() + { + return ToString(); + } + + public override string ToString() + { + return _internalText; + } + + public object Clone() + { + return new LiteralTemplateSection(_internalText, Context); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Tools/ProgrammableTextSection.cs b/mROA.Codegen/Tools/ProgrammableTextSection.cs new file mode 100644 index 0000000..5d91bd5 --- /dev/null +++ b/mROA.Codegen/Tools/ProgrammableTextSection.cs @@ -0,0 +1,29 @@ +using System; + +namespace mROA.CodegenTools +{ + public class ProgrammableTextSection : ITemplateSection, IBaking + { + public TemplateDocument Context { get; set; } + public int TargetLength => 0; + + private Func _bakeFunc; + + public ProgrammableTextSection(Func bakeFunc, TemplateDocument context) + { + _bakeFunc = bakeFunc; + Context = context; + } + + + public string Bake() + { + return _bakeFunc(Context.AdditionalContext); + } + + public object Clone() + { + return new ProgrammableTextSection(_bakeFunc, Context); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Tools/Reading/DefineSectionReader.cs b/mROA.Codegen/Tools/Reading/DefineSectionReader.cs new file mode 100644 index 0000000..5d4f7e0 --- /dev/null +++ b/mROA.Codegen/Tools/Reading/DefineSectionReader.cs @@ -0,0 +1,24 @@ +using System; + +namespace mROA.CodegenTools +{ + public class DefineSectionReader : LeadingTextSectionReader + { + public DefineSectionReader() : base("", index, StringComparison.Ordinal); + var sectionName = GetTagValue(index, tagEnd); + tagEnd += 1; + var endIndex = TemplateText.IndexOf("", tagEnd, StringComparison.Ordinal); + var storedText = TemplateText.Substring(tagEnd, endIndex - tagEnd); + index = endIndex + 4; + PassCaretToCloseSymbol(); + PassCaretToCloseSymbol(); + return new DefineTemplateSection(storedText, sectionName, document); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Tools/Reading/ISectionReader.cs b/mROA.Codegen/Tools/Reading/ISectionReader.cs new file mode 100644 index 0000000..0ed658e --- /dev/null +++ b/mROA.Codegen/Tools/Reading/ISectionReader.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace mROA.CodegenTools +{ + public interface ISectionReader + { + string TemplateText { get; set; } + int GetNextSectionIndex(int currentIndex); + ITemplateSection ExtractSection(ref int index, TemplateDocument document); + } +} \ No newline at end of file diff --git a/mROA.Codegen/Tools/Reading/InnerTemplateSectionReader.cs b/mROA.Codegen/Tools/Reading/InnerTemplateSectionReader.cs new file mode 100644 index 0000000..9b84f2c --- /dev/null +++ b/mROA.Codegen/Tools/Reading/InnerTemplateSectionReader.cs @@ -0,0 +1,39 @@ +using System; + +namespace mROA.CodegenTools +{ + public class InnerTemplateSectionReader : LeadingTextSectionReader + { + public InnerTemplateSectionReader() + : base("", start, StringComparison.Ordinal); + var innerStartSymbol = TemplateText.IndexOf("", _currentCaretPosition, StringComparison.Ordinal) + 1; + return _currentCaretPosition; + } + + public string TemplateText { get; set; } + + public int GetNextSectionIndex(int currentIndex) + { + _currentCaretPosition = Math.Max(currentIndex, _currentCaretPosition); + var index = TemplateText.IndexOf(_tagLeading, _currentCaretPosition, StringComparison.Ordinal); + _currentCaretPosition = index; + return index; + } + + public abstract ITemplateSection ExtractSection(ref int index, TemplateDocument document); + + protected string GetTagValue(int from, int to) + { + var realStart = from + 4; + var span = TemplateText.AsSpan(); + var slice = span.Slice(realStart, to - realStart); + return new string(slice.ToArray()); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Tools/Reading/LinkSectionReader.cs b/mROA.Codegen/Tools/Reading/LinkSectionReader.cs new file mode 100644 index 0000000..15f53f0 --- /dev/null +++ b/mROA.Codegen/Tools/Reading/LinkSectionReader.cs @@ -0,0 +1,20 @@ +namespace mROA.CodegenTools +{ + public class LinkSectionReader : LeadingTextSectionReader + { + public LinkSectionReader() : base(" ReaderTypes = new List + { + typeof(DefineSectionReader), + typeof(InsertSectionReader), + typeof(LinkSectionReader), + typeof(InnerTemplateSectionReader) + }; + + public static TemplateDocument Parse(string templateText) + { + + int currentIndex = 0; + var activeReaders = new List(); + + foreach (var readerType in ReaderTypes) + { + var reader = Activator.CreateInstance(readerType) as ISectionReader; + reader.TemplateText = templateText; + activeReaders.Add(reader); + } + + var doc = new TemplateDocument(); + + while (currentIndex < templateText.Length) + { + List<(ISectionReader reader, int index)> indices = activeReaders.Select(i => ((ISectionReader Readers, int index))(i, i.GetNextSectionIndex(currentIndex))).Where(i => i.index > -1).ToList(); + int minIndex = templateText.Length; + ISectionReader minReader = null; + if (indices.Count != 0) + { + minIndex = indices.Min(i => i.index); + minReader = indices.FirstOrDefault(i => i.index == minIndex).reader; + + if (indices.Count != activeReaders.Count) + { + activeReaders = indices.Select(i => i.reader).ToList(); + } + } + + + if (currentIndex != minIndex) + { + var literalText = templateText.Substring(currentIndex, minIndex - currentIndex); + var literal = + new LiteralTemplateSection(literalText, doc); + doc.Parts.Add(literal); + currentIndex = minIndex; + } + + if (indices.Count != 0) + { + var section = minReader.ExtractSection(ref currentIndex, doc); + doc.Parts.Add(section); + } + + + } + + return doc; + } + + public static TemplateDocument FromEmbeddedResource(string resourceName) + { + return FromEmbeddedResource(resourceName, Assembly.GetCallingAssembly()); + } + + public static TemplateDocument FromEmbeddedResource(string resourceName, Assembly assembly) + { + var fileName = assembly.GetManifestResourceNames().First(n => n.EndsWith(resourceName)); + var res = assembly.GetManifestResourceStream(fileName); + var reader = new StreamReader(res); + var templateText = reader.ReadToEnd(); + return Parse(templateText); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/Tools/TemplateDocument.cs b/mROA.Codegen/Tools/TemplateDocument.cs new file mode 100644 index 0000000..6567006 --- /dev/null +++ b/mROA.Codegen/Tools/TemplateDocument.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace mROA.CodegenTools +{ + public class TemplateDocument : ICloneable + { + public List Parts { get; set; } = new List(); + public object AdditionalContext { get; set; } + public ITagged this[string tag] => Parts.OfType().FirstOrDefault(i => i.Tag == tag); + + public void Insert(string tag, object value) + { + var selectedPart = this[tag]; + if (selectedPart is InsertTemplatePart itp) + { + itp.Setup(value); + } + } + + public string Compile() + { + var approximatelyLength = Parts.Sum(i => i.TargetLength); + var stringBuilder = new StringBuilder(approximatelyLength); + + foreach (var part in Parts.OfType()) + { + var baked = part.Bake(); + stringBuilder.Append(baked); + } + + return stringBuilder.ToString(); + } + + public object Clone() + { + var cloneDoc = new TemplateDocument + { + AdditionalContext = AdditionalContext is ICloneable c ? c.Clone() : AdditionalContext + }; + + cloneDoc.Parts = Parts.Select(i => + { + var clone = i.Clone() as ITemplateSection; + clone.Context = cloneDoc; + return clone; + }).ToList(); + + return cloneDoc; + } + + public void AddDefine(string tag, string text) + { + Parts.Add(new DefineTemplateSection(text, tag, this)); + } + } +} \ No newline at end of file diff --git a/mROA.Codegen/mROA.Codegen.csproj b/mROA.Codegen/mROA.Codegen.csproj index 658a3e6..1d06379 100644 --- a/mROA.Codegen/mROA.Codegen.csproj +++ b/mROA.Codegen/mROA.Codegen.csproj @@ -25,20 +25,19 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + + + + + + + + + + + + - - - - - - - - - - - - diff --git a/mROA.Codegen/mROASourceGenerator.cs b/mROA.Codegen/mROASourceGenerator.cs index 25609fb..85edf25 100644 --- a/mROA.Codegen/mROASourceGenerator.cs +++ b/mROA.Codegen/mROASourceGenerator.cs @@ -3,11 +3,13 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.IO; using System.Linq; using System.Text; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; +using mROA.CodegenTools; namespace mROA.Codegen { @@ -18,6 +20,10 @@ namespace mROA.Codegen [Generator] public class mROASourceGenerator : ISourceGenerator { + private TemplateDocument MethodRepoTemplate; + private TemplateDocument ClassTemplateOriginal; + private TemplateDocument ClassTemplate; + private static Predicate ParameterFilter = i => i.Type.Name is "CancellationToken" or "RequestContext"; @@ -26,35 +32,44 @@ namespace mROA.Codegen public void Initialize(GeneratorInitializationContext context) { + MethodRepoTemplate = TemplateReader.FromEmbeddedResource("MethodRepo.cstmpl"); + ClassTemplateOriginal = TemplateReader.FromEmbeddedResource("RemoteEndpoint.cstmpl"); } public void Execute(GeneratorExecutionContext context) { - var trees = context.Compilation.SyntaxTrees; - - var interfaces = new List(); - foreach (var tree in trees) + try { - var node = tree.GetRoot() as CompilationUnitSyntax; + var trees = context.Compilation.SyntaxTrees; - foreach (var member in node.Members) + var interfaces = new List(); + foreach (var tree in trees) { - if (member is InterfaceDeclarationSyntax ids) - { - interfaces.Add(ids); - } - else if (member is NamespaceDeclarationSyntax nds) - { - foreach (var inside in nds.Members) + var node = tree.GetRoot() as CompilationUnitSyntax; - if (inside is InterfaceDeclarationSyntax ids2) - if (ContainsSOIAttribute(ids2.AttributeLists, context, ids2)) - interfaces.Add(ids2); + foreach (var member in node.Members) + { + if (member is InterfaceDeclarationSyntax ids) + { + interfaces.Add(ids); + } + else if (member is NamespaceDeclarationSyntax nds) + { + foreach (var inside in nds.Members) + + if (inside is InterfaceDeclarationSyntax ids2) + if (ContainsSOIAttribute(ids2.AttributeLists, context, ids2)) + interfaces.Add(ids2); + } } } - } - GenerateCode(context, context.Compilation, interfaces.ToImmutableArray()); + GenerateCode(context, context.Compilation, interfaces.ToImmutableArray()); + } + catch (Exception) + { + Console.WriteLine("ERROR: Unable to load method repository"); + } } private void GenerateCode(GeneratorExecutionContext context, Compilation compilation, @@ -97,7 +112,7 @@ namespace mROA.Codegen className = className.TrimStart('I') + "RemoteEndpoint"; - + ClassTemplate = (TemplateDocument)ClassTemplateOriginal.Clone(); var declaredMethods = new List(); var propertiesAccessMethods = new List<(string, IMethodSymbol)>(); @@ -136,38 +151,24 @@ namespace mROA.Codegen impl = $"public {propertySymbol.Type.ToDisplayString()} {symbol.Name} {{ {getter.Item1} {setter.Item1} }}"; } - - declaredMethods.Add(impl); + ClassTemplate.Insert("methods", impl); + // declaredMethods.Add(impl); break; case IEventSymbol eventSymbol: - declaredMethods.Add( - $"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};"); + ClassTemplate.Insert("methods", $"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};"); + // declaredMethods.Add( + // $"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};"); break; } } GenerateEventImplementation(classSymbol, invokers, declaredMethods, context, eventBinders); - var code = $@"// - -using mROA; -using System; -using mROA.Implementation; -using System.Collections.Generic; -using mROA.Abstract; - -namespace {namespaceName} -{{ - partial class {className} : RemoteObjectBase, {originalName} - {{ - public {className}(int id, IRepresentationModule representationModule) : base(id, representationModule) - {{ - }} - - {string.Join("\r\n\t\t", declaredMethods)} - }} -}} -"; + ClassTemplate.AddDefine("className", className); + ClassTemplate.AddDefine("originalName", originalName); + ClassTemplate.AddDefine("namespaceName", namespaceName); + + var code = ClassTemplate.Compile(); // Add the source code to the compilation. @@ -182,39 +183,11 @@ namespace {namespaceName} { var methodsStringed = invokers; - var coCodegenRepoCode = @$"// -using System.Collections.Generic; -using System.Reflection; -using mROA.Abstract; -using mROA.Implementation; -using System; -using System.Threading; + // var invokersJoin = string.Join(",\r\n\t\t\t", methodsStringed); -namespace mROA.Codegen -{{ - public class CoCodegenMethodRepository : IMethodRepository - {{ - private readonly List _methods = new () {{ - {string.Join(",\r\n\t\t\t", methodsStringed)} - }}; + // MethodRepoTemplate.Insert("invoker", invokersJoin); - public IMethodInvoker GetMethod(int id) - {{ - if (id == -1) - return mROA.Implementation.MethodInvoker.Dispose; - - if (_methods.Count <= id) - return null; - - return _methods[id]; - }} - - public void Inject(T dependency) - {{ - }} - }} -}} -"; + var coCodegenRepoCode = MethodRepoTemplate.Compile(); #if !DONT_ADD context.AddSource("CoCodegenMethodRepository.g.cs", SourceText.From(coCodegenRepoCode, Encoding.UTF8)); #endif @@ -264,7 +237,9 @@ namespace mROA.Codegen var currentEvent = events[i]; var additionalMethod = GenerateMethodExternalCaller(currentEvent, out var signature); - declaredMethods.Add(additionalMethod); + ClassTemplate.Insert("methods", additionalMethod); + + // declaredMethods.Add(additionalMethod); additionalSignatures.Add(signature); GenerateEventCode(currentEvent, invokers, classSymbol); GenerateBinderCode(currentEvent, invokers, classSymbol, singleEventBinder); @@ -382,8 +357,9 @@ namespace {classSymbol.ContainingNamespace.ToDisplayString()} sb.AppendLine("\t\t\t" + prefix + caller + postfix + ";"); sb.AppendLine("\t\t}"); + ClassTemplate.Insert("methods", sb.ToString()); - declaredMethods.Add(sb.ToString()); + // declaredMethods.Add(sb.ToString()); var parameterTypes = string.Join(", ", $"{string.Join(", ", parameters.Select(p => $"typeof({p.Type.ToDisplayString()})"))}"); var level = "\t\t\t"; @@ -449,6 +425,7 @@ namespace {classSymbol.ContainingNamespace.ToDisplayString()} {level} SuitableType = typeof({baseInterace.ToDisplayString()}), {level} Invoking = (i, parameters, special) => {funcInvoking} {level}}}"; + MethodRepoTemplate.Insert("invoker", backend); invokers.Add(backend); } @@ -533,6 +510,8 @@ namespace {classSymbol.ContainingNamespace.ToDisplayString()} {level} return null; {level} }} {level}}}"; + MethodRepoTemplate.Insert("invoker", backend); + invokers.Add(backend); } @@ -629,6 +608,7 @@ namespace {classSymbol.ContainingNamespace.ToDisplayString()} } propsCollection.Add((frontend, method)); + MethodRepoTemplate.Insert("invoker", backend); invokers.Add(backend); } diff --git a/mROA.CodegenTools/Reading/InnerTemplateSectionReader.cs b/mROA.CodegenTools/Reading/InnerTemplateSectionReader.cs index c69038e..9427874 100644 --- a/mROA.CodegenTools/Reading/InnerTemplateSectionReader.cs +++ b/mROA.CodegenTools/Reading/InnerTemplateSectionReader.cs @@ -20,7 +20,7 @@ namespace mROA.CodegenTools var tagName = GetTagValue(from, to); var innerDocText = TemplateText.Substring(index, end - index); - var innerDoc = TemplateReader.Parce(innerDocText); + var innerDoc = TemplateReader.Parse(innerDocText); _currentCaretPosition = end + 4; index = _currentCaretPosition; return new InnerTemplateSection(tagName, innerDoc, document); diff --git a/mROA.CodegenTools/Reading/TemplateReader.cs b/mROA.CodegenTools/Reading/TemplateReader.cs index 2535b48..55148a5 100644 --- a/mROA.CodegenTools/Reading/TemplateReader.cs +++ b/mROA.CodegenTools/Reading/TemplateReader.cs @@ -16,7 +16,7 @@ namespace mROA.CodegenTools typeof(InnerTemplateSectionReader) }; - public static TemplateDocument Parce(string templateText) + public static TemplateDocument Parse(string templateText) { int currentIndex = 0; @@ -71,11 +71,16 @@ namespace mROA.CodegenTools public static TemplateDocument FromEmbeddedResource(string resourceName) { - var fileName = Assembly.GetCallingAssembly().GetManifestResourceNames().First(n => n.EndsWith(resourceName)); - var res = Assembly.GetCallingAssembly().GetManifestResourceStream(fileName); + return FromEmbeddedResource(resourceName, Assembly.GetCallingAssembly()); + } + + public static TemplateDocument FromEmbeddedResource(string resourceName, Assembly assembly) + { + var fileName = assembly.GetManifestResourceNames().First(n => n.EndsWith(resourceName)); + var res = assembly.GetManifestResourceStream(fileName); var reader = new StreamReader(res); var templateText = reader.ReadToEnd(); - return Parce(templateText); + return Parse(templateText); } } } \ No newline at end of file diff --git a/mROA.CodegenTools/TemplateDocument.cs b/mROA.CodegenTools/TemplateDocument.cs index 6ce384e..71319c2 100644 --- a/mROA.CodegenTools/TemplateDocument.cs +++ b/mROA.CodegenTools/TemplateDocument.cs @@ -36,9 +36,11 @@ namespace mROA.CodegenTools public object Clone() { - var cloneDoc = new TemplateDocument(); - cloneDoc.AdditionalContext = AdditionalContext is ICloneable c ? c.Clone() : AdditionalContext; - + var cloneDoc = new TemplateDocument + { + AdditionalContext = AdditionalContext is ICloneable c ? c.Clone() : AdditionalContext + }; + cloneDoc.Parts = Parts.Select(i => { var clone = i.Clone() as ITemplateSection; diff --git a/mROA.CodegenTools/mROA.CodegenTools.csproj b/mROA.CodegenTools/mROA.CodegenTools.csproj index d2a210c..d9c2ee6 100644 --- a/mROA.CodegenTools/mROA.CodegenTools.csproj +++ b/mROA.CodegenTools/mROA.CodegenTools.csproj @@ -2,6 +2,7 @@ netstandard2.0 + 8