Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle custom type converters #197

Closed
mikkelbu opened this issue Apr 9, 2020 · 3 comments · Fixed by #269
Closed

Handle custom type converters #197

mikkelbu opened this issue Apr 9, 2020 · 3 comments · Fixed by #269
Assignees
Milestone

Comments

@mikkelbu
Copy link
Member

mikkelbu commented Apr 9, 2020

We should be able to handle custom type converters.

Suggestions from Gitter: https://gitter.im/GuOrg/Gu.Roslyn.Asserts?at=5e7935aa2e334e1b7aefffa0

One heuristic you could use is to assume that the presence of a type converter for a type means that the type converter can convert from string. That is not a guarantee but it's such a mainline scenario.
...
So that would be a search in the custom attributes on the targetType ITypeSymbol
For a custom attribute with whatever the full type name of TypeConverterAttribute is
And that's when argumentType is System.String

@jnm2
Copy link
Contributor

jnm2 commented May 6, 2020

(moved from accidental duplicate #232)

A warning should not be produced. The analyzer can see that CustomType has [TypeConverter(typeof(CustomTypeConverter))] even though it can't run it. It's a safe assumption that type converters can convert from string. Even without that assumption (say, with an int test parameter), the warning message is making a claim that it can't prove.

using System;
using System.ComponentModel;
using System.Globalization;
using NUnit.Framework;

class C
{
    // NUnit1001 The value of the argument at position '0' of type string cannot be assigned to
    // the argument 'customType' of type CustomType.
    //        ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
    [TestCase("String representation")]
    public void M(CustomType customType)
    {
    }
}

[TypeConverter(typeof(CustomTypeConverter))]
struct CustomType
{
    public CustomType(string value)
    {
        Value = value;
    }

    public string Value { get; }

    private sealed class CustomTypeConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            return value is string str
                ? new CustomType(str)
                : base.ConvertFrom(context, culture, value);
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return destinationType == typeof(string) || base.CanConvertTo(context, destinationType);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            return destinationType == typeof(string)
                ? value.ToString()
                : base.ConvertTo(context, culture, value, destinationType);
        }
    }
}

@jnm2
Copy link
Contributor

jnm2 commented Jul 26, 2020

@mikkelbu Can I contribute this one if no one is working on it?

@mikkelbu
Copy link
Member Author

Sure Joseph, you are most welcome to solve this issue. I'll assign it to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants