Skip to content

[Instantiable]: Add generated interface implementations for generic constraints purposes. #202

Description

@willnationsdev

I can use the InstantiableAttribute to define various static New() methods for types. However, if I want to write a generic method that takes advantage of these static New() methods, I'd have to provide my own means of doing so.

For example:

public interface INewable;

public interface INewable<T> : INewable
{
    abstract static T New();
}

Then, if people want to customize the names, (which could cause conflicts with other implementing partial declarations), we can just allow the user to override the generated interface name. For example:

// Sample declaration with custom names.
[Instantiable("Init", "CreateFromMilliseconds", GeneratedInterfaceType = "IGodotTemporal"]
public partial class Clock : Control
{
    public void Init(int milliseconds);
}

// Resulting generated interfaces (which `Namespace.Clock.g.cs` would now auto-implement for me).
public interface IGodotTemporal;

public interface IGodotTemporal<T> : IGodotTemporal
{
    void Init(int milliseconds);
    abstract static T CreateFromMilliseconds(int milliseconds);
}

// Usage
var clock = Clock.CreateFromMilliseconds(2000);

To implement this feature, we'd need to...

  1. Add the property to the InstantiableAttribute.
  2. Extract the value from each one by parsing the attribute text.
  3. De-duplicate the type names and consolidate which methods would need to be part of each interface.
  4. Ensure the interfaces are added to the RegisterPostInitialiationOutput for the source generator.
    • Or, alternatively, check if such a type has already been defined by a referenced assembly (e.g. if the user purposefully wants to isolate the abstractions from the main project for tests or use in other class libraries, etc.).
    • Or, alternatively, an assembly attribute could "remap" the would-be generated interface to instead use an existing type declaration from a referenced assembly. Something like, [assembly: RemapInstantiableInterface("IGodotTemporal", "MyClassLib.TimeStuff.IGodotTemporal")].
  5. The existing generated source would need to be updated to include the interface in its BaseListSyntax.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions