Skip to content

Inline @Options class javadoc into command help #130

Description

@dblevins

HelpProcessor only processes @Command-annotated methods, so javadoc on @Options (and @GlobalOptions) classes never reaches the rendered help. Authors who add javadoc to an Options class constructor — including @param tags for each @Option parameter — get no benefit at runtime; only the command method's own javadoc is rendered.

This means well-documented Options classes either go unused at help time, or authors duplicate the relevant content into every command method that consumes the Options class.

Example of the gap

@Command
public String create(
    @Option("to") final List<Email> to,
    final Schedule schedule,           // <-- Options class
    final String... command) { ... }

@Options
public static class Schedule {
    /**
     * @param minute     accepts values `0-59` and wildcards `, - * /`
     * @param hour       accepts values `0-23` and wildcards `, - * /`
     * @param dayOfMonth accepts values `1-31` and wildcards `, - * ? / L W`
     */
    public Schedule(
        @Option("minute") @Default("0") final String minute,
        @Option("hour") @Default("0") final String hour,
        @Option("day-of-month") @Default("*") final String dayOfMonth) { ... }
}

The @param tags above are never read. To get the per-option descriptions to render, the author must either repeat them on the create method's javadoc (matching by Java parameter name, which doesn't apply here since Schedule is one parameter, not many), or push them into OptionDescriptions.properties.

Sketch of a fix

  1. Extend HelpProcessor to also process classes annotated with @Options and @GlobalOptions. Emit a parallel resource file (e.g. META-INF/crest/{className}/{className}.properties) mapping option names to constructor parameter names, mirroring the per-command resource.
  2. At runtime, when ComplexParam is built for an Options class, load that resource and make it available to Help.getItems() for the option-description fallback chain.
  3. Description priority for an Options-class option becomes:
    1. OptionDescriptions.properties (existing)
    2. @Option(description) (existing)
    3. @param tag on the Options class constructor (new)
    4. @param tag on the command method (existing — kept as last-resort for the rare case where someone wants to override per-command)

Open design questions

  • Where does the constructor's javadoc body go in the rendered output? It clearly belongs somewhere in the command's man page, but the command method's javadoc is already authoritative for the DESCRIPTION section. Possibilities: (a) inline it into DESCRIPTION at a configurable insertion point; (b) render it as a sub-section preceding OPTIONS for that group only; (c) skip the body entirely and inline @param tags only.
  • What if the same @Options class is used by two commands with conflicting documentation needs? Class-level javadoc is global — there's no command-specific override path. May need to accept that and treat the bundle as authoritative across commands, or layer a per-command override into the options-descriptions properties bundle.
  • @GlobalOptions rendering — these options appear on every command. If their class has javadoc, where does it go? The "global help" page? Each per-command page? Both?

These are tractable, but the call about where the body content surfaces deserves a focused design discussion before implementation.

Out of scope for this issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions