mirror of
https://github.com/olehomelchenko/astrolabe.git
synced 2026-08-08 02:02:33 +00:00
Editor: view-scoped data context — per-view dataset columns in hints and transforms
This commit is contained in:
@@ -27,7 +27,13 @@ import { validateExpression } from '@core/expr-validate';
|
||||
import { stringValueAtOffset, valueKeyAtOffset } from '@core/spec-cursor';
|
||||
import type { ColumnType } from '@core/type-inference';
|
||||
import { useSnippetStore } from '../stores/SnippetStore';
|
||||
import { availableFields, dataInfo, type DataInfo, type FieldHint } from './active-dataset';
|
||||
import {
|
||||
availableFieldsAt,
|
||||
dataInfoAt,
|
||||
fieldTypeAt,
|
||||
type DataInfo,
|
||||
type FieldHint,
|
||||
} from './active-dataset';
|
||||
|
||||
/** Property values that reference a data field (where column names belong). */
|
||||
const FIELD_KEYS = new Set(['field', 'groupby']);
|
||||
@@ -65,9 +71,11 @@ export function configureSpecDatasetHints(): void {
|
||||
provideCompletionItems(model, position) {
|
||||
// Field suggestions only edit the draft; nothing to offer on the published view.
|
||||
if (useSnippetStore.getState().editorView !== 'draft') return { suggestions: [] };
|
||||
const key = valueKeyAtOffset(model.getValue(), model.getOffsetAt(position));
|
||||
const text = model.getValue();
|
||||
const offset = model.getOffsetAt(position);
|
||||
const key = valueKeyAtOffset(text, offset);
|
||||
if (key === null || !FIELD_KEYS.has(key)) return { suggestions: [] };
|
||||
const fields = availableFields();
|
||||
const fields = availableFieldsAt(text, offset);
|
||||
if (fields.length === 0) return { suggestions: [] };
|
||||
|
||||
const word = model.getWordUntilPosition(position);
|
||||
@@ -92,7 +100,7 @@ export function configureSpecDatasetHints(): void {
|
||||
});
|
||||
|
||||
// All three providers annotate the draft only: they derive their field set from
|
||||
// the draft buffer (dataInfo), so gating to the draft view keeps the hints
|
||||
// the draft buffer (dataInfoAt), so gating to the draft view keeps the hints
|
||||
// consistent with the text they are computed from. The published view is a
|
||||
// read-only reference, where field hints are marginal.
|
||||
monaco.languages.registerHoverProvider('json', {
|
||||
@@ -119,10 +127,10 @@ export function configureSpecDatasetHints(): void {
|
||||
}
|
||||
}
|
||||
|
||||
// Over a field name: its type + stats.
|
||||
// Over a field name: its type + stats, resolved at this view's data binding.
|
||||
const word = model.getWordAtPosition(position);
|
||||
if (word) {
|
||||
const info = dataInfo();
|
||||
const info = dataInfoAt(text, offset);
|
||||
const hint = info.fields.find((f) => f.name === word.word);
|
||||
if (hint) {
|
||||
return {
|
||||
@@ -143,15 +151,19 @@ export function configureSpecDatasetHints(): void {
|
||||
monaco.languages.registerInlayHintsProvider('json', {
|
||||
provideInlayHints(model, range) {
|
||||
if (useSnippetStore.getState().editorView !== 'draft') return { hints: [], dispose() {} };
|
||||
const types = new Map(availableFields().map((f) => [f.name, f.type]));
|
||||
if (types.size === 0) return { hints: [], dispose() {} };
|
||||
const text = model.getValue();
|
||||
const hints: monaco.languages.InlayHint[] = [];
|
||||
for (let line = range.startLineNumber; line <= range.endLineNumber; line++) {
|
||||
// First `field` per line; the compact format keeps each encoding channel
|
||||
// (and its lone field) on its own line, so one match per line suffices.
|
||||
const match = /"field"\s*:\s*"([^"]+)"/.exec(model.getLineContent(line));
|
||||
if (!match) continue;
|
||||
const type = types.get(match[1]);
|
||||
// Resolve the type at this field's own data binding — views in a
|
||||
// composition can bind different datasets. The offset points inside the
|
||||
// field's value so the path resolves to its enclosing view.
|
||||
const valueCol = match.index + match[0].length - match[1].length;
|
||||
const offset = model.getOffsetAt({ lineNumber: line, column: valueCol });
|
||||
const type = fieldTypeAt(text, offset, match[1]);
|
||||
if (!type) continue; // unknown or derived (no type to annotate)
|
||||
hints.push({
|
||||
position: { lineNumber: line, column: match.index + match[0].length + 1 },
|
||||
|
||||
Reference in New Issue
Block a user