Skip to content

Codegen: --vscode-extension flag to inline extraImports wiring #105

@hyperpolymath

Description

@hyperpolymath

Problem

The Node-CJS codegen (lib/codegen_node.ml, added by #35 / #90) emits a .cjs shim that wraps the compiled wasm module. The shim exposes an extraImports hook that callers populate with the concrete vscode-API bindings before activate fires:

// Inside the generated extension.cjs:
const extras = (typeof exports.extraImports === "function")
    ? exports.extraImports()
    : {};
return { wasi_snapshot_preview1, ...extras };

Today, every consumer hand-writes a wrapper file to install extraImports before vscode's extension host calls activate. The pattern is identical across the three current consumers:

// hyperpolymath/my-lang:vscode-extension/src/index.cjs
// hyperpolymath/standards:rsr-certifier/extensions/vscode/src/index.cjs
// hyperpolymath/affinescript:editors/vscode/src/index.cjs  (still to land)

const shim = require("../out/extension.cjs");
const makeVscodeBindings = require("./affine-vscode-adapter.cjs");
// or: const makeVscodeBindings = require("@hyperpolymath/affine-vscode");

shim.extraImports = () => makeVscodeBindings(
    require("vscode"),
    require("vscode-languageclient/node"),
    shim,
);

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

This boilerplate is 100% mechanical and identical in every extension. It's what's left to manually wire — and it's the thing #35's original plan called out as belonging in codegen:

(Real wiring belongs in the codegen — Phase 3 will replace this manual hookup with auto-generated glue once extension.affine is the source of truth for the extension entry point.)

packages/affine-vscode/README.adoc

Proposed plan

Add a codegen flag, e.g. --vscode-extension, that opts into emitting the wiring inline so the generated .cjs is directly loadable as a VS Code extension's main:

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

The emitted shim then includes the equivalent of:

// Inserted by --vscode-extension:
const makeVscodeBindings = require("@hyperpolymath/affine-vscode");
exports.extraImports = function() {
  return makeVscodeBindings(
    require("vscode"),
    require("vscode-languageclient/node"),
    exports,
  );
};

… with @hyperpolymath/affine-vscode listed in the extension's package.json dependencies. (Once the npm-publish follow-up lands — see the sibling follow-up issue — this is a normal npm install.)

Each consumer's package.json main then points directly at out/extension.cjs. No hand-written index.cjs, no vendored affine-vscode-adapter.cjs file.

Sub-flags

  • --vscode-extension-adapter <module-specifier> — override the require() specifier for the adapter (useful for testing against a local checkout or for extensions that vendor their own).
  • --vscode-extension-no-lc — for extensions that don't ship a language client (no vscode-languageclient/node dependency); the wiring skips that require and passes null.

Acceptance criteria

  • affinescript compile src/extension.affine -o out/extension.cjs --vscode-extension emits a fully-wired CJS module.
  • A VS Code extension whose package.json main points at the unmodified generated .cjs activates and disposes cleanly.
  • The pilot in editors/vscode/ is migrated off the hand-written index.cjs (once that wrapper exists; this work and the affinescript-pilot port in [Repo] Port editors/vscode/src/extension.ts to .affine once #35 lands #63 likely coordinate).
  • my-lang and standards downstream PRs simplify accordingly (their index.cjs + vendored adapter both disappear).
  • Codegen tests cover the --vscode-extension flag.

Out of scope

  • A general --vscode-target-language-server-extension shape for extensions that aren't language-server-shaped. This issue covers the LSP+commands pattern that the current adapter implements.
  • A browser-host webworker variant (Node-only for now).

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions