Document C# diagnostics

This commit is contained in:
Raul Santos
2023-08-06 18:10:52 +02:00
parent dac6f82d3e
commit 44029d167d
18 changed files with 839 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
GD0001: Missing partial modifier on declaration of type which is a subclass of GodotObject
==========================================================================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0001
**Category** Usage
**Fix is breaking or non-breaking** Non-breaking
**Enabled by default** Yes
==================================== ======================================
Cause
-----
A type that derives from ``GodotObject`` is not declared partial.
Rule description
----------------
Godot source generators add generated code to user-defined types to implement
the integration with the engine. Source generators can't add generated code to
types that aren't declared partial.
.. code-block:: csharp
// The source generators can't enhance this type to work with Godot.
public class InvalidNode : Node { }
// The source generators can enhance this type to work with Godot.
public partial class ValidNode { }
How to fix violations
---------------------
To fix a violation of this rule, add the ``partial`` keyword to the type
declaration.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. Types that derive from ``GodotObject``
but aren't partial can't be enhanced by the source generators, resulting in
unexpected runtime errors.

View File

@@ -0,0 +1,52 @@
GD0002: Missing partial modifier on declaration of type which contains one or more subclasses of GodotObject
============================================================================================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0002
**Category** Usage
**Fix is breaking or non-breaking** Non-breaking
**Enabled by default** Yes
==================================== ======================================
Cause
-----
A type that derives from ``GodotObject`` is contained in a non-partial type declaration.
Rule description
----------------
Godot source generators add generated code to user-defined types to implement
the integration with the engine. Source generators can't add generated code to
types that aren't declared partial.
.. code-block:: csharp
public class InvalidParentType
{
// MyNode is contained in a non-partial type so the source generators
// can't enhance this type to work with Godot.
public partial class MyNode : Node { }
}
public partial class ValidParentType
{
// MyNode is contained in a partial type so the source generators
// can enhance this type to work with Godot.
public partial class MyNode : Node { }
}
How to fix violations
---------------------
To fix a violation of this rule, add the ``partial`` keyword to the type
declaration.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. Types that derive from ``GodotObject``
but aren't partial can't be enhanced by the source generators, resulting in
unexpected runtime errors.

View File

@@ -0,0 +1,46 @@
GD0101: Attempted to export static member
=========================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0101
**Category** Usage
**Fix is breaking or non-breaking** Breaking - If the ``static`` keyword is removed
Non-breaking - If the ``[Export]`` attribute is removed
**Enabled by default** Yes
==================================== ======================================
Cause
-----
A static member is annotated with the ``[Export]`` attribute. Static members
can't be exported.
Rule description
----------------
Godot doesn't allow exporting static members.
.. code-block:: csharp
// Static members can't be exported.
[Export]
public static int InvalidProperty { get; set; }
// Instance members can be exported.
[Export]
public int ValidProperty { get; set; }
How to fix violations
---------------------
To fix a violation of this rule, remove the ``[Export]`` attribute or remove the
``static`` keyword.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. Static members can't be exported so
they will be ignored by Godot, resulting in runtime errors.

View File

@@ -0,0 +1,50 @@
GD0102: The type of the exported member is not supported
========================================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0102
**Category** Usage
**Fix is breaking or non-breaking** Breaking - If the member type is changed
Non-breaking - If the ``[Export]`` attribute is removed
**Enabled by default** Yes
==================================== ======================================
Cause
-----
An unsupported type is specified for a member annotated with the ``[Export]``
attribute when a :ref:`Variant-compatible <doc_c_sharp_variant>` type is expected.
Rule description
----------------
Every exported member must be Variant-compatible so it can be marshalled by
the engine.
.. code-block:: csharp
class SomeType { }
// SomeType is not a valid member type because it doesn't derive from GodotObject,
// so it's not compatible with Variant.
[Export]
public SomeType InvalidProperty { get; set; }
// System.Int32 is a valid type because it's compatible with Variant.
[Export]
public int ValidProperty { get; set; }
How to fix violations
---------------------
To fix a violation of this rule, change the member's type to be Variant-compatible
or remove the ``[Export]`` attribute.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. Members with types that can't be marshalled
will result in runtime errors.

