Skip to content

Commit e53cc91

Browse files
fix: resolve command registration conflict causing LSP client startup failure
- Fixed duplicate command registration between LSP server and extension - LSP server handles 'just-lsp.run_recipe' for internal protocol communication - Extension provides 'justlang-lsp.run_recipe' for command palette access - Added comprehensive documentation explaining both command systems - Enhanced error logging for better debugging - Added just-lsp-installer for improved server detection and installation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent e4d1cde commit e53cc91

File tree

8 files changed

+421
-40
lines changed

8 files changed

+421
-40
lines changed

README.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
# JustLang-LSP Extension
22

33
## Overview
4+
45
JustLang-LSP is a Visual Studio Code extension designed to enhance the development experience by providing task automation and integration with JustLang syntax. It supports `Justfile` (any capitalization), `.justfile`, and `*.just` formats. This extension leverages the VS Code API to register commands and task providers, enabling seamless execution of tasks defined in JustLang files.
56

67
This extension now includes a language client for the `just-lsp` language server, providing features like completion, diagnostics, and more.
8+
I ported my own
9+
10+
https://docs.pkgx.sh/
11+
#!/usr/bin/env -S pkgx +cargo rust-script
12+
https://github.com/pkgxdev/pkgx
13+
14+
cargo install pkgx rust-script
15+
16+
17+
718

819
## Features
920

@@ -19,10 +30,29 @@ This extension now includes a language client for the `just-lsp` language server
1930
### VSCode Integration
2031
- **Task Provider Integration**: Automatically detects and registers tasks from JustLang files (`Justfile`, `.justfile`, or `*.just`)
2132
- **Recipe Execution**: Run recipes directly from the editor with live output streaming
22-
- **Command Registration**: Enhanced command palette integration with recipe execution
33+
- **Smart Command Registration**: Intelligent command handling with LSP server integration
2334
- **Syntax Highlighting**: Comprehensive syntax highlighting using TextMate grammar
2435
- **Language Configuration**: Smart bracket matching, auto-closing pairs, and comment handling
2536

37+
#### Command System
38+
The extension provides two recipe execution commands:
39+
40+
1. **LSP Server Command** (`just-lsp.run_recipe`):
41+
- Provided by the just-lsp language server
42+
- Used internally for LSP protocol communication and code actions
43+
- Triggered automatically by LSP server features (not directly accessible in command palette)
44+
45+
2. **Extension Command** (`justlang-lsp.run_recipe`):
46+
- Accessible via Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P`) → "Just: Run Recipe"
47+
- Provides interactive recipe browser with descriptions and parameter prompts
48+
- Shows recipe grouping, confirmation dialogs, and real-time execution output
49+
- Available regardless of LSP server status
50+
51+
**How to Access:**
52+
- **Command Palette**: `Ctrl+Shift+P` → "Just: Run Recipe" (uses extension command)
53+
- **LSP Features**: Code actions, hover actions, etc. (uses LSP server command)
54+
- **Task Provider**: VS Code Tasks panel (separate task-based execution)
55+
2656
## Requirements
2757

2858
This extension requires the `just-lsp` language server to be installed on your system. You can install it by following the instructions in the [just-lsp repository](https://github.com/elasticdotventures/just-lsp).
@@ -99,5 +129,6 @@ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file
99129
**Syntax Highlighting**: Syntax highlighting and language configuration features were adapted from the [wolfmah-vscode.just-syntax](https://github.com/wolfmah-vscode/just-syntax) repository under the Mozilla Public License 2.0 (MPL 2.0). See the [LICENSE](LICENSE) file for details.
100130

101131
## Additional Thanks
132+
* https://github.com/terror/just-lsp (lsp)
102133
* Robert Neff - nefrob.vscode-just-syntax
103134
* skellock - skellock.just

just-lsp-ng.pkgx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env -S pkgx rust-script
2+
//! ```cargo
3+
//! [dependencies]
4+
//! time = "0.1.25"
5+
//! ```
6+
fn main() {
7+
println!("{}", time::now().rfc822z());
8+
}

