From 12e4aa93b3099b574468dc1a69679dcf1aa8c461 Mon Sep 17 00:00:00 2001 From: Raul Santos Date: Sun, 9 Jul 2023 14:14:36 +0200 Subject: [PATCH] C#: Document generated members Documents generated members and tries to discourage users from calling/overriding internal methods that only exist to be used by the engine. --- .../ScriptMethodsGenerator.cs | 22 +++++++ .../ScriptPropertiesGenerator.cs | 32 +++++++++- .../ScriptPropertyDefValGenerator.cs | 15 ++++- .../ScriptSerializationGenerator.cs | 4 ++ .../ScriptSignalsGenerator.cs | 23 +++++++ modules/mono/editor/bindings_generator.cpp | 61 ++++++++++++++++--- .../GodotSharp/Core/GodotObject.base.cs | 40 ++++++++++++ .../Core/Interfaces/ISerializationListener.cs | 12 +++- 8 files changed, 195 insertions(+), 14 deletions(-) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs index 1affe692d0b..5ea0ca53c3c 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptMethodsGenerator.cs @@ -135,6 +135,10 @@ namespace Godot.SourceGenerators source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n"); + source.Append(" /// \n") + .Append(" /// Cached StringNames for the methods contained in this class, for fast lookup.\n") + .Append(" /// \n"); + source.Append( $" public new class MethodName : {symbol.BaseType.FullQualifiedNameIncludeGlobal()}.MethodName {{\n"); @@ -147,6 +151,12 @@ namespace Godot.SourceGenerators foreach (string methodName in distinctMethodNames) { + source.Append(" /// \n") + .Append(" /// Cached name for the '") + .Append(methodName) + .Append("' method.\n") + .Append(" /// \n"); + source.Append(" public new static readonly global::Godot.StringName "); source.Append(methodName); source.Append(" = \""); @@ -162,6 +172,14 @@ namespace Godot.SourceGenerators { const string listType = "global::System.Collections.Generic.List"; + source.Append(" /// \n") + .Append(" /// Get the method information for all the methods declared in this class.\n") + .Append(" /// This method is used by Godot to register the available methods in the editor.\n") + .Append(" /// Do not call this method.\n") + .Append(" /// \n"); + + source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n"); + source.Append(" internal new static ") .Append(listType) .Append(" GetGodotMethodList()\n {\n"); @@ -188,6 +206,8 @@ namespace Godot.SourceGenerators if (godotClassMethods.Length > 0) { + source.Append(" /// \n"); + source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n"); source.Append(" protected override bool InvokeGodotClassMethod(in godot_string_name method, "); source.Append("NativeVariantPtrArgs args, out godot_variant ret)\n {\n"); @@ -205,6 +225,8 @@ namespace Godot.SourceGenerators if (distinctMethodNames.Length > 0) { + source.Append(" /// \n"); + source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n"); source.Append(" protected override bool HasGodotClassMethod(in godot_string_name method)\n {\n"); bool isFirstEntry = true; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs index 3e6858485df..208c08aed4e 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs @@ -124,6 +124,10 @@ namespace Godot.SourceGenerators source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n"); + source.Append(" /// \n") + .Append(" /// Cached StringNames for the properties and fields contained in this class, for fast lookup.\n") + .Append(" /// \n"); + source.Append( $" public new class PropertyName : {symbol.BaseType.FullQualifiedNameIncludeGlobal()}.PropertyName {{\n"); @@ -132,6 +136,13 @@ namespace Godot.SourceGenerators foreach (var property in godotClassProperties) { string propertyName = property.PropertySymbol.Name; + + source.Append(" /// \n") + .Append(" /// Cached name for the '") + .Append(propertyName) + .Append("' property.\n") + .Append(" /// \n"); + source.Append(" public new static readonly global::Godot.StringName "); source.Append(propertyName); source.Append(" = \""); @@ -142,6 +153,13 @@ namespace Godot.SourceGenerators foreach (var field in godotClassFields) { string fieldName = field.FieldSymbol.Name; + + source.Append(" /// \n") + .Append(" /// Cached name for the '") + .Append(fieldName) + .Append("' field.\n") + .Append(" /// \n"); + source.Append(" public new static readonly global::Godot.StringName "); source.Append(fieldName); source.Append(" = \""); @@ -162,6 +180,8 @@ namespace Godot.SourceGenerators if (!allPropertiesAreReadOnly) { + source.Append(" /// \n"); + source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n"); source.Append(" protected override bool SetGodotClassPropertyValue(in godot_string_name name, "); source.Append("in godot_variant value)\n {\n"); @@ -193,6 +213,8 @@ namespace Godot.SourceGenerators // Generate GetGodotClassPropertyValue + source.Append(" /// \n"); + source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n"); source.Append(" protected override bool GetGodotClassPropertyValue(in godot_string_name name, "); source.Append("out godot_variant value)\n {\n"); @@ -217,7 +239,15 @@ namespace Godot.SourceGenerators // Generate GetGodotPropertyList - string dictionaryType = "global::System.Collections.Generic.List"; + const string dictionaryType = "global::System.Collections.Generic.List"; + + source.Append(" /// \n") + .Append(" /// Get the property information for all the properties declared in this class.\n") + .Append(" /// This method is used by Godot to register the available properties in the editor.\n") + .Append(" /// Do not call this method.\n") + .Append(" /// \n"); + + source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n"); source.Append(" internal new static ") .Append(dictionaryType) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs index ac908a6de3b..4df16d05f07 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs @@ -285,10 +285,20 @@ namespace Godot.SourceGenerators { source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n"); - string dictionaryType = + const string dictionaryType = "global::System.Collections.Generic.Dictionary"; source.Append("#if TOOLS\n"); + + source.Append(" /// \n") + .Append(" /// Get the default values for all properties declared in this class.\n") + .Append(" /// This method is used by Godot to determine the value that will be\n") + .Append(" /// used by the inspector when resetting properties.\n") + .Append(" /// Do not call this method.\n") + .Append(" /// \n"); + + source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n"); + source.Append(" internal new static "); source.Append(dictionaryType); source.Append(" GetGodotPropertyDefaultValues()\n {\n"); @@ -320,7 +330,8 @@ namespace Godot.SourceGenerators source.Append(" return values;\n"); source.Append(" }\n"); - source.Append("#endif\n"); + + source.Append("#endif // TOOLS\n"); source.Append("#pragma warning restore CS0109\n"); } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs index 97771b721da..231a7be021e 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs @@ -149,6 +149,8 @@ namespace Godot.SourceGenerators godotSignalDelegates.Add(new(signalName, signalDelegateSymbol, invokeMethodData.Value)); } + source.Append(" /// \n"); + source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n"); source.Append( " protected override void SaveGodotObjectData(global::Godot.Bridge.GodotSerializationInfo info)\n {\n"); source.Append(" base.SaveGodotObjectData(info);\n"); @@ -196,6 +198,8 @@ namespace Godot.SourceGenerators source.Append(" }\n"); + source.Append(" /// \n"); + source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n"); source.Append( " protected override void RestoreGodotObjectData(global::Godot.Bridge.GodotSerializationInfo info)\n {\n"); source.Append(" base.RestoreGodotObjectData(info);\n"); diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs index 7e3323f588b..8f2774d5ae9 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs @@ -176,6 +176,10 @@ namespace Godot.SourceGenerators source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n"); + source.Append(" /// \n") + .Append(" /// Cached StringNames for the signals contained in this class, for fast lookup.\n") + .Append(" /// \n"); + source.Append( $" public new class SignalName : {symbol.BaseType.FullQualifiedNameIncludeGlobal()}.SignalName {{\n"); @@ -184,6 +188,13 @@ namespace Godot.SourceGenerators foreach (var signalDelegate in godotSignalDelegates) { string signalName = signalDelegate.Name; + + source.Append(" /// \n") + .Append(" /// Cached name for the '") + .Append(signalName) + .Append("' signal.\n") + .Append(" /// \n"); + source.Append(" public new static readonly global::Godot.StringName "); source.Append(signalName); source.Append(" = \""); @@ -199,6 +210,14 @@ namespace Godot.SourceGenerators { const string listType = "global::System.Collections.Generic.List"; + source.Append(" /// \n") + .Append(" /// Get the signal information for all the signals declared in this class.\n") + .Append(" /// This method is used by Godot to register the available signals in the editor.\n") + .Append(" /// Do not call this method.\n") + .Append(" /// \n"); + + source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n"); + source.Append(" internal new static ") .Append(listType) .Append(" GetGodotSignalList()\n {\n"); @@ -258,6 +277,8 @@ namespace Godot.SourceGenerators if (godotSignalDelegates.Count > 0) { + source.Append(" /// \n"); + source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n"); source.Append( " protected override void RaiseGodotClassSignalCallbacks(in godot_string_name signal, "); source.Append("NativeVariantPtrArgs args)\n {\n"); @@ -276,6 +297,8 @@ namespace Godot.SourceGenerators if (godotSignalDelegates.Count > 0) { + source.Append(" /// \n"); + source.Append(" [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]\n"); source.Append( " protected override bool HasGodotClassSignal(in godot_string_name signal)\n {\n"); diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 15bb574f4d4..cff41a57f3f 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -1616,7 +1616,16 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str // Generate InvokeGodotClassMethod - output << MEMBER_BEGIN "protected internal " << (is_derived_type ? "override" : "virtual") + output << MEMBER_BEGIN "/// \n" + << INDENT1 "/// Invokes the method with the given name, using the given arguments.\n" + << INDENT1 "/// This method is used by Godot to invoke methods from the engine side.\n" + << INDENT1 "/// Do not call or override this method.\n" + << INDENT1 "/// \n" + << INDENT1 "/// Name of the method to invoke.\n" + << INDENT1 "/// Arguments to use with the invoked method.\n" + << INDENT1 "/// Value returned by the invoked method.\n"; + + output << INDENT1 "protected internal " << (is_derived_type ? "override" : "virtual") << " bool " CS_METHOD_INVOKE_GODOT_CLASS_METHOD "(in godot_string_name method, " << "NativeVariantPtrArgs args, out godot_variant ret)\n" << INDENT1 "{\n"; @@ -1696,6 +1705,13 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str // Generate HasGodotClassMethod + output << MEMBER_BEGIN "/// \n" + << INDENT1 "/// Check if the type contains a method with the given name.\n" + << INDENT1 "/// This method is used by Godot to check if a method exists before invoking it.\n" + << INDENT1 "/// Do not call or override this method.\n" + << INDENT1 "/// \n" + << INDENT1 "/// Name of the method to check for.\n"; + output << MEMBER_BEGIN "protected internal " << (is_derived_type ? "override" : "virtual") << " bool " CS_METHOD_HAS_GODOT_CLASS_METHOD "(in godot_string_name method)\n" << INDENT1 "{\n"; @@ -1728,6 +1744,13 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str // Generate HasGodotClassSignal + output << MEMBER_BEGIN "/// \n" + << INDENT1 "/// Check if the type contains a signal with the given name.\n" + << INDENT1 "/// This method is used by Godot to check if a signal exists before raising it.\n" + << INDENT1 "/// Do not call or override this method.\n" + << INDENT1 "/// \n" + << INDENT1 "/// Name of the method to check for.\n"; + output << MEMBER_BEGIN "protected internal " << (is_derived_type ? "override" : "virtual") << " bool " CS_METHOD_HAS_GODOT_CLASS_SIGNAL "(in godot_string_name signal)\n" << INDENT1 "{\n"; @@ -1758,39 +1781,57 @@ Error BindingsGenerator::_generate_cs_type(const TypeInterface &itype, const Str //Generate StringName for all class members bool is_inherit = !itype.is_singleton && obj_types.has(itype.base_name); //PropertyName + output << MEMBER_BEGIN "/// \n" + << INDENT1 "/// Cached StringNames for the properties and fields contained in this class, for fast lookup.\n" + << INDENT1 "/// \n"; if (is_inherit) { - output << MEMBER_BEGIN "public new class PropertyName : " << obj_types[itype.base_name].proxy_name << ".PropertyName"; + output << INDENT1 "public new class PropertyName : " << obj_types[itype.base_name].proxy_name << ".PropertyName"; } else { - output << MEMBER_BEGIN "public class PropertyName"; + output << INDENT1 "public class PropertyName"; } output << "\n" << INDENT1 "{\n"; for (const PropertyInterface &iprop : itype.properties) { - output << INDENT2 "public static readonly StringName " << iprop.proxy_name << " = \"" << iprop.cname << "\";\n"; + output << INDENT2 "/// \n" + << INDENT2 "/// Cached name for the '" << iprop.cname << "' property.\n" + << INDENT2 "/// \n" + << INDENT2 "public static readonly StringName " << iprop.proxy_name << " = \"" << iprop.cname << "\";\n"; } output << INDENT1 "}\n"; //MethodName + output << MEMBER_BEGIN "/// \n" + << INDENT1 "/// Cached StringNames for the methods contained in this class, for fast lookup.\n" + << INDENT1 "/// \n"; if (is_inherit) { - output << MEMBER_BEGIN "public new class MethodName : " << obj_types[itype.base_name].proxy_name << ".MethodName"; + output << INDENT1 "public new class MethodName : " << obj_types[itype.base_name].proxy_name << ".MethodName"; } else { - output << MEMBER_BEGIN "public class MethodName"; + output << INDENT1 "public class MethodName"; } output << "\n" << INDENT1 "{\n"; for (const MethodInterface &imethod : itype.methods) { - output << INDENT2 "public static readonly StringName " << imethod.proxy_name << " = \"" << imethod.cname << "\";\n"; + output << INDENT2 "/// \n" + << INDENT2 "/// Cached name for the '" << imethod.cname << "' method.\n" + << INDENT2 "/// \n" + << INDENT2 "public static readonly StringName " << imethod.proxy_name << " = \"" << imethod.cname << "\";\n"; } output << INDENT1 "}\n"; //SignalName + output << MEMBER_BEGIN "/// \n" + << INDENT1 "/// Cached StringNames for the signals contained in this class, for fast lookup.\n" + << INDENT1 "/// \n"; if (is_inherit) { - output << MEMBER_BEGIN "public new class SignalName : " << obj_types[itype.base_name].proxy_name << ".SignalName"; + output << INDENT1 "public new class SignalName : " << obj_types[itype.base_name].proxy_name << ".SignalName"; } else { - output << MEMBER_BEGIN "public class SignalName"; + output << INDENT1 "public class SignalName"; } output << "\n" << INDENT1 "{\n"; for (const SignalInterface &isignal : itype.signals_) { - output << INDENT2 "public static readonly StringName " << isignal.proxy_name << " = \"" << isignal.cname << "\";\n"; + output << INDENT2 "/// \n" + << INDENT2 "/// Cached name for the '" << isignal.cname << "' signal.\n" + << INDENT2 "/// \n" + << INDENT2 "public static readonly StringName " << isignal.proxy_name << " = \"" << isignal.cname << "\";\n"; } output << INDENT1 "}\n"; diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs index 12e8a638d3b..c6337e56efd 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotObject.base.cs @@ -191,12 +191,30 @@ namespace Godot } // ReSharper disable once VirtualMemberNeverOverridden.Global + /// + /// Set the value of a property contained in this class. + /// This method is used by Godot to assign property values. + /// Do not call or override this method. + /// + /// Name of the property to set. + /// Value to set the property to if it was found. + /// if a property with the given name was found. + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] protected internal virtual bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value) { return false; } // ReSharper disable once VirtualMemberNeverOverridden.Global + /// + /// Get the value of a property contained in this class. + /// This method is used by Godot to retrieve property values. + /// Do not call or override this method. + /// + /// Name of the property to get. + /// Value of the property if it was found. + /// if a property with the given name was found. + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] protected internal virtual bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value) { value = default; @@ -204,6 +222,14 @@ namespace Godot } // ReSharper disable once VirtualMemberNeverOverridden.Global + /// + /// Raises the signal with the given name, using the given arguments. + /// This method is used by Godot to raise signals from the engine side.\n" + /// Do not call or override this method. + /// + /// Name of the signal to raise. + /// Arguments to use with the raised signal. + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] protected internal virtual void RaiseGodotClassSignalCallbacks(in godot_string_name signal, NativeVariantPtrArgs args) { @@ -233,11 +259,25 @@ namespace Godot return nativeConstructor; } + /// + /// Saves this instance's state to be restored when reloading assemblies. + /// Do not call or override this method. + /// To add data to be saved and restored, implement . + /// + /// Object used to save the data. + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] protected internal virtual void SaveGodotObjectData(GodotSerializationInfo info) { } // TODO: Should this be a constructor overload? + /// + /// Restores this instance's state after reloading assemblies. + /// Do not call or override this method. + /// To add data to be saved and restored, implement . + /// + /// Object that contains the previously saved data. + [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] protected internal virtual void RestoreGodotObjectData(GodotSerializationInfo info) { } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs index 90b4d1b8d35..3288705dab8 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Interfaces/ISerializationListener.cs @@ -1,11 +1,21 @@ namespace Godot { /// - /// An interface that requires methods for before and after serialization. + /// Allows a GodotObject to react to the serialization/deserialization + /// that occurs when Godot reloads assemblies. /// public interface ISerializationListener { + /// + /// Executed before serializing this instance's state when reloading assemblies. + /// Clear any data that should not be serialized. + /// void OnBeforeSerialize(); + + /// + /// Executed after deserializing this instance's state after reloading assemblies. + /// Restore any state that has been lost. + /// void OnAfterDeserialize(); } }