From 91bc14c3ffd96f3f024d5be7b850c3e85ec8dd3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Luthi?= Date: Wed, 7 Aug 2019 12:16:12 +0200 Subject: [PATCH 1/2] Fix NullReferenceException when creating a default immutable instance --- src/CommandLine/Infrastructure/ReflectionHelper.cs | 5 +++++ tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/src/CommandLine/Infrastructure/ReflectionHelper.cs b/src/CommandLine/Infrastructure/ReflectionHelper.cs index a7926cb7..1373b2b3 100644 --- a/src/CommandLine/Infrastructure/ReflectionHelper.cs +++ b/src/CommandLine/Infrastructure/ReflectionHelper.cs @@ -91,6 +91,11 @@ public static T CreateDefaultImmutableInstance(Type[] constructorTypes) public static object CreateDefaultImmutableInstance(Type type, Type[] constructorTypes) { var ctor = type.GetTypeInfo().GetConstructor(constructorTypes); + if (ctor == null) + { + throw new InvalidOperationException($"Type appears to be immutable, but no constructor found for type {type.FullName} to accept values."); + } + var values = (from prms in ctor.GetParameters() select prms.ParameterType.CreateDefaultForImmutable()).ToArray(); return ctor.Invoke(values); diff --git a/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs b/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs index c6234089..59fcf9cc 100644 --- a/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs +++ b/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs @@ -1158,6 +1158,14 @@ public void OptionClass_IsImmutable_HasNoCtor() act.Should().Throw(); } + [Fact] + public void OptionClass_IsImmutable_HasNoCtor_HelpRequested() + { + Action act = () => InvokeBuild(new string[] { "--help" }); + + act.Should().Throw(); + } + private class ValueWithNoSetterOptions { [Value(0, MetaName = "Test", Default = 0)] From d6333553baeda33cb20cf719955416e113d7e0b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Luthi?= Date: Wed, 7 Aug 2019 12:22:45 +0200 Subject: [PATCH 2/2] Improve exception message when immutable type can't be created --- src/CommandLine/Core/InstanceBuilder.cs | 2 +- src/CommandLine/Infrastructure/ReflectionHelper.cs | 2 +- tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/CommandLine/Core/InstanceBuilder.cs b/src/CommandLine/Core/InstanceBuilder.cs index a1fdd9f2..5ea056d8 100644 --- a/src/CommandLine/Core/InstanceBuilder.cs +++ b/src/CommandLine/Core/InstanceBuilder.cs @@ -167,7 +167,7 @@ private static T BuildImmutable(Type typeInfo, Maybe> factory, IEnume if(ctor == null) { - throw new InvalidOperationException($"Type appears to be immutable, but no constructor found for type {typeInfo.FullName} to accept values."); + throw new InvalidOperationException($"Type {typeInfo.FullName} appears to be immutable, but no constructor found to accept values."); } var values = diff --git a/src/CommandLine/Infrastructure/ReflectionHelper.cs b/src/CommandLine/Infrastructure/ReflectionHelper.cs index 1373b2b3..47fe70ea 100644 --- a/src/CommandLine/Infrastructure/ReflectionHelper.cs +++ b/src/CommandLine/Infrastructure/ReflectionHelper.cs @@ -93,7 +93,7 @@ public static object CreateDefaultImmutableInstance(Type type, Type[] constructo var ctor = type.GetTypeInfo().GetConstructor(constructorTypes); if (ctor == null) { - throw new InvalidOperationException($"Type appears to be immutable, but no constructor found for type {type.FullName} to accept values."); + throw new InvalidOperationException($"Type {type.FullName} appears to be immutable, but no constructor found to accept values."); } var values = (from prms in ctor.GetParameters() diff --git a/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs b/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs index 59fcf9cc..bb88595e 100644 --- a/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs +++ b/tests/CommandLine.Tests/Unit/Core/InstanceBuilderTests.cs @@ -1155,7 +1155,8 @@ public void OptionClass_IsImmutable_HasNoCtor() { Action act = () => InvokeBuild(new string[] { "Test" }, false, false); - act.Should().Throw(); + act.Should().Throw() + .Which.Message.Should().Be("Type CommandLine.Tests.Unit.Core.InstanceBuilderTests+ValueWithNoSetterOptions appears to be immutable, but no constructor found to accept values."); } [Fact] @@ -1163,7 +1164,8 @@ public void OptionClass_IsImmutable_HasNoCtor_HelpRequested() { Action act = () => InvokeBuild(new string[] { "--help" }); - act.Should().Throw(); + act.Should().Throw() + .Which.Message.Should().Be("Type CommandLine.Tests.Unit.Core.InstanceBuilderTests+ValueWithNoSetterOptions appears to be immutable, but no constructor found to accept values."); } private class ValueWithNoSetterOptions