Editor: Vega-Lite expression intelligence; single-home render errors

This commit is contained in:
2026-07-01 05:00:47 +03:00
parent 9b2618cac6
commit da6a675982
20 changed files with 1001 additions and 260 deletions
+4 -24
View File
@@ -8,8 +8,8 @@
* takes a string; it can't list your columns. Enum values (`type`, `mark`, …)
* are left to the schema — we add only what it lacks, no second source.
* - **Hover** — a column's inferred type + cardinality/range (from the stored
* profile); over a `calculate`/`filter`/`expr` string, a live validity check
* via core/expr-validate. Monaco merges these with the schema's own hovers.
* profile). Monaco merges this with the schema's own hovers. (Expression-string
* hovers and completion live in services/spec-expression-hints.)
* - **Inlay hints** — a faint `·<data-type>` beside each `field` (the column's
* raw type: number/string/date/boolean), annotation without touching the text.
* Deliberately the *data* type, not the encoding `type` — they share the line,
@@ -25,8 +25,7 @@
*/
import * as monaco from 'monaco-editor/esm/vs/editor/edcore.main';
import { validateExpression } from '@core/expr-validate';
import { stringValueAtOffset, valueKeyAtOffset } from '@core/spec-cursor';
import { valueKeyAtOffset } from '@core/spec-cursor';
import { useSnippetStore } from '../stores/SnippetStore';
import {
availableFieldsAt,
@@ -38,8 +37,6 @@ import {
/** Property values that reference a data field (where column names belong). */
const FIELD_KEYS = new Set(['field', 'groupby']);
/** Property values that hold a Vega expression (where the validity check fires). */
const EXPR_KEYS = new Set(['calculate', 'filter', 'expr']);
/** Markdown hover for a field hint: type + stats for source, a note for derived. */
function fieldHoverContents(hint: FieldHint, info: DataInfo): { value: string }[] {
@@ -109,25 +106,8 @@ export function configureSpecDatasetHints(): void {
const text = model.getValue();
const offset = model.getOffsetAt(position);
// Over an expression value: a live validity check.
const key = valueKeyAtOffset(text, offset);
if (key !== null && EXPR_KEYS.has(key)) {
const expr = stringValueAtOffset(text, offset);
if (expr !== null) {
const result = validateExpression(expr);
return {
contents: [
{
value: result.valid
? '✓ Valid Vega expression'
: `${result.error ?? 'Invalid expression'}`,
},
],
};
}
}
// Over a field name: its type + stats, resolved at this view's data binding.
// (Expression-string hovers live in services/spec-expression-hints.)
const word = model.getWordAtPosition(position);
if (word) {
const info = dataInfoAt(text, offset);