Skip to content

fix: Async setup and input cleanup now carry cancellation tokens - #1594

Merged
hatayama merged 4 commits into
v3-betafrom
feature/hatayama/add-async-cancellation-tokens
Jul 7, 2026
Merged

hatayama merged 4 commits into
v3-betafrom
feature/hatayama/add-async-cancellation-tokens

Conversation

@hatayama

@hatayama hatayama commented Jul 7, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Setup wizard async workflows now use Task-based cores with CancellationToken ct instead of async void bodies.
  • Mouse and keyboard input cleanup helpers now accept CancellationToken ct while preserving uncancelable release paths for held input state.

User Impact

  • Async setup and input cleanup paths are easier to cancel and reason about without changing the visible setup or input simulation behavior.
  • Held input cleanup still runs even when the originating operation is canceled, preventing synthetic input from being left active.

Changes

  • Add a source guard for the R2-5 refactor target files so async methods keep the standard CancellationToken ct parameter.
  • Convert Setup Wizard event handlers into void wrappers that call cancellable Task-based implementations.
  • Add ct parameters to simulate mouse/keyboard release helpers and pass the existing uncancelable cleanup token where cleanup must complete.

Verification

  • dist/darwin-arm64/uloop clear-console --project-path "<PROJECT_ROOT>"
  • dist/darwin-arm64/uloop compile --project-path "<PROJECT_ROOT>"
  • dist/darwin-arm64/uloop run-tests --project-path "<PROJECT_ROOT>" --test-mode EditMode --filter-type exact --filter-value "io.github.hatayama.UnityCliLoop.Tests.Editor.StaticFacadeStateGuardTests.RefactorTargets_WhenDeclaringAsyncMethods_RequireCancellationTokenCt"
  • dist/darwin-arm64/uloop run-tests --project-path "<PROJECT_ROOT>" --test-mode EditMode --filter-type regex --filter-value "StaticFacadeStateGuardTests"
  • dist/darwin-arm64/uloop run-tests --project-path "<PROJECT_ROOT>" --test-mode EditMode --filter-type regex --filter-value "InputSystemOptionalCompileGuardTests|PlayModeToolPreflightServiceTests"

Convert setup wizard async UI handlers to Task-based cores with CancellationToken ct and add a source guard for the R2-5 target files. Add ct parameters to mouse and keyboard release helpers while preserving uncancelable cleanup paths for held input state.
@coderabbitai

coderabbitai Bot commented Jul 7, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@hatayama, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 40 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a547f35a-cd16-46e3-99d1-d886b3680415

📥 Commits

Reviewing files that changed from the base of the PR and between 8c3642f and ab3bfa4.

📒 Files selected for processing (1)
  • Assets/Tests/Editor/StaticFacadeStateGuardTests.cs
📝 Walkthrough

Walkthrough

Adds a static async-method guard for CancellationToken ct, and threads cancellation through keyboard, mouse, and setup wizard editor flows, including cleanup paths and setup/install operations.

Changes

CancellationToken Propagation

Layer / File(s) Summary
Static guard test
Assets/Tests/Editor/StaticFacadeStateGuardTests.cs
Adds allowlisted target files, regex patterns for async method signatures and exact CancellationToken ct matching, a line-number helper, and NUnit coverage for the scan and regex behavior.
SimulateKeyboardUseCase token threading
Packages/src/Editor/FirstPartyTools/SimulateKeyboard/SimulateKeyboardUseCase.cs
Passes explicit cancellation tokens through press, keydown rollback, keyup release, and timed cleanup paths, and refactors release helpers to accept and propagate the token into main-thread switching and scheduled updates.
SimulateMouseInputUseCase token threading
Packages/src/Editor/FirstPartyTools/SimulateMouseInput/SimulateMouseInputUseCase.cs
Passes explicit cancellation tokens through click and long-press release paths, refactors the button release helper to accept and use the token, and propagates cancellation in timed cleanup.
SetupWizardWindow async/cancellation refactor
Packages/src/Editor/Presentation/Setup/SetupWizardWindow.cs
Converts refresh, CLI install, repair, and skills install flows from async void to Task-returning methods with cancellation tokens, and threads the token through CLI version refresh, repair checks, prompt handling, and skill file installation.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SetupWizardWindow
  participant RefreshUIAsync
  participant HandleInstallCliAsync
  participant HandleRepairCliPathSetup
  participant HandleInstallSkillsAsync

  SetupWizardWindow->>RefreshUIAsync: RefreshUIAsync(bool, ct)
  RefreshUIAsync->>RefreshUIAsync: ForceRefreshCliVersionAsync(ct)
  HandleInstallCliAsync->>HandleRepairCliPathSetup: HandleRepairCliPathSetup(ct)
  HandleInstallCliAsync->>HandleInstallCliAsync: InstallGlobalCliAsync(ct)
  HandleInstallSkillsAsync->>HandleInstallSkillsAsync: InstallSkillFilesAsync(ct)
Loading

Possibly related PRs

  • hatayama/unity-cli-loop#1565: Both PRs modify SetupWizardWindow's skills-install flow, including the HandleInstallSkills orchestration path.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: async setup and input cleanup now carry cancellation tokens.
Description check ✅ Passed The description is directly related to the changeset and accurately summarizes the setup, input cleanup, and guard updates.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/hatayama/add-async-cancellation-tokens

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread Assets/Tests/Editor/StaticFacadeStateGuardTests.cs Outdated
Require the R2-5 source guard to match the exact CancellationToken ct parameter name so near-miss names such as cts do not satisfy the convention.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
Assets/Tests/Editor/StaticFacadeStateGuardTests.cs (1)

90-97: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Regex guard has false-negative gaps for method signatures it can't match.

AsyncMethodSignaturePattern requires an explicit access modifier (private|internal|public|protected) before async, so an implicit-private async method (no leading modifier) would be silently skipped instead of flagged. Similarly, Task(?:<[^>]+>)? can't handle a nested generic return type like Task<List<string>> — the pattern fails to match the whole signature (since [^>]+ stops at the first >), so such a method would also be silently skipped by the guard rather than reported as a violation. Neither case currently exists in the target files, but the guard's whole purpose is preventing future regressions, so a silent skip defeats it.

♻️ Possible mitigation
 private static readonly Regex AsyncMethodSignaturePattern = new Regex(
-    @"\b(?:private|internal|public|protected)\s+(?:static\s+)?async\s+(?:void|Task(?:<[^>]+>)?)\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)",
+    @"\basync\s+(?:void|Task(?:<[^)]+>)?)\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)",
     RegexOptions.Compiled | RegexOptions.Singleline);

