Files
Polonium.Tasks/src/GenerateProxyNodesTask.cs

103 lines
3.8 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace Polonium.Tasks;
public class GenerateProxyNodesTask : Task
{
[Required]
public string SourceDirectory { get; set; }
[Required]
public string OutputDirectory { get; set; }
[Required]
public string TemplateDirectory { get; set; }
[Required]
public string AttributeName { get; set; }
public override bool Execute()
{
try
{
if(Directory.Exists(OutputDirectory))
Directory.Delete(OutputDirectory, true);
Directory.CreateDirectory(OutputDirectory);
string[] csFiles = Directory.GetFiles(SourceDirectory, "*.cs", SearchOption.AllDirectories);
foreach (string csFile in csFiles)
{
string code = File.ReadAllText(csFile);
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
CompilationUnitSyntax root = syntaxTree.GetCompilationUnitRoot();
IEnumerable<ClassDeclarationSyntax> classes = root.DescendantNodes().OfType<ClassDeclarationSyntax>()
.Where(cls => cls.AttributeLists
.SelectMany(attrList => attrList.Attributes)
.Any(attr => attr.Name.ToString().Contains(AttributeName)));
foreach (ClassDeclarationSyntax cls in classes)
{
string className = cls.Identifier.Text;
StringBuilder sb = new StringBuilder();
sb
.AppendLine("using Godot;")
.AppendLine("namespace GlobalClasses;")
.AppendLine("[GlobalClass]")
.AppendLine("[Tool]")
.AppendLine($"public partial class {className} : {GetDisplayName(cls)}")
.AppendLine("{")
.AppendLine("}");
string outputFile = Path.Combine(OutputDirectory, $"{className}.cs");
File.WriteAllText(outputFile, sb.ToString());
Log.LogMessage(MessageImportance.High, $"Generated proxy file: {outputFile}");
StringBuilder sbx = new StringBuilder();
sbx
.AppendLine("// meta-default: true")
.AppendLine("using _BINDINGS_NAMESPACE_;")
.AppendLine("using System;")
.AppendLine("public partial class _CLASS_ : GlobalClasses._CLASS_")
.AppendLine("{")
.AppendLine("}");
if(!Directory.Exists($"{TemplateDirectory}/{className}"))
Directory.CreateDirectory($"{TemplateDirectory}/{className}");
string templateFile = $"{TemplateDirectory}/{className}/Polonium_{className}.cs";
File.WriteAllText(templateFile, sbx.ToString());
}
}
return true;
}
catch (Exception ex)
{
Log.LogErrorFromException(ex);
return false;
}
}
private string GetDisplayName(ClassDeclarationSyntax cls)
{
string name = cls.Identifier.Text;
SyntaxNode node = cls.Parent;
while (node is not null)
{
if(node is NamespaceDeclarationSyntax ns)
name = ns.Name.ToString() + "." + name;
else if (node is FileScopedNamespaceDeclarationSyntax fs)
name = fs.Name.ToString() + "." + name;
node = node.Parent;
}
return name;
}
}