Files
NebulaLauncher/Nebula.SourceGenerators/ViewConstructGenerator.cs

89 lines
3.0 KiB
C#
Raw Normal View History

2025-07-02 21:32:51 +03:00
using System;
2025-01-15 19:47:27 +03:00
using System.Collections.Immutable;
2025-07-02 21:32:51 +03:00
using System.Linq;
2025-01-15 19:47:27 +03:00
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
namespace Nebula.SourceGenerators;
2025-07-02 21:32:51 +03:00
[Generator]
public class ViewConstructorGenerator : IIncrementalGenerator
2025-01-15 19:47:27 +03:00
{
2025-07-02 21:32:51 +03:00
private static readonly string ViewModelAttribute = "Nebula.Shared.ViewHelper.ViewModelRegisterAttribute";
2025-01-15 19:47:27 +03:00
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var provider = context.SyntaxProvider
.CreateSyntaxProvider(
2025-07-02 21:32:51 +03:00
(s, _) => s is ClassDeclarationSyntax,
(ctx, _) => SourceHelper.GetClassDeclarationForSourceGen(ctx,ViewModelAttribute))
2025-01-15 19:47:27 +03:00
.Where(t => t.reportAttributeFound)
2025-07-02 21:32:51 +03:00
.Select((t, _) => t.Item1);
context.RegisterSourceOutput(context.CompilationProvider.Combine(provider.Collect()),
(ctx, t) => GenerateCode(ctx, t.Left, t.Right));
2025-01-15 19:47:27 +03:00
}
2025-07-02 21:32:51 +03:00
private void GenerateCode(SourceProductionContext context, Compilation compilation,
ImmutableArray<ClassDeclarationSyntax> classDeclarations)
2025-01-15 19:47:27 +03:00
{
2025-07-02 21:32:51 +03:00
foreach (var classDeclarationSyntax in classDeclarations)
2025-01-15 19:47:27 +03:00
{
var semanticModel = compilation.GetSemanticModel(classDeclarationSyntax.SyntaxTree);
2025-07-02 21:32:51 +03:00
if (semanticModel.GetDeclaredSymbol(classDeclarationSyntax) is not INamedTypeSymbol classSymbol)
2025-01-15 19:47:27 +03:00
continue;
2025-07-02 21:32:51 +03:00
var viewModelName = classSymbol.Name;
var viewModelNamespace = classSymbol.ContainingNamespace.ToDisplayString();
2025-01-15 19:47:27 +03:00
2025-07-02 21:32:51 +03:00
var viewModelRegisterAttr = classSymbol.GetAttributes()
.FirstOrDefault(attr => attr.AttributeClass?.ToDisplayString() == ViewModelAttribute);
2025-01-15 19:47:27 +03:00
2025-07-02 21:32:51 +03:00
var viewTypeArg = viewModelRegisterAttr?.ConstructorArguments.FirstOrDefault();
if (viewTypeArg?.Value is not INamedTypeSymbol viewTypeSymbol)
continue;
2025-01-15 19:47:27 +03:00
2025-07-02 21:32:51 +03:00
try
{
var viewName = viewTypeSymbol.Name;
var viewNamespace = viewTypeSymbol.ContainingNamespace.ToDisplayString();
var code = $@"
namespace {viewNamespace}
2025-01-15 19:47:27 +03:00
{{
2025-07-02 21:32:51 +03:00
public partial class {viewName}
{{
public {viewName}({viewModelNamespace}.{viewModelName} viewModel)
: this()
{{
DataContext = viewModel;
}}
}}
}}";
// Add the source code to the compilation.
context.AddSource($"{viewName}_viewConstructAuto.g.cs", SourceText.From(code, Encoding.UTF8));
}
catch (Exception e)
{
var coder1 = $@"
// <auto-generated/>
// Error!
namespace {viewModelNamespace}
{{
public partial class {viewModelName}
{{
// {e.Message}
2025-01-15 19:47:27 +03:00
}}
2025-07-02 21:32:51 +03:00
}}";
2025-01-15 19:47:27 +03:00
2025-07-02 21:32:51 +03:00
// Add the source code to the compilation.
context.AddSource($"{viewModelName}_viewError.g.cs", SourceText.From(coder1, Encoding.UTF8));
}
2025-01-15 19:47:27 +03:00
}
}
2025-07-02 21:32:51 +03:00
2025-01-15 19:47:27 +03:00
}