Innovenergy_trunk/csharp/Lib/SrcGen/GenerateAttributes.cs

74 lines
2.7 KiB
C#

using InnovEnergy.Lib.Utils;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace InnovEnergy.Lib.SrcGen;
public static class GenerateAttributes
{
public static async Task Generate(Project project, Compilation compilation)
{
var syntaxTrees = await project
.Documents
.Where(d => d.Project == project)
.Where(d => d.SupportsSyntaxTree)
.Select(async d => await d.GetSyntaxRootAsync())
.WhenAll();
syntaxTrees.NotNull()
.SelectMany(c => c.GetGenerateAttributes())
.ForEach(GenerateFile);
String GenerateFile(AttributeSyntax attribute)
{
var derivedType = attribute.GetAncestor<StructDeclarationSyntax>();
var defineArgs = attribute.ArgumentList?.Arguments ?? Enumerable.Empty<SyntaxNode>();
var filePath = derivedType.SyntaxTree.FilePath;
var derivedName = derivedType.Identifier.ValueText;
var baseRef = attribute.GetGenericArgument();
var baseType = compilation.GetDefinition<StructDeclarationSyntax>(baseRef);
var baseName = baseType.Identifier.ValueText;
var baseFile = baseType.GetAncestor<CompilationUnitSyntax>();
var generatedPath = filePath.GetGeneratedPath(baseName);
var defines = defineArgs
.Select(n => n.ToString())
.Select(s => s.Replace("\"", "").ToUpper())
.Select(s => $"#define {s}");
Console.WriteLine($"Generating {generatedPath}");
var code = GenerateCode();
var fileContents = Utils.AutoGeneratedMessage(nameof(GenerateAttributes))
+ defines.JoinLines() + "\n"
+ code;
File.WriteAllText(generatedPath, fileContents);
return generatedPath;
String GenerateCode()
{
try
{
return baseFile
.AddPartialModifier()
.ReplaceIdentifiers(baseName, derivedName)
.RemoveNotImplemented()
.GetText()
.ToString();
}
catch (Exception e)
{
return $"Failed to generate source for {filePath}\n\n{e}"
.SplitLines()
.Select(l => $"// {l}")
.JoinLines();
}
}
}
}
}