2024-02-23 11:24:22 -05:00
|
|
|
import { parse, recast, initPromise, Identifier } from './wasm'
|
2023-02-12 10:56:45 +11:00
|
|
|
import {
|
|
|
|
createLiteral,
|
|
|
|
createIdentifier,
|
|
|
|
createCallExpression,
|
|
|
|
createObjectExpression,
|
|
|
|
createArrayExpression,
|
|
|
|
createPipeSubstitution,
|
|
|
|
createVariableDeclaration,
|
|
|
|
createPipeExpression,
|
|
|
|
findUniqueName,
|
|
|
|
addSketchTo,
|
2023-03-02 21:19:11 +11:00
|
|
|
giveSketchFnCallTag,
|
2023-04-01 16:47:00 +11:00
|
|
|
moveValueIntoNewVariable,
|
2024-03-22 10:23:04 +11:00
|
|
|
sketchOnExtrudedFace,
|
2024-05-24 20:54:42 +10:00
|
|
|
deleteSegmentFromPipeExpression,
|
|
|
|
removeSingleConstraintInfo,
|
2024-06-29 10:36:04 -07:00
|
|
|
deleteFromSelection,
|
2023-02-12 10:56:45 +11:00
|
|
|
} from './modifyAst'
|
2023-07-10 15:15:07 +10:00
|
|
|
import { enginelessExecutor } from '../lib/testHelpers'
|
2024-05-24 20:54:42 +10:00
|
|
|
import { findUsesOfTagInPipe, getNodePathFromSourceRange } from './queryAst'
|
2024-06-24 11:45:40 -04:00
|
|
|
import { err } from 'lib/trap'
|
2024-09-13 21:14:14 +10:00
|
|
|
import { SimplifiedArgDetails } from './std/stdTypes'
|
2024-10-30 16:52:17 -04:00
|
|
|
import { Node } from 'wasm-lib/kcl/bindings/Node'
|
2023-03-02 21:19:11 +11:00
|
|
|
|
2024-04-19 14:24:40 -07:00
|
|
|
beforeAll(async () => {
|
|
|
|
await initPromise
|
|
|
|
})
|
2023-02-12 10:56:45 +11:00
|
|
|
|
|
|
|
describe('Testing createLiteral', () => {
|
|
|
|
it('should create a literal', () => {
|
|
|
|
const result = createLiteral(5)
|
|
|
|
expect(result.type).toBe('Literal')
|
|
|
|
expect(result.value).toBe(5)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
describe('Testing createIdentifier', () => {
|
|
|
|
it('should create an identifier', () => {
|
|
|
|
const result = createIdentifier('myVar')
|
|
|
|
expect(result.type).toBe('Identifier')
|
|
|
|
expect(result.name).toBe('myVar')
|
|
|
|
})
|
|
|
|
})
|
|
|
|
describe('Testing createCallExpression', () => {
|
|
|
|
it('should create a call expression', () => {
|
|
|
|
const result = createCallExpression('myFunc', [createLiteral(5)])
|
|
|
|
expect(result.type).toBe('CallExpression')
|
|
|
|
expect(result.callee.type).toBe('Identifier')
|
|
|
|
expect(result.callee.name).toBe('myFunc')
|
|
|
|
expect(result.arguments[0].type).toBe('Literal')
|
|
|
|
expect((result.arguments[0] as any).value).toBe(5)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
describe('Testing createObjectExpression', () => {
|
|
|
|
it('should create an object expression', () => {
|
|
|
|
const result = createObjectExpression({
|
|
|
|
myProp: createLiteral(5),
|
|
|
|
})
|
|
|
|
expect(result.type).toBe('ObjectExpression')
|
|
|
|
expect(result.properties[0].type).toBe('ObjectProperty')
|
|
|
|
expect(result.properties[0].key.name).toBe('myProp')
|
|
|
|
expect(result.properties[0].value.type).toBe('Literal')
|
|
|
|
expect((result.properties[0].value as any).value).toBe(5)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
describe('Testing createArrayExpression', () => {
|
|
|
|
it('should create an array expression', () => {
|
|
|
|
const result = createArrayExpression([createLiteral(5)])
|
|
|
|
expect(result.type).toBe('ArrayExpression')
|
|
|
|
expect(result.elements[0].type).toBe('Literal')
|
|
|
|
expect((result.elements[0] as any).value).toBe(5)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
describe('Testing createPipeSubstitution', () => {
|
|
|
|
it('should create a pipe substitution', () => {
|
|
|
|
const result = createPipeSubstitution()
|
|
|
|
expect(result.type).toBe('PipeSubstitution')
|
|
|
|
})
|
|
|
|
})
|
|
|
|
describe('Testing createVariableDeclaration', () => {
|
|
|
|
it('should create a variable declaration', () => {
|
|
|
|
const result = createVariableDeclaration('myVar', createLiteral(5))
|
|
|
|
expect(result.type).toBe('VariableDeclaration')
|
|
|
|
expect(result.declarations[0].type).toBe('VariableDeclarator')
|
|
|
|
expect(result.declarations[0].id.type).toBe('Identifier')
|
|
|
|
expect(result.declarations[0].id.name).toBe('myVar')
|
|
|
|
expect(result.declarations[0].init.type).toBe('Literal')
|
|
|
|
expect((result.declarations[0].init as any).value).toBe(5)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
describe('Testing createPipeExpression', () => {
|
|
|
|
it('should create a pipe expression', () => {
|
|
|
|
const result = createPipeExpression([createLiteral(5)])
|
|
|
|
expect(result.type).toBe('PipeExpression')
|
|
|
|
expect(result.body[0].type).toBe('Literal')
|
|
|
|
expect((result.body[0] as any).value).toBe(5)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('Testing findUniqueName', () => {
|
|
|
|
it('should find a unique name', () => {
|
|
|
|
const result = findUniqueName(
|
2024-02-23 11:24:22 -05:00
|
|
|
JSON.stringify([
|
2024-11-07 11:23:41 -05:00
|
|
|
{ type: 'Identifier', name: 'yo01', start: 0, end: 0, moduleId: 0 },
|
|
|
|
{ type: 'Identifier', name: 'yo02', start: 0, end: 0, moduleId: 0 },
|
|
|
|
{ type: 'Identifier', name: 'yo03', start: 0, end: 0, moduleId: 0 },
|
|
|
|
{ type: 'Identifier', name: 'yo04', start: 0, end: 0, moduleId: 0 },
|
|
|
|
{ type: 'Identifier', name: 'yo05', start: 0, end: 0, moduleId: 0 },
|
|
|
|
{ type: 'Identifier', name: 'yo06', start: 0, end: 0, moduleId: 0 },
|
|
|
|
{ type: 'Identifier', name: 'yo07', start: 0, end: 0, moduleId: 0 },
|
|
|
|
{ type: 'Identifier', name: 'yo08', start: 0, end: 0, moduleId: 0 },
|
|
|
|
{ type: 'Identifier', name: 'yo09', start: 0, end: 0, moduleId: 0 },
|
2024-10-30 16:52:17 -04:00
|
|
|
] satisfies Node<Identifier>[]),
|
2023-02-12 10:56:45 +11:00
|
|
|
'yo',
|
|
|
|
2
|
|
|
|
)
|
|
|
|
expect(result).toBe('yo10')
|
|
|
|
})
|
|
|
|
})
|
|
|
|
describe('Testing addSketchTo', () => {
|
|
|
|
it('should add a sketch to a program', () => {
|
|
|
|
const result = addSketchTo(
|
|
|
|
{
|
|
|
|
body: [],
|
|
|
|
start: 0,
|
|
|
|
end: 0,
|
2024-11-07 11:23:41 -05:00
|
|
|
moduleId: 0,
|
2024-10-30 16:52:17 -04:00
|
|
|
nonCodeMeta: { nonCodeNodes: {}, startNodes: [] },
|
2023-02-12 10:56:45 +11:00
|
|
|
},
|
|
|
|
'yz'
|
|
|
|
)
|
|
|
|
const str = recast(result.modifiedAst)
|
2024-10-02 14:19:40 -05:00
|
|
|
expect(str).toBe(`sketch001 = startSketchOn('YZ')
|
2023-10-05 14:27:48 -07:00
|
|
|
|> startProfileAt('default', %)
|
2023-03-17 15:53:20 +11:00
|
|
|
|> line('default', %)
|
2023-09-11 17:14:41 -07:00
|
|
|
`)
|
2023-02-12 10:56:45 +11:00
|
|
|
})
|
|
|
|
})
|
2023-03-02 21:19:11 +11:00
|
|
|
|
|
|
|
function giveSketchFnCallTagTestHelper(
|
|
|
|
code: string,
|
|
|
|
searchStr: string
|
2023-03-07 15:45:59 +11:00
|
|
|
): { tag: string; newCode: string; isTagExisting: boolean } {
|
2023-03-02 21:19:11 +11:00
|
|
|
// giveSketchFnCallTag inputs and outputs an ast, which is very verbose for testing
|
|
|
|
// this wrapper changes the input and output to code
|
|
|
|
// making it more of an integration test, but easier to read the test intention is the goal
|
2023-09-29 11:11:01 -07:00
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
2023-03-02 21:19:11 +11:00
|
|
|
const start = code.indexOf(searchStr)
|
|
|
|
const range: [number, number] = [start, start + searchStr.length]
|
2024-06-24 11:45:40 -04:00
|
|
|
const sketchRes = giveSketchFnCallTag(ast, range)
|
|
|
|
if (err(sketchRes)) throw sketchRes
|
|
|
|
const { modifiedAst, tag, isTagExisting } = sketchRes
|
2023-03-02 21:19:11 +11:00
|
|
|
const newCode = recast(modifiedAst)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(newCode)) throw newCode
|
2023-03-07 15:45:59 +11:00
|
|
|
return { tag, newCode, isTagExisting }
|
2023-03-02 21:19:11 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
describe('Testing giveSketchFnCallTag', () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const code = `part001 = startSketchOn('XY')
|
2023-10-05 14:27:48 -07:00
|
|
|
|> startProfileAt([0, 0], %)
|
2023-03-02 21:19:11 +11:00
|
|
|
|> line([-2.57, -0.13], %)
|
|
|
|
|> line([0, 0.83], %)
|
2024-03-01 17:16:18 -08:00
|
|
|
|> line([0.82, 0.34], %)`
|
2023-03-02 21:19:11 +11:00
|
|
|
it('Should add tag to a sketch function call', () => {
|
2023-03-07 15:45:59 +11:00
|
|
|
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
|
2023-03-02 21:19:11 +11:00
|
|
|
code,
|
|
|
|
'line([0, 0.83], %)'
|
|
|
|
)
|
2024-06-24 22:39:04 -07:00
|
|
|
expect(newCode).toContain('line([0, 0.83], %, $seg01)')
|
2023-03-02 21:19:11 +11:00
|
|
|
expect(tag).toBe('seg01')
|
2023-03-07 15:45:59 +11:00
|
|
|
expect(isTagExisting).toBe(false)
|
2023-03-02 21:19:11 +11:00
|
|
|
})
|
|
|
|
it('Should create a unique tag if seg01 already exists', () => {
|
|
|
|
let _code = code.replace(
|
|
|
|
'line([-2.57, -0.13], %)',
|
2024-06-24 22:39:04 -07:00
|
|
|
'line([-2.57, -0.13], %, $seg01)'
|
2023-03-02 21:19:11 +11:00
|
|
|
)
|
2023-03-07 15:45:59 +11:00
|
|
|
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
|
2023-03-02 21:19:11 +11:00
|
|
|
_code,
|
|
|
|
'line([0, 0.83], %)'
|
|
|
|
)
|
2024-06-24 22:39:04 -07:00
|
|
|
expect(newCode).toContain('line([0, 0.83], %, $seg02)')
|
2023-03-02 21:19:11 +11:00
|
|
|
expect(tag).toBe('seg02')
|
2023-03-07 15:45:59 +11:00
|
|
|
expect(isTagExisting).toBe(false)
|
2023-03-02 21:19:11 +11:00
|
|
|
})
|
|
|
|
it('Should return existing tag if it already exists', () => {
|
2024-06-24 22:39:04 -07:00
|
|
|
const lineButWithTag = 'line([-2.57, -0.13], %, $butts)'
|
2023-03-02 21:19:11 +11:00
|
|
|
let _code = code.replace('line([-2.57, -0.13], %)', lineButWithTag)
|
2023-03-07 15:45:59 +11:00
|
|
|
const { newCode, tag, isTagExisting } = giveSketchFnCallTagTestHelper(
|
2023-03-02 21:19:11 +11:00
|
|
|
_code,
|
|
|
|
lineButWithTag
|
|
|
|
)
|
|
|
|
expect(newCode).toContain(lineButWithTag) // no change
|
|
|
|
expect(tag).toBe('butts')
|
2023-03-07 15:45:59 +11:00
|
|
|
expect(isTagExisting).toBe(true)
|
2023-03-02 21:19:11 +11:00
|
|
|
})
|
|
|
|
})
|
2023-04-01 16:47:00 +11:00
|
|
|
|
|
|
|
describe('Testing moveValueIntoNewVariable', () => {
|
2023-09-13 11:42:09 -07:00
|
|
|
const fn = (fnName: string) => `fn ${fnName} = (x) => {
|
2023-04-01 16:47:00 +11:00
|
|
|
return x
|
|
|
|
}
|
|
|
|
`
|
2023-09-11 15:15:37 -07:00
|
|
|
const code = `${fn('def')}${fn('jkl')}${fn('hmm')}
|
|
|
|
fn ghi = (x) => {
|
|
|
|
return 2
|
|
|
|
}
|
2023-04-01 16:47:00 +11:00
|
|
|
const abc = 3
|
|
|
|
const identifierGuy = 5
|
2024-10-02 14:19:40 -05:00
|
|
|
yo = 5 + 6
|
|
|
|
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], %)
|
2023-08-24 15:34:51 -07:00
|
|
|
|> angledLine([def(yo), 3.09], %)
|
2023-04-01 16:47:00 +11:00
|
|
|
|> angledLine([ghi(%), 3.09], %)
|
2023-08-24 15:34:51 -07:00
|
|
|
|> angledLine([jkl(yo) + 2, 3.09], %)
|
2024-10-02 14:19:40 -05:00
|
|
|
yo2 = hmm([identifierGuy + 5])`
|
2023-07-20 19:25:04 -04:00
|
|
|
it('should move a binary expression into a new variable', async () => {
|
2023-09-29 11:11:01 -07:00
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2023-04-01 16:47:00 +11:00
|
|
|
const startIndex = code.indexOf('100 + 100') + 1
|
|
|
|
const { modifiedAst } = moveValueIntoNewVariable(
|
|
|
|
ast,
|
2024-10-09 19:38:40 -04:00
|
|
|
execState.memory,
|
2023-04-01 16:47:00 +11:00
|
|
|
[startIndex, startIndex],
|
|
|
|
'newVar'
|
|
|
|
)
|
|
|
|
const newCode = recast(modifiedAst)
|
2024-10-02 14:19:40 -05:00
|
|
|
expect(newCode).toContain(`newVar = 100 + 100`)
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
|
|
|
|
})
|
2023-06-22 16:43:33 +10:00
|
|
|
it('should move a value into a new variable', async () => {
|
2023-09-29 11:11:01 -07:00
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2023-04-01 16:47:00 +11:00
|
|
|
const startIndex = code.indexOf('2.8') + 1
|
|
|
|
const { modifiedAst } = moveValueIntoNewVariable(
|
|
|
|
ast,
|
2024-10-09 19:38:40 -04:00
|
|
|
execState.memory,
|
2023-04-01 16:47:00 +11:00
|
|
|
[startIndex, startIndex],
|
|
|
|
'newVar'
|
|
|
|
)
|
|
|
|
const newCode = recast(modifiedAst)
|
2024-10-02 14:19:40 -05:00
|
|
|
expect(newCode).toContain(`newVar = 2.8`)
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(newCode).toContain(`line([newVar, 0], %)`)
|
|
|
|
})
|
2023-07-20 19:25:04 -04:00
|
|
|
it('should move a callExpression into a new variable', async () => {
|
2023-09-29 11:11:01 -07:00
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2023-04-01 16:47:00 +11:00
|
|
|
const startIndex = code.indexOf('def(')
|
|
|
|
const { modifiedAst } = moveValueIntoNewVariable(
|
|
|
|
ast,
|
2024-10-09 19:38:40 -04:00
|
|
|
execState.memory,
|
2023-04-01 16:47:00 +11:00
|
|
|
[startIndex, startIndex],
|
|
|
|
'newVar'
|
|
|
|
)
|
|
|
|
const newCode = recast(modifiedAst)
|
2024-10-02 14:19:40 -05:00
|
|
|
expect(newCode).toContain(`newVar = def(yo)`)
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
|
|
|
|
})
|
2023-07-20 19:25:04 -04:00
|
|
|
it('should move a binary expression with call expression into a new variable', async () => {
|
2023-09-29 11:11:01 -07:00
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2023-04-01 16:47:00 +11:00
|
|
|
const startIndex = code.indexOf('jkl(') + 1
|
|
|
|
const { modifiedAst } = moveValueIntoNewVariable(
|
|
|
|
ast,
|
2024-10-09 19:38:40 -04:00
|
|
|
execState.memory,
|
2023-04-01 16:47:00 +11:00
|
|
|
[startIndex, startIndex],
|
|
|
|
'newVar'
|
|
|
|
)
|
|
|
|
const newCode = recast(modifiedAst)
|
2024-10-02 14:19:40 -05:00
|
|
|
expect(newCode).toContain(`newVar = jkl(yo) + 2`)
|
2023-04-01 16:47:00 +11:00
|
|
|
expect(newCode).toContain(`angledLine([newVar, 3.09], %)`)
|
|
|
|
})
|
2023-07-20 19:25:04 -04:00
|
|
|
it('should move a identifier into a new variable', async () => {
|
2023-09-29 11:11:01 -07:00
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2023-04-01 16:47:00 +11:00
|
|
|
const startIndex = code.indexOf('identifierGuy +') + 1
|
|
|
|
const { modifiedAst } = moveValueIntoNewVariable(
|
|
|
|
ast,
|
2024-10-09 19:38:40 -04:00
|
|
|
execState.memory,
|
2023-04-01 16:47:00 +11:00
|
|
|
[startIndex, startIndex],
|
|
|
|
'newVar'
|
|
|
|
)
|
|
|
|
const newCode = recast(modifiedAst)
|
2024-10-02 14:19:40 -05:00
|
|
|
expect(newCode).toContain(`newVar = identifierGuy + 5`)
|
|
|
|
expect(newCode).toContain(`yo2 = hmm([newVar])`)
|
2023-04-01 16:47:00 +11:00
|
|
|
})
|
|
|
|
})
|
2024-03-22 10:23:04 +11:00
|
|
|
|
|
|
|
describe('testing sketchOnExtrudedFace', () => {
|
|
|
|
test('it should be able to extrude on regular segments', async () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const code = `part001 = startSketchOn('-XZ')
|
2024-03-22 10:23:04 +11:00
|
|
|
|> startProfileAt([3.58, 2.06], %)
|
|
|
|
|> line([9.7, 9.19], %)
|
|
|
|
|> line([8.62, -9.57], %)
|
|
|
|
|> close(%)
|
|
|
|
|> extrude(5 + 7, %)`
|
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
|
|
|
|
2024-06-04 13:57:01 -04:00
|
|
|
const segmentSnippet = `line([9.7, 9.19], %)`
|
|
|
|
const segmentRange: [number, number] = [
|
|
|
|
code.indexOf(segmentSnippet),
|
|
|
|
code.indexOf(segmentSnippet) + segmentSnippet.length,
|
|
|
|
]
|
|
|
|
const segmentPathToNode = getNodePathFromSourceRange(ast, segmentRange)
|
|
|
|
const extrudeSnippet = `extrude(5 + 7, %)`
|
|
|
|
const extrudeRange: [number, number] = [
|
|
|
|
code.indexOf(extrudeSnippet),
|
|
|
|
code.indexOf(extrudeSnippet) + extrudeSnippet.length,
|
2024-03-22 10:23:04 +11:00
|
|
|
]
|
2024-06-04 13:57:01 -04:00
|
|
|
const extrudePathToNode = getNodePathFromSourceRange(ast, extrudeRange)
|
2024-03-22 10:23:04 +11:00
|
|
|
|
2024-06-24 11:45:40 -04:00
|
|
|
const extruded = sketchOnExtrudedFace(
|
2024-06-04 13:57:01 -04:00
|
|
|
ast,
|
|
|
|
segmentPathToNode,
|
2024-07-15 19:20:32 +10:00
|
|
|
extrudePathToNode
|
2024-06-04 13:57:01 -04:00
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(extruded)) throw extruded
|
|
|
|
const { modifiedAst } = extruded
|
|
|
|
|
2024-03-22 10:23:04 +11:00
|
|
|
const newCode = recast(modifiedAst)
|
2024-10-02 14:19:40 -05:00
|
|
|
expect(newCode).toContain(`part001 = startSketchOn('-XZ')
|
2024-03-22 10:23:04 +11:00
|
|
|
|> startProfileAt([3.58, 2.06], %)
|
2024-06-24 22:39:04 -07:00
|
|
|
|> line([9.7, 9.19], %, $seg01)
|
2024-03-22 10:23:04 +11:00
|
|
|
|> line([8.62, -9.57], %)
|
|
|
|
|> close(%)
|
|
|
|
|> extrude(5 + 7, %)
|
2024-10-02 14:19:40 -05:00
|
|
|
sketch001 = startSketchOn(part001, seg01)`)
|
2024-03-22 10:23:04 +11:00
|
|
|
})
|
|
|
|
test('it should be able to extrude on close segments', async () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const code = `part001 = startSketchOn('-XZ')
|
2024-03-22 10:23:04 +11:00
|
|
|
|> startProfileAt([3.58, 2.06], %)
|
|
|
|
|> line([9.7, 9.19], %)
|
|
|
|
|> line([8.62, -9.57], %)
|
|
|
|
|> close(%)
|
|
|
|
|> extrude(5 + 7, %)`
|
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
2024-06-04 13:57:01 -04:00
|
|
|
const segmentSnippet = `close(%)`
|
|
|
|
const segmentRange: [number, number] = [
|
|
|
|
code.indexOf(segmentSnippet),
|
|
|
|
code.indexOf(segmentSnippet) + segmentSnippet.length,
|
2024-03-22 10:23:04 +11:00
|
|
|
]
|
2024-06-04 13:57:01 -04:00
|
|
|
const segmentPathToNode = getNodePathFromSourceRange(ast, segmentRange)
|
|
|
|
const extrudeSnippet = `extrude(5 + 7, %)`
|
|
|
|
const extrudeRange: [number, number] = [
|
|
|
|
code.indexOf(extrudeSnippet),
|
|
|
|
code.indexOf(extrudeSnippet) + extrudeSnippet.length,
|
|
|
|
]
|
|
|
|
const extrudePathToNode = getNodePathFromSourceRange(ast, extrudeRange)
|
2024-03-22 10:23:04 +11:00
|
|
|
|
2024-06-24 11:45:40 -04:00
|
|
|
const extruded = sketchOnExtrudedFace(
|
2024-06-04 13:57:01 -04:00
|
|
|
ast,
|
|
|
|
segmentPathToNode,
|
2024-07-15 19:20:32 +10:00
|
|
|
extrudePathToNode
|
2024-06-04 13:57:01 -04:00
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(extruded)) throw extruded
|
|
|
|
const { modifiedAst } = extruded
|
|
|
|
|
2024-03-22 10:23:04 +11:00
|
|
|
const newCode = recast(modifiedAst)
|
2024-10-02 14:19:40 -05:00
|
|
|
expect(newCode).toContain(`part001 = startSketchOn('-XZ')
|
2024-03-22 10:23:04 +11:00
|
|
|
|> startProfileAt([3.58, 2.06], %)
|
|
|
|
|> line([9.7, 9.19], %)
|
|
|
|
|> line([8.62, -9.57], %)
|
2024-06-24 22:39:04 -07:00
|
|
|
|> close(%, $seg01)
|
2024-03-22 10:23:04 +11:00
|
|
|
|> extrude(5 + 7, %)
|
2024-10-02 14:19:40 -05:00
|
|
|
sketch001 = startSketchOn(part001, seg01)`)
|
2024-03-22 10:23:04 +11:00
|
|
|
})
|
|
|
|
test('it should be able to extrude on start-end caps', async () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const code = `part001 = startSketchOn('-XZ')
|
2024-03-22 10:23:04 +11:00
|
|
|
|> startProfileAt([3.58, 2.06], %)
|
|
|
|
|> line([9.7, 9.19], %)
|
|
|
|
|> line([8.62, -9.57], %)
|
|
|
|
|> close(%)
|
|
|
|
|> extrude(5 + 7, %)`
|
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
2024-06-04 13:57:01 -04:00
|
|
|
const sketchSnippet = `startProfileAt([3.58, 2.06], %)`
|
|
|
|
const sketchRange: [number, number] = [
|
|
|
|
code.indexOf(sketchSnippet),
|
|
|
|
code.indexOf(sketchSnippet) + sketchSnippet.length,
|
2024-03-22 10:23:04 +11:00
|
|
|
]
|
2024-06-04 13:57:01 -04:00
|
|
|
const sketchPathToNode = getNodePathFromSourceRange(ast, sketchRange)
|
|
|
|
const extrudeSnippet = `extrude(5 + 7, %)`
|
|
|
|
const extrudeRange: [number, number] = [
|
|
|
|
code.indexOf(extrudeSnippet),
|
|
|
|
code.indexOf(extrudeSnippet) + extrudeSnippet.length,
|
|
|
|
]
|
|
|
|
const extrudePathToNode = getNodePathFromSourceRange(ast, extrudeRange)
|
2024-03-22 10:23:04 +11:00
|
|
|
|
2024-06-24 11:45:40 -04:00
|
|
|
const extruded = sketchOnExtrudedFace(
|
2024-03-22 10:23:04 +11:00
|
|
|
ast,
|
2024-06-04 13:57:01 -04:00
|
|
|
sketchPathToNode,
|
|
|
|
extrudePathToNode,
|
2024-09-26 18:25:05 +10:00
|
|
|
{ type: 'cap', subType: 'end' }
|
2024-03-22 10:23:04 +11:00
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(extruded)) throw extruded
|
|
|
|
const { modifiedAst } = extruded
|
|
|
|
|
2024-03-22 10:23:04 +11:00
|
|
|
const newCode = recast(modifiedAst)
|
2024-10-02 14:19:40 -05:00
|
|
|
expect(newCode).toContain(`part001 = startSketchOn('-XZ')
|
2024-03-22 10:23:04 +11:00
|
|
|
|> startProfileAt([3.58, 2.06], %)
|
|
|
|
|> line([9.7, 9.19], %)
|
|
|
|
|> line([8.62, -9.57], %)
|
|
|
|
|> close(%)
|
|
|
|
|> extrude(5 + 7, %)
|
2024-10-02 14:19:40 -05:00
|
|
|
sketch001 = startSketchOn(part001, 'END')`)
|
2024-06-04 13:57:01 -04:00
|
|
|
})
|
|
|
|
test('it should ensure that the new sketch is inserted after the extrude', async () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const code = `sketch001 = startSketchOn('-XZ')
|
2024-06-04 13:57:01 -04:00
|
|
|
|> startProfileAt([3.29, 7.86], %)
|
|
|
|
|> line([2.48, 2.44], %)
|
|
|
|
|> line([2.66, 1.17], %)
|
|
|
|
|> line([3.75, 0.46], %)
|
|
|
|
|> line([4.99, -0.46], %)
|
|
|
|
|> 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
|
|
|
part001 = extrude(5 + 7, sketch001)`
|
2024-06-04 13:57:01 -04:00
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
2024-06-04 13:57:01 -04:00
|
|
|
const segmentSnippet = `line([4.99, -0.46], %)`
|
|
|
|
const segmentRange: [number, number] = [
|
|
|
|
code.indexOf(segmentSnippet),
|
|
|
|
code.indexOf(segmentSnippet) + segmentSnippet.length,
|
|
|
|
]
|
|
|
|
const segmentPathToNode = getNodePathFromSourceRange(ast, segmentRange)
|
|
|
|
const extrudeSnippet = `extrude(5 + 7, sketch001)`
|
|
|
|
const extrudeRange: [number, number] = [
|
|
|
|
code.indexOf(extrudeSnippet),
|
|
|
|
code.indexOf(extrudeSnippet) + extrudeSnippet.length,
|
|
|
|
]
|
|
|
|
const extrudePathToNode = getNodePathFromSourceRange(ast, extrudeRange)
|
|
|
|
|
2024-06-24 11:45:40 -04:00
|
|
|
const updatedAst = sketchOnExtrudedFace(
|
2024-06-04 13:57:01 -04:00
|
|
|
ast,
|
|
|
|
segmentPathToNode,
|
2024-07-15 19:20:32 +10:00
|
|
|
extrudePathToNode
|
2024-06-04 13:57:01 -04:00
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(updatedAst)) throw updatedAst
|
|
|
|
const newCode = recast(updatedAst.modifiedAst)
|
2024-10-02 14:19:40 -05:00
|
|
|
expect(newCode).toContain(`part001 = extrude(5 + 7, sketch001)
|
|
|
|
sketch002 = startSketchOn(part001, seg01)`)
|
2024-03-22 10:23:04 +11:00
|
|
|
})
|
|
|
|
})
|
2024-05-24 20:54:42 +10:00
|
|
|
|
|
|
|
describe('Testing deleteSegmentFromPipeExpression', () => {
|
|
|
|
it('Should delete a segment withOUT any dependent segments', async () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const code = `part001 = startSketchOn('-XZ')
|
2024-05-24 20:54:42 +10:00
|
|
|
|> startProfileAt([54.78, -95.91], %)
|
|
|
|
|> line([306.21, 198.82], %)
|
2024-07-27 17:59:41 -07:00
|
|
|
|> line([306.21, 198.85], %, $a)
|
2024-05-24 20:54:42 +10:00
|
|
|
|> line([306.21, 198.87], %)`
|
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2024-07-27 17:59:41 -07:00
|
|
|
const lineOfInterest = 'line([306.21, 198.85], %, $a)'
|
2024-05-24 20:54:42 +10:00
|
|
|
const range: [number, number] = [
|
|
|
|
code.indexOf(lineOfInterest),
|
|
|
|
code.indexOf(lineOfInterest) + lineOfInterest.length,
|
|
|
|
]
|
|
|
|
const pathToNode = getNodePathFromSourceRange(ast, range)
|
|
|
|
const modifiedAst = deleteSegmentFromPipeExpression(
|
|
|
|
[],
|
|
|
|
ast,
|
2024-10-09 19:38:40 -04:00
|
|
|
execState.memory,
|
2024-05-24 20:54:42 +10:00
|
|
|
code,
|
|
|
|
pathToNode
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(modifiedAst)) throw modifiedAst
|
2024-05-24 20:54:42 +10:00
|
|
|
const newCode = recast(modifiedAst)
|
2024-10-02 14:19:40 -05:00
|
|
|
expect(newCode).toBe(`part001 = startSketchOn('-XZ')
|
2024-05-24 20:54:42 +10:00
|
|
|
|> startProfileAt([54.78, -95.91], %)
|
|
|
|
|> line([306.21, 198.82], %)
|
|
|
|
|> line([306.21, 198.87], %)
|
|
|
|
`)
|
|
|
|
})
|
|
|
|
describe('Should delete a segment WITH any dependent segments, unconstraining the dependent parts', () => {
|
|
|
|
const makeCode = (
|
|
|
|
line: string,
|
|
|
|
replace1 = '',
|
|
|
|
replace2 = ''
|
2024-10-02 14:19:40 -05:00
|
|
|
) => `part001 = startSketchOn('-XZ')
|
2024-05-24 20:54:42 +10:00
|
|
|
|> startProfileAt([54.78, -95.91], %)
|
2024-06-24 22:39:04 -07:00
|
|
|
|> line([306.21, 198.82], %, $b)
|
2024-05-24 20:54:42 +10:00
|
|
|
${!replace1 ? ` |> ${line}\n` : ''} |> angledLine([-65, ${
|
2024-07-27 22:56:46 -07:00
|
|
|
!replace1 ? 'segLen(a)' : replace1
|
2024-05-24 20:54:42 +10:00
|
|
|
}], %)
|
|
|
|
|> line([306.21, 198.87], %)
|
2024-07-27 22:56:46 -07:00
|
|
|
|> angledLine([65, ${!replace2 ? 'segAng(a)' : replace2}], %)
|
2024-05-24 20:54:42 +10:00
|
|
|
|> line([-963.39, -154.67], %)
|
|
|
|
`
|
|
|
|
test.each([
|
2024-06-24 22:39:04 -07:00
|
|
|
['line', 'line([306.21, 198.85], %, $a)', ['365.11', '33']],
|
|
|
|
['lineTo', 'lineTo([306.21, 198.85], %, $a)', ['110.48', '119.73']],
|
|
|
|
['yLine', 'yLine(198.85, %, $a)', ['198.85', '90']],
|
|
|
|
['xLine', 'xLine(198.85, %, $a)', ['198.85', '0']],
|
|
|
|
['yLineTo', 'yLineTo(198.85, %, $a)', ['95.94', '90']],
|
|
|
|
['xLineTo', 'xLineTo(198.85, %, $a)', ['162.14', '180']],
|
2024-05-24 20:54:42 +10:00
|
|
|
[
|
|
|
|
'angledLine',
|
2024-06-24 22:39:04 -07:00
|
|
|
'angledLine({ angle: 45.5, length: 198.85 }, %, $a)',
|
2024-05-24 20:54:42 +10:00
|
|
|
['198.85', '45.5'],
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'angledLineOfXLength',
|
2024-06-24 22:39:04 -07:00
|
|
|
'angledLineOfXLength({ angle: 45.5, length: 198.85 }, %, $a)',
|
2024-05-24 20:54:42 +10:00
|
|
|
['283.7', '45.5'],
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'angledLineOfYLength',
|
2024-06-24 22:39:04 -07:00
|
|
|
'angledLineOfYLength({ angle: 45.5, length: 198.85 }, %, $a)',
|
2024-05-24 20:54:42 +10:00
|
|
|
['278.79', '45.5'],
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'angledLineToX',
|
2024-06-24 22:39:04 -07:00
|
|
|
'angledLineToX({ angle: 45.5, to: 198.85 }, %, $a)',
|
2024-05-24 20:54:42 +10:00
|
|
|
['231.33', '134.5'],
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'angledLineToY',
|
2024-06-24 22:39:04 -07:00
|
|
|
'angledLineToY({ angle: 45.5, to: 198.85 }, %, $a)',
|
2024-05-24 20:54:42 +10:00
|
|
|
['134.51', '45.5'],
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'angledLineThatIntersects',
|
2024-06-24 22:39:04 -07:00
|
|
|
`angledLineThatIntersects({ angle: 45.5, intersectTag: b, offset: 198.85 }, %, $a)`,
|
2024-05-24 20:54:42 +10:00
|
|
|
['918.4', '45.5'],
|
|
|
|
],
|
|
|
|
])(`%s`, async (_, line, [replace1, replace2]) => {
|
|
|
|
const code = makeCode(line)
|
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2024-05-24 20:54:42 +10:00
|
|
|
const lineOfInterest = line
|
|
|
|
const range: [number, number] = [
|
|
|
|
code.indexOf(lineOfInterest),
|
|
|
|
code.indexOf(lineOfInterest) + lineOfInterest.length,
|
|
|
|
]
|
|
|
|
const pathToNode = getNodePathFromSourceRange(ast, range)
|
|
|
|
const dependentSegments = findUsesOfTagInPipe(ast, pathToNode)
|
|
|
|
const modifiedAst = deleteSegmentFromPipeExpression(
|
|
|
|
dependentSegments,
|
|
|
|
ast,
|
2024-10-09 19:38:40 -04:00
|
|
|
execState.memory,
|
2024-05-24 20:54:42 +10:00
|
|
|
code,
|
|
|
|
pathToNode
|
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(modifiedAst)) throw modifiedAst
|
2024-05-24 20:54:42 +10:00
|
|
|
const newCode = recast(modifiedAst)
|
|
|
|
expect(newCode).toBe(makeCode(line, replace1, replace2))
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe('Testing removeSingleConstraintInfo', () => {
|
|
|
|
describe('with mostly object notation', () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const code = `part001 = startSketchOn('-XZ')
|
2024-05-24 20:54:42 +10:00
|
|
|
|> startProfileAt([0, 0], %)
|
|
|
|
|> line([3 + 0, 4 + 0], %)
|
|
|
|
|> angledLine({ angle: 3 + 0, length: 3.14 + 0 }, %)
|
|
|
|
|> lineTo([6.14 + 0, 3.14 + 0], %)
|
|
|
|
|> xLineTo(8 + 0, %)
|
|
|
|
|> yLineTo(5 + 0, %)
|
2024-06-24 22:39:04 -07:00
|
|
|
|> yLine(3.14 + 0, %, $a)
|
2024-05-24 20:54:42 +10:00
|
|
|
|> xLine(3.14 + 0, %)
|
|
|
|
|> angledLineOfXLength({ angle: 3 + 0, length: 3.14 + 0 }, %)
|
|
|
|
|> angledLineOfYLength({ angle: 30 + 0, length: 3 + 0 }, %)
|
|
|
|
|> angledLineToX({ angle: 12.14 + 0, to: 12 + 0 }, %)
|
|
|
|
|> angledLineToY({ angle: 30 + 0, to: 10.14 + 0 }, %)
|
|
|
|
|> angledLineThatIntersects({
|
|
|
|
angle: 3.14 + 0,
|
2024-06-24 22:39:04 -07:00
|
|
|
intersectTag: a,
|
2024-05-24 20:54:42 +10:00
|
|
|
offset: 0 + 0
|
|
|
|
}, %)
|
|
|
|
|> tangentialArcTo([3.14 + 0, 13.14 + 0], %)`
|
|
|
|
test.each([
|
|
|
|
[' line([3 + 0, 4], %)', 'arrayIndex', 1],
|
|
|
|
[
|
|
|
|
'angledLine({ angle: 3, length: 3.14 + 0 }, %)',
|
|
|
|
'objectProperty',
|
|
|
|
'angle',
|
|
|
|
],
|
|
|
|
['lineTo([6.14, 3.14 + 0], %)', 'arrayIndex', 0],
|
|
|
|
['xLineTo(8, %)', '', ''],
|
|
|
|
['yLineTo(5, %)', '', ''],
|
2024-06-24 22:39:04 -07:00
|
|
|
['yLine(3.14, %, $a)', '', ''],
|
2024-05-24 20:54:42 +10:00
|
|
|
['xLine(3.14, %)', '', ''],
|
|
|
|
[
|
|
|
|
'angledLineOfXLength({ angle: 3, length: 3.14 + 0 }, %)',
|
|
|
|
'objectProperty',
|
|
|
|
'angle',
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'angledLineOfYLength({ angle: 30 + 0, length: 3 }, %)',
|
|
|
|
'objectProperty',
|
|
|
|
'length',
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'angledLineToX({ angle: 12.14 + 0, to: 12 }, %)',
|
|
|
|
'objectProperty',
|
|
|
|
'to',
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'angledLineToY({ angle: 30, to: 10.14 + 0 }, %)',
|
|
|
|
'objectProperty',
|
|
|
|
'angle',
|
|
|
|
],
|
|
|
|
[
|
|
|
|
`angledLineThatIntersects({
|
|
|
|
angle: 3.14 + 0,
|
|
|
|
offset: 0,
|
2024-06-24 22:39:04 -07:00
|
|
|
intersectTag: a
|
2024-05-24 20:54:42 +10:00
|
|
|
}, %)`,
|
|
|
|
'objectProperty',
|
|
|
|
'offset',
|
|
|
|
],
|
|
|
|
['tangentialArcTo([3.14 + 0, 13.14], %)', 'arrayIndex', 1],
|
2024-09-13 21:14:14 +10:00
|
|
|
] as const)('stdlib fn: %s', async (expectedFinish, key, value) => {
|
2024-05-24 20:54:42 +10:00
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
|
|
|
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2024-05-24 20:54:42 +10:00
|
|
|
const lineOfInterest = expectedFinish.split('(')[0] + '('
|
|
|
|
const range: [number, number] = [
|
|
|
|
code.indexOf(lineOfInterest) + 1,
|
|
|
|
code.indexOf(lineOfInterest) + lineOfInterest.length,
|
|
|
|
]
|
|
|
|
const pathToNode = getNodePathFromSourceRange(ast, range)
|
2024-09-13 21:14:14 +10:00
|
|
|
let argPosition: SimplifiedArgDetails
|
|
|
|
if (key === 'arrayIndex' && typeof value === 'number') {
|
|
|
|
argPosition = {
|
|
|
|
type: 'arrayItem',
|
|
|
|
index: value === 0 ? 0 : 1,
|
|
|
|
}
|
|
|
|
} else if (key === 'objectProperty' && typeof value === 'string') {
|
|
|
|
argPosition = {
|
|
|
|
type: 'objectProperty',
|
|
|
|
key: value,
|
|
|
|
}
|
|
|
|
} else if (key === '') {
|
|
|
|
argPosition = {
|
|
|
|
type: 'singleValue',
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw new Error('argPosition is undefined')
|
|
|
|
}
|
2024-05-24 20:54:42 +10:00
|
|
|
const mod = removeSingleConstraintInfo(
|
2024-09-13 21:14:14 +10:00
|
|
|
pathToNode,
|
|
|
|
argPosition,
|
2024-05-24 20:54:42 +10:00
|
|
|
ast,
|
2024-10-09 19:38:40 -04:00
|
|
|
execState.memory
|
2024-05-24 20:54:42 +10:00
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (!mod) return new Error('mod is undefined')
|
2024-05-24 20:54:42 +10:00
|
|
|
const recastCode = recast(mod.modifiedAst)
|
|
|
|
expect(recastCode).toContain(expectedFinish)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
describe('with array notation', () => {
|
2024-10-02 14:19:40 -05:00
|
|
|
const code = `part001 = startSketchOn('-XZ')
|
2024-05-24 20:54:42 +10:00
|
|
|
|> startProfileAt([0, 0], %)
|
|
|
|
|> angledLine([3.14 + 0, 3.14 + 0], %)
|
|
|
|
|> angledLineOfXLength([3 + 0, 3.14 + 0], %)
|
|
|
|
|> angledLineOfYLength([30 + 0, 3 + 0], %)
|
|
|
|
|> angledLineToX([12.14 + 0, 12 + 0], %)
|
|
|
|
|> angledLineToY([30 + 0, 10.14 + 0], %)`
|
|
|
|
test.each([
|
|
|
|
['angledLine([3, 3.14 + 0], %)', 'arrayIndex', 0],
|
|
|
|
['angledLineOfXLength([3, 3.14 + 0], %)', 'arrayIndex', 0],
|
|
|
|
['angledLineOfYLength([30 + 0, 3], %)', 'arrayIndex', 1],
|
|
|
|
['angledLineToX([12.14 + 0, 12], %)', 'arrayIndex', 1],
|
|
|
|
['angledLineToY([30, 10.14 + 0], %)', 'arrayIndex', 0],
|
|
|
|
])('stdlib fn: %s', async (expectedFinish, key, value) => {
|
|
|
|
const ast = parse(code)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (err(ast)) throw ast
|
|
|
|
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2024-05-24 20:54:42 +10:00
|
|
|
const lineOfInterest = expectedFinish.split('(')[0] + '('
|
|
|
|
const range: [number, number] = [
|
|
|
|
code.indexOf(lineOfInterest) + 1,
|
|
|
|
code.indexOf(lineOfInterest) + lineOfInterest.length,
|
|
|
|
]
|
2024-09-13 21:14:14 +10:00
|
|
|
let argPosition: SimplifiedArgDetails
|
|
|
|
if (key === 'arrayIndex' && typeof value === 'number') {
|
|
|
|
argPosition = {
|
|
|
|
type: 'arrayItem',
|
|
|
|
index: value === 0 ? 0 : 1,
|
|
|
|
}
|
|
|
|
} else if (key === 'objectProperty' && typeof value === 'string') {
|
|
|
|
argPosition = {
|
|
|
|
type: 'objectProperty',
|
|
|
|
key: value,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw new Error('argPosition is undefined')
|
|
|
|
}
|
2024-05-24 20:54:42 +10:00
|
|
|
const pathToNode = getNodePathFromSourceRange(ast, range)
|
|
|
|
const mod = removeSingleConstraintInfo(
|
2024-09-13 21:14:14 +10:00
|
|
|
pathToNode,
|
|
|
|
argPosition,
|
2024-05-24 20:54:42 +10:00
|
|
|
ast,
|
2024-10-09 19:38:40 -04:00
|
|
|
execState.memory
|
2024-05-24 20:54:42 +10:00
|
|
|
)
|
2024-06-24 11:45:40 -04:00
|
|
|
if (!mod) return new Error('mod is undefined')
|
2024-05-24 20:54:42 +10:00
|
|
|
const recastCode = recast(mod.modifiedAst)
|
|
|
|
expect(recastCode).toContain(expectedFinish)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
2024-06-29 10:36:04 -07:00
|
|
|
|
|
|
|
describe('Testing deleteFromSelection', () => {
|
|
|
|
const cases = [
|
|
|
|
[
|
|
|
|
'basicCase',
|
|
|
|
{
|
2024-10-02 14:19:40 -05:00
|
|
|
codeBefore: `myVar = 5
|
|
|
|
sketch003 = startSketchOn('XZ')
|
2024-06-29 10:36:04 -07:00
|
|
|
|> startProfileAt([3.82, 13.6], %)
|
|
|
|
|> line([-2.94, 2.7], %)
|
|
|
|
|> line([7.7, 0.16], %)
|
|
|
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
|
|
|> close(%)`,
|
2024-10-02 14:19:40 -05:00
|
|
|
codeAfter: `myVar = 5\n`,
|
2024-06-29 10:36:04 -07:00
|
|
|
lineOfInterest: 'line([-2.94, 2.7], %)',
|
|
|
|
type: 'default',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'delete extrude',
|
|
|
|
{
|
2024-10-02 14:19:40 -05:00
|
|
|
codeBefore: `sketch001 = startSketchOn('XZ')
|
2024-06-29 10:36:04 -07:00
|
|
|
|> startProfileAt([3.29, 7.86], %)
|
|
|
|
|> line([2.48, 2.44], %)
|
|
|
|
|> line([2.66, 1.17], %)
|
|
|
|
|> line([3.75, 0.46], %)
|
|
|
|
|> line([4.99, -0.46], %, $seg01)
|
|
|
|
|> line([-3.86, -2.73], %)
|
|
|
|
|> line([-17.67, 0.85], %)
|
|
|
|
|> close(%)
|
|
|
|
const extrude001 = extrude(10, sketch001)`,
|
2024-10-02 14:19:40 -05:00
|
|
|
codeAfter: `sketch001 = startSketchOn('XZ')
|
2024-06-29 10:36:04 -07:00
|
|
|
|> startProfileAt([3.29, 7.86], %)
|
|
|
|
|> line([2.48, 2.44], %)
|
|
|
|
|> line([2.66, 1.17], %)
|
|
|
|
|> line([3.75, 0.46], %)
|
|
|
|
|> line([4.99, -0.46], %, $seg01)
|
|
|
|
|> line([-3.86, -2.73], %)
|
|
|
|
|> line([-17.67, 0.85], %)
|
|
|
|
|> close(%)\n`,
|
|
|
|
lineOfInterest: 'line([2.66, 1.17], %)',
|
|
|
|
type: 'extrude-wall',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'delete extrude with sketch on it',
|
|
|
|
{
|
2024-10-02 14:19:40 -05:00
|
|
|
codeBefore: `myVar = 5
|
|
|
|
sketch001 = startSketchOn('XZ')
|
2024-06-29 10:36:04 -07:00
|
|
|
|> startProfileAt([4.46, 5.12], %, $tag)
|
|
|
|
|> line([0.08, myVar], %)
|
|
|
|
|> line([13.03, 2.02], %, $seg01)
|
|
|
|
|> line([3.9, -7.6], %)
|
|
|
|
|> line([-11.18, -2.15], %)
|
|
|
|
|> line([5.41, -9.61], %)
|
|
|
|
|> line([-8.54, -2.51], %)
|
|
|
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
|
|
|> close(%)
|
|
|
|
const extrude001 = extrude(5, sketch001)
|
2024-10-02 14:19:40 -05:00
|
|
|
sketch002 = startSketchOn(extrude001, seg01)
|
2024-06-29 10:36:04 -07:00
|
|
|
|> startProfileAt([-12.55, 2.89], %)
|
|
|
|
|> line([3.02, 1.9], %)
|
|
|
|
|> line([1.82, -1.49], %, $seg02)
|
2024-07-27 22:56:46 -07:00
|
|
|
|> angledLine([-86, segLen(seg02)], %)
|
2024-06-29 10:36:04 -07:00
|
|
|
|> line([-3.97, -0.53], %)
|
|
|
|
|> line([0.3, 0.84], %)
|
|
|
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
|
|
|> close(%)`,
|
2024-10-02 14:19:40 -05:00
|
|
|
codeAfter: `myVar = 5
|
|
|
|
sketch001 = startSketchOn('XZ')
|
2024-06-29 10:36:04 -07:00
|
|
|
|> startProfileAt([4.46, 5.12], %, $tag)
|
|
|
|
|> line([0.08, myVar], %)
|
|
|
|
|> line([13.03, 2.02], %, $seg01)
|
|
|
|
|> line([3.9, -7.6], %)
|
|
|
|
|> line([-11.18, -2.15], %)
|
|
|
|
|> line([5.41, -9.61], %)
|
|
|
|
|> line([-8.54, -2.51], %)
|
|
|
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
|
|
|> close(%)
|
2024-10-02 14:19:40 -05:00
|
|
|
sketch002 = startSketchOn({
|
2024-06-29 10:36:04 -07:00
|
|
|
plane: {
|
|
|
|
origin: { x: 1, y: 2, z: 3 },
|
|
|
|
x_axis: { x: 4, y: 5, z: 6 },
|
|
|
|
y_axis: { x: 7, y: 8, z: 9 },
|
|
|
|
z_axis: { x: 10, y: 11, z: 12 }
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|> startProfileAt([-12.55, 2.89], %)
|
|
|
|
|> line([3.02, 1.9], %)
|
|
|
|
|> line([1.82, -1.49], %, $seg02)
|
2024-07-27 22:56:46 -07:00
|
|
|
|> angledLine([-86, segLen(seg02)], %)
|
2024-06-29 10:36:04 -07:00
|
|
|
|> line([-3.97, -0.53], %)
|
|
|
|
|> line([0.3, 0.84], %)
|
|
|
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
|
|
|> close(%)
|
|
|
|
`,
|
|
|
|
lineOfInterest: 'line([-11.18, -2.15], %)',
|
|
|
|
type: 'extrude-wall',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'delete extrude with sketch on it',
|
|
|
|
{
|
2024-10-02 14:19:40 -05:00
|
|
|
codeBefore: `myVar = 5
|
|
|
|
sketch001 = startSketchOn('XZ')
|
2024-06-29 10:36:04 -07:00
|
|
|
|> startProfileAt([4.46, 5.12], %, $tag)
|
|
|
|
|> line([0.08, myVar], %)
|
|
|
|
|> line([13.03, 2.02], %, $seg01)
|
|
|
|
|> line([3.9, -7.6], %)
|
|
|
|
|> line([-11.18, -2.15], %)
|
|
|
|
|> line([5.41, -9.61], %)
|
|
|
|
|> line([-8.54, -2.51], %)
|
|
|
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
|
|
|> close(%)
|
|
|
|
const extrude001 = extrude(5, sketch001)
|
2024-10-02 14:19:40 -05:00
|
|
|
sketch002 = startSketchOn(extrude001, seg01)
|
2024-06-29 10:36:04 -07:00
|
|
|
|> startProfileAt([-12.55, 2.89], %)
|
|
|
|
|> line([3.02, 1.9], %)
|
|
|
|
|> line([1.82, -1.49], %, $seg02)
|
2024-07-27 22:56:46 -07:00
|
|
|
|> angledLine([-86, segLen(seg02)], %)
|
2024-06-29 10:36:04 -07:00
|
|
|
|> line([-3.97, -0.53], %)
|
|
|
|
|> line([0.3, 0.84], %)
|
|
|
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
|
|
|> close(%)`,
|
2024-10-02 14:19:40 -05:00
|
|
|
codeAfter: `myVar = 5
|
|
|
|
sketch001 = startSketchOn('XZ')
|
2024-06-29 10:36:04 -07:00
|
|
|
|> startProfileAt([4.46, 5.12], %, $tag)
|
|
|
|
|> line([0.08, myVar], %)
|
|
|
|
|> line([13.03, 2.02], %, $seg01)
|
|
|
|
|> line([3.9, -7.6], %)
|
|
|
|
|> line([-11.18, -2.15], %)
|
|
|
|
|> line([5.41, -9.61], %)
|
|
|
|
|> line([-8.54, -2.51], %)
|
|
|
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
|
|
|> close(%)
|
2024-10-02 14:19:40 -05:00
|
|
|
sketch002 = startSketchOn({
|
2024-06-29 10:36:04 -07:00
|
|
|
plane: {
|
|
|
|
origin: { x: 1, y: 2, z: 3 },
|
|
|
|
x_axis: { x: 4, y: 5, z: 6 },
|
|
|
|
y_axis: { x: 7, y: 8, z: 9 },
|
|
|
|
z_axis: { x: 10, y: 11, z: 12 }
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|> startProfileAt([-12.55, 2.89], %)
|
|
|
|
|> line([3.02, 1.9], %)
|
|
|
|
|> line([1.82, -1.49], %, $seg02)
|
2024-07-27 22:56:46 -07:00
|
|
|
|> angledLine([-86, segLen(seg02)], %)
|
2024-06-29 10:36:04 -07:00
|
|
|
|> line([-3.97, -0.53], %)
|
|
|
|
|> line([0.3, 0.84], %)
|
|
|
|
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
|
|
|
|> close(%)
|
|
|
|
`,
|
|
|
|
lineOfInterest: 'startProfileAt([4.46, 5.12], %, $tag)',
|
|
|
|
type: 'end-cap',
|
|
|
|
},
|
|
|
|
],
|
|
|
|
] as const
|
|
|
|
test.each(cases)(
|
|
|
|
'%s',
|
|
|
|
async (name, { codeBefore, codeAfter, lineOfInterest, type }) => {
|
|
|
|
// const lineOfInterest = 'line([-2.94, 2.7], %)'
|
|
|
|
const ast = parse(codeBefore)
|
|
|
|
if (err(ast)) throw ast
|
2024-10-09 19:38:40 -04:00
|
|
|
const execState = await enginelessExecutor(ast)
|
2024-06-29 10:36:04 -07:00
|
|
|
|
|
|
|
// deleteFromSelection
|
|
|
|
const range: [number, number] = [
|
|
|
|
codeBefore.indexOf(lineOfInterest),
|
|
|
|
codeBefore.indexOf(lineOfInterest) + lineOfInterest.length,
|
|
|
|
]
|
|
|
|
const newAst = await deleteFromSelection(
|
|
|
|
ast,
|
|
|
|
{
|
|
|
|
range,
|
|
|
|
type,
|
|
|
|
},
|
2024-10-09 19:38:40 -04:00
|
|
|
execState.memory,
|
2024-06-29 10:36:04 -07:00
|
|
|
async () => {
|
|
|
|
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
|
|
return {
|
|
|
|
origin: { x: 1, y: 2, z: 3 },
|
|
|
|
x_axis: { x: 4, y: 5, z: 6 },
|
|
|
|
y_axis: { x: 7, y: 8, z: 9 },
|
|
|
|
z_axis: { x: 10, y: 11, z: 12 },
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
if (err(newAst)) throw newAst
|
|
|
|
const newCode = recast(newAst)
|
|
|
|
expect(newCode).toBe(codeAfter)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
})
|