package.json

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -223,22 +223,19 @@
223223
],
224224
"commands": [
225225
{
226-
"command": "justlang.formatDocument",
227-
"title": "Just: Format Document"
228-
},
229-
{
230-
"command": "justlang.runRecipe",
231-
"title": "Just: Run Recipe"
232-
},
233-
{
234-
"command": "just-lsp.run_recipe",
235-
"title": "Just: Run Recipe (LSP)",
226+
"command": "justlang-lsp.run_recipe",
227+
"title": "Just: Run Recipe",
236228
"category": "Just"
237229
},
238230
{
239231
"command": "just-lsp.show_recipes",
240232
"title": "Just: Show All Recipes",
241233
"category": "Just"
234+
},
235+
{
236+
"command": "just-lsp.install",
237+
"title": "Just: Install/Update just-lsp Server",
238+
"category": "Just"
242239
}
243240
],
244241
"files": [

src/client.ts

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import * as vscode from 'vscode';
22
import { LanguageClient, LanguageClientOptions, ServerOptions, ErrorAction, CloseAction } from 'vscode-languageclient/node';
33
import * as path from 'path';
44
import * as fs from 'fs';
5+
import { JustLspInstaller } from './just-lsp-installer';
56

67
function findExecutable(bin: string): string | null {
78
const pathVar = process.env.PATH;
@@ -19,37 +20,30 @@ function findExecutable(bin: string): string | null {
1920
}
2021

2122
// runs the justlsp binary
22-
export function createLanguageClient(context: vscode.ExtensionContext): LanguageClient | null {
23+
export async function createLanguageClient(context: vscode.ExtensionContext): Promise<LanguageClient | null> {
2324
const config = vscode.workspace.getConfiguration('justlang-lsp');
25+
const installer = new JustLspInstaller();
2426

25-
// Find the binary
26-
const serverPath = config.get<string>('server.path') || findExecutable('just-lsp');
27+
// Try to detect just-lsp using the new installer system
28+
let serverPath = await installer.detectJustLsp();
2729

28-
// Check if debug logging is enabled (force enable during tests)
29-
const isTestEnvironment = process.env.NODE_ENV === 'test' || process.env.VSCODE_TEST === '1';
30-
const debugEnabled = isTestEnvironment || config.get<boolean>('debug.enabled', false);
31-
32-
// Check if the just-lsp binary is executable
33-
try {
34-
if (serverPath && fs.existsSync(serverPath)) {
35-
fs.accessSync(serverPath, fs.constants.X_OK);
36-
} else {
37-
throw new Error('just-lsp binary not found');
30+
// If not found, prompt for installation
31+
if (!serverPath) {
32+
const shouldInstall = await installer.promptInstallation();
33+
if (shouldInstall) {
34+
// Try detection again after installation
35+
serverPath = await installer.detectJustLsp();
3836
}
39-
} catch (err) {
40-
vscode.window.showErrorMessage(
41-
`just-lsp binary at ${serverPath} is not executable: ${err instanceof Error ? err.message : String(err)}`
42-
);
43-
console.error(`[justlang-lsp] just-lsp binary at ${serverPath} is not executable:`, err);
44-
return null;
4537
}
4638

4739
if (!serverPath) {
48-
vscode.window.showErrorMessage(
49-
'just-lsp executable not found. Please specify the path in your settings or ensure it is in your PATH.'
50-
);
40+
console.error('[justlang-lsp] just-lsp binary not found after detection and installation attempts');
5141
return null;
5242
}
43+
44+
// Check if debug logging is enabled (force enable during tests)
45+
const isTestEnvironment = process.env.NODE_ENV === 'test' || process.env.VSCODE_TEST === '1';
46+
const debugEnabled = isTestEnvironment || config.get<boolean>('debug.enabled', false);
5347

5448
console.log(`[justlang-lsp] Found just-lsp executable at: ${serverPath}`);
5549
console.log('[justlang-lsp] Preparing to launch language server process...');

src/commands.ts

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as vscode from 'vscode';
22
import { LanguageClient } from 'vscode-languageclient/node';
33
import { RecipeRunner } from './recipe-runner';
4+
import { JustLspInstaller } from './just-lsp-installer';
45

56
let commandsRegistered = false;
67
let recipeRunner: RecipeRunner | null = null;
@@ -21,8 +22,9 @@ export function registerCommands(context: vscode.ExtensionContext, client: Langu
2122
return;
2223
}
2324

24-
// Register the enhanced run recipe command with JSON parsing
25-
const runRecipeCommand = vscode.commands.registerCommand('just-lsp.run_recipe', async (recipeName?: string, args?: string[]) => {
25+
// Register the enhanced run recipe command with JSON parsing
26+
// Note: Use different name to avoid conflict with LSP server's executeCommandProvider
27+
const runRecipeCommand = vscode.commands.registerCommand('justlang-lsp.run_recipe', async (recipeName?: string, args?: string[]) => {
2628
const runner = getRecipeRunner();
2729
if (!runner) {
2830
vscode.window.showErrorMessage('No workspace found for recipe execution');
@@ -61,7 +63,39 @@ export function registerCommands(context: vscode.ExtensionContext, client: Langu
6163
}
6264
});
6365

64-
context.subscriptions.push(runRecipeCommand, showRecipesCommand);
66+
// Register install just-lsp command
67+
const installJustLspCommand = vscode.commands.registerCommand('just-lsp.install', async () => {
68+
const installer = new JustLspInstaller();
69+
70+
// First check if already installed
71+
const existingPath = await installer.detectJustLsp();
72+
if (existingPath) {
73+
const choice = await vscode.window.showInformationMessage(
74+
`just-lsp is already installed at: ${existingPath}`,
75+
'Reinstall',
76+
'OK'
77+
);
78+
if (choice !== 'Reinstall') {
79+
return;
80+
}
81+
}
82+
83+
// Attempt installation
84+
const result = await installer.installJustLsp();
85+
if (result.success) {
86+
const choice = await vscode.window.showInformationMessage(
87+
`just-lsp installed successfully at: ${result.path}`,
88+
'Reload Window'
89+
);
90+
if (choice === 'Reload Window') {
91+
vscode.commands.executeCommand('workbench.action.reloadWindow');
92+
}
93+
} else {
94+
vscode.window.showErrorMessage(`Installation failed: ${result.error}`);
95+
}
96+
});
97+
98+
context.subscriptions.push(runRecipeCommand, showRecipesCommand, installJustLspCommand);
6599
commandsRegistered = true;
66100
console.log('[justlang-lsp] Commands registered successfully');
67101
}

src/extension.ts

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,27 @@ export function activate(context: vscode.ExtensionContext) {
3939
await stopLsp();
4040
}
4141
logger.info('Creating language client', 'Extension');
42-
client = createLanguageClient(context);
42+
client = await createLanguageClient(context);
4343
if (client) {
4444
logger.info('Language client created, starting...', 'Extension');
4545
try {
46+
logger.info('About to call client.start()', 'Extension');
4647
await client.start();
4748
logger.info('Language client started successfully', 'Extension', { state: client.state });
48-
registerCommands(context, client);
4949
} catch (err) {
50-
logger.errorFromException(err, 'Language client failed to start', 'Extension');
51-
vscode.window.showErrorMessage('justlang-lsp language client failed to start.');
50+
const errorMessage = err instanceof Error ? err.message : String(err);
51+
const errorStack = err instanceof Error ? err.stack : 'No stack trace available';
52+
logger.error('Language client failed to start', 'Extension', {
53+
error: errorMessage,
54+
stack: errorStack,
55+
clientState: client?.state
56+
});
57+
console.error('[justlang-lsp] DETAILED START ERROR:', {
58+
message: errorMessage,
59+
stack: errorStack,
60+
error: err
61+
});
62+
vscode.window.showErrorMessage(`justlang-lsp language client failed to start: ${errorMessage}`);
5263
}
5364
} else {
5465
logger.error('Language client creation failed', 'Extension');
@@ -79,6 +90,9 @@ export function activate(context: vscode.ExtensionContext) {
7990
}
8091
});
8192

93+
// Register commands once during activation
94+
registerCommands(context, null);
95+
8296
if (enableLsp) {
8397
startLsp();
8498
} else {

0 commit comments

Comments
 (0)