Клинап
This commit is contained in:
@@ -1,32 +1,30 @@
|
|||||||
using System;
|
namespace mROA.Codegen.Tools
|
||||||
|
|
||||||
namespace mROA.CodegenTools
|
|
||||||
{
|
{
|
||||||
public class DefineTemplateSection : ITagged
|
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)
|
public DefineTemplateSection(string storedText, string tag, TemplateDocument context)
|
||||||
{
|
{
|
||||||
StoredText = storedText;
|
StoredText = storedText;
|
||||||
_tag = tag;
|
Tag = tag;
|
||||||
Context = context;
|
Context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Tag => _tag;
|
public string StoredText { get; }
|
||||||
|
public TemplateDocument Context { get; set; }
|
||||||
|
|
||||||
|
public string Tag { get; }
|
||||||
|
|
||||||
public int TargetLength => StoredText.Length;
|
public int TargetLength => StoredText.Length;
|
||||||
|
|
||||||
|
public object Clone()
|
||||||
|
{
|
||||||
|
return new DefineTemplateSection(StoredText, Tag, Context);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return StoredText;
|
return StoredText;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Clone()
|
|
||||||
{
|
|
||||||
return new DefineTemplateSection(StoredText, _tag, Context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace mROA.CodegenTools
|
namespace mROA.Codegen.Tools
|
||||||
{
|
{
|
||||||
public interface ITemplateSection : ICloneable
|
public interface ITemplateSection : ICloneable
|
||||||
{
|
{
|
||||||
@@ -12,8 +12,7 @@ namespace mROA.CodegenTools
|
|||||||
{
|
{
|
||||||
string Bake();
|
string Bake();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public interface ITagged : ITemplateSection
|
public interface ITagged : ITemplateSection
|
||||||
{
|
{
|
||||||
string Tag { get; }
|
string Tag { get; }
|
||||||
|
|||||||
@@ -1,25 +1,24 @@
|
|||||||
namespace mROA.CodegenTools
|
namespace mROA.Codegen.Tools
|
||||||
{
|
{
|
||||||
public class InnerTemplateSection : ITemplateSection, ITagged
|
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)
|
public InnerTemplateSection(string tag, TemplateDocument innerTemplate, TemplateDocument context)
|
||||||
{
|
{
|
||||||
_tag = tag;
|
Tag = tag;
|
||||||
Context = context;
|
Context = context;
|
||||||
InnerTemplate = innerTemplate;
|
InnerTemplate = innerTemplate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TemplateDocument InnerTemplate { get; }
|
||||||
|
|
||||||
|
public string Tag { get; }
|
||||||
|
|
||||||
|
public TemplateDocument Context { get; set; }
|
||||||
|
public int TargetLength => 0;
|
||||||
|
|
||||||
public object Clone()
|
public object Clone()
|
||||||
{
|
{
|
||||||
return new InnerTemplateSection(_tag, InnerTemplate, Context);
|
return new InnerTemplateSection(Tag, InnerTemplate, Context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,70 +1,20 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace mROA.CodegenTools
|
namespace mROA.Codegen.Tools
|
||||||
{
|
{
|
||||||
public class InsertTemplateSection : ITagged, IBaking
|
public class InsertTemplateSection : ITagged, IBaking
|
||||||
{
|
{
|
||||||
private object _insertedValue;
|
|
||||||
private string _tag;
|
|
||||||
public string Tag => _tag;
|
|
||||||
public TemplateDocument Context { get; set; }
|
|
||||||
public readonly List<string> Parameters;
|
public readonly List<string> Parameters;
|
||||||
|
private object _insertedValue;
|
||||||
|
|
||||||
public InsertTemplateSection(string tag, TemplateDocument context, params string[] parameters)
|
public InsertTemplateSection(string tag, TemplateDocument context, params string[] parameters)
|
||||||
{
|
{
|
||||||
_tag = tag;
|
Tag = tag;
|
||||||
Parameters = parameters.ToList();
|
Parameters = parameters.ToList();
|
||||||
Context = context;
|
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 = (InsertTemplateSection)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()
|
public string Bake()
|
||||||
{
|
{
|
||||||
switch (_insertedValue)
|
switch (_insertedValue)
|
||||||
@@ -78,9 +28,59 @@ namespace mROA.CodegenTools
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string Tag { get; private set; }
|
||||||
|
|
||||||
|
public TemplateDocument Context { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public int TargetLength => 0;
|
||||||
|
|
||||||
public object Clone()
|
public object Clone()
|
||||||
{
|
{
|
||||||
return new InsertTemplateSection(_tag, Context, Parameters.ToArray());
|
return new InsertTemplateSection(Tag, Context, Parameters.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = (InsertTemplateSection)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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,43 +1,39 @@
|
|||||||
using System.Linq;
|
namespace mROA.Codegen.Tools
|
||||||
|
|
||||||
namespace mROA.CodegenTools
|
|
||||||
{
|
{
|
||||||
public class LinkTemplateSection : ITemplateSection, IBaking
|
public class LinkTemplateSection : ITemplateSection, IBaking
|
||||||
{
|
{
|
||||||
private readonly string _linkedTag;
|
|
||||||
|
|
||||||
public LinkTemplateSection(string linkedTag, TemplateDocument context)
|
public LinkTemplateSection(string linkedTag, TemplateDocument context)
|
||||||
{
|
{
|
||||||
_linkedTag = linkedTag;
|
LinkedTag = linkedTag;
|
||||||
Context = context;
|
Context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TemplateDocument Context { get; set; }
|
public string LinkedTag { get; }
|
||||||
|
|
||||||
public string LinkedTag => _linkedTag;
|
public string Bake()
|
||||||
|
{
|
||||||
|
return Context[LinkedTag]?.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemplateDocument Context { get; set; }
|
||||||
|
|
||||||
public int TargetLength
|
public int TargetLength
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var attached = Context[_linkedTag];
|
var attached = Context[LinkedTag];
|
||||||
return attached?.TargetLength ?? 0;
|
return attached?.TargetLength ?? 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Bake()
|
public object Clone()
|
||||||
{
|
{
|
||||||
return Context[_linkedTag]?.ToString();
|
return new LinkTemplateSection(LinkedTag, Context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"{nameof(LinkedTag)}: {_linkedTag}";
|
return $"{nameof(LinkedTag)}: {LinkedTag}";
|
||||||
}
|
|
||||||
|
|
||||||
public object Clone()
|
|
||||||
{
|
|
||||||
return new LinkTemplateSection(_linkedTag, Context);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
namespace mROA.CodegenTools
|
namespace mROA.Codegen.Tools
|
||||||
{
|
{
|
||||||
public class LiteralTemplateSection : ITemplateSection, IBaking
|
public class LiteralTemplateSection : ITemplateSection, IBaking
|
||||||
{
|
{
|
||||||
private string _internalText;
|
private readonly string _internalText;
|
||||||
|
|
||||||
public LiteralTemplateSection(string internalText, TemplateDocument context)
|
public LiteralTemplateSection(string internalText, TemplateDocument context)
|
||||||
{
|
{
|
||||||
@@ -10,22 +10,22 @@ namespace mROA.CodegenTools
|
|||||||
Context = context;
|
Context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TemplateDocument Context { get; set; }
|
|
||||||
public int TargetLength => _internalText.Length;
|
|
||||||
|
|
||||||
public string Bake()
|
public string Bake()
|
||||||
{
|
{
|
||||||
return ToString();
|
return ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TemplateDocument Context { get; set; }
|
||||||
|
public int TargetLength => _internalText.Length;
|
||||||
|
|
||||||
|
public object Clone()
|
||||||
|
{
|
||||||
|
return new LiteralTemplateSection(_internalText, Context);
|
||||||
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return _internalText;
|
return _internalText;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Clone()
|
|
||||||
{
|
|
||||||
return new LiteralTemplateSection(_internalText, Context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace mROA.CodegenTools
|
namespace mROA.Codegen.Tools
|
||||||
{
|
{
|
||||||
public class ProgrammableTextSection : ITemplateSection, IBaking
|
public class ProgrammableTextSection : ITemplateSection, IBaking
|
||||||
{
|
{
|
||||||
public TemplateDocument Context { get; set; }
|
private readonly Func<object, string> _bakeFunc;
|
||||||
public int TargetLength => 0;
|
|
||||||
|
|
||||||
private Func<object, string> _bakeFunc;
|
|
||||||
|
|
||||||
public ProgrammableTextSection(Func<object, string> bakeFunc, TemplateDocument context)
|
public ProgrammableTextSection(Func<object, string> bakeFunc, TemplateDocument context)
|
||||||
{
|
{
|
||||||
@@ -21,6 +18,9 @@ namespace mROA.CodegenTools
|
|||||||
return _bakeFunc(Context.AdditionalContext);
|
return _bakeFunc(Context.AdditionalContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TemplateDocument Context { get; set; }
|
||||||
|
public int TargetLength => 0;
|
||||||
|
|
||||||
public object Clone()
|
public object Clone()
|
||||||
{
|
{
|
||||||
return new ProgrammableTextSection(_bakeFunc, Context);
|
return new ProgrammableTextSection(_bakeFunc, Context);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace mROA.CodegenTools
|
namespace mROA.Codegen.Tools.Reading
|
||||||
{
|
{
|
||||||
public class DefineSectionReader : LeadingTextSectionReader
|
public class DefineSectionReader : LeadingTextSectionReader
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
namespace mROA.Codegen.Tools.Reading
|
||||||
|
|
||||||
namespace mROA.CodegenTools
|
|
||||||
{
|
{
|
||||||
public interface ISectionReader
|
public interface ISectionReader
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace mROA.CodegenTools
|
namespace mROA.Codegen.Tools.Reading
|
||||||
{
|
{
|
||||||
public class InnerTemplateSectionReader : LeadingTextSectionReader
|
public class InnerTemplateSectionReader : LeadingTextSectionReader
|
||||||
{
|
{
|
||||||
public InnerTemplateSectionReader()
|
public InnerTemplateSectionReader()
|
||||||
: base("<!T")
|
: base("<!T")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -15,10 +15,10 @@ namespace mROA.CodegenTools
|
|||||||
var end = FindEnd(index + 4);
|
var end = FindEnd(index + 4);
|
||||||
var from = index;
|
var from = index;
|
||||||
index = PassCaretToCloseSymbol();
|
index = PassCaretToCloseSymbol();
|
||||||
var to = index - 1;
|
var to = index - 1;
|
||||||
|
|
||||||
var tagName = GetTagValue(from, to);
|
var tagName = GetTagValue(from, to);
|
||||||
|
|
||||||
var innerDocText = TemplateText.Substring(index, end - index);
|
var innerDocText = TemplateText.Substring(index, end - index);
|
||||||
var innerDoc = TemplateReader.Parse(innerDocText);
|
var innerDoc = TemplateReader.Parse(innerDocText);
|
||||||
_currentCaretPosition = end + 4;
|
_currentCaretPosition = end + 4;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace mROA.CodegenTools
|
namespace mROA.Codegen.Tools.Reading
|
||||||
{
|
{
|
||||||
public class InsertSectionReader : LeadingTextSectionReader
|
public class InsertSectionReader : LeadingTextSectionReader
|
||||||
{
|
{
|
||||||
@@ -12,12 +12,12 @@ namespace mROA.CodegenTools
|
|||||||
public override ITemplateSection ExtractSection(ref int index, TemplateDocument document)
|
public override ITemplateSection ExtractSection(ref int index, TemplateDocument document)
|
||||||
{
|
{
|
||||||
var from = index;
|
var from = index;
|
||||||
index = PassCaretToCloseSymbol();
|
index = PassCaretToCloseSymbol();
|
||||||
var to = index - 1;
|
var to = index - 1;
|
||||||
|
|
||||||
var tagText = GetTagValue(from, to);
|
var tagText = GetTagValue(from, to);
|
||||||
var parts = tagText.Split(' ');
|
var parts = tagText.Split(' ');
|
||||||
|
|
||||||
return new InsertTemplateSection(parts[0], document, parts.Skip(1).ToArray());
|
return new InsertTemplateSection(parts[0], document, parts.Skip(1).ToArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace mROA.CodegenTools
|
namespace mROA.Codegen.Tools.Reading
|
||||||
{
|
{
|
||||||
public abstract class LeadingTextSectionReader : ISectionReader
|
public abstract class LeadingTextSectionReader : ISectionReader
|
||||||
{
|
{
|
||||||
|
private readonly string _tagLeading;
|
||||||
protected int _currentCaretPosition;
|
protected int _currentCaretPosition;
|
||||||
private string _tagLeading;
|
|
||||||
|
|
||||||
protected LeadingTextSectionReader(string tagLeading)
|
protected LeadingTextSectionReader(string tagLeading)
|
||||||
{
|
{
|
||||||
_tagLeading = tagLeading + " ";
|
_tagLeading = tagLeading + " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int PassCaretToCloseSymbol()
|
|
||||||
{
|
|
||||||
_currentCaretPosition = TemplateText.IndexOf(">", _currentCaretPosition, StringComparison.Ordinal) + 1;
|
|
||||||
return _currentCaretPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string TemplateText { get; set; }
|
public string TemplateText { get; set; }
|
||||||
|
|
||||||
public int GetNextSectionIndex(int currentIndex)
|
public int GetNextSectionIndex(int currentIndex)
|
||||||
@@ -30,6 +24,12 @@ namespace mROA.CodegenTools
|
|||||||
|
|
||||||
public abstract ITemplateSection ExtractSection(ref int index, TemplateDocument document);
|
public abstract ITemplateSection ExtractSection(ref int index, TemplateDocument document);
|
||||||
|
|
||||||
|
protected int PassCaretToCloseSymbol()
|
||||||
|
{
|
||||||
|
_currentCaretPosition = TemplateText.IndexOf(">", _currentCaretPosition, StringComparison.Ordinal) + 1;
|
||||||
|
return _currentCaretPosition;
|
||||||
|
}
|
||||||
|
|
||||||
protected string GetTagValue(int from, int to)
|
protected string GetTagValue(int from, int to)
|
||||||
{
|
{
|
||||||
var realStart = from + 4;
|
var realStart = from + 4;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace mROA.CodegenTools
|
namespace mROA.Codegen.Tools.Reading
|
||||||
{
|
{
|
||||||
public class LinkSectionReader : LeadingTextSectionReader
|
public class LinkSectionReader : LeadingTextSectionReader
|
||||||
{
|
{
|
||||||
@@ -11,7 +11,7 @@ namespace mROA.CodegenTools
|
|||||||
{
|
{
|
||||||
var from = index;
|
var from = index;
|
||||||
index = PassCaretToCloseSymbol();
|
index = PassCaretToCloseSymbol();
|
||||||
var to = index - 1;
|
var to = index - 1;
|
||||||
|
|
||||||
var tagText = GetTagValue(from, to);
|
var tagText = GetTagValue(from, to);
|
||||||
return new LinkTemplateSection(tagText, document);
|
return new LinkTemplateSection(tagText, document);
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace mROA.CodegenTools
|
namespace mROA.Codegen.Tools.Reading
|
||||||
{
|
{
|
||||||
public static class TemplateReader
|
public static class TemplateReader
|
||||||
{
|
{
|
||||||
private static readonly List<Type> ReaderTypes = new List<Type>
|
private static readonly List<Type> ReaderTypes = new()
|
||||||
{
|
{
|
||||||
typeof(DefineSectionReader),
|
typeof(DefineSectionReader),
|
||||||
typeof(InsertSectionReader),
|
typeof(InsertSectionReader),
|
||||||
@@ -18,8 +18,7 @@ namespace mROA.CodegenTools
|
|||||||
|
|
||||||
public static TemplateDocument Parse(string templateText)
|
public static TemplateDocument Parse(string templateText)
|
||||||
{
|
{
|
||||||
|
var currentIndex = 0;
|
||||||
int currentIndex = 0;
|
|
||||||
var activeReaders = new List<ISectionReader>();
|
var activeReaders = new List<ISectionReader>();
|
||||||
|
|
||||||
foreach (var readerType in ReaderTypes)
|
foreach (var readerType in ReaderTypes)
|
||||||
@@ -28,26 +27,25 @@ namespace mROA.CodegenTools
|
|||||||
reader.TemplateText = templateText;
|
reader.TemplateText = templateText;
|
||||||
activeReaders.Add(reader);
|
activeReaders.Add(reader);
|
||||||
}
|
}
|
||||||
|
|
||||||
var doc = new TemplateDocument();
|
var doc = new TemplateDocument();
|
||||||
|
|
||||||
while (currentIndex < templateText.Length)
|
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();
|
List<(ISectionReader reader, int index)> indices = activeReaders
|
||||||
int minIndex = templateText.Length;
|
.Select(i => ((ISectionReader Readers, int index))(i, i.GetNextSectionIndex(currentIndex)))
|
||||||
|
.Where(i => i.index > -1).ToList();
|
||||||
|
var minIndex = templateText.Length;
|
||||||
ISectionReader minReader = null;
|
ISectionReader minReader = null;
|
||||||
if (indices.Count != 0)
|
if (indices.Count != 0)
|
||||||
{
|
{
|
||||||
minIndex = indices.Min(i => i.index);
|
minIndex = indices.Min(i => i.index);
|
||||||
minReader = indices.FirstOrDefault(i => i.index == minIndex).reader;
|
minReader = indices.FirstOrDefault(i => i.index == minIndex).reader;
|
||||||
|
|
||||||
if (indices.Count != activeReaders.Count)
|
if (indices.Count != activeReaders.Count) activeReaders = indices.Select(i => i.reader).ToList();
|
||||||
{
|
|
||||||
activeReaders = indices.Select(i => i.reader).ToList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (currentIndex != minIndex)
|
if (currentIndex != minIndex)
|
||||||
{
|
{
|
||||||
var literalText = templateText.Substring(currentIndex, minIndex - currentIndex);
|
var literalText = templateText.Substring(currentIndex, minIndex - currentIndex);
|
||||||
@@ -62,8 +60,6 @@ namespace mROA.CodegenTools
|
|||||||
var section = minReader.ExtractSection(ref currentIndex, doc);
|
var section = minReader.ExtractSection(ref currentIndex, doc);
|
||||||
doc.Parts.Add(section);
|
doc.Parts.Add(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return doc;
|
return doc;
|
||||||
|
|||||||
@@ -3,21 +3,35 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace mROA.CodegenTools
|
namespace mROA.Codegen.Tools
|
||||||
{
|
{
|
||||||
public class TemplateDocument : ICloneable
|
public class TemplateDocument : ICloneable
|
||||||
{
|
{
|
||||||
public List<ITemplateSection> Parts { get; set; } = new List<ITemplateSection>();
|
public List<ITemplateSection> Parts { get; set; } = new();
|
||||||
public object AdditionalContext { get; set; }
|
public object AdditionalContext { get; set; }
|
||||||
public ITagged? this[string tag] => Parts.OfType<ITagged>().FirstOrDefault(i => i.Tag == tag);
|
public ITagged? this[string tag] => Parts.OfType<ITagged>().FirstOrDefault(i => i.Tag == tag);
|
||||||
|
|
||||||
|
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 Insert(string tag, object value)
|
public void Insert(string tag, object value)
|
||||||
{
|
{
|
||||||
var selectedPart = this[tag];
|
var selectedPart = this[tag];
|
||||||
if (selectedPart is InsertTemplateSection itp)
|
if (selectedPart is InsertTemplateSection itp) itp.Setup(value);
|
||||||
{
|
|
||||||
itp.Setup(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Compile()
|
public string Compile()
|
||||||
@@ -34,28 +48,14 @@ namespace mROA.CodegenTools
|
|||||||
return stringBuilder.ToString();
|
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)
|
public void AddDefine(string tag, string text)
|
||||||
{
|
{
|
||||||
Parts.Add(new DefineTemplateSection(text, tag, this));
|
Parts.Add(new DefineTemplateSection(text, tag, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddDefine(string tag, object value) => AddDefine(tag, value.ToString());
|
public void AddDefine(string tag, object value)
|
||||||
|
{
|
||||||
|
AddDefine(tag, value.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>9</LangVersion>
|
||||||
|
|
||||||
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||||
<IsRoslynComponent>true</IsRoslynComponent>
|
<IsRoslynComponent>true</IsRoslynComponent>
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
<RepositoryUrl>https://github.com/YaslePoy/mROA</RepositoryUrl>
|
<RepositoryUrl>https://github.com/YaslePoy/mROA</RepositoryUrl>
|
||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
<Version>1.2.0</Version>
|
<Version>2.0.0</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -31,12 +31,12 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false"/>
|
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="PartialInterface.cstmpl" />
|
<EmbeddedResource Include="PartialInterface.cstmpl"/>
|
||||||
<EmbeddedResource Include="RemoteEndpoint.cstmpl" />
|
<EmbeddedResource Include="RemoteEndpoint.cstmpl"/>
|
||||||
<EmbeddedResource Include="RemoteTypeBinder.cstmpl" />
|
<EmbeddedResource Include="RemoteTypeBinder.cstmpl"/>
|
||||||
<None Remove="MethodRepo.cstmpl"/>
|
<None Remove="MethodRepo.cstmpl"/>
|
||||||
<EmbeddedResource Include="MethodRepo.cstmpl"/>
|
<EmbeddedResource Include="MethodRepo.cstmpl"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
+190
-209
@@ -3,44 +3,49 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
using Microsoft.CodeAnalysis.Text;
|
using Microsoft.CodeAnalysis.Text;
|
||||||
using mROA.CodegenTools;
|
using mROA.Codegen.Tools;
|
||||||
|
using mROA.Codegen.Tools.Reading;
|
||||||
|
|
||||||
|
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
|
||||||
|
|
||||||
namespace mROA.Codegen
|
namespace mROA.Codegen
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A sample source generator that creates a custom report based on class properties. The target class should be annotated with the 'Generators.ReportAttribute' attribute.
|
/// A sample source generator that creates a custom report based on class properties. The target class should be
|
||||||
/// When using the source code as a baseline, an incremental source generator is preferable because it reduces the performance overhead.
|
/// annotated with the 'Generators.ReportAttribute' attribute.
|
||||||
|
/// When using the source code as a baseline, an incremental source generator is preferable because it reduces the
|
||||||
|
/// performance overhead.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Generator]
|
[Generator]
|
||||||
public class mROASourceGenerator : ISourceGenerator
|
public class MRoaSourceGenerator : ISourceGenerator
|
||||||
{
|
{
|
||||||
private TemplateDocument MethodRepoTemplate;
|
private static readonly Predicate<IParameterSymbol> ParameterFilter =
|
||||||
private TemplateDocument ClassTemplateOriginal;
|
|
||||||
private TemplateDocument ClassTemplate;
|
|
||||||
private TemplateDocument InterfaceTemplateOriginal;
|
|
||||||
private TemplateDocument InterfaceTemplate;
|
|
||||||
private TemplateDocument BinderTemplate;
|
|
||||||
private TemplateDocument MethodInvokerOriginal;
|
|
||||||
private static Predicate<IParameterSymbol> ParameterFilter =
|
|
||||||
i => i.Type.Name is "CancellationToken" or "RequestContext";
|
i => i.Type.Name is "CancellationToken" or "RequestContext";
|
||||||
|
|
||||||
private static Predicate<ITypeSymbol> ParameterFilterForType =
|
private static readonly Predicate<ITypeSymbol> ParameterFilterForType =
|
||||||
i => i.Name is "CancellationToken" or "RequestContext";
|
i => i.Name is "CancellationToken" or "RequestContext";
|
||||||
|
|
||||||
|
private TemplateDocument _binderTemplate;
|
||||||
|
private TemplateDocument _classTemplate;
|
||||||
|
private TemplateDocument _classTemplateOriginal;
|
||||||
|
private TemplateDocument _interfaceTemplate;
|
||||||
|
private TemplateDocument _interfaceTemplateOriginal;
|
||||||
|
private TemplateDocument _methodInvokerOriginal;
|
||||||
|
private TemplateDocument _methodRepoTemplate;
|
||||||
|
|
||||||
public void Initialize(GeneratorInitializationContext context)
|
public void Initialize(GeneratorInitializationContext context)
|
||||||
{
|
{
|
||||||
MethodRepoTemplate = TemplateReader.FromEmbeddedResource("MethodRepo.cstmpl");
|
_methodRepoTemplate = TemplateReader.FromEmbeddedResource("MethodRepo.cstmpl");
|
||||||
MethodInvokerOriginal =
|
_methodInvokerOriginal =
|
||||||
((InnerTemplateSection)MethodRepoTemplate["syncInvoker"])?.InnerTemplate;
|
((InnerTemplateSection)_methodRepoTemplate["syncInvoker"]!).InnerTemplate;
|
||||||
ClassTemplateOriginal = TemplateReader.FromEmbeddedResource("RemoteEndpoint.cstmpl");
|
_classTemplateOriginal = TemplateReader.FromEmbeddedResource("RemoteEndpoint.cstmpl");
|
||||||
BinderTemplate = TemplateReader.FromEmbeddedResource("RemoteTypeBinder.cstmpl");
|
_binderTemplate = TemplateReader.FromEmbeddedResource("RemoteTypeBinder.cstmpl");
|
||||||
InterfaceTemplateOriginal = TemplateReader.FromEmbeddedResource("PartialInterface.cstmpl");
|
_interfaceTemplateOriginal = TemplateReader.FromEmbeddedResource("PartialInterface.cstmpl");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Execute(GeneratorExecutionContext context)
|
public void Execute(GeneratorExecutionContext context)
|
||||||
@@ -52,28 +57,22 @@ namespace mROA.Codegen
|
|||||||
var interfaces = new List<InterfaceDeclarationSyntax>();
|
var interfaces = new List<InterfaceDeclarationSyntax>();
|
||||||
foreach (var tree in trees)
|
foreach (var tree in trees)
|
||||||
{
|
{
|
||||||
var node = tree.GetRoot() as CompilationUnitSyntax;
|
var node = (CompilationUnitSyntax)tree.GetRoot();
|
||||||
|
|
||||||
foreach (var member in node.Members)
|
foreach (var member in node.Members)
|
||||||
{
|
|
||||||
if (member is InterfaceDeclarationSyntax ids)
|
if (member is InterfaceDeclarationSyntax ids)
|
||||||
{
|
|
||||||
interfaces.Add(ids);
|
interfaces.Add(ids);
|
||||||
}
|
|
||||||
else if (member is NamespaceDeclarationSyntax nds)
|
else if (member is NamespaceDeclarationSyntax nds)
|
||||||
{
|
|
||||||
foreach (var inside in nds.Members)
|
foreach (var inside in nds.Members)
|
||||||
|
|
||||||
if (inside is InterfaceDeclarationSyntax ids2)
|
if (inside is InterfaceDeclarationSyntax ids2)
|
||||||
if (ContainsSOIAttribute(ids2.AttributeLists, context, ids2))
|
if (ContainsSoiAttribute(ids2.AttributeLists, context, ids2))
|
||||||
interfaces.Add(ids2);
|
interfaces.Add(ids2);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GenerateCode(context, context.Compilation, interfaces.ToImmutableArray());
|
GenerateCode(context, context.Compilation, interfaces.ToImmutableArray());
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
Console.WriteLine("ERROR: Unable to load method repository");
|
Console.WriteLine("ERROR: Unable to load method repository");
|
||||||
}
|
}
|
||||||
@@ -82,10 +81,10 @@ namespace mROA.Codegen
|
|||||||
private void GenerateCode(GeneratorExecutionContext context, Compilation compilation,
|
private void GenerateCode(GeneratorExecutionContext context, Compilation compilation,
|
||||||
ImmutableArray<InterfaceDeclarationSyntax> classes)
|
ImmutableArray<InterfaceDeclarationSyntax> classes)
|
||||||
{
|
{
|
||||||
List<IMethodSymbol> totalMethods = new List<IMethodSymbol>();
|
var totalMethods = new List<IMethodSymbol>();
|
||||||
|
|
||||||
|
|
||||||
List<string> invokers = new List<string>();
|
var invokers = new List<string>();
|
||||||
var declarations = classes.ToList().OrderBy(i => i.Identifier.Text).ToList();
|
var declarations = classes.ToList().OrderBy(i => i.Identifier.Text).ToList();
|
||||||
foreach (var classDeclarationSyntax in declarations)
|
foreach (var classDeclarationSyntax in declarations)
|
||||||
{
|
{
|
||||||
@@ -93,11 +92,10 @@ namespace mROA.Codegen
|
|||||||
|
|
||||||
if (semanticModel.GetDeclaredSymbol(classDeclarationSyntax) is not INamedTypeSymbol classSymbol)
|
if (semanticModel.GetDeclaredSymbol(classDeclarationSyntax) is not INamedTypeSymbol classSymbol)
|
||||||
continue;
|
continue;
|
||||||
List<IMethodSymbol> innerMethods = new List<IMethodSymbol>();
|
|
||||||
|
|
||||||
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
|
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
|
||||||
var className = classDeclarationSyntax.Identifier.Text;
|
var className = classDeclarationSyntax.Identifier.Text;
|
||||||
innerMethods = CollectMembers(classSymbol);
|
var innerMethods = CollectMembers(classSymbol);
|
||||||
var associated = innerMethods.Select(i => i.AssociatedSymbol).Where(i => i != null)
|
var associated = innerMethods.Select(i => i.AssociatedSymbol).Where(i => i != null)
|
||||||
.Distinct(SymbolEqualityComparer.Default).Cast<ISymbol>().ToList();
|
.Distinct(SymbolEqualityComparer.Default).Cast<ISymbol>().ToList();
|
||||||
|
|
||||||
@@ -111,12 +109,10 @@ namespace mROA.Codegen
|
|||||||
|
|
||||||
className = className.TrimStart('I') + "RemoteEndpoint";
|
className = className.TrimStart('I') + "RemoteEndpoint";
|
||||||
|
|
||||||
ClassTemplate = (TemplateDocument)ClassTemplateOriginal.Clone();
|
_classTemplate = (TemplateDocument)_classTemplateOriginal.Clone();
|
||||||
var declaredMethods = new List<string>();
|
|
||||||
var propertiesAccessMethods = new List<(string, IMethodSymbol)>();
|
var propertiesAccessMethods = new List<(string, IMethodSymbol)>();
|
||||||
|
|
||||||
foreach (var method in innerMethods)
|
foreach (var method in innerMethods)
|
||||||
{
|
|
||||||
switch (method.MethodKind)
|
switch (method.MethodKind)
|
||||||
{
|
{
|
||||||
case MethodKind.PropertyGet or MethodKind.PropertySet:
|
case MethodKind.PropertyGet or MethodKind.PropertySet:
|
||||||
@@ -124,13 +120,11 @@ namespace mROA.Codegen
|
|||||||
classSymbol);
|
classSymbol);
|
||||||
continue;
|
continue;
|
||||||
default:
|
default:
|
||||||
GenerateDeclaredMethod(method, declaredMethods, invokers, classSymbol);
|
GenerateDeclaredMethod(method, invokers, classSymbol);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var symbol in associated)
|
foreach (var symbol in associated)
|
||||||
{
|
|
||||||
switch (symbol)
|
switch (symbol)
|
||||||
{
|
{
|
||||||
case IPropertySymbol propertySymbol:
|
case IPropertySymbol propertySymbol:
|
||||||
@@ -141,60 +135,51 @@ namespace mROA.Codegen
|
|||||||
i.Item2.AssociatedSymbol!.Name == propertySymbol.Name && !i.Item2.ReturnsVoid);
|
i.Item2.AssociatedSymbol!.Name == propertySymbol.Name && !i.Item2.ReturnsVoid);
|
||||||
string impl;
|
string impl;
|
||||||
if (propertySymbol.IsIndexer)
|
if (propertySymbol.IsIndexer)
|
||||||
{
|
|
||||||
impl =
|
impl =
|
||||||
$"public {propertySymbol.Type.ToDisplayString()} this[{string.Join(", ", propertySymbol.Parameters.Select(p => p.ToDisplayString()))}] {{ {getter.Item1} {setter.Item1} }}";
|
$"public {propertySymbol.Type.ToUnityString()} this[{string.Join(", ", propertySymbol.Parameters.Select(p => p.ToDisplayString()))}] {{ {getter.Item1} {setter.Item1} }}";
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
impl =
|
impl =
|
||||||
$"public {propertySymbol.Type.ToDisplayString()} {symbol.Name} {{ {getter.Item1} {setter.Item1} }}";
|
$"public {propertySymbol.Type.ToUnityString()} {symbol.Name} {{ {getter.Item1} {setter.Item1} }}";
|
||||||
}
|
|
||||||
|
|
||||||
ClassTemplate.Insert("methods", impl);
|
_classTemplate.Insert("methods", impl);
|
||||||
// declaredMethods.Add(impl);
|
// declaredMethods.Add(impl);
|
||||||
break;
|
break;
|
||||||
case IEventSymbol eventSymbol:
|
case IEventSymbol eventSymbol:
|
||||||
ClassTemplate.Insert("methods",
|
_classTemplate.Insert("methods",
|
||||||
$"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};");
|
$"public event {eventSymbol.Type.ToUnityString()}? {eventSymbol.Name};");
|
||||||
// declaredMethods.Add(
|
// declaredMethods.Add(
|
||||||
// $"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};");
|
// $"public event {eventSymbol.Type.ToDisplayString()}? {eventSymbol.Name};");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
GenerateEventImplementation(classSymbol, invokers, context);
|
GenerateEventImplementation(classSymbol, invokers, context);
|
||||||
|
|
||||||
ClassTemplate.AddDefine("className", className);
|
_classTemplate.AddDefine("className", className);
|
||||||
ClassTemplate.AddDefine("originalName", originalName);
|
_classTemplate.AddDefine("originalName", originalName);
|
||||||
ClassTemplate.AddDefine("namespaceName", namespaceName);
|
_classTemplate.AddDefine("namespaceName", namespaceName);
|
||||||
|
|
||||||
var code = ClassTemplate.Compile();
|
var code = _classTemplate.Compile();
|
||||||
|
|
||||||
|
|
||||||
// Add the source code to the compilation.
|
// Add the source code to the compilation.
|
||||||
#if !DONT_ADD
|
#if !DONT_ADD
|
||||||
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
|
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
|
||||||
#endif
|
#endif
|
||||||
BinderTemplate.Insert("remoteTypePair",
|
_binderTemplate.Insert("remoteTypePair",
|
||||||
$"{{ typeof({classSymbol.ToDisplayString()}), typeof({namespaceName}.{className}) }}");
|
$"{{ typeof({classSymbol.ToUnityString()}), typeof({namespaceName}.{className}) }}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (totalMethods.Count != 0)
|
if (totalMethods.Count != 0)
|
||||||
{
|
{
|
||||||
var methodsStringed = invokers;
|
var coCodegenRepoCode = _methodRepoTemplate.Compile();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var coCodegenRepoCode = MethodRepoTemplate.Compile();
|
|
||||||
#if !DONT_ADD
|
#if !DONT_ADD
|
||||||
context.AddSource("CoCodegenMethodRepository.g.cs", SourceText.From(coCodegenRepoCode, Encoding.UTF8));
|
context.AddSource("CoCodegenMethodRepository.g.cs", SourceText.From(coCodegenRepoCode, Encoding.UTF8));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BinderTemplate["remoteTypePair+"] != null)
|
if (_binderTemplate["remoteTypePair+"] != null)
|
||||||
{
|
{
|
||||||
var fronendRepoCode = BinderTemplate.Compile();
|
var fronendRepoCode = _binderTemplate.Compile();
|
||||||
#if !DONT_ADD
|
#if !DONT_ADD
|
||||||
context.AddSource("RemoteTypeBinder.g.cs", SourceText.From(fronendRepoCode, Encoding.UTF8));
|
context.AddSource("RemoteTypeBinder.g.cs", SourceText.From(fronendRepoCode, Encoding.UTF8));
|
||||||
#endif
|
#endif
|
||||||
@@ -209,29 +194,27 @@ namespace mROA.Codegen
|
|||||||
if (events.Count == 0)
|
if (events.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
InterfaceTemplate = (TemplateDocument)InterfaceTemplateOriginal.Clone();
|
_interfaceTemplate = (TemplateDocument)_interfaceTemplateOriginal.Clone();
|
||||||
InterfaceTemplate.AddDefine("name", classSymbol.Name);
|
_interfaceTemplate.AddDefine("name", classSymbol.Name);
|
||||||
InterfaceTemplate.AddDefine("namespace", classSymbol.ContainingNamespace.ToDisplayString());
|
_interfaceTemplate.AddDefine("namespace", classSymbol.ContainingNamespace.ToDisplayString());
|
||||||
var singleEventBinder = new List<string>(events.Count);
|
|
||||||
var objectBinderTemplate =
|
var objectBinderTemplate =
|
||||||
(TemplateDocument)((InnerTemplateSection)BinderTemplate["objectBinderTemplate"]).InnerTemplate.Clone();
|
(TemplateDocument)((InnerTemplateSection)_binderTemplate["objectBinderTemplate"]!).InnerTemplate
|
||||||
for (int i = 0; i < events.Count; i++)
|
.Clone();
|
||||||
|
foreach (var currentEvent in events)
|
||||||
{
|
{
|
||||||
var currentEvent = events[i];
|
|
||||||
|
|
||||||
var additionalMethod = GenerateMethodExternalCaller(currentEvent, out var signature);
|
var additionalMethod = GenerateMethodExternalCaller(currentEvent, out var signature);
|
||||||
ClassTemplate.Insert("methods", additionalMethod);
|
_classTemplate.Insert("methods", additionalMethod);
|
||||||
|
|
||||||
// declaredMethods.Add(additionalMethod);
|
// declaredMethods.Add(additionalMethod);
|
||||||
InterfaceTemplate.Insert("signature", signature);
|
_interfaceTemplate.Insert("signature", signature);
|
||||||
GenerateEventCode(currentEvent, invokers, classSymbol);
|
GenerateEventCode(currentEvent, invokers, classSymbol);
|
||||||
GenerateBinderCode(currentEvent, invokers, classSymbol, objectBinderTemplate);
|
GenerateBinderCode(currentEvent, invokers, classSymbol, objectBinderTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
objectBinderTemplate.AddDefine("type", classSymbol.ToDisplayString());
|
objectBinderTemplate.AddDefine("type", classSymbol.ToUnityString());
|
||||||
var partialInterface = InterfaceTemplate.Compile();
|
var partialInterface = _interfaceTemplate.Compile();
|
||||||
var binder = objectBinderTemplate.Compile();
|
var binder = objectBinderTemplate.Compile();
|
||||||
BinderTemplate.Insert("eventBinder", binder);
|
_binderTemplate.Insert("eventBinder", binder);
|
||||||
|
|
||||||
#if !DONT_ADD
|
#if !DONT_ADD
|
||||||
context.AddSource($"{classSymbol.Name}.g.cs", SourceText.From(partialInterface, Encoding.UTF8));
|
context.AddSource($"{classSymbol.Name}.g.cs", SourceText.From(partialInterface, Encoding.UTF8));
|
||||||
@@ -241,10 +224,10 @@ namespace mROA.Codegen
|
|||||||
private string GenerateMethodExternalCaller(IEventSymbol eventSymbol, out string interfaceSignature)
|
private string GenerateMethodExternalCaller(IEventSymbol eventSymbol, out string interfaceSignature)
|
||||||
{
|
{
|
||||||
var level = "\t\t";
|
var level = "\t\t";
|
||||||
var parameters = (eventSymbol.Type as INamedTypeSymbol).TypeArguments;
|
var parameters = ((INamedTypeSymbol)eventSymbol.Type).TypeArguments;
|
||||||
var parameterIndex = 0;
|
var parameterIndex = 0;
|
||||||
var parametersDeclaration =
|
var parametersDeclaration =
|
||||||
string.Join(", ", parameters.Select(i => $"{i.ToDisplayString()} p{parameterIndex++}"));
|
string.Join(", ", parameters.Select(i => $"{i.ToUnityString()} p{parameterIndex++}"));
|
||||||
var signature = $@"public void {EventExternalName(eventSymbol)}({parametersDeclaration})";
|
var signature = $@"public void {EventExternalName(eventSymbol)}({parametersDeclaration})";
|
||||||
interfaceSignature = signature + ";";
|
interfaceSignature = signature + ";";
|
||||||
var caller = $@"{signature}
|
var caller = $@"{signature}
|
||||||
@@ -255,18 +238,21 @@ namespace mROA.Codegen
|
|||||||
return caller;
|
return caller;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string EventExternalName(IEventSymbol eventSymbol) => $"{eventSymbol.Name}External";
|
private static string EventExternalName(IEventSymbol eventSymbol)
|
||||||
|
{
|
||||||
|
return $"{eventSymbol.Name}External";
|
||||||
|
}
|
||||||
|
|
||||||
private static string Caster(ITypeSymbol type, string inner)
|
private static string Caster(ITypeSymbol type, string inner)
|
||||||
{
|
{
|
||||||
if (!type.IsValueType)
|
if (!type.IsValueType)
|
||||||
return inner +
|
return inner +
|
||||||
" as " +
|
" as " +
|
||||||
type.ToDisplayString();
|
type.ToUnityString();
|
||||||
return $"({type.ToDisplayString()})" + inner;
|
return $"({type.ToUnityString()})" + inner;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GenerateDeclaredMethod(IMethodSymbol method, List<string> declaredMethods, List<string> invokers,
|
private void GenerateDeclaredMethod(IMethodSymbol method, List<string> invokers,
|
||||||
INamedTypeSymbol baseInterace)
|
INamedTypeSymbol baseInterace)
|
||||||
{
|
{
|
||||||
var index = invokers.Count;
|
var index = invokers.Count;
|
||||||
@@ -283,7 +269,7 @@ namespace mROA.Codegen
|
|||||||
{
|
{
|
||||||
case INamedTypeSymbol namedType:
|
case INamedTypeSymbol namedType:
|
||||||
isAsync = namedType.Name == "Task";
|
isAsync = namedType.Name == "Task";
|
||||||
isVoid = isAsync && namedType.TypeParameters.Length == 0 || namedType.Name == "Void";
|
isVoid = (isAsync && namedType.TypeParameters.Length == 0) || namedType.Name == "Void";
|
||||||
parameters = method.Parameters.ToList();
|
parameters = method.Parameters.ToList();
|
||||||
parameters.RemoveAll(ParameterFilter);
|
parameters.RemoveAll(ParameterFilter);
|
||||||
isParametrized = parameters.Count != 0;
|
isParametrized = parameters.Count != 0;
|
||||||
@@ -302,18 +288,18 @@ namespace mROA.Codegen
|
|||||||
sb.AppendLine("public" + (isAsync
|
sb.AppendLine("public" + (isAsync
|
||||||
? " async "
|
? " async "
|
||||||
: " ") +
|
: " ") +
|
||||||
$"{method.ReturnType.ToDisplayString()} {method.Name}({string.Join(", ", method.Parameters.Select(ToFullString))}){{");
|
$"{method.ReturnType.ToUnityString()} {method.Name}({string.Join(", ", method.Parameters.Select(ToFullString))}){{");
|
||||||
|
|
||||||
|
|
||||||
var prefix = isAsync ? "await " : "";
|
var prefix = isAsync ? "await " : "";
|
||||||
var postfix = !isAsync ? isVoid ? ".Wait()" : ".GetAwaiter().GetResult()" : "";
|
var postfix = !isAsync ? isVoid ? ".Wait()" : ".GetAwaiter().GetResult()" : "";
|
||||||
var parameterLink = isParametrized
|
var parameterLink = isParametrized
|
||||||
? ", new object[] {" + string.Join(", ", parameters.Select(i => i.Name)) + "}"
|
? ", new System.Object[] { " + string.Join(", ", parameters.Select(i => i.Name)) + " }"
|
||||||
: string.Empty;
|
: string.Empty;
|
||||||
var tokenInsert = isAsync && method.Parameters.FirstOrDefault(i => i.Type.Name == "CancellationToken") is
|
var tokenInsert = isAsync && method.Parameters.FirstOrDefault(i => i.Type.Name == "CancellationToken") is
|
||||||
{ } tokenSymbol
|
{ } tokenSymbol
|
||||||
? ", cancellationToken : " + tokenSymbol.Name
|
? ", cancellationToken : " + tokenSymbol.Name
|
||||||
: String.Empty;
|
: string.Empty;
|
||||||
var caller = isVoid
|
var caller = isVoid
|
||||||
? $"CallAsync({index}{parameterLink}{tokenInsert})"
|
? $"CallAsync({index}{parameterLink}{tokenInsert})"
|
||||||
: isAsync
|
: isAsync
|
||||||
@@ -326,18 +312,16 @@ namespace mROA.Codegen
|
|||||||
sb.AppendLine("\t\t\t" + prefix + caller + postfix + ";");
|
sb.AppendLine("\t\t\t" + prefix + caller + postfix + ";");
|
||||||
|
|
||||||
sb.AppendLine("\t\t}");
|
sb.AppendLine("\t\t}");
|
||||||
ClassTemplate.Insert("methods", sb.ToString());
|
_classTemplate.Insert("methods", sb.ToString());
|
||||||
|
|
||||||
// declaredMethods.Add(sb.ToString());
|
// declaredMethods.Add(sb.ToString());
|
||||||
var parameterTypes = string.Join(", ",
|
var parameterTypes = string.Join(", ",
|
||||||
$"{string.Join(", ", parameters.Select(p => $"typeof({p.Type.ToDisplayString()})"))}");
|
$"{string.Join(", ", parameters.Select(p => $"typeof({p.Type.ToUnityString()})"))}");
|
||||||
var level = "\t\t\t";
|
var level = "\t\t\t";
|
||||||
|
|
||||||
var parametersInsertList = new List<string>();
|
var parametersInsertList = new List<string>();
|
||||||
|
|
||||||
for (var i = 0; i < method.Parameters.Length; i++)
|
foreach (var parameter in method.Parameters)
|
||||||
{
|
|
||||||
var parameter = method.Parameters[i];
|
|
||||||
switch (parameter.Type.Name)
|
switch (parameter.Type.Name)
|
||||||
{
|
{
|
||||||
case "CancellationToken":
|
case "CancellationToken":
|
||||||
@@ -351,53 +335,50 @@ namespace mROA.Codegen
|
|||||||
$"parameters[{parameters.IndexOf(parameter)}]"));
|
$"parameters[{parameters.IndexOf(parameter)}]"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var parametersInsert = string.Join(", ", parametersInsertList);
|
var parametersInsert = string.Join(", ", parametersInsertList);
|
||||||
var backend = string.Empty;
|
string backend;
|
||||||
|
|
||||||
var funcInvoking = string.Empty;
|
string funcInvoking;
|
||||||
|
|
||||||
if (isAsync && !isVoid)
|
if (isAsync && !isVoid)
|
||||||
funcInvoking =
|
funcInvoking =
|
||||||
$"(i as {method.ContainingType.ToDisplayString()}).{method.Name}({parametersInsert}).ContinueWith(t => {{ post(t.Result); }})";
|
$"(i as {method.ContainingType.ToUnityString()}).{method.Name}({parametersInsert}).ContinueWith(t => {{ post(t.Result); }})";
|
||||||
else if (isAsync && isVoid)
|
else if (isAsync && isVoid)
|
||||||
funcInvoking =
|
funcInvoking =
|
||||||
$"(i as {method.ContainingType.ToDisplayString()}).{method.Name}({parametersInsert}).ContinueWith(t => {{ post(null); }})";
|
$"(i as {method.ContainingType.ToUnityString()}).{method.Name}({parametersInsert}).ContinueWith(t => {{ post(null); }})";
|
||||||
else if (!isAsync && isVoid)
|
else if (!isAsync && isVoid)
|
||||||
{
|
|
||||||
funcInvoking = $@"{{
|
funcInvoking = $@"{{
|
||||||
{level} (i as {method.ContainingType.ToDisplayString()}).{method.Name}({parametersInsert});
|
{level} (i as {method.ContainingType.ToUnityString()}).{method.Name}({parametersInsert});
|
||||||
{level} return null;
|
{level} return null;
|
||||||
{level} }}";
|
{level} }}";
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
funcInvoking = $"(i as {method.ContainingType.ToUnityString()}).{method.Name}({parametersInsert})";
|
||||||
funcInvoking = $"(i as {method.ContainingType.ToDisplayString()}).{method.Name}({parametersInsert})";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isAsync)
|
if (isAsync)
|
||||||
{
|
{
|
||||||
var invokerTemplate = (TemplateDocument)((InnerTemplateSection)MethodRepoTemplate["asyncInvoker"]).InnerTemplate.Clone();
|
var invokerTemplate =
|
||||||
|
(TemplateDocument)((InnerTemplateSection)_methodRepoTemplate["asyncInvoker"]!).InnerTemplate
|
||||||
|
.Clone();
|
||||||
invokerTemplate.AddDefine("isVoid", isVoid.ToString().ToLower());
|
invokerTemplate.AddDefine("isVoid", isVoid.ToString().ToLower());
|
||||||
invokerTemplate.AddDefine("returnType", ExtractTaskType(method.ReturnType));
|
invokerTemplate.AddDefine("returnType", ExtractTaskType(method.ReturnType));
|
||||||
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterace.ToDisplayString());
|
invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString());
|
||||||
invokerTemplate.AddDefine("funcInvoking", funcInvoking);
|
invokerTemplate.AddDefine("funcInvoking", funcInvoking);
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var invokerTemplate = (TemplateDocument)MethodInvokerOriginal.Clone();
|
var invokerTemplate = (TemplateDocument)_methodInvokerOriginal.Clone();
|
||||||
invokerTemplate.AddDefine("isVoid", isVoid.ToString().ToLower());
|
invokerTemplate.AddDefine("isVoid", isVoid.ToString().ToLower());
|
||||||
invokerTemplate.AddDefine("returnType", isVoid ? "void" : method.ReturnType.ToDisplayString());
|
invokerTemplate.AddDefine("returnType", isVoid ? "void" : method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterace.ToDisplayString());
|
invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString());
|
||||||
invokerTemplate.AddDefine("funcInvoking", funcInvoking);
|
invokerTemplate.AddDefine("funcInvoking", funcInvoking);
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
MethodRepoTemplate.Insert("invoker", backend);
|
_methodRepoTemplate.Insert("invoker", backend);
|
||||||
|
|
||||||
invokers.Add(backend);
|
invokers.Add(backend);
|
||||||
}
|
}
|
||||||
@@ -410,24 +391,21 @@ namespace mROA.Codegen
|
|||||||
|
|
||||||
var index = invokers.Count - 1;
|
var index = invokers.Count - 1;
|
||||||
var parameters = (eventSymbol.Type as INamedTypeSymbol)!.TypeArguments.ToList();
|
var parameters = (eventSymbol.Type as INamedTypeSymbol)!.TypeArguments.ToList();
|
||||||
int parameterIndex = 0;
|
|
||||||
var parametersDeclaration = string.Join(", ",
|
var parametersDeclaration = string.Join(", ",
|
||||||
JoinWithComa(Enumerable.Range(0, parameters.Count).Select(i => "p" + i++)));
|
JoinWithComa(Enumerable.Range(0, parameters.Count).Select(i => "p" + i)));
|
||||||
|
|
||||||
var transferParameters =
|
var transferParameters =
|
||||||
JoinWithComa(parameters.Where(i => !ParameterFilterForType(i))
|
JoinWithComa(parameters.Where(i => !ParameterFilterForType(i))
|
||||||
.Select(i => "p" + parameters.IndexOf(i)));
|
.Select(i => "p" + parameters.IndexOf(i)));
|
||||||
|
|
||||||
string callFilter;
|
|
||||||
|
|
||||||
var requestIndex = parameters.FindIndex(i => i.Name == "RequestContext");
|
var requestIndex = parameters.FindIndex(i => i.Name == "RequestContext");
|
||||||
if (requestIndex != -1)
|
if (requestIndex != -1)
|
||||||
{
|
{
|
||||||
callFilter = $"\n\r\t\t\tif(ownerId == p{requestIndex}.OwnerId) return;";
|
var callFilter = $"\n\r\t\t\tif(ownerId == p{requestIndex}.OwnerId) return;";
|
||||||
eventBinderTemplate.AddDefine("callFilter", callFilter);
|
eventBinderTemplate.AddDefine("callFilter", callFilter);
|
||||||
}
|
}
|
||||||
|
|
||||||
eventBinderTemplate.AddDefine("type", baseType.ToDisplayString());
|
eventBinderTemplate.AddDefine("type", baseType.ToUnityString());
|
||||||
eventBinderTemplate.AddDefine("eventName", eventSymbol.Name);
|
eventBinderTemplate.AddDefine("eventName", eventSymbol.Name);
|
||||||
eventBinderTemplate.AddDefine("parametersDeclaration", parametersDeclaration);
|
eventBinderTemplate.AddDefine("parametersDeclaration", parametersDeclaration);
|
||||||
eventBinderTemplate.AddDefine("commandId", index.ToString());
|
eventBinderTemplate.AddDefine("commandId", index.ToString());
|
||||||
@@ -436,22 +414,23 @@ namespace mROA.Codegen
|
|||||||
document.Insert("eventBinder", eventBinderCode);
|
document.Insert("eventBinder", eventBinderCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string JoinWithComa(IEnumerable<string> parts) => string.Join(", ", parts);
|
private static string JoinWithComa(IEnumerable<string> parts)
|
||||||
|
{
|
||||||
|
return string.Join(", ", parts);
|
||||||
|
}
|
||||||
|
|
||||||
private void GenerateEventCode(IEventSymbol eventSymbol, List<string> invokers, ITypeSymbol baseInterface)
|
private void GenerateEventCode(IEventSymbol eventSymbol, List<string> invokers, ITypeSymbol baseInterface)
|
||||||
{
|
{
|
||||||
var level = "\t\t\t";
|
var level = "\t\t\t";
|
||||||
|
|
||||||
var parameters = (eventSymbol.Type as INamedTypeSymbol).TypeArguments;
|
var parameters = ((INamedTypeSymbol)eventSymbol.Type).TypeArguments;
|
||||||
var parsingParameters = parameters.RemoveAll(ParameterFilterForType).ToList();
|
var parsingParameters = parameters.RemoveAll(ParameterFilterForType).ToList();
|
||||||
var parameterTypes = string.Join(", ",
|
var parameterTypes = string.Join(", ",
|
||||||
$"{string.Join(", ", parsingParameters.Select(p => $"typeof({p.ToDisplayString()})"))}");
|
$"{string.Join(", ", parsingParameters.Select(p => $"typeof({p.ToUnityString()})"))}");
|
||||||
|
|
||||||
var parametersInsertList = new List<string>();
|
var parametersInsertList = new List<string>();
|
||||||
|
|
||||||
for (var i = 0; i < parameters.Length; i++)
|
foreach (var parameter in parameters)
|
||||||
{
|
|
||||||
var parameter = parameters[i];
|
|
||||||
switch (parameter.Name)
|
switch (parameter.Name)
|
||||||
{
|
{
|
||||||
case "CancellationToken":
|
case "CancellationToken":
|
||||||
@@ -465,25 +444,23 @@ namespace mROA.Codegen
|
|||||||
$"parameters[{parameters.IndexOf(parameter)}]"));
|
$"parameters[{parameters.IndexOf(parameter)}]"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var parametersInsert = string.Join(", ", parametersInsertList);
|
var parametersInsert = string.Join(", ", parametersInsertList);
|
||||||
|
|
||||||
var funcInvoking = $@"{{
|
var funcInvoking = $@"{{
|
||||||
{level} (i as {baseInterface.ToDisplayString()}).{EventExternalName(eventSymbol)}({parametersInsert});
|
{level} (i as {baseInterface.ToUnityString()}).{EventExternalName(eventSymbol)}({parametersInsert});
|
||||||
{level} return null;
|
{level} return null;
|
||||||
{level} }}";
|
{level} }}";
|
||||||
|
|
||||||
var invokerTemplate = (TemplateDocument)MethodInvokerOriginal.Clone();
|
var invokerTemplate = (TemplateDocument)_methodInvokerOriginal.Clone();
|
||||||
invokerTemplate.AddDefine("isVoid", "true");
|
invokerTemplate.AddDefine("isVoid", "true");
|
||||||
invokerTemplate.AddDefine("returnType", "void");
|
invokerTemplate.AddDefine("returnType", "void");
|
||||||
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterface.ToDisplayString());
|
invokerTemplate.AddDefine("suitableType", baseInterface.ToUnityString());
|
||||||
invokerTemplate.AddDefine("funcInvoking", funcInvoking);
|
invokerTemplate.AddDefine("funcInvoking", funcInvoking);
|
||||||
var backend = invokerTemplate.Compile();
|
var backend = invokerTemplate.Compile();
|
||||||
MethodRepoTemplate.Insert("invoker", backend);
|
_methodRepoTemplate.Insert("invoker", backend);
|
||||||
|
|
||||||
invokers.Add(backend);
|
invokers.Add(backend);
|
||||||
}
|
}
|
||||||
@@ -491,58 +468,45 @@ namespace mROA.Codegen
|
|||||||
private void GeneratePropertyMethod(IMethodSymbol method,
|
private void GeneratePropertyMethod(IMethodSymbol method,
|
||||||
List<(string, IMethodSymbol)> propsCollection, List<string> invokers, INamedTypeSymbol baseInterace)
|
List<(string, IMethodSymbol)> propsCollection, List<string> invokers, INamedTypeSymbol baseInterace)
|
||||||
{
|
{
|
||||||
var level = "\t\t\t";
|
|
||||||
var index = invokers.Count;
|
var index = invokers.Count;
|
||||||
string frontend;
|
string frontend;
|
||||||
string backend = string.Empty;
|
string backend;
|
||||||
if (method.MethodKind == MethodKind.PropertyGet)
|
if (method.MethodKind == MethodKind.PropertyGet)
|
||||||
{
|
{
|
||||||
var parametersArray = "";
|
var parametersArray = "";
|
||||||
if (method.Parameters.Length != 0)
|
if (method.Parameters.Length != 0)
|
||||||
{
|
{
|
||||||
parametersArray = $", new object[] {{{string.Join(", ", method.Parameters.Select(p => p.Name))}}}";
|
parametersArray =
|
||||||
|
$", new System.Object[] {{ {string.Join(", ", method.Parameters.Select(p => p.Name))} }}";
|
||||||
|
|
||||||
var parameterTypes = string.Join(", ",
|
var parameterTypes = string.Join(", ",
|
||||||
$"{string.Join(", ", method.Parameters.Select(p => "typeof(" + p.Type.ToDisplayString() + ")"))}");
|
$"{string.Join(", ", method.Parameters.Select(p => "typeof(" + p.Type.ToUnityString() + ")"))}");
|
||||||
var parameterInserts = string.Join(", ",
|
var parameterInserts = string.Join(", ",
|
||||||
method.Parameters.Select(
|
method.Parameters.Select(
|
||||||
p => Caster(p.Type, "parameters[" + method.Parameters.IndexOf(p) + "]")));
|
p => Caster(p.Type, "parameters[" + method.Parameters.IndexOf(p) + "]")));
|
||||||
|
|
||||||
var invokerTemplate = (TemplateDocument)MethodInvokerOriginal.Clone();
|
var invokerTemplate = (TemplateDocument)_methodInvokerOriginal.Clone();
|
||||||
invokerTemplate.AddDefine("isVoid", "false");
|
invokerTemplate.AddDefine("isVoid", "false");
|
||||||
invokerTemplate.AddDefine("returnType", method.ReturnType.ToDisplayString());
|
invokerTemplate.AddDefine("returnType", method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterace.ToDisplayString());
|
invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString());
|
||||||
invokerTemplate.AddDefine("funcInvoking", $"(i as {method.ContainingType.ToDisplayString()})[{parameterInserts}]");
|
invokerTemplate.AddDefine("funcInvoking",
|
||||||
|
$"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}]");
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
// backend = $@"new mROA.Implementation.MethodInvoker
|
|
||||||
// {level}{{
|
|
||||||
// {level} IsVoid = false,
|
|
||||||
// {level} ReturnType = typeof({method.ReturnType.ToDisplayString()}),
|
|
||||||
// {level} ParameterTypes = new Type[] {{ {parameterTypes} }},
|
|
||||||
// {level} SuitableType = typeof({baseInterace.ToDisplayString()}),
|
|
||||||
// {level} Invoking = (i, parameters, _) => (i as {method.ContainingType.ToDisplayString()})[{parameterInserts}],
|
|
||||||
// {level}}}";
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var invokerTemplate = (TemplateDocument)MethodInvokerOriginal.Clone();
|
var invokerTemplate = (TemplateDocument)_methodInvokerOriginal.Clone();
|
||||||
invokerTemplate.AddDefine("isVoid", "false");
|
invokerTemplate.AddDefine("isVoid", "false");
|
||||||
invokerTemplate.AddDefine("returnType", method.ReturnType.ToDisplayString());
|
invokerTemplate.AddDefine("returnType", method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterace.ToDisplayString());
|
invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString());
|
||||||
invokerTemplate.AddDefine("funcInvoking", $"(i as {method.ContainingType.ToDisplayString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name}");
|
invokerTemplate.AddDefine("funcInvoking",
|
||||||
|
$"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name}");
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
// backend = $@"new mROA.Implementation.MethodInvoker
|
|
||||||
// {level}{{
|
|
||||||
// {level} IsVoid = false,
|
|
||||||
// {level} ReturnType = typeof({method.ReturnType.ToDisplayString()}),
|
|
||||||
// {level} SuitableType = typeof({baseInterace.ToDisplayString()}),
|
|
||||||
// {level} Invoking = (i, _, _) => (i as {method.ContainingType.ToDisplayString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name},
|
|
||||||
// {level}}}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
frontend =
|
frontend =
|
||||||
$"get => GetResultAsync<{method.ReturnType.ToDisplayString()}>({index}{parametersArray}).GetAwaiter().GetResult();";
|
$"get => GetResultAsync<{method.ReturnType.ToUnityString()}>({index}{parametersArray}).GetAwaiter().GetResult();";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -552,77 +516,63 @@ namespace mROA.Codegen
|
|||||||
parametersArray = string.Join(", ", method.Parameters.Select(p => p.Name));
|
parametersArray = string.Join(", ", method.Parameters.Select(p => p.Name));
|
||||||
|
|
||||||
var parameterTypes = string.Join(", ",
|
var parameterTypes = string.Join(", ",
|
||||||
$"{string.Join(", ", method.Parameters.Select(p => $"typeof({p.Type.ToDisplayString()})"))}");
|
$"{string.Join(", ", method.Parameters.Select(p => $"typeof({p.Type.ToUnityString()})"))}");
|
||||||
var parameterInserts = string.Join(", ",
|
var parameterInserts = string.Join(", ",
|
||||||
method.Parameters.Take(method.Parameters.Length - 1).Select(p =>
|
method.Parameters.Take(method.Parameters.Length - 1).Select(p =>
|
||||||
Caster(p.Type, "parameters[" + method.Parameters.IndexOf(p) + "]")));
|
Caster(p.Type, "parameters[" + method.Parameters.IndexOf(p) + "]")));
|
||||||
|
|
||||||
var valueInsert = Caster(method.Parameters.Last().Type,
|
var valueInsert = Caster(method.Parameters.Last().Type,
|
||||||
"parameters[" + (method.Parameters.Length - 1) + "]");
|
"parameters[" + (method.Parameters.Length - 1) + "]");
|
||||||
var invokerTemplate = (TemplateDocument)MethodInvokerOriginal.Clone();
|
var invokerTemplate = (TemplateDocument)_methodInvokerOriginal.Clone();
|
||||||
|
|
||||||
|
|
||||||
invokerTemplate.AddDefine("isVoid", "true");
|
invokerTemplate.AddDefine("isVoid", "true");
|
||||||
invokerTemplate.AddDefine("returnType", method.ReturnType.ToDisplayString());
|
invokerTemplate.AddDefine("returnType", method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
invokerTemplate.AddDefine("parametersType", parameterTypes);
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterace.ToDisplayString());
|
invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString());
|
||||||
invokerTemplate.AddDefine("funcInvoking", $"(i as {method.ContainingType.ToDisplayString()})[{parameterInserts}] = {valueInsert}");
|
invokerTemplate.AddDefine("funcInvoking",
|
||||||
|
$"(i as {method.ContainingType.ToUnityString()})[{parameterInserts}] = {valueInsert}");
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
// backend = $@"new mROA.Implementation.MethodInvoker
|
|
||||||
// {level}{{
|
|
||||||
// {level} IsVoid = true,
|
|
||||||
// {level} ReturnType = typeof({method.ReturnType.ToDisplayString()}),
|
|
||||||
// {level} ParameterTypes = new Type[] {{ {parameterTypes} }},
|
|
||||||
// {level} SuitableType = typeof({baseInterace.ToDisplayString()}),
|
|
||||||
// {level} Invoking = (i, parameters, _) => (i as {method.ContainingType.ToDisplayString()})[{parameterInserts}] = {valueInsert},
|
|
||||||
// {level}}}";
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var invokerTemplate = (TemplateDocument)MethodInvokerOriginal.Clone();
|
var invokerTemplate = (TemplateDocument)_methodInvokerOriginal.Clone();
|
||||||
|
|
||||||
invokerTemplate.AddDefine("isVoid", "true");
|
invokerTemplate.AddDefine("isVoid", "true");
|
||||||
invokerTemplate.AddDefine("returnType", method.ReturnType.ToDisplayString());
|
invokerTemplate.AddDefine("returnType", method.ReturnType.ToUnityString());
|
||||||
invokerTemplate.AddDefine("parametersType", $"typeof({method.Parameters.First().Type.ToDisplayString()})");
|
invokerTemplate.AddDefine("parametersType",
|
||||||
invokerTemplate.AddDefine("suitableType", baseInterace.ToDisplayString());
|
$"typeof({method.Parameters.First().Type.ToUnityString()})");
|
||||||
invokerTemplate.AddDefine("funcInvoking", $"(i as {method.ContainingType.ToDisplayString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name} = {Caster((method.AssociatedSymbol as IPropertySymbol)!.Type, "parameters[0]")}");
|
invokerTemplate.AddDefine("suitableType", baseInterace.ToUnityString());
|
||||||
|
invokerTemplate.AddDefine("funcInvoking",
|
||||||
|
$"(i as {method.ContainingType.ToUnityString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name} = {Caster((method.AssociatedSymbol as IPropertySymbol)!.Type, "parameters[0]")}");
|
||||||
backend = invokerTemplate.Compile();
|
backend = invokerTemplate.Compile();
|
||||||
|
|
||||||
// backend = $@"new mROA.Implementation.MethodInvoker
|
|
||||||
// {level}{{
|
|
||||||
// {level} IsVoid = true,
|
|
||||||
// {level} ReturnType = typeof({method.ReturnType.ToDisplayString()}),
|
|
||||||
// {level} ParameterTypes = new Type[] {{ typeof({method.Parameters.First().Type.ToDisplayString()}) }},
|
|
||||||
// {level} SuitableType = typeof({baseInterace.ToDisplayString()}),
|
|
||||||
// {level} Invoking = (i, parameters, _) => (i as {method.ContainingType.ToDisplayString()}).{(method.AssociatedSymbol as IPropertySymbol)!.Name} = {Caster((method.AssociatedSymbol as IPropertySymbol)!.Type, "parameters[0]")},
|
|
||||||
// {level}}}";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
frontend = $"set => CallAsync({index}, new object[] {{ {parametersArray} }}).Wait();";
|
frontend = $"set => CallAsync({index}, new System.Object[] {{ {parametersArray} }}).Wait();";
|
||||||
}
|
}
|
||||||
|
|
||||||
propsCollection.Add((frontend, method));
|
propsCollection.Add((frontend, method));
|
||||||
MethodRepoTemplate.Insert("invoker", backend);
|
_methodRepoTemplate.Insert("invoker", backend);
|
||||||
invokers.Add(backend);
|
invokers.Add(backend);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ToFullString(IParameterSymbol parameter)
|
private static string ToFullString(IParameterSymbol parameter)
|
||||||
=> /*parameter.Type.ContainingNamespace is null*/
|
{
|
||||||
/*?*/ parameter.ToDisplayString();
|
return parameter.ToDisplayParts().ToUnityString();
|
||||||
/*: $"{parameter.Type.ContainingNamespace.ToDisplayString()}.{parameter.Type.MetadataName} {parameter.Name}";*/
|
}
|
||||||
|
|
||||||
private static string ToFullString(ITypeSymbol type) =>
|
private static string ToFullString(ITypeSymbol type)
|
||||||
// => type.ContainingNamespace is null || type.Name == "Void"
|
{
|
||||||
type.ToDisplayString();
|
return type.ToUnityString();
|
||||||
// : $"{type.ContainingNamespace.ToDisplayString()}.{type.MetadataName}";
|
}
|
||||||
|
|
||||||
private string ExtractTaskType(ITypeSymbol taskType)
|
private string ExtractTaskType(ITypeSymbol taskType)
|
||||||
{
|
{
|
||||||
var generics = ((INamedTypeSymbol)taskType).TypeArguments;
|
var generics = ((INamedTypeSymbol)taskType).TypeArguments;
|
||||||
return generics.Length == 0 ? "void" : generics[0].ToDisplayString();
|
return generics.Length == 0 ? "void" : generics[0].ToUnityString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool ContainsSOIAttribute(SyntaxList<AttributeListSyntax> attributes, GeneratorExecutionContext context,
|
private bool ContainsSoiAttribute(SyntaxList<AttributeListSyntax> attributes, GeneratorExecutionContext context,
|
||||||
InterfaceDeclarationSyntax interfaceDeclarationSyntax)
|
InterfaceDeclarationSyntax interfaceDeclarationSyntax)
|
||||||
{
|
{
|
||||||
foreach (var attributeSyntax in
|
foreach (var attributeSyntax in
|
||||||
@@ -632,7 +582,7 @@ namespace mROA.Codegen
|
|||||||
.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol)
|
.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol)
|
||||||
continue; // if we can't get the symbol, ignore it
|
continue; // if we can't get the symbol, ignore it
|
||||||
|
|
||||||
string attributeName = attributeSymbol.ContainingType.ToDisplayString();
|
var attributeName = attributeSymbol.ContainingType.ToDisplayString();
|
||||||
|
|
||||||
// Check the full name of the [Report] attribute.
|
// Check the full name of the [Report] attribute.
|
||||||
if (attributeName == "mROA.Implementation.Attributes.SharedObjectInterfaceAttribute")
|
if (attributeName == "mROA.Implementation.Attributes.SharedObjectInterfaceAttribute")
|
||||||
@@ -645,13 +595,44 @@ namespace mROA.Codegen
|
|||||||
private List<IMethodSymbol> CollectMembers(INamedTypeSymbol type)
|
private List<IMethodSymbol> CollectMembers(INamedTypeSymbol type)
|
||||||
{
|
{
|
||||||
var methods = type.GetMembers().OfType<IMethodSymbol>().ToList();
|
var methods = type.GetMembers().OfType<IMethodSymbol>().ToList();
|
||||||
foreach (var inner in type.AllInterfaces)
|
foreach (var inner in type.AllInterfaces) methods.AddRange(inner.GetMembers().OfType<IMethodSymbol>());
|
||||||
{
|
|
||||||
methods.AddRange(inner.GetMembers().OfType<IMethodSymbol>());
|
|
||||||
}
|
|
||||||
|
|
||||||
methods.RemoveAll(m => m.Name == "Dispose");
|
methods.RemoveAll(m => m.Name == "Dispose");
|
||||||
return methods.OrderBy(i => i.Name).ToList();
|
return methods.OrderBy(i => i.Name).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class CodegenExtentions
|
||||||
|
{
|
||||||
|
public static string ToUnityString(this ITypeSymbol type)
|
||||||
|
{
|
||||||
|
var parts = type.ToDisplayParts();
|
||||||
|
|
||||||
|
if (parts.Any(i => i.Kind == SymbolDisplayPartKind.Keyword)) return parts.ToUnityString();
|
||||||
|
|
||||||
|
return type.ToDisplayString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToUnityString(this ImmutableArray<SymbolDisplayPart> parts)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
foreach (var displayPart in parts)
|
||||||
|
if (displayPart.Kind == SymbolDisplayPartKind.Keyword)
|
||||||
|
{
|
||||||
|
if (displayPart.ToString() == "void")
|
||||||
|
{
|
||||||
|
sb.Append(displayPart.ToString());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append($"{displayPart.Symbol!.ContainingNamespace.ToDisplayString()}.{displayPart.Symbol.Name}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb.Append(displayPart.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -23,6 +23,8 @@ namespace mROA.Implementation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public int Id => (_interaction ?? throw new NullReferenceException("Interaction is not initialized"))
|
public int Id => (_interaction ?? throw new NullReferenceException("Interaction is not initialized"))
|
||||||
.ConnectionId;
|
.ConnectionId;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user