Skip to content

Conversation

@cristianoc
Copy link
Collaborator

…ve integration tests.

Summary

Add reanalyze server support, monorepo build support, and comprehensive integration tests.


1. Fixes

ARM64 binary lookup fallback

File: shared/src/findBinary.ts

  • For ARM64 architecture, try the arm64-specific directory first (e.g., darwinarm64), then fall back to the generic platform directory (e.g., darwin) for older ReScript versions that don't have arm64-specific directories

Fixed "rescript" JS wrapper lookup

File: shared/src/findBinary.ts

  • For the "rescript" JS wrapper (as opposed to native binaries like bsc.exe), don't use the bsc_path directory from compiler-info.json - fall through to find the JS wrapper in node_modules/.bin instead

Build watcher process cleanup

File: server/src/utils.ts

  • Added killBuildWatcher() function that properly kills the entire process group (not just the parent process) and cleans up lock files
  • Uses process.kill(-proc.pid, "SIGTERM") on Unix to kill the entire process group, ensuring child processes (like the native rescript binary) are also killed
  • The rescript compiler doesn't remove lock files on SIGTERM, so we now clean them up manually

Build watcher stdin handling for older ReScript File: server/src/utils.ts

  • Use "pipe" for stdin instead of "ignore" because older ReScript versions (9.x, 10.x, 11.x) have a handler that exits when stdin closes: process.stdin.on("close", exitProcess)

Server shutdown cleanup

File: server/src/server.ts

  • Kill all build watchers and clean up lock files on LSP server shutdown

2. New Functionality

Reanalyze Server Support (ReScript >= 12.1.0)

Files: client/src/commands/code_analysis.ts, client/src/commands.ts, client/src/extension.ts

  • Added persistent reanalyze-server support for ReScript >= 12.1.0 (uses Unix socket for incremental analysis)
  • Server state management per monorepo root
  • Functions: startReanalyzeServer(), stopReanalyzeServer(), stopAllReanalyzeServers(), showReanalyzeServerLog()
  • Dedicated output channels for server logs per project
  • Automatic socket file cleanup
  • Servers are stopped when code analysis is stopped or extension deactivates

New Command: Show Reanalyze Server Log

Files: client/src/extension.ts, package.json

  • New command: rescript-vscode.show_reanalyze_server_log
  • Displays the reanalyze server output channel for debugging

New Command: Start Build

Files: client/src/extension.ts, server/src/server.ts, package.json

  • New command: rescript-vscode.start_build
  • Allows manually starting the build watcher without waiting for the prompt
  • LSP request handler: rescript/startBuild

Monorepo Support

Files: shared/src/findBinary.ts, server/src/server.ts, server/src/utils.ts, client/src/commands/code_analysis.ts

  • New function getMonorepoRootFromBinaryPath() to derive monorepo root from binary path
  • Build watcher now runs from monorepo root, not subpackage directory
  • Lock file detection at monorepo root level (checks both lib/rescript.lock and .bsb.lock)
  • Build prompt correctly uses monorepo root path when opening files from subpackages
  • Tracks buildRootPath separately from projectRootPath for proper cleanup

ReScript Version-Aware Build Command

File: server/src/utils.ts

  • Uses rescript watch for ReScript >= 12.0.0
  • Uses rescript build -w for ReScript < 12.0.0

Improved Error Handling and Logging

Files: Multiple

  • Better error messages when binaries are not found
  • Logging for build watcher process lifecycle (start, error, exit)
  • Logging for file open/close events

3. Tests

Test Infrastructure

Files: client/package.json, client/.vscode-test.mjs, client/tsconfig.json

  • Added test dependencies: @types/mocha, @vscode/test-cli, @vscode/test-electron
  • Test configuration for 4 test suites with different workspace folders
  • Added skipLibCheck: true to tsconfig for test type compatibility

Test Helpers (client/src/test/suite/helpers.ts) Shared utilities for all test suites:

  • getWorkspaceRoot() - Get workspace folder path
  • removeRescriptLockFile(), removeBsbLockFile(), removeMonorepoLockFiles() - Lock file cleanup
  • removeReanalyzeSocketFile() - Socket file cleanup
  • ensureExtensionActivated() - Ensure extension is active
  • openFile() - Open file in editor
  • findLspLogContent() - Read LSP logs for verification
  • waitFor(), sleep() - Async utilities
  • getCompilerLogPath(), getFileMtime(), waitForFileUpdate() - File modification tracking
  • insertCommentAndSave(), restoreContentAndSave() - Edit and restore files
  • startBuildWatcher(), startCodeAnalysis(), stopCodeAnalysis() - Command execution
  • showReanalyzeServerLog(), findBuildPromptInLogs() - Verification helpers

Example Project Tests (client/src/test/suite/exampleProject.test.ts) Tests against analysis/examples/example-project/ (ReScript 12.1.0):

  1. Extension should be present - Verify extension loads
  2. Commands should be registered - Verify all new commands are registered
  3. Start Code Analysis should run - Run code analysis on a ReScript file
  4. Start Build command should start build watcher - Manual build start
  5. Build watcher recompiles on file save - Edit file, verify compiler.log updates
  6. Code analysis with incremental updates - Add dead code, verify new diagnostics appear
  7. Should prompt to start build when no lock file exists - Verify build prompt

Monorepo Root Tests (client/src/test/suite/monorepoRoot.test.ts) Tests against analysis/examples/monorepo-project/ opened at root:

  1. Build watcher works when opening root package - Build from root, verify compiler.log
  2. Build watcher works when opening subpackage file - Open subpackage file, build still uses root compiler.log
  3. Code analysis works from subpackage - Run reanalyze from lib package
  4. Should prompt to start build with monorepo root path - Open subpackage, prompt uses root path

Monorepo Subpackage Tests (client/src/test/suite/monorepoSubpackage.test.ts) Tests against analysis/examples/monorepo-project/packages/app/ (VSCode opened on subpackage):

  1. Should prompt to start build with monorepo root path - Even when opened from subpackage, prompt uses monorepo root
  2. Lock file created at monorepo root, not subpackage - Verify lock file location
  3. Code analysis works when opened from subpackage - Diagnostics shown correctly

ReScript 9 Tests (client/src/test/suite/rescript9.test.ts) Tests against analysis/examples/rescript9-project/ (ReScript 9.x):

  1. Extension should be present - Extension loads with older ReScript
  2. Build watcher should start with 'rescript build -w' - Not 'rescript watch'
  3. Build watcher recompiles on file save - Verify incremental compilation
  4. Should prompt to start build when no lock file exists - Uses .bsb.lock
  5. Lock file should be cleaned up on language server restart - Verify cleanup

Test Projects Added

  • analysis/examples/monorepo-project/ - Monorepo with root package + packages/app + packages/lib
  • analysis/examples/rescript9-project/ - ReScript 9.x project with bsconfig.json
  • Updated analysis/examples/example-project/ to use ReScript 12.1.0

Other Changes

.gitignore

  • Added .vscode-test/ directory (VSCode test downloads)

package.json (root)

  • Added two new commands to the extension manifest:
    • rescript-vscode.show_reanalyze_server_log - "ReScript: Show Code Analyzer Server Log"
    • rescript-vscode.start_build - "ReScript: Start Build"

…ve integration tests.

## Summary

Add reanalyze server support, monorepo build support, and comprehensive integration tests.

---

## 1. Fixes

### ARM64 binary lookup fallback
**File:** `shared/src/findBinary.ts`
- For ARM64 architecture, try the arm64-specific directory first (e.g., `darwinarm64`), then fall back to the generic platform directory (e.g., `darwin`) for older ReScript versions that don't have arm64-specific directories

### Fixed "rescript" JS wrapper lookup
**File:** `shared/src/findBinary.ts`
- For the "rescript" JS wrapper (as opposed to native binaries like `bsc.exe`), don't use the `bsc_path` directory from `compiler-info.json` - fall through to find the JS wrapper in node_modules/.bin instead

### Build watcher process cleanup
**File:** `server/src/utils.ts`
- Added `killBuildWatcher()` function that properly kills the entire process group (not just the parent process) and cleans up lock files
- Uses `process.kill(-proc.pid, "SIGTERM")` on Unix to kill the entire process group, ensuring child processes (like the native rescript binary) are also killed
- The rescript compiler doesn't remove lock files on SIGTERM, so we now clean them up manually

### Build watcher stdin handling for older ReScript
**File:** `server/src/utils.ts`
- Use "pipe" for stdin instead of "ignore" because older ReScript versions (9.x, 10.x, 11.x) have a handler that exits when stdin closes: `process.stdin.on("close", exitProcess)`

### Server shutdown cleanup
**File:** `server/src/server.ts`
- Kill all build watchers and clean up lock files on LSP server shutdown

---

## 2. New Functionality

### Reanalyze Server Support (ReScript >= 12.1.0)
**Files:** `client/src/commands/code_analysis.ts`, `client/src/commands.ts`, `client/src/extension.ts`
- Added persistent reanalyze-server support for ReScript >= 12.1.0 (uses Unix socket for incremental analysis)
- Server state management per monorepo root
- Functions: `startReanalyzeServer()`, `stopReanalyzeServer()`, `stopAllReanalyzeServers()`, `showReanalyzeServerLog()`
- Dedicated output channels for server logs per project
- Automatic socket file cleanup
- Servers are stopped when code analysis is stopped or extension deactivates

### New Command: Show Reanalyze Server Log
**Files:** `client/src/extension.ts`, `package.json`
- New command: `rescript-vscode.show_reanalyze_server_log`
- Displays the reanalyze server output channel for debugging

### New Command: Start Build
**Files:** `client/src/extension.ts`, `server/src/server.ts`, `package.json`
- New command: `rescript-vscode.start_build`
- Allows manually starting the build watcher without waiting for the prompt
- LSP request handler: `rescript/startBuild`

### Monorepo Support
**Files:** `shared/src/findBinary.ts`, `server/src/server.ts`, `server/src/utils.ts`, `client/src/commands/code_analysis.ts`
- New function `getMonorepoRootFromBinaryPath()` to derive monorepo root from binary path
- Build watcher now runs from monorepo root, not subpackage directory
- Lock file detection at monorepo root level (checks both `lib/rescript.lock` and `.bsb.lock`)
- Build prompt correctly uses monorepo root path when opening files from subpackages
- Tracks `buildRootPath` separately from `projectRootPath` for proper cleanup

### ReScript Version-Aware Build Command
**File:** `server/src/utils.ts`
- Uses `rescript watch` for ReScript >= 12.0.0
- Uses `rescript build -w` for ReScript < 12.0.0

### Improved Error Handling and Logging
**Files:** Multiple
- Better error messages when binaries are not found
- Logging for build watcher process lifecycle (start, error, exit)
- Logging for file open/close events

---

## 3. Tests

### Test Infrastructure
**Files:** `client/package.json`, `client/.vscode-test.mjs`, `client/tsconfig.json`
- Added test dependencies: `@types/mocha`, `@vscode/test-cli`, `@vscode/test-electron`
- Test configuration for 4 test suites with different workspace folders
- Added `skipLibCheck: true` to tsconfig for test type compatibility

### Test Helpers (`client/src/test/suite/helpers.ts`)
Shared utilities for all test suites:
- `getWorkspaceRoot()` - Get workspace folder path
- `removeRescriptLockFile()`, `removeBsbLockFile()`, `removeMonorepoLockFiles()` - Lock file cleanup
- `removeReanalyzeSocketFile()` - Socket file cleanup
- `ensureExtensionActivated()` - Ensure extension is active
- `openFile()` - Open file in editor
- `findLspLogContent()` - Read LSP logs for verification
- `waitFor()`, `sleep()` - Async utilities
- `getCompilerLogPath()`, `getFileMtime()`, `waitForFileUpdate()` - File modification tracking
- `insertCommentAndSave()`, `restoreContentAndSave()` - Edit and restore files
- `startBuildWatcher()`, `startCodeAnalysis()`, `stopCodeAnalysis()` - Command execution
- `showReanalyzeServerLog()`, `findBuildPromptInLogs()` - Verification helpers

### Example Project Tests (`client/src/test/suite/exampleProject.test.ts`)
Tests against `analysis/examples/example-project/` (ReScript 12.1.0):
1. **Extension should be present** - Verify extension loads
2. **Commands should be registered** - Verify all new commands are registered
3. **Start Code Analysis should run** - Run code analysis on a ReScript file
4. **Start Build command should start build watcher** - Manual build start
5. **Build watcher recompiles on file save** - Edit file, verify compiler.log updates
6. **Code analysis with incremental updates** - Add dead code, verify new diagnostics appear
7. **Should prompt to start build when no lock file exists** - Verify build prompt

### Monorepo Root Tests (`client/src/test/suite/monorepoRoot.test.ts`)
Tests against `analysis/examples/monorepo-project/` opened at root:
1. **Build watcher works when opening root package** - Build from root, verify compiler.log
2. **Build watcher works when opening subpackage file** - Open subpackage file, build still uses root compiler.log
3. **Code analysis works from subpackage** - Run reanalyze from lib package
4. **Should prompt to start build with monorepo root path** - Open subpackage, prompt uses root path

### Monorepo Subpackage Tests (`client/src/test/suite/monorepoSubpackage.test.ts`)
Tests against `analysis/examples/monorepo-project/packages/app/` (VSCode opened on subpackage):
1. **Should prompt to start build with monorepo root path** - Even when opened from subpackage, prompt uses monorepo root
2. **Lock file created at monorepo root, not subpackage** - Verify lock file location
3. **Code analysis works when opened from subpackage** - Diagnostics shown correctly

### ReScript 9 Tests (`client/src/test/suite/rescript9.test.ts`)
Tests against `analysis/examples/rescript9-project/` (ReScript 9.x):
1. **Extension should be present** - Extension loads with older ReScript
2. **Build watcher should start with 'rescript build -w'** - Not 'rescript watch'
3. **Build watcher recompiles on file save** - Verify incremental compilation
4. **Should prompt to start build when no lock file exists** - Uses `.bsb.lock`
5. **Lock file should be cleaned up on language server restart** - Verify cleanup

### Test Projects Added
- `analysis/examples/monorepo-project/` - Monorepo with root package + packages/app + packages/lib
- `analysis/examples/rescript9-project/` - ReScript 9.x project with bsconfig.json
- Updated `analysis/examples/example-project/` to use ReScript 12.1.0

---

## Other Changes

### .gitignore
- Added `.vscode-test/` directory (VSCode test downloads)

### package.json (root)
- Added two new commands to the extension manifest:
  - `rescript-vscode.show_reanalyze_server_log` - "ReScript: Show Code Analyzer Server Log"
  - `rescript-vscode.start_build` - "ReScript: Start Build"
@cristianoc cristianoc requested review from cknitt and zth January 27, 2026 10:22
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.

2 participants