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 PMI to use the new System.CommandLine parser #209

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
342 changes: 174 additions & 168 deletions src/cijobs/cijobs.cs

Large diffs are not rendered by default.

214 changes: 110 additions & 104 deletions src/jit-analyze/jit-analyze.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,92 +3,57 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;
using System.CommandLine;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools.Common;
using Newtonsoft.Json;
using System.CommandLine.Invocation;
using Command = Microsoft.DotNet.Cli.Utils.Command;
using CommandResult = Microsoft.DotNet.Cli.Utils.CommandResult;

namespace ManagedCodeGen
{
public class jitanalyze
{
public class Config
{
private ArgumentSyntax _syntaxResult;
private string _basePath = null;
private string _diffPath = null;
private bool _recursive = false;
private bool _full = false;
private bool _warn = false;
private int _count = 5;
private string _json;
private string _tsv;
private bool _noreconcile = false;
private string _note;
private string _filter;

public Config(string[] args)
void ReportError(string message)
{
_syntaxResult = ArgumentSyntax.Parse(args, syntax =>
{
syntax.DefineOption("b|base", ref _basePath, "Base file or directory.");
syntax.DefineOption("d|diff", ref _diffPath, "Diff file or directory.");
syntax.DefineOption("r|recursive", ref _recursive, "Search directories recursively.");
syntax.DefineOption("c|count", ref _count,
"Count of files and methods (at most) to output in the summary."
+ " (count) improvements and (count) regressions of each will be included."
+ " (default 5)");
syntax.DefineOption("w|warn", ref _warn,
"Generate warning output for files/methods that only "
+ "exists in one dataset or the other (only in base or only in diff).");
syntax.DefineOption("note", ref _note,
"Descriptive note to add to summary output");
syntax.DefineOption("noreconcile", ref _noreconcile,
"Do not reconcile unique methods in base/diff");
syntax.DefineOption("json", ref _json,
"Dump analysis data to specified file in JSON format.");
syntax.DefineOption("tsv", ref _tsv,
"Dump analysis data to specified file in tab-separated format.");
syntax.DefineOption("filter", ref _filter,
"Only consider assembly files whose names match the filter");
});

// Run validation code on parsed input to ensure we have a sensible scenario.
validate();
Console.WriteLine(message);
Error = true;
}

private void validate()
public void validate()
{
if (_basePath == null)
if (Base == null)
{
_syntaxResult.ReportError("Base path (--base) is required.");
ReportError("Base path (--base) is required.");
}

if (_diffPath == null)
if (Diff == null)
{
_syntaxResult.ReportError("Diff path (--diff) is required.");
ReportError("Diff path (--diff) is required.");
}
}

public string BasePath { get { return _basePath; } }
public string DiffPath { get { return _diffPath; } }
public bool Recursive { get { return _recursive; } }
public bool Full { get { return _full; } }
public bool Warn { get { return _warn; } }
public int Count { get { return _count; } }
public string TSVFileName { get { return _tsv; } }
public string JsonFileName { get { return _json; } }
public bool DoGenerateJson { get { return _json != null; } }
public bool DoGenerateTSV { get { return _tsv != null; } }
public bool Reconcile { get { return !_noreconcile; } }
public string Note { get { return _note; } }

public string Filter { get { return _filter; } }
public string Base { get; set; }
public string Diff { get; set; }
public bool Recursive { get; set; }
public bool Full { get; set; }
public bool Warn { get; set; }
public int Count { get; set; }
public string TsvFileName { get; set; }
public string JsonFileName { get; set; }
public bool DoGenerateJson { get { return JsonFileName != null; } }
public bool DoGenerateTSV { get { return TsvFileName != null; } }
public bool NoReconcile { get; set; }
public bool Reconcile { get { return !NoReconcile; } }
public string Note { get; set; }
public string Filter { get; set; }
public bool Error { get; set; }
}

public class FileInfo
Expand Down Expand Up @@ -688,61 +653,102 @@ public static Dictionary<string, int> DiffInText(string diffPath, string basePat

public static int Main(string[] args)
{
// Parse incoming arguments
Config config = new Config(args);

Dictionary<string, int> diffCounts = DiffInText(config.DiffPath, config.BasePath);

// Early out if no textual diffs found.
if (diffCounts == null)
{
Console.WriteLine("No diffs found.");
return 0;
}

try
RootCommand rootCommand = new RootCommand();

Option basePathOption = new Option("--base", "Base file or directory.", new Argument<string>());
basePathOption.AddAlias("-b");
Option diffPathOption = new Option("--diff", "Diff file or directory.", new Argument<string>());
diffPathOption.AddAlias("-d");
Option recursiveOption = new Option("--recursive", "Search directories recursively.", new Argument<bool>());
recursiveOption.AddAlias("-r");
Option countOption = new Option("--count", "Count of files and methods (at most) to output in the summary."
+ " (count) improvements and (count) regressions of each will be included."
+ " (default 5)", new Argument<uint>(5));
countOption.AddAlias("-c");
Option warnOption = new Option("--warn", "Generate warning output for files/methods that only "
+ "exists in one dataset or the other (only in base or only in diff).", new Argument<bool>());
warnOption.AddAlias("-w");
Option noReconcileOption = new Option("--noreconcile", "Do not reconcile unique methods in base/diff", new Argument<bool>());
Option noteOption = new Option("--note", "Descriptive note to add to summary output", new Argument<string>());
Option jsonOption = new Option("--jsonFileName", "Dump analysis data to specified file in JSON format.", new Argument<string>());
Option tsvOption = new Option("--tsvFileName", "Dump analysis data to specified file in tab-separated format.", new Argument<string>());
Option filterOption = new Option("--filter", "Only consider assembly files whose names match the filter", new Argument<string>());

rootCommand.AddOption(basePathOption);
rootCommand.AddOption(diffPathOption);
rootCommand.AddOption(recursiveOption);
rootCommand.AddOption(countOption);
rootCommand.AddOption(warnOption);
rootCommand.AddOption(noReconcileOption);
rootCommand.AddOption(noteOption);
rootCommand.AddOption(jsonOption);
rootCommand.AddOption(tsvOption);
rootCommand.AddOption(filterOption);

rootCommand.Handler = CommandHandler.Create<Config>((config) =>
{
// Extract method info from base and diff directory or file.
var baseList = ExtractFileInfo(config.BasePath, config.Filter, config.Recursive);
var diffList = ExtractFileInfo(config.DiffPath, config.Filter, config.Recursive);
config.validate();

// Compare the method info for each file and generate a list of
// non-zero deltas. The lists that include files in one but not
// the other are used as the comparator function only compares where it
// has both sides.
if (config.Error)
{
return -1;
}

var compareList = Comparator(baseList, diffList, config);
Dictionary<string, int> diffCounts = DiffInText(config.Diff, config.Base);

// Generate warning lists if requested.
if (config.Warn)
// Early out if no textual diffs found.
if (diffCounts == null)
{
WarnFiles(diffList, baseList);
WarnMethods(compareList);
Console.WriteLine("No diffs found.");
return 0;
}

if (config.DoGenerateTSV)
try
{
GenerateTSV(compareList, config.TSVFileName);
}
// Extract method info from base and diff directory or file.
var baseList = ExtractFileInfo(config.Base, config.Filter, config.Recursive);
var diffList = ExtractFileInfo(config.Diff, config.Filter, config.Recursive);

// Compare the method info for each file and generate a list of
// non-zero deltas. The lists that include files in one but not
// the other are used as the comparator function only compares where it
// has both sides.

var compareList = Comparator(baseList, diffList, config);

if (config.DoGenerateJson)
// Generate warning lists if requested.
if (config.Warn)
{
WarnFiles(diffList, baseList);
WarnMethods(compareList);
}

if (config.DoGenerateTSV)
{
GenerateTSV(compareList, config.TsvFileName);
}

if (config.DoGenerateJson)
{
GenerateJson(compareList, config.JsonFileName);
}

return Summarize(compareList, config, diffCounts);

}
catch (DirectoryNotFoundException e)
{
GenerateJson(compareList, config.JsonFileName);
Console.WriteLine("Error: {0}", e.Message);
return 0;
}
catch (FileNotFoundException e)
{
Console.WriteLine("Error: {0}", e.Message);
return 0;
}
});

return Summarize(compareList, config, diffCounts);

}
catch (System.IO.DirectoryNotFoundException e)
{
Console.WriteLine("Error: {0}", e.Message);
return 0;
}
catch (System.IO.FileNotFoundException e)
{
Console.WriteLine("Error: {0}", e.Message);
return 0;
}
return rootCommand.InvokeAsync(args).Result;
}
}
}
Loading