Skip to content

fix(completion): make PowerShell tab completion work again#1374

Merged
clay-good merged 1 commit into
mainfrom
fix/powershell-empty-switch
Jul 17, 2026
Merged

fix(completion): make PowerShell tab completion work again#1374
clay-good merged 1 commit into
mainfrom
fix/powershell-empty-switch

Conversation

@clay-good

@clay-good clay-good commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Status: LGTM — reproduced, fixed, and verified with a real PowerShell 7.5.4 parser (18 parse errors → 0) and live tab completion.

Fixes #1293

What was wrong

openspec completion install generated a PowerShell script that failed to parse, so completions never worked for any PowerShell user. The generator emitted switch ($positionalIndex) { } with zero clauses for every command whose positional arguments are all path-typed (PowerShell completes paths natively, so those cases produce no clauses) — 18 such blocks in the current registry. An empty switch body is a hard syntax error in PowerShell (Missing condition in switch statement clause), and PowerShell parses the whole file before running it, so one bad block aborted the entire script.

How it was fixed

In generateIndexedPositionalCompletion, the case clauses are now built first; when no positional produces any completion, the whole positional-index block (the token-counting loop plus the switch) is skipped — it existed only to feed the switch, so this is behavior-equivalent and leaves no dead code. Commands with real positional completions are unchanged.

Replication / proof

Generate the script from the real command registry and parse it with PowerShell's own parser:

BEFORE fix: parse errors = 18
  first: Missing condition in switch statement clause. (line 106)
AFTER fix:  parse errors = 0

Dot-sourcing the fixed script in pwsh 7.5.4 and invoking TabExpansion2 returns real completions:

completions for 'openspec val': validate
completions for 'openspec completion ': generate, install, uninstall

Two regression tests added: a unit test for a path-only positional command, and a registry-wide test asserting the generated script never contains an empty switch ($positionalIndex) block. Full suite: 1,860 passed; the only failures are the 17 known environment-only zsh-installer failures on this machine (local oh-my-zsh; CI unaffected).

Notes

  • bash/zsh/fish generators are untouched — empty case bodies are legal in those shells.
  • Pre-existing and out of scope: with an empty command list the outer switch ($command) would also be empty, but the registry is static and never empty, so it's unreachable in practice.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Fixed PowerShell completion scripts failing to load when commands contained only path-based positional parameters.
    • Prevented generation of invalid empty PowerShell switch blocks.
    • Restored tab completion for affected commands.
  • Tests

    • Added coverage to verify generated scripts omit empty positional completion switches and avoid unnecessary positional-index references.

…erShell script

An empty switch body is a parse error in PowerShell, and the generator
emitted one for every command whose positionals are all path-typed
(18 in the current registry). PowerShell parses the entire file before
execution, so the whole completion script failed to load. Skip the
positional-index block when no positional produces completions.

Fixes #1293

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@clay-good
clay-good requested a review from TabishB as a code owner July 16, 2026 13:51
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6168fa35-aee5-4e5a-9c08-fa88ba20c84b

📥 Commits

Reviewing files that changed from the base of the PR and between 0a99f41 and 9659f48.

📒 Files selected for processing (3)
  • .changeset/fix-powershell-empty-switch.md
  • src/core/completions/generators/powershell-generator.ts
  • test/core/completions/generators/powershell-generator.test.ts

📝 Walkthrough

Walkthrough

The PowerShell generator now omits empty positional-index switches. Tests cover commands with no positional completions and the actual command registry, while a changeset documents the fix.

Changes

PowerShell completion generation

Layer / File(s) Summary
Skip empty positional completion switches
src/core/completions/generators/powershell-generator.ts
Precomputes positional clauses, skips entries without completions, and avoids emitting an empty switch ($positionalIndex) block.
Validate generated PowerShell output
test/core/completions/generators/powershell-generator.test.ts, .changeset/fix-powershell-empty-switch.md
Tests custom and registry-based generation, and documents the PowerShell completion fix.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: tabishb

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: fixing PowerShell tab completion by preventing parse-breaking empty switch blocks.
Linked Issues check ✅ Passed The generator fix and regression tests address the linked issue by omitting empty PowerShell switch blocks and restoring completion parsing.
Out of Scope Changes check ✅ Passed All changes are in-scope: generator logic, regression tests, and a changelog entry for the PowerShell completion fix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/powershell-empty-switch

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed: private package registry requires authentication. Disable ESLint in CodeRabbit settings or use public packages.


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.

@alfred-openspec alfred-openspec left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good. The fix is correctly scoped, preserves mixed positional indexing, and includes focused plus registry-wide regression coverage.

@clay-good
clay-good added this pull request to the merge queue Jul 17, 2026
Merged via the queue into main with commit da3907b Jul 17, 2026
14 checks passed
@clay-good
clay-good deleted the fix/powershell-empty-switch branch July 17, 2026 17:03
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.

PowerShell completion script fails to parse: empty switch blocks (Missing condition in switch statement clause)

2 participants