Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions .claude/agents/vscode-test-writer.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,38 +45,35 @@ When writing tests, you will:

For this VS Code extension project:

- Tests live alongside source in a test directory structure
- Tests live in `src/test/suite/` directory
- Test fixtures are in `test-fixtures/` with their own package.json files
- Tests run via `yarn test` or the VS Code Debug launcher "Launch Tests"
- The extension uses webpack bundling, but tests run against unbundled source
- Key components to test: `PrettierEditService`, `ModuleResolver`, formatting providers
- Tests run via `npm test` or the VS Code Debug launcher "Launch Tests"
- The extension uses esbuild bundling with ESM modules
- Key components to test: `PrettierEditService`, `ModuleResolver`, `PrettierDynamicInstance`
- Use `ensureExtensionActivated()` from `testUtils.js` to ensure extension is ready before tests

## Test File Structure

```typescript
import * as assert from "assert";
import * as vscode from "vscode";
import * as sinon from "sinon";
import { ensureExtensionActivated } from "./testUtils.js"; // Note: .js extension for ESM

suite("ComponentName Test Suite", () => {
let sandbox: sinon.SinonSandbox;

setup(() => {
sandbox = sinon.createSandbox();
});

teardown(() => {
sandbox.restore();
describe("ComponentName Test Suite", () => {
before(async () => {
await ensureExtensionActivated();
});

test("should describe expected behavior", async () => {
it("should describe expected behavior", async () => {
// Arrange
// Act
// Assert
});
});
```

**Note**: This project uses ESM modules. Always use `.js` extension for local imports.

## Quality Standards

- Tests must be deterministic and not flaky
Expand Down
11 changes: 7 additions & 4 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
{
"permissions": {
"allow": [
"WebFetch(domain:prettier.io)",
"WebFetch(domain:code.visualstudio.com)",
"Bash(npm run prettier:*)",
"Bash(npm run check-types:*)",
"Bash(npm run compile:*)",
"Bash(npm run lint:*)",
"mcp__ide__getDiagnostics"
"Bash(npm run prettier:*)",
"Bash(npm test:*)",
"mcp__ide__getDiagnostics",
"WebFetch(domain:code.visualstudio.com)",
"WebFetch(domain:prettier.io)"
],
"deny": [],
"ask": []
Expand Down
14 changes: 8 additions & 6 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ This is the official Prettier VS Code extension (`prettier.prettier-vscode`). It
Entry points:

- Desktop: `src/extension.ts` → bundled to `dist/extension.js`
- Browser: Same entry, bundled to `dist/web-extension.js` (uses `BrowserModuleResolver` instead of `ModuleResolver`)
- Browser: Same entry, bundled to `dist/web-extension.cjs` (esbuild swaps `ModuleResolverNode.ts``ModuleResolverWeb.ts`)

Core components:

- `src/extension.ts` - Extension activation, creates ModuleResolver, PrettierEditService, and StatusBar
- `src/extension.ts` - Extension activation (async), creates ModuleResolver, PrettierEditService, and StatusBar
- `src/PrettierEditService.ts` - Registers VS Code document formatting providers, handles format requests
- `src/ModuleResolver.ts` - Resolves local/global Prettier installations, falls back to bundled Prettier
- `src/PrettierInstance.ts` - Interface for Prettier loading, with `PrettierMainThreadInstance` and `PrettierWorkerInstance` implementations
- `src/ModuleResolverNode.ts` - Resolves local/global Prettier installations, falls back to bundled Prettier (desktop)
- `src/ModuleResolverWeb.ts` - Uses bundled standalone Prettier for browser (web)
- `src/PrettierDynamicInstance.ts` - Implements `PrettierInstance` interface, loads Prettier dynamically using ESM `import()`
- `src/types.ts` - TypeScript types including `PrettierInstance` interface

esbuild produces two bundles:

Expand Down Expand Up @@ -69,11 +71,11 @@ When reviewing pull requests, focus on:
### Performance

- Avoid blocking the extension host main thread
- `PrettierWorkerInstance` runs Prettier in a worker thread to avoid blocking
- Prettier is loaded lazily using dynamic `import()` to minimize startup time
- Module and config resolution results are cached appropriately

### Browser Compatibility

- Code in the main bundle should work in both Node.js and browser contexts
- Browser-specific code uses `BrowserModuleResolver`
- Browser build swaps `ModuleResolverNode.ts``ModuleResolverWeb.ts` via esbuild aliasing
- No Node.js-only APIs in shared code paths
5 changes: 2 additions & 3 deletions .github/instructions/tests.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ Tests run inside a VS Code Extension Development Host using Mocha.

## Test Structure

- Use Mocha's `suite()` and `test()` functions
- Use Mocha's `describe()` and `it()` functions (BDD style)
- Import assertions from `assert` module
- Tests interact with real VS Code APIs
- Use `.js` extension for local imports (ESM compatibility)

## Test Fixtures

Expand All @@ -28,8 +29,6 @@ Tests run inside a VS Code Extension Development Host using Mocha.
## Async Patterns

- Tests are async - use `async/await`
- Use `wait()` helper when needing delays
- Prettier v3 formatting is async, may need retries for timing

## Test File Naming

Expand Down
7 changes: 4 additions & 3 deletions .github/instructions/typescript.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ This is a VS Code extension. Follow these patterns:
- Import VS Code API from `vscode` module: `import { commands, workspace, window } from "vscode"`
- Use named imports, not namespace imports
- Group imports: vscode first, then node modules, then local modules
- **ESM**: Always use `.js` extension for local imports (e.g., `import { foo } from "./utils.js"`)

## VS Code Extension Patterns

Expand All @@ -22,13 +23,13 @@ This is a VS Code extension. Follow these patterns:
## Class Patterns

- Services follow dependency injection pattern (pass dependencies via constructor)
- Key services: `LoggingService`, `ModuleResolver`, `PrettierEditService`, `StatusBar`
- Key services: `LoggingService`, `ModuleResolver` (from `ModuleResolverNode.ts`/`ModuleResolverWeb.ts`), `PrettierEditService`, `StatusBar`
- Use `Disposable` interface for cleanup

## Prettier Integration

- Support both Prettier v2 and v3+ via `PrettierInstance` interface
- `PrettierMainThreadInstance` loads directly, `PrettierWorkerInstance` uses worker thread
- Support both Prettier v2 and v3+ via `PrettierInstance` interface (defined in `src/types.ts`)
- `PrettierDynamicInstance` loads Prettier using dynamic ESM `import()` for lazy loading
- Module resolution: local install → global install → bundled Prettier
- Handle `.prettierrc`, `.prettierignore`, and `package.json` prettier config

Expand Down
2 changes: 1 addition & 1 deletion .vscode-test.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineConfig } from "@vscode/test-cli";

export default defineConfig({
files: "out/test/suite/**/*.test.js",
files: "out/test/suite/**/*.test.cjs",
mocha: {
ui: "bdd",
timeout: 10000,
Expand Down
18 changes: 6 additions & 12 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"--extensionDevelopmentPath=${workspaceFolder}"
],
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"preLaunchTask": "npm: webpack"
"preLaunchTask": "npm: compile"
},
{
"name": "Run Extension (With Other Extensions)",
Expand All @@ -24,33 +24,27 @@
"runtimeExecutable": "${execPath}",
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"preLaunchTask": "npm: webpack"
"preLaunchTask": "npm: compile"
},
{
"name": "Extension Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceFolder}/test-fixtures/test.code-workspace",
"--disable-extensions",
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/suite/index"
],
"outFiles": ["${workspaceFolder}/out/test/**/*.js"],
"testConfiguration": "${workspaceFolder}/.vscode-test.mjs",
"outFiles": ["${workspaceFolder}/out/test/**/*.cjs"],
"preLaunchTask": "npm: compile:test"
},
{
"name": "Run Web Extension",
"type": "pwa-extensionHost",
"type": "extensionHost",
"debugWebWorkerHost": true,
"request": "launch",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionDevelopmentKind=web"
],
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"preLaunchTask": "npm: webpack"
"preLaunchTask": "npm: compile"
}
]
}
11 changes: 10 additions & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,22 @@
}
},
{
"label": "compile",
"label": "npm: compile",
"type": "npm",
"script": "compile",
"problemMatcher": "$tsc",
"presentation": {
"reveal": "silent"
}
},
{
"label": "npm: compile:test",
"type": "npm",
"script": "compile:test",
"problemMatcher": "$tsc",
"presentation": {
"reveal": "silent"
}
}
]
}
21 changes: 9 additions & 12 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Web tests are located in `src/test/web/suite/` and test the extension's browser
### Entry Points

- **Desktop**: `src/extension.ts` → bundled to `dist/extension.js`
- **Browser**: Same entry, bundled to `dist/web-extension.js` (uses `BrowserModuleResolver` instead of `ModuleResolver`)
- **Browser**: Same entry, bundled to `dist/web-extension.cjs` (esbuild swaps `ModuleResolverNode.ts` → `ModuleResolverWeb.ts`)

### Core Components

Expand All @@ -79,28 +79,25 @@ Web tests are located in `src/test/web/suite/` and test the extension's browser
- Watches for config file changes (`.prettierrc`, `package.json`, etc.)
- Builds language selectors based on Prettier's supported languages + plugins

**ModuleResolver** (`src/ModuleResolver.ts`):
**ModuleResolver** (`src/ModuleResolverNode.ts` for desktop, `src/ModuleResolverWeb.ts` for browser):

- Resolves local/global Prettier installations
- Falls back to bundled Prettier if none found
- Caches resolved modules and configurations
- Handles Workspace Trust restrictions
- **Desktop (ModuleResolverNode.ts)**: Resolves local/global Prettier installations, falls back to bundled Prettier, caches resolved modules, handles Workspace Trust
- **Browser (ModuleResolverWeb.ts)**: Uses bundled Prettier standalone with all built-in plugins

**Prettier Instance** (`PrettierInstance.ts`, `PrettierMainThreadInstance.ts`, `PrettierWorkerInstance.ts`):
**Prettier Instance** (`src/PrettierDynamicInstance.ts`):

- `PrettierInstance` is an interface with two implementations
- `PrettierMainThreadInstance` loads Prettier directly via `require()`
- `PrettierWorkerInstance` loads Prettier in a worker thread to avoid blocking
- Implements the `PrettierInstance` interface (defined in `src/types.ts`)
- Loads Prettier dynamically using ESM `import()` for lazy loading
- Works with both Prettier v2 and v3+

### Bundling

esbuild produces two bundles:

- Node bundle (`dist/extension.js`) for desktop VS Code
- Web bundle (`dist/web-extension.js`) for vscode.dev/browser
- Web bundle (`dist/web-extension.cjs`) for vscode.dev/browser

The browser build uses path aliasing to swap `ModuleResolver` → `BrowserModuleResolver`.
The browser build uses path aliasing to swap `ModuleResolverNode.ts` → `ModuleResolverWeb.ts`.

Build configuration is in `esbuild.mjs`.

Expand Down
1 change: 0 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ Key components:

- `PrettierEditService.ts` - Handles document formatting
- `ModuleResolver.ts` - Resolves Prettier installations (local, global, or bundled)
- `PrettierInstance.ts` - Interface for Prettier, with `PrettierMainThreadInstance` and `PrettierWorkerInstance` implementations

## Submitting Changes

Expand Down
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@
<img alt="Follow Prettier on Twitter" src="https://img.shields.io/twitter/follow/prettiercode.svg?label=follow+prettier&style=flat-square"></a>
</p>

> [!IMPORTANT]
> **Extension Migration:** This extension is being moved from `esbenp.prettier-vscode` to [`prettier.prettier-vscode`](https://marketplace.visualstudio.com/items?itemName=prettier.prettier-vscode). Version 12+ is only published to the new for now as it is a major change. Once it is stable, we will publish v12 to both extensions and deprecate the `esbenp.prettier-vscode` extension. **Version 12.x is currently not stable, use with caution in production environments.**
> 🚨🚨🚨 **Extension Migration:** This extension is being moved from `esbenp.prettier-vscode` to [`prettier.prettier-vscode`](https://marketplace.visualstudio.com/items?itemName=prettier.prettier-vscode). Version 12+ is only published to the new for now as it is a major change. Once it is stable, we will publish v12 to both extensions and deprecate the `esbenp.prettier-vscode` extension. **Version 12.x is currently not stable, use with caution and report bugs.**
## Installation

Expand Down
Loading