74 lines
2.7 KiB
C#
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();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|