Compare commits
15 Commits
a34fca7581
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 400cc3a048 | |||
| f93f1eaf74 | |||
| 7f7ef09231 | |||
| f53c66a8ec | |||
| 9668c27e2d | |||
| ed9ae2113d | |||
| 03468ad89c | |||
| 302d11e2dd | |||
| 8bb977c735 | |||
| c7970c2274 | |||
| fc54380ce3 | |||
| 0a3a6faca5 | |||
| e97b2f098f | |||
| 6738080639 | |||
| 24a74a6f80 |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -2,4 +2,8 @@ bin/
|
|||||||
obj/
|
obj/
|
||||||
/packages/
|
/packages/
|
||||||
riderModule.iml
|
riderModule.iml
|
||||||
/_ReSharper.Caches/
|
/_ReSharper.Caches/
|
||||||
|
.idea/
|
||||||
|
VersionInfo.props
|
||||||
|
/summerizer.py
|
||||||
|
/summerizer
|
||||||
|
|||||||
13
.idea/.idea.Polonium.Generators/.idea/.gitignore
generated
vendored
13
.idea/.idea.Polonium.Generators/.idea/.gitignore
generated
vendored
@@ -1,13 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Rider ignored files
|
|
||||||
/contentModel.xml
|
|
||||||
/modules.xml
|
|
||||||
/.idea.Hangman.SDK.Generators.iml
|
|
||||||
/projectSettingsUpdater.xml
|
|
||||||
# Editor-based HTTP Client requests
|
|
||||||
/httpRequests/
|
|
||||||
# Datasource local storage ignored files
|
|
||||||
/dataSources/
|
|
||||||
/dataSources.local.xml
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
|
||||||
</project>
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="UserContentModel">
|
|
||||||
<attachedFolders />
|
|
||||||
<explicitIncludes />
|
|
||||||
<explicitExcludes />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
6
.idea/.idea.Polonium.Generators/.idea/vcs.xml
generated
6
.idea/.idea.Polonium.Generators/.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<Import Project="VersionInfo.props" Condition="Exists('VersionInfo.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
|
|
||||||
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
|
||||||
<IsRoslynComponent>true</IsRoslynComponent>
|
<IsRoslynComponent>true</IsRoslynComponent>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<Version>0.1.1-x</Version>
|
<Version>$(PoloniumGeneratorsVersion)</Version>
|
||||||
<Authors>Hangman</Authors>
|
<Authors>Hangman</Authors>
|
||||||
<PackageId>Polonium.Generators</PackageId>
|
<PackageId>Polonium.Generators</PackageId>
|
||||||
<DisableImplicitRestore>true</DisableImplicitRestore>
|
<DisableImplicitRestore>true</DisableImplicitRestore>
|
||||||
@@ -33,18 +32,13 @@
|
|||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="CopyPackageToLocalFeed" AfterTargets="Pack">
|
<Target Name="CopyPackageToLocalFeed" AfterTargets="Pack">
|
||||||
<Message Text="Executing Copy Pack Task" Importance="high" />
|
|
||||||
<Message Text="OutputPath: $(ProjectDir)$(OutputPath)" Importance="high" />
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<NuGetPackages Include="$(OutputPath)../*.nupkg" />
|
<NuGetPackages Include="$(OutputPath)../*.nupkg" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Message Text="Printing pkgs--------------------" Importance="high"/>
|
|
||||||
<Message Text="Pkgs: @(NuGetPackages)" Importance="high"/>
|
|
||||||
<Copy SourceFiles="@(NuGetPackages)" DestinationFolder="/NuGetFeed"/>
|
<Copy SourceFiles="@(NuGetPackages)" DestinationFolder="/NuGetFeed"/>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="RestoreNoCache" BeforeTargets="Restore">
|
<Target Name="RestoreNoCache" BeforeTargets="CoreCompile">
|
||||||
<Message Text="Restoring packages with no chache" Importance="high"/>
|
|
||||||
<Exec Command="dotnet restore --no-cache"/>
|
<Exec Command="dotnet restore --no-cache"/>
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
36
README.md
Normal file
36
README.md
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# Polonium.Generators
|
||||||
|
|
||||||
|
**Project Description**
|
||||||
|
Polonium.Generators is a C# source generator suite specifically built for the Polonium ecosystem. By analyzing attributes like `[ProxyNode]`, `[AutoPatch]`, `[RegistryEntity]`, and `[RegistryPassThrough]`, it generates boilerplate code that ties together key features in Polonium, reducing repetitive tasks and ensuring consistency.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Code Generation Highlights
|
||||||
|
|
||||||
|
1. **`[ProxyNode]`**
|
||||||
|
When a class is annotated with `[ProxyNode]` (and optionally `[ProxyProperty]` for properties or `[ProxyMethod]` for methods), Polonium.Generators automatically creates partial classes or methods, simplifying script bridging and property handling. This is primarily used in Polonium’s embedded classes, but it can also be extended.
|
||||||
|
|
||||||
|
2. **`[AutoPatch]` & `[PatchableProperty]`**
|
||||||
|
If an interface is marked with `[AutoPatch]` and contains at most one `[PatchableProperty]` (with a getter and setter), Polonium.Generators will create a corresponding Patch class. This allows you to apply changes ("patches") to classes implementing that interface without direct references, greatly simplifying state synchronization.
|
||||||
|
|
||||||
|
3. **`[RegistryEntity]`**
|
||||||
|
Classes annotated with `[RegistryEntity]` trigger a code generation step that adds a property for that class in `GlobalRegistry`, enabling you to easily access and manage instances across your entire project.
|
||||||
|
|
||||||
|
4. **`[RegistryPassThrough]`**
|
||||||
|
Properties marked with `[RegistryPassThrough]` are automatically bridged so that getting or setting them references the central `PoloniumRegistry`. While primarily used by Polonium’s own embedded classes, it can be adapted for larger multi-module scenarios.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
1. Ensure you’re targeting .NET 6 or higher (or the same version Polonium requires).
|
||||||
|
2. Install via NuGet:
|
||||||
|
```bash
|
||||||
|
dotnet add package Polonium.Generators
|
||||||
|
```
|
||||||
|
3. Add `<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>` in your `.csproj` if you want to inspect the generated sources.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## License
|
||||||
|
This project is licensed under the [MIT License](https://opensource.org/licenses/MIT).
|
||||||
|
|
||||||
12
publish
Normal file → Executable file
12
publish
Normal file → Executable file
@@ -1,2 +1,12 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
dotnet nuget push "$(ls -t ./bin/Debug/Polonium.Generators.*.nupkg | head -n 1)" --source hangman-lab
|
|
||||||
|
SCRIPT_DIR=$(dirname "$(realpath "${BASH_SOURCE[0]}")")/
|
||||||
|
LATEST_PACKAGE=$(ls -t "${SCRIPT_DIR}"bin/Debug/Polonium.Generators.*.nupkg 2>/dev/null | head -n 1)
|
||||||
|
|
||||||
|
if [[ -z "$LATEST_PACKAGE" ]]; then
|
||||||
|
echo "❌ Error: No .nupkg file found in ${SCRIPT_DIR}/bin/Debug/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "🚀 Pushing NuGet package: $LATEST_PACKAGE"
|
||||||
|
dotnet nuget push "$LATEST_PACKAGE" --source hangman-lab --skip-duplicate
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
@@ -10,7 +12,7 @@ public abstract class AssetProcessGenerator : ISourceGenerator
|
|||||||
{
|
{
|
||||||
context.RegisterForSyntaxNotifications(() => new ClassSyntaxReceiver());
|
context.RegisterForSyntaxNotifications(() => new ClassSyntaxReceiver());
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void Execute(GeneratorExecutionContext context);
|
public abstract void Execute(GeneratorExecutionContext context);
|
||||||
|
|
||||||
protected IEnumerable<AssetInfo> GetAssetsOfType(GeneratorExecutionContext context, INamedTypeSymbol? t)
|
protected IEnumerable<AssetInfo> GetAssetsOfType(GeneratorExecutionContext context, INamedTypeSymbol? t)
|
||||||
@@ -75,6 +77,146 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected IEnumerable<InterfaceInfo> GetInterfacesWithAttribute(GeneratorExecutionContext context,
|
||||||
|
INamedTypeSymbol? attribute)
|
||||||
|
{
|
||||||
|
if(context.SyntaxReceiver is not ClassSyntaxReceiver receiver)
|
||||||
|
yield break;
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
foreach (InterfaceDeclarationSyntax ifc in receiver.Interfaces)
|
||||||
|
{
|
||||||
|
SemanticModel model = compilation.GetSemanticModel(ifc.SyntaxTree);
|
||||||
|
INamedTypeSymbol? interfaceSymbol = model.GetDeclaredSymbol(ifc) as INamedTypeSymbol;
|
||||||
|
string filePath = ifc.SyntaxTree.FilePath;
|
||||||
|
string interfaceName = Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
if(interfaceSymbol is null)
|
||||||
|
continue;
|
||||||
|
if (HasAttribute(interfaceSymbol, attribute))
|
||||||
|
yield return new InterfaceInfo
|
||||||
|
{
|
||||||
|
DeclarationSyntax = ifc,
|
||||||
|
InterfaceName = interfaceName,
|
||||||
|
InterfaceFillName = interfaceSymbol.ToDisplayString(),
|
||||||
|
Path = filePath,
|
||||||
|
Symbol = interfaceSymbol,
|
||||||
|
Namespace = interfaceSymbol.ContainingNamespace.ToDisplayString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IEnumerable<ClassInfo> GetClassesWithAttribute(GeneratorExecutionContext context,
|
||||||
|
INamedTypeSymbol? attribute)
|
||||||
|
{
|
||||||
|
if(context.SyntaxReceiver is not ClassSyntaxReceiver receiver)
|
||||||
|
yield break;
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
foreach (ClassDeclarationSyntax? declaration in receiver.Classes)
|
||||||
|
{
|
||||||
|
SemanticModel model = compilation.GetSemanticModel(declaration.SyntaxTree);
|
||||||
|
INamedTypeSymbol? sClassSymbol = model.GetDeclaredSymbol(declaration) as INamedTypeSymbol;
|
||||||
|
string filePath = declaration.SyntaxTree.FilePath;
|
||||||
|
string className = Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
if (sClassSymbol is null)
|
||||||
|
continue;
|
||||||
|
if (HasAttribute(sClassSymbol, attribute))
|
||||||
|
yield return new ClassInfo
|
||||||
|
{
|
||||||
|
DeclarationSyntax = declaration,
|
||||||
|
ClassName = className,
|
||||||
|
ClassFullName = sClassSymbol.ToDisplayString(),
|
||||||
|
Path = filePath,
|
||||||
|
Symbol = sClassSymbol,
|
||||||
|
Namespace = sClassSymbol.ContainingNamespace.ToDisplayString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected IEnumerable<ClassInfo> GetClassesWithInterface(GeneratorExecutionContext context, INamedTypeSymbol? ifc, bool direct = true)
|
||||||
|
{
|
||||||
|
if(context.SyntaxReceiver is not ClassSyntaxReceiver receiver)
|
||||||
|
yield break;
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
foreach (ClassDeclarationSyntax? declaration in receiver.Classes)
|
||||||
|
{
|
||||||
|
SemanticModel model = compilation.GetSemanticModel(declaration.SyntaxTree);
|
||||||
|
INamedTypeSymbol? sClassSymbol = model.GetDeclaredSymbol(declaration) as INamedTypeSymbol;
|
||||||
|
string filePath = declaration.SyntaxTree.FilePath;
|
||||||
|
string className = Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
bool interfaceFound = false;
|
||||||
|
if (sClassSymbol is null)
|
||||||
|
yield break;
|
||||||
|
if (direct)
|
||||||
|
interfaceFound = sClassSymbol.Interfaces.Any(i => SymbolEqualityComparer.Default.Equals(i, ifc));
|
||||||
|
else
|
||||||
|
interfaceFound = sClassSymbol.AllInterfaces.Any(i => SymbolEqualityComparer.Default.Equals(i, ifc));
|
||||||
|
|
||||||
|
if (interfaceFound)
|
||||||
|
{
|
||||||
|
yield return new ClassInfo
|
||||||
|
{
|
||||||
|
DeclarationSyntax = declaration,
|
||||||
|
ClassName = className,
|
||||||
|
ClassFullName = sClassSymbol.ToDisplayString(),
|
||||||
|
Path = filePath,
|
||||||
|
Symbol = sClassSymbol,
|
||||||
|
Namespace = sClassSymbol.ContainingNamespace.ToDisplayString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static bool HasAttribute(INamedTypeSymbol? type, INamedTypeSymbol? attr)
|
||||||
|
{
|
||||||
|
if (type is null)
|
||||||
|
return false;
|
||||||
|
return type.GetAttributes().Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, attr));
|
||||||
|
}
|
||||||
|
protected IEnumerable<ClassInfo> GetClassesOfType(GeneratorExecutionContext context, INamedTypeSymbol? type)
|
||||||
|
{
|
||||||
|
if(context.SyntaxReceiver is not ClassSyntaxReceiver receiver)
|
||||||
|
yield break;
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
foreach (ClassDeclarationSyntax? declaration in receiver.Classes)
|
||||||
|
{
|
||||||
|
SemanticModel model = compilation.GetSemanticModel(declaration.SyntaxTree);
|
||||||
|
INamedTypeSymbol? sClassSymbol = model.GetDeclaredSymbol(declaration) as INamedTypeSymbol;
|
||||||
|
string filePath = declaration.SyntaxTree.FilePath;
|
||||||
|
string className = Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
if (sClassSymbol is null)
|
||||||
|
continue;
|
||||||
|
ClassInfo res = new ClassInfo
|
||||||
|
{
|
||||||
|
DeclarationSyntax = declaration,
|
||||||
|
ClassName = className,
|
||||||
|
ClassFullName = sClassSymbol.ToDisplayString(),
|
||||||
|
Path = filePath,
|
||||||
|
Symbol = sClassSymbol,
|
||||||
|
Namespace = sClassSymbol.ContainingNamespace.ToDisplayString()
|
||||||
|
};
|
||||||
|
if (IsDerivedFrom(sClassSymbol, type))
|
||||||
|
{
|
||||||
|
yield return res;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (INamedTypeSymbol interfaceSymbol in sClassSymbol.AllInterfaces)
|
||||||
|
{
|
||||||
|
if (SymbolEqualityComparer.Default.Equals(interfaceSymbol, type))
|
||||||
|
{
|
||||||
|
yield return res;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/ClassInfo.cs
Normal file
15
src/ClassInfo.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
|
namespace Polonium.Generators;
|
||||||
|
|
||||||
|
public class ClassInfo
|
||||||
|
{
|
||||||
|
public INamedTypeSymbol Symbol { get; set; }
|
||||||
|
public ClassDeclarationSyntax DeclarationSyntax { get; set; }
|
||||||
|
public string ClassName { get; set; }
|
||||||
|
public string ClassFullName { get; set; }
|
||||||
|
public string Namespace { get; set; }
|
||||||
|
public string Path { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
@@ -6,13 +6,14 @@ namespace Polonium.Generators;
|
|||||||
|
|
||||||
public class ClassSyntaxReceiver : ISyntaxReceiver
|
public class ClassSyntaxReceiver : ISyntaxReceiver
|
||||||
{
|
{
|
||||||
public List<ClassDeclarationSyntax> Classes { get; set; } = new ();
|
public List<ClassDeclarationSyntax> Classes { get; } = new ();
|
||||||
|
public List<InterfaceDeclarationSyntax> Interfaces { get; } = new ();
|
||||||
|
|
||||||
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
||||||
{
|
{
|
||||||
if (syntaxNode is ClassDeclarationSyntax classDeclaration)
|
if (syntaxNode is ClassDeclarationSyntax classDeclaration)
|
||||||
{
|
|
||||||
Classes.Add(classDeclaration);
|
Classes.Add(classDeclaration);
|
||||||
}
|
if(syntaxNode is InterfaceDeclarationSyntax interfaceDeclaration)
|
||||||
|
Interfaces.Add(interfaceDeclaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
42
src/Generators/AbstractSkinItemTemplateGenerator.cs
Normal file
42
src/Generators/AbstractSkinItemTemplateGenerator.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
|
|
||||||
|
namespace Polonium.Generators.Generators;
|
||||||
|
|
||||||
|
public class AbstractSkinItemTemplateGenerator : AssetProcessGenerator
|
||||||
|
{
|
||||||
|
public override void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
if (context.SyntaxReceiver is not ClassSyntaxReceiver receiver)
|
||||||
|
return;
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
INamedTypeSymbol? skinItem = compilation.GetTypeByMetadataName("Polonium.ItemManagers.SkinItem");
|
||||||
|
foreach (ClassInfo c in GetClassesOfType(context, skinItem))
|
||||||
|
{
|
||||||
|
if (!c.DeclarationSyntax.Modifiers.Any(m => m.IsKind(SyntaxKind.AbstractKeyword)))
|
||||||
|
continue;
|
||||||
|
StringBuilder sb = new();
|
||||||
|
sb
|
||||||
|
.AppendLine("using System;")
|
||||||
|
.AppendLine("using Skin=Polonium.SkinManagers.Skin;")
|
||||||
|
.AppendLine($"namespace {c.Namespace}")
|
||||||
|
.AppendLine($"public abstract partial class {c.ClassName}")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine($" public new abstract partial class Generic<T{c.ClassName}, TSkin>")
|
||||||
|
.AppendLine($" where T{c.ClassName} : Generic<T{c.ClassName}, TSkin>")
|
||||||
|
.AppendLine($" where TSkin : Skin")
|
||||||
|
.AppendLine(" {")
|
||||||
|
.AppendLine($" public new abstract class Template : {c.ClassName}.Template")
|
||||||
|
.AppendLine(" {")
|
||||||
|
.AppendLine($" public override T{c.ClassName} Get => GenericGet<T{c.ClassName}, TSkin>();")
|
||||||
|
.AppendLine($" public override void Return(T{c.ClassName} item) => GenericReturn<T{c.ClassName}, TSkin>(item);")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine("}");
|
||||||
|
context.AddSource($"{c.ClassName}_AbstractSkinItemTemplate.g.cs", sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
src/Generators/ActionNameRegisterGenerator.cs
Normal file
32
src/Generators/ActionNameRegisterGenerator.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Polonium.Generators.Generators;
|
||||||
|
[Generator]
|
||||||
|
public class ActionNameRegisterGenerator : AssetProcessGenerator
|
||||||
|
{
|
||||||
|
public override void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
if (!(context.SyntaxReceiver is ClassSyntaxReceiver receiver))
|
||||||
|
return;
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
INamedTypeSymbol? actionSyntax = compilation.GetTypeByMetadataName("Polonium.Agents.AgentAction");
|
||||||
|
StringBuilder sb = new();
|
||||||
|
sb
|
||||||
|
.AppendLine("using System;")
|
||||||
|
.AppendLine("using Polonium;")
|
||||||
|
.AppendLine("using Polonium.Attributes;")
|
||||||
|
.AppendLine("[AutoRegister]")
|
||||||
|
.AppendLine("public static class ActionNameRegister")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine(" public static void Register()")
|
||||||
|
.AppendLine(" {");
|
||||||
|
foreach (AssetInfo a in GetAssetsOfType(context, actionSyntax))
|
||||||
|
sb.AppendLine($" PoloniumRegistry.Action<{a.ClassName}>.Name = \"{a.ClassName}\";");
|
||||||
|
sb
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine("}");
|
||||||
|
context.AddSource("ActionNameRegister.g.cs", sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,6 +18,7 @@ public class AssetRegisterGenerator : AssetProcessGenerator
|
|||||||
sb
|
sb
|
||||||
.AppendLine("using System;")
|
.AppendLine("using System;")
|
||||||
.AppendLine("using Godot;")
|
.AppendLine("using Godot;")
|
||||||
|
.AppendLine("using Polonium;")
|
||||||
.AppendLine("using Polonium.Attributes;")
|
.AppendLine("using Polonium.Attributes;")
|
||||||
.AppendLine("[AutoRegister]")
|
.AppendLine("[AutoRegister]")
|
||||||
.AppendLine("public static class AssetRegister")
|
.AppendLine("public static class AssetRegister")
|
||||||
@@ -40,7 +41,7 @@ public class AssetRegisterGenerator : AssetProcessGenerator
|
|||||||
string className = Path.GetFileNameWithoutExtension(filePath);
|
string className = Path.GetFileNameWithoutExtension(filePath);
|
||||||
sb
|
sb
|
||||||
.AppendLine(
|
.AppendLine(
|
||||||
$" GlobalRegistry.Asset<{className}>.Scene = ResourceLoader.Load<PackedScene>(\"{gdPath}\");"
|
$" PoloniumRegistry.Asset<{className}>.Scene = ResourceLoader.Load<PackedScene>(\"{gdPath}\");"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
131
src/Generators/FramePatchGenerator.cs
Normal file
131
src/Generators/FramePatchGenerator.cs
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
|
namespace Polonium.Generators.Generators;
|
||||||
|
[Generator]
|
||||||
|
public class FramePatchGenerator : AssetProcessGenerator
|
||||||
|
{
|
||||||
|
public override void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
if(context.SyntaxReceiver is not ClassSyntaxReceiver receiver)
|
||||||
|
return;
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
INamedTypeSymbol? autoPatch = compilation.GetTypeByMetadataName("Polonium.Attributes.AutoPatch");
|
||||||
|
INamedTypeSymbol? patchableProperty = compilation.GetTypeByMetadataName("Polonium.Attributes.PatchableProperty");
|
||||||
|
foreach (InterfaceInfo inf in GetInterfacesWithAttribute(context, autoPatch))
|
||||||
|
{
|
||||||
|
|
||||||
|
PropertyDeclarationSyntax? underlying = inf.DeclarationSyntax.Members
|
||||||
|
.OfType<PropertyDeclarationSyntax>()
|
||||||
|
.FirstOrDefault(m => m.AttributeLists
|
||||||
|
.SelectMany(a => a.Attributes)
|
||||||
|
.Any(a =>
|
||||||
|
{
|
||||||
|
SemanticModel model = compilation.GetSemanticModel(a.SyntaxTree);
|
||||||
|
INamedTypeSymbol? attributeSymbol = model.GetSymbolInfo(a).Symbol?.ContainingType;
|
||||||
|
return SymbolEqualityComparer.Default.Equals(attributeSymbol, patchableProperty);
|
||||||
|
}));
|
||||||
|
if (underlying is null)
|
||||||
|
continue;
|
||||||
|
SemanticModel model = compilation.GetSemanticModel(underlying.SyntaxTree);
|
||||||
|
ITypeSymbol? underlyingType = model.GetTypeInfo(underlying.Type).Type;
|
||||||
|
ITypeSymbol? hashSet = compilation
|
||||||
|
.GetTypeByMetadataName("Polonium.DataStructures.PatchableItems.PatchableHashSet`1");
|
||||||
|
ITypeSymbol? dictionary = compilation
|
||||||
|
.GetTypeByMetadataName("Polonium.DataStructures.PatchableItems.PatchableDictionary`2");
|
||||||
|
string typeString = "";
|
||||||
|
StringBuilder sb = new();
|
||||||
|
sb
|
||||||
|
.AppendLine("using System;")
|
||||||
|
.AppendLine("using System.Collections.Generic;")
|
||||||
|
.AppendLine("using System.Linq;")
|
||||||
|
.AppendLine("using Polonium.Interfaces;")
|
||||||
|
.AppendLine("using Polonium.DataStructures.PatchableItems;")
|
||||||
|
.AppendLine("using Polonium.Resources.FramePatches;")
|
||||||
|
.AppendLine("using Polonium.Resources.FramePatches.Generic;")
|
||||||
|
.AppendLine($"namespace {inf.Namespace};");
|
||||||
|
|
||||||
|
string lName = inf.InterfaceName[0] == 'I' ? inf.InterfaceName.Substring(1) : inf.InterfaceName;
|
||||||
|
if (SymbolEqualityComparer.Default.Equals(underlyingType?.OriginalDefinition, hashSet))
|
||||||
|
{
|
||||||
|
ITypeSymbol? x1 = (underlyingType as INamedTypeSymbol)?.TypeArguments[0];
|
||||||
|
sb
|
||||||
|
.AppendLine($"public partial class {lName}Patch : HashSetFramePatch<{x1?.ToDisplayString()}>")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine($" public override void Patch(IPatchableFrame frame)")
|
||||||
|
.AppendLine(" {")
|
||||||
|
.AppendLine($" if(frame is not {inf.InterfaceFillName} sFrame)")
|
||||||
|
.AppendLine(" return;")
|
||||||
|
.AppendLine($" switch (sFrame.{underlying.Identifier.ToString()}.UpdateMethod )")
|
||||||
|
.AppendLine(" {")
|
||||||
|
.AppendLine(" case UpdateMethods.None:")
|
||||||
|
.AppendLine(" return;")
|
||||||
|
.AppendLine(" case UpdateMethods.Update:")
|
||||||
|
.AppendLine($" foreach({x1?.ToDisplayString()} x in Updates)")
|
||||||
|
.AppendLine($" sFrame.{underlying.Identifier.ToString()}.Add(x);")
|
||||||
|
.AppendLine(" return;")
|
||||||
|
.AppendLine(" case UpdateMethods.Replace:")
|
||||||
|
.AppendLine($" sFrame.{underlying.Identifier.ToString()}.Data = Updates;")
|
||||||
|
.AppendLine(" return;")
|
||||||
|
.AppendLine(" case UpdateMethods.Custom:")
|
||||||
|
.AppendLine($" sFrame.{underlying.Identifier.ToString()}.CustomUpdate(Updates);")
|
||||||
|
.AppendLine(" return;")
|
||||||
|
.AppendLine(" default:")
|
||||||
|
.AppendLine(" return;")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine("}");
|
||||||
|
}
|
||||||
|
else if (SymbolEqualityComparer.Default.Equals(underlyingType?.OriginalDefinition, dictionary))
|
||||||
|
{
|
||||||
|
ITypeSymbol? x1 = (underlyingType as INamedTypeSymbol)?.TypeArguments[0];
|
||||||
|
ITypeSymbol? x2 = (underlyingType as INamedTypeSymbol)?.TypeArguments[1];
|
||||||
|
sb
|
||||||
|
.AppendLine($"public partial class {lName}Patch : DictionaryFramePatch<{x1?.ToDisplayString()}, {x2?.ToDisplayString()}>")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine(" public override void Patch(IPatchableFrame frame)")
|
||||||
|
.AppendLine(" {")
|
||||||
|
.AppendLine($" if(frame is not {inf.InterfaceFillName} sFrame)")
|
||||||
|
.AppendLine(" return;")
|
||||||
|
.AppendLine($" switch (sFrame.{underlying.Identifier.ToString()}.UpdateMethod )")
|
||||||
|
.AppendLine(" {")
|
||||||
|
.AppendLine(" case UpdateMethods.None:")
|
||||||
|
.AppendLine(" return;")
|
||||||
|
.AppendLine(" case UpdateMethods.Update:")
|
||||||
|
.AppendLine($" foreach({x1?.ToDisplayString()} x in Updates.Keys)")
|
||||||
|
.AppendLine($" sFrame.{underlying.Identifier.ToString()}[x] = Updates[x];")
|
||||||
|
.AppendLine(" return;")
|
||||||
|
.AppendLine(" case UpdateMethods.Replace:")
|
||||||
|
.AppendLine($" sFrame.{underlying.Identifier.ToString()}.Data = Updates;")
|
||||||
|
.AppendLine(" return;")
|
||||||
|
.AppendLine(" case UpdateMethods.Custom:")
|
||||||
|
.AppendLine($" sFrame.{underlying.Identifier.ToString()}.CustomUpdate(Updates);")
|
||||||
|
.AppendLine(" return;")
|
||||||
|
.AppendLine(" default:")
|
||||||
|
.AppendLine(" return;")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sb
|
||||||
|
|
||||||
|
.AppendLine($"public partial class {lName}Patch : FramePatch<{underlyingType?.ToDisplayString()}>")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine(" public override void Patch(IPatchableFrame frame)")
|
||||||
|
.AppendLine(" {")
|
||||||
|
.AppendLine($" if(frame is not {inf.InterfaceFillName} sFrame)")
|
||||||
|
.AppendLine(" return;")
|
||||||
|
.AppendLine($" sFrame.{underlying.Identifier.ToString()} = Updates;")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine("}");
|
||||||
|
}
|
||||||
|
context.AddSource($"{lName}Patch.g.cs", sb.ToString());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
using System.Text;
|
|
||||||
using Microsoft.CodeAnalysis;
|
|
||||||
|
|
||||||
namespace Polonium.Generators.Generators;
|
|
||||||
[Generator]
|
|
||||||
public class GlobalRegistryGenerator : ISourceGenerator
|
|
||||||
{
|
|
||||||
public void Initialize(GeneratorInitializationContext context)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Execute(GeneratorExecutionContext context)
|
|
||||||
{
|
|
||||||
StringBuilder sb = new();
|
|
||||||
sb
|
|
||||||
.AppendLine("using Godot;")
|
|
||||||
.AppendLine("using System;")
|
|
||||||
.AppendLine("using System.Collections.Generic;")
|
|
||||||
.AppendLine("using System.Linq;")
|
|
||||||
.AppendLine("using System.Reflection;")
|
|
||||||
.AppendLine("using Polonium.Attributes;")
|
|
||||||
.AppendLine("using Polonium;")
|
|
||||||
.AppendLine("using Polonium.Interfaces;")
|
|
||||||
.AppendLine("public static partial class GlobalRegistry")
|
|
||||||
.AppendLine("{")
|
|
||||||
.AppendLine(" public static void Start()")
|
|
||||||
.AppendLine(" {")
|
|
||||||
.AppendLine(" PoloniumRegistry.Prepare();")
|
|
||||||
.AppendLine(" Assembly assembly = Assembly.GetExecutingAssembly();")
|
|
||||||
.AppendLine(" IEnumerable<Type> registerTypes = Utils.GetLoadableTypes(assembly);")
|
|
||||||
.AppendLine(" registerTypes = registerTypes.Where(t => t.IsClass && t.GetCustomAttributes(typeof(AutoRegister), false).Any());")
|
|
||||||
.AppendLine(" foreach(Type t in registerTypes)")
|
|
||||||
.AppendLine(" {")
|
|
||||||
.AppendLine(" MethodInfo registerMethod = t.GetMethod(\"Register\", BindingFlags.Static | BindingFlags.Public);")
|
|
||||||
.AppendLine(" if (registerMethod != null)")
|
|
||||||
.AppendLine(" registerMethod.Invoke(null, null);")
|
|
||||||
.AppendLine(" }")
|
|
||||||
.AppendLine(" }")
|
|
||||||
.AppendLine(" public static class Asset<T> where T : Node")
|
|
||||||
.AppendLine(" {")
|
|
||||||
.AppendLine(" private static readonly Queue<T> Pool = new();")
|
|
||||||
.AppendLine(" public static PackedScene Scene { get; set; }")
|
|
||||||
.AppendLine(" public static T Instance => Scene.Instantiate<T>();")
|
|
||||||
.AppendLine(" public static T Get() => Pool.Count > 0 ? Pool.Dequeue() : Instance;")
|
|
||||||
.AppendLine(" public static void Return(T obj)")
|
|
||||||
.AppendLine(" {")
|
|
||||||
.AppendLine(" if(Pool.Count < 10)")
|
|
||||||
.AppendLine(" Pool.Enqueue(obj);")
|
|
||||||
.AppendLine(" else")
|
|
||||||
.AppendLine(" obj.QueueFree();")
|
|
||||||
.AppendLine(" }")
|
|
||||||
.AppendLine(" }")
|
|
||||||
.AppendLine(" public static PoloniumRegistry PoloniumRegistry => PoloniumRegistry.Instance;")
|
|
||||||
.AppendLine(" public static bool Paused { get; set; }")
|
|
||||||
.AppendLine(" public static HashSet<ITimeConsumer> TimeConsumers { get; } = new ();")
|
|
||||||
.AppendLine("}");
|
|
||||||
context.AddSource("GlobalRegistry.g.cs", sb.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
58
src/Generators/PoloniumFactoryGenerator.cs
Normal file
58
src/Generators/PoloniumFactoryGenerator.cs
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
|
namespace Polonium.Generators.Generators;
|
||||||
|
[Generator]
|
||||||
|
public class PoloniumFactoryGenerator : AssetProcessGenerator
|
||||||
|
{
|
||||||
|
public override void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
if (!(context.SyntaxReceiver is ClassSyntaxReceiver receiver))
|
||||||
|
return;
|
||||||
|
StringBuilder sb = new();
|
||||||
|
sb
|
||||||
|
.AppendLine("using System;")
|
||||||
|
.AppendLine("using Polonium.Attributes;")
|
||||||
|
.AppendLine("using Polonium.Interfaces;")
|
||||||
|
.AppendLine("using Polonium.Resources;")
|
||||||
|
.AppendLine("using Polonium.MessageManager;")
|
||||||
|
.AppendLine("[AutoRegister]")
|
||||||
|
.AppendLine("public class PoloniumFactoryRegister")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine(" public static void Register()")
|
||||||
|
.AppendLine(" {")
|
||||||
|
.AppendLine(" GlobalRegistry.PoloniumFactory = new PoloniumFactory();")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine(" public class PoloniumFactory : IPoloniumFactory")
|
||||||
|
.AppendLine(" {")
|
||||||
|
.AppendLine(" public MessageHeader CreateMessageHeader()")
|
||||||
|
.AppendLine(" {");
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
INamedTypeSymbol? signalHeader = compilation.GetTypeByMetadataName("Polonium.MessageManager.MessageHeader");
|
||||||
|
|
||||||
|
bool founded = false;
|
||||||
|
foreach (ClassDeclarationSyntax cls in receiver.Classes)
|
||||||
|
{
|
||||||
|
SemanticModel semanticModel = compilation.GetSemanticModel(cls.SyntaxTree);
|
||||||
|
INamedTypeSymbol? nCls = semanticModel.GetDeclaredSymbol(cls) as INamedTypeSymbol;
|
||||||
|
if(nCls is null)
|
||||||
|
continue;
|
||||||
|
if (IsDerivedFrom(nCls, signalHeader) && !nCls.IsAbstract)
|
||||||
|
{
|
||||||
|
sb.AppendLine($" return new {nCls.ToDisplayString()}();");
|
||||||
|
founded = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!founded)
|
||||||
|
sb.AppendLine($" throw new NotImplementedException();");
|
||||||
|
|
||||||
|
sb
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine(" }")
|
||||||
|
.AppendLine("}");
|
||||||
|
|
||||||
|
context.AddSource("PoloniumFactoryRegistry.g.cs", sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using Microsoft.CodeAnalysis;
|
|
||||||
|
|
||||||
namespace Polonium.Generators.Generators;
|
|
||||||
[Generator]
|
|
||||||
public class ProxyNodeGenerator : AssetProcessGenerator
|
|
||||||
{
|
|
||||||
private INamedTypeSymbol? NodeProxy { get; set; }
|
|
||||||
|
|
||||||
private IEnumerable<INamedTypeSymbol> ProxyNodesInNamespace(INamespaceSymbol ns)
|
|
||||||
{
|
|
||||||
foreach (INamespaceOrTypeSymbol member in ns.GetMembers())
|
|
||||||
{
|
|
||||||
if (member is INamespaceSymbol nsx)
|
|
||||||
foreach (INamedTypeSymbol nsz in ProxyNodesInNamespace(nsx))
|
|
||||||
yield return nsz;
|
|
||||||
else if (member is INamedTypeSymbol nsu)
|
|
||||||
if (nsu.GetAttributes().Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, NodeProxy)))
|
|
||||||
yield return nsu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public override void Execute(GeneratorExecutionContext context)
|
|
||||||
{
|
|
||||||
Compilation compilation = context.Compilation;
|
|
||||||
NodeProxy = compilation.GetTypeByMetadataName("Polonium.Attributes.ProxyNode");
|
|
||||||
foreach (INamedTypeSymbol node in ProxyNodesInNamespace(compilation.GlobalNamespace))
|
|
||||||
{
|
|
||||||
StringBuilder sb = new();
|
|
||||||
sb
|
|
||||||
.AppendLine($"namespace Polonium.Nodes;")
|
|
||||||
.AppendLine("using Godot;")
|
|
||||||
.AppendLine($"[GlobalClass]")
|
|
||||||
.AppendLine($"[Tool]")
|
|
||||||
.AppendLine($"public partial class {node.Name} : {node.ToDisplayString()}")
|
|
||||||
.AppendLine("{")
|
|
||||||
.AppendLine("}");
|
|
||||||
context.AddSource($"NodeProxy_{node.Name}.g.cs", sb.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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 (
|
||||||
|
|||||||
31
src/Generators/SendMessageMethodGenerator.cs
Normal file
31
src/Generators/SendMessageMethodGenerator.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using System.Text;
|
||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Polonium.Generators.Generators;
|
||||||
|
[Generator]
|
||||||
|
public class SendMessageMethodGenerator : AssetProcessGenerator
|
||||||
|
{
|
||||||
|
public override void Execute(GeneratorExecutionContext context)
|
||||||
|
{
|
||||||
|
if (context.SyntaxReceiver is not ClassSyntaxReceiver receiver)
|
||||||
|
return;
|
||||||
|
Compilation compilation = context.Compilation;
|
||||||
|
INamedTypeSymbol? ifc = compilation.GetTypeByMetadataName("Polonium.Interfaces.IMessageClient");
|
||||||
|
foreach (ClassInfo cls in GetClassesWithInterface(context, ifc))
|
||||||
|
{
|
||||||
|
StringBuilder sb = new();
|
||||||
|
sb
|
||||||
|
.AppendLine("using Polonium.Interfaces;")
|
||||||
|
.AppendLine("using System;")
|
||||||
|
.AppendLine("using Polonium.Resources;")
|
||||||
|
.AppendLine("using Polonium.MessageManager;")
|
||||||
|
.AppendLine($"namespace {cls.Namespace};")
|
||||||
|
.AppendLine($"public partial class {cls.ClassName}")
|
||||||
|
.AppendLine("{")
|
||||||
|
.AppendLine(" public event IMessageClient.MessageSentEventHandler MessageSent;")
|
||||||
|
.AppendLine(" public void SendMessage(PoloniumMessage msg) => MessageSent?.Invoke(msg); ")
|
||||||
|
.AppendLine("}");
|
||||||
|
context.AddSource($"{cls.ClassName}_MessageClient.g.cs", sb.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
67
src/Generators/TemplateBlockGenerator.cs
Normal file
67
src/Generators/TemplateBlockGenerator.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/InterfaceInfo.cs
Normal file
14
src/InterfaceInfo.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Microsoft.CodeAnalysis;
|
||||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
|
||||||
|
namespace Polonium.Generators;
|
||||||
|
|
||||||
|
public class InterfaceInfo
|
||||||
|
{
|
||||||
|
public INamedTypeSymbol Symbol { get; set; }
|
||||||
|
public InterfaceDeclarationSyntax DeclarationSyntax { get; set; }
|
||||||
|
public string InterfaceName { get; set; }
|
||||||
|
public string InterfaceFillName { get; set; }
|
||||||
|
public string Namespace { get; set; }
|
||||||
|
public string Path { get; set; }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user