diff --git a/commandsv3/src/main/java/org/wpilib/command3/Command.java b/commandsv3/src/main/java/org/wpilib/command3/Command.java index f47abc8e80..1b7fe034c8 100644 --- a/commandsv3/src/main/java/org/wpilib/command3/Command.java +++ b/commandsv3/src/main/java/org/wpilib/command3/Command.java @@ -85,7 +85,7 @@ import org.wpilib.units.measure.Time; * // to run when not in use. Interrupting one of the inner commands while it's * // running will cancel the entire sequence. * private Command advancedScoringSequence() { - * return Command.noRequirements().executing(coroutine -> { + * return Command.noRequirements(coroutine -> { * coroutine.await(drivetrain.driveToScoringLocation()); * coroutine.await(elevator.moveToScoringHeight()); * coroutine.await(gripper.release()); @@ -226,15 +226,17 @@ public interface Command { * Creates a command that does not require any hardware; that is, it does not affect the state of * any physical objects. This is useful for commands that do some cleanup or state management, * such as resetting odometry or sensors, that you don't want to interrupt a command that's - * controlling the mechanisms it affects. + * controlling the mechanisms it affects, or for a command composition that you don't want to + * inherit the requirements of its child commands. * *

More configuration options are needed after calling this function before the command can be * created. See {@link StagedCommandBuilder} for details. * + * @param body The command's body. Cannot be null. * @return a builder that can be used to configure the resulting command */ - static NeedsExecutionBuilderStage noRequirements() { - return new StagedCommandBuilder().noRequirements(); + static NeedsNameBuilderStage noRequirements(Consumer body) { + return new StagedCommandBuilder().noRequirements().executing(body); } /** @@ -326,7 +328,7 @@ public interface Command { static NeedsNameBuilderStage waitUntil(BooleanSupplier condition) { requireNonNullParam(condition, "condition", "Command.waitUntil"); - return noRequirements().executing(coroutine -> coroutine.waitUntil(condition)); + return noRequirements(coroutine -> coroutine.waitUntil(condition)); } /** @@ -339,7 +341,7 @@ public interface Command { static NeedsNameBuilderStage waitFor(Time duration) { requireNonNullParam(duration, "duration", "Command.waitFor"); - return noRequirements().executing(coroutine -> coroutine.wait(duration)); + return noRequirements(coroutine -> coroutine.wait(duration)); } /** diff --git a/commandsv3/src/main/java/org/wpilib/command3/Coroutine.java b/commandsv3/src/main/java/org/wpilib/command3/Coroutine.java index 88c710d3cf..06907d48f4 100644 --- a/commandsv3/src/main/java/org/wpilib/command3/Coroutine.java +++ b/commandsv3/src/main/java/org/wpilib/command3/Coroutine.java @@ -79,7 +79,7 @@ public final class Coroutine { * *

{@code
    * Command example() {
-   *   return Command.noRequirements().executing(coroutine -> {
+   *   return Command.noRequirements(coroutine -> {
    *     Command child = ...;
    *     coroutine.fork(child);
    *     // ... do more things
@@ -121,7 +121,7 @@ public final class Coroutine {
    *
    * 
{@code
    * Command example() {
-   *   return Command.noRequirements().executing(coroutine -> {
+   *   return Command.noRequirements(coroutine -> {
    *     Collection innerCommands = ...;
    *     coroutine.fork(innerCommands);
    *     // ... do more things
diff --git a/commandsv3/src/main/java/org/wpilib/command3/Trigger.java b/commandsv3/src/main/java/org/wpilib/command3/Trigger.java
index 8c25cfcb06..32baf60303 100644
--- a/commandsv3/src/main/java/org/wpilib/command3/Trigger.java
+++ b/commandsv3/src/main/java/org/wpilib/command3/Trigger.java
@@ -34,7 +34,7 @@ import org.wpilib.units.measure.Time;
  * canceled when the enclosing command exits.
  *
  * 
{@code
- * Command shootWhileAiming = Command.noRequirements().executing(co -> {
+ * Command shootWhileAiming = Command.noRequirements(co -> {
  *   turret.atTarget.onTrue(shooter.shootOnce());
  *   co.await(turret.lockOnGoal());
  * }).named("Shoot While Aiming");
diff --git a/commandsv3/src/test/java/org/wpilib/command3/BindingScopeTest.java b/commandsv3/src/test/java/org/wpilib/command3/BindingScopeTest.java
index 060edf548d..931911f106 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/BindingScopeTest.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/BindingScopeTest.java
@@ -27,8 +27,7 @@ class BindingScopeTest extends SchedulerTest {
     BindingScope[] scopeRef = new BindingScope[1];
 
     var command =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 coroutine -> {
                   BindingScope scope = BindingScope.createNarrowestScope(m_scheduler);
                   scopeRef[0] = scope;
@@ -49,8 +48,7 @@ class BindingScopeTest extends SchedulerTest {
 
     BindingScope[] scopeRef = new BindingScope[1];
     var command =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 coroutine -> {
                   BindingScope scope = BindingScope.createNarrowestScope(m_scheduler);
                   scopeRef[0] = scope;
diff --git a/commandsv3/src/test/java/org/wpilib/command3/CoroutineTest.java b/commandsv3/src/test/java/org/wpilib/command3/CoroutineTest.java
index 9e32ad9883..69f5718dbb 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/CoroutineTest.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/CoroutineTest.java
@@ -24,8 +24,7 @@ class CoroutineTest extends CommandTestBase {
     var c = new NullCommand();
 
     var all =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.fork(a, b, c);
                   co.park();
@@ -45,8 +44,7 @@ class CoroutineTest extends CommandTestBase {
     AtomicInteger i = new AtomicInteger(0);
 
     var yieldInSynchronized =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   while (true) {
                     synchronized (mutex) {
@@ -68,8 +66,7 @@ class CoroutineTest extends CommandTestBase {
     AtomicInteger i = new AtomicInteger(0);
 
     var yieldInLock =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   while (true) {
                     lock.lock();
@@ -93,8 +90,7 @@ class CoroutineTest extends CommandTestBase {
     AtomicReference escapeeCallback = new AtomicReference<>();
 
     var badCommand =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   escapeeCallback.set(co::yield);
                 })
@@ -111,12 +107,10 @@ class CoroutineTest extends CommandTestBase {
   @SuppressWarnings("CoroutineMayNotBeInScope")
   void usingParentCoroutineInChildThrows() {
     var parent =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 parentCoroutine -> {
                   parentCoroutine.await(
-                      Command.noRequirements()
-                          .executing(
+                      Command.noRequirements(
                               childCoroutine -> {
                                 parentCoroutine.yield();
                               })
@@ -135,10 +129,9 @@ class CoroutineTest extends CommandTestBase {
     AtomicBoolean secondRan = new AtomicBoolean(false);
     AtomicBoolean ranAfterAwait = new AtomicBoolean(false);
 
-    var firstInner = Command.noRequirements().executing(c2 -> firstRan.set(true)).named("First");
+    var firstInner = Command.noRequirements(c2 -> firstRan.set(true)).named("First");
     var secondInner =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 c2 -> {
                   secondRan.set(true);
                   c2.park();
@@ -146,8 +139,7 @@ class CoroutineTest extends CommandTestBase {
             .named("Second");
 
     var outer =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.awaitAny(firstInner, secondInner);
 
diff --git a/commandsv3/src/test/java/org/wpilib/command3/ParallelGroupBuilderTest.java b/commandsv3/src/test/java/org/wpilib/command3/ParallelGroupBuilderTest.java
index 8a32c3a4bc..a7f65ebccf 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/ParallelGroupBuilderTest.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/ParallelGroupBuilderTest.java
@@ -26,8 +26,8 @@ class ParallelGroupBuilderTest {
 
   @Test
   void optionalPopulatesOptionalOnly() {
-    var a = Command.noRequirements().executing(Coroutine::park).named("A");
-    var b = Command.noRequirements().executing(Coroutine::park).named("B");
+    var a = Command.noRequirements(Coroutine::park).named("A");
+    var b = Command.noRequirements(Coroutine::park).named("B");
 
     var group = new ParallelGroupBuilder().optional(a, b).withAutomaticName();
 
@@ -50,8 +50,8 @@ class ParallelGroupBuilderTest {
 
   @Test
   void requiringPopulatesRequiredOnly() {
-    var a = Command.noRequirements().executing(Coroutine::park).named("A");
-    var b = Command.noRequirements().executing(Coroutine::park).named("B");
+    var a = Command.noRequirements(Coroutine::park).named("A");
+    var b = Command.noRequirements(Coroutine::park).named("B");
 
     var group = new ParallelGroupBuilder().requiring(a, b).withAutomaticName();
 
@@ -62,10 +62,10 @@ class ParallelGroupBuilderTest {
 
   @Test
   void mixedRequiredAndOptional() {
-    var reqA = Command.noRequirements().executing(Coroutine::park).named("ReqA");
-    var reqB = Command.noRequirements().executing(Coroutine::park).named("ReqB");
-    var optX = Command.noRequirements().executing(Coroutine::park).named("OptX");
-    var optY = Command.noRequirements().executing(Coroutine::park).named("OptY");
+    var reqA = Command.noRequirements(Coroutine::park).named("ReqA");
+    var reqB = Command.noRequirements(Coroutine::park).named("ReqB");
+    var optX = Command.noRequirements(Coroutine::park).named("OptX");
+    var optY = Command.noRequirements(Coroutine::park).named("OptY");
 
     var group =
         new ParallelGroupBuilder().requiring(reqA, reqB).optional(optX, optY).withAutomaticName();
diff --git a/commandsv3/src/test/java/org/wpilib/command3/ParallelGroupTest.java b/commandsv3/src/test/java/org/wpilib/command3/ParallelGroupTest.java
index bac8725be1..7411e288d6 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/ParallelGroupTest.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/ParallelGroupTest.java
@@ -183,9 +183,9 @@ class ParallelGroupTest extends CommandTestBase {
 
   @Test
   void automaticNameRace() {
-    var a = Command.noRequirements().executing(coroutine -> {}).named("A");
-    var b = Command.noRequirements().executing(coroutine -> {}).named("B");
-    var c = Command.noRequirements().executing(coroutine -> {}).named("C");
+    var a = Command.noRequirements(coroutine -> {}).named("A");
+    var b = Command.noRequirements(coroutine -> {}).named("B");
+    var c = Command.noRequirements(coroutine -> {}).named("C");
 
     var group = new ParallelGroupBuilder().optional(a, b, c).withAutomaticName();
     assertEquals("(A | B | C)", group.name());
@@ -193,9 +193,9 @@ class ParallelGroupTest extends CommandTestBase {
 
   @Test
   void automaticNameAll() {
-    var a = Command.noRequirements().executing(coroutine -> {}).named("A");
-    var b = Command.noRequirements().executing(coroutine -> {}).named("B");
-    var c = Command.noRequirements().executing(coroutine -> {}).named("C");
+    var a = Command.noRequirements(coroutine -> {}).named("A");
+    var b = Command.noRequirements(coroutine -> {}).named("B");
+    var c = Command.noRequirements(coroutine -> {}).named("C");
 
     var group = new ParallelGroupBuilder().requiring(a, b, c).withAutomaticName();
     assertEquals("(A & B & C)", group.name());
@@ -203,9 +203,9 @@ class ParallelGroupTest extends CommandTestBase {
 
   @Test
   void automaticNameDeadline() {
-    var a = Command.noRequirements().executing(coroutine -> {}).named("A");
-    var b = Command.noRequirements().executing(coroutine -> {}).named("B");
-    var c = Command.noRequirements().executing(coroutine -> {}).named("C");
+    var a = Command.noRequirements(coroutine -> {}).named("A");
+    var b = Command.noRequirements(coroutine -> {}).named("B");
+    var c = Command.noRequirements(coroutine -> {}).named("C");
 
     var group = new ParallelGroupBuilder().requiring(a).optional(b, c).withAutomaticName();
     assertEquals("[(A) * (B | C)]", group.name());
diff --git a/commandsv3/src/test/java/org/wpilib/command3/SchedulerCancellationTests.java b/commandsv3/src/test/java/org/wpilib/command3/SchedulerCancellationTests.java
index 9c35df0ddb..82d7754969 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/SchedulerCancellationTests.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/SchedulerCancellationTests.java
@@ -84,7 +84,7 @@ class SchedulerCancellationTests extends CommandTestBase {
 
   @Test
   void cancelsEvictsOnDeck() {
-    var command = Command.noRequirements().executing(Coroutine::park).named("Command");
+    var command = Command.noRequirements(Coroutine::park).named("Command");
     m_scheduler.schedule(command);
     m_scheduler.cancel(command);
     assertFalse(m_scheduler.isScheduledOrRunning(command));
@@ -95,8 +95,7 @@ class SchedulerCancellationTests extends CommandTestBase {
     var ranAfterCancel = new AtomicBoolean(false);
     var commandRef = new AtomicReference(null);
     var command =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.scheduler().cancel(commandRef.get());
                   ranAfterCancel.set(true);
@@ -115,7 +114,7 @@ class SchedulerCancellationTests extends CommandTestBase {
 
   @Test
   void cancelAllEvictsOnDeck() {
-    var command = Command.noRequirements().executing(Coroutine::park).named("Command");
+    var command = Command.noRequirements(Coroutine::park).named("Command");
     m_scheduler.schedule(command);
     m_scheduler.cancelAll();
     assertFalse(m_scheduler.isScheduledOrRunning(command));
@@ -125,7 +124,7 @@ class SchedulerCancellationTests extends CommandTestBase {
   void cancelAllCancelsAll() {
     var commands = new ArrayList(10);
     for (int i = 1; i <= 10; i++) {
-      commands.add(Command.noRequirements().executing(Coroutine::yield).named("Command " + i));
+      commands.add(Command.noRequirements(Coroutine::yield).named("Command " + i));
     }
     commands.forEach(m_scheduler::schedule);
     m_scheduler.run();
@@ -141,8 +140,7 @@ class SchedulerCancellationTests extends CommandTestBase {
   void cancelAllCallsOnCancelHookForRunningCommands() {
     AtomicBoolean ranHook = new AtomicBoolean(false);
     var command =
-        Command.noRequirements()
-            .executing(Coroutine::park)
+        Command.noRequirements(Coroutine::park)
             .whenCanceled(() -> ranHook.set(true))
             .named("Command");
     m_scheduler.schedule(command);
@@ -155,8 +153,7 @@ class SchedulerCancellationTests extends CommandTestBase {
   void cancelAllDoesNotCallOnCancelHookForQueuedCommands() {
     AtomicBoolean ranHook = new AtomicBoolean(false);
     var command =
-        Command.noRequirements()
-            .executing(Coroutine::park)
+        Command.noRequirements(Coroutine::park)
             .whenCanceled(() -> ranHook.set(true))
             .named("Command");
     m_scheduler.schedule(command);
@@ -209,20 +206,16 @@ class SchedulerCancellationTests extends CommandTestBase {
   @Test
   void cancelDeeplyNestedCompositions() {
     Command root =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.await(
-                      Command.noRequirements()
-                          .executing(
+                      Command.noRequirements(
                               co2 -> {
                                 co2.await(
-                                    Command.noRequirements()
-                                        .executing(
+                                    Command.noRequirements(
                                             co3 -> {
                                               co3.await(
-                                                  Command.noRequirements()
-                                                      .executing(Coroutine::park)
+                                                  Command.noRequirements(Coroutine::park)
                                                       .named("Park"));
                                             })
                                         .named("C3"));
diff --git a/commandsv3/src/test/java/org/wpilib/command3/SchedulerConflictTests.java b/commandsv3/src/test/java/org/wpilib/command3/SchedulerConflictTests.java
index e4b4411adf..1bdbd22f03 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/SchedulerConflictTests.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/SchedulerConflictTests.java
@@ -20,8 +20,7 @@ class SchedulerConflictTests extends CommandTestBase {
     var mech = new Mechanism("The Mechanism", m_scheduler);
 
     var group =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.awaitAll(
                       mech.run(Coroutine::park).named("First"),
@@ -64,8 +63,7 @@ class SchedulerConflictTests extends CommandTestBase {
             .named("Second");
 
     var group =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.fork(first);
                   co.fork(second);
@@ -88,25 +86,21 @@ class SchedulerConflictTests extends CommandTestBase {
   void nestedOneShotCompositionsAllRunInOneCycle() {
     var runs = new AtomicInteger(0);
     Supplier makeOneShot =
-        () -> Command.noRequirements().executing(_c -> runs.incrementAndGet()).named("One Shot");
+        () -> Command.noRequirements(_c -> runs.incrementAndGet()).named("One Shot");
     var command =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.fork(makeOneShot.get());
                   co.fork(makeOneShot.get());
                   co.fork(
-                      Command.noRequirements()
-                          .executing(inner -> inner.fork(makeOneShot.get()))
+                      Command.noRequirements(inner -> inner.fork(makeOneShot.get()))
                           .named("Inner"));
                   co.fork(
-                      Command.noRequirements()
-                          .executing(
+                      Command.noRequirements(
                               co2 -> {
                                 co2.fork(makeOneShot.get());
                                 co2.fork(
-                                    Command.noRequirements()
-                                        .executing(
+                                    Command.noRequirements(
                                             co3 -> {
                                               co3.fork(makeOneShot.get());
                                             })
@@ -130,7 +124,7 @@ class SchedulerConflictTests extends CommandTestBase {
     // Child conflicts with and is lower priority than the Top command
     // It should not be scheduled, and the parent command should exit immediately
     var child = mechanism.run(Coroutine::park).named("Child");
-    var parent = Command.noRequirements().executing(co -> co.await(child)).named("Parent");
+    var parent = Command.noRequirements(co -> co.await(child)).named("Parent");
 
     m_scheduler.schedule(top);
     m_scheduler.schedule(parent);
@@ -149,7 +143,7 @@ class SchedulerConflictTests extends CommandTestBase {
     // Child conflicts with and is higher priority than the Top command
     // It should be scheduled, and the top command should be interrupted
     var child = mechanism.run(Coroutine::park).named("Child");
-    var parent = Command.noRequirements().executing(co -> co.await(child)).named("Parent");
+    var parent = Command.noRequirements(co -> co.await(child)).named("Parent");
 
     m_scheduler.schedule(top);
     m_scheduler.schedule(parent);
diff --git a/commandsv3/src/test/java/org/wpilib/command3/SchedulerDefaultCommandTests.java b/commandsv3/src/test/java/org/wpilib/command3/SchedulerDefaultCommandTests.java
index 1d4d18241e..1522603938 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/SchedulerDefaultCommandTests.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/SchedulerDefaultCommandTests.java
@@ -64,8 +64,7 @@ class SchedulerDefaultCommandTests extends CommandTestBase {
     var commandScopedCommand = mech.run(Coroutine::park).named("Command-Scoped Default Command");
 
     var scopingCommand =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   mech.setDefaultCommand(commandScopedCommand);
                   co.park();
@@ -93,8 +92,7 @@ class SchedulerDefaultCommandTests extends CommandTestBase {
 
     var commandScopedCommand = mech.run(Coroutine::park).named("Command-Scoped Default Command");
     var scopingCommand =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   mech.setDefaultCommand(commandScopedCommand);
                   co.park();
@@ -126,8 +124,7 @@ class SchedulerDefaultCommandTests extends CommandTestBase {
     var commandScopedCommand = mech.run(Coroutine::park).named("Command-Scoped Default Command");
 
     final Command scopingCommand =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   mech.setDefaultCommand(commandScopedCommand);
                   co.park();
diff --git a/commandsv3/src/test/java/org/wpilib/command3/SchedulerErrorHandlingTests.java b/commandsv3/src/test/java/org/wpilib/command3/SchedulerErrorHandlingTests.java
index 97e20d83fb..1cc7ab6745 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/SchedulerErrorHandlingTests.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/SchedulerErrorHandlingTests.java
@@ -43,17 +43,14 @@ class SchedulerErrorHandlingTests extends CommandTestBase {
   @Test
   void nestedErrorDetection() {
     var command =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.await(
-                      Command.noRequirements()
-                          .executing(
+                      Command.noRequirements(
                               c2 -> {
                                 new Trigger(m_scheduler, () -> true)
                                     .onTrue(
-                                        Command.noRequirements()
-                                            .executing(
+                                        Command.noRequirements(
                                                 c3 -> {
                                                   // Throws IndexOutOfBoundsException
                                                   var unused = new ArrayList<>(0).get(-1);
@@ -95,10 +92,9 @@ class SchedulerErrorHandlingTests extends CommandTestBase {
 
   @Test
   void commandEncounteringErrorCancelsChildren() {
-    var child = Command.noRequirements().executing(Coroutine::park).named("Child 1");
+    var child = Command.noRequirements(Coroutine::park).named("Child 1");
     var command =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.fork(child);
                   throw new RuntimeException("The exception");
@@ -118,15 +114,13 @@ class SchedulerErrorHandlingTests extends CommandTestBase {
   @Test
   void childCommandEncounteringErrorCancelsParent() {
     var child =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   throw new RuntimeException("The exception"); // note: bubbles up to the parent
                 })
             .named("Child 1");
     var command =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.await(child);
                   co.park(); // pretend other things would happen after the child
@@ -145,16 +139,14 @@ class SchedulerErrorHandlingTests extends CommandTestBase {
   @SuppressWarnings("PMD.CompareObjectsWithEquals")
   void childCommandEncounteringErrorAfterRemountCancelsParent() {
     var child =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.yield();
                   throw new RuntimeException("The exception"); // does not bubble up to the parent
                 })
             .named("Child 1");
     var command =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.await(child);
                   co.park(); // pretend other things would happen after the child
diff --git a/commandsv3/src/test/java/org/wpilib/command3/SchedulerSideloadFunctionTests.java b/commandsv3/src/test/java/org/wpilib/command3/SchedulerSideloadFunctionTests.java
index 1da2e2a561..c6b0ff92aa 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/SchedulerSideloadFunctionTests.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/SchedulerSideloadFunctionTests.java
@@ -41,7 +41,7 @@ class SchedulerSideloadFunctionTests extends CommandTestBase {
 
   @Test
   void sideloadSchedulingCommand() {
-    var command = Command.noRequirements().executing(Coroutine::park).named("Command");
+    var command = Command.noRequirements(Coroutine::park).named("Command");
     // one-shot sideload forks a command and immediately exits
     m_scheduler.sideload(co -> co.fork(command));
     m_scheduler.run();
@@ -51,10 +51,9 @@ class SchedulerSideloadFunctionTests extends CommandTestBase {
 
   @Test
   void childCommandEscapesViaSideload() {
-    var child = Command.noRequirements().executing(Coroutine::park).named("Child");
+    var child = Command.noRequirements(Coroutine::park).named("Child");
     var parent =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 parentCoroutine -> {
                   m_scheduler.sideload(sideloadCoroutine -> sideloadCoroutine.fork(child));
                 })
@@ -73,7 +72,7 @@ class SchedulerSideloadFunctionTests extends CommandTestBase {
 
   @Test
   void sideloadCancelingCommand() {
-    var command = Command.noRequirements().executing(Coroutine::park).named("Command");
+    var command = Command.noRequirements(Coroutine::park).named("Command");
     m_scheduler.schedule(command);
     m_scheduler.run();
     assertTrue(m_scheduler.isRunning(command), "command should have started");
@@ -89,7 +88,7 @@ class SchedulerSideloadFunctionTests extends CommandTestBase {
   void sideloadAffectsStateForTriggerInSameCycle() {
     AtomicBoolean signal = new AtomicBoolean(false);
     var trigger = new Trigger(m_scheduler, signal::get);
-    var command = Command.noRequirements().executing(Coroutine::park).named("Command");
+    var command = Command.noRequirements(Coroutine::park).named("Command");
     trigger.onTrue(command);
     m_scheduler.sideload(co -> signal.set(true));
 
diff --git a/commandsv3/src/test/java/org/wpilib/command3/SchedulerTelemetryTests.java b/commandsv3/src/test/java/org/wpilib/command3/SchedulerTelemetryTests.java
index 46def5a11e..aa370ba5c7 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/SchedulerTelemetryTests.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/SchedulerTelemetryTests.java
@@ -20,8 +20,8 @@ class SchedulerTelemetryTests extends CommandTestBase {
     m_scheduler.schedule(group);
     m_scheduler.run();
 
-    var scheduledCommand1 = Command.noRequirements().executing(Coroutine::park).named("Command 1");
-    var scheduledCommand2 = Command.noRequirements().executing(Coroutine::park).named("Command 2");
+    var scheduledCommand1 = Command.noRequirements(Coroutine::park).named("Command 1");
+    var scheduledCommand2 = Command.noRequirements(Coroutine::park).named("Command 2");
     m_scheduler.schedule(scheduledCommand1);
     m_scheduler.schedule(scheduledCommand2);
 
diff --git a/commandsv3/src/test/java/org/wpilib/command3/SchedulerTest.java b/commandsv3/src/test/java/org/wpilib/command3/SchedulerTest.java
index 4db9d272d7..5e222073a8 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/SchedulerTest.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/SchedulerTest.java
@@ -18,8 +18,7 @@ class SchedulerTest extends CommandTestBase {
     var enabled = new AtomicBoolean(false);
     var ran = new AtomicBoolean(false);
     var command =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 coroutine -> {
                   do {
                     coroutine.yield();
@@ -58,8 +57,7 @@ class SchedulerTest extends CommandTestBase {
 
     for (int cmdCount = 0; cmdCount < numCommands; cmdCount++) {
       var command =
-          Command.noRequirements()
-              .executing(
+          Command.noRequirements(
                   coroutine -> {
                     for (int i = 0; i < iterations; i++) {
                       mechanism.m_x++;
@@ -114,8 +112,7 @@ class SchedulerTest extends CommandTestBase {
 
     // the group has no requirements, but can schedule child commands that do
     var group =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.awaitAll(
                       m1.run(Coroutine::park).named("M1 Command"),
diff --git a/commandsv3/src/test/java/org/wpilib/command3/SchedulerTimingTests.java b/commandsv3/src/test/java/org/wpilib/command3/SchedulerTimingTests.java
index 99d39dc63d..bc8fc84201 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/SchedulerTimingTests.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/SchedulerTimingTests.java
@@ -25,8 +25,7 @@ class SchedulerTimingTests extends CommandTestBase {
     // equivalent to calling Coroutine.park(). No deleterious side effects other than stalling
     // the command
     AtomicReference commandRef = new AtomicReference<>();
-    var command =
-        Command.noRequirements().executing(co -> co.await(commandRef.get())).named("Self Await");
+    var command = Command.noRequirements(co -> co.await(commandRef.get())).named("Self Await");
     commandRef.set(command);
 
     m_scheduler.schedule(command);
@@ -49,8 +48,8 @@ class SchedulerTimingTests extends CommandTestBase {
     //
     // Externally canceling child allows parent to continue
     // Externally canceling parent cancels both
-    var parent = Command.noRequirements().executing(co -> co.await(childRef.get())).named("Parent");
-    var child = Command.noRequirements().executing(co -> co.await(parentRef.get())).named("Child");
+    var parent = Command.noRequirements(co -> co.await(childRef.get())).named("Parent");
+    var child = Command.noRequirements(co -> co.await(parentRef.get())).named("Child");
     parentRef.set(parent);
     childRef.set(child);
 
@@ -87,8 +86,7 @@ class SchedulerTimingTests extends CommandTestBase {
     //
     // Externally canceling either command allows the other to exit
     var command1 =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.yield();
                   co.await(ref2.get());
@@ -96,8 +94,7 @@ class SchedulerTimingTests extends CommandTestBase {
                 })
             .named("Command 1");
     var command2 =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.yield();
                   co.await(ref1.get());
@@ -134,8 +131,7 @@ class SchedulerTimingTests extends CommandTestBase {
     AtomicInteger runCount = new AtomicInteger(0);
 
     var inner =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   runCount.incrementAndGet();
                   co.yield();
@@ -145,7 +141,7 @@ class SchedulerTimingTests extends CommandTestBase {
                 })
             .named("Inner");
 
-    var outer = Command.noRequirements().executing(co -> co.await(inner)).named("Outer");
+    var outer = Command.noRequirements(co -> co.await(inner)).named("Outer");
     m_scheduler.schedule(outer);
     m_scheduler.run();
 
@@ -159,8 +155,7 @@ class SchedulerTimingTests extends CommandTestBase {
 
     AtomicBoolean completedWait = new AtomicBoolean(false);
     var command =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.wait(Milliseconds.of(1));
                   completedWait.set(true);
@@ -184,8 +179,7 @@ class SchedulerTimingTests extends CommandTestBase {
     RobotController.setTimeSource(time::get);
     AtomicBoolean completedWait = new AtomicBoolean(false);
     var command =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.wait(Milliseconds.of(1));
                   completedWait.set(true);
@@ -212,8 +206,7 @@ class SchedulerTimingTests extends CommandTestBase {
   void awaitingExitsImmediatelyWithoutAOneLoopDelay() {
     AtomicInteger innerRuns = new AtomicInteger(0);
     var inner =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   // executed immediately when forked
                   innerRuns.incrementAndGet();
@@ -224,7 +217,7 @@ class SchedulerTimingTests extends CommandTestBase {
                 })
             .named("Inner");
 
-    var outer = Command.noRequirements().executing(co -> co.await(inner)).named("Outer");
+    var outer = Command.noRequirements(co -> co.await(inner)).named("Outer");
     m_scheduler.schedule(outer);
 
     // First run: runs outer, forks inner, inner runs to its first yield, outer yields
diff --git a/commandsv3/src/test/java/org/wpilib/command3/SequentialGroupBuilderTest.java b/commandsv3/src/test/java/org/wpilib/command3/SequentialGroupBuilderTest.java
index b97bfdac8b..e9e19436f6 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/SequentialGroupBuilderTest.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/SequentialGroupBuilderTest.java
@@ -14,7 +14,7 @@ import org.junit.jupiter.api.Test;
 class SequentialGroupBuilderTest {
   @Test
   void andThenSingle() {
-    var c1 = Command.noRequirements().executing(Coroutine::park).named("C1");
+    var c1 = Command.noRequirements(Coroutine::park).named("C1");
 
     var builder = new SequentialGroupBuilder();
     var sequence = builder.andThen(c1).named("Seq");
@@ -25,8 +25,8 @@ class SequentialGroupBuilderTest {
 
   @Test
   void andThenMultiple() {
-    var c1 = Command.noRequirements().executing(Coroutine::park).named("C1");
-    var c2 = Command.noRequirements().executing(Coroutine::park).named("C2");
+    var c1 = Command.noRequirements(Coroutine::park).named("C1");
+    var c2 = Command.noRequirements(Coroutine::park).named("C2");
 
     var builder = new SequentialGroupBuilder();
     var sequence = builder.andThen(c1, c2).named("Seq");
@@ -38,8 +38,8 @@ class SequentialGroupBuilderTest {
 
   @Test
   void andThenRepeated() {
-    var c1 = Command.noRequirements().executing(Coroutine::park).named("C1");
-    var c2 = Command.noRequirements().executing(Coroutine::park).named("C2");
+    var c1 = Command.noRequirements(Coroutine::park).named("C1");
+    var c2 = Command.noRequirements(Coroutine::park).named("C2");
 
     var builder = new SequentialGroupBuilder();
     var sequence = builder.andThen(c1).andThen(c2).named("Seq");
@@ -69,7 +69,7 @@ class SequentialGroupBuilderTest {
 
   @Test
   void untilReturnsParallelGroup() {
-    var c1 = Command.noRequirements().executing(Coroutine::park).named("C1");
+    var c1 = Command.noRequirements(Coroutine::park).named("C1");
     var builder = new SequentialGroupBuilder();
     var sequence = builder.andThen(c1).until(() -> false).named("Seq");
     assertInstanceOf(ParallelGroup.class, sequence);
@@ -91,7 +91,7 @@ class SequentialGroupBuilderTest {
 
   @Test
   void automaticNameWithOneCommand() {
-    var c1 = Command.noRequirements().executing(Coroutine::park).named("C1");
+    var c1 = Command.noRequirements(Coroutine::park).named("C1");
     var builder = new SequentialGroupBuilder();
     var sequence = builder.andThen(c1).withAutomaticName();
     assertEquals("C1", sequence.name());
@@ -99,8 +99,8 @@ class SequentialGroupBuilderTest {
 
   @Test
   void automaticNameWithMultipleCommands() {
-    var c1 = Command.noRequirements().executing(Coroutine::park).named("C1");
-    var c2 = Command.noRequirements().executing(Coroutine::park).named("C2");
+    var c1 = Command.noRequirements(Coroutine::park).named("C1");
+    var c2 = Command.noRequirements(Coroutine::park).named("C2");
     var builder = new SequentialGroupBuilder();
     var sequence = builder.andThen(c1, c2).withAutomaticName();
     assertEquals("C1 -> C2", sequence.name());
diff --git a/commandsv3/src/test/java/org/wpilib/command3/SequentialGroupTest.java b/commandsv3/src/test/java/org/wpilib/command3/SequentialGroupTest.java
index b4863c2f4a..16f0bb6d02 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/SequentialGroupTest.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/SequentialGroupTest.java
@@ -15,7 +15,7 @@ import org.junit.jupiter.api.Test;
 class SequentialGroupTest extends CommandTestBase {
   @Test
   void single() {
-    var command = Command.noRequirements().executing(Coroutine::yield).named("The Command");
+    var command = Command.noRequirements(Coroutine::yield).named("The Command");
 
     var sequence = new SequentialGroup("The Sequence", List.of(command));
     m_scheduler.schedule(sequence);
@@ -33,8 +33,8 @@ class SequentialGroupTest extends CommandTestBase {
 
   @Test
   void twoCommands() {
-    var c1 = Command.noRequirements().executing(Coroutine::yield).named("C1");
-    var c2 = Command.noRequirements().executing(Coroutine::yield).named("C2");
+    var c1 = Command.noRequirements(Coroutine::yield).named("C1");
+    var c2 = Command.noRequirements(Coroutine::yield).named("C2");
 
     var sequence = new SequentialGroup("C1 > C2", List.of(c1, c2));
     m_scheduler.schedule(sequence);
diff --git a/commandsv3/src/test/java/org/wpilib/command3/TriggerTest.java b/commandsv3/src/test/java/org/wpilib/command3/TriggerTest.java
index 65e1d275a7..366284e575 100644
--- a/commandsv3/src/test/java/org/wpilib/command3/TriggerTest.java
+++ b/commandsv3/src/test/java/org/wpilib/command3/TriggerTest.java
@@ -17,7 +17,7 @@ class TriggerTest extends CommandTestBase {
   void onTrue() {
     var signal = new AtomicBoolean(false);
     var trigger = new Trigger(m_scheduler, signal::get);
-    var command = Command.noRequirements().executing(Coroutine::park).named("Command");
+    var command = Command.noRequirements(Coroutine::park).named("Command");
     trigger.onTrue(command);
 
     signal.set(true);
@@ -34,7 +34,7 @@ class TriggerTest extends CommandTestBase {
   void onFalse() {
     var signal = new AtomicBoolean(false);
     var trigger = new Trigger(m_scheduler, signal::get);
-    var command = Command.noRequirements().executing(Coroutine::park).named("Command");
+    var command = Command.noRequirements(Coroutine::park).named("Command");
     trigger.onFalse(command);
 
     m_scheduler.run();
@@ -51,7 +51,7 @@ class TriggerTest extends CommandTestBase {
   void whileTrue() {
     var signal = new AtomicBoolean(false);
     var trigger = new Trigger(m_scheduler, signal::get);
-    var command = Command.noRequirements().executing(Coroutine::park).named("Command");
+    var command = Command.noRequirements(Coroutine::park).named("Command");
     trigger.whileTrue(command);
 
     signal.set(true);
@@ -68,7 +68,7 @@ class TriggerTest extends CommandTestBase {
   void whileFalse() {
     var signal = new AtomicBoolean(false);
     var trigger = new Trigger(m_scheduler, signal::get);
-    var command = Command.noRequirements().executing(Coroutine::park).named("Command");
+    var command = Command.noRequirements(Coroutine::park).named("Command");
     trigger.whileFalse(command);
 
     m_scheduler.run();
@@ -84,7 +84,7 @@ class TriggerTest extends CommandTestBase {
   void toggleOnTrue() {
     var signal = new AtomicBoolean(false);
     var trigger = new Trigger(m_scheduler, signal::get);
-    var command = Command.noRequirements().executing(Coroutine::park).named("Command");
+    var command = Command.noRequirements(Coroutine::park).named("Command");
     trigger.toggleOnTrue(command);
 
     m_scheduler.run();
@@ -107,7 +107,7 @@ class TriggerTest extends CommandTestBase {
   void toggleOnFalse() {
     var signal = new AtomicBoolean(false);
     var trigger = new Trigger(m_scheduler, signal::get);
-    var command = Command.noRequirements().executing(Coroutine::park).named("Command");
+    var command = Command.noRequirements(Coroutine::park).named("Command");
     trigger.toggleOnFalse(command);
 
     m_scheduler.run();
@@ -128,8 +128,7 @@ class TriggerTest extends CommandTestBase {
     var innerSignal = new AtomicBoolean(false);
 
     var inner =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   while (true) {
                     innerRan.set(true);
@@ -139,8 +138,7 @@ class TriggerTest extends CommandTestBase {
             .named("Inner");
 
     var outer =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   new Trigger(m_scheduler, innerSignal::get).onTrue(inner);
                   // If we yield, then the outer command exits and immediately cancels the
@@ -170,7 +168,7 @@ class TriggerTest extends CommandTestBase {
     var triggerSignal = new AtomicBoolean(false);
     var trigger = new Trigger(m_scheduler, triggerSignal::get);
 
-    var command = Command.noRequirements().executing(Coroutine::park).named("Command");
+    var command = Command.noRequirements(Coroutine::park).named("Command");
     trigger.addBinding(scope, BindingType.RUN_WHILE_HIGH, command);
 
     triggerSignal.set(true);
@@ -209,7 +207,7 @@ class TriggerTest extends CommandTestBase {
     var triggerSignal = new AtomicBoolean(false);
     var trigger = new Trigger(m_scheduler, triggerSignal::get);
 
-    var command = Command.noRequirements().executing(Coroutine::park).named("Command");
+    var command = Command.noRequirements(Coroutine::park).named("Command");
     trigger.whileTrue(command);
 
     triggerSignal.set(true);
@@ -230,8 +228,7 @@ class TriggerTest extends CommandTestBase {
     var triggeredCommandRan = new AtomicBoolean(false);
 
     var inner =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   triggeredCommandRan.set(true);
                   co.park();
@@ -239,8 +236,7 @@ class TriggerTest extends CommandTestBase {
             .named("Inner");
 
     var awaited =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   co.yield();
                   condition.set(true);
@@ -248,8 +244,7 @@ class TriggerTest extends CommandTestBase {
             .named("Awaited");
 
     var outer =
-        Command.noRequirements()
-            .executing(
+        Command.noRequirements(
                 co -> {
                   new Trigger(m_scheduler, condition::get).onTrue(inner);
                   co.await(awaited);
diff --git a/design-docs/commands-v3.md b/design-docs/commands-v3.md
index d9d598efa1..1dc642413a 100644
--- a/design-docs/commands-v3.md
+++ b/design-docs/commands-v3.md
@@ -144,7 +144,7 @@ void bindDriveButtons() {
 Trigger atScoringPosition = new Trigger(() -> getPosition().isNear(kScoringPosition));
 
 Command autonomous() {
-  return Command.noRequirements().executing(coroutine -> {
+  return Command.noRequirements(coroutine -> {
     // This binding only exists while the autonomous command is running
     atScoringPosition.onTrue(score());
 
@@ -212,7 +212,7 @@ class ExampleOpmode extends PeriodicOpMode {
     robot.gamepad.leftBumper().onTrue(robot.mechanism.run(...).named("Bound Command"));
 
     // A manually scheduled command in an opmode will be canceled when the opmode exits if it hasn't already exited on its own
-    Scheduler.getInstance().schedule(Command.noRequirements().executing(coroutine -> {
+    Scheduler.getInstance().schedule(Command.noRequirements(coroutine -> {
       // Change the default command while this command is running.
       // It will be reset to the opmode-scoped default command when this command exits.
       // If no opmode-scoped default command exists, it will be reset to the global default command.
@@ -255,7 +255,7 @@ outside its command makes no sense, and an error will be thrown if attempting to
 
 ```java
 Coroutine coroutine;
-var badCommand = Command.noRequirements().executing(co -> {
+var badCommand = Command.noRequirements(co -> {
   coroutine = co;
 }).named("Do not do this");
 
@@ -357,13 +357,10 @@ compilation error.
 // OK - requirements, body, and name are all provided
 // Each builder method returns a different builder object that provides methods
 // for progressing to the next stage.
-Command command = Command.noRequirements().executing(...).named("Name");
+Command command = Command.noRequirements(...).named("Name");
 
 // Compilation error! Missing the command body
-Command command = Command.noRequirements().named("Name");
-
-// Compilation error! Missing the command name
-Command command = Command.noRequirements().executing(...);
+Command command = Command.noRequirements(...);
 ```
 
 #### Forced Naming