View File

@@ -0,0 +1,55 @@
GD0103: The exported member is read-only
========================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0103
**Category** Usage
**Fix is breaking or non-breaking** Non-breaking
**Enabled by default** Yes
==================================== ======================================
Cause
-----
A read-only member is annotated with the ``[Export]`` attribute. Read-only members
can't be exported.
Rule description
----------------
Godot doesn't allow exporting read-only members.
.. code-block:: csharp
// Read-only fields can't be exported.
[Export]
public readonly int invalidField;
// This field can be exported because it's not declared 'readonly'.
[Export]
public int validField;
// Read-only properties can't be exported.
[Export]
public int InvalidProperty { get; }
// This property can be exported because it has both a getter and a setter.
[Export]
public int ValidProperty { get; set; }
How to fix violations
---------------------
To fix a violation of this rule for fields, remove the ``readonly`` keyword or
remove the ``[Export]`` attribute.
To fix a violation of this rule for properties, make sure the property declares
both a getter and a setter, or remove the ``[Export]`` attribute.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. Read-only members can't be exported so
they will be ignored by Godot, resulting in runtime errors.

View File

@@ -0,0 +1,46 @@
GD0104: The exported property is write-only
===========================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0104
**Category** Usage
**Fix is breaking or non-breaking** Non-breaking
**Enabled by default** Yes
==================================== ======================================
Cause
-----
A write-only property is annotated with the ``[Export]`` attribute. Write-only properties
can't be exported.
Rule description
----------------
Godot doesn't allow exporting write-only properties.
.. code-block:: csharp
private int _backingField;
// Write-only properties can't be exported.
[Export]
public int InvalidProperty { set => _backingField = value; }
// This property can be exported because it has both a getter and a setter.
[Export]
public int ValidProperty { get; set; }
How to fix violations
---------------------
To fix a violation of this rule, make sure the property declares
both a getter and a setter, or remove the ``[Export]`` attribute.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. Write-only members can't be exported so
they will be ignored by Godot, resulting in runtime errors.

View File

@@ -0,0 +1,44 @@
GD0105: Attempted to export indexer property
============================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0105
**Category** Usage
**Fix is breaking or non-breaking** Non-breaking
**Enabled by default** Yes
==================================== ======================================
Cause
-----
An indexer is annotated with the ``[Export]`` attribute. Indexers can't be exported.
Rule description
----------------
Godot doesn't allow exporting indexer properties.
.. code-block:: csharp
private int[] _backingField;
// Indexers can't be exported.
[Export]
public int this[int index]
{
get => _backingField[index];
set => _backingField[index] = value;
}
How to fix violations
---------------------
To fix a violation of this rule, remove the ``[Export]`` attribute.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. Indexers can't be exported so
they will be ignored by Godot, resulting in runtime errors.

View File

@@ -0,0 +1,59 @@
GD0106: Attempted to export explicit interface property implementation
======================================================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0106
**Category** Usage
**Fix is breaking or non-breaking** Non-breaking
**Enabled by default** Yes
==================================== ======================================
Cause
-----
An explicit interface property implementation is annotated with the ``[Export]``
attribute. Properties that implement an interface explicitly can't be exported.
Rule description
----------------
Godot doesn't allow exporting explicit interface property implementations.
When an interface member is implemented explicitly, the member is hidden and
consumers can't access them unless the type is converted to the interface first.
Explicitly implemented members can also share the same name of other members in
the type, so it could create naming conflicts with other exported members.
.. code-block:: csharp
public interface MyInterface
{
public int MyProperty { get; set; }
}
public class MyNode1 : Node, MyInterface
{
// The property can be exported because it implements the interface implicitly.
[Export]
public int MyProperty { get; set; }
}
public class MyNode2 : Node, MyInterface
{
// The property can't be exported because it implements the interface explicitly.
[Export]
int MyInterface.MyProperty { get; set; }
}
How to fix violations
---------------------
To fix a violation of this rule, implement the interface implicitly or remove
the ``[Export]`` attribute.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. Explicit interface property implementations
can't be exported so they will be ignored by Godot, resulting in runtime errors.

