Skip to content

kkkmail/require-named-args-fs

Repository files navigation

require-named-args-fs

This is a clone of https://github.com/mykolav/require-named-args-fs with attempt to fix extension method calls.

Require a method to be invoked with named arguments

Motivation

1. There seems to be a certain level of interest in having a way to force named arguments in C#

In simpler cases, it's possible to reduce code repetition if you can require named parameters.
For example, let's take a code snippet from the blog post and simplify it:

Here's the original code:

public class AddressDTOBuilder
{
    private AddressDTO _entity = new Address;
    public AddressBuilder Id(int id)
    {
        _entity.Id = id;
        return this;
    }

    public AddressBuilder Line1(string line1)
    {
        _entity.Line1 = line1;
        return this;
    }

    // some methods omitted

    public AddressBuilder AttentionTo(string attn)
    {
        _entity.AttentionTo = attn;
        return this;
    }

    // more methods omitted

    public AddressDTO Build()
    {
        return _entity;
    }

    // This approach allows easy modification of test values
    // Another approach would just have a static method returning AddressDTO
    public AddressBuilder WithTestValues()
    {
        _entity = new AddressDTO
        {
            Line1 = "12345 Test Street",
            Line2 = "3rd Floor",
            Line3 = "Suite 300",
            AttentionTo = "Test Person",
            City = "Test City",
            State = "OH",
            ZipCode = "43210",
            Country = "US",
            Description = "Test Description",
            Id = Constants.TEST_ADDRESS_ID
        }
    }
}

And a simplified version:

public class TestAddressDTOBuilder
{
    [RequireNamedArgs]
    public AddressDTO BuildWith(
        string line1 = null,
        string line2 = null,
        string line3 = null,
        string attentionTo = null,
        string city = null,
        string state = null,
        string zipCode = null,
        string country = null,
        string description = null,
        Guid? id = null)
    {
        var addressDto = new AddressDTO
        {
            Line1 = line1 ?? "12345 Test Street",
            Line2 = line2 ?? "3rd Floor",
            Line3 = line3 ?? "Suite 300",
            AttentionTo = attentionTo ?? "Test Person",
            City = city ?? "Test City",
            State = state ?? "OH",
            ZipCode = zipCode ?? "43210",
            Country = country ?? "US",
            Description = description ?? "Test Description",
            Id = id ?? Constants.TEST_ADDRESS_ID
        };

        return addressDto;
    }
}

Using the [RequireNamedArgs] attribute in the above code sample is important as it makes sure a call to BuildWith uses named arguments.

So something like this is OK:

var testAddressDtoBuilder = new TestAddressDTOBuilder();
// some code skipped...
var addressDto = testAddressDtoBuilder.BuildWith(line3: "Suite 500", state: "WA");

But the analyzer will not allow the code sample below to compile:

var testAddressDtoBuilder = new TestAddressDTOBuilder();
// some code skipped...
var addressDto = testAddressDtoBuilder.BuildWith("54321 Another test street", "9th Floor");

Download and install

Install the RequireNamedArgs nuget package. For example, run the following command in the NuGet Package Manager Console.

Install-Package RequireNamedArgs

This will download all the binaries, and add necessary analyzer references to your project.

How to use it?

  1. Install the nuget package.
  2. Introduce RequireNamedArgsAttribute attribute to your solution.
    I. e., create your own
    [AttributeUsage(AttributeTargets.Method)]
    public class RequireNamedArgsAttribute : Attribute { }
  3. Mark methods which should only be invoked with named arguments with a [RequireNamedArgs] attribute.

For example:

[RequireNamedArgs]
public static void TellPowerLevel(string name, int powerLevel) {}

// Elsewhere in your code:
// if `TellPowerLevel` method is called with positional arguments,
// the analyzer will emit an error.
TellPowerLevel(name: "Goku", powerLevel: 9001);

How does it work?

  1. This analyzer looks at an invocation expression (e.g., a method call).
  2. It then finds the method's definition.
  3. If the definition is marked with a [RequireNamedArgs] attribute,
    the analyzer requires every caller to provide names for the invocation's arguments.
  4. If the last parameter is params, the analyzer
    doesn't emit the diagnostic, as C# doesn't allow named arguments in this case.

The RequireNamedArgs analyzer in action

Technical details

The analyzer, code-fix provider, and tests are implemented in F#

Thank you!

License

The RequireNamedArgs analyzer and code-fix provider are licensed under the MIT license.
So they can be used freely in commercial applications.

About

This is a clone of https://github.com/mykolav/require-named-args-fs with attempt to fix extension method calls.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published