Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,012 changes: 27 additions & 2,985 deletions src/integration.spec.ts

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions src/lang/KclSingleton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import type {
Selections,
} from '@src/machines/modelingSharedTypes'
import { type handleSelectionBatch as handleSelectionBatchFn } from '@src/lib/selections'
import { processEnv } from '@src/env'

interface ExecuteArgs {
ast?: Node<Program>
Expand Down Expand Up @@ -281,6 +282,15 @@ export class KclManager extends EventTarget {

// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.ensureWasmInit().then(async () => {
if (this.wasmInitFailed) {
if (processEnv()?.VITEST) {
console.log(
'Running in vitest runtime. KclSingleton polluting global runtime.'
)
return
}
}

await this.safeParse(this.singletons.codeManager.code).then((ast) => {
if (ast) {
this.ast = ast
Expand Down Expand Up @@ -422,6 +432,13 @@ export class KclManager extends EventTarget {
}

async ensureWasmInit() {
if (processEnv()?.VITEST) {
const message =
'kclSingle is trying to call ensureWasmInit. This will be blocked in VITEST runtimes.'
console.log(message)
return Promise.resolve(message)
}

try {
await initPromise
if (this.wasmInitFailed) {
Expand Down
120 changes: 120 additions & 0 deletions src/lang/getNodePathFromSourceRange.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { getNodePathFromSourceRange } from '@src/lang/queryAstNodePathUtils'
import { assertParse, type Name, type Parameter } from '@src/lang/wasm'
import { join } from 'path'
import { loadAndInitialiseWasmInstance } from '@src/lang/wasmUtilsNode'
import { topLevelRange } from '@src/lang/util'
import { getNodeFromPath } from '@src/lang/queryAst'
import { err } from '@src/lib/trap'
import { ARG_INDEX_FIELD, LABELED_ARG_FIELD } from '@src/lang/queryAstConstants'
const WASM_PATH = join(process.cwd(), 'public/kcl_wasm_lib_bg.wasm')

describe('getNodePathFromSourceRange', () => {
describe('testing getNodePathFromSourceRange', () => {
it('test it gets the right path for a `lineTo` CallExpression within a SketchExpression', async () => {
const instance = await loadAndInitialiseWasmInstance(WASM_PATH)
const code = `
myVar = 5
sk3 = startSketchOn(XY)
|> startProfile(at = [0, 0])
|> line(endAbsolute = [1, 2])
|> line(endAbsolute = [3, 4], tag = $yo)
|> close()
`
const subStr = 'line(endAbsolute = [3, 4], tag = $yo)'
const lineToSubstringIndex = code.indexOf(subStr)
const sourceRange = topLevelRange(
lineToSubstringIndex,
lineToSubstringIndex + subStr.length
)

const ast = assertParse(code, instance)
const nodePath = getNodePathFromSourceRange(ast, sourceRange)
const _node = getNodeFromPath<any>(ast, nodePath)
if (err(_node)) throw _node
const { node } = _node

expect(topLevelRange(node.start, node.end)).toEqual(sourceRange)
expect(node.type).toBe('CallExpressionKw')
})
it('gets path right for function definition params', async () => {
const instance = await loadAndInitialiseWasmInstance(WASM_PATH)
const code = `fn cube(pos, scale) {
sg = startSketchOn(XY)
|> startProfile(at = pos)
|> line(end = [0, scale])
|> line(end = [scale, 0])
|> line(end = [0, -scale])

return sg
}

b1 = cube(pos = [0,0], scale = 10)`
const subStr = 'pos, scale'
const subStrIndex = code.indexOf(subStr)
const sourceRange = topLevelRange(subStrIndex, subStrIndex + 'pos'.length)

const ast = assertParse(code, instance)
const nodePath = getNodePathFromSourceRange(ast, sourceRange)
const _node = getNodeFromPath<Parameter>(ast, nodePath)
if (err(_node)) throw _node
const node = _node.node

expect(nodePath).toEqual([
['body', ''],
[0, 'index'],
['declaration', 'VariableDeclaration'],
['init', ''],
['params', 'FunctionExpression'],
[0, 'index'],
])
expect(node.type).toBe('Parameter')
expect(node.identifier.name).toBe('pos')
})
it('gets path right for deep within function definition body', async () => {
const instance = await loadAndInitialiseWasmInstance(WASM_PATH)
const code = `fn cube(pos, scale) {
sg = startSketchOn(XY)
|> startProfile(at = pos)
|> line(end = [0, scale])
|> line(end = [scale, 0])
|> line(end = [0, -scale])

return sg
}

b1 = cube(pos = [0,0], scale = 10)`
const subStr = 'scale, 0'
const subStrIndex = code.indexOf(subStr)
const sourceRange = topLevelRange(
subStrIndex,
subStrIndex + 'scale'.length
)

const ast = assertParse(code, instance)
const nodePath = getNodePathFromSourceRange(ast, sourceRange)
const _node = getNodeFromPath<Name>(ast, nodePath)
if (err(_node)) throw _node
const node = _node.node
expect(nodePath).toEqual([
['body', ''],
[0, 'index'],
['declaration', 'VariableDeclaration'],
['init', ''],
['body', 'FunctionExpression'],
['body', 'FunctionExpression'],
[0, 'index'],
['declaration', 'VariableDeclaration'],
['init', ''],
['body', 'PipeExpression'],
[3, 'index'],
['arguments', 'CallExpressionKw'],
[0, ARG_INDEX_FIELD],
['arg', LABELED_ARG_FIELD],
['elements', 'ArrayExpression'],
[0, 'index'],
])
expect(node.type).toBe('Name')
expect(node.name.name).toBe('scale')
})
})
})
5 changes: 4 additions & 1 deletion src/lang/langHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { emptyExecState, kclLint } from '@src/lang/wasm'
import { EXECUTE_AST_INTERRUPT_ERROR_STRING } from '@src/lib/constants'
import type RustContext from '@src/lib/rustContext'
import { jsAppSettings } from '@src/lib/settings/settingsUtils'
import type { ModuleType } from '@src/lib/wasm_lib_wrapper'
import { REJECTED_TOO_EARLY_WEBSOCKET_MESSAGE } from '@src/network/utils'
import type { EditorView } from 'codemirror'

Expand Down Expand Up @@ -171,12 +172,14 @@ function handleExecuteError(e: any): ExecutionResult {
export async function lintAst({
ast,
sourceCode,
instance,
}: {
ast: Program
sourceCode: string
instance?: ModuleType
}): Promise<Array<Diagnostic>> {
try {
const discovered_findings = await kclLint(ast)
const discovered_findings = await kclLint(ast, instance)
return discovered_findings.map((lint) => {
let actions
const suggestion = lint.suggestion
Expand Down
Loading