When a command's XML doc comment has <param> tags but no <summary> tag, every per-parameter customization encoded in those <param> tags — short aliases (-i, --in, ...) and descriptions — is silently dropped. The command still builds and runs fine, it just falls back to auto-generated kebab-case long names with no short alias and no description, as if the <param> tags weren't there at all.
This is silent: no generator diagnostic, no warning. I hit it while porting several tools off reflection-based CLI parsers (CommandLineParser/Argu) onto Nullean.Argh for AOT — for a while I assumed the difference was between registering via Map("name", MethodGroup) / MapRoot(MethodGroup) vs a class registered via Map<T>(), since that's what changed between my broken and working attempts. It isn't — it reproduces identically for both delegate-based and class-based registration, and for MapRoot too. The only variable that matters is whether <summary> is present.
Repro
Nullean.Argh 0.18.0, .NET SDK 10.0.300, macOS arm64.
using Nullean.Argh;
var app = new ArghApp();
app.Map<Commands>();
return await app.RunAsync(args);
public sealed class Commands
{
/// <summary>Has a summary tag.</summary>
/// <param name="input">-i, --in, Input path.</param>
/// <param name="output">-o, --out, Output path.</param>
[CommandName("with-summary")]
public int WithSummary(string input, string output) => 0;
/// <param name="input">-i, --in, Input path.</param>
/// <param name="output">-o, --out, Output path.</param>
[CommandName("without-summary")]
public int WithoutSummary(string input, string output) => 0;
}
$ app with-summary --help
Usage: app with-summary --in <string> --out <string>
Has a summary tag.
Options:
-i, --in <string> [required] Input path.
-o, --out <string> [required] Output path.
$ app without-summary --help
Usage: app without-summary --input <string> --output <string>
Options:
--input <string> [required]
--output <string> [required]
Both methods have byte-for-byte identical <param> tags. with-summary gets -i/-o short aliases and descriptions from them; without-summary gets neither, purely because it lacks a <summary> tag. Confirmed this holds for MapRoot(MethodGroup) too, not just Map<T>()/Map("name", MethodGroup).
Expected
<param> short-alias/description parsing shouldn't depend on <summary> being present — a command with no summary should still honor its parameter docs. Failing that, a generator diagnostic when <param> tags exist without a <summary> would at least surface the drop instead of silently falling back to defaults.
When a command's XML doc comment has
<param>tags but no<summary>tag, every per-parameter customization encoded in those<param>tags — short aliases (-i, --in, ...) and descriptions — is silently dropped. The command still builds and runs fine, it just falls back to auto-generated kebab-case long names with no short alias and no description, as if the<param>tags weren't there at all.This is silent: no generator diagnostic, no warning. I hit it while porting several tools off reflection-based CLI parsers (
CommandLineParser/Argu) ontoNullean.Arghfor AOT — for a while I assumed the difference was between registering viaMap("name", MethodGroup)/MapRoot(MethodGroup)vs a class registered viaMap<T>(), since that's what changed between my broken and working attempts. It isn't — it reproduces identically for both delegate-based and class-based registration, and forMapRoottoo. The only variable that matters is whether<summary>is present.Repro
Nullean.Argh0.18.0, .NET SDK 10.0.300, macOS arm64.Both methods have byte-for-byte identical
<param>tags.with-summarygets-i/-oshort aliases and descriptions from them;without-summarygets neither, purely because it lacks a<summary>tag. Confirmed this holds forMapRoot(MethodGroup)too, not justMap<T>()/Map("name", MethodGroup).Expected
<param>short-alias/description parsing shouldn't depend on<summary>being present — a command with no summary should still honor its parameter docs. Failing that, a generator diagnostic when<param>tags exist without a<summary>would at least surface the drop instead of silently falling back to defaults.