|
1 | 1 | import { Compartment, EditorState, Extension } from "@codemirror/state"; |
2 | 2 | import { EditorView, keymap, lineNumbers } from "@codemirror/view"; |
3 | | -import { defaultKeymap, standardKeymap, toggleComment } from "@codemirror/commands"; |
| 3 | +import { defaultKeymap, toggleComment } from "@codemirror/commands"; |
4 | 4 | import { html } from "@codemirror/lang-html"; |
5 | 5 | import { css } from "@codemirror/lang-css"; |
6 | 6 | import { javascript } from "@codemirror/lang-javascript"; |
7 | 7 | import { autocompletion } from "@codemirror/autocomplete"; |
8 | | -import { foldGutter, foldKeymap } from "@codemirror/language"; |
| 8 | +import { foldGutter, foldKeymap, syntaxTree } from "@codemirror/language"; |
| 9 | +import { linter, lintGutter } from "@codemirror/lint"; |
9 | 10 | import { formatCode } from "./runner"; |
10 | 11 | import { monokai } from "@uiw/codemirror-theme-monokai"; |
11 | 12 | import { bbedit } from "@uiw/codemirror-theme-bbedit"; |
@@ -65,6 +66,28 @@ function createEditorConfig( |
65 | 66 | extensions: [ |
66 | 67 | lineNumbers(), |
67 | 68 | foldGutter(), |
| 69 | + // Linting: use syntax tree to surface parse errors from the language parser |
| 70 | + linter((view) => { |
| 71 | + const diags: any[] = []; |
| 72 | + try { |
| 73 | + syntaxTree(view.state).iterate({ |
| 74 | + enter: (node) => { |
| 75 | + if (node.type.isError) { |
| 76 | + diags.push({ |
| 77 | + from: node.from, |
| 78 | + to: node.to, |
| 79 | + severity: "error", |
| 80 | + message: "Syntax error", |
| 81 | + }); |
| 82 | + } |
| 83 | + }, |
| 84 | + }); |
| 85 | + } catch (e) { |
| 86 | + // If iterate isn't supported for some tree shapes, fail silently |
| 87 | + } |
| 88 | + return diags; |
| 89 | + }), |
| 90 | + lintGutter(), |
68 | 91 | language, |
69 | 92 | themeCompartment.of(darkModeState.get() ? monokai : bbedit), |
70 | 93 | EditorView.lineWrapping, |
|
0 commit comments