View File

@@ -0,0 +1,51 @@
GD0201: The name of the delegate must end with 'EventHandler'
=============================================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0201
**Category** Usage
**Fix is breaking or non-breaking** Breaking
**Enabled by default** Yes
==================================== ======================================
Cause
-----
A delegate annotated with the ``[Signal]`` attribute has a name that doesn't
end with 'EventHandler'.
Rule description
----------------
Godot source generators will generate C# events using the name of the delegate
with the 'EventHandler' suffix removed. Adding the 'EventHandler' suffix to the
name of delegates used in events is a `.NET naming convention <https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/names-of-classes-structs-and-interfaces#names-of-common-types>`_.
Using a suffix for the delegate allows the generated event to use the name without
the suffix avoiding a naming conflict.
.. code-block:: csharp
// This delegate is invalid since the name doesn't end with 'EventHandler'.
[Signal]
public void InvalidSignal();
// This delegate is valid since the name ends with 'EventHandler'.
[Signal]
public void ValidSignalEventHandler();
Take a look at the :ref:`C# signals <doc_c_sharp_signals>` documentation for more
information about how to declare and use signals.
How to fix violations
---------------------
To fix a violation of this rule, add 'EventHandler' to the end of the delegate name.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. Signal delegates without the suffix
will be ignored by the source generator, so the signal won't be registered.

View File

@@ -0,0 +1,60 @@
GD0202: The parameter of the delegate signature of the signal is not supported
==============================================================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0202
**Category** Usage
**Fix is breaking or non-breaking** Breaking - If the parameter type is changed
Non-breaking - If the ``[Signal]`` attribute is removed
**Enabled by default** Yes
==================================== ======================================
Cause
-----
An unsupported type is specified for a parameter of a delegate annotated with
the ``[Signal]`` attribute when a :ref:`Variant-compatible <doc_c_sharp_variant>`
type is expected.
Rule description
----------------
Every signal parameter must be Variant-compatible so it can be marshalled when
emitting the signal and invoking the callbacks.
.. code-block:: csharp
class SomeType { }
// SomeType is not a valid parameter type because it doesn't derive from GodotObject,
// so it's not compatible with Variant.
public void InvalidSignalEventHandler(SomeType someType);
// System.Int32 is a valid type because it's compatible with Variant.
public void ValidSignalEventHandler(int someInt);
Take a look at the :ref:`C# signals <doc_c_sharp_signals>` documentation for more
information about how to declare and use signals.
How to fix violations
---------------------
To fix a violation of this rule, change the parameter type to be Variant-compatible
or remove the ``[Signal]`` attribute from the delegate. Note that removing the
attribute will mean the signal is not registered.
.. tip::
If the signal doesn't need to interact with Godot, consider using
`C# events <https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/events/>`_
directly. Pure C# events allow you to use any C# type for its parameters.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. Signal delegates with parameters that
can't be marshalled will result in runtime errors when emitting the signal or
invoking the callbacks.

View File

@@ -0,0 +1,56 @@
GD0203: The delegate signature of the signal must return void
=============================================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0203
**Category** Usage
**Fix is breaking or non-breaking** Breaking - If the return type is changed
Non-breaking - If the ``[Signal]`` attribute is removed
**Enabled by default** Yes
==================================== ======================================
Cause
-----
A delegate annotated with the ``[Signal]`` attribute has a return type when
``void`` was expected.
Rule description
----------------
Every signal must return ``void``. There can be multiple callbacks registered
for each signal, if signal callbacks could return something it wouldn't be
possible to determine which of the returned values to use.
.. code-block:: csharp
// This signal delegate is invalid because it doesn't return void.
public int InvalidSignalEventHandler();
// This signal delegate is valid because it returns void.
public void ValidSignalEventHandler();
Take a look at the :ref:`C# signals <doc_c_sharp_signals>` documentation for more
information about how to declare and use signals.
How to fix violations
---------------------
To fix a violation of this rule, change the delegate to return ``void`` or
remove the ``[Signal]`` attribute from the delegate. Note that removing the
attribute will mean the signal is not registered.
.. tip::
If the signal doesn't need to interact with Godot, consider using
`C# events <https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/events/>`_
directly. Pure C# events allow you to use any C# type for its parameters.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. Signal delegates that return something
will result in unexpected runtime errors.

View File

@@ -0,0 +1,51 @@
GD0301: The generic type argument must be a Variant compatible type
===================================================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0301
**Category** Usage
**Fix is breaking or non-breaking** Breaking
**Enabled by default** Yes
==================================== ======================================
Cause
-----
An unsupported type is specified for a generic type argument when a
:ref:`Variant-compatible <doc_c_sharp_variant>` type is expected.
Rule description
----------------
When a generic type parameter is annotated with the ``[MustBeVariant]`` attribute,
the generic type is required to be a Variant-compatible type. For example,
the generic ``Godot.Collections.Array<T>`` type only supports items of a type
that can be converted to Variant.
.. code-block:: csharp
class SomeType { }
// SomeType is not a valid type because it doesn't derive from GodotObject,
// so it's not compatible with Variant.
var invalidArray = new Godot.Collections.Array<SomeType>();
// System.Int32 is a valid type because it's compatible with Variant.
var validArray = new Godot.Collections.Array<int>();
How to fix violations
---------------------
To fix a violation of this rule, change the generic type argument to be a
Variant-compatible type or use a different API that doesn't require the generic
type argument to be a Variant-compatible type.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. API that contains generic type arguments
annotated with the ``[MustBeVariant]`` attribute usually has this requirement
because the values will be passed to the engine, if the type can't be marshalled
it will result in runtime errors.

View File

@@ -0,0 +1,57 @@
GD0302: The generic type parameter must be annotated with the MustBeVariant attribute
=====================================================================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0302
**Category** Usage
**Fix is breaking or non-breaking** Breaking
**Enabled by default** Yes
==================================== ======================================
Cause
-----
A generic type is specified for a generic type argument when a
:ref:`Variant-compatible <doc_c_sharp_variant>` type is expected, but the
specified generic type is not annotated with the ``[MustBeVariant]`` attribute.
Rule description
----------------
When a generic type parameter is annotated with the ``[MustBeVariant]`` attribute,
the generic type is required to be a Variant-compatible type. When the type used
is also a generic type, this generic type must be annoted with the ``[MustBeVariant]``
attribute as well. For example, the generic ``Godot.Collections.Array<T>`` type
only supports items of a type that can be converted to Variant, a generic type
can be specified if it's properly annotated.
.. code-block:: csharp
public void Method1<T>()
{
// T is not valid here because it may not a Variant-compatible type.
var invalidArray = new Godot.Collections.Array<T>();
}
public void Method2<[MustBeVariant] T>()
{
// T is guaranteed to be a Variant-compatible type because it's annotated
// with the [MustBeVariant] attribute, so it can be used here.
var validArray = new Godot.Collections.Array<T>();
}
How to fix violations
---------------------
To fix a violation of this rule, add the ``[MustBeVariant]`` attribute to the
generic type that is used as a generic type argument that must be Variant-compatible.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. API that contains generic type arguments
annotated with the ``[MustBeVariant]`` attribute usually has this requirement
because the values will be passed to the engine, if the type can't be marshalled
it will result in runtime errors.

View File

@@ -0,0 +1,37 @@
GD0303: Symbol parent of a type argument that must be Variant compatible was not handled
========================================================================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0303
**Category** Usage
**Fix is breaking or non-breaking** Not fixable
**Enabled by default** Yes
==================================== ======================================
Cause
-----
This is a bug in the engine and must be reported.
Rule description
----------------
The ``MustBeVariantAnalyzer`` has found an unhandled case in the user source
code. Please, open an `issue <https://github.com/godotengine/godot/issues>`_
and attach a minimal reproduction project so it can be fixed.
How to fix violations
---------------------
Violations of this rule can't be fixed.
When to suppress warnings
-------------------------
Suppressing a warning from this rule may result in unexpected errors, since the
case found by the analyzer may need to be handled by the user to prevent
types that are not Variant-compatible from reaching the engine. Attempting to
marshal incompatible types will result in runtime errors.

View File

@@ -0,0 +1,55 @@
GD0401: The class must derive from GodotObject or a derived class
=================================================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0401
**Category** Usage
**Fix is breaking or non-breaking** Breaking - If changing the inheritance chain
Non-breaking - If removing the ``[GlobalClass]`` attribute
**Enabled by default** Yes
==================================== ======================================
Cause
-----
A type annotated with the ``[GlobalClass]`` attribute does not derive from
``GodotObject``.
Rule description
----------------
The ``[GlobalClass]`` has no effect for types that don't derive from ``GodotObject``.
Every :ref:`global class <doc_c_sharp_global_classes>` must ultimately derive from
``GodotObject`` so it can be marshalled.
.. code-block:: csharp
// This type is not registered as a global class because it doesn't derive from GodotObject.
[GlobalClass]
class SomeType { }
// This type is a global class because it derives from Godot.Node
// which ultimately derives from GodotObject.
[GlobalClass]
class MyNode : Node { }
// This type is a global class because it derives from Godot.Resource
// which ultimately derives from GodotObject.
[GlobalClass]
class MyResource : Resource { }
How to fix violations
---------------------
To fix a violation of this rule, change the type to derive from ``GodotObject``
or remove the ``[GlobalClass]`` attribute.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. Adding the ``[GlobalClass]`` to a type
that doesn't derive from ``GodotObject`` is an easy mistake to make and this
warning helps users realize that it may result in unexpected errors.

View File

@@ -0,0 +1,46 @@
GD0402: The class must not contain generic arguments
====================================================
==================================== ======================================
Value
==================================== ======================================
**Rule ID** GD0402
**Category** Usage
**Fix is breaking or non-breaking** Breaking
**Enabled by default** Yes
==================================== ======================================
Cause
-----
A generic type is annotated with the ``[GlobalClass]`` attribute.
Rule description
----------------
The Godot editor assumes every :ref:`global class <doc_c_sharp_global_classes>`
is instantiable, but generic types can't be instantiated because the type
arguments are unbound.
.. code-block:: csharp
// This type is a valid global class because it's not generic.
[GlobalClass]
class SomeType : Node { }
// This type is not a valid global class because it's generic.
[GlobalClass]
class SomeGenericType<T> { }
How to fix violations
---------------------
To fix a violation of this rule, change the type to remove the generic type parameters
or remove the ``[GlobalClass]`` attribute.
When to suppress warnings
-------------------------
Do not suppress a warning from this rule. Adding the ``[GlobalClass]`` to a
generic type is an easy mistake to make and this warning helps users realize
that it may result in unexpected errors.

View File

@@ -0,0 +1,29 @@
C# diagnostics
==============
Godot includes analyzers that inspect your C# source code to check for invalid
or unsupported code and let you know that something is wrong during build time.
Rules
-----
.. toctree::
:maxdepth: 1
:name: toc-C#-diagnostics
GD0001
GD0002
GD0101
GD0102
GD0103
GD0104
GD0105
GD0106
GD0201
GD0202
GD0203
GD0301
GD0302
GD0303
GD0401
GD0402

View File

@@ -14,3 +14,4 @@ C#
c_sharp_exports
c_sharp_global_classes
c_sharp_style_guide
diagnostics/index