restructure: move el compiler content into lang/
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
// tools/lsp/vscode-extension/extension.js
|
||||
//
|
||||
// El Language VSCode extension — Language Client
|
||||
//
|
||||
// Launches the el-lsp binary as a child process and connects VSCode's
|
||||
// Language Client to it over stdin/stdout (JSON-RPC 2.0 + Content-Length).
|
||||
//
|
||||
// Capabilities provided by el-lsp:
|
||||
// - textDocumentSync (full)
|
||||
// - completionProvider — builtins + user fns + keywords
|
||||
// - hoverProvider — signatures + descriptions
|
||||
// - definitionProvider — go-to-def for user-defined fns
|
||||
// - diagnostics — unclosed braces/parens, unterminated strings
|
||||
//
|
||||
// Setup (development):
|
||||
// 1. cd tools/lsp && ./build.sh (builds dist/el-lsp)
|
||||
// 2. cd vscode-extension && npm install (installs vscode-languageclient)
|
||||
// 3. Open vscode-extension/ in VSCode
|
||||
// 4. Press F5 (launches Extension Development Host)
|
||||
// 5. Open any .el file
|
||||
//
|
||||
// Package as .vsix:
|
||||
// npm install -g @vscode/vsce
|
||||
// cd tools/lsp/vscode-extension && vsce package
|
||||
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const { workspace, window, ExtensionContext } = require('vscode');
|
||||
const {
|
||||
LanguageClient,
|
||||
TransportKind,
|
||||
} = require('vscode-languageclient/node');
|
||||
|
||||
/** @type {LanguageClient | undefined} */
|
||||
let client;
|
||||
|
||||
/**
|
||||
* activate — entry point called when any .el file is first opened.
|
||||
*
|
||||
* @param {ExtensionContext} context
|
||||
*/
|
||||
function activate(context) {
|
||||
// ── Resolve el-lsp binary ────────────────────────────────────────────
|
||||
const config = workspace.getConfiguration('el');
|
||||
|
||||
// Default path resolution (tries in order):
|
||||
// 1. el.lspPath setting (user override)
|
||||
// 2. dist/el-lsp alongside the extension dir (packaged install)
|
||||
// 3. The canonical source-tree location
|
||||
const CANONICAL_LSP = '/Users/will/Development/neuron-technologies/foundation/el/tools/lsp/dist/el-lsp';
|
||||
const defaultLspPath = (() => {
|
||||
const sibling = path.join(context.extensionPath, 'dist', 'el-lsp');
|
||||
if (fs.existsSync(sibling)) return sibling;
|
||||
return CANONICAL_LSP;
|
||||
})();
|
||||
const serverPath = config.get('lspPath') || defaultLspPath;
|
||||
|
||||
if (!fs.existsSync(serverPath)) {
|
||||
window.showErrorMessage(
|
||||
`El Language Server binary not found at: ${serverPath}\n` +
|
||||
`Run tools/lsp/build.sh to build it, then reload VSCode.\n` +
|
||||
`Or set "el.lspPath" in settings to the correct path.`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// ── Server options (start el-lsp as child process) ───────────────────
|
||||
/** @type {import('vscode-languageclient/node').ServerOptions} */
|
||||
const serverOptions = {
|
||||
run: {
|
||||
command: serverPath,
|
||||
transport: TransportKind.stdio,
|
||||
options: { env: { ...process.env } },
|
||||
},
|
||||
debug: {
|
||||
command: serverPath,
|
||||
transport: TransportKind.stdio,
|
||||
options: {
|
||||
env: { ...process.env },
|
||||
// Redirect el-lsp stderr to VSCode's Output panel in debug mode.
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// ── Client options ───────────────────────────────────────────────────
|
||||
/** @type {import('vscode-languageclient/node').LanguageClientOptions} */
|
||||
const clientOptions = {
|
||||
// Activate for all .el files (file:// and untitled: schemes).
|
||||
documentSelector: [
|
||||
{ scheme: 'file', language: 'el' },
|
||||
{ scheme: 'untitled', language: 'el' },
|
||||
],
|
||||
synchronize: {
|
||||
// Fire fileEvents so the client resends on disk changes outside VSCode.
|
||||
fileEvents: workspace.createFileSystemWatcher('**/*.el'),
|
||||
},
|
||||
outputChannelName: 'El Language Server',
|
||||
// Trace LSP messages to the Output panel for debugging.
|
||||
// Set "el.trace.server": "verbose" in settings to enable.
|
||||
traceOutputChannel: window.createOutputChannel('El LSP Trace'),
|
||||
};
|
||||
|
||||
// ── Create and start client ──────────────────────────────────────────
|
||||
client = new LanguageClient(
|
||||
'el-language-server',
|
||||
'El Language Server',
|
||||
serverOptions,
|
||||
clientOptions,
|
||||
);
|
||||
|
||||
// Register the client so it is disposed when the extension deactivates.
|
||||
context.subscriptions.push(client);
|
||||
|
||||
client.start().then(() => {
|
||||
// Show a discrete status bar item while the server is active.
|
||||
const status = window.createStatusBarItem(1);
|
||||
status.text = '$(symbol-misc) El LSP';
|
||||
status.tooltip = 'El Language Server is running';
|
||||
status.command = 'el.restartServer';
|
||||
status.show();
|
||||
context.subscriptions.push(status);
|
||||
}).catch((err) => {
|
||||
window.showErrorMessage(`El Language Server failed to start: ${err.message}`);
|
||||
});
|
||||
|
||||
// ── Commands ─────────────────────────────────────────────────────────
|
||||
context.subscriptions.push(
|
||||
require('vscode').commands.registerCommand('el.restartServer', () => {
|
||||
if (client) {
|
||||
client.stop().then(() => client.start());
|
||||
window.showInformationMessage('El Language Server restarted.');
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* deactivate — called when the extension is unloaded.
|
||||
* Sends LSP shutdown + exit to the server process.
|
||||
*/
|
||||
function deactivate() {
|
||||
if (!client) {
|
||||
return undefined;
|
||||
}
|
||||
return client.stop();
|
||||
}
|
||||
|
||||
module.exports = { activate, deactivate };
|
||||
Reference in New Issue
Block a user