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

Missing required values on immutable targets causes exception #115

Closed
ericnewton76 opened this issue Nov 4, 2017 · 1 comment
Closed

Comments

@ericnewton76
Copy link
Member

Issue by altearius
Thursday Mar 02, 2017 at 13:36 GMT
Originally opened as gsscoder/commandline#419


I am using CommandLineParser 2.1.1-beta.

Suppose you have two immutable options classes, one of which defines some required values:

[Verb("create", HelpText = "Create a new migration.")]
public class CreateMigrationOptions
{
	public CreateMigrationOptions(string name)
	{
		Name = name;
	}

	[Value(0, HelpText = "The optional name of the migration to create.")]
	public string Name { get; }
}

[Verb("add", HelpText = "Add a new script to a migration.")]
public class AddScriptOptions
{
	public AddScriptOptions(string migration, string script)
	{
		Migration = migration;
		Script = script;
	}

	[Value(0, Required = true, HelpText = "The name of the migration to modify.")]
	public string Migration { get; }

	[Value(1, Required = true, HelpText = "The name of the script to add.")]
	public string Script { get; }
}

When parsing command line arguments that invoke the second verb, but without the required options, a ParameterCountMismatch exception is thrown:

var parsed = Parser.Default
	.ParseArguments<
		CreateMigrationOptions,
		AddScriptOptions>(new[] { "add" });

Here is the stack trace:

System.Reflection.TargetParameterCountException: Parameter count mismatch.
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at CommandLine.Core.InstanceBuilder.<>c__DisplayClass0_2`1.<Build>b__23()
   at CommandLine.Core.InstanceBuilder.<>c__DisplayClass0_0`1.<Build>b__7()
   at CommandLine.Core.InstanceBuilder.Build[T](Maybe`1 factory, Func`3 tokenizer, IEnumerable`1 arguments, StringComparer nameComparer, Boolean ignoreValueCase, CultureInfo parsingCulture, IEnumerable`1 nonFatalErrors)
   at CommandLine.Core.InstanceChooser.MatchVerb(Func`3 tokenizer, IEnumerable`1 verbs, IEnumerable`1 arguments, StringComparer nameComparer, CultureInfo parsingCulture, IEnumerable`1 nonFatalErrors)
   at CommandLine.Core.InstanceChooser.<>c__DisplayClass0_0.<Choose>b__0()
   at CommandLine.Core.InstanceChooser.Choose(Func`3 tokenizer, IEnumerable`1 types, IEnumerable`1 arguments, StringComparer nameComparer, CultureInfo parsingCulture, IEnumerable`1 nonFatalErrors)
   at CommandLine.Parser.ParseArguments(IEnumerable`1 args, Type[] types)
   at CommandLine.ParserExtensions.ParseArguments[T1,T2,T3,T4,T5,T6,T7](Parser parser, IEnumerable`1 args)
   at Snorri.Program.ExecuteCommands(IResolutionRoot kernel, IEnumerable`1 args) in e:\Users\niels\Documents\Visual Studio 2015\Projects\Snorri\src\Snorri\Program.cs:line 78
   at Snorri.Program.<>c__DisplayClass1_0.<Main>b__0(IKernel kernel) in e:\Users\niels\Documents\Visual Studio 2015\Projects\Snorri\src\Snorri\Program.cs:line 28
   at Snorri.Program.WithDependencies(Action`1 executeCommands) in e:\Users\niels\Documents\Visual Studio 2015\Projects\Snorri\src\Snorri\Program.cs:line 127
   at Snorri.Program.Main(String[] args) in e:\Users\niels\Documents\Visual Studio 2015\Projects\Snorri\src\Snorri\Program.cs:line 28

If you change the AddScriptOptions to no longer be immutable, or if you remove the CreateMigrationOptions class from the call to ParseArguments, then there is no exception thrown, and the parsed.Errors enumerable is populated (correctly noting that a required value was missing).

Thus, throwing an exception in this case feels like it may be a bug.

@pic-Nick
Copy link
Contributor

I have simpler reproduction of this issue. The following code throws System.Reflection.TargetParameterCountException: Parameter count mismatch. exception in Main when run without parameters.

using System;
using System.Collections.Generic;
using CommandLine;

namespace CommandLineTest {
  static class Program {
    [STAThread]
    static void Main(string[] args) {
        var result = Parser.Default.ParseArguments<Options>(args); // <-- Exception
    }
  }

  internal class Options {
    [Value(0, Required = true)]
    public string ScriptName { get; }

    [Value(1)]
    public IEnumerable<string> ScriptParams { get; }

    public Options(string scriptName, IEnumerable<string> scriptParams) {
      this.ScriptName = scriptName;
      this.ScriptParams = scriptParams;
    }
  }
}

Stacktrace:

at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at CommandLine.Core.InstanceBuilder.<>c__DisplayClass0_2`1.<Build>b__24()
at CommandLine.Core.InstanceBuilder.<>c__DisplayClass0_0`1.<Build>b__7()
at CommandLine.Core.InstanceBuilder.Build[T](Maybe`1 factory, Func`3 tokenizer, IEnumerable`1 arguments, StringComparer nameComparer, Boolean ignoreValueCase, CultureInfo parsingCulture, IEnumerable`1 nonFatalErrors)
at CommandLine.Parser.ParseArguments[T](IEnumerable`1 args)

If change Options class to mutable or remove option ScriptParams, exception disappears and help screen shows.

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

No branches or pull requests

2 participants