diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java index 90d5f6bc37..73d562fc5f 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/Command.java @@ -258,7 +258,10 @@ public interface Command { * decorated without issue. * * @return the decorated command - * @deprecated use {@link #endlessly()} instead. + * @deprecated PerpetualCommand violates the assumption that execute() doesn't get called after + * isFinished() returns true -- an assumption that should be valid. This was unsafe/undefined + * behavior from the start, and RepeatCommand provides an easy way to achieve similar end + * results with slightly different (and safe) semantics. */ @SuppressWarnings("removal") // PerpetualCommand @Deprecated(forRemoval = true, since = "2023") @@ -266,22 +269,6 @@ public interface Command { return new PerpetualCommand(this); } - /** - * Decorates this command to run endlessly, ignoring its ordinary end conditions. The decorated - * command can still be interrupted or canceled. - * - *

Note: This decorator works by composing this command within a CommandGroup. The command - * cannot be used independently after being decorated, or be re-decorated with a different - * decorator, unless it is manually cleared from the list of grouped commands with {@link - * CommandGroupBase#clearGroupedCommand(Command)}. The decorated command can, however, be further - * decorated without issue. - * - * @return the decorated command - */ - default EndlessCommand endlessly() { - return new EndlessCommand(this); - } - /** * Decorates this command to run repeatedly, restarting it when it ends, until this command is * interrupted. The decorated command can still be canceled. diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/EndlessCommand.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/EndlessCommand.java deleted file mode 100644 index 9ba8c1a291..0000000000 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/EndlessCommand.java +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -package edu.wpi.first.wpilibj2.command; - -import static edu.wpi.first.wpilibj2.command.CommandGroupBase.registerGroupedCommands; -import static edu.wpi.first.wpilibj2.command.CommandGroupBase.requireUngrouped; - -/** - * A command that runs another command endlessly, ignoring that command's end conditions. While this - * class does not extend {@link CommandGroupBase}, it is still considered a CommandGroup, as it - * allows one to compose another command within it; the command instances that are passed to it - * cannot be added to any other groups, or scheduled individually. - * - *

As a rule, CommandGroups require the union of the requirements of their component commands. - * - *

This class is provided by the NewCommands VendorDep - */ -public class EndlessCommand extends CommandBase { - protected final Command m_command; - - /** - * Creates a new EndlessCommand. Will run another command endlessly, ignoring that command's end - * conditions, unless this command itself is interrupted. - * - * @param command the command to run endlessly - */ - public EndlessCommand(Command command) { - requireUngrouped(command); - registerGroupedCommands(command); - m_command = command; - m_requirements.addAll(command.getRequirements()); - } - - @Override - public void initialize() { - m_command.initialize(); - } - - @Override - public void execute() { - m_command.execute(); - } - - @Override - public void end(boolean interrupted) { - m_command.end(interrupted); - } - - @Override - public boolean runsWhenDisabled() { - return m_command.runsWhenDisabled(); - } -} diff --git a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/PerpetualCommand.java b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/PerpetualCommand.java index c165c354ac..9ef643e4a4 100644 --- a/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/PerpetualCommand.java +++ b/wpilibNewCommands/src/main/java/edu/wpi/first/wpilibj2/command/PerpetualCommand.java @@ -17,7 +17,10 @@ import static edu.wpi.first.wpilibj2.command.CommandGroupBase.requireUngrouped; * *

This class is provided by the NewCommands VendorDep * - * @deprecated Replaced by {@link EndlessCommand}. + * @deprecated PerpetualCommand violates the assumption that execute() doesn't get called after + * isFinished() returns true -- an assumption that should be valid. This was unsafe/undefined + * behavior from the start, and RepeatCommand provides an easy way to achieve similar end + * results with slightly different (and safe) semantics. */ @Deprecated(forRemoval = true, since = "2023") public class PerpetualCommand extends CommandBase { diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp index 70d5b5cce3..e26717914b 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/Command.cpp @@ -7,7 +7,6 @@ #include "frc2/command/CommandHelper.h" #include "frc2/command/CommandScheduler.h" #include "frc2/command/ConditionalCommand.h" -#include "frc2/command/EndlessCommand.h" #include "frc2/command/InstantCommand.h" #include "frc2/command/ParallelCommandGroup.h" #include "frc2/command/ParallelDeadlineGroup.h" @@ -91,10 +90,6 @@ PerpetualCommand Command::Perpetually() && { WPI_UNIGNORE_DEPRECATED } -CommandPtr Command::Endlessly() && { - return CommandPtr(std::move(*this).TransferOwnership()).Endlessly(); -} - CommandPtr Command::Repeatedly() && { return CommandPtr(std::move(*this).TransferOwnership()).Repeatedly(); } diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp index 8b124f683c..22665381d9 100644 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp +++ b/wpilibNewCommands/src/main/native/cpp/frc2/command/CommandPtr.cpp @@ -6,7 +6,6 @@ #include "frc2/command/CommandScheduler.h" #include "frc2/command/ConditionalCommand.h" -#include "frc2/command/EndlessCommand.h" #include "frc2/command/InstantCommand.h" #include "frc2/command/ParallelCommandGroup.h" #include "frc2/command/ParallelDeadlineGroup.h" @@ -26,11 +25,6 @@ CommandPtr CommandPtr::Repeatedly() && { return std::move(*this); } -CommandPtr CommandPtr::Endlessly() && { - m_ptr = std::make_unique(std::move(m_ptr)); - return std::move(*this); -} - CommandPtr CommandPtr::AsProxy() && { m_ptr = std::make_unique(std::move(m_ptr)); return std::move(*this); diff --git a/wpilibNewCommands/src/main/native/cpp/frc2/command/EndlessCommand.cpp b/wpilibNewCommands/src/main/native/cpp/frc2/command/EndlessCommand.cpp deleted file mode 100644 index 43714bfea4..0000000000 --- a/wpilibNewCommands/src/main/native/cpp/frc2/command/EndlessCommand.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include "frc2/command/EndlessCommand.h" - -using namespace frc2; - -EndlessCommand::EndlessCommand(std::unique_ptr&& command) { - if (!CommandGroupBase::RequireUngrouped(*command)) { - return; - } - m_command = std::move(command); - m_command->SetGrouped(true); - AddRequirements(m_command->GetRequirements()); -} - -void EndlessCommand::Initialize() { - m_command->Initialize(); -} - -void EndlessCommand::Execute() { - m_command->Execute(); -} - -void EndlessCommand::End(bool interrupted) { - m_command->End(interrupted); -} diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/Command.h b/wpilibNewCommands/src/main/native/include/frc2/command/Command.h index c499f6ef07..6609712880 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/Command.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/Command.h @@ -200,19 +200,21 @@ class Command { * conditions. The decorated command can still be interrupted or canceled. * * @return the decorated command - * @deprecated replace with EndlessCommand + * @deprecated PerpetualCommand violates the assumption that execute() doesn't +get called after isFinished() returns true -- an assumption that should be +valid. This was unsafe/undefined behavior from the start, and RepeatCommand +provides an easy way to achieve similar end results with slightly different (and +safe) semantics. */ - WPI_DEPRECATED("Replace with Endlessly()") + WPI_DEPRECATED( + "PerpetualCommand violates the assumption that execute() doesn't get " + "called after isFinished() returns true -- an assumption that should be " + "valid." + "This was unsafe/undefined behavior from the start, and RepeatCommand " + "provides an easy way to achieve similar end results with slightly " + "different (and safe) semantics.") PerpetualCommand Perpetually() &&; - /** - * Decorates this command to run endlessly, ignoring its ordinary end - * conditions. The decorated command can still be interrupted or canceled. - * - * @return the decorated command - */ - [[nodiscard]] CommandPtr Endlessly() &&; - /** * Decorates this command to run repeatedly, restarting it when it ends, until * this command is interrupted. The decorated command can still be canceled. diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h index dbdbfb6492..74663aa100 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/CommandPtr.h @@ -46,14 +46,6 @@ class CommandPtr final { */ [[nodiscard]] CommandPtr Repeatedly() &&; - /** - * Decorates this command to run endlessly, ignoring its ordinary end - * conditions. The decorated command can still be interrupted or canceled. - * - * @return the decorated command - */ - [[nodiscard]] CommandPtr Endlessly() &&; - /** * Decorates this command to run "by proxy" by wrapping it in a * ProxyScheduleCommand. This is useful for "forking off" from command groups diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/EndlessCommand.h b/wpilibNewCommands/src/main/native/include/frc2/command/EndlessCommand.h deleted file mode 100644 index c47da46f77..0000000000 --- a/wpilibNewCommands/src/main/native/include/frc2/command/EndlessCommand.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#pragma once - -#ifdef _WIN32 -#pragma warning(push) -#pragma warning(disable : 4521) -#endif - -#include -#include - -#include "frc2/command/CommandBase.h" -#include "frc2/command/CommandGroupBase.h" -#include "frc2/command/CommandHelper.h" - -namespace frc2 { -/** - * A command that runs another command endlessly, ignoring that command's - * end conditions. While this class does not extend {@link CommandGroupBase}, - * it is still considered a CommandGroup, as it allows one to compose another - * command within it; the command instances that are passed to it cannot be - * added to any other groups, or scheduled individually. - * - *

As a rule, CommandGroups require the union of the requirements of their - * component commands. - * - * This class is provided by the NewCommands VendorDep - */ -class EndlessCommand : public CommandHelper { - public: - /** - * Creates a new EndlessCommand. Will run another command endlessly, - * ignoring that command's end conditions, unless this command itself is - * interrupted. - * - * @param command the command to run endlessly - */ - explicit EndlessCommand(std::unique_ptr&& command); - - /** - * Creates a new EndlessCommand. Will run another command endlessly, - * ignoring that command's end conditions, unless this command itself is - * interrupted. - * - * @param command the command to run endlessly - */ - template >>> - explicit EndlessCommand(T&& command) - : EndlessCommand(std::make_unique>( - std::forward(command))) {} - - EndlessCommand(EndlessCommand&& other) = default; - - // No copy constructors for command groups - EndlessCommand(const EndlessCommand& other) = delete; - - // Prevent template expansion from emulating copy ctor - EndlessCommand(EndlessCommand&) = delete; - - void Initialize() override; - - void Execute() override; - - void End(bool interrupted) override; - - private: - std::unique_ptr m_command; -}; -} // namespace frc2 - -#ifdef _WIN32 -#pragma warning(pop) -#endif diff --git a/wpilibNewCommands/src/main/native/include/frc2/command/PerpetualCommand.h b/wpilibNewCommands/src/main/native/include/frc2/command/PerpetualCommand.h index b4e7380dbc..2d57a26b49 100644 --- a/wpilibNewCommands/src/main/native/include/frc2/command/PerpetualCommand.h +++ b/wpilibNewCommands/src/main/native/include/frc2/command/PerpetualCommand.h @@ -29,7 +29,11 @@ namespace frc2 { * * This class is provided by the NewCommands VendorDep * - * @deprecated replace with EndlessCommand + * @deprecated PerpetualCommand violates the assumption that execute() doesn't +get called after isFinished() returns true -- an assumption that should be +valid. This was unsafe/undefined behavior from the start, and RepeatCommand +provides an easy way to achieve similar end results with slightly different (and +safe) semantics. */ class PerpetualCommand : public CommandHelper { public: @@ -40,10 +44,16 @@ class PerpetualCommand : public CommandHelper { * * @param command the command to run perpetually */ - WPI_DEPRECATED("Replace with EndlessCommand") + WPI_DEPRECATED( + "PerpetualCommand violates the assumption that execute() doesn't get " + "called after isFinished() returns true -- an assumption that should be " + "valid." + "This was unsafe/undefined behavior from the start, and RepeatCommand " + "provides an easy way to achieve similar end results with slightly " + "different (and safe) semantics.") explicit PerpetualCommand(std::unique_ptr&& command); - WPI_IGNORE_DEPRECATED + /** * Creates a new PerpetualCommand. Will run another command in perpetuity, * ignoring that command's end conditions, unless this command itself is @@ -53,7 +63,13 @@ class PerpetualCommand : public CommandHelper { */ template >>> - WPI_DEPRECATED("Replace with EndlessCommand") + WPI_DEPRECATED( + "PerpetualCommand violates the assumption that execute() doesn't get " + "called after isFinished() returns true -- an assumption that should be " + "valid." + "This was unsafe/undefined behavior from the start, and RepeatCommand " + "provides an easy way to achieve similar end results with slightly " + "different (and safe) semantics.") explicit PerpetualCommand(T&& command) : PerpetualCommand(std::make_unique>( std::forward(command))) {} diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java index 8cfc629200..4296beeb62 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/CommandDecoratorTest.java @@ -201,22 +201,6 @@ class CommandDecoratorTest extends CommandTestBase { } } - @Test - void endlesslyTest() { - try (CommandScheduler scheduler = new CommandScheduler()) { - Command command = new InstantCommand(); - - Command perpetual = command.endlessly(); - - scheduler.schedule(perpetual); - scheduler.run(); - scheduler.run(); - scheduler.run(); - - assertTrue(scheduler.isScheduled(perpetual)); - } - } - @Test void unlessTest() { try (CommandScheduler scheduler = new CommandScheduler()) { diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/EndlessCommandTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/EndlessCommandTest.java deleted file mode 100644 index 9ea067846e..0000000000 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/EndlessCommandTest.java +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -package edu.wpi.first.wpilibj2.command; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.jupiter.api.Test; - -class EndlessCommandTest extends CommandTestBase { - @Test - void endlessCommandScheduleTest() { - try (CommandScheduler scheduler = new CommandScheduler()) { - EndlessCommand command = new EndlessCommand(new InstantCommand()); - - scheduler.schedule(command); - scheduler.run(); - - assertTrue(scheduler.isScheduled(command)); - } - } -} diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelRaceGroupTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelRaceGroupTest.java index 0898b052b3..113bf1bde5 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelRaceGroupTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ParallelRaceGroupTest.java @@ -137,8 +137,8 @@ class ParallelRaceGroupTest extends CommandTestBase { Command command1 = command1Holder.getMock(); MockCommandHolder command2Holder = new MockCommandHolder(true, system2); Command command2 = command2Holder.getMock(); - MockCommandHolder endlessCommandHolder = new MockCommandHolder(true); - Command command3 = new EndlessCommand(endlessCommandHolder.getMock()); + MockCommandHolder command3Holder = new MockCommandHolder(true); + Command command3 = command3Holder.getMock(); Command group1 = new SequentialCommandGroup(command1, command2); assertNotNull(group1); @@ -153,6 +153,7 @@ class ParallelRaceGroupTest extends CommandTestBase { command2Holder.setFinished(true); // at this point the sequential group should be done assertDoesNotThrow(() -> scheduler.run()); + assertFalse(scheduler.isScheduled(group2)); } } diff --git a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ScheduleCommandTest.java b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ScheduleCommandTest.java index 24470c1f3e..9014bc7b96 100644 --- a/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ScheduleCommandTest.java +++ b/wpilibNewCommands/src/test/java/edu/wpi/first/wpilibj2/command/ScheduleCommandTest.java @@ -36,7 +36,7 @@ class ScheduleCommandTest extends CommandTestBase { new SequentialCommandGroup(new InstantCommand(), scheduleCommand); scheduler.schedule(group); - scheduler.schedule(new InstantCommand().endlessly()); + scheduler.schedule(new RunCommand(() -> {})); scheduler.run(); assertDoesNotThrow(scheduler::run); } diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp index d91ecb2e9f..3c69fab10e 100644 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp +++ b/wpilibNewCommands/src/test/native/cpp/frc2/command/CommandDecoratorTest.cpp @@ -6,7 +6,6 @@ #include "CommandTestBase.h" #include "frc2/command/ConditionalCommand.h" -#include "frc2/command/EndlessCommand.h" #include "frc2/command/FunctionalCommand.h" #include "frc2/command/InstantCommand.h" #include "frc2/command/ParallelRaceGroup.h" @@ -120,19 +119,6 @@ TEST_F(CommandDecoratorTest, Perpetually) { EXPECT_TRUE(scheduler.IsScheduled(&command)); } -TEST_F(CommandDecoratorTest, Endlessly) { - CommandScheduler scheduler = GetScheduler(); - - auto command = InstantCommand([] {}, {}).Endlessly(); - - scheduler.Schedule(command); - - scheduler.Run(); - scheduler.Run(); - - EXPECT_TRUE(scheduler.IsScheduled(command)); -} - TEST_F(CommandDecoratorTest, Unless) { CommandScheduler scheduler = GetScheduler(); diff --git a/wpilibNewCommands/src/test/native/cpp/frc2/command/EndlessCommandTest.cpp b/wpilibNewCommands/src/test/native/cpp/frc2/command/EndlessCommandTest.cpp deleted file mode 100644 index 0cf017b078..0000000000 --- a/wpilibNewCommands/src/test/native/cpp/frc2/command/EndlessCommandTest.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) FIRST and other WPILib contributors. -// Open Source Software; you can modify and/or share it under the terms of -// the WPILib BSD license file in the root directory of this project. - -#include "CommandTestBase.h" -#include "frc2/command/InstantCommand.h" - -using namespace frc2; -class EndlessCommandTest : public CommandTestBase {}; - -TEST_F(EndlessCommandTest, EndlessCommandSchedule) { - CommandScheduler scheduler = GetScheduler(); - - bool check = false; - - auto command = InstantCommand([&check] { check = true; }, {}).Endlessly(); - - scheduler.Schedule(command); - scheduler.Run(); - EXPECT_TRUE(scheduler.IsScheduled(command)); - EXPECT_TRUE(check); -}