| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | using System.Linq; | 
					
						
							|  |  |  | using System.Text; | 
					
						
							|  |  |  | using Microsoft.CodeAnalysis; | 
					
						
							|  |  |  | using Microsoft.CodeAnalysis.CSharp.Syntax; | 
					
						
							|  |  |  | using Microsoft.CodeAnalysis.Text; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Godot.SourceGenerators | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     [Generator] | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |     public class ScriptMemberInvokerGenerator : ISourceGenerator | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |     { | 
					
						
							|  |  |  |         public void Execute(GeneratorExecutionContext context) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             if (context.AreGodotSourceGeneratorsDisabled()) | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             INamedTypeSymbol[] godotClasses = context | 
					
						
							|  |  |  |                 .Compilation.SyntaxTrees | 
					
						
							|  |  |  |                 .SelectMany(tree => | 
					
						
							|  |  |  |                     tree.GetRoot().DescendantNodes() | 
					
						
							|  |  |  |                         .OfType<ClassDeclarationSyntax>() | 
					
						
							|  |  |  |                         .SelectGodotScriptClasses(context.Compilation) | 
					
						
							|  |  |  |                         // Report and skip non-partial classes | 
					
						
							|  |  |  |                         .Where(x => | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                             if (x.cds.IsPartial()) | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                             { | 
					
						
							|  |  |  |                                 if (x.cds.IsNested() && !x.cds.AreAllOuterTypesPartial(out var typeMissingPartial)) | 
					
						
							|  |  |  |                                 { | 
					
						
							|  |  |  |                                     Common.ReportNonPartialGodotScriptOuterClass(context, typeMissingPartial!); | 
					
						
							|  |  |  |                                     return false; | 
					
						
							|  |  |  |                                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                                 return true; | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                             Common.ReportNonPartialGodotScriptClass(context, x.cds, x.symbol); | 
					
						
							|  |  |  |                             return false; | 
					
						
							|  |  |  |                         }) | 
					
						
							|  |  |  |                         .Select(x => x.symbol) | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |                 .Distinct<INamedTypeSymbol>(SymbolEqualityComparer.Default) | 
					
						
							|  |  |  |                 .ToArray(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (godotClasses.Length > 0) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 var typeCache = new MarshalUtils.TypeCache(context); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 foreach (var godotClass in godotClasses) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     VisitGodotScriptClass(context, typeCache, godotClass); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private static void VisitGodotScriptClass( | 
					
						
							|  |  |  |             GeneratorExecutionContext context, | 
					
						
							|  |  |  |             MarshalUtils.TypeCache typeCache, | 
					
						
							|  |  |  |             INamedTypeSymbol symbol | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace; | 
					
						
							|  |  |  |             string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ? | 
					
						
							|  |  |  |                 namespaceSymbol.FullQualifiedName() : | 
					
						
							|  |  |  |                 string.Empty; | 
					
						
							|  |  |  |             bool hasNamespace = classNs.Length != 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             bool isInnerClass = symbol.ContainingType != null; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |             string uniqueHint = symbol.FullQualifiedName().SanitizeQualifiedNameForUniqueHint() | 
					
						
							|  |  |  |                                 + "_ScriptMemberInvoker_Generated"; | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             var source = new StringBuilder(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             source.Append("using Godot;\n"); | 
					
						
							|  |  |  |             source.Append("using Godot.NativeInterop;\n"); | 
					
						
							|  |  |  |             source.Append("\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (hasNamespace) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 source.Append("namespace "); | 
					
						
							|  |  |  |                 source.Append(classNs); | 
					
						
							|  |  |  |                 source.Append(" {\n\n"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             if (isInnerClass) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 var containingType = symbol.ContainingType; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 while (containingType != null) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     source.Append("partial "); | 
					
						
							|  |  |  |                     source.Append(containingType.GetDeclarationKeyword()); | 
					
						
							|  |  |  |                     source.Append(" "); | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |                     source.Append(containingType.NameWithTypeParameters()); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                     source.Append("\n{\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     containingType = containingType.ContainingType; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             source.Append("partial class "); | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |             source.Append(symbol.NameWithTypeParameters()); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             source.Append("\n{\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             var members = symbol.GetMembers(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // TODO: Static static marshaling (no reflection, no runtime type checks) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             var methodSymbols = members | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |                 .Where(s => !s.IsStatic && s.Kind == SymbolKind.Method && !s.IsImplicitlyDeclared) | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 .Cast<IMethodSymbol>() | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |                 .Where(m => m.MethodKind == MethodKind.Ordinary); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             var propertySymbols = members | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |                 .Where(s => !s.IsStatic && s.Kind == SymbolKind.Property) | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 .Cast<IPropertySymbol>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             var fieldSymbols = members | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |                 .Where(s => !s.IsStatic && s.Kind == SymbolKind.Field && !s.IsImplicitlyDeclared) | 
					
						
							|  |  |  |                 .Cast<IFieldSymbol>(); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |             var godotClassMethods = methodSymbols.WhereHasGodotCompatibleSignature(typeCache).ToArray(); | 
					
						
							|  |  |  |             var godotClassProperties = propertySymbols.WhereIsGodotCompatibleType(typeCache).ToArray(); | 
					
						
							|  |  |  |             var godotClassFields = fieldSymbols.WhereIsGodotCompatibleType(typeCache).ToArray(); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |             source.Append("    private partial class GodotInternal {\n"); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // Generate cached StringNames for methods and properties, for fast lookup | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |             // TODO: Move the generation of these cached StringNames to its own generator | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             foreach (var method in godotClassMethods) | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             { | 
					
						
							|  |  |  |                 string methodName = method.Method.Name; | 
					
						
							|  |  |  |                 source.Append("        public static readonly StringName MethodName_"); | 
					
						
							|  |  |  |                 source.Append(methodName); | 
					
						
							|  |  |  |                 source.Append(" = \""); | 
					
						
							|  |  |  |                 source.Append(methodName); | 
					
						
							|  |  |  |                 source.Append("\";\n"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             source.Append("    }\n"); // class GodotInternal | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // Generate InvokeGodotClassMethod | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             if (godotClassMethods.Length > 0) | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             { | 
					
						
							|  |  |  |                 source.Append("    protected override bool InvokeGodotClassMethod(in godot_string_name method, "); | 
					
						
							|  |  |  |                 source.Append("NativeVariantPtrArgs args, int argCount, out godot_variant ret)\n    {\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 foreach (var method in godotClassMethods) | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 { | 
					
						
							|  |  |  |                     GenerateMethodInvoker(method, source); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 source.Append("        return base.InvokeGodotClassMethod(method, args, argCount, out ret);\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 source.Append("    }\n"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             // Generate Set/GetGodotClassPropertyValue | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (godotClassProperties.Length > 0 || godotClassFields.Length > 0) | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             { | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 bool isFirstEntry; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 // Setters | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |                 bool allPropertiesAreReadOnly = godotClassFields.All(fi => fi.FieldSymbol.IsReadOnly) && | 
					
						
							|  |  |  |                                                 godotClassProperties.All(pi => pi.PropertySymbol.IsReadOnly); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 if (!allPropertiesAreReadOnly) | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                     source.Append("    protected override bool SetGodotClassPropertyValue(in godot_string_name name, "); | 
					
						
							|  |  |  |                     source.Append("in godot_variant value)\n    {\n"); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                     isFirstEntry = true; | 
					
						
							|  |  |  |                     foreach (var property in godotClassProperties) | 
					
						
							|  |  |  |                     { | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |                         if (property.PropertySymbol.IsReadOnly) | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                             continue; | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |                         GeneratePropertySetter(property.PropertySymbol.Name, | 
					
						
							|  |  |  |                             property.PropertySymbol.Type.FullQualifiedName(), source, isFirstEntry); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                         isFirstEntry = false; | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                     foreach (var field in godotClassFields) | 
					
						
							|  |  |  |                     { | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |                         if (field.FieldSymbol.IsReadOnly) | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |                         GeneratePropertySetter(field.FieldSymbol.Name, | 
					
						
							|  |  |  |                             field.FieldSymbol.Type.FullQualifiedName(), source, isFirstEntry); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                         isFirstEntry = false; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     source.Append("        return base.SetGodotClassPropertyValue(name, value);\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     source.Append("    }\n"); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 // Getters | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 source.Append("    protected override bool GetGodotClassPropertyValue(in godot_string_name name, "); | 
					
						
							|  |  |  |                 source.Append("out godot_variant value)\n    {\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 isFirstEntry = true; | 
					
						
							|  |  |  |                 foreach (var property in godotClassProperties) | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |                     GeneratePropertyGetter(property.PropertySymbol.Name, source, isFirstEntry); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                     isFirstEntry = false; | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 foreach (var field in godotClassFields) | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 { | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |                     GeneratePropertyGetter(field.FieldSymbol.Name, source, isFirstEntry); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                     isFirstEntry = false; | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 source.Append("        return base.GetGodotClassPropertyValue(name, out value);\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 source.Append("    }\n"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             // Generate HasGodotClassMethod | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (godotClassMethods.Length > 0) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 source.Append("    protected override bool HasGodotClassMethod(in godot_string_name method)\n    {\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 bool isFirstEntry = true; | 
					
						
							|  |  |  |                 foreach (var method in godotClassMethods) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     GenerateHasMethodEntry(method, source, isFirstEntry); | 
					
						
							|  |  |  |                     isFirstEntry = false; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 source.Append("        return base.HasGodotClassMethod(method);\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 source.Append("    }\n"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             source.Append("}\n"); // partial class | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (isInnerClass) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 var containingType = symbol.ContainingType; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 while (containingType != null) | 
					
						
							|  |  |  |                 { | 
					
						
							|  |  |  |                     source.Append("}\n"); // outer class | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     containingType = containingType.ContainingType; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (hasNamespace) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 source.Append("\n}\n"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |             context.AddSource(uniqueHint, SourceText.From(source.ToString(), Encoding.UTF8)); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private static void GenerateMethodInvoker( | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |             GodotMethodData method, | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             StringBuilder source | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             string methodName = method.Method.Name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             source.Append("        if (method == GodotInternal.MethodName_"); | 
					
						
							|  |  |  |             source.Append(methodName); | 
					
						
							|  |  |  |             source.Append(" && argCount == "); | 
					
						
							|  |  |  |             source.Append(method.ParamTypes.Length); | 
					
						
							|  |  |  |             source.Append(") {\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (method.RetType != null) | 
					
						
							|  |  |  |                 source.Append("            object retBoxed = "); | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 source.Append("            "); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             source.Append(methodName); | 
					
						
							|  |  |  |             source.Append("("); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (int i = 0; i < method.ParamTypes.Length; i++) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 if (i != 0) | 
					
						
							|  |  |  |                     source.Append(", "); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 // TODO: static marshaling (no reflection, no runtime type checks) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 string paramTypeQualifiedName = method.ParamTypeSymbols[i].FullQualifiedName(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 source.Append("("); | 
					
						
							|  |  |  |                 source.Append(paramTypeQualifiedName); | 
					
						
							|  |  |  |                 source.Append(")Marshaling.ConvertVariantToManagedObjectOfType(args["); | 
					
						
							|  |  |  |                 source.Append(i); | 
					
						
							|  |  |  |                 source.Append("], typeof("); | 
					
						
							|  |  |  |                 source.Append(paramTypeQualifiedName); | 
					
						
							|  |  |  |                 source.Append("))"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             source.Append(");\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (method.RetType != null) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 // TODO: static marshaling (no reflection, no runtime type checks) | 
					
						
							|  |  |  |                 source.Append("            ret = Marshaling.ConvertManagedObjectToVariant(retBoxed);\n"); | 
					
						
							|  |  |  |                 source.Append("            return true;\n"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 source.Append("            ret = default;\n"); | 
					
						
							|  |  |  |                 source.Append("            return true;\n"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             source.Append("        }\n"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private static void GeneratePropertySetter( | 
					
						
							|  |  |  |             string propertyMemberName, | 
					
						
							|  |  |  |             string propertyTypeQualifiedName, | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             StringBuilder source, | 
					
						
							|  |  |  |             bool isFirstEntry | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |         ) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             source.Append("        "); | 
					
						
							|  |  |  |             if (!isFirstEntry) | 
					
						
							|  |  |  |                 source.Append("else "); | 
					
						
							|  |  |  |             source.Append("if (name == GodotInternal.PropName_"); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             source.Append(propertyMemberName); | 
					
						
							|  |  |  |             source.Append(") {\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             source.Append("            "); | 
					
						
							|  |  |  |             source.Append(propertyMemberName); | 
					
						
							|  |  |  |             source.Append(" = "); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // TODO: static marshaling (no reflection, no runtime type checks) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             source.Append("("); | 
					
						
							|  |  |  |             source.Append(propertyTypeQualifiedName); | 
					
						
							|  |  |  |             source.Append(")Marshaling.ConvertVariantToManagedObjectOfType(value, typeof("); | 
					
						
							|  |  |  |             source.Append(propertyTypeQualifiedName); | 
					
						
							|  |  |  |             source.Append("));\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             source.Append("            return true;\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             source.Append("        }\n"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         private static void GeneratePropertyGetter( | 
					
						
							|  |  |  |             string propertyMemberName, | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             StringBuilder source, | 
					
						
							|  |  |  |             bool isFirstEntry | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |         ) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             source.Append("        "); | 
					
						
							|  |  |  |             if (!isFirstEntry) | 
					
						
							|  |  |  |                 source.Append("else "); | 
					
						
							|  |  |  |             source.Append("if (name == GodotInternal.PropName_"); | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             source.Append(propertyMemberName); | 
					
						
							|  |  |  |             source.Append(") {\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // TODO: static marshaling (no reflection, no runtime type checks) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             source.Append("            value = Marshaling.ConvertManagedObjectToVariant("); | 
					
						
							|  |  |  |             source.Append(propertyMemberName); | 
					
						
							|  |  |  |             source.Append(");\n"); | 
					
						
							|  |  |  |             source.Append("            return true;\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             source.Append("        }\n"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |         private static void GenerateHasMethodEntry( | 
					
						
							| 
									
										
										
										
											2022-02-27 21:57:30 +01:00
										 |  |  |             GodotMethodData method, | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |             StringBuilder source, | 
					
						
							|  |  |  |             bool isFirstEntry | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             string methodName = method.Method.Name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             source.Append("        "); | 
					
						
							|  |  |  |             if (!isFirstEntry) | 
					
						
							|  |  |  |                 source.Append("else "); | 
					
						
							|  |  |  |             source.Append("if (method == GodotInternal.MethodName_"); | 
					
						
							|  |  |  |             source.Append(methodName); | 
					
						
							|  |  |  |             source.Append(") {\n           return true;\n        }\n"); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:25:16 +01:00
										 |  |  |         public void Initialize(GeneratorInitializationContext context) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |