2024-12-06 13:57:31 +13:00
|
|
|
import {
|
|
|
|
assertParse,
|
|
|
|
recast,
|
|
|
|
initPromise,
|
|
|
|
PathToNode,
|
|
|
|
Identifier,
|
|
|
|
} from './wasm'
|
2023-04-01 16:47:00 +11:00
|
|
|
import {
|
|
|
|
findAllPreviousVariables,
|
|
|
|
isNodeSafeToReplace,
|
|
|
|
isTypeInValue,
|
|
|
|
getNodePathFromSourceRange,
|
2023-10-11 13:36:54 +11:00
|
|
|
doesPipeHaveCallExp,
|
2024-09-27 15:44:44 -07:00
|
|
|
hasExtrudeSketch,
|
2024-05-24 20:54:42 +10:00
|
|
|
findUsesOfTagInPipe,
|
2024-06-21 13:20:42 +10:00
|
|
|
hasSketchPipeBeenExtruded,
|
2024-09-17 08:29:52 -05:00
|
|
|
doesSceneHaveSweepableSketch,
|
2024-06-25 12:46:40 +10:00
|
|
|
traverse,
|
2024-11-17 18:03:21 -05:00
|
|
|
getNodeFromPath,
|
2023-04-01 16:47:00 +11:00
|
|
|
} from './queryAst'
|
2023-07-10 15:15:07 +10:00
|
|
|
import { enginelessExecutor } from '../lib/testHelpers'
|
2023-04-01 16:47:00 +11:00
|
|
|
import {
|
|
|
|
createArrayExpression,
|
|
|
|
createCallExpression,
|
|
|
|
createLiteral,
|
|
|
|
createPipeSubstitution,
|
|
|
|
} from './modifyAst'
|
2024-06-24 11:45:40 -04:00
|
|
|
import { err } from 'lib/trap'
|
2024-11-21 15:04:30 +11:00
|
|
|
import { codeRefFromRange } from './std/artifactGraph'
|
2023-03-10 08:35:30 +11:00
|
|
|
|
2024-04-19 14:24:40 -07:00
|
|
|
beforeAll(async () => {
|
|
|
|
await initPromise
|
|
|
|
})
|
2023-03-10 08:35:30 +11:00
|
|
|
|
|
|
|
describe('findAllPreviousVariables', () => {
|
2023-06-22 16:43:33 +10:00
|
|
|
it('should find all previous variables', async () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const code = `baseThick = 1
|
|
|
|
armAngle = 60
|
2023-03-10 08:35:30 +11:00
|
|
|
|
2024-10-02 14:19:40 -05:00
|
|
|
baseThickHalf = baseThick / 2
|
|
|
|
halfArmAngle = armAngle / 2
|
2023-03-10 08:35:30 +11:00
|
|
|
|
2024-10-02 14:19:40 -05:00
|
|
|
arrExpShouldNotBeIncluded = [1, 2, 3]
|
|
|
|
objExpShouldNotBeIncluded = { a: 1, b: 2, c: 3 }
|
2023-03-10 08:35:30 +11:00
|
|
|
|
2024-10-02 14:19:40 -05:00
|
|
|
part001 = startSketchOn('XY')
|
2023-10-05 14:27:48 -07:00
|
|
|
|> startProfileAt([0, 0], %)
|
2023-03-10 08:35:30 +11:00
|
|
|
|> yLineTo(1, %)
|
|
|
|
|> xLine(3.84, %) // selection-range-7ish-before-this
|
|
|
|
|
2024-10-02 14:19:40 -05:00
|
|
|
variableBelowShouldNotBeIncluded = 3
|
2024-03-01 17:16:18 -08:00
|
|
|
`
|
2023-03-10 08:35:30 +11:00
|
|
|
const rangeStart = code.indexOf('// selection-range-7ish-before-this') - 7
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2023-03-10 08:35:30 +11:00
|
|
|
|
|
|
|
const { variables, bodyPath, insertIndex } = findAllPreviousVariables(
|
|
|
|
ast,
|
2024-10-09 19:38:40 -04:00
|
|
|
execState.memory,
|
2024-12-06 13:57:31 +13:00
|
|
|
[rangeStart, rangeStart, true]
|
2023-03-10 08:35:30 +11:00
|
|
|
)
|
|
|
|
expect(variables).toEqual([
|
|
|
|
{ key: 'baseThick', value: 1 },
|
|
|
|
{ key: 'armAngle', value: 60 },
|
|
|
|
{ key: 'baseThickHalf', value: 0.5 },
|
|
|
|
{ key: 'halfArmAngle', value: 30 },
|
|
|
|
// no arrExpShouldNotBeIncluded, variableBelowShouldNotBeIncluded etc
|
|
|
|
])
|
|
|
|
// there are 4 number variables and 2 non-number variables before the sketch var
|
|
|
|
// ∴ the insert index should be 6
|
|
|
|
expect(insertIndex).toEqual(6)
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(bodyPath).toEqual([['body', '']])
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('testing argIsNotIdentifier', () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const code = `part001 = startSketchOn('XY')
|
2023-10-05 14:27:48 -07:00
|
|
|
|> startProfileAt([-1.2, 4.83], %)
|
2023-04-01 16:47:00 +11:00
|
|
|
|> line([2.8, 0], %)
|
|
|
|
|> angledLine([100 + 100, 3.09], %)
|
|
|
|
|> angledLine([abc, 3.09], %)
|
|
|
|
|> angledLine([def('yo'), 3.09], %)
|
|
|
|
|> angledLine([ghi(%), 3.09], %)
|
|
|
|
|> angledLine([jkl('yo') + 2, 3.09], %)
|
2024-10-02 14:19:40 -05:00
|
|
|
yo = 5 + 6
|
|
|
|
yo2 = hmm([identifierGuy + 5])`
|
2023-04-01 16:47:00 +11:00
|
|
|
it('find a safe binaryExpression', () => {
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2023-04-01 16:47:00 +11:00
|
|
|
const rangeStart = code.indexOf('100 + 100') + 2
|
2024-12-06 13:57:31 +13:00
|
|
|
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart, true])
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(result)) throw result
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(result.isSafe).toBe(true)
|
|
|
|
expect(result.value?.type).toBe('BinaryExpression')
|
|
|
|
expect(code.slice(result.value.start, result.value.end)).toBe('100 + 100')
|
2024-07-25 20:11:46 -04:00
|
|
|
const replaced = result.replacer(structuredClone(ast), 'replaceName')
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(replaced)) throw replaced
|
|
|
|
const outCode = recast(replaced.modifiedAst)
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
|
|
|
|
})
|
|
|
|
it('find a safe Identifier', () => {
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2023-04-01 16:47:00 +11:00
|
|
|
const rangeStart = code.indexOf('abc')
|
2024-12-06 13:57:31 +13:00
|
|
|
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart, true])
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(result)) throw result
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(result.isSafe).toBe(true)
|
|
|
|
expect(result.value?.type).toBe('Identifier')
|
|
|
|
expect(code.slice(result.value.start, result.value.end)).toBe('abc')
|
|
|
|
})
|
|
|
|
it('find a safe CallExpression', () => {
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2023-04-01 16:47:00 +11:00
|
|
|
const rangeStart = code.indexOf('def')
|
2024-12-06 13:57:31 +13:00
|
|
|
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart, true])
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(result)) throw result
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(result.isSafe).toBe(true)
|
|
|
|
expect(result.value?.type).toBe('CallExpression')
|
|
|
|
expect(code.slice(result.value.start, result.value.end)).toBe("def('yo')")
|
2024-07-25 20:11:46 -04:00
|
|
|
const replaced = result.replacer(structuredClone(ast), 'replaceName')
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(replaced)) throw replaced
|
|
|
|
const outCode = recast(replaced.modifiedAst)
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
|
|
|
|
})
|
|
|
|
it('find an UNsafe CallExpression, as it has a PipeSubstitution', () => {
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2023-04-01 16:47:00 +11:00
|
|
|
const rangeStart = code.indexOf('ghi')
|
2024-12-06 13:57:31 +13:00
|
|
|
const range: [number, number, boolean] = [rangeStart, rangeStart, true]
|
2023-04-01 16:47:00 +11:00
|
|
|
const result = isNodeSafeToReplace(ast, range)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(result)) throw result
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(result.isSafe).toBe(false)
|
|
|
|
expect(result.value?.type).toBe('CallExpression')
|
|
|
|
expect(code.slice(result.value.start, result.value.end)).toBe('ghi(%)')
|
|
|
|
})
|
|
|
|
it('find an UNsafe Identifier, as it is a callee', () => {
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2023-04-01 16:47:00 +11:00
|
|
|
const rangeStart = code.indexOf('ine([2.8,')
|
2024-12-06 13:57:31 +13:00
|
|
|
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart, true])
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(result)) throw result
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(result.isSafe).toBe(false)
|
|
|
|
expect(result.value?.type).toBe('CallExpression')
|
|
|
|
expect(code.slice(result.value.start, result.value.end)).toBe(
|
|
|
|
'line([2.8, 0], %)'
|
|
|
|
)
|
|
|
|
})
|
|
|
|
it("find a safe BinaryExpression that's assigned to a variable", () => {
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2023-04-01 16:47:00 +11:00
|
|
|
const rangeStart = code.indexOf('5 + 6') + 1
|
2024-12-06 13:57:31 +13:00
|
|
|
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart, true])
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(result)) throw result
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(result.isSafe).toBe(true)
|
|
|
|
expect(result.value?.type).toBe('BinaryExpression')
|
|
|
|
expect(code.slice(result.value.start, result.value.end)).toBe('5 + 6')
|
2024-07-25 20:11:46 -04:00
|
|
|
const replaced = result.replacer(structuredClone(ast), 'replaceName')
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(replaced)) throw replaced
|
|
|
|
const outCode = recast(replaced.modifiedAst)
|
2024-10-02 14:19:40 -05:00
|
|
|
expect(outCode).toContain(`yo = replaceName`)
|
2023-04-01 16:47:00 +11:00
|
|
|
})
|
|
|
|
it('find a safe BinaryExpression that has a CallExpression within', () => {
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2023-04-01 16:47:00 +11:00
|
|
|
const rangeStart = code.indexOf('jkl') + 1
|
2024-12-06 13:57:31 +13:00
|
|
|
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart, true])
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(result)) throw result
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(result.isSafe).toBe(true)
|
|
|
|
expect(result.value?.type).toBe('BinaryExpression')
|
|
|
|
expect(code.slice(result.value.start, result.value.end)).toBe(
|
|
|
|
"jkl('yo') + 2"
|
|
|
|
)
|
2024-07-25 20:11:46 -04:00
|
|
|
const replaced = result.replacer(structuredClone(ast), 'replaceName')
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(replaced)) throw replaced
|
|
|
|
const { modifiedAst } = replaced
|
2023-04-01 16:47:00 +11:00
|
|
|
const outCode = recast(modifiedAst)
|
|
|
|
expect(outCode).toContain(`angledLine([replaceName, 3.09], %)`)
|
|
|
|
})
|
|
|
|
it('find a safe BinaryExpression within a CallExpression', () => {
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2023-04-01 16:47:00 +11:00
|
|
|
const rangeStart = code.indexOf('identifierGuy') + 1
|
2024-12-06 13:57:31 +13:00
|
|
|
const result = isNodeSafeToReplace(ast, [rangeStart, rangeStart, true])
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(result)) throw result
|
|
|
|
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(result.isSafe).toBe(true)
|
|
|
|
expect(result.value?.type).toBe('BinaryExpression')
|
|
|
|
expect(code.slice(result.value.start, result.value.end)).toBe(
|
|
|
|
'identifierGuy + 5'
|
|
|
|
)
|
2024-07-25 20:11:46 -04:00
|
|
|
const replaced = result.replacer(structuredClone(ast), 'replaceName')
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(replaced)) throw replaced
|
|
|
|
const { modifiedAst } = replaced
|
2023-04-01 16:47:00 +11:00
|
|
|
const outCode = recast(modifiedAst)
|
2024-10-02 14:19:40 -05:00
|
|
|
expect(outCode).toContain(`yo2 = hmm([replaceName])`)
|
2023-04-01 16:47:00 +11:00
|
|
|
})
|
|
|
|
|
|
|
|
describe('testing isTypeInValue', () => {
|
2023-07-20 19:25:04 -04:00
|
|
|
it('finds the pipeSubstituion', () => {
|
2023-04-01 16:47:00 +11:00
|
|
|
const val = createCallExpression('yoyo', [
|
|
|
|
createArrayExpression([
|
|
|
|
createLiteral(1),
|
|
|
|
createCallExpression('yoyo2', [createPipeSubstitution()]),
|
|
|
|
createLiteral('hey'),
|
|
|
|
]),
|
|
|
|
])
|
|
|
|
expect(isTypeInValue(val, 'PipeSubstitution')).toBe(true)
|
|
|
|
})
|
|
|
|
it('There is no pipeSubstituion', () => {
|
|
|
|
const val = createCallExpression('yoyo', [
|
|
|
|
createArrayExpression([
|
|
|
|
createLiteral(1),
|
|
|
|
createCallExpression('yoyo2', [createLiteral(5)]),
|
|
|
|
createLiteral('hey'),
|
|
|
|
]),
|
|
|
|
])
|
|
|
|
expect(isTypeInValue(val, 'PipeSubstitution')).toBe(false)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('testing getNodePathFromSourceRange', () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const code = `part001 = startSketchOn('XY')
|
2023-10-05 14:27:48 -07:00
|
|
|
|> startProfileAt([0.39, -0.05], %)
|
2023-04-01 16:47:00 +11:00
|
|
|
|> line([0.94, 2.61], %)
|
2024-03-01 17:16:18 -08:00
|
|
|
|> line([-0.21, -1.4], %)`
|
2023-07-20 19:25:04 -04:00
|
|
|
it('finds the second line when cursor is put at the end', () => {
|
2023-04-01 16:47:00 +11:00
|
|
|
const searchLn = `line([0.94, 2.61], %)`
|
|
|
|
const sourceIndex = code.indexOf(searchLn) + searchLn.length
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2024-12-06 13:57:31 +13:00
|
|
|
const result = getNodePathFromSourceRange(ast, [
|
|
|
|
sourceIndex,
|
|
|
|
sourceIndex,
|
|
|
|
true,
|
|
|
|
])
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(result).toEqual([
|
|
|
|
['body', ''],
|
|
|
|
[0, 'index'],
|
|
|
|
['declarations', 'VariableDeclaration'],
|
|
|
|
[0, 'index'],
|
|
|
|
['init', ''],
|
|
|
|
['body', 'PipeExpression'],
|
2023-10-05 14:27:48 -07:00
|
|
|
[2, 'index'],
|
2023-04-01 16:47:00 +11:00
|
|
|
])
|
|
|
|
})
|
2023-07-20 19:25:04 -04:00
|
|
|
it('finds the last line when cursor is put at the end', () => {
|
2023-04-01 16:47:00 +11:00
|
|
|
const searchLn = `line([-0.21, -1.4], %)`
|
|
|
|
const sourceIndex = code.indexOf(searchLn) + searchLn.length
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2024-12-06 13:57:31 +13:00
|
|
|
const result = getNodePathFromSourceRange(ast, [
|
|
|
|
sourceIndex,
|
|
|
|
sourceIndex,
|
|
|
|
true,
|
|
|
|
])
|
2023-04-01 16:47:00 +11:00
|
|
|
const expected = [
|
|
|
|
['body', ''],
|
|
|
|
[0, 'index'],
|
|
|
|
['declarations', 'VariableDeclaration'],
|
|
|
|
[0, 'index'],
|
|
|
|
['init', ''],
|
|
|
|
['body', 'PipeExpression'],
|
2023-10-05 14:27:48 -07:00
|
|
|
[3, 'index'],
|
2023-04-01 16:47:00 +11:00
|
|
|
]
|
|
|
|
expect(result).toEqual(expected)
|
|
|
|
// expect similar result for start of line
|
|
|
|
const startSourceIndex = code.indexOf(searchLn)
|
|
|
|
const startResult = getNodePathFromSourceRange(ast, [
|
|
|
|
startSourceIndex,
|
|
|
|
startSourceIndex,
|
2024-12-06 13:57:31 +13:00
|
|
|
true,
|
2023-04-01 16:47:00 +11:00
|
|
|
])
|
|
|
|
expect(startResult).toEqual([...expected, ['callee', 'CallExpression']])
|
|
|
|
// expect similar result when whole line is selected
|
|
|
|
const selectWholeThing = getNodePathFromSourceRange(ast, [
|
|
|
|
startSourceIndex,
|
|
|
|
sourceIndex,
|
2024-12-06 13:57:31 +13:00
|
|
|
true,
|
2023-04-01 16:47:00 +11:00
|
|
|
])
|
|
|
|
expect(selectWholeThing).toEqual(expected)
|
2023-03-10 08:35:30 +11:00
|
|
|
})
|
2024-11-17 18:03:21 -05:00
|
|
|
|
|
|
|
it('finds the node in if-else condition', () => {
|
|
|
|
const code = `y = 0
|
|
|
|
x = if x > y {
|
|
|
|
x + 1
|
|
|
|
} else {
|
|
|
|
y
|
|
|
|
}`
|
|
|
|
const searchLn = `x > y`
|
|
|
|
const sourceIndex = code.indexOf(searchLn)
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2024-11-17 18:03:21 -05:00
|
|
|
|
2024-12-06 13:57:31 +13:00
|
|
|
const result = getNodePathFromSourceRange(ast, [
|
|
|
|
sourceIndex,
|
|
|
|
sourceIndex,
|
|
|
|
true,
|
|
|
|
])
|
2024-11-17 18:03:21 -05:00
|
|
|
expect(result).toEqual([
|
|
|
|
['body', ''],
|
|
|
|
[1, 'index'],
|
|
|
|
['declarations', 'VariableDeclaration'],
|
|
|
|
[0, 'index'],
|
|
|
|
['init', ''],
|
|
|
|
['cond', 'IfExpression'],
|
|
|
|
['left', 'BinaryExpression'],
|
|
|
|
])
|
|
|
|
const _node = getNodeFromPath<Identifier>(ast, result)
|
|
|
|
if (err(_node)) throw _node
|
|
|
|
expect(_node.node.type).toEqual('Identifier')
|
|
|
|
expect(_node.node.name).toEqual('x')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('finds the node in if-else then', () => {
|
|
|
|
const code = `y = 0
|
|
|
|
x = if x > y {
|
|
|
|
x + 1
|
|
|
|
} else {
|
|
|
|
y
|
|
|
|
}`
|
|
|
|
const searchLn = `x + 1`
|
|
|
|
const sourceIndex = code.indexOf(searchLn)
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2024-11-17 18:03:21 -05:00
|
|
|
|
2024-12-06 13:57:31 +13:00
|
|
|
const result = getNodePathFromSourceRange(ast, [
|
|
|
|
sourceIndex,
|
|
|
|
sourceIndex,
|
|
|
|
true,
|
|
|
|
])
|
2024-11-17 18:03:21 -05:00
|
|
|
expect(result).toEqual([
|
|
|
|
['body', ''],
|
|
|
|
[1, 'index'],
|
|
|
|
['declarations', 'VariableDeclaration'],
|
|
|
|
[0, 'index'],
|
|
|
|
['init', ''],
|
|
|
|
['then_val', 'IfExpression'],
|
|
|
|
['body', 'IfExpression'],
|
|
|
|
[0, 'index'],
|
|
|
|
['expression', 'ExpressionStatement'],
|
|
|
|
['left', 'BinaryExpression'],
|
|
|
|
])
|
|
|
|
const _node = getNodeFromPath<Identifier>(ast, result)
|
|
|
|
if (err(_node)) throw _node
|
|
|
|
expect(_node.node.type).toEqual('Identifier')
|
|
|
|
expect(_node.node.name).toEqual('x')
|
|
|
|
})
|
|
|
|
|
|
|
|
it('finds the node in import statement item', () => {
|
|
|
|
const code = `import foo, bar as baz from 'thing.kcl'`
|
|
|
|
const searchLn = `bar`
|
|
|
|
const sourceIndex = code.indexOf(searchLn)
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2024-11-17 18:03:21 -05:00
|
|
|
|
2024-12-06 13:57:31 +13:00
|
|
|
const result = getNodePathFromSourceRange(ast, [
|
|
|
|
sourceIndex,
|
|
|
|
sourceIndex,
|
|
|
|
true,
|
|
|
|
])
|
2024-11-17 18:03:21 -05:00
|
|
|
expect(result).toEqual([
|
|
|
|
['body', ''],
|
|
|
|
[0, 'index'],
|
|
|
|
['items', 'ImportStatement'],
|
|
|
|
[1, 'index'],
|
|
|
|
['name', 'ImportItem'],
|
|
|
|
])
|
|
|
|
const _node = getNodeFromPath<Identifier>(ast, result)
|
|
|
|
if (err(_node)) throw _node
|
|
|
|
expect(_node.node.type).toEqual('Identifier')
|
|
|
|
expect(_node.node.name).toEqual('bar')
|
|
|
|
})
|
2023-03-10 08:35:30 +11:00
|
|
|
})
|
2023-10-11 13:36:54 +11:00
|
|
|
|
|
|
|
describe('testing doesPipeHave', () => {
|
|
|
|
it('finds close', () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const exampleCode = `length001 = 2
|
|
|
|
part001 = startSketchAt([-1.41, 3.46])
|
2024-07-27 17:59:41 -07:00
|
|
|
|> line([19.49, 1.16], %, $seg01)
|
2023-10-11 13:36:54 +11:00
|
|
|
|> angledLine([-35, length001], %)
|
|
|
|
|> line([-3.22, -7.36], %)
|
2024-07-27 22:56:46 -07:00
|
|
|
|> angledLine([-175, segLen(seg01)], %)
|
2023-10-11 13:36:54 +11:00
|
|
|
|> close(%)
|
|
|
|
`
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2023-10-11 13:36:54 +11:00
|
|
|
const result = doesPipeHaveCallExp({
|
|
|
|
calleeName: 'close',
|
|
|
|
ast,
|
2024-11-21 15:04:30 +11:00
|
|
|
selection: {
|
2024-12-06 13:57:31 +13:00
|
|
|
codeRef: codeRefFromRange([100, 101, true], ast),
|
2024-11-21 15:04:30 +11:00
|
|
|
},
|
2023-10-11 13:36:54 +11:00
|
|
|
})
|
|
|
|
expect(result).toEqual(true)
|
|
|
|
})
|
|
|
|
it('finds extrude', () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const exampleCode = `length001 = 2
|
|
|
|
part001 = startSketchAt([-1.41, 3.46])
|
2024-07-27 17:59:41 -07:00
|
|
|
|> line([19.49, 1.16], %, $seg01)
|
2023-10-11 13:36:54 +11:00
|
|
|
|> angledLine([-35, length001], %)
|
|
|
|
|> line([-3.22, -7.36], %)
|
2024-07-27 22:56:46 -07:00
|
|
|
|> angledLine([-175, segLen(seg01)], %)
|
2023-10-11 13:36:54 +11:00
|
|
|
|> close(%)
|
|
|
|
|> extrude(1, %)
|
|
|
|
`
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2023-10-11 13:36:54 +11:00
|
|
|
const result = doesPipeHaveCallExp({
|
|
|
|
calleeName: 'extrude',
|
|
|
|
ast,
|
2024-11-21 15:04:30 +11:00
|
|
|
selection: {
|
2024-12-06 13:57:31 +13:00
|
|
|
codeRef: codeRefFromRange([100, 101, true], ast),
|
2024-11-21 15:04:30 +11:00
|
|
|
},
|
2023-10-11 13:36:54 +11:00
|
|
|
})
|
|
|
|
expect(result).toEqual(true)
|
|
|
|
})
|
|
|
|
it('does NOT find close', () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const exampleCode = `length001 = 2
|
|
|
|
part001 = startSketchAt([-1.41, 3.46])
|
2024-07-27 17:59:41 -07:00
|
|
|
|> line([19.49, 1.16], %, $seg01)
|
2023-10-11 13:36:54 +11:00
|
|
|
|> angledLine([-35, length001], %)
|
|
|
|
|> line([-3.22, -7.36], %)
|
2024-07-27 22:56:46 -07:00
|
|
|
|> angledLine([-175, segLen(seg01)], %)
|
2023-10-11 13:36:54 +11:00
|
|
|
`
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2023-10-11 13:36:54 +11:00
|
|
|
const result = doesPipeHaveCallExp({
|
|
|
|
calleeName: 'close',
|
|
|
|
ast,
|
2024-11-21 15:04:30 +11:00
|
|
|
selection: {
|
2024-12-06 13:57:31 +13:00
|
|
|
codeRef: codeRefFromRange([100, 101, true], ast),
|
2024-11-21 15:04:30 +11:00
|
|
|
},
|
2023-10-11 13:36:54 +11:00
|
|
|
})
|
|
|
|
expect(result).toEqual(false)
|
|
|
|
})
|
|
|
|
it('returns false if not a pipe', () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const exampleCode = `length001 = 2`
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2023-10-11 13:36:54 +11:00
|
|
|
const result = doesPipeHaveCallExp({
|
|
|
|
calleeName: 'close',
|
|
|
|
ast,
|
2024-11-21 15:04:30 +11:00
|
|
|
selection: {
|
2024-12-06 13:57:31 +13:00
|
|
|
codeRef: codeRefFromRange([9, 10, true], ast),
|
2024-11-21 15:04:30 +11:00
|
|
|
},
|
2023-10-11 13:36:54 +11:00
|
|
|
})
|
|
|
|
expect(result).toEqual(false)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2024-09-27 15:44:44 -07:00
|
|
|
describe('testing hasExtrudeSketch', () => {
|
|
|
|
it('find sketch', async () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const exampleCode = `length001 = 2
|
|
|
|
part001 = startSketchAt([-1.41, 3.46])
|
2024-07-27 17:59:41 -07:00
|
|
|
|> line([19.49, 1.16], %, $seg01)
|
2023-10-11 13:36:54 +11:00
|
|
|
|> angledLine([-35, length001], %)
|
|
|
|
|> line([-3.22, -7.36], %)
|
2024-07-27 22:56:46 -07:00
|
|
|
|> angledLine([-175, segLen(seg01)], %)`
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2024-09-27 15:44:44 -07:00
|
|
|
const result = hasExtrudeSketch({
|
2023-10-11 13:36:54 +11:00
|
|
|
ast,
|
2024-11-21 15:04:30 +11:00
|
|
|
selection: {
|
2024-12-06 13:57:31 +13:00
|
|
|
codeRef: codeRefFromRange([100, 101, true], ast),
|
2024-11-21 15:04:30 +11:00
|
|
|
},
|
2024-10-09 19:38:40 -04:00
|
|
|
programMemory: execState.memory,
|
2023-10-11 13:36:54 +11:00
|
|
|
})
|
|
|
|
expect(result).toEqual(true)
|
|
|
|
})
|
2024-09-27 15:44:44 -07:00
|
|
|
it('find solid', async () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const exampleCode = `length001 = 2
|
|
|
|
part001 = startSketchAt([-1.41, 3.46])
|
2024-07-27 17:59:41 -07:00
|
|
|
|> line([19.49, 1.16], %, $seg01)
|
2023-10-11 13:36:54 +11:00
|
|
|
|> angledLine([-35, length001], %)
|
|
|
|
|> line([-3.22, -7.36], %)
|
2024-07-27 22:56:46 -07:00
|
|
|
|> angledLine([-175, segLen(seg01)], %)
|
2023-10-11 13:36:54 +11:00
|
|
|
|> extrude(1, %)`
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2024-09-27 15:44:44 -07:00
|
|
|
const result = hasExtrudeSketch({
|
2023-10-11 13:36:54 +11:00
|
|
|
ast,
|
2024-11-21 15:04:30 +11:00
|
|
|
selection: {
|
2024-12-06 13:57:31 +13:00
|
|
|
codeRef: codeRefFromRange([100, 101, true], ast),
|
2024-11-21 15:04:30 +11:00
|
|
|
},
|
2024-10-09 19:38:40 -04:00
|
|
|
programMemory: execState.memory,
|
2023-10-11 13:36:54 +11:00
|
|
|
})
|
|
|
|
expect(result).toEqual(true)
|
|
|
|
})
|
|
|
|
it('finds nothing', async () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const exampleCode = `length001 = 2`
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2024-09-27 15:44:44 -07:00
|
|
|
const result = hasExtrudeSketch({
|
2023-10-11 13:36:54 +11:00
|
|
|
ast,
|
2024-11-21 15:04:30 +11:00
|
|
|
selection: {
|
2024-12-06 13:57:31 +13:00
|
|
|
codeRef: codeRefFromRange([10, 11, true], ast),
|
2024-11-21 15:04:30 +11:00
|
|
|
},
|
2024-10-09 19:38:40 -04:00
|
|
|
programMemory: execState.memory,
|
2023-10-11 13:36:54 +11:00
|
|
|
})
|
|
|
|
expect(result).toEqual(false)
|
|
|
|
})
|
|
|
|
})
|
2024-05-24 20:54:42 +10:00
|
|
|
|
|
|
|
describe('Testing findUsesOfTagInPipe', () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const exampleCode = `part001 = startSketchOn('-XZ')
|
2024-05-24 20:54:42 +10:00
|
|
|
|> startProfileAt([68.12, 156.65], %)
|
|
|
|
|> line([306.21, 198.82], %)
|
2024-06-24 22:39:04 -07:00
|
|
|
|> line([306.21, 198.85], %, $seg01)
|
2024-07-27 22:56:46 -07:00
|
|
|
|> angledLine([-65, segLen(seg01)], %)
|
2024-05-24 20:54:42 +10:00
|
|
|
|> line([306.21, 198.87], %)
|
2024-07-27 22:56:46 -07:00
|
|
|
|> angledLine([65, segLen(seg01)], %)`
|
2024-05-24 20:54:42 +10:00
|
|
|
it('finds the current segment', async () => {
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2024-06-24 22:39:04 -07:00
|
|
|
const lineOfInterest = `198.85], %, $seg01`
|
2024-05-24 20:54:42 +10:00
|
|
|
const characterIndex =
|
|
|
|
exampleCode.indexOf(lineOfInterest) + lineOfInterest.length
|
|
|
|
const pathToNode = getNodePathFromSourceRange(ast, [
|
|
|
|
characterIndex,
|
|
|
|
characterIndex,
|
2024-12-06 13:57:31 +13:00
|
|
|
true,
|
2024-05-24 20:54:42 +10:00
|
|
|
])
|
|
|
|
const result = findUsesOfTagInPipe(ast, pathToNode)
|
|
|
|
expect(result).toHaveLength(2)
|
|
|
|
result.forEach((range) => {
|
|
|
|
expect(exampleCode.slice(range[0], range[1])).toContain('segLen')
|
|
|
|
})
|
|
|
|
})
|
|
|
|
it('find no tag if line has no tag', () => {
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-06-24 11:45:40 -04:00
|
|
|
|
2024-05-24 20:54:42 +10:00
|
|
|
const lineOfInterest = `line([306.21, 198.82], %)`
|
|
|
|
const characterIndex =
|
|
|
|
exampleCode.indexOf(lineOfInterest) + lineOfInterest.length
|
|
|
|
const pathToNode = getNodePathFromSourceRange(ast, [
|
|
|
|
characterIndex,
|
|
|
|
characterIndex,
|
2024-12-06 13:57:31 +13:00
|
|
|
true,
|
2024-05-24 20:54:42 +10:00
|
|
|
])
|
|
|
|
const result = findUsesOfTagInPipe(ast, pathToNode)
|
|
|
|
expect(result).toHaveLength(0)
|
|
|
|
})
|
|
|
|
})
|
2024-06-21 13:20:42 +10:00
|
|
|
|
|
|
|
describe('Testing hasSketchPipeBeenExtruded', () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const exampleCode = `sketch001 = startSketchOn('XZ')
|
2024-06-21 13:20:42 +10:00
|
|
|
|> startProfileAt([3.29, 7.86], %)
|
|
|
|
|> line([2.48, 2.44], %)
|
|
|
|
|> line([2.66, 1.17], %)
|
|
|
|
|> line([3.75, 0.46], %)
|
2024-06-24 22:39:04 -07:00
|
|
|
|> line([4.99, -0.46], %, $seg01)
|
2024-06-21 13:20:42 +10:00
|
|
|
|> line([3.3, -2.12], %)
|
|
|
|
|> line([2.16, -3.33], %)
|
|
|
|
|> line([0.85, -3.08], %)
|
|
|
|
|> line([-0.18, -3.36], %)
|
|
|
|
|> line([-3.86, -2.73], %)
|
|
|
|
|> line([-17.67, 0.85], %)
|
|
|
|
|> close(%)
|
2024-10-02 14:19:40 -05:00
|
|
|
extrude001 = extrude(10, sketch001)
|
2024-11-19 21:30:26 +01:00
|
|
|
sketch002 = startSketchOn(extrude001, seg01)
|
2024-06-21 13:20:42 +10:00
|
|
|
|> startProfileAt([-12.94, 6.6], %)
|
|
|
|
|> line([2.45, -0.2], %)
|
|
|
|
|> line([-2, -1.25], %)
|
|
|
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
|
|
|> close(%)
|
2024-11-19 21:30:26 +01:00
|
|
|
sketch003 = startSketchOn(extrude001, 'END')
|
|
|
|
|> startProfileAt([8.14, 2.8], %)
|
|
|
|
|> line([-1.24, 4.39], %)
|
|
|
|
|> line([3.79, 1.91], %)
|
|
|
|
|> line([1.77, -2.95], %)
|
|
|
|
|> line([3.12, 1.74], %)
|
|
|
|
|> line([1.91, -4.09], %)
|
|
|
|
|> line([-5.6, -2.75], %)
|
|
|
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
|
|
|> close(%)
|
|
|
|
|> extrude(3.14, %)
|
2024-06-21 13:20:42 +10:00
|
|
|
`
|
2024-11-19 21:30:26 +01:00
|
|
|
it('identifies sketch001 pipe as extruded (extrusion after pipe)', async () => {
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-06-24 22:39:04 -07:00
|
|
|
const lineOfInterest = `line([4.99, -0.46], %, $seg01)`
|
2024-06-21 13:20:42 +10:00
|
|
|
const characterIndex =
|
|
|
|
exampleCode.indexOf(lineOfInterest) + lineOfInterest.length
|
|
|
|
const extruded = hasSketchPipeBeenExtruded(
|
|
|
|
{
|
2024-12-06 13:57:31 +13:00
|
|
|
codeRef: codeRefFromRange([characterIndex, characterIndex, true], ast),
|
2024-06-21 13:20:42 +10:00
|
|
|
},
|
|
|
|
ast
|
|
|
|
)
|
|
|
|
expect(extruded).toBeTruthy()
|
|
|
|
})
|
2024-11-19 21:30:26 +01:00
|
|
|
it('identifies sketch002 pipe as not extruded', async () => {
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-06-21 13:20:42 +10:00
|
|
|
const lineOfInterest = `line([2.45, -0.2], %)`
|
|
|
|
const characterIndex =
|
|
|
|
exampleCode.indexOf(lineOfInterest) + lineOfInterest.length
|
|
|
|
const extruded = hasSketchPipeBeenExtruded(
|
|
|
|
{
|
2024-12-06 13:57:31 +13:00
|
|
|
codeRef: codeRefFromRange([characterIndex, characterIndex, true], ast),
|
2024-06-21 13:20:42 +10:00
|
|
|
},
|
|
|
|
ast
|
|
|
|
)
|
|
|
|
expect(extruded).toBeFalsy()
|
|
|
|
})
|
2024-11-19 21:30:26 +01:00
|
|
|
it('identifies sketch003 pipe as extruded (extrusion within pipe)', async () => {
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-11-19 21:30:26 +01:00
|
|
|
const lineOfInterest = `|> line([3.12, 1.74], %)`
|
|
|
|
const characterIndex =
|
|
|
|
exampleCode.indexOf(lineOfInterest) + lineOfInterest.length
|
|
|
|
const extruded = hasSketchPipeBeenExtruded(
|
|
|
|
{
|
2024-12-06 13:57:31 +13:00
|
|
|
codeRef: codeRefFromRange([characterIndex, characterIndex, true], ast),
|
2024-11-19 21:30:26 +01:00
|
|
|
},
|
|
|
|
ast
|
|
|
|
)
|
|
|
|
expect(extruded).toBeTruthy()
|
|
|
|
})
|
2024-06-21 13:20:42 +10:00
|
|
|
})
|
|
|
|
|
2024-09-17 08:29:52 -05:00
|
|
|
describe('Testing doesSceneHaveSweepableSketch', () => {
|
2024-06-21 13:20:42 +10:00
|
|
|
it('finds sketch001 pipe to be extruded', async () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const exampleCode = `sketch001 = startSketchOn('XZ')
|
2024-06-21 13:20:42 +10:00
|
|
|
|> startProfileAt([3.29, 7.86], %)
|
|
|
|
|> line([2.48, 2.44], %)
|
|
|
|
|> line([-3.86, -2.73], %)
|
|
|
|
|> line([-17.67, 0.85], %)
|
|
|
|
|> close(%)
|
2024-10-02 14:19:40 -05:00
|
|
|
extrude001 = extrude(10, sketch001)
|
|
|
|
sketch002 = startSketchOn(extrude001, $seg01)
|
2024-06-21 13:20:42 +10:00
|
|
|
|> startProfileAt([-12.94, 6.6], %)
|
|
|
|
|> line([2.45, -0.2], %)
|
|
|
|
|> line([-2, -1.25], %)
|
|
|
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
|
|
|> close(%)
|
|
|
|
`
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-09-17 08:29:52 -05:00
|
|
|
const extrudable = doesSceneHaveSweepableSketch(ast)
|
2024-06-21 13:20:42 +10:00
|
|
|
expect(extrudable).toBeTruthy()
|
|
|
|
})
|
2024-12-04 17:24:16 -05:00
|
|
|
it('finds sketch001 and sketch002 pipes to be lofted', async () => {
|
|
|
|
const exampleCode = `sketch001 = startSketchOn('XZ')
|
|
|
|
|> circle({ center = [0, 0], radius = 1 }, %)
|
|
|
|
plane001 = offsetPlane('XZ', 2)
|
|
|
|
sketch002 = startSketchOn(plane001)
|
|
|
|
|> circle({ center = [0, 0], radius = 3 }, %)
|
|
|
|
`
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-12-04 17:24:16 -05:00
|
|
|
const extrudable = doesSceneHaveSweepableSketch(ast, 2)
|
|
|
|
expect(extrudable).toBeTruthy()
|
|
|
|
})
|
2024-06-21 13:20:42 +10:00
|
|
|
it('find sketch002 NOT pipe to be extruded', async () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const exampleCode = `sketch001 = startSketchOn('XZ')
|
2024-06-21 13:20:42 +10:00
|
|
|
|> startProfileAt([3.29, 7.86], %)
|
|
|
|
|> line([2.48, 2.44], %)
|
|
|
|
|> line([-3.86, -2.73], %)
|
|
|
|
|> line([-17.67, 0.85], %)
|
|
|
|
|> close(%)
|
2024-10-02 14:19:40 -05:00
|
|
|
extrude001 = extrude(10, sketch001)
|
2024-06-21 13:20:42 +10:00
|
|
|
`
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(exampleCode)
|
2024-09-17 08:29:52 -05:00
|
|
|
const extrudable = doesSceneHaveSweepableSketch(ast)
|
2024-06-21 13:20:42 +10:00
|
|
|
expect(extrudable).toBeFalsy()
|
|
|
|
})
|
|
|
|
})
|
2024-06-25 12:46:40 +10:00
|
|
|
|
2024-06-25 14:16:44 +10:00
|
|
|
describe('Testing traverse and pathToNode', () => {
|
2024-06-25 12:46:40 +10:00
|
|
|
it.each([
|
|
|
|
['basic', '2.73'],
|
|
|
|
[
|
|
|
|
'very nested, array, object, callExpression, array, memberExpression',
|
|
|
|
'.yo',
|
|
|
|
],
|
|
|
|
])('testing %s', async (testName, literalOfInterest) => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const code = `myVar = 5
|
|
|
|
sketch001 = startSketchOn('XZ')
|
2024-06-25 12:46:40 +10:00
|
|
|
|> startProfileAt([3.29, 7.86], %)
|
|
|
|
|> line([2.48, 2.44], %)
|
|
|
|
|> line([-3.86, -2.73], %)
|
|
|
|
|> line([-17.67, 0.85], %)
|
|
|
|
|> close(%)
|
2024-10-02 14:19:40 -05:00
|
|
|
bing = { yo: 55 }
|
|
|
|
myNestedVar = [
|
2024-06-25 12:46:40 +10:00
|
|
|
{
|
|
|
|
prop: line([bing.yo, 21], sketch001)
|
|
|
|
}
|
|
|
|
]
|
|
|
|
`
|
2024-12-06 13:57:31 +13:00
|
|
|
const ast = assertParse(code)
|
2024-06-25 12:46:40 +10:00
|
|
|
let pathToNode: PathToNode = []
|
|
|
|
traverse(ast, {
|
|
|
|
enter: (node, path) => {
|
|
|
|
if (
|
|
|
|
node.type === 'Literal' &&
|
|
|
|
String(node.value) === literalOfInterest
|
|
|
|
) {
|
|
|
|
pathToNode = path
|
|
|
|
} else if (
|
|
|
|
node.type === 'Identifier' &&
|
|
|
|
literalOfInterest.includes(node.name)
|
|
|
|
) {
|
|
|
|
pathToNode = path
|
|
|
|
}
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
const literalIndex = code.indexOf(literalOfInterest)
|
|
|
|
const pathToNode2 = getNodePathFromSourceRange(ast, [
|
|
|
|
literalIndex + 2,
|
|
|
|
literalIndex + 2,
|
2024-12-06 13:57:31 +13:00
|
|
|
true,
|
2024-06-25 12:46:40 +10:00
|
|
|
])
|
|
|
|
expect(pathToNode).toEqual(pathToNode2)
|
|
|
|
})
|
|
|
|
})
|