(Dropping the mandatory-modifier requirement widens matches to any async method regardless of visibility keyword ordering; nested generics still need a more permissive inner class, e.g. [^)]+ up to the method's opening paren, since > no longer needs excluding.)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Assets/Tests/Editor/StaticFacadeStateGuardTests.cs` around lines 90 - 97,
Update StaticFacadeStateGuardTests so AsyncMethodSignaturePattern does not
silently miss async methods with implicit-private visibility or nested generic
Task return types. Relax the modifier portion to match async methods regardless
of whether a visibility keyword is present, and make the return-type portion
permissive enough to capture nested generics like Task<List<string>> before the
parameter list. Keep the change localized to AsyncMethodSignaturePattern and
verify the guard still identifies async method names for the existing test
parsing logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@Assets/Tests/Editor/StaticFacadeStateGuardTests.cs`:
- Around line 90-97: Update StaticFacadeStateGuardTests so
AsyncMethodSignaturePattern does not silently miss async methods with
implicit-private visibility or nested generic Task return types. Relax the
modifier portion to match async methods regardless of whether a visibility
keyword is present, and make the return-type portion permissive enough to
capture nested generics like Task<List<string>> before the parameter list. Keep
the change localized to AsyncMethodSignaturePattern and verify the guard still
identifies async method names for the existing test parsing logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 354b1e2e-fd7e-4f88-889a-c21605e0fdcc

📥 Commits

Reviewing files that changed from the base of the PR and between c41526c and 611fbff.

📒 Files selected for processing (4)
  • Assets/Tests/Editor/StaticFacadeStateGuardTests.cs
  • Packages/src/Editor/FirstPartyTools/SimulateKeyboard/SimulateKeyboardUseCase.cs
  • Packages/src/Editor/FirstPartyTools/SimulateMouseInput/SimulateMouseInputUseCase.cs
  • Packages/src/Editor/Presentation/Setup/SetupWizardWindow.cs

Cover implicit-private async methods and nested generic Task returns so the R2-5 cancellation token guard does not silently skip future async methods.
@hatayama

hatayama commented Jul 7, 2026

Copy link
Copy Markdown
Owner Author

CodeRabbit nitpick about AsyncMethodSignaturePattern was valid. Fixed in 8c3642f by allowing implicit-private async methods and nested generic Task returns, with a regression assertion covering async Task<List<string>> LoadAsync(CancellationToken ct). Re-ran Unity compile and StaticFacadeStateGuardTests successfully.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
Assets/Tests/Editor/StaticFacadeStateGuardTests.cs (1)

90-92: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Regex still misses generic async methods; could silently skip a violation.

The method-name capture ([A-Za-z_][A-Za-z0-9_]*)\s*\( won't match generic methods like async Task<T> Foo<T>(...) (the <T> between name and ( breaks the match), so such methods would be silently excluded from the guard scan instead of being flagged for missing CancellationToken ct. Low risk today given the small allowlist, but worth hardening since this guard's whole purpose is to catch exactly this class of omission.

♻️ Optional hardening to also capture generic type parameters
-            @"\b(?:(?:private|internal|public|protected)\s+)?(?:static\s+)?async\s+(?:void|Task(?:<[^()\n]+>)?)\s+([A-Za-z_][A-Za-z0-9_]*)\s*\(([^)]*)\)",
+            @"\b(?:(?:private|internal|public|protected)\s+)?(?:static\s+)?async\s+(?:void|Task(?:<[^()\n]+>)?)\s+([A-Za-z_][A-Za-z0-9_]*)\s*(?:<[^()\n]+>)?\s*\(([^)]*)\)",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Assets/Tests/Editor/StaticFacadeStateGuardTests.cs` around lines 90 - 92, The
AsyncMethodSignaturePattern in StaticFacadeStateGuardTests only matches
non-generic async method names, so generic methods like Foo<T> are skipped by
the guard scan. Update the regex to allow optional generic type parameter
clauses after the method name and before the parameter list, so generic async
methods are still captured and checked for the missing CancellationToken ct
requirement.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@Assets/Tests/Editor/StaticFacadeStateGuardTests.cs`:
- Around line 90-92: The AsyncMethodSignaturePattern in
StaticFacadeStateGuardTests only matches non-generic async method names, so
generic methods like Foo<T> are skipped by the guard scan. Update the regex to
allow optional generic type parameter clauses after the method name and before
the parameter list, so generic async methods are still captured and checked for
the missing CancellationToken ct requirement.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d50b8656-7356-4328-bec7-87336e6a60ac

📥 Commits

Reviewing files that changed from the base of the PR and between 611fbff and 8c3642f.

📒 Files selected for processing (1)
  • Assets/Tests/Editor/StaticFacadeStateGuardTests.cs

Allow optional generic method type parameters so the cancellation-token source guard cannot skip async methods such as Foo<T>.
@hatayama

hatayama commented Jul 7, 2026

Copy link
Copy Markdown
Owner Author

CodeRabbit follow-up about generic method type parameters was also valid. Fixed in ab3bfa4 by allowing optional generic method clauses such as Foo<T>(...); the regression assertion now covers async Task<List<string>> LoadAsync<T>(CancellationToken ct). Re-ran Unity compile and StaticFacadeStateGuardTests successfully.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant