Skip to content

feat(theme-check-vscode): surface orphaned files on startup#1218

Open
ryandiginomad wants to merge 2 commits into
Shopify:mainfrom
ryandiginomad:feat/970-orphaned-files-on-boot
Open

feat(theme-check-vscode): surface orphaned files on startup#1218
ryandiginomad wants to merge 2 commits into
Shopify:mainfrom
ryandiginomad:feat/970-orphaned-files-on-boot

Conversation

@ryandiginomad

@ryandiginomad ryandiginomad commented May 31, 2026

Copy link
Copy Markdown
Contributor

What are you adding in this PR?

Closes #970.

theme-graph already knows which files are orphaned (dead code), and there's a Liquid Theme Check: Find dead code command to list them — but it's easy to miss because you have to know to run it. This surfaces it proactively: on activation, if the theme has orphaned files, the extension shows a single dismissable notification.

  • Review → opens the existing dead-code quick pick
  • Don't show again → flips the setting off
  • Gated by a new themeCheck.checkOrphanedFilesOnBoot setting (default true), mirroring the existing themeCheck.preloadOnBoot pattern

Implementation notes:

  • Reuses the whole-theme dead-code detection already exposed via ThemeGraphDeadCodeRequest (ThemeGraphManager.deadCode(rootUri)) — no server changes.
  • The startup check finds theme roots via workspace.findFiles('**/.theme-check.yml') (there's no active editor at boot), aggregates orphaned files across roots, and prompts once.
  • Refactored makeDeadCode to extract fetchDeadCode + showDeadCodePicker so the command and the startup check share logic — makeDeadCode's behavior is unchanged and covered by a characterization test.
  • Wired into both node and browser activation, fire-and-forget so it never blocks or fails activation.

Unit tests: new orphanedFilesOnBoot.spec.ts covers disabled setting / no orphans / orphans → notification / "Don't show again" → setting update / "Review" → picker, plus characterization tests guarding the makeDeadCode refactor. Full theme-check-vscode vitest suite green (23 tests), tsc --noEmit clean, prettier clean.

🤖 AI assistance

Drafted with Claude Code. I reviewed every change, ran the tests, and tophatted the flows below in a real extension host. The orphaned-files detection this builds on is existing Shopify code; this PR adds the startup surfacing plus a shared refactor.

What's next? Any followup issues?

None required. A few knobs I'm happy to adjust in this PR if you have preferences:

  • Setting default true (matches the issue's "prompt on start-up" intent) vs opt-in false for less startup noise.
  • Changeset marked minor (new feature + setting); can drop to patch given the fixed version group.
  • Multi-root: aggregates the count across all theme roots; "Review" opens the first root with orphans. Per-root prompts could be a follow-up if there's appetite.

What did you learn?

  • At activation time there's no active editor, so the usual "resolve the theme root from the open document" approach doesn't apply — root discovery uses workspace.findFiles('**/.theme-check.yml') instead.
  • Stock Dawn ships 2 orphaned files (assets/component-progress-bar.css, snippets/quick-order-product-row.liquid), so the notification surfaces real signal even on a vanilla theme.

Tophatting

Tested manually against a fresh Dawn clone — which has 2 orphaned files out of the box — plus one intentionally orphaned snippet (3 total), using the web extension host (this also exercises the browser activation path):

cd packages/vscode-extension
pnpm build
git clone --depth 1 https://github.com/Shopify/dawn.git .tmp/dawn
# optional: add an unreferenced snippets/zz-orphan.liquid
pnpm exec vscode-test-web --quality=stable --extensionDevelopmentPath=. .tmp/dawn
  1. Boot with orphans → one dismissable notification:

    Startup notification: Found 3 orphaned files in your theme

  2. Review → opens the existing dead-code quick pick with all 3 files:

    Dead-code quick pick listing the 3 orphaned files

  3. Don't show again → writes the setting to user settings:

    settings.json showing themeCheck.checkOrphanedFilesOnBoot: false

  4. Reload with the setting off → no notification on boot.

  • I added screenshots of the changes (there's no startup notification before this change, so the screenshots show the new flow)

Before you deploy

  • I included a minor bump changeset
  • My feature is backward compatible

On activation, check the theme for orphaned (dead) files and show a single
dismissable notification with "Review" (opens the existing dead-code picker)
and "Don't show again" actions, instead of requiring the user to run the
dead-code command manually.

- Gated by a new `themeCheck.checkOrphanedFilesOnBoot` setting (default on),
  mirroring the existing `themeCheck.preloadOnBoot` pattern
- Reuses the whole-theme dead-code detection already exposed via
  ThemeGraphDeadCodeRequest
- Extract fetchDeadCode + showDeadCodePicker from makeDeadCode so the startup
  check and the command share logic (no behavior change; covered by tests)
- Wired into both node and browser activation, fire-and-forget so it never
  blocks or fails activation

Closes Shopify#970
@ryandiginomad ryandiginomad requested a review from a team as a code owner May 31, 2026 15:19
@ryandiginomad

Copy link
Copy Markdown
Contributor Author

Quick check-in — this PR has been ready for review for a week. CLA signed, CI green. Ready whenever the theme-tools team has a window, and happy to address anything that comes up.

@aswamy aswamy 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.

Thanks for the PR @ryandiginomad . Please ensure your PR description follows the PR template here. This ensures that you have run the code and have tested it out manually before submitting.

const enabled = workspace.getConfiguration().get(CHECK_ORPHANED_ON_BOOT_SETTING, true);
if (!enabled) return;

const configFiles = await workspace.findFiles('**/.theme-check.yml', '**/node_modules/**');

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.

Startup check misses supported theme roots. This only scans **/.theme-check.yml, but the existing root detector also supports shopify.extension.toml roots and configless themes inferred from assets + snippets (see find-root.ts (line 7)). Those workspaces can activate the extension but will never get this new orphaned-file prompt.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch — fixed in 2d33a1f. The startup scan now globs every root signal findRoot recognises ({.theme-check.yml,shopify.extension.toml,snippets/*}) instead of just .theme-check.yml, and each match is resolved to its root via the server's themeGraph/rootUri request, so theme app extensions and configless themes get the prompt too.


const configFiles = await workspace.findFiles('**/.theme-check.yml', '**/node_modules/**');

let total = 0;

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.

This aggregates total across all config files, but line 42 opens the picker only for firstHit. In a workspace with multiple themes, the notification may say “Found 12 orphaned files” while Review shows only the first theme’s subset.

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.

In my workspace, i have two separate themes:

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 2d33a1f. The check now dedupes the resolved roots and prompts once per theme that has orphaned files, so each notification's count matches the files its own "Review" picker opens — no more cross-theme aggregation. Your two-theme workspace would now get one notification per theme. Added unit tests for the multi-theme and dedupe cases.

@ryandiginomad

Copy link
Copy Markdown
Contributor Author

Done — reworked the description to follow the PR template, including a Tophatting section with screenshots: tested in a real extension host against a fresh Dawn clone (boot notification → Review opens the dead-code picker → Don't show again writes the setting → no notification after reload). Happy to adjust anything else.

@aswamy

aswamy commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

@ryandiginomad Please also complete the comments i wrote above

… boot

Addresses review feedback on the orphaned-files startup check:

- The startup scan only globbed `**/.theme-check.yml`, so theme app
  extensions (`shopify.extension.toml`) and configless themes (inferred
  from a `snippets` directory) never got the prompt even though they
  activate the extension. The glob now matches every root signal that
  `findRoot` recognises, and the server resolves each anchor to its root.

- The notification aggregated the orphaned-file count across all themes
  but "Review" only opened the first theme's files. It now dedupes by the
  server-resolved root and prompts once per theme, so each count matches
  the files its own picker opens.
@ryandiginomad

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review and the two-theme screenshot — both inline points are addressed in 2d33a1f (replied in each thread):

  1. Missed roots: the startup scan now globs every root signal findRoot recognises ({.theme-check.yml,shopify.extension.toml,snippets/*}), and resolves each match to its root via the server's themeGraph/rootUri request, so theme app extensions and configless themes get the prompt too.

  2. Aggregate count vs. first-theme picker: it now dedupes by resolved root and prompts once per theme that has orphaned files, so each notification's count matches the files its own "Review" picker opens — no cross-theme aggregation.

Both behaviors are covered by new unit tests (multi-theme prompting, root dedupe, the wider glob, per-root counts): pnpm vitest run packages/vscode-extension/src/common/orphanedFilesOnBoot.spec.ts → 9 passing. tsc --noEmit and prettier are clean.

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.

VSCode prompt to remove dead code with an alert

2 participants