Remove KclValue::SketchGroup variant (#3446)
We can store Rust types like `SketchGroup` as their own variant of `KclValue`, or as `KclValue::UserVal`. Sometimes we store in one and try to read from the other, which fails. This causes bugs, like #3338.
Instead, we should use either ::SketchGroup or ::UserVal, and stop using the other. If we stopped using ::UserVal, we'd need a new variant for every Rust type we wanted to build, including user-defined types. So I don't think that's practical.
Instead, we should store every KCL value by de/serializing it into UserVal. This is a first step along that path, removing just the SketchGroup variants. If it goes well, we can remove the other specialized variants too.
My only concern is there might be performance implications from how frequently we convert between serde_json::Value and Rust types via Serde. But I'm not too worried -- there's no parsing JSON strings, just traversing serde_json::Value trees. This isn't great for performance but I think it'll probably be miniscule in comparison to doing all the API calls.
2024-08-21 11:06:48 -05:00
|
|
|
import {
|
|
|
|
parse,
|
|
|
|
SketchGroup,
|
|
|
|
recast,
|
|
|
|
initPromise,
|
|
|
|
sketchGroupFromKclValue,
|
|
|
|
} from '../wasm'
|
2023-03-02 21:19:11 +11:00
|
|
|
import {
|
|
|
|
ConstraintType,
|
|
|
|
getTransformInfos,
|
2023-03-07 15:45:59 +11:00
|
|
|
transformAstSketchLines,
|
2023-03-02 21:19:11 +11:00
|
|
|
} from './sketchcombos'
|
2023-03-20 07:09:19 +11:00
|
|
|
import { getSketchSegmentFromSourceRange } from './sketchConstraints'
|
2023-10-16 21:20:05 +11:00
|
|
|
import { Selection } from 'lib/selections'
|
2023-07-10 15:15:07 +10:00
|
|
|
import { enginelessExecutor } from '../../lib/testHelpers'
|
2024-06-24 11:45:40 -04:00
|
|
|
import { err } from 'lib/trap'
|
2023-02-21 10:50:45 +11:00
|
|
|
|
2024-04-19 14:24:40 -07:00
|
|
|
beforeAll(async () => {
|
|
|
|
await initPromise
|
|
|
|
})
|
2023-02-21 10:50:45 +11:00
|
|
|
|
|
|
|
// testing helper function
|
2023-06-22 16:43:33 +10:00
|
|
|
async function testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode,
|
|
|
|
callToSwap,
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType,
|
2023-02-21 10:50:45 +11:00
|
|
|
}: {
|
|
|
|
inputCode: string
|
|
|
|
callToSwap: string
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: ConstraintType
|
2023-06-22 16:43:33 +10:00
|
|
|
}): Promise<{
|
2023-02-21 10:50:45 +11:00
|
|
|
newCode: string
|
|
|
|
originalRange: [number, number]
|
2023-06-22 16:43:33 +10:00
|
|
|
}> {
|
2023-02-21 10:50:45 +11:00
|
|
|
const startIndex = inputCode.indexOf(callToSwap)
|
2023-04-03 16:05:25 +10:00
|
|
|
const range: Selection = {
|
|
|
|
type: 'default',
|
|
|
|
range: [startIndex, startIndex + callToSwap.length],
|
|
|
|
}
|
2023-09-29 11:11:01 -07:00
|
|
|
const ast = parse(inputCode)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) return Promise.reject(ast)
|
|
|
|
|
2023-07-10 15:15:07 +10:00
|
|
|
const programMemory = await enginelessExecutor(ast)
|
2023-04-03 16:05:25 +10:00
|
|
|
const selections = {
|
|
|
|
codeBasedSelections: [range],
|
|
|
|
otherSelections: [],
|
|
|
|
}
|
|
|
|
const transformInfos = getTransformInfos(selections, ast, constraintType)
|
2023-03-02 21:19:11 +11:00
|
|
|
|
2024-06-24 11:45:40 -04:00
|
|
|
if (!transformInfos)
|
|
|
|
return Promise.reject(new Error('transformInfos undefined'))
|
|
|
|
const ast2 = transformAstSketchLines({
|
2023-02-21 10:50:45 +11:00
|
|
|
ast,
|
2023-03-02 21:19:11 +11:00
|
|
|
programMemory,
|
2023-04-03 16:05:25 +10:00
|
|
|
selectionRanges: selections,
|
2023-03-02 21:19:11 +11:00
|
|
|
transformInfos,
|
2023-03-07 15:45:59 +11:00
|
|
|
referenceSegName: '',
|
2023-03-02 21:19:11 +11:00
|
|
|
})
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast2)) return Promise.reject(ast2)
|
|
|
|
|
|
|
|
const newCode = recast(ast2.modifiedAst)
|
|
|
|
if (err(newCode)) return Promise.reject(newCode)
|
|
|
|
|
2023-02-21 10:50:45 +11:00
|
|
|
return {
|
2024-06-24 11:45:40 -04:00
|
|
|
newCode,
|
2023-04-03 16:05:25 +10:00
|
|
|
originalRange: range.range,
|
2023-02-21 10:50:45 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-01 17:34:54 -05:00
|
|
|
describe('testing swapping out sketch calls with xLine/xLineTo', () => {
|
2023-02-21 10:50:45 +11:00
|
|
|
const bigExampleArr = [
|
2023-10-05 14:27:48 -07:00
|
|
|
`const part001 = startSketchOn('XY')`,
|
|
|
|
` |> startProfileAt([0, 0], %)`,
|
2024-06-24 22:39:04 -07:00
|
|
|
` |> lineTo([1, 1], %, $abc1)`,
|
|
|
|
` |> line([-2.04, -0.7], %, $abc2)`,
|
|
|
|
` |> angledLine({ angle: 157, length: 1.69 }, %, $abc3)`,
|
|
|
|
` |> angledLineOfXLength({ angle: 217, length: 0.86 }, %, $abc4)`,
|
|
|
|
` |> angledLineOfYLength({ angle: 104, length: 1.58 }, %, $abc5)`,
|
|
|
|
` |> angledLineToX({ angle: 55, to: -2.89 }, %, $abc6)`,
|
|
|
|
` |> angledLineToY({ angle: 330, to: 2.53 }, %, $abc7)`,
|
|
|
|
` |> xLine(1.47, %, $abc8)`,
|
|
|
|
` |> yLine(1.57, %, $abc9)`,
|
|
|
|
` |> xLineTo(1.49, %, $abc10)`,
|
|
|
|
` |> yLineTo(2.64, %, $abc11)`,
|
2023-02-21 10:50:45 +11:00
|
|
|
` |> lineTo([2.55, 3.58], %) // lineTo`,
|
|
|
|
` |> line([0.73, -0.75], %)`,
|
|
|
|
` |> angledLine([63, 1.38], %) // angledLine`,
|
|
|
|
` |> angledLineOfXLength([319, 1.15], %) // angledLineOfXLength`,
|
|
|
|
` |> angledLineOfYLength([50, 1.35], %) // angledLineOfYLength`,
|
|
|
|
` |> angledLineToX([291, 6.66], %) // angledLineToX`,
|
|
|
|
` |> angledLineToY([228, 2.14], %) // angledLineToY`,
|
|
|
|
` |> xLine(-1.33, %)`,
|
|
|
|
` |> yLine(-1.07, %)`,
|
|
|
|
` |> xLineTo(3.27, %)`,
|
|
|
|
` |> yLineTo(2.14, %)`,
|
|
|
|
]
|
|
|
|
const bigExample = bigExampleArr.join('\n')
|
2023-06-22 16:43:33 +10:00
|
|
|
it('line with tag converts to xLine', async () => {
|
2024-06-24 22:39:04 -07:00
|
|
|
const callToSwap = 'line([-2.04, -0.7], %, $abc2)'
|
|
|
|
const expectedLine = 'xLine(-2.04, %, $abc2)'
|
2023-06-22 16:43:33 +10:00
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
|
|
|
callToSwap,
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('line w/o tag converts to xLine', async () => {
|
2023-02-21 10:50:45 +11:00
|
|
|
const callToSwap = 'line([0.73, -0.75], %)'
|
|
|
|
const expectedLine = 'xLine(0.73, %)'
|
2023-06-22 16:43:33 +10:00
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
|
|
|
callToSwap,
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('lineTo with tag converts to xLineTo', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
2024-06-24 22:39:04 -07:00
|
|
|
callToSwap: 'lineTo([1, 1], %, $abc1)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
2024-06-24 22:39:04 -07:00
|
|
|
const expectedLine = 'xLineTo(1, %, $abc1)'
|
2023-02-21 10:50:45 +11:00
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('lineTo w/o tag converts to xLineTo', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
|
|
|
callToSwap: 'lineTo([2.55, 3.58], %)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
const expectedLine = 'xLineTo(2.55, %) // lineTo'
|
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLine with tag converts to xLine', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
2024-06-24 22:39:04 -07:00
|
|
|
callToSwap: 'angledLine({ angle: 157, length: 1.69 }, %, $abc3)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
2024-06-24 22:39:04 -07:00
|
|
|
const expectedLine = 'xLine(-1.56, %, $abc3)'
|
2024-03-15 17:03:42 -04:00
|
|
|
console.log(newCode)
|
2023-02-21 10:50:45 +11:00
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLine w/o tag converts to xLine', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
|
|
|
callToSwap: 'angledLine([63, 1.38], %)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
const expectedLine = 'xLine(0.63, %) // angledLine'
|
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLineOfXLength with tag converts to xLine', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
2024-06-24 22:39:04 -07:00
|
|
|
callToSwap: 'angledLineOfXLength({ angle: 217, length: 0.86 }, %, $abc4)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
2024-06-24 22:39:04 -07:00
|
|
|
const expectedLine = 'xLine(-0.86, %, $abc4)'
|
2023-11-01 17:34:54 -05:00
|
|
|
// hmm "-0.86" is correct since the angle is 104, but need to make sure this is compatible `-myVar`
|
2023-02-21 10:50:45 +11:00
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLineOfXLength w/o tag converts to xLine', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
|
|
|
callToSwap: 'angledLineOfXLength([319, 1.15], %)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
const expectedLine = 'xLine(1.15, %) // angledLineOfXLength'
|
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLineOfYLength with tag converts to yLine', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
2024-06-24 22:39:04 -07:00
|
|
|
callToSwap: 'angledLineOfYLength({ angle: 104, length: 1.58 }, %, $abc5)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'vertical',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
2024-06-24 22:39:04 -07:00
|
|
|
const expectedLine = 'yLine(1.58, %, $abc5)'
|
2023-02-21 10:50:45 +11:00
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLineOfYLength w/o tag converts to yLine', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
|
|
|
callToSwap: 'angledLineOfYLength([50, 1.35], %)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'vertical',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
const expectedLine = 'yLine(1.35, %) // angledLineOfYLength'
|
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLineToX with tag converts to xLineTo', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
2024-06-24 22:39:04 -07:00
|
|
|
callToSwap: 'angledLineToX({ angle: 55, to: -2.89 }, %, $abc6)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
2024-06-24 22:39:04 -07:00
|
|
|
const expectedLine = 'xLineTo(-2.89, %, $abc6)'
|
2023-02-21 10:50:45 +11:00
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLineToX w/o tag converts to xLineTo', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
|
|
|
callToSwap: 'angledLineToX([291, 6.66], %)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
const expectedLine = 'xLineTo(6.66, %) // angledLineToX'
|
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLineToY with tag converts to yLineTo', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
2024-06-24 22:39:04 -07:00
|
|
|
callToSwap: 'angledLineToY({ angle: 330, to: 2.53 }, %, $abc7)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'vertical',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
2024-06-24 22:39:04 -07:00
|
|
|
const expectedLine = 'yLineTo(2.53, %, $abc7)'
|
2023-02-21 10:50:45 +11:00
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLineToY w/o tag converts to yLineTo', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: bigExample,
|
|
|
|
callToSwap: 'angledLineToY([228, 2.14], %)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'vertical',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
const expectedLine = 'yLineTo(2.14, %) // angledLineToY'
|
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2023-11-01 17:34:54 -05:00
|
|
|
describe('testing swapping out sketch calls with xLine/xLineTo while keeping variable/identifiers intact', () => {
|
2023-07-10 15:15:07 +10:00
|
|
|
// Enable rotations #152
|
2023-02-21 10:50:45 +11:00
|
|
|
const variablesExampleArr = [
|
|
|
|
`const lineX = -1`,
|
|
|
|
`const lineToX = -1.3`,
|
|
|
|
`const angledLineAngle = 207`,
|
|
|
|
`const angledLineOfXLengthX = 0.8`,
|
|
|
|
`const angledLineOfYLengthY = 0.89`,
|
|
|
|
`const angledLineToXx = -1.86`,
|
|
|
|
`const angledLineToYy = -0.76`,
|
2023-10-05 14:27:48 -07:00
|
|
|
`const part001 = startSketchOn('XY')`,
|
|
|
|
` |> startProfileAt([0, 0], %)`,
|
2023-07-10 15:15:07 +10:00
|
|
|
// ` |> rx(90, %)`,
|
2023-02-21 10:50:45 +11:00
|
|
|
` |> lineTo([1, 1], %)`,
|
|
|
|
` |> line([lineX, 2.13], %)`,
|
|
|
|
` |> lineTo([lineToX, 2.85], %)`,
|
|
|
|
` |> angledLine([angledLineAngle, 1.64], %)`,
|
|
|
|
` |> angledLineOfXLength([329, angledLineOfXLengthX], %)`,
|
|
|
|
` |> angledLineOfYLength([222, angledLineOfYLengthY], %)`,
|
|
|
|
` |> angledLineToX([330, angledLineToXx], %)`,
|
|
|
|
` |> angledLineToY([217, angledLineToYy], %)`,
|
|
|
|
` |> line([0.89, -0.1], %)`,
|
|
|
|
]
|
|
|
|
const varExample = variablesExampleArr.join('\n')
|
2023-06-22 16:43:33 +10:00
|
|
|
it('line keeps variable when converted to xLine', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: varExample,
|
|
|
|
callToSwap: 'line([lineX, 2.13], %)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
const expectedLine = 'xLine(lineX, %)'
|
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('lineTo keeps variable when converted to xLineTo', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: varExample,
|
|
|
|
callToSwap: 'lineTo([lineToX, 2.85], %)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
const expectedLine = 'xLineTo(lineToX, %)'
|
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLineOfXLength keeps variable when converted to xLine', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: varExample,
|
|
|
|
callToSwap: 'angledLineOfXLength([329, angledLineOfXLengthX], %)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
const expectedLine = 'xLine(angledLineOfXLengthX, %)'
|
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLineOfYLength keeps variable when converted to yLine', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: varExample,
|
|
|
|
callToSwap: 'angledLineOfYLength([222, angledLineOfYLengthY], %)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'vertical',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
2023-03-02 21:19:11 +11:00
|
|
|
const expectedLine = 'yLine(-angledLineOfYLengthY, %)'
|
2023-02-21 10:50:45 +11:00
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLineToX keeps variable when converted to xLineTo', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: varExample,
|
|
|
|
callToSwap: 'angledLineToX([330, angledLineToXx], %)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
const expectedLine = 'xLineTo(angledLineToXx, %)'
|
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('angledLineToY keeps variable when converted to yLineTo', async () => {
|
|
|
|
const { newCode, originalRange } = await testingSwapSketchFnCall({
|
2023-02-21 10:50:45 +11:00
|
|
|
inputCode: varExample,
|
|
|
|
callToSwap: 'angledLineToY([217, angledLineToYy], %)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'vertical',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
const expectedLine = 'yLineTo(angledLineToYy, %)'
|
|
|
|
expect(newCode).toContain(expectedLine)
|
|
|
|
// new line should start at the same place as the old line
|
|
|
|
expect(originalRange[0]).toBe(newCode.indexOf(expectedLine))
|
|
|
|
})
|
|
|
|
|
2023-06-22 16:43:33 +10:00
|
|
|
it('trying to convert angledLineToY to xLineTo should not work because of the variable', async () => {
|
2023-02-21 10:50:45 +11:00
|
|
|
const illegalConvert = () =>
|
|
|
|
testingSwapSketchFnCall({
|
|
|
|
inputCode: varExample,
|
|
|
|
callToSwap: 'angledLineToY([217, angledLineToYy], %)',
|
2023-03-02 21:19:11 +11:00
|
|
|
constraintType: 'horizontal',
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
await expect(illegalConvert).rejects.toThrowError('no callback helper')
|
2023-02-21 10:50:45 +11:00
|
|
|
})
|
|
|
|
})
|
2023-03-20 07:09:19 +11:00
|
|
|
|
|
|
|
describe('testing getSketchSegmentIndexFromSourceRange', () => {
|
|
|
|
const code = `
|
2023-10-05 14:27:48 -07:00
|
|
|
const part001 = startSketchOn('XY')
|
|
|
|
|> startProfileAt([0, 0.04], %) // segment-in-start
|
2023-03-20 07:09:19 +11:00
|
|
|
|> line([0, 0.4], %)
|
|
|
|
|> xLine(3.48, %)
|
|
|
|
|> line([2.14, 1.35], %) // normal-segment
|
2024-03-01 17:16:18 -08:00
|
|
|
|> xLine(3.54, %)`
|
2023-06-22 16:43:33 +10:00
|
|
|
it('normal case works', async () => {
|
2023-09-29 11:11:01 -07:00
|
|
|
const programMemory = await enginelessExecutor(parse(code))
|
2023-03-20 07:09:19 +11:00
|
|
|
const index = code.indexOf('// normal-segment') - 7
|
Remove KclValue::SketchGroup variant (#3446)
We can store Rust types like `SketchGroup` as their own variant of `KclValue`, or as `KclValue::UserVal`. Sometimes we store in one and try to read from the other, which fails. This causes bugs, like #3338.
Instead, we should use either ::SketchGroup or ::UserVal, and stop using the other. If we stopped using ::UserVal, we'd need a new variant for every Rust type we wanted to build, including user-defined types. So I don't think that's practical.
Instead, we should store every KCL value by de/serializing it into UserVal. This is a first step along that path, removing just the SketchGroup variants. If it goes well, we can remove the other specialized variants too.
My only concern is there might be performance implications from how frequently we convert between serde_json::Value and Rust types via Serde. But I'm not too worried -- there's no parsing JSON strings, just traversing serde_json::Value trees. This isn't great for performance but I think it'll probably be miniscule in comparison to doing all the API calls.
2024-08-21 11:06:48 -05:00
|
|
|
const sg = sketchGroupFromKclValue(
|
|
|
|
programMemory.get('part001'),
|
|
|
|
'part001'
|
|
|
|
) as SketchGroup
|
|
|
|
const _segment = getSketchSegmentFromSourceRange(sg, [index, index])
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(_segment)) throw _segment
|
|
|
|
const { __geoMeta, ...segment } = _segment.segment
|
2023-03-20 07:09:19 +11:00
|
|
|
expect(segment).toEqual({
|
2024-02-11 12:59:00 +11:00
|
|
|
type: 'ToPoint',
|
2023-03-20 07:09:19 +11:00
|
|
|
to: [5.62, 1.79],
|
|
|
|
from: [3.48, 0.44],
|
2024-06-24 14:45:07 -07:00
|
|
|
tag: null,
|
2023-03-20 07:09:19 +11:00
|
|
|
})
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('verify it works when the segment is in the `start` property', async () => {
|
2023-09-29 11:11:01 -07:00
|
|
|
const programMemory = await enginelessExecutor(parse(code))
|
2023-03-20 07:09:19 +11:00
|
|
|
const index = code.indexOf('// segment-in-start') - 7
|
2024-06-24 11:45:40 -04:00
|
|
|
const _segment = getSketchSegmentFromSourceRange(
|
Remove KclValue::SketchGroup variant (#3446)
We can store Rust types like `SketchGroup` as their own variant of `KclValue`, or as `KclValue::UserVal`. Sometimes we store in one and try to read from the other, which fails. This causes bugs, like #3338.
Instead, we should use either ::SketchGroup or ::UserVal, and stop using the other. If we stopped using ::UserVal, we'd need a new variant for every Rust type we wanted to build, including user-defined types. So I don't think that's practical.
Instead, we should store every KCL value by de/serializing it into UserVal. This is a first step along that path, removing just the SketchGroup variants. If it goes well, we can remove the other specialized variants too.
My only concern is there might be performance implications from how frequently we convert between serde_json::Value and Rust types via Serde. But I'm not too worried -- there's no parsing JSON strings, just traversing serde_json::Value trees. This isn't great for performance but I think it'll probably be miniscule in comparison to doing all the API calls.
2024-08-21 11:06:48 -05:00
|
|
|
sketchGroupFromKclValue(
|
|
|
|
programMemory.get('part001'),
|
|
|
|
'part001'
|
|
|
|
) as SketchGroup,
|
2023-03-20 07:09:19 +11:00
|
|
|
[index, index]
|
2024-06-24 11:45:40 -04:00
|
|
|
)
|
|
|
|
if (err(_segment)) throw _segment
|
|
|
|
const { __geoMeta, ...segment } = _segment.segment
|
2023-09-12 18:10:27 -07:00
|
|
|
expect(segment).toEqual({
|
|
|
|
to: [0, 0.04],
|
|
|
|
from: [0, 0.04],
|
2024-06-24 14:45:07 -07:00
|
|
|
tag: null,
|
2024-02-11 12:59:00 +11:00
|
|
|
type: 'Base',
|
2023-09-12 18:10:27 -07:00
|
|
|
})
|
2023-03-20 07:09:19 +11:00
|
|
|
})
|
|
|
|
})
|