From db2da0543e774c3406b32770c260918cfbc10e6b Mon Sep 17 00:00:00 2001 From: Ross Goldberg <484615+rgoldberg@users.noreply.github.com> Date: Thu, 23 Dec 2021 09:32:57 -0500 Subject: [PATCH] Allow aliases of a CommandSpec that is already a subcommand to be properly & consistently modified. Resolves #1528 --- src/main/java/picocli/CommandLine.java | 29 +++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/main/java/picocli/CommandLine.java b/src/main/java/picocli/CommandLine.java index 49067abdb..eff281d36 100644 --- a/src/main/java/picocli/CommandLine.java +++ b/src/main/java/picocli/CommandLine.java @@ -6428,9 +6428,7 @@ public CommandSpec addSubcommand(String name, CommandLine subCommandLine) { if (subSpec.name == null) { subSpec.name(actualName); } subSpec.parent(this); for (String alias : subSpec.aliases()) { - if (t.isDebug()) {t.debug("Adding alias '%s' for '%s'%n", (parent == null ? "" : parent.qualifiedName() + " ") + alias, this.qualifiedName());} - previous = commands.put(interpolator.interpolate(alias), subCommandLine); - if (previous != null && previous != subCommandLine) { throw new DuplicateNameException("Alias '" + alias + "' for subcommand '" + actualName + "' is already used by another subcommand of '" + this.name() + "'"); } + addAlias(alias, actualName, subCommandLine, t); } subSpec.initCommandHierarchyWithResourceBundle(resourceBundleBaseName(), resourceBundle()); if (scopeType() == ScopeType.INHERIT) { @@ -6451,6 +6449,17 @@ public CommandSpec addSubcommand(String name, CommandLine subCommandLine) { } return this; } + private void addAlias(String alias, String name, CommandLine subCommandLine, Tracer t) { + if (t.isDebug()) {t.debug("Adding alias '%s' for '%s'%n", (parent == null ? "" : parent.qualifiedName() + " ") + alias, qualifiedName());} + CommandLine previous = commands.put(interpolator.interpolate(alias), subCommandLine); + if (previous != null && previous != subCommandLine) { + throw new DuplicateNameException("Alias '" + alias + "' for subcommand '" + name + "' is already used by another subcommand of '" + name() + "'"); + } + } + private void removeAlias(String alias, CommandLine subCommandLine, Tracer t) { + if (t.isDebug()) {t.debug("Removing alias '%s' for '%s'%n", (parent == null ? "" : parent.qualifiedName() + " ") + alias, qualifiedName());} + commands.remove(interpolator.interpolate(alias)); + } private void inheritAttributesFrom(CommandSpec root) { inherited = true; initFrom(root); @@ -7086,7 +7095,21 @@ public String[] version() { * @return this CommandSpec for method chaining * @since 3.1 */ public CommandSpec aliases(String... aliases) { + Set existingAliasSet = this.aliases; this.aliases = new LinkedHashSet(Arrays.asList(aliases == null ? new String[0] : aliases)); + if (parent != null) { + //remove & add aliases + Set newAliasSet = new LinkedHashSet(this.aliases); + newAliasSet.removeAll(existingAliasSet); + Tracer t = new Tracer(); + for (String alias : newAliasSet) { + parent.addAlias(alias, name, commandLine, t); + } + existingAliasSet.removeAll(this.aliases); + for (String alias : existingAliasSet) { + parent.removeAlias(alias, commandLine, t); + } + } return this; }