mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-23 08:00:45 +00:00
refactor(editor): extract Monaco model path/URI computation
Headless linting needs to derive the exact model URI the editor uses; computeUri/computePath were component-local closures over scriptLang and lang. Move them to lint/monacoUri.ts with those as explicit parameters. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,7 +41,6 @@
|
||||
|
||||
import { editorConfig, registerWebviewPaste, updateOptions } from '$lib/editorUtils'
|
||||
import { editorFontSize } from '$lib/editorFontSize.svelte'
|
||||
import { createHash as randomHash } from '$lib/editorLangUtils'
|
||||
import { workspaceStore } from '$lib/stores'
|
||||
import DdlMigrationGuard from './DdlMigrationGuard.svelte'
|
||||
import {
|
||||
@@ -109,7 +108,8 @@
|
||||
import type { ScriptLintResult } from './copilot/chat/shared'
|
||||
import FakeMonacoPlaceHolder from './FakeMonacoPlaceHolder.svelte'
|
||||
import { editorPositionMap } from '$lib/utils'
|
||||
import { extToLang, langToExt } from '$lib/editorLangUtils'
|
||||
import { extToLang } from '$lib/editorLangUtils'
|
||||
import { computeModelPath, computeModelUri } from './lint/monacoUri'
|
||||
import { aiChatManager } from './copilot/chat/AIChatManager.svelte'
|
||||
import type { Selection } from 'monaco-editor'
|
||||
import { canHavePreprocessor, getPreprocessorModuleCode } from '$lib/script_helpers'
|
||||
@@ -252,7 +252,12 @@
|
||||
cmdEnterAction?.()
|
||||
}
|
||||
|
||||
let filePath = $state(computePath(untrack(() => path)))
|
||||
let filePath = $state(
|
||||
computeModelPath(
|
||||
untrack(() => path),
|
||||
untrack(() => scriptLang)
|
||||
)
|
||||
)
|
||||
|
||||
let initialPath: string | undefined = $state(untrack(() => path))
|
||||
|
||||
@@ -269,41 +274,14 @@
|
||||
let dbSchema: DBSchema | undefined = $state(undefined)
|
||||
|
||||
let destroyed = false
|
||||
const uri = computeUri(
|
||||
const uri = computeModelUri(
|
||||
untrack(() => filePath),
|
||||
untrack(() => scriptLang)
|
||||
untrack(() => scriptLang),
|
||||
untrack(() => lang)
|
||||
)
|
||||
|
||||
console.log('uri', uri)
|
||||
|
||||
function computeUri(filePath: string, scriptLang: string | undefined) {
|
||||
let file
|
||||
if (filePath.includes('.')) {
|
||||
file = filePath
|
||||
} else {
|
||||
file = `${filePath}.${scriptLang == 'tsx' ? 'tsx' : langToExt(lang)}`
|
||||
}
|
||||
if (file.startsWith('/')) {
|
||||
file = file.slice(1)
|
||||
}
|
||||
return !['deno', 'go', 'python3'].includes(scriptLang ?? '')
|
||||
? `file:///${file}`
|
||||
: `file:///tmp/monaco/${file}`
|
||||
}
|
||||
|
||||
function computePath(path: string | undefined): string {
|
||||
if (
|
||||
['deno', 'go', 'python3'].includes(scriptLang ?? '') ||
|
||||
path == '' ||
|
||||
path == undefined //||path.startsWith('/')
|
||||
) {
|
||||
return randomHash()
|
||||
} else {
|
||||
// console.log('path', path)
|
||||
return path as string
|
||||
}
|
||||
}
|
||||
|
||||
export function switchToFile(path: string, value: string, lang: string) {
|
||||
if (editor) {
|
||||
const uri = mUri.parse(path)
|
||||
@@ -2035,7 +2013,7 @@
|
||||
})
|
||||
|
||||
$effect(() => {
|
||||
filePath = computePath(path)
|
||||
filePath = computeModelPath(path, scriptLang)
|
||||
})
|
||||
$effect(() => {
|
||||
path != initialPath &&
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { describe, it, expect } from 'vitest'
|
||||
import { scriptLangToEditorLang } from '$lib/scripts'
|
||||
import { computeModelPath, computeModelUri } from './monacoUri'
|
||||
|
||||
// Mirrors what Editor.svelte does: path -> filePath -> uri.
|
||||
function uriFor(path: string | undefined, scriptLang: string) {
|
||||
const filePath = computeModelPath(path, scriptLang)
|
||||
return computeModelUri(filePath, scriptLang, scriptLangToEditorLang(scriptLang as any))
|
||||
}
|
||||
|
||||
describe('computeModelUri', () => {
|
||||
it.each([
|
||||
['u/admin/my_script', 'bun', 'file:///u/admin/my_script.ts'],
|
||||
['u/admin/my_script', 'bunnative', 'file:///u/admin/my_script.ts'],
|
||||
['u/admin/my_script', 'nativets', 'file:///u/admin/my_script.ts'],
|
||||
['u/admin/component', 'tsx', 'file:///u/admin/component.tsx'],
|
||||
['u/admin/component', 'jsx', 'file:///u/admin/component.js'],
|
||||
['u/admin/script', 'javascript', 'file:///u/admin/script.js'],
|
||||
// flow module and raw-app runnable derive their path as <item path>/<id>
|
||||
['f/flows/myflow/a', 'bun', 'file:///f/flows/myflow/a.ts'],
|
||||
['u/admin/myapp/backend_1', 'bun', 'file:///u/admin/myapp/backend_1.ts'],
|
||||
['/u/admin/leading_slash', 'bun', 'file:///u/admin/leading_slash.ts'],
|
||||
// a path that already carries an extension keeps it verbatim
|
||||
['u/admin/lib.ts', 'bun', 'file:///u/admin/lib.ts']
|
||||
])('%s (%s) -> %s', (path, scriptLang, expected) => {
|
||||
expect(uriFor(path, scriptLang)).toBe(expected)
|
||||
})
|
||||
|
||||
it.each(['deno', 'go', 'python3'])(
|
||||
'randomizes the path and namespaces %s under /tmp/monaco',
|
||||
(scriptLang) => {
|
||||
const uri = uriFor('u/admin/my_script', scriptLang)
|
||||
expect(uri.startsWith('file:///tmp/monaco/')).toBe(true)
|
||||
expect(uri).not.toContain('my_script')
|
||||
expect(uri).not.toBe(uriFor('u/admin/my_script', scriptLang))
|
||||
}
|
||||
)
|
||||
|
||||
it('falls back to a random path when none is given', () => {
|
||||
expect(computeModelPath(undefined, 'bun')).not.toBe('')
|
||||
expect(computeModelPath('', 'bun')).not.toBe('')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,34 @@
|
||||
import { createHash as randomHash, langToExt } from '$lib/editorLangUtils'
|
||||
|
||||
// Canonical Monaco model path/URI for a piece of Windmill code. Diagnostics are a
|
||||
// property of the model at a given URI, so any code that lints headlessly must
|
||||
// derive the URI from here — a URI that differs from the editor's yields a second,
|
||||
// independently-validated model and diverging markers.
|
||||
|
||||
const RANDOMIZED_PATH_LANGS = ['deno', 'go', 'python3']
|
||||
|
||||
export function computeModelPath(path: string | undefined, scriptLang: string | undefined): string {
|
||||
if (RANDOMIZED_PATH_LANGS.includes(scriptLang ?? '') || path == '' || path == undefined) {
|
||||
return randomHash()
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
export function computeModelUri(
|
||||
filePath: string,
|
||||
scriptLang: string | undefined,
|
||||
editorLang: string
|
||||
): string {
|
||||
let file: string
|
||||
if (filePath.includes('.')) {
|
||||
file = filePath
|
||||
} else {
|
||||
file = `${filePath}.${scriptLang == 'tsx' ? 'tsx' : langToExt(editorLang)}`
|
||||
}
|
||||
if (file.startsWith('/')) {
|
||||
file = file.slice(1)
|
||||
}
|
||||
return !RANDOMIZED_PATH_LANGS.includes(scriptLang ?? '')
|
||||
? `file:///${file}`
|
||||
: `file:///tmp/monaco/${file}`
|
||||
}
|
||||
Reference in New Issue
Block a user