Skip to content

Latest commit

 

History

History
118 lines (92 loc) · 4.58 KB

File metadata and controls

118 lines (92 loc) · 4.58 KB

affine-vscode

JS-side adapter for the stdlib/Vscode.affine and stdlib/VscodeLanguageClient.affine binding modules. Issue #35 Phase 2 deliverable.

Install

npm install @hyperpolymath/affine-vscode

Add it to your extension’s package.json dependencies. vscode and vscode-languageclient are peer dependencies (the latter is optional — omit it with --vscode-extension-no-lc).

Usage

Compile with the --vscode-extension flag and the generated .cjs is directly loadable as the extension’s main — the adapter wiring is emitted inline, so there is no hand-written entry point to maintain:

affinescript compile src/extension.affine -o out/extension.cjs --vscode-extension

Point your extension’s package.json main at the unmodified out/extension.cjs and list @hyperpolymath/affine-vscode in dependencies. Sub-flags: --vscode-extension-adapter <specifier> overrides the adapter require() target; --vscode-extension-no-lc omits the vscode-languageclient/node dependency.

Manual wiring (fallback)

If you cannot use the flag, set the shim’s extraImports hook before the first activate/deactivate call so the extern fns resolve to live vscode APIs. Pass the shim module itself as the third argument — the adapter reads its handle table and _instance lazily:

const vscode = require("vscode");
const lc = require("vscode-languageclient/node");
const makeBindings = require("@hyperpolymath/affine-vscode");

const shim = require("./extension.cjs");
shim.extraImports = () => makeBindings(vscode, lc, shim);

exports.activate = shim.activate;
exports.deactivate = shim.deactivate;

Surface

The adapter implements every extern fn declared in:

  • stdlib/Vscode.affine — initial set (issue #35 Phase 2): commands.registerCommand, workspace.getConfiguration / createFileSystemWatcher, window.{showError,showWarning,showInformation}Message, window.createTerminal + terminal.show / sendText, ExtensionContext.subscriptions.push, window.activeTextEditor, editorActive{FilePath,LanguageId}, workspaceConfigGet{Bool,String}, consoleLog, execSync, and three string helpers.

    Expanded 2026-05-11 for the rsr-certifier port (issue #64): workspaceFolderFirstPath / workspaceRootUri, uriFromPath / uriJoinPath / uriPath, fsWriteFile, openTextDocument / showTextDocument, createStatusBarItem + statusBarItem.{setText,setTooltip,setCommand,setBackgroundColorTheme,show,hide,asDisposable}, createDiagnosticCollection + diagnosticCollection.{clear,setForUri,asDisposable}, createWebviewPanel + webviewPanel.{setHtml,asDisposable}, clipboardWriteText, onDidSaveTextDocument, pathBasename / pathJoin / processPlatform, and extensionAbsolutePath.

  • stdlib/VscodeLanguageClient.affine — 3 bindings covering new LanguageClient(…​) / start() / stop().

Deliberate omissions

Two API shapes are not bound because they cannot be expressed in the current synchronous extern-call ABI without an async-extern hookup:

  • vscode.window.withProgress(opts, async task) — the second arg is an async Thenable-returning task.

  • LanguageClient.sendRequest(method, params) — returns a Thenable.

Extensions that need either should fall back to shelling out to a CLI via Vscode::createTerminal / Vscode::execSync until an async-extern ABI lands.

Design notes

  • All host objects (Disposable, Terminal, ExtensionContext, StatusBarItem, DiagnosticCollection, WebviewPanel, Uri, TextDocument, …​) are represented as opaque integer handles on both sides of the FFI. The adapter maintains a JS-side handle table.

  • String args are passed across as i32 pointers into the wasm linear memory; the adapter reads the [u32 length][utf-8 bytes] layout out of instance.exports.memory.buffer.

  • Wasm function-pointer args (e.g. command handlers) come in as __indirect_function_table indices; the adapter wraps each in a JS thunk that re-enters the wasm module on invocation.

  • Diagnostics avoid a Range+Diagnostic struct FFI by accepting a JSON array: [{startLine,startCol,endLine,endCol,message,severity}, …​]. The adapter parses it and constructs the vscode objects.

Status

Phase 2 — bindings landed. The pilot affinescript port (issue #63) and external-extension ports (issue #64: my-lang, rsr-certifier) consume this adapter; the long-term plan is to publish it to npm so consumers do not have to vendor mod.js. Phase 4 (rattlescript-face sweep) still to do.