Skip to content

feat: lint GLSL in JS/TS tagged template literals - #28

Merged
johncarmack1984 merged 1 commit into
mainfrom
feat/embedded-glsl-templates
Jul 22, 2026
Merged

feat: lint GLSL in JS/TS tagged template literals#28
johncarmack1984 merged 1 commit into
mainfrom
feat/embedded-glsl-templates

Conversation

@johncarmack1984

Copy link
Copy Markdown
Owner

Lint GLSL written inline in JS/TS glsl`...` tagged template literals — and the /* glsl */ `...` marker form — the way deck.gl/luma.gl projects keep shaders next to their new Model(...) call rather than in separate .glsl files. The most-requested capability in this space.

What's covered

  • Extraction (src/embed.rs, new): a heuristic scanner — sibling to derive.rs — that finds each tagged-template shader in .ts/.tsx/.js/.jsx/.mts/.cts/.mjs/.cjs, tracking strings/comments so a backtick in a "..." string or glsl inside a longer identifier isn't mistaken for a shader. It records a per-line map back to the host file.
  • CLI: glslint check 'src/**/*.ts' validates each embedded shader and maps every diagnostic — glslang errors and the source lints — to the exact host .ts line and column (embed's per-line host map composed with the assembler's own line map).
  • LSP: the server diagnoses JS/TS documents live (the VS Code extension now activates on and selects them). The GLSL-only features — hover, definition, completion, outline — stay on .glsl files.

Practical cases

  • Interpolations (${...}): a template with any interpolation is an incomplete translation unit (the injected value can declare symbols the shader uses, or use ones it declares), so it's checked with the source-level lints only — never a validation error that might be our own substitution's fault — and gets one informational note. Non-interpolated templates are fully validated. The ${...} is blanked to spaces (newlines preserved) purely so the lints' line/column math stays exact.
  • Multiple templates per file, handled independently.
  • Stage inference: a stage-specific builtin decides it (gl_Position/gl_VertexID → vertex, gl_FragCoord/discard → fragment, local_size_x → compute), then the binding name, then a fragment default — ordered so the default and name hint are only reached when no stage-specific builtin is present, and therefore can't cause a wrong-stage false positive. No main → a chunk wrapped syntax-only under its inferred stage.
  • luma module injection when a new Model({ modules }) call wires up the shader's binding, via the new derive_for_binding.

The glslang backend is untouched. New Severity::Note (→ LSP INFORMATION). Fixtures + unit/integration tests cover extraction, mapping accuracy, the interpolation path, and the stage-guess false-positive regression.

Docs: README gains a "Shaders inside JS/TS" section and an embed.rs entry in "How it works"; the extension README documents the JS/TS support.

Extract GLSL from `glsl`...`` and `/* glsl */ `...`` tagged templates in
.ts/.tsx/.js/.jsx files and lint it in place, with every diagnostic mapped
to the exact host-file line and column.

- embed.rs: a heuristic scanner (sibling to derive.rs) that finds each
  tagged-template shader, tracks strings/comments, and records a per-line
  map back to the host file. Line continuations are applied and `${...}`
  interpolations are blanked (line/column preserving).
- check.rs: check_source dispatches JS/TS files to check_embedded, which
  validates each template and remaps glslang errors and source lints alike.
- Interpolated templates are checked lints-only (an incomplete translation
  unit) with an informational note; non-interpolated ones are fully
  validated.
- Stage is inferred from stage-specific builtins first, then the binding
  name, then a fragment default -- ordered so the default can never
  misreport a builtin as undeclared.
- luma modules are resolved for an inline binding via derive_for_binding.
- lsp.rs diagnoses JS/TS documents (symbol features stay GLSL-only); new
  Severity::Note. The VS Code extension activates on and selects JS/TS.
@johncarmack1984
johncarmack1984 merged commit db05149 into main Jul 22, 2026
7 checks passed
@johncarmack1984
johncarmack1984 deleted the feat/embedded-glsl-templates branch July 22, 2026 19:57
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.

1 participant