add: Template Define
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
"profiles": {
|
"profiles": {
|
||||||
"DebugRoslynSourceGenerator": {
|
"DebugRoslynSourceGenerator": {
|
||||||
"commandName": "DebugRoslynComponent",
|
"commandName": "DebugRoslynComponent",
|
||||||
"targetProject": "../Polonium.Generators.Test/Polonium.Generators.Test.csproj"
|
"targetProject": "../Polonium.Workspace/Polonium.Test/Polonium.Test.csproj"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
namespace Polonium.Generators;
|
namespace Polonium.Generators;
|
||||||
|
|
||||||
@@ -75,6 +77,14 @@ public abstract class AssetProcessGenerator : ISourceGenerator
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
protected static string Format(string template, string data)
|
||||||
|
{
|
||||||
|
string[] dataParts = data.Split(':');
|
||||||
|
for(int i = 0; i < dataParts.Length; i++)
|
||||||
|
template = template.Replace($"/*{i}*/", dataParts[i]);
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
34
src/ContextExtensions.cs
Normal file
34
src/ContextExtensions.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
|
namespace Polonium.Generators;
|
||||||
|
|
||||||
|
public static class ContextExtensions
|
||||||
|
{
|
||||||
|
public static IEnumerable<ClassDeclarationSyntax> GetClassesWithAttribute(this GeneratorExecutionContext context, ClassSyntaxReceiver receiver, INamedTypeSymbol? t)
|
||||||
|
{
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
foreach (ClassDeclarationSyntax? cls in receiver.Classes)
|
||||||
|
{
|
||||||
|
SemanticModel model = compilation.GetSemanticModel(cls.SyntaxTree);
|
||||||
|
if (
|
||||||
|
model.GetDeclaredSymbol(cls) is INamedTypeSymbol symbol &&
|
||||||
|
symbol.GetAttributes().Any(x => SymbolEqualityComparer.Default.Equals(x.AttributeClass, t))
|
||||||
|
)
|
||||||
|
yield return cls;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<AttributeData> GetAttributes(this GeneratorExecutionContext context, ClassDeclarationSyntax cls, INamedTypeSymbol? t)
|
||||||
|
{
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
SemanticModel model = compilation.GetSemanticModel(cls.SyntaxTree);
|
||||||
|
return model
|
||||||
|
.GetDeclaredSymbol(cls)!
|
||||||
|
.GetAttributes()
|
||||||
|
.Where(x => SymbolEqualityComparer.Default.Equals(x.AttributeClass, t));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
namespace Polonium.Generators.Generators;
|
namespace Polonium.Generators.Generators;
|
||||||
[Generator]
|
[Generator]
|
||||||
@@ -12,7 +13,7 @@ public class RegistryEntityGenerator : AssetProcessGenerator
|
|||||||
return;
|
return;
|
||||||
Compilation compilation = context.Compilation;
|
Compilation compilation = context.Compilation;
|
||||||
INamedTypeSymbol? regEntity = compilation.GetTypeByMetadataName("Polonium.Attributes.RegistryEntity");
|
INamedTypeSymbol? regEntity = compilation.GetTypeByMetadataName("Polonium.Attributes.RegistryEntity");
|
||||||
foreach (var derivedClassDeclaration in receiver.Classes)
|
foreach (ClassDeclarationSyntax? derivedClassDeclaration in receiver.Classes)
|
||||||
{
|
{
|
||||||
SemanticModel model = compilation.GetSemanticModel(derivedClassDeclaration.SyntaxTree);
|
SemanticModel model = compilation.GetSemanticModel(derivedClassDeclaration.SyntaxTree);
|
||||||
if (
|
if (
|
||||||
|
|||||||
69
src/Generators/TemplateBlockGenerator.cs
Normal file
69
src/Generators/TemplateBlockGenerator.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
|
namespace Polonium.Generators.Generators;
|
||||||
|
[Generator]
|
||||||
|
public class TemplateBlockGenerator : AssetProcessGenerator
|
||||||
|
{
|
||||||
|
public override void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
if (!(context.SyntaxReceiver is ClassSyntaxReceiver receiver))
|
||||||
|
return;
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
INamedTypeSymbol? templateDefine = compilation.GetTypeByMetadataName("Polonium.Attributes.TemplateDefines.TemplateBlock");
|
||||||
|
|
||||||
|
foreach (ClassDeclarationSyntax? cls in context.GetClassesWithAttribute(receiver, templateDefine))
|
||||||
|
{
|
||||||
|
if(!cls.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)))
|
||||||
|
continue;
|
||||||
|
string isStatic = "";
|
||||||
|
if(cls.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword)))
|
||||||
|
isStatic = "static";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb
|
||||||
|
.AppendLine($"public {isStatic} partial class {cls.Identifier.ToString()}")
|
||||||
|
.AppendLine("{");
|
||||||
|
HashSet<string> headers = new();
|
||||||
|
foreach (AttributeData attr in context.GetAttributes(cls, templateDefine))
|
||||||
|
{
|
||||||
|
string signature = attr.ConstructorArguments[0].Value?.ToString()??string.Empty;
|
||||||
|
string template = attr.ConstructorArguments[1].Value?.ToString()??string.Empty;
|
||||||
|
string dataFile = attr.ConstructorArguments[2].Value?.ToString()??string.Empty;
|
||||||
|
string depsStr = attr.ConstructorArguments[3].Value?.ToString()??string.Empty;
|
||||||
|
string[] deps = depsStr.Split(';');
|
||||||
|
foreach (string dep in deps)
|
||||||
|
headers.Add(dep);
|
||||||
|
sb
|
||||||
|
.AppendLine($" {signature}")
|
||||||
|
.AppendLine(" {");
|
||||||
|
AdditionalText? df = context.AdditionalFiles.FirstOrDefault(f => f.Path.EndsWith(dataFile));
|
||||||
|
string[] data =(df?.GetText()?.ToString() ?? "").Split('\n');
|
||||||
|
foreach (string d in data)
|
||||||
|
{
|
||||||
|
if(d.Trim().Equals(""))
|
||||||
|
continue;
|
||||||
|
sb.AppendLine($" {Format(template, d)}");
|
||||||
|
}
|
||||||
|
sb.AppendLine(" }");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine("}");
|
||||||
|
StringBuilder hb = new StringBuilder();
|
||||||
|
foreach (string header in headers)
|
||||||
|
{
|
||||||
|
if(header.Trim().Equals(""))
|
||||||
|
continue;
|
||||||
|
hb.AppendLine($"using {header};");
|
||||||
|
}
|
||||||
|
hb.Append(sb);
|
||||||
|
context.AddSource($"{cls.Identifier.ToString()}_TemplateDefine.g.cs", hb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
63
src/Generators/TemplateInlineGenerator.cs
Normal file
63
src/Generators/TemplateInlineGenerator.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
|
namespace Polonium.Generators.Generators;
|
||||||
|
[Generator]
|
||||||
|
public class TemplateInlineGenerator : AssetProcessGenerator
|
||||||
|
{
|
||||||
|
public override void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
if (!(context.SyntaxReceiver is ClassSyntaxReceiver receiver))
|
||||||
|
return;
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
INamedTypeSymbol? templateDefine = compilation.GetTypeByMetadataName("Polonium.Attributes.TemplateDefines.TemplateInline");
|
||||||
|
|
||||||
|
foreach (ClassDeclarationSyntax? cls in context.GetClassesWithAttribute(receiver, templateDefine))
|
||||||
|
{
|
||||||
|
if(!cls.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)))
|
||||||
|
continue;
|
||||||
|
string isStatic = "";
|
||||||
|
if(cls.Modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword)))
|
||||||
|
isStatic = "static";
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb
|
||||||
|
.AppendLine($"public {isStatic} partial class {cls.Identifier.ToString()}")
|
||||||
|
.AppendLine("{");
|
||||||
|
HashSet<string> headers = new();
|
||||||
|
foreach (AttributeData attr in context.GetAttributes(cls, templateDefine))
|
||||||
|
{
|
||||||
|
string template = attr.ConstructorArguments[0].Value?.ToString()??string.Empty;
|
||||||
|
string dataFile = attr.ConstructorArguments[1].Value?.ToString()??string.Empty;
|
||||||
|
string depsString = attr.ConstructorArguments[2].Value?.ToString()??string.Empty;
|
||||||
|
string[] deps = depsString.Split(';');
|
||||||
|
foreach (string dep in deps)
|
||||||
|
headers.Add(dep);
|
||||||
|
AdditionalText? df = context.AdditionalFiles.FirstOrDefault(f => f.Path.EndsWith(dataFile));
|
||||||
|
string[] data =(df?.GetText()?.ToString() ?? "").Split('\n');
|
||||||
|
foreach (string d in data)
|
||||||
|
{
|
||||||
|
if(d.Trim().Equals(""))
|
||||||
|
continue;
|
||||||
|
sb.AppendLine($" {Format(template, d)}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine("}");
|
||||||
|
StringBuilder hb = new();
|
||||||
|
foreach(string header in headers)
|
||||||
|
{
|
||||||
|
if(header.Trim().Equals(""))
|
||||||
|
continue;
|
||||||
|
hb.AppendLine($"using {header};");
|
||||||
|
}
|
||||||
|
hb.Append(sb);
|
||||||
|
Console.WriteLine(hb.ToString());
|
||||||
|
context.AddSource($"{cls.Identifier.ToString()}_TemplateInline.g.cs", hb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user