commandline
commandline copied to clipboard
InvalidCastException in GetUsageData when using nullable reference types
https://github.com/rubberduck203/GitNStats/issues/27
I recently enabled nullable reference types for my application.
Since then, calling my app with the --help
flag has started failing with an unhandled exception.
$ dotnet run --project src/gitnstats/gitnstats.csproj -- --help
Unhandled exception. System.InvalidCastException: Unable to cast object of type 'System.Runtime.CompilerServices.NullableAttribute' to type 'CommandLine.Text.UsageAttribute'.
at CommandLine.Core.ReflectionExtensions.<>c.<GetUsageData>b__2_3(<>f__AnonymousType1`2 <>h__TransparentIdentifier0)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
at CommandLine.Core.ReflectionExtensions.GetUsageData(Type type)
at CommandLine.Text.HelpText.GetUsageFromType(Type type)
at CommandLine.Text.HelpText.RenderUsageTextAsLines[T](ParserResult`1 parserResult, Func`2 mapperFunc)+MoveNext()
at CSharpx.EnumerableExtensions.ToMaybe[T](IEnumerable`1 source)
at CommandLine.Text.HelpText.AutoBuild[T](ParserResult`1 parserResult, Func`2 onError, Func`2 onExample, Boolean verbsIndex, Int32 maxDisplayWidth)
at CommandLine.Text.HelpText.AutoBuild[T](ParserResult`1 parserResult, Func`2 onError, Int32 maxDisplayWidth)
at CommandLine.Text.HelpText.AutoBuild[T](ParserResult`1 parserResult, Int32 maxDisplayWidth)
at CommandLine.Parser.<>c__DisplayClass17_0`1.<DisplayHelp>b__1(IEnumerable`1 _, TextWriter writer)
at CSharpx.MaybeExtensions.Do[T1,T2](Maybe`1 maybe, Action`2 action)
at CommandLine.Parser.<>c__DisplayClass17_0`1.<DisplayHelp>b__0(IEnumerable`1 errors)
at CommandLine.ParserResultExtensions.WithNotParsed[T](ParserResult`1 result, Action`1 action)
at CommandLine.Parser.DisplayHelp[T](ParserResult`1 parserResult, TextWriter helpWriter, Int32 maxDisplayWidth)
at CommandLine.Parser.MakeParserResult[T](ParserResult`1 parserResult, ParserSettings settings)
at CommandLine.Parser.ParseArguments[T](IEnumerable`1 args)
at GitNStats.Program.Main(String[] args) in /Users/rubberduck/src/GitNStats/src/gitnstats/Program.cs:line 11
The invalid cast is occurring in this block of code.
https://github.com/commandlineparser/commandline/blob/d443a51aeb3a418425e970542b3b96e9da5f62e2/src/CommandLine/Core/ReflectionExtensions.cs#L39-L48
I haven't figured out if it's occurring on line 44 or 45 yet, but GetUsageData
seems to be assuming that it will only find a single attribute.
I'll do my best to update this with a minimal reproduction.
Minimal reproduction can be found here: https://github.com/rubberduck203/commandline/commit/90ccab813e6fa5b004ffd4cf601375e32bca6093
In the test project file, enable nullable reference types
This means the tests can not target net461
, so we need a separate test project.
<nullable>enable</nullable>
The options class must have a nullable property, then we need to add custom usage examples in order to trigger the bug.
public class ReflectionExtensionsTests
{
[Fact]
public void GetUsageDataDoesNotExplodeWhenUsedWithNullableReferenceTypesUsingTheUsageAttribute()
{
typeof(NullableReferenceTypeOptions).GetUsageData();
}
}
public class NullableReferenceTypeOptions
{
[Option(HelpText = "Define a string value here.")]
public string? StringValue { get; set; }
[Usage]
public static IEnumerable<Example> Examples
{
get
{
yield return new Example("Run on current directory", new NullableReferenceTypeOptions());
}
}
}
I submitted PR #715 to fix this.
I just experienced this bug. It would be great if it could be resolved. Looking at the pull request that code change will fix the issue.
I've experienced that issue too and it would be great if we can have a release of the fix !
Still experiencing this same issue.
The last commit to this repo was several months before I submitted the bug report & PR in 2020.
@ericnewton76 any chance a fix for this could be merged, possibly the open PR? We have run into the same issue with nullable options lately, and would very much prefer not to introduce workarounds.
As a workaround you can wrap the offending property in a #nullable disable
/#nullable restore
pair