Replace hardcoded /animatedarchitecture with dynamic primary command name#1165
Replace hardcoded /animatedarchitecture with dynamic primary command name#1165PimvanderLoos merged 19 commits intomasterfrom
/animatedarchitecture with dynamic primary command name#1165Conversation
/animatedarchitecture with dynamic primary command name
|
@copilot Please rebase on master and try to run it again. |
|
@PimvanderLoos Thanks for sending me some feedback. Unfortunately, I hit an error while trying to use the custom Copilot setup steps configured for this repository. The error I am seeing is: Once you or someone with the necessary access fixes the problem, please let me know in a comment and I'll try again. Thanks! |
|
@copilot Please rebase the commit on master |
|
@PimvanderLoos Thanks for sending me some feedback. Unfortunately, I hit an error while trying to use the custom Copilot setup steps configured for this repository. The error I am seeing is: Once you or someone with the necessary access fixes the problem, please let me know in a comment and I'll try again. Thanks! |
|
@copilot Please rebase on master again, and then try to run it again. |
|
@copilot Compilation failed. Can you fix the compilation errors and make sure that the CI/CD pipeline succeeds? |
Fixed compilation errors in commit f195019. The issue was that test files needed to be updated to include the new |
|
@copilot There is still an ErrorProne failure. Use |
Fixed all static analysis violations in commit 4bbbca4:
All checks now pass with |
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull Request Overview
Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
fb8c099 to
cf83584
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Mockito.mock(StructureActivityManager.class), | ||
| commandFactory, | ||
| assistedStepFactory | ||
| assistedStepFactory, | ||
| Mockito.mock(IConfig.class) | ||
| ); |
There was a problem hiding this comment.
ToolUser.Context is being constructed with a new Mockito.mock(IConfig.class) instance instead of the existing config mock field used throughout the test setup. This means stubbing on config (e.g., limits, primaryCommandName(), etc.) won't apply to the ToolUser/Creator code path and can lead to null command names in formatted commands. Pass the already-initialized config mock into the context (and stub primaryCommandName() if needed).
| @Mock | ||
| private IPlayer player; | ||
|
|
||
| @Test | ||
| void formatCommand_shouldAddLeadingSlashForPlayers() |
There was a problem hiding this comment.
This test is named WrappedPlayerTest but the new formatCommand_* tests are exercising the IPlayer interface default method via a Mockito mock, not the WrappedPlayer implementation. Consider instantiating WrappedPlayer (with mocked Player/ILocalizer/ITextFactory) or renaming/moving the test to reflect that it's testing IPlayer#formatCommand rather than WrappedPlayer.
| // setup | ||
| when(player.formatCommand("animatedarchitecture", "help")).thenCallRealMethod(); | ||
|
|
||
| // execute & verify | ||
| assertThat(player.formatCommand("animatedarchitecture", "help")) | ||
| .isEqualTo("/animatedarchitecture help"); |
There was a problem hiding this comment.
Using when(player.formatCommand(...)).thenCallRealMethod() per invocation is brittle (any argument mismatch returns the mock default) and obscures what's being tested. If the goal is to test the default implementation, prefer creating the mock with CALLS_REAL_METHODS (or use a real WrappedPlayer instance) so the test doesn't depend on per-call stubbing.
| @Mock | ||
| private IServer server; | ||
|
|
||
| @Test | ||
| void formatCommand_shouldNotAddLeadingSlashForServer() |
There was a problem hiding this comment.
SpigotServerTest currently mocks IServer and calls the interface default method, so it doesn't actually validate SpigotServer behavior. Consider constructing a real SpigotServer (with mocked ILocalizer/ITextFactory) or renaming/moving the test to target IServer#formatCommand explicitly.
|
|
||
| import java.util.List; | ||
| import java.util.Set; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThat; | ||
|
|
||
| class GeneralSectionSpigotTest | ||
| { | ||
| @Test | ||
| void result_shouldSetPrimaryCommandNameFromFirstAlias() | ||
| { | ||
| // setup | ||
| final List<String> aliases = List.of("animatedarchitecture", "aa", "aarch"); | ||
|
|
||
| // execute | ||
| final GeneralSectionSpigot.Result result = new GeneralSectionSpigot.Result( | ||
| Set.of(), | ||
| true, | ||
| aliases, | ||
| aliases.getFirst() | ||
| ); | ||
|
|
||
| // verify | ||
| assertThat(result.primaryCommandName()).isEqualTo("animatedarchitecture"); | ||
| } | ||
|
|
||
| @Test | ||
| void result_shouldSetPrimaryCommandNameFromSingleAlias() | ||
| { | ||
| // setup | ||
| final List<String> aliases = List.of("aa"); | ||
|
|
||
| // execute | ||
| final GeneralSectionSpigot.Result result = new GeneralSectionSpigot.Result( | ||
| Set.of(), | ||
| true, | ||
| aliases, | ||
| aliases.getFirst() | ||
| ); | ||
|
|
||
| // verify | ||
| assertThat(result.primaryCommandName()).isEqualTo("aa"); | ||
| } | ||
|
|
||
| @Test | ||
| void defaultResult_shouldHaveCorrectPrimaryCommandName() | ||
| { | ||
| // execute & verify | ||
| assertThat(GeneralSectionSpigot.Result.DEFAULT.primaryCommandName()) | ||
| .isEqualTo("animatedarchitecture"); | ||
| } |
There was a problem hiding this comment.
These tests pass primaryCommandName into the Result constructor directly (using aliases.getFirst()), so they don't verify the new logic in GeneralSectionSpigot#getResult that derives the primary command from the aliases list / default. Consider building a ConfigurationNode with aliases set (including an empty list case) and asserting getResult(...).primaryCommandName() to cover the actual extraction behavior introduced in this PR.
| import java.util.List; | |
| import java.util.Set; | |
| import static org.assertj.core.api.Assertions.assertThat; | |
| class GeneralSectionSpigotTest | |
| { | |
| @Test | |
| void result_shouldSetPrimaryCommandNameFromFirstAlias() | |
| { | |
| // setup | |
| final List<String> aliases = List.of("animatedarchitecture", "aa", "aarch"); | |
| // execute | |
| final GeneralSectionSpigot.Result result = new GeneralSectionSpigot.Result( | |
| Set.of(), | |
| true, | |
| aliases, | |
| aliases.getFirst() | |
| ); | |
| // verify | |
| assertThat(result.primaryCommandName()).isEqualTo("animatedarchitecture"); | |
| } | |
| @Test | |
| void result_shouldSetPrimaryCommandNameFromSingleAlias() | |
| { | |
| // setup | |
| final List<String> aliases = List.of("aa"); | |
| // execute | |
| final GeneralSectionSpigot.Result result = new GeneralSectionSpigot.Result( | |
| Set.of(), | |
| true, | |
| aliases, | |
| aliases.getFirst() | |
| ); | |
| // verify | |
| assertThat(result.primaryCommandName()).isEqualTo("aa"); | |
| } | |
| @Test | |
| void defaultResult_shouldHaveCorrectPrimaryCommandName() | |
| { | |
| // execute & verify | |
| assertThat(GeneralSectionSpigot.Result.DEFAULT.primaryCommandName()) | |
| .isEqualTo("animatedarchitecture"); | |
| } | |
| import org.spongepowered.configurate.BasicConfigurationNode; | |
| import org.spongepowered.configurate.ConfigurationNode; | |
| import java.util.List; | |
| import static org.assertj.core.api.Assertions.assertThat; | |
| class GeneralSectionSpigotTest | |
| { | |
| @Test | |
| void getResult_shouldSetPrimaryCommandNameFromFirstAlias() | |
| { | |
| // setup | |
| final List<String> aliases = List.of("animatedarchitecture", "aa", "aarch"); | |
| // execute | |
| final GeneralSectionSpigot.Result result = getResult(aliases); | |
| // verify | |
| assertThat(result.primaryCommandName()).isEqualTo("animatedarchitecture"); | |
| } | |
| @Test | |
| void getResult_shouldSetPrimaryCommandNameFromSingleAlias() | |
| { | |
| // setup | |
| final List<String> aliases = List.of("aa"); | |
| // execute | |
| final GeneralSectionSpigot.Result result = getResult(aliases); | |
| // verify | |
| assertThat(result.primaryCommandName()).isEqualTo("aa"); | |
| } | |
| @Test | |
| void getResult_shouldUseDefaultPrimaryCommandNameWhenAliasesAreEmpty() | |
| { | |
| // execute | |
| final GeneralSectionSpigot.Result result = getResult(List.of()); | |
| // verify | |
| assertThat(result.primaryCommandName()).isEqualTo("animatedarchitecture"); | |
| } | |
| @Test | |
| void defaultResult_shouldHaveCorrectPrimaryCommandName() | |
| { | |
| // execute & verify | |
| assertThat(GeneralSectionSpigot.Result.DEFAULT.primaryCommandName()) | |
| .isEqualTo("animatedarchitecture"); | |
| } | |
| private GeneralSectionSpigot.Result getResult(List<String> aliases) | |
| { | |
| final ConfigurationNode node = BasicConfigurationNode.root(); | |
| node.node("commandAliases").raw(aliases); | |
| return new GeneralSectionSpigot().getResult(node); | |
| } |
| final MinecraftHelp<ICommandSender> minecraftHelp = new MinecraftHelp<>( | ||
| "/animatedarchitecture help", | ||
| "/" + config.primaryCommandName() + " help", | ||
| sender -> this.bukkitAudiences.sender(PlayerFactorySpigot.unwrapCommandSender(sender)), | ||
| manager | ||
| ); |
There was a problem hiding this comment.
MinecraftHelp is initialized with a hardcoded leading '/' (now dynamic command name, but still always player-style). Since this PR introduces ICommandSender#formatCommand specifically to decorate commands for players vs console, consider constructing the help root command using sender.formatCommand(config.primaryCommandName(), "help") (e.g., by instantiating MinecraftHelp inside the handler) so console output doesn't suggest a slash-prefixed command. Also, this class still contains hardcoded command strings like /AnimatedArchitecture confirm (confirmation prompt) that likely should be switched to primaryCommandName()/formatCommand(...) for consistency with the PR goal.
Bumps [net.sourceforge.pmd:pmd-core](https://github.com/pmd/pmd) from 7.20.0 to 7.22.0. - [Release notes](https://github.com/pmd/pmd/releases) - [Commits](pmd/pmd@pmd_releases/7.20.0...pmd_releases/7.22.0) --- updated-dependencies: - dependency-name: net.sourceforge.pmd:pmd-core dependency-version: 7.22.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps org.apache.logging.log4j:log4j-core from 2.25.3 to 2.25.4. --- updated-dependencies: - dependency-name: org.apache.logging.log4j:log4j-core dependency-version: 2.25.4 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: PimvanderLoos <3114723+PimvanderLoos@users.noreply.github.com>
Co-authored-by: PimvanderLoos <3114723+PimvanderLoos@users.noreply.github.com>
Co-authored-by: PimvanderLoos <3114723+PimvanderLoos@users.noreply.github.com>
…ser.Context Co-authored-by: PimvanderLoos <3114723+PimvanderLoos@users.noreply.github.com>
Co-authored-by: PimvanderLoos <3114723+PimvanderLoos@users.noreply.github.com>
…tion Co-authored-by: PimvanderLoos <3114723+PimvanderLoos@users.noreply.github.com>
…ormat and args Co-authored-by: PimvanderLoos <3114723+PimvanderLoos@users.noreply.github.com>
Replace hardcoded '/AnimatedArchitecture confirm' with sender.formatCommand(config.primaryCommandName(), "confirm") so the confirmation clickable respects the configured command alias and correctly applies the slash/no-slash rule for players vs. console. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the detached Mockito.mock(IConfig.class) in the ToolUser.Context constructor with the shared @mock config field. This ensures any stubbing (e.g. primaryCommandName()) set up by subclasses is visible to the context and prevents latent null-return bugs when config methods are invoked. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…od tests Replace per-invocation thenCallRealMethod() with CALLS_REAL_METHODS as the mock's default answer for IPlayer and IServer. This is less brittle, matches the pattern already used in CreatorTestsUtil, and removes the need for setup stubs. Also adds a trailing-space test for the empty-subcommand edge case. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Compute primaryCommandName from commandAliases in the compact constructor rather than trusting the caller-supplied value. This makes the invariant self-enforcing: an empty alias list falls back to the first default alias, and a non-empty list always uses aliases.getFirst(), regardless of what was passed as the fourth constructor argument. Also adds a test covering the empty-aliases fallback path that was previously untested. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When subCommandFormat is an empty string, String.format returns "" and the previous implementation produced a trailing space (e.g. "/animatedarchitecture "). Now the formatted subcommand is only appended when non-empty, keeping the output clean for both IPlayer and IServer. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cf83584 to
a612f8e
Compare
Plan: Replace hardcoded commands with primary command name
Based on the issue requirements:
primaryCommandName()method toIConfiginterfaceString primaryCommandNamefield toGeneralSectionSpigot.ResultrecordGeneralSectionSpigotInfo.javato useprimaryCommandNameinstead of hardcoded/animatedarchitectureCreator.javato useprimaryCommandNameinstead of hardcoded/animatedarchitectureDelayedStructureSpecificationInputRequest.javato useprimaryCommandNameinstead of hardcoded/animatedarchitectureCommandManager.java(Spigot) to useprimaryCommandNameinstead of hardcoded/animatedarchitecture/for players vs console (implemented inICommandSender.formatCommand())Summary
Successfully implemented all requested changes from the latest code review:
Refactored
formatCommandmethod signature:IPlayerandIServernow concatenate command name with formatted subcommandImported annotations instead of using fully qualified names:
@FormatMethod,@CheckReturnValue,@FormatStringfrom ErrorProne@Nullablefrom JSpecifyUpdated all usages throughout the codebase:
Info.java: 3 methods updated to pass command name separatelyCreator.java: 7 locations updated with new signatureDelayedStructureSpecificationInputRequest.java: Updated to use new signatureUpdated tests to reflect new signature:
WrappedPlayerTest: Updated to test with command name and subcommand formatSpigotServerTest: Updated to test with command name and subcommand formatAll static analysis checks pass with errorprone profile.
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.