diff --git a/cloud-core/src/main/java/org/incendo/cloud/syntax/StandardCommandSyntaxFormatter.java b/cloud-core/src/main/java/org/incendo/cloud/syntax/StandardCommandSyntaxFormatter.java index fcee6f88f..5c04478b6 100644 --- a/cloud-core/src/main/java/org/incendo/cloud/syntax/StandardCommandSyntaxFormatter.java +++ b/cloud-core/src/main/java/org/incendo/cloud/syntax/StandardCommandSyntaxFormatter.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.function.Predicate; +import java.util.stream.Collectors; import org.apiguardian.api.API; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @@ -76,7 +77,7 @@ public StandardCommandSyntaxFormatter(final @NonNull CommandManager manager) final @NonNull List<@NonNull CommandComponent> commandComponents, final @Nullable CommandNode node ) { - return this.apply(commandComponents, node, n -> { + return this.apply(sender, commandComponents, node, n -> { if (sender == null) { return true; } @@ -95,7 +96,9 @@ public StandardCommandSyntaxFormatter(final @NonNull CommandManager manager) }); } + @SuppressWarnings("unchecked") private @NonNull String apply( + final @Nullable C sender, final @NonNull List<@NonNull CommandComponent> commandComponents, final @Nullable CommandNode node, final @NonNull Predicate<@NonNull CommandNode> filter @@ -110,7 +113,7 @@ public StandardCommandSyntaxFormatter(final @NonNull CommandManager manager) final AggregateParser aggregateParser = (AggregateParser) commandComponent.parser(); formattingInstance.appendAggregate(commandComponent, aggregateParser); } else if (commandComponent.type() == CommandComponent.ComponentType.FLAG) { - formattingInstance.appendFlag((CommandFlagParser) commandComponent.parser()); + formattingInstance.appendFlag(this.filterFlagsByPermission(sender, (CommandFlagParser) commandComponent.parser())); } else { if (commandComponent.required()) { formattingInstance.appendRequired(commandComponent); @@ -163,8 +166,12 @@ public StandardCommandSyntaxFormatter(final @NonNull CommandManager manager) formattingInstance.appendBlankSpace(); formattingInstance.appendAggregate(component, aggregateParser); } else if (component.type() == CommandComponent.ComponentType.FLAG) { - formattingInstance.appendBlankSpace(); - formattingInstance.appendFlag((CommandFlagParser) component.parser()); + final List> flags = this.filterFlagsByPermission(sender, (CommandFlagParser) component.parser()); + + if (!flags.isEmpty()) { + formattingInstance.appendBlankSpace(); + formattingInstance.appendFlag(flags); + } } else if (component.type() == CommandComponent.ComponentType.LITERAL) { formattingInstance.appendBlankSpace(); formattingInstance.appendLiteral(component); @@ -190,6 +197,16 @@ public StandardCommandSyntaxFormatter(final @NonNull CommandManager manager) return new FormattingInstance(); } + private List> filterFlagsByPermission( + final @Nullable C sender, + final @NonNull CommandFlagParser flagParser + ) { + return flagParser + .flags() + .stream() + .filter(flag -> sender == null || this.manager.testPermission(sender, flag.permission()).allowed()) + .collect(Collectors.toList()); + } /** * Instance that is used when building command syntax @@ -251,14 +268,12 @@ public void appendAggregate( /** * Appends a flag argument * - * @param flagParser flag parser + * @param flags the flags to append */ - public void appendFlag(final @NonNull CommandFlagParser flagParser) { + public void appendFlag(final @NonNull Iterable> flags) { this.builder.append(this.optionalPrefix()); - final Iterator> flagIterator = flagParser - .flags() - .iterator(); + final Iterator> flagIterator = flags.iterator(); while (flagIterator.hasNext()) { final CommandFlag flag = flagIterator.next(); diff --git a/cloud-core/src/test/java/org/incendo/cloud/syntax/StandardCommandSyntaxFormatterTest.java b/cloud-core/src/test/java/org/incendo/cloud/syntax/StandardCommandSyntaxFormatterTest.java index 48dc4ee9b..f85e8f2dc 100644 --- a/cloud-core/src/test/java/org/incendo/cloud/syntax/StandardCommandSyntaxFormatterTest.java +++ b/cloud-core/src/test/java/org/incendo/cloud/syntax/StandardCommandSyntaxFormatterTest.java @@ -31,6 +31,7 @@ import org.incendo.cloud.execution.ExecutionCoordinator; import org.incendo.cloud.internal.CommandNode; import org.incendo.cloud.internal.CommandRegistrationHandler; +import org.incendo.cloud.parser.flag.CommandFlag; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -106,6 +107,25 @@ void respectsPermissions() { assertThat(formatted).isEqualTo(" all"); } + @Test + void respectsFlagPermissions() { + final Command.Builder root = this.manager.commandBuilder("root"); + this.manager.command( + root.flag(CommandFlag.builder("some_flag").withPermission("some_permission").build()) + .handler(ctx -> {}) + ); + + final CommandNode rootNode = this.manager.commandTree().getNamedNode("root"); + + final String permittedFormatted = this.formatter.apply( + new TestCommandSender("some_permission"), Collections.emptyList(), rootNode); + assertThat(permittedFormatted).isEqualTo(" [--some_flag]"); + + final String formatted = this.formatter.apply( + new TestCommandSender(), Collections.emptyList(), rootNode); + assertThat(formatted).isEqualTo(""); + } + static final class SpecificTestCommandSender extends TestCommandSender { }