Files
NebulaLauncher/Nebula.SourceGenerators/DependencyAutoGenerator.cs

83 lines
3.2 KiB
C#
Raw Normal View History

2025-01-14 22:10:16 +03:00
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
namespace Nebula.SourceGenerators;
[Generator]
public class DependencyAutoGenerator : IIncrementalGenerator
{
2025-01-15 19:47:27 +03:00
private static readonly string ConstructGeneratorAttributeName = "Nebula.Shared.Attributes.ConstructGeneratorAttribute";
private static readonly string GeneratePropertyAttributeName = "Nebula.Shared.Attributes.GeneratePropertyAttribute";
2025-01-14 22:10:16 +03:00
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var provider = context.SyntaxProvider
.CreateSyntaxProvider(
(s, _) => s is ClassDeclarationSyntax,
2025-01-15 19:47:27 +03:00
(ctx, _) => SourceHelper.GetClassDeclarationForSourceGen(ctx,ConstructGeneratorAttributeName))
2025-01-14 22:10:16 +03:00
.Where(t => t.reportAttributeFound)
.Select((t, _) => t.Item1);
context.RegisterSourceOutput(context.CompilationProvider.Combine(provider.Collect()),
(ctx, t) => GenerateCode(ctx, t.Left, t.Right));
}
private void GenerateCode(SourceProductionContext context, Compilation compilation,
ImmutableArray<ClassDeclarationSyntax> classDeclarations)
{
foreach (var classDeclarationSyntax in classDeclarations)
{
var semanticModel = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree);
if (semanticModel.GetDeclaredSymbol(classDeclarationSyntax) is not INamedTypeSymbol classSymbol)
continue;
var namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
var className = classDeclarationSyntax.Identifier.Text;
var propertiesGenerated = GetProperties(classSymbol).ToList();
var constr = propertiesGenerated.Select(a => $"{a.Type.ToDisplayString()} g{a.Name}");
var body = propertiesGenerated.Select(a => $"this.{a.Name} = g{a.Name};");
2025-01-22 21:06:05 +03:00
var propertiesGeneratedC = GetProperties(classSymbol)
.Where(a=>
SourceHelper.HasAttribute(a,"Nebula.Shared.Attributes.DesignConstructAttribute"))
.ToList();
var bodyC = propertiesGeneratedC.Select(a => $"this.{a.Name} = new {a.Type.ToDisplayString()}();");
2025-01-14 22:10:16 +03:00
var code = $@"// <auto-generated/>
namespace {namespaceName};
partial class {className}
{{
2025-01-22 21:06:05 +03:00
public {className}(){{
{string.Join("\n\t\t", bodyC)}
InitialiseInDesignMode();
}}
2025-01-14 22:10:16 +03:00
public {className}(
{string.Join(",\n\t\t", constr)}
) : base(){{
{string.Join("\n\t\t", body)}
2025-01-16 21:07:50 +03:00
Initialise();
2025-01-14 22:10:16 +03:00
}}
}}
";
// Add the source code to the compilation.
context.AddSource($"{className}.g.cs", SourceText.From(code, Encoding.UTF8));
}
}
private static IEnumerable<IPropertySymbol> GetProperties(INamedTypeSymbol classSymbol)
{
return classSymbol.GetMembers().OfType<IPropertySymbol>().Where(a =>
2025-01-15 19:47:27 +03:00
SourceHelper.HasAttribute(a, GeneratePropertyAttributeName));
2025-01-14 22:10:16 +03:00
}
}