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

Update System.CommandLine version #84229

Merged
merged 6 commits into from
Jun 30, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions eng/Version.Details.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,9 @@
<Uri>https://github.com/dotnet/llvm-project</Uri>
<Sha>76f334f354eb653a7b409a5319b591ea09df5a43</Sha>
</Dependency>
<Dependency Name="System.CommandLine" Version="2.0.0-beta4.22564.1">
<Dependency Name="System.CommandLine" Version="2.0.0-beta4.23307.1">
<Uri>https://github.com/dotnet/command-line-api</Uri>
<Sha>8374d5fca634a93458c84414b1604c12f765d1ab</Sha>
<Sha>02fe27cd6a9b001c8feb7938e6ef4b3799745759</Sha>
</Dependency>
<Dependency Name="Microsoft.SourceBuild.Intermediate.command-line-api" Version="0.1.356401">
<Uri>https://github.com/dotnet/command-line-api</Uri>
Expand Down
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@
<optimizationPGOCoreCLRVersion>1.0.0-prerelease.23303.6</optimizationPGOCoreCLRVersion>
<!-- Not auto-updated. -->
<MicrosoftDiaSymReaderNativeVersion>16.11.23-beta1.23063.1</MicrosoftDiaSymReaderNativeVersion>
<SystemCommandLineVersion>2.0.0-beta4.22564.1</SystemCommandLineVersion>
<SystemCommandLineVersion>2.0.0-beta4.23307.1</SystemCommandLineVersion>
<TraceEventVersion>3.0.3</TraceEventVersion>
<NETStandardLibraryRefVersion>2.1.0</NETStandardLibraryRefVersion>
<NetStandardLibraryVersion>2.0.3</NetStandardLibraryVersion>
Expand Down
49 changes: 39 additions & 10 deletions src/coreclr/tools/Common/CommandLineHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.CommandLine.Help;
using System.Collections.Generic;
using System.CommandLine.Binding;
using System.CommandLine.Parsing;
using System.IO;
using System.IO.Compression;
Expand All @@ -24,23 +24,23 @@ internal static partial class Helpers
{
public const string DefaultSystemModule = "System.Private.CoreLib";

public static Dictionary<string, string> BuildPathDictionary(IReadOnlyList<Token> tokens, bool strict)
public static Dictionary<string, string> BuildPathDictionary(IReadOnlyList<CliToken> tokens, bool strict)
{
Dictionary<string, string> dictionary = new(StringComparer.OrdinalIgnoreCase);

foreach (Token token in tokens)
foreach (CliToken token in tokens)
{
AppendExpandedPaths(dictionary, token.Value, strict);
}

return dictionary;
}

public static List<string> BuildPathList(IReadOnlyList<Token> tokens)
public static List<string> BuildPathList(IReadOnlyList<CliToken> tokens)
{
List<string> paths = new();
Dictionary<string, string> dictionary = new(StringComparer.OrdinalIgnoreCase);
foreach (Token token in tokens)
foreach (CliToken token in tokens)
{
AppendExpandedPaths(dictionary, token.Value, false);
foreach (string file in dictionary.Values)
Expand Down Expand Up @@ -113,6 +113,36 @@ public static TargetArchitecture GetTargetArchitecture(string token)
}
}

public static CliRootCommand UseVersion(this CliRootCommand command)
{
for (int i = 0; i < command.Options.Count; i++)
{
if (command.Options[i] is VersionOption)
{
command.Options[i] = new VersionOption("--version", "-v");
break;
}
}

return command;
}

public static CliRootCommand UseExtendedHelp(this CliRootCommand command, Func<HelpContext, IEnumerable<Action<HelpContext>>> customizer)
{
foreach (CliOption option in command.Options)
{
if (option is HelpOption helpOption)
{
HelpBuilder builder = new();
builder.CustomizeLayout(customizer);
helpOption.Action = new HelpAction { Builder = builder };
break;
}
}

return command;
}

public static void MakeReproPackage(string makeReproPath, string outputFilePath, string[] args, ParseResult res, IEnumerable<string> inputOptions, IEnumerable<string> outputOptions = null)
{
Directory.CreateDirectory(makeReproPath);
Expand Down Expand Up @@ -177,16 +207,15 @@ public static void MakeReproPackage(string makeReproPath, string outputFilePath,
Dictionary<string, string> outputToReproPackageFileName = new();

List<string> rspFile = new List<string>();
foreach (var option in res.CommandResult.Command.Options)
foreach (CliOption<object> option in res.CommandResult.Command.Options)
adamsitnik marked this conversation as resolved.
Show resolved Hide resolved
{
if (!res.HasOption(option) || option.Name == "make-repro-path")
if (res.GetResult(option) == null || option.Name == "make-repro-path")
{
continue;
}

IValueDescriptor descriptor = option;
object val = res.CommandResult.GetValue(option);
if (val is not null && !(descriptor.HasDefaultValue && descriptor.GetDefaultValue().Equals(val)))
if (val is not null)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adamsitnik, this was the functionality compromise. I couldn't find a way to obtain the default value of CliOption.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@am11 thank you for your feedback! I've opened dotnet/command-line-api#2218 to address that.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a new release with that change? From latest build: https://dev.azure.com/dnceng-public/public/_build/results?buildId=303826&view=results

{
if (val is IEnumerable<string> || val is IDictionary<string, string>)
{
Expand Down Expand Up @@ -234,7 +263,7 @@ public static void MakeReproPackage(string makeReproPath, string outputFilePath,
}
}

foreach (var argument in res.CommandResult.Command.Arguments)
foreach (CliArgument<object> argument in res.CommandResult.Command.Arguments)
{
object val = res.CommandResult.GetValue(argument);
if (val is IEnumerable<string> || val is IDictionary<string, string>)
Expand Down
90 changes: 45 additions & 45 deletions src/coreclr/tools/ILVerify/ILVerifyRootCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,61 +8,61 @@

namespace ILVerify
{
internal sealed class ILVerifyRootCommand : RootCommand
internal sealed class ILVerifyRootCommand : CliRootCommand
{
public Argument<Dictionary<string, string>> InputFilePath { get; } =
new("input-file-path", result => Helpers.BuildPathDictionary(result.Tokens, true), false, "Input file(s)") { Arity = ArgumentArity.OneOrMore };
public Option<Dictionary<string, string>> Reference { get; } =
new(new[] { "--reference", "-r" }, result => Helpers.BuildPathDictionary(result.Tokens, false), false, "Reference metadata from the specified assembly");
public Option<string> SystemModule { get; } =
new(new[] { "--system-module", "-s" }, "System module name (default: mscorlib)");
public Option<bool> SanityChecks { get; } =
new(new[] { "--sanity-checks", "-c" }, "Check for valid constructs that are likely mistakes");
public Option<string[]> Include { get; } =
new(new[] { "--include", "-i" }, "Use only methods/types/namespaces, which match the given regular expression(s)");
public Option<FileInfo> IncludeFile { get; } =
new Option<FileInfo>(new[] { "--include-file" }, "Same as --include, but the regular expression(s) are declared line by line in the specified file.").AcceptExistingOnly();
public Option<string[]> Exclude { get; } =
new(new[] { "--exclude", "-e" }, "Skip methods/types/namespaces, which match the given regular expression(s)");
public Option<FileInfo> ExcludeFile { get; } =
new Option<FileInfo>(new[] { "--exclude-file" }, "Same as --exclude, but the regular expression(s) are declared line by line in the specified file.").AcceptExistingOnly();
public Option<string[]> IgnoreError { get; } =
new(new[] { "--ignore-error", "-g" }, "Ignore errors, which match the given regular expression(s)");
public Option<FileInfo> IgnoreErrorFile { get; } =
new Option<FileInfo>(new[] { "--ignore-error-file" }, "Same as --ignore-error, but the regular expression(s) are declared line by line in the specified file.").AcceptExistingOnly();
public Option<bool> Statistics { get; } =
new(new[] { "--statistics" }, "Print verification statistics");
public Option<bool> Verbose { get; } =
new(new[] { "--verbose" }, "Verbose output");
public Option<bool> Tokens { get; } =
new(new[] { "--tokens", "-t" }, "Include metadata tokens in error messages");
public CliArgument<Dictionary<string, string>> InputFilePath { get; } =
new("input-file-path") { CustomParser = result => Helpers.BuildPathDictionary(result.Tokens, true), Description = "Input file(s)", Arity = ArgumentArity.OneOrMore };
public CliOption<Dictionary<string, string>> Reference { get; } =
new("--reference", "-r") { CustomParser = result => Helpers.BuildPathDictionary(result.Tokens, false), Description = "Reference metadata from the specified assembly" };
public CliOption<string> SystemModule { get; } =
new("--system-module", "-s") { Description = "System module name (default: mscorlib)" };
public CliOption<bool> SanityChecks { get; } =
new("--sanity-checks", "-c") { Description = "Check for valid constructs that are likely mistakes" };
public CliOption<string[]> Include { get; } =
new("--include", "-i") { Description = "Use only methods/types/namespaces, which match the given regular expression(s)" };
public CliOption<FileInfo> IncludeFile { get; } =
new CliOption<FileInfo>("--include-file") { Description = "Same as --include, but the regular expression(s) are declared line by line in the specified file." }.AcceptExistingOnly();
public CliOption<string[]> Exclude { get; } =
new("--exclude", "-e") { Description = "Skip methods/types/namespaces, which match the given regular expression(s)" };
public CliOption<FileInfo> ExcludeFile { get; } =
new CliOption<FileInfo>("--exclude-file") { Description = "Same as --exclude, but the regular expression(s) are declared line by line in the specified file." }.AcceptExistingOnly();
public CliOption<string[]> IgnoreError { get; } =
new("--ignore-error", "-g") { Description = "Ignore errors, which match the given regular expression(s)" };
public CliOption<FileInfo> IgnoreErrorFile { get; } =
new CliOption<FileInfo>("--ignore-error-file") { Description = "Same as --ignore-error, but the regular expression(s) are declared line by line in the specified file." }.AcceptExistingOnly();
public CliOption<bool> Statistics { get; } =
new("--statistics") { Description = "Print verification statistics" };
public CliOption<bool> Verbose { get; } =
new("--verbose") { Description = "Verbose output" };
public CliOption<bool> Tokens { get; } =
new("--tokens", "-t") { Description = "Include metadata tokens in error messages" };

public ParseResult Result;

public ILVerifyRootCommand()
: base("Tool for verifying MSIL code based on ECMA-335.")
{
AddArgument(InputFilePath);
AddOption(Reference);
AddOption(SystemModule);
AddOption(SanityChecks);
AddOption(Include);
AddOption(IncludeFile);
AddOption(Exclude);
AddOption(ExcludeFile);
AddOption(IgnoreError);
AddOption(IgnoreErrorFile);
AddOption(Statistics);
AddOption(Verbose);
AddOption(Tokens);
Arguments.Add(InputFilePath);
Options.Add(Reference);
Options.Add(SystemModule);
Options.Add(SanityChecks);
Options.Add(Include);
Options.Add(IncludeFile);
Options.Add(Exclude);
Options.Add(ExcludeFile);
Options.Add(IgnoreError);
Options.Add(IgnoreErrorFile);
Options.Add(Statistics);
Options.Add(Verbose);
Options.Add(Tokens);

this.SetHandler(context =>
this.SetAction(result =>
{
Result = context.ParseResult;
Result = result;

try
{
context.ExitCode = new Program(this).Run();
return new Program(this).Run();
}
catch (Exception e)
{
Expand All @@ -73,9 +73,9 @@ public ILVerifyRootCommand()
Console.Error.WriteLine(e.ToString());

Console.ResetColor();

context.ExitCode = 1;
}

return 1;
});
}
}
Expand Down
16 changes: 7 additions & 9 deletions src/coreclr/tools/ILVerify/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -450,16 +450,14 @@ public PEReader Resolve(string simpleName)
return null;
}

private T Get<T>(Option<T> option) => _command.Result.GetValue(option);
private T Get<T>(Argument<T> argument) => _command.Result.GetValue(argument);
private T Get<T>(CliOption<T> option) => _command.Result.GetValue(option);
private T Get<T>(CliArgument<T> argument) => _command.Result.GetValue(argument);

private static int Main(string[] args) =>
new CommandLineBuilder(new ILVerifyRootCommand())
.UseTokenReplacer(Helpers.TryReadResponseFile)
.UseVersionOption("--version", "-v")
.UseHelp()
.UseParseErrorReporting()
.Build()
.Invoke(args);
new CliConfiguration(new ILVerifyRootCommand().UseVersion())
{
ResponseFileTokenReplacer = Helpers.TryReadResponseFile,
EnableParseErrorReporting = true
}.Invoke(args);
}
}
36 changes: 14 additions & 22 deletions src/coreclr/tools/InjectResource/Program.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,21 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.CommandLine;
using System.IO;

var binOption = new Option<FileInfo>(
name: "--bin",
description: "Binary data to attach to the image");
var imageOption = new Option<FileInfo>(
name: "--image",
description: "PE image to add the binary resource into");
var nameOption = new Option<string>(
name: "--name",
description: "Resource name");
var rootCommand = new RootCommand("Inject native resources into a Portable Executable image");
rootCommand.AddOption(binOption);
rootCommand.AddOption(imageOption);
rootCommand.AddOption(nameOption);
CliOption<FileInfo> binOption = new("--bin") { Description = "Binary data to attach to the image" };
CliOption<FileInfo> imageOption = new("--image") { Description = "PE image to add the binary resource into" };
CliOption<string> nameOption = new("--name") { Description = "Resource name" };
CliRootCommand rootCommand = new("Inject native resources into a Portable Executable image");
rootCommand.Options.Add(binOption);
rootCommand.Options.Add(imageOption);
rootCommand.Options.Add(nameOption);

rootCommand.SetHandler((FileInfo binaryData, FileInfo peImage, string name) =>
{
using ResourceUpdater updater = new(peImage);
updater.AddBinaryResource(name, File.ReadAllBytes(binaryData.FullName));
},
binOption,
imageOption,
nameOption);
rootCommand.SetAction(result =>
{
using ResourceUpdater updater = new(result.GetValue(imageOption)!);
updater.AddBinaryResource(result.GetValue(nameOption)!, File.ReadAllBytes(result.GetValue(binOption)!.FullName));
});

return rootCommand.Invoke(args);
return new CliConfiguration(rootCommand).Invoke(args);
Loading