8 changed files with 361 additions and 172 deletions
@ -0,0 +1,94 @@ |
|||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using Generator; |
||||
|
using Microsoft.CodeAnalysis; |
||||
|
using Microsoft.CodeAnalysis.CSharp; |
||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax; |
||||
|
|
||||
|
namespace DevGenerators; |
||||
|
|
||||
|
[Generator(LanguageNames.CSharp)] |
||||
|
public class EnumMemberDictionaryGenerator : IIncrementalGenerator |
||||
|
{ |
||||
|
const string DictionaryAttributeFullName = "global::Avalonia.SourceGenerator.GenerateEnumValueDictionaryAttribute"; |
||||
|
const string ListAttributeFullName = "global::Avalonia.SourceGenerator.GenerateEnumValueListAttribute"; |
||||
|
|
||||
|
public void Initialize(IncrementalGeneratorInitializationContext context) |
||||
|
{ |
||||
|
var allMethodsWithAttributes = context.SyntaxProvider |
||||
|
.CreateSyntaxProvider( |
||||
|
static (s, _) => s is MethodDeclarationSyntax |
||||
|
{ |
||||
|
AttributeLists.Count: > 0, |
||||
|
} md && md.Modifiers.Any(m=>m.IsKind(SyntaxKind.PartialKeyword)), |
||||
|
static (context, _) => |
||||
|
(IMethodSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node)!); |
||||
|
|
||||
|
var all = allMethodsWithAttributes |
||||
|
.Where(s => |
||||
|
s.HasAttributeWithFullyQualifiedName(DictionaryAttributeFullName) |
||||
|
|| s.HasAttributeWithFullyQualifiedName(ListAttributeFullName) |
||||
|
).Collect(); |
||||
|
context.RegisterSourceOutput(all, static (context, methods) => |
||||
|
{ |
||||
|
foreach (var typeGroup in methods.GroupBy(f => f.ContainingType)) |
||||
|
{ |
||||
|
var classBuilder = new StringBuilder(); |
||||
|
if (typeGroup.Key.ContainingNamespace != null) |
||||
|
classBuilder |
||||
|
.AppendLine("using System;") |
||||
|
.Append("namespace ") |
||||
|
.Append(typeGroup.Key.ContainingNamespace) |
||||
|
.AppendLine(";"); |
||||
|
classBuilder |
||||
|
.Append("partial class ") |
||||
|
.AppendLine(typeGroup.Key.Name) |
||||
|
.AppendLine("{"); |
||||
|
|
||||
|
foreach (var method in typeGroup) |
||||
|
{ |
||||
|
var namedReturn = method.ReturnType as INamedTypeSymbol; |
||||
|
var arrayReturn = method.ReturnType as IArrayTypeSymbol; |
||||
|
|
||||
|
if ((namedReturn != null && namedReturn.Arity > 0) || arrayReturn != null) |
||||
|
{ |
||||
|
ITypeSymbol enumType = namedReturn != null |
||||
|
? namedReturn.TypeArguments.Last() |
||||
|
: arrayReturn!.ElementType; |
||||
|
|
||||
|
var isDic = method.HasAttributeWithFullyQualifiedName(DictionaryAttributeFullName); |
||||
|
|
||||
|
classBuilder |
||||
|
.Pad(1) |
||||
|
.Append("private static partial " + method.ReturnType + " " + method.Name + "()") |
||||
|
.AppendLine().Pad(4).Append(" => new ").Append(method.ReturnType).AppendLine("{"); |
||||
|
foreach (var member in enumType.GetMembers()) |
||||
|
{ |
||||
|
if (member.Name == ".ctor") |
||||
|
continue; |
||||
|
|
||||
|
if (isDic) |
||||
|
classBuilder.Pad(2) |
||||
|
.Append("{\"") |
||||
|
.Append(member.Name) |
||||
|
.Append("\", ") |
||||
|
.Append(member.ToString()) |
||||
|
.AppendLine("},"); |
||||
|
else |
||||
|
classBuilder.Pad(2).Append(member.ToString()).AppendLine(","); |
||||
|
} |
||||
|
|
||||
|
classBuilder.Pad(1).AppendLine("};"); |
||||
|
} |
||||
|
} |
||||
|
classBuilder.AppendLine("}"); |
||||
|
|
||||
|
context.AddSource(typeGroup.Key.GetFullyQualifiedName().Replace(":", ""), classBuilder.ToString()); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
using System.IO; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using Generator; |
||||
|
using Microsoft.CodeAnalysis; |
||||
|
using Microsoft.CodeAnalysis.CSharp; |
||||
|
using Microsoft.CodeAnalysis.CSharp.Syntax; |
||||
|
|
||||
|
namespace DevGenerators; |
||||
|
|
||||
|
[Generator(LanguageNames.CSharp)] |
||||
|
public class X11AtomsGenerator : IIncrementalGenerator |
||||
|
{ |
||||
|
public void Initialize(IncrementalGeneratorInitializationContext context) |
||||
|
{ |
||||
|
var x11AtomsClasses = context.SyntaxProvider |
||||
|
.CreateSyntaxProvider( |
||||
|
static (s, _) => s is ClassDeclarationSyntax |
||||
|
{ |
||||
|
Identifier.Text: "X11Atoms" |
||||
|
}, |
||||
|
static (context, _) => |
||||
|
(INamedTypeSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node)!); |
||||
|
|
||||
|
var all = x11AtomsClasses.Collect(); |
||||
|
context.RegisterSourceOutput(all, static (context, classes) => |
||||
|
{ |
||||
|
foreach (var cl in classes) |
||||
|
{ |
||||
|
var classBuilder = new StringBuilder(); |
||||
|
if (cl.ContainingNamespace != null) |
||||
|
classBuilder |
||||
|
.AppendLine("using System;") |
||||
|
.AppendLine("using static Avalonia.X11.XLib;") |
||||
|
.Append("namespace ") |
||||
|
.Append(cl.ContainingNamespace) |
||||
|
.AppendLine(";"); |
||||
|
classBuilder |
||||
|
.Append("partial class ") |
||||
|
.AppendLine(cl.Name) |
||||
|
.AppendLine("{"); |
||||
|
|
||||
|
var fields = cl.GetMembers().OfType<IFieldSymbol>() |
||||
|
.Where(f => f.Type.Name == "IntPtr" |
||||
|
&& f.DeclaredAccessibility == Accessibility.Public).ToList(); |
||||
|
|
||||
|
classBuilder.Pad(1).AppendLine("private void PopulateAtoms(IntPtr display)").Pad(1).AppendLine("{"); |
||||
|
classBuilder.Pad(2).Append("var atoms = new IntPtr[").Append(fields.Count).AppendLine("];"); |
||||
|
classBuilder.Pad(2).Append("var atomNames = new string[").Append(fields.Count).AppendLine("] {"); |
||||
|
|
||||
|
|
||||
|
for (int c = 0; c < fields.Count; c++) |
||||
|
classBuilder.Pad(3).Append("\"").Append(fields[c].Name).AppendLine("\","); |
||||
|
classBuilder.Pad(2).AppendLine("};"); |
||||
|
|
||||
|
classBuilder.Pad(2).AppendLine("XInternAtoms(display, atomNames, atomNames.Length, true, atoms);"); |
||||
|
|
||||
|
for (int c = 0; c < fields.Count; c++) |
||||
|
classBuilder.Pad(2).Append("InitAtom(ref ").Append(fields[c].Name).Append(", \"") |
||||
|
.Append(fields[c].Name).Append("\", atoms[").Append(c).AppendLine("]);"); |
||||
|
|
||||
|
|
||||
|
classBuilder.Pad(1).AppendLine("}"); |
||||
|
classBuilder.AppendLine("}"); |
||||
|
|
||||
|
context.AddSource(cl.GetFullyQualifiedName().Replace(":", ""), classBuilder.ToString()); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
Loading…
Reference in new issue