committed by
GitHub
9 changed files with 375 additions and 173 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