Skip to content

Commit 809f8f2

Browse files
authored
bugfix: added check on the model type before it proceeds accessing the property (#519)
Addresses #518.
1 parent f5afce9 commit 809f8f2

File tree

2 files changed

+62
-15
lines changed

2 files changed

+62
-15
lines changed

src/CommandLineUtils/Conventions/ArgumentAttributeConvention.cs

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -150,26 +150,30 @@ private void AddArgument(PropertyInfo prop,
150150

151151
if (r.SelectedCommand is IModelAccessor cmd)
152152
{
153-
if (argument.Values.Count == 0)
153+
var model = cmd.GetModel();
154+
if (prop.DeclaringType.IsAssignableFrom(model.GetType()))
154155
{
155-
if (!ReflectionHelper.IsSpecialValueTupleType(prop.PropertyType, out _))
156+
if (argument.Values.Count == 0)
156157
{
157-
var value = getter.Invoke(cmd.GetModel());
158-
if (value != null)
158+
if (!ReflectionHelper.IsSpecialValueTupleType(prop.PropertyType, out _))
159159
{
160-
argument.TryParse(value.ToString());
161-
argument.DefaultValue = value.ToString();
160+
var value = getter.Invoke(model);
161+
if (value != null)
162+
{
163+
argument.TryParse(value.ToString());
164+
argument.DefaultValue = value.ToString();
165+
}
162166
}
163167
}
164-
}
165-
else
166-
{
167-
setter.Invoke(
168-
cmd.GetModel(),
169-
parser.Parse(
170-
argument.Name,
171-
argument.Value,
172-
convention.Application.ValueParsers.ParseCulture));
168+
else
169+
{
170+
setter.Invoke(
171+
model,
172+
parser.Parse(
173+
argument.Name,
174+
argument.Value,
175+
convention.Application.ValueParsers.ParseCulture));
176+
}
173177
}
174178
}
175179
});

test/CommandLineUtils.Tests/ArgumentAttributeTests.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using System.Linq;
56
using Xunit;
67
using Xunit.Abstractions;
78

@@ -94,5 +95,47 @@ public void KeepsDefaultValues()
9495
Assert.Equal("a", app3.Model.Arg1);
9596
Assert.Equal(new[] { "b", "c" }, app3.Model.Arg2);
9697
}
98+
99+
[Subcommand(typeof(ACommand))]
100+
public class Program
101+
{
102+
}
103+
104+
[Command("a")]
105+
[Subcommand(typeof(BCommand))]
106+
public class ACommand
107+
{
108+
[Argument(0)]
109+
public string? Arg1 { get; set; }
110+
}
111+
112+
[Command("b")]
113+
public class BCommand
114+
{
115+
[Argument(0)]
116+
public string? Arg1 { get; set; }
117+
}
118+
119+
[Fact]
120+
public void SameArgumentInSubcommandsCallingACommand()
121+
{
122+
var app1 = new CommandLineApplication<Program>();
123+
app1.Conventions.UseDefaultConventions();
124+
var result = app1.Parse("a", "any-value");
125+
var command = result.SelectedCommand as CommandLineApplication<ACommand>;
126+
Assert.NotNull(command);
127+
Assert.Equal("any-value", command.Model.Arg1);
128+
}
129+
130+
[Fact]
131+
public void SameArgumentInSubcommandsCallingBCommand()
132+
{
133+
var app1 = new CommandLineApplication<Program>();
134+
app1.Conventions.UseDefaultConventions();
135+
var result = app1.Parse("a", "b", "any-value");
136+
var command = result.SelectedCommand as CommandLineApplication<BCommand>;
137+
Assert.NotNull(command);
138+
Assert.Equal("any-value", command.Model.Arg1);
139+
}
97140
}
98141
}

0 commit comments

Comments
 (0)