Code Monkey home page Code Monkey logo

interfacegenerator's Introduction

InterfaceGenerator NuGet Version

A simple source generator that creates interfaces by implementations. Useful for when you need an interface purely for the sake of mocking, or maybe you're not sure if you'll need the abstraction later on.

Inspired by net_automatic_interface

Example user implementation:

[GenerateAutoInterface]
public class SampleService : ISampleService
{
    public double Multiply(double x, double y)
    {
        return x * y;            
    }

    public int NiceNumber => 69;
}

Auto generated interface:

public partial interface ISampleService
{
    double Multiply(double x, double y);
    int NiceNumber { get; }
}

Supports:

  • Methods, properties, indexers.
  • Default arguments, params arguments.
  • Generic types and methods.
  • XML docs.
  • Explicit interface names (using the Name property on GenerateAutoInterface).
  • Explicit interface visibility (using the VisibilityModifier property on GenerateAutoInterface).
  • Explicitly excluding a member from the interface (using [AutoInterfaceIgnore]).

Missing:

  • Events.
  • Nested types.
  • Probably a bunch of edge cases I forgot about.

interfacegenerator's People

Contributors

adamhathcock avatar daver32 avatar edtro-bp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

interfacegenerator's Issues

Help needed: how can get the errors from the analyzer

Hi,
Possibly I have overlooked something, but I need some help getting started to start using this project (because I think the concept is really great).

I have added the Nuget package to a NET6 class library project and added the GenerateAutoInterface attribute to my class, but VS cannot find any reference.

Within the readme an other project net_automatic_interface is mentioned, There you need to add the code for the attribute manually.

Do you also need to do this for this project?

Or is NET6 not supported?

Kr
Edward

Feature Request: Support Records

This library (1.0.5 on net6.0) works perfectly for me, thanks for the great work!

What I stumbled upon using it was, that records are not supported. It may need some fine tuning to properly support them though.

// records don't work at all for now
[InterfaceGenerator.GenerateAutoInterface]
record Record : IRecord
{
    public void Method(){}
}

// I expect it to generate an interface like that:
internal partial interface IRecord
{
    string Property { get; init; }
    void Method();
    void Deconstruct(out string Property);
}
// classes work fine
[InterfaceGenerator.GenerateAutoInterface]
class Class : IClass
{
    public string Property { get; set; }
    public void Method(){}
}

// this generates a proper interface:
internal partial interface IClass
{
    string Property { get; set; }
    void Method();
}

Offer a way to remove things added by being a `record`

We've started using records a lot for services because not having to write out the constructor and all the private readonly fields is convenient.

