{
Command command = null;
- var commandAttributes = (CommandAttribute[])type.GetCustomAttributes(typeof(CommandAttribute), inherit: false);
- foreach (CommandAttribute commandAttribute in commandAttributes)
+ var baseAttributes = (BaseAttribute[])type.GetCustomAttributes(typeof(BaseAttribute), inherit: false);
+ foreach (BaseAttribute baseAttribute in baseAttributes)
{
- // If there is a previous command and the current command doesn't have help or alias expansion, use "simple" aliasing
- if (command != null && commandAttribute.Help == null && commandAttribute.AliasExpansion == null) {
- command.AddAlias(commandAttribute.Name);
- continue;
- }
- command = new Command(commandAttribute.Name, commandAttribute.Help);
- var builder = new CommandLineBuilder(command);
- builder.UseHelp();
+ if (baseAttribute is CommandAttribute commandAttribute)
+ {
+ command = new Command(commandAttribute.Name, commandAttribute.Help);
+ var builder = new CommandLineBuilder(command);
+ builder.UseHelp();
- var properties = new List<(PropertyInfo, Option)>();
- PropertyInfo argument = null;
+ var properties = new List<(PropertyInfo, Option)>();
+ PropertyInfo argument = null;
- foreach (PropertyInfo property in type.GetProperties().Where(p => p.CanWrite))
- {
- var argumentAttribute = (ArgumentAttribute)property.GetCustomAttributes(typeof(ArgumentAttribute), inherit: false).SingleOrDefault();
- if (argumentAttribute != null)
- {
- if (argument != null) {
- throw new ArgumentException($"More than one ArgumentAttribute in command class: {type.Name}");
- }
- command.Argument = new Argument {
- Name = argumentAttribute.Name ?? property.Name.ToLowerInvariant(),
- Description = argumentAttribute.Help,
- ArgumentType = property.PropertyType,
- Arity = new ArgumentArity(0, int.MaxValue)
- };
- argument = property;
- }
- else
+ foreach (PropertyInfo property in type.GetProperties().Where(p => p.CanWrite))
{
- var optionAttribute = (OptionAttribute)property.GetCustomAttributes(typeof(OptionAttribute), inherit: false).SingleOrDefault();
- if (optionAttribute != null)
+ var argumentAttribute = (ArgumentAttribute)property.GetCustomAttributes(typeof(ArgumentAttribute), inherit: false).SingleOrDefault();
+ if (argumentAttribute != null)
{
- var option = new Option(optionAttribute.Name ?? BuildAlias(property.Name), optionAttribute.Help, new Argument { ArgumentType = property.PropertyType });
- command.AddOption(option);
- properties.Add((property, option));
-
- foreach (var optionAliasAttribute in (OptionAliasAttribute[])property.GetCustomAttributes(typeof(OptionAliasAttribute), inherit: false))
- {
- option.AddAlias(optionAliasAttribute.Name);
+ if (argument != null) {
+ throw new ArgumentException($"More than one ArgumentAttribute in command class: {type.Name}");
}
+ command.Argument = new Argument {
+ Name = argumentAttribute.Name ?? property.Name.ToLowerInvariant(),
+ Description = argumentAttribute.Help,
+ ArgumentType = property.PropertyType,
+ Arity = new ArgumentArity(0, int.MaxValue)
+ };
+ argument = property;
}
else
{
- // If not an option, add as just a settable properties
- properties.Add((property, null));
+ var optionAttribute = (OptionAttribute)property.GetCustomAttributes(typeof(OptionAttribute), inherit: false).SingleOrDefault();
+ if (optionAttribute != null)
+ {
+ var option = new Option(optionAttribute.Name ?? BuildAlias(property.Name), optionAttribute.Help, new Argument { ArgumentType = property.PropertyType });
+ command.AddOption(option);
+ properties.Add((property, option));
+
+ foreach (var optionAliasAttribute in (OptionAliasAttribute[])property.GetCustomAttributes(typeof(OptionAliasAttribute), inherit: false))
+ {
+ option.AddAlias(optionAliasAttribute.Name);
+ }
+ }
+ else
+ {
+ // If not an option, add as just a settable properties
+ properties.Add((property, null));
+ }
}
}
+
+ command.Handler = new Handler(this, commandAttribute.AliasExpansion, argument, properties, type);
+ rootBuilder.AddCommand(command);
}
- command.Handler = new Handler(this, commandAttribute.AliasExpansion, argument, properties, type);
- rootBuilder.AddCommand(command);
+ if (baseAttribute is CommandAliasAttribute commandAliasAttribute)
+ {
+ if (command == null) {
+ throw new ArgumentException($"No previous CommandAttribute for this CommandAliasAttrbute: {type.Name}");
+ }
+ command.AddAlias(commandAliasAttribute.Name);
+ }
}
}
}
[Command(Name = "dumpmt", AliasExpansion = "DumpMT", Help = "Displays information about a method table at the specified address.")]
[Command(Name = "dumpobj", AliasExpansion = "DumpObj", Help = "Displays info about an object at the specified address.")]
[Command(Name = "dumpstackobjects", AliasExpansion = "DumpStackObjects", Help = "Displays all managed objects found within the bounds of the current stack.")]
- [Command(Name = "dso")]
+ [CommandAlias(Name = "dso")]
[Command(Name = "eeheap", AliasExpansion = "EEHeap", Help = "Displays info about process memory consumed by internal runtime data structures.")]
[Command(Name = "finalizequeue", AliasExpansion = "FinalizeQueue", Help = "Displays all objects registered for finalization.")]
[Command(Name = "gcroot", AliasExpansion = "GCRoot", Help = "Displays info about references (or roots) to an object at the specified address.")]
[Command(Name = "ip2md", AliasExpansion = "IP2MD", Help = "Displays the MethodDesc structure at the specified address in code that has been JIT-compiled.")]
[Command(Name = "name2ee", AliasExpansion = "Name2EE", Help = "Displays the MethodTable structure and EEClass structure for the specified type or method in the specified module.")]
[Command(Name = "printexception", AliasExpansion = "PrintException", Help = "Displays and formats fields of any object derived from the Exception class at the specified address.")]
- [Command(Name = "pe")]
+ [CommandAlias(Name = "pe")]
[Command(Name = "syncblk", AliasExpansion = "SyncBlk", Help = "Displays the SyncBlock holder info.")]
[Command(Name = "histclear", AliasExpansion = "HistClear", Help = "Releases any resources used by the family of Hist commands.")]
[Command(Name = "histinit", AliasExpansion = "HistInit", Help = "Initializes the SOS structures from the stress log saved in the debuggee.")]