Browse Source

Fix and refactor PixiEditor code gen

CPKreuz 2 years ago
parent
commit
f88a7da833
1 changed files with 109 additions and 96 deletions
  1. 109 96
      src/PixiEditorGen/CommandNameListGenerator.cs

+ 109 - 96
src/PixiEditorGen/CommandNameListGenerator.cs

@@ -7,152 +7,90 @@ namespace PixiEditorGen;
 [Generator(LanguageNames.CSharp)]
 [Generator(LanguageNames.CSharp)]
 public class CommandNameListGenerator : IIncrementalGenerator
 public class CommandNameListGenerator : IIncrementalGenerator
 {
 {
-    private const string Command = "PixiEditor.Models.Commands.Attributes.Commands";
+    private const string Commands = "PixiEditor.Models.Commands.Attributes.Commands";
 
 
     private const string Evaluators = "PixiEditor.Models.Commands.Attributes.Evaluators.Evaluator";
     private const string Evaluators = "PixiEditor.Models.Commands.Attributes.Evaluators.Evaluator";
 
 
     private const string Groups = "PixiEditor.Models.Commands.Attributes.Commands.Command.GroupAttribute";
     private const string Groups = "PixiEditor.Models.Commands.Attributes.Commands.Command.GroupAttribute";
-    
+
     public void Initialize(IncrementalGeneratorInitializationContext context)
     public void Initialize(IncrementalGeneratorInitializationContext context)
     {
     {
-        var commandList = context.SyntaxProvider.CreateSyntaxProvider(
-            (x, token) =>
-        {
-            return x is MethodDeclarationSyntax method && method.AttributeLists.Count > 0;
-        }, static (context, cancelToken) =>
-        {
-            var method = (MethodDeclarationSyntax)context.Node;
-
-            if (!HasCommandAttribute(method, context, cancelToken, Command))
-                return (null, null, null);
-
-            var symbol = context.SemanticModel.GetDeclaredSymbol(method, cancelToken);
-
-            if (symbol is IMethodSymbol methodSymbol)
-            {
-                if (methodSymbol.ReceiverType == null)
-                    return (null, null, null);
-                
-                return (methodSymbol.ReceiverType.ToDisplayString(), methodSymbol.Name, methodSymbol.Parameters.Select(x => x.ToDisplayString()));
-            }
-            else
-            {
-                return (null, null, null);
-            }
-        }).Where(x => x.Item1 != null);
-
-        var evaluatorList = context.SyntaxProvider.CreateSyntaxProvider(
-            (x, token) =>
-            {
-                return x is MethodDeclarationSyntax method && method.AttributeLists.Count > 0;
-            }, static (context, cancelToken) =>
-            {
-                var method = (MethodDeclarationSyntax)context.Node;
-
-                if (!HasCommandAttribute(method, context, cancelToken, Evaluators))
-                    return (null, null, null);
-
-                var symbol = context.SemanticModel.GetDeclaredSymbol(method, cancelToken);
-
-                if (symbol is IMethodSymbol methodSymbol)
-                {
-                    return (methodSymbol.ReceiverType.ToDisplayString(), methodSymbol.Name, methodSymbol.Parameters.Select(x => x.ToDisplayString()));
-                }
-                else
-                {
-                    return (null, null, null);
-                }
-            }).Where(x => x.Item1 != null);
-        
-        var groupList = context.SyntaxProvider.CreateSyntaxProvider(
-            (x, token) =>
-            {
-                return x is TypeDeclarationSyntax type && type.AttributeLists.Count > 0;
-            }, static (context, cancelToken) =>
-            {
-                var method = (TypeDeclarationSyntax)context.Node;
-
-                if (!HasCommandAttribute(method, context, cancelToken, Groups))
-                    return null;
-
-                var symbol = context.SemanticModel.GetDeclaredSymbol(method, cancelToken);
-
-                if (symbol is ITypeSymbol methodSymbol)
-                {
-                    return methodSymbol.ToDisplayString();
-                }
-                else
-                {
-                    return null;
-                }
-            }).Where(x => x != null);
+        var commandList = CreateSyntaxProvider(context, Commands).Where(x => !x.IsNone);
+        var evaluatorList = CreateSyntaxProvider(context, Evaluators).Where(x => !x.IsNone);
+        var groupList = CreateGroupSyntaxProvider(context).Where(x => x != null);
 
 
         context.RegisterSourceOutput(commandList.Collect(), static (context, methodNames) =>
         context.RegisterSourceOutput(commandList.Collect(), static (context, methodNames) =>
         {
         {
             var code = new StringBuilder(
             var code = new StringBuilder(
-                @"namespace PixiEditor.Models.Commands;
+                """
+                namespace PixiEditor.Models.Commands;
 
 
-internal partial class CommandNameList {
-    partial void AddCommands() {");
+                internal partial class CommandNameList {
+                    partial void AddCommands() {
+                """);
 
 
             List<string> createdClasses = new List<string>();
             List<string> createdClasses = new List<string>();
 
 
             foreach (var method in methodNames)
             foreach (var method in methodNames)
             {
             {
-                if (!createdClasses.Contains(method.Item1))
+                if (!createdClasses.Contains(method.OwnerTypeName))
                 {
                 {
-                    code.AppendLine($"      Commands.Add(typeof({method.Item1}), new());");
-                    createdClasses.Add(method.Item1);
+                    code.AppendLine($"      Commands.Add(typeof({method.OwnerTypeName}), new());");
+                    createdClasses.Add(method.OwnerTypeName);
                 }
                 }
 
 
-                var parameters = string.Join(",", method.Item3.Select(x => $"typeof({x})"));
-                
+                var parameters = string.Join(",", method.ParameterTypeNames);
+
                 bool hasParameters = parameters.Length > 0;
                 bool hasParameters = parameters.Length > 0;
                 string paramString = hasParameters ? $"new Type[] {{ {parameters} }}" : "Array.Empty<Type>()";
                 string paramString = hasParameters ? $"new Type[] {{ {parameters} }}" : "Array.Empty<Type>()";
-                
-                code.AppendLine($"      Commands[typeof({method.Item1})].Add((\"{method.Item2}\", {paramString}));");
+
+                code.AppendLine($"      Commands[typeof({method.OwnerTypeName})].Add((\"{method.MethodName}\", {paramString}));");
             }
             }
 
 
             code.Append("   }\n}");
             code.Append("   }\n}");
 
 
             context.AddSource("CommandNameList+Commands", code.ToString());
             context.AddSource("CommandNameList+Commands", code.ToString());
         });
         });
-        
+
         context.RegisterSourceOutput(evaluatorList.Collect(), static (context, methodNames) =>
         context.RegisterSourceOutput(evaluatorList.Collect(), static (context, methodNames) =>
         {
         {
             var code = new StringBuilder(
             var code = new StringBuilder(
-                @"namespace PixiEditor.Models.Commands;
+                """
+                namespace PixiEditor.Models.Commands;
 
 
-internal partial class CommandNameList {
-    partial void AddEvaluators() {");
+                internal partial class CommandNameList {
+                    partial void AddEvaluators() {
+                """);
 
 
             List<string> createdClasses = new List<string>();
             List<string> createdClasses = new List<string>();
 
 
             foreach (var method in methodNames)
             foreach (var method in methodNames)
             {
             {
-                if (!createdClasses.Contains(method.Item1))
+                if (!createdClasses.Contains(method.OwnerTypeName))
                 {
                 {
-                    code.AppendLine($"      Evaluators.Add(typeof({method.Item1}), new());");
-                    createdClasses.Add(method.Item1);
+                    code.AppendLine($"      Evaluators.Add(typeof({method.OwnerTypeName}), new());");
+                    createdClasses.Add(method.OwnerTypeName);
                 }
                 }
 
 
-                if (method.Item3 == null || !method.Item3.Any())
+                if (method.ParameterTypeNames == null || !method.ParameterTypeNames.Any())
                 {
                 {
-                    code.AppendLine($"      Evaluators[typeof({method.Item1})].Add((\"{method.Item2}\", Array.Empty<Type>()));");
+                    code.AppendLine($"      Evaluators[typeof({method.OwnerTypeName})].Add((\"{method.MethodName}\", Array.Empty<Type>()));");
                 }
                 }
                 else
                 else
                 {
                 {
-                    var parameters = string.Join(",", method.Item3.Select(x => $"typeof({x})"));
+                    var parameters = string.Join(",", method.ParameterTypeNames);
                     string paramString = parameters.Length > 0 ? $"new Type[] {{ {parameters} }}" : "Array.Empty<Type>()";
                     string paramString = parameters.Length > 0 ? $"new Type[] {{ {parameters} }}" : "Array.Empty<Type>()";
-                    code.AppendLine($"      Evaluators[typeof({method.Item1})].Add((\"{method.Item2}\", {paramString}));");
+                    code.AppendLine($"      Evaluators[typeof({method.OwnerTypeName})].Add((\"{method.MethodName}\", {paramString}));");
                 }
                 }
             }
             }
 
 
             code.Append("   }\n}");
             code.Append("   }\n}");
 
 
+            File.WriteAllText(@"C:\Users\phili\Documents\Evals.txt", code.ToString());
+
             context.AddSource("CommandNameList+Evaluators", code.ToString());
             context.AddSource("CommandNameList+Evaluators", code.ToString());
         });
         });
-        
+
         context.RegisterSourceOutput(groupList.Collect(), static (context, typeNames) =>
         context.RegisterSourceOutput(groupList.Collect(), static (context, typeNames) =>
         {
         {
             var code = new StringBuilder(
             var code = new StringBuilder(
@@ -171,7 +109,62 @@ internal partial class CommandNameList {
             context.AddSource("CommandNameList+Groups", code.ToString());
             context.AddSource("CommandNameList+Groups", code.ToString());
         });
         });
     }
     }
-    
+
+    private IncrementalValuesProvider<Command> CreateSyntaxProvider(IncrementalGeneratorInitializationContext context, string className)
+    {
+        return context.SyntaxProvider.CreateSyntaxProvider(
+            (x, token) =>
+            {
+                return x is MethodDeclarationSyntax method && method.AttributeLists.Count > 0;
+            }, (context, cancelToken) =>
+            {
+                var method = (MethodDeclarationSyntax)context.Node;
+
+                if (!HasCommandAttribute(method, context, cancelToken, className))
+                    return Command.None;
+
+                var symbol = context.SemanticModel.GetDeclaredSymbol(method, cancelToken);
+
+                if (symbol is IMethodSymbol methodSymbol)
+                {
+                    if (methodSymbol.ReceiverType == null)
+                        return Command.None;
+
+                    return new Command(methodSymbol);
+                }
+                else
+                {
+                    return Command.None;
+                }
+            });
+    }
+
+    private IncrementalValuesProvider<string?> CreateGroupSyntaxProvider(IncrementalGeneratorInitializationContext context)
+    {
+        return context.SyntaxProvider.CreateSyntaxProvider(
+            (x, token) =>
+            {
+                return x is TypeDeclarationSyntax type && type.AttributeLists.Count > 0;
+            }, static (context, cancelToken) =>
+            {
+                var method = (TypeDeclarationSyntax)context.Node;
+
+                if (!HasCommandAttribute(method, context, cancelToken, Groups))
+                    return null;
+
+                var symbol = context.SemanticModel.GetDeclaredSymbol(method, cancelToken);
+
+                if (symbol is ITypeSymbol methodSymbol)
+                {
+                    return methodSymbol.ToDisplayString();
+                }
+                else
+                {
+                    return null;
+                }
+            });
+    }
+
     private static bool HasCommandAttribute(MemberDeclarationSyntax declaration, GeneratorSyntaxContext context, CancellationToken token, string commandAttributeStart)
     private static bool HasCommandAttribute(MemberDeclarationSyntax declaration, GeneratorSyntaxContext context, CancellationToken token, string commandAttributeStart)
     {
     {
         foreach (var attrList in declaration.AttributeLists)
         foreach (var attrList in declaration.AttributeLists)
@@ -191,4 +184,24 @@ internal partial class CommandNameList {
 
 
         return false;
         return false;
     }
     }
+
+    readonly struct Command
+    {
+        public string OwnerTypeName { get; }
+
+        public string MethodName { get; }
+
+        public string[] ParameterTypeNames { get; }
+
+        public Command(IMethodSymbol symbol)
+        {
+            OwnerTypeName = symbol.ContainingType.ToDisplayString();
+            MethodName = symbol.Name;
+            ParameterTypeNames = symbol.Parameters.Select(x => $"typeof({x.Type.ToDisplayString()})").ToArray();
+        }
+
+        public bool IsNone => OwnerTypeName == null;
+
+        public static Command None => default;
+    }
 }
 }