It would be nice to have the option to exclude those things from the generated interface. Specifically:

  • the Deconstruct method (void Deconstructor(out param1, out param2, ...)
  • any properties that are auto-created from using a positional constructor (they have get + init)

I'm surprised the Equals and GetHashCode methods didn't get included as well, but I'm fine with that.

Generated code doesn't handle default values for enums

We have our own custom set of log events that we keep track of in a database. The severity is stored with a custom LogLevel enum:

public enum LogLevel
{
    Trace = 0,
    Debug = 1,
    Information = 2,
    Warning = 3,
    Error = 4,
    Critical = 5,
    None = 6
}

For the DAL class, we have a method that has this format:
public async Task<IEnumerable<LogMessage>> GetLogsForObject(string objectType, long objectId, LogLevel minLogLevel = LogLevel.Information)

It generates the following interface:

public partial interface ILogMessageRepository
    {
        System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<TSWCloud.Domain.Logging.LogMessage>> GetLogsForObject(string objectType, long objectId, TSWCloud.Domain.Logging.LogLevel minLogLevel = 2);
    }

When compiling, this gives the error:
A value of type 'int' cannot be used as a default parameter because there is no standard conversions to type LogLevel

Instead, it should generate the following interface:

public interface ILogMessageRepository
{
    Task<IEnumerable<LogMessage>> GetLogsForObject(string objectType, long objectId,
        LogLevel minLogLevel = LogLevel.Information);
}

Nullable Annotations should be taken over to the interface.

Curent Behaviour:
For the class

[InterfaceGenerator.GenerateAutoInterface(VisibilityModifier = "public")]
public class AClass : IAClass
{

    [return: NotNullIfNotNull(nameof(content))]
    public byte[]? TheMethod(byte[]? content)
    {
        if (content == null) return content;
        return content;
    }
}

this interface is generated:

public partial interface IAClass
{
    byte[]? TheMethod(byte[]? content);
}

Excpected Interface:

public partial interface IAClass
{
    [return: NotNullIfNotNull(nameof(content))]
    byte[]? TheMethod(byte[]? content);
}

Also other paremeter Attributes should be considered. Eg. MaybeNullWhen() or EnumeratorCancellation.

move to NET6 LTS

probably better to use NET6 instead of netstandard? can netstandard cause any issues moving forward

VisibilityModifier should be an enum

Currently the VisibilityModifier option on the GenerateAutoInterfaceAttribute is of type string. I think it would be better to be able to define this setting using an enum.

Theoretically there could be multiple access modifiers. For example "protected internal:". Therefor the enum should have the [Flags] attribute to be able to define multiple access modifiers or just include all allowed combinations.

Keyword parameter identifiers don't get escaped

Hey,

while testing this source generator with another one I noticed an issue with some generated parameter names.
Methods that use keywords such as long as identifiers don't get properly prefixed with @ in the generated interface.

Example:

public void VoidMethodWithKeywordParam(long @long)

results in:

void VoidMethodWithKeywordParam(long long); // CS1001 Identifier expected

but should be:

void VoidMethodWithKeywordParam(long @long);

This should be the line where param.Name needs to be checked and sometimes prefixed.

writer.Write("{0} {1}", param.Type, param.Name);

e. g. AutoRest is handling these identifiers like this:
1. Writing the identifier.
2. Checking for C# keywords

Generated files are not marked as AutoGenerated

Most of the generated files have this comment on top:
// <auto-generated/>
Then, code analysis tools know to don't show warnings about this code. This library doesn't add this comment and because of that, I have a lot of warnings to GenerateAutoInterfaceAttribute (I don't have any warnings to files with generated interfaces) (some of the warnings are against my configuration, I don't know why).

image

When referencing InterfaceGenerator, build size increases by 17.5 MB

I've noticed that if using InterfaceGenerator, the following libraries appear in the bin folder (17.5 MB size total)

  • Microsoft.CodeAnalysis.dll
  • Microsoft.CodeAnalysis.CSharp.dll
  • Microsoft.CodeAnalysis.CSharp.Workspaces.dll
  • Microsoft.CodeAnalysis.VisualBasic.dll
  • Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll
  • Microsoft.CodeAnalysis.Workspaces.dll

Note that if I use https://github.com/codecentric/net_automatic_interface then these libraries are not referenced, so this must be a bug.

Feature Request: Init only setters

This library seems not to support init only setters from c# 9

how to reproduce

Tested on 1.0.5 on net6.0

Given this code:

[InterfaceGenerator.GenerateAutoInterface]
class Class : IClass
{
    public string Property { get; init; }
}

AutoInterface creates this interface:

internal partial interface IClass
{
    string Property { get; set; }
}

but it should be:

internal partial interface IClass
{
    string Property { get; init; }
}

Keep same nullable context as implementation

If possible, it would great if the nullable context (off, annotations, on) could be set per item on the interface to match whatever has been set on the implementation with #nullable enable and the like.

Right now, if I set something to a nullable reference type, I get a build warning.

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Auto-generated code requires an explicit '#nullable'

Feature request: XML Docs also for the interface

I noticed that XML docs are copied to the interface but only for members. They are not copied to the interface itself. Maybe they should be also copied when XML docs are defined on the class?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.