Compare commits
17 Commits
jtran/plus
...
max/undele
Author | SHA1 | Date | |
---|---|---|---|
792a101a2f | |||
b0371ccc20 | |||
f5fdad05a4 | |||
19d4ad6332 | |||
66fba3b6fb | |||
dc49105606 | |||
4434e8abbe | |||
1da7d09ab3 | |||
a2343fcfda | |||
f6a02357ca | |||
6875ad5022 | |||
d2c5e7d6ce | |||
51e1e940d3 | |||
17d0f8cf30 | |||
8ccc5653ab | |||
0c0165d515 | |||
168672588d |
@ -2388,6 +2388,7 @@ fillet001 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg01)])
|
|||||||
scene,
|
scene,
|
||||||
editor,
|
editor,
|
||||||
toolbar,
|
toolbar,
|
||||||
|
cmdBar,
|
||||||
}) => {
|
}) => {
|
||||||
// Code samples
|
// Code samples
|
||||||
const initialCode = `sketch001 = startSketchOn(XY)
|
const initialCode = `sketch001 = startSketchOn(XY)
|
||||||
@ -2401,14 +2402,14 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
|> fillet(radius = 5, tags = [seg01]) // fillet01
|
|> fillet(radius = 5, tags = [seg01]) // fillet01
|
||||||
|> fillet(radius = 5, tags = [seg02]) // fillet02
|
|> fillet(radius = 5, tags = [seg02]) // fillet02
|
||||||
fillet03 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg01)])
|
fillet03 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg01)])
|
||||||
fillet04 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg02)])
|
fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg02)])
|
||||||
`
|
`
|
||||||
const pipedFilletDeclaration = 'fillet(radius = 5, tags = [seg01])'
|
const firstPipedFilletDeclaration = 'fillet(radius = 5, tags = [seg01])'
|
||||||
const secondPipedFilletDeclaration = 'fillet(radius = 5, tags = [seg02])'
|
const secondPipedFilletDeclaration = 'fillet(radius = 5, tags = [seg02])'
|
||||||
const standaloneFilletDeclaration =
|
const standaloneAssignedFilletDeclaration =
|
||||||
'fillet03 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg01)])'
|
'fillet03 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg01)])'
|
||||||
const secondStandaloneFilletDeclaration =
|
const standaloneUnassignedFilletDeclaration =
|
||||||
'fillet04 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg02)])'
|
'fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg02)])'
|
||||||
|
|
||||||
// Locators
|
// Locators
|
||||||
const pipedFilletEdgeLocation = { x: 600, y: 193 }
|
const pipedFilletEdgeLocation = { x: 600, y: 193 }
|
||||||
@ -2430,6 +2431,7 @@ fillet04 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
}, initialCode)
|
}, initialCode)
|
||||||
await page.setBodyDimensions({ width: 1000, height: 500 })
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
await homePage.goToModelingScene()
|
await homePage.goToModelingScene()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
// verify modeling scene is loaded
|
// verify modeling scene is loaded
|
||||||
await scene.expectPixelColor(
|
await scene.expectPixelColor(
|
||||||
@ -2446,15 +2448,19 @@ fillet04 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
await test.step('Delete fillet via feature tree selection', async () => {
|
await test.step('Delete fillet via feature tree selection', async () => {
|
||||||
await test.step('Open Feature Tree Pane', async () => {
|
await test.step('Open Feature Tree Pane', async () => {
|
||||||
await toolbar.openPane('feature-tree')
|
await toolbar.openPane('feature-tree')
|
||||||
await page.waitForTimeout(500)
|
await scene.settled(cmdBar)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Delete piped fillet via feature tree selection', async () => {
|
await test.step('Delete piped fillet via feature tree selection', async () => {
|
||||||
await test.step('Verify all fillets are present in the editor', async () => {
|
await test.step('Verify all fillets are present in the editor', async () => {
|
||||||
await editor.expectEditor.toContain(pipedFilletDeclaration)
|
await editor.expectEditor.toContain(firstPipedFilletDeclaration)
|
||||||
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
|
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
|
||||||
await editor.expectEditor.toContain(standaloneFilletDeclaration)
|
await editor.expectEditor.toContain(
|
||||||
await editor.expectEditor.toContain(secondStandaloneFilletDeclaration)
|
standaloneAssignedFilletDeclaration
|
||||||
|
)
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
standaloneUnassignedFilletDeclaration
|
||||||
|
)
|
||||||
})
|
})
|
||||||
await test.step('Verify test fillets are present in the scene', async () => {
|
await test.step('Verify test fillets are present in the scene', async () => {
|
||||||
await scene.expectPixelColor(
|
await scene.expectPixelColor(
|
||||||
@ -2475,13 +2481,17 @@ fillet04 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
)
|
)
|
||||||
await operationButton.click({ button: 'left' })
|
await operationButton.click({ button: 'left' })
|
||||||
await page.keyboard.press('Delete')
|
await page.keyboard.press('Delete')
|
||||||
await page.waitForTimeout(500)
|
await scene.settled(cmdBar)
|
||||||
})
|
})
|
||||||
await test.step('Verify piped fillet is deleted but other fillets are not (in the editor)', async () => {
|
await test.step('Verify piped fillet is deleted but other fillets are not (in the editor)', async () => {
|
||||||
await editor.expectEditor.not.toContain(pipedFilletDeclaration)
|
await editor.expectEditor.not.toContain(firstPipedFilletDeclaration)
|
||||||
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
|
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
|
||||||
await editor.expectEditor.toContain(standaloneFilletDeclaration)
|
await editor.expectEditor.toContain(
|
||||||
await editor.expectEditor.toContain(secondStandaloneFilletDeclaration)
|
standaloneAssignedFilletDeclaration
|
||||||
|
)
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
standaloneUnassignedFilletDeclaration
|
||||||
|
)
|
||||||
})
|
})
|
||||||
await test.step('Verify piped fillet is deleted but non-piped is not (in the scene)', async () => {
|
await test.step('Verify piped fillet is deleted but non-piped is not (in the scene)', async () => {
|
||||||
await scene.expectPixelColor(
|
await scene.expectPixelColor(
|
||||||
@ -2497,22 +2507,51 @@ fillet04 = fillet(extrude001, radius = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Delete non-piped fillet via feature tree selection', async () => {
|
await test.step('Delete standalone assigned fillet via feature tree selection', async () => {
|
||||||
await test.step('Delete non-piped fillet', async () => {
|
await test.step('Delete standalone assigned fillet', async () => {
|
||||||
const operationButton = await toolbar.getFeatureTreeOperation(
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||||
'Fillet',
|
'Fillet',
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
await operationButton.click({ button: 'left' })
|
await operationButton.click({ button: 'left' })
|
||||||
await page.keyboard.press('Delete')
|
await page.keyboard.press('Delete')
|
||||||
await page.waitForTimeout(500)
|
await scene.settled(cmdBar)
|
||||||
})
|
})
|
||||||
await test.step('Verify non-piped fillet is deleted but other two fillets are not (in the editor)', async () => {
|
await test.step('Verify standalone assigned fillet is deleted but other two fillets are not (in the editor)', async () => {
|
||||||
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
|
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
|
||||||
await editor.expectEditor.not.toContain(standaloneFilletDeclaration)
|
await editor.expectEditor.not.toContain(
|
||||||
await editor.expectEditor.toContain(secondStandaloneFilletDeclaration)
|
standaloneAssignedFilletDeclaration
|
||||||
|
)
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
standaloneUnassignedFilletDeclaration
|
||||||
|
)
|
||||||
})
|
})
|
||||||
await test.step('Verify non-piped fillet is deleted but piped is not (in the scene)', async () => {
|
await test.step('Verify standalone assigned fillet is deleted but piped is not (in the scene)', async () => {
|
||||||
|
await scene.expectPixelColor(
|
||||||
|
edgeColorWhite,
|
||||||
|
standaloneFilletEdgeLocation,
|
||||||
|
lowTolerance
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Delete standalone unassigned fillet via feature tree selection', async () => {
|
||||||
|
await test.step('Delete standalone unassigned fillet', async () => {
|
||||||
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||||
|
'Fillet',
|
||||||
|
1
|
||||||
|
)
|
||||||
|
await operationButton.click({ button: 'left' })
|
||||||
|
await page.keyboard.press('Delete')
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
})
|
||||||
|
await test.step('Verify standalone unassigned fillet is deleted but other fillet is not (in the editor)', async () => {
|
||||||
|
await editor.expectEditor.toContain(secondPipedFilletDeclaration)
|
||||||
|
await editor.expectEditor.not.toContain(
|
||||||
|
standaloneUnassignedFilletDeclaration
|
||||||
|
)
|
||||||
|
})
|
||||||
|
await test.step('Verify standalone unassigned fillet is deleted but piped is not (in the scene)', async () => {
|
||||||
await scene.expectPixelColor(
|
await scene.expectPixelColor(
|
||||||
edgeColorWhite,
|
edgeColorWhite,
|
||||||
standaloneFilletEdgeLocation,
|
standaloneFilletEdgeLocation,
|
||||||
@ -2964,14 +3003,14 @@ extrude001 = extrude(sketch001, length = -12)
|
|||||||
|> chamfer(length = 5, tags = [seg01]) // chamfer01
|
|> chamfer(length = 5, tags = [seg01]) // chamfer01
|
||||||
|> chamfer(length = 5, tags = [seg02]) // chamfer02
|
|> chamfer(length = 5, tags = [seg02]) // chamfer02
|
||||||
chamfer03 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg01)])
|
chamfer03 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg01)])
|
||||||
chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
||||||
`
|
`
|
||||||
const pipedChamferDeclaration = 'chamfer(length = 5, tags = [seg01])'
|
const firstPipedChamferDeclaration = 'chamfer(length = 5, tags = [seg01])'
|
||||||
const secondPipedChamferDeclaration = 'chamfer(length = 5, tags = [seg02])'
|
const secondPipedChamferDeclaration = 'chamfer(length = 5, tags = [seg02])'
|
||||||
const standaloneChamferDeclaration =
|
const standaloneAssignedChamferDeclaration =
|
||||||
'chamfer03 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg01)])'
|
'chamfer03 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg01)])'
|
||||||
const secondStandaloneChamferDeclaration =
|
const standaloneUnassignedChamferDeclaration =
|
||||||
'chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])'
|
'chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])'
|
||||||
|
|
||||||
// Locators
|
// Locators
|
||||||
const pipedChamferEdgeLocation = { x: 600, y: 193 }
|
const pipedChamferEdgeLocation = { x: 600, y: 193 }
|
||||||
@ -3010,16 +3049,18 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
await test.step('Delete chamfer via feature tree selection', async () => {
|
await test.step('Delete chamfer via feature tree selection', async () => {
|
||||||
await test.step('Open Feature Tree Pane', async () => {
|
await test.step('Open Feature Tree Pane', async () => {
|
||||||
await toolbar.openPane('feature-tree')
|
await toolbar.openPane('feature-tree')
|
||||||
await page.waitForTimeout(500)
|
await scene.settled(cmdBar)
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Delete piped chamfer via feature tree selection', async () => {
|
await test.step('Delete piped chamfer via feature tree selection', async () => {
|
||||||
await test.step('Verify all chamfers are present in the editor', async () => {
|
await test.step('Verify all chamfers are present in the editor', async () => {
|
||||||
await editor.expectEditor.toContain(pipedChamferDeclaration)
|
await editor.expectEditor.toContain(firstPipedChamferDeclaration)
|
||||||
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
|
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
|
||||||
await editor.expectEditor.toContain(standaloneChamferDeclaration)
|
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
secondStandaloneChamferDeclaration
|
standaloneAssignedChamferDeclaration
|
||||||
|
)
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
standaloneUnassignedChamferDeclaration
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
await test.step('Verify test chamfers are present in the scene', async () => {
|
await test.step('Verify test chamfers are present in the scene', async () => {
|
||||||
@ -3041,14 +3082,16 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
)
|
)
|
||||||
await operationButton.click({ button: 'left' })
|
await operationButton.click({ button: 'left' })
|
||||||
await page.keyboard.press('Delete')
|
await page.keyboard.press('Delete')
|
||||||
await page.waitForTimeout(500)
|
await scene.settled(cmdBar)
|
||||||
})
|
})
|
||||||
await test.step('Verify piped chamfer is deleted but other chamfers are not (in the editor)', async () => {
|
await test.step('Verify piped chamfer is deleted but other chamfers are not (in the editor)', async () => {
|
||||||
await editor.expectEditor.not.toContain(pipedChamferDeclaration)
|
await editor.expectEditor.not.toContain(firstPipedChamferDeclaration)
|
||||||
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
|
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
|
||||||
await editor.expectEditor.toContain(standaloneChamferDeclaration)
|
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
secondStandaloneChamferDeclaration
|
standaloneAssignedChamferDeclaration
|
||||||
|
)
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
standaloneUnassignedChamferDeclaration
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
await test.step('Verify piped chamfer is deleted but non-piped is not (in the scene)', async () => {
|
await test.step('Verify piped chamfer is deleted but non-piped is not (in the scene)', async () => {
|
||||||
@ -3065,24 +3108,51 @@ chamfer04 = chamfer(extrude001, length = 5, tags = [getOppositeEdge(seg02)])
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
await test.step('Delete non-piped chamfer via feature tree selection', async () => {
|
await test.step('Delete standalone assigned chamfer via feature tree selection', async () => {
|
||||||
await test.step('Delete non-piped chamfer', async () => {
|
await test.step('Delete standalone assigned chamfer', async () => {
|
||||||
const operationButton = await toolbar.getFeatureTreeOperation(
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||||
'Chamfer',
|
'Chamfer',
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
await operationButton.click({ button: 'left' })
|
await operationButton.click({ button: 'left' })
|
||||||
await page.keyboard.press('Delete')
|
await page.keyboard.press('Delete')
|
||||||
await page.waitForTimeout(500)
|
await scene.settled(cmdBar)
|
||||||
})
|
})
|
||||||
await test.step('Verify non-piped chamfer is deleted but other two chamfers are not (in the editor)', async () => {
|
await test.step('Verify standalone assigned chamfer is deleted but other two chamfers are not (in the editor)', async () => {
|
||||||
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
|
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
|
||||||
await editor.expectEditor.not.toContain(standaloneChamferDeclaration)
|
await editor.expectEditor.not.toContain(
|
||||||
|
standaloneAssignedChamferDeclaration
|
||||||
|
)
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
secondStandaloneChamferDeclaration
|
standaloneUnassignedChamferDeclaration
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
await test.step('Verify non-piped chamfer is deleted but piped is not (in the scene)', async () => {
|
await test.step('Verify standalone assigned chamfer is deleted but piped is not (in the scene)', async () => {
|
||||||
|
await scene.expectPixelColor(
|
||||||
|
edgeColorWhite,
|
||||||
|
standaloneChamferEdgeLocation,
|
||||||
|
lowTolerance
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('Delete standalone unassigned chamfer via feature tree selection', async () => {
|
||||||
|
await test.step('Delete standalone unassigned chamfer', async () => {
|
||||||
|
const operationButton = await toolbar.getFeatureTreeOperation(
|
||||||
|
'Chamfer',
|
||||||
|
1
|
||||||
|
)
|
||||||
|
await operationButton.click({ button: 'left' })
|
||||||
|
await page.keyboard.press('Delete')
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
})
|
||||||
|
await test.step('Verify standalone unassigned chamfer is deleted but piped chamfer is not (in the editor)', async () => {
|
||||||
|
await editor.expectEditor.toContain(secondPipedChamferDeclaration)
|
||||||
|
await editor.expectEditor.not.toContain(
|
||||||
|
standaloneUnassignedChamferDeclaration
|
||||||
|
)
|
||||||
|
})
|
||||||
|
await test.step('Verify standalone unassigned chamfer is deleted but piped is not (in the scene)', async () => {
|
||||||
await scene.expectPixelColor(
|
await scene.expectPixelColor(
|
||||||
edgeColorWhite,
|
edgeColorWhite,
|
||||||
standaloneChamferEdgeLocation,
|
standaloneChamferEdgeLocation,
|
||||||
|
@ -64,7 +64,7 @@ import { KCL_DEFAULT_CONSTANT_PREFIXES } from '@src/lib/constants'
|
|||||||
import type { DefaultPlaneStr } from '@src/lib/planes'
|
import type { DefaultPlaneStr } from '@src/lib/planes'
|
||||||
|
|
||||||
import { err, trap } from '@src/lib/trap'
|
import { err, trap } from '@src/lib/trap'
|
||||||
import { isOverlap, roundOff } from '@src/lib/utils'
|
import { isArray, isOverlap, roundOff } from '@src/lib/utils'
|
||||||
import type { ExtrudeFacePlane } from '@src/machines/modelingMachine'
|
import type { ExtrudeFacePlane } from '@src/machines/modelingMachine'
|
||||||
import { ARG_AT } from '@src/lang/constants'
|
import { ARG_AT } from '@src/lang/constants'
|
||||||
|
|
||||||
@ -949,6 +949,27 @@ export function deleteSegmentFromPipeExpression(
|
|||||||
return _modifiedAst
|
return _modifiedAst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a standalone top level statement from the AST
|
||||||
|
* Used for removing both unassigned statements and variable declarations
|
||||||
|
*
|
||||||
|
* @param ast The AST to modify
|
||||||
|
* @param pathToNode The path to the node to delete
|
||||||
|
*/
|
||||||
|
export function deleteTopLevelStatement(
|
||||||
|
ast: Node<Program>,
|
||||||
|
pathToNode: PathToNode
|
||||||
|
): Error | void {
|
||||||
|
const pathStep = pathToNode[1]
|
||||||
|
if (!isArray(pathStep) || typeof pathStep[0] !== 'number') {
|
||||||
|
return new Error(
|
||||||
|
'Invalid pathToNode structure: expected a number at path[1][0]'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const statementIndex: number = pathStep[0]
|
||||||
|
ast.body.splice(statementIndex, 1)
|
||||||
|
}
|
||||||
|
|
||||||
export function removeSingleConstraintInfo(
|
export function removeSingleConstraintInfo(
|
||||||
pathToCallExp: PathToNode,
|
pathToCallExp: PathToNode,
|
||||||
argDetails: SimplifiedArgDetails,
|
argDetails: SimplifiedArgDetails,
|
||||||
|
@ -801,7 +801,7 @@ extrude001 = extrude(sketch001, length = -15)`
|
|||||||
expectedCode
|
expectedCode
|
||||||
)
|
)
|
||||||
}, 10_000)
|
}, 10_000)
|
||||||
it(`should delete a non-piped ${edgeTreatmentType} from a single segment`, async () => {
|
it(`should delete a standalone assigned ${edgeTreatmentType} from a single segment`, async () => {
|
||||||
const code = `sketch001 = startSketchOn(XY)
|
const code = `sketch001 = startSketchOn(XY)
|
||||||
|> startProfile(at = [-10, 10])
|
|> startProfile(at = [-10, 10])
|
||||||
|> line(end = [20, 0])
|
|> line(end = [20, 0])
|
||||||
@ -810,8 +810,34 @@ extrude001 = extrude(sketch001, length = -15)`
|
|||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
extrude001 = extrude(sketch001, length = -15)
|
extrude001 = extrude(sketch001, length = -15)
|
||||||
fillet001 = ${edgeTreatmentType}(extrude001, ${parameterName} = 3, tags = [seg01])`
|
${edgeTreatmentType}001 = ${edgeTreatmentType}(extrude001, ${parameterName} = 3, tags = [seg01])`
|
||||||
const edgeTreatmentSnippet = `fillet001 = ${edgeTreatmentType}(extrude001, ${parameterName} = 3, tags = [seg01])`
|
const edgeTreatmentSnippet = `${edgeTreatmentType}001 = ${edgeTreatmentType}(extrude001, ${parameterName} = 3, tags = [seg01])`
|
||||||
|
const expectedCode = `sketch001 = startSketchOn(XY)
|
||||||
|
|> startProfile(at = [-10, 10])
|
||||||
|
|> line(end = [20, 0])
|
||||||
|
|> line(end = [0, -20])
|
||||||
|
|> line(end = [-20, 0], tag = $seg01)
|
||||||
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|
|> close()
|
||||||
|
extrude001 = extrude(sketch001, length = -15)`
|
||||||
|
|
||||||
|
await runDeleteEdgeTreatmentTest(
|
||||||
|
code,
|
||||||
|
edgeTreatmentSnippet,
|
||||||
|
expectedCode
|
||||||
|
)
|
||||||
|
}, 10_000)
|
||||||
|
it(`should delete a standalone ${edgeTreatmentType} without assignment from a single segment`, async () => {
|
||||||
|
const code = `sketch001 = startSketchOn(XY)
|
||||||
|
|> startProfile(at = [-10, 10])
|
||||||
|
|> line(end = [20, 0])
|
||||||
|
|> line(end = [0, -20])
|
||||||
|
|> line(end = [-20, 0], tag = $seg01)
|
||||||
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|
|> close()
|
||||||
|
extrude001 = extrude(sketch001, length = -15)
|
||||||
|
${edgeTreatmentType}(extrude001, ${parameterName} = 5, tags = [seg01])`
|
||||||
|
const edgeTreatmentSnippet = `${edgeTreatmentType}(extrude001, ${parameterName} = 5, tags = [seg01])`
|
||||||
const expectedCode = `sketch001 = startSketchOn(XY)
|
const expectedCode = `sketch001 = startSketchOn(XY)
|
||||||
|> startProfile(at = [-10, 10])
|
|> startProfile(at = [-10, 10])
|
||||||
|> line(end = [20, 0])
|
|> line(end = [20, 0])
|
||||||
|
@ -16,6 +16,7 @@ import {
|
|||||||
getNodeFromPath,
|
getNodeFromPath,
|
||||||
hasSketchPipeBeenExtruded,
|
hasSketchPipeBeenExtruded,
|
||||||
traverse,
|
traverse,
|
||||||
|
locateVariableWithCallOrPipe,
|
||||||
} from '@src/lang/queryAst'
|
} from '@src/lang/queryAst'
|
||||||
import { getNodePathFromSourceRange } from '@src/lang/queryAstNodePathUtils'
|
import { getNodePathFromSourceRange } from '@src/lang/queryAstNodePathUtils'
|
||||||
import type { Artifact } from '@src/lang/std/artifactGraph'
|
import type { Artifact } from '@src/lang/std/artifactGraph'
|
||||||
@ -26,25 +27,25 @@ import {
|
|||||||
sketchLineHelperMapKw,
|
sketchLineHelperMapKw,
|
||||||
} from '@src/lang/std/sketch'
|
} from '@src/lang/std/sketch'
|
||||||
import { findKwArg } from '@src/lang/util'
|
import { findKwArg } from '@src/lang/util'
|
||||||
import type {
|
import {
|
||||||
ArtifactGraph,
|
type ArtifactGraph,
|
||||||
CallExpressionKw,
|
type CallExpressionKw,
|
||||||
Expr,
|
type Expr,
|
||||||
ObjectExpression,
|
type ObjectExpression,
|
||||||
PathToNode,
|
type PathToNode,
|
||||||
PipeExpression,
|
type Program,
|
||||||
Program,
|
type VariableDeclarator,
|
||||||
VariableDeclaration,
|
type ExpressionStatement,
|
||||||
VariableDeclarator,
|
|
||||||
} from '@src/lang/wasm'
|
} from '@src/lang/wasm'
|
||||||
import type { KclCommandValue } from '@src/lib/commandTypes'
|
import type { KclCommandValue } from '@src/lib/commandTypes'
|
||||||
import type { Selection, Selections } from '@src/lib/selections'
|
import type { Selection, Selections } from '@src/lib/selections'
|
||||||
import { err } from '@src/lib/trap'
|
import { err } from '@src/lib/trap'
|
||||||
import { isArray } from '@src/lib/utils'
|
|
||||||
import {
|
import {
|
||||||
createTagExpressions,
|
createTagExpressions,
|
||||||
modifyAstWithTagsForSelection,
|
modifyAstWithTagsForSelection,
|
||||||
} from '@src/lang/modifyAst/tagManagement'
|
} from '@src/lang/modifyAst/tagManagement'
|
||||||
|
import { deleteNodeInExtrudePipe } from '@src/lang/modifyAst/deleteNodeInExtrudePipe'
|
||||||
|
import { deleteTopLevelStatement } from '@src/lang/modifyAst'
|
||||||
|
|
||||||
// Edge Treatment Types
|
// Edge Treatment Types
|
||||||
export enum EdgeTreatmentType {
|
export enum EdgeTreatmentType {
|
||||||
@ -164,12 +165,12 @@ export async function modifyAstWithEdgeTreatmentAndTag(
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Locate the extrude call
|
// Locate the extrude call
|
||||||
const locatedExtrudeDeclarator = locateExtrudeDeclarator(
|
const locatedExtrudeDeclarator = locateVariableWithCallOrPipe(
|
||||||
clonedAst,
|
clonedAst,
|
||||||
pathToExtrudeNode
|
pathToExtrudeNode
|
||||||
)
|
)
|
||||||
if (err(locatedExtrudeDeclarator)) return locatedExtrudeDeclarator
|
if (err(locatedExtrudeDeclarator)) return locatedExtrudeDeclarator
|
||||||
const { extrudeDeclarator } = locatedExtrudeDeclarator
|
const { variableDeclarator } = locatedExtrudeDeclarator
|
||||||
|
|
||||||
// Modify the extrude expression to include this edge treatment expression
|
// Modify the extrude expression to include this edge treatment expression
|
||||||
// CallExpression - no edge treatment
|
// CallExpression - no edge treatment
|
||||||
@ -177,33 +178,33 @@ export async function modifyAstWithEdgeTreatmentAndTag(
|
|||||||
|
|
||||||
let pathToEdgeTreatmentNode: PathToNode
|
let pathToEdgeTreatmentNode: PathToNode
|
||||||
|
|
||||||
if (extrudeDeclarator.init.type === 'CallExpressionKw') {
|
if (variableDeclarator.init.type === 'CallExpressionKw') {
|
||||||
// 1. case when no edge treatment exists
|
// 1. case when no edge treatment exists
|
||||||
|
|
||||||
// modify ast with new edge treatment call by mutating the extrude node
|
// modify ast with new edge treatment call by mutating the extrude node
|
||||||
extrudeDeclarator.init = createPipeExpression([
|
variableDeclarator.init = createPipeExpression([
|
||||||
extrudeDeclarator.init,
|
variableDeclarator.init,
|
||||||
edgeTreatmentCall,
|
edgeTreatmentCall,
|
||||||
])
|
])
|
||||||
|
|
||||||
// get path to the edge treatment node
|
// get path to the edge treatment node
|
||||||
pathToEdgeTreatmentNode = getPathToNodeOfEdgeTreatmentLiteral(
|
pathToEdgeTreatmentNode = getPathToNodeOfEdgeTreatmentLiteral(
|
||||||
pathToExtrudeNode,
|
pathToExtrudeNode,
|
||||||
extrudeDeclarator,
|
variableDeclarator,
|
||||||
firstTag,
|
firstTag,
|
||||||
parameters
|
parameters
|
||||||
)
|
)
|
||||||
pathToEdgeTreatmentNodes.push(pathToEdgeTreatmentNode)
|
pathToEdgeTreatmentNodes.push(pathToEdgeTreatmentNode)
|
||||||
} else if (extrudeDeclarator.init.type === 'PipeExpression') {
|
} else if (variableDeclarator.init.type === 'PipeExpression') {
|
||||||
// 2. case when edge treatment exists or extrude in sketch pipe
|
// 2. case when edge treatment exists or extrude in sketch pipe
|
||||||
|
|
||||||
// mutate the extrude node with the new edge treatment call
|
// mutate the extrude node with the new edge treatment call
|
||||||
extrudeDeclarator.init.body.push(edgeTreatmentCall)
|
variableDeclarator.init.body.push(edgeTreatmentCall)
|
||||||
|
|
||||||
// get path to the edge treatment node
|
// get path to the edge treatment node
|
||||||
pathToEdgeTreatmentNode = getPathToNodeOfEdgeTreatmentLiteral(
|
pathToEdgeTreatmentNode = getPathToNodeOfEdgeTreatmentLiteral(
|
||||||
pathToExtrudeNode,
|
pathToExtrudeNode,
|
||||||
extrudeDeclarator,
|
variableDeclarator,
|
||||||
firstTag,
|
firstTag,
|
||||||
parameters
|
parameters
|
||||||
)
|
)
|
||||||
@ -330,38 +331,6 @@ export function getEdgeTagCall(
|
|||||||
return tagCall
|
return tagCall
|
||||||
}
|
}
|
||||||
|
|
||||||
export function locateExtrudeDeclarator(
|
|
||||||
node: Program,
|
|
||||||
pathToExtrudeNode: PathToNode
|
|
||||||
): { extrudeDeclarator: VariableDeclarator; shallowPath: PathToNode } | Error {
|
|
||||||
const nodeOfExtrudeCall = getNodeFromPath<VariableDeclaration>(
|
|
||||||
node,
|
|
||||||
pathToExtrudeNode,
|
|
||||||
'VariableDeclaration'
|
|
||||||
)
|
|
||||||
if (err(nodeOfExtrudeCall)) return nodeOfExtrudeCall
|
|
||||||
|
|
||||||
const { node: extrudeVarDecl } = nodeOfExtrudeCall
|
|
||||||
const extrudeDeclarator = extrudeVarDecl.declaration
|
|
||||||
if (!extrudeDeclarator) {
|
|
||||||
return new Error('Extrude Declarator not found.')
|
|
||||||
}
|
|
||||||
|
|
||||||
const extrudeInit = extrudeDeclarator?.init
|
|
||||||
if (!extrudeInit) {
|
|
||||||
return new Error('Extrude Init not found.')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
extrudeInit.type !== 'CallExpressionKw' &&
|
|
||||||
extrudeInit.type !== 'PipeExpression'
|
|
||||||
) {
|
|
||||||
return new Error('Extrude must be a PipeExpression or CallExpressionKw')
|
|
||||||
}
|
|
||||||
|
|
||||||
return { extrudeDeclarator, shallowPath: nodeOfExtrudeCall.shallowPath }
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPathToNodeOfEdgeTreatmentLiteral(
|
function getPathToNodeOfEdgeTreatmentLiteral(
|
||||||
pathToExtrudeNode: PathToNode,
|
pathToExtrudeNode: PathToNode,
|
||||||
extrudeDeclarator: VariableDeclarator,
|
extrudeDeclarator: VariableDeclarator,
|
||||||
@ -484,7 +453,7 @@ function getParameterNameAndValue(
|
|||||||
: parameters.length.valueAst
|
: parameters.length.valueAst
|
||||||
return { parameterName: 'length', parameterValue }
|
return { parameterName: 'length', parameterValue }
|
||||||
} else {
|
} else {
|
||||||
return new Error('Unsupported edge treatment type}')
|
return new Error('Unsupported edge treatment type')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -614,14 +583,11 @@ export async function deleteEdgeTreatment(
|
|||||||
selection: Selection
|
selection: Selection
|
||||||
): Promise<Node<Program> | Error> {
|
): Promise<Node<Program> | Error> {
|
||||||
/**
|
/**
|
||||||
* Deletes an edge treatment (fillet or chamfer)
|
* Deletes an edge treatment (fillet or chamfer) from the AST
|
||||||
* from the AST based on the selection.
|
|
||||||
* Handles both standalone treatments
|
|
||||||
* and those within a PipeExpression.
|
|
||||||
*
|
*
|
||||||
* Supported cases:
|
* Supported cases:
|
||||||
* [+] fillet and chamfer
|
* [+] fillet and chamfer
|
||||||
* [+] piped and non-piped edge treatments
|
* [+] piped, standalone (assigned and unassigned) edge treatments
|
||||||
* [-] delete single tag from array of tags (currently whole expression is deleted)
|
* [-] delete single tag from array of tags (currently whole expression is deleted)
|
||||||
* [-] multiple selections with different edge treatments (currently single selection is supported)
|
* [-] multiple selections with different edge treatments (currently single selection is supported)
|
||||||
*/
|
*/
|
||||||
@ -632,119 +598,49 @@ export async function deleteEdgeTreatment(
|
|||||||
return new Error('Selection is not an edge cut')
|
return new Error('Selection is not an edge cut')
|
||||||
}
|
}
|
||||||
|
|
||||||
const { subType: edgeTreatmentType } = artifact
|
const { subType } = artifact
|
||||||
if (
|
if (!isEdgeTreatmentType(subType)) {
|
||||||
!edgeTreatmentType ||
|
|
||||||
!['fillet', 'chamfer'].includes(edgeTreatmentType)
|
|
||||||
) {
|
|
||||||
return new Error('Unsupported or missing edge treatment type')
|
return new Error('Unsupported or missing edge treatment type')
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Clone ast and retrieve the VariableDeclarator
|
// 2. Clone ast and retrieve the edge treatment node
|
||||||
const astClone = structuredClone(ast)
|
const astClone = structuredClone(ast)
|
||||||
const varDec = getNodeFromPath<VariableDeclarator>(
|
const edgeTreatmentNode = getNodeFromPath<
|
||||||
ast,
|
VariableDeclarator | ExpressionStatement
|
||||||
selection?.codeRef?.pathToNode,
|
>(astClone, selection?.codeRef?.pathToNode, [
|
||||||
'VariableDeclarator'
|
'VariableDeclarator',
|
||||||
)
|
'ExpressionStatement',
|
||||||
if (err(varDec)) return varDec
|
])
|
||||||
|
if (err(edgeTreatmentNode)) return edgeTreatmentNode
|
||||||
|
|
||||||
// 3: Check if edge treatment is in a pipe
|
// 3: Delete edge treatments
|
||||||
const inPipe = varDec.node.init.type === 'PipeExpression'
|
// There 3 possible cases:
|
||||||
|
// - piped: const body = extrude(...) |> fillet(...)
|
||||||
|
// - assigned to variables: fillet0001 = fillet(...)
|
||||||
|
// - unassigned standalone statements: fillet(...)
|
||||||
|
// piped and assigned nodes are in the variable declarator
|
||||||
|
// unassigned nodes are in the expression statement
|
||||||
|
|
||||||
// 4A. Handle standalone edge treatment
|
|
||||||
if (!inPipe) {
|
|
||||||
const varDecPathStep = varDec.shallowPath[1]
|
|
||||||
|
|
||||||
if (!isArray(varDecPathStep) || typeof varDecPathStep[0] !== 'number') {
|
|
||||||
return new Error(
|
|
||||||
'Invalid shallowPath structure: expected a number at shallowPath[1][0]'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const varDecIndex: number = varDecPathStep[0]
|
|
||||||
|
|
||||||
// Remove entire VariableDeclarator from the ast
|
|
||||||
astClone.body.splice(varDecIndex, 1)
|
|
||||||
return astClone
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4B. Handle edge treatment within pipe
|
|
||||||
if (inPipe) {
|
|
||||||
// Retrieve the CallExpression path
|
|
||||||
const callExp =
|
|
||||||
getNodeFromPath<CallExpressionKw>(
|
|
||||||
ast,
|
|
||||||
selection?.codeRef?.pathToNode,
|
|
||||||
'CallExpressionKw'
|
|
||||||
) ?? null
|
|
||||||
if (err(callExp)) return callExp
|
|
||||||
|
|
||||||
const shallowPath = callExp.shallowPath
|
|
||||||
|
|
||||||
// Initialize variables to hold the PipeExpression path and callIndex
|
|
||||||
let pipeExpressionPath: PathToNode | null = null
|
|
||||||
let callIndex: number | null = null
|
|
||||||
|
|
||||||
// Iterate through the shallowPath to find the PipeExpression and callIndex
|
|
||||||
for (let i = 0; i < shallowPath.length - 1; i++) {
|
|
||||||
const [key, value] = shallowPath[i]
|
|
||||||
|
|
||||||
if (key === 'body' && value === 'PipeExpression') {
|
|
||||||
pipeExpressionPath = shallowPath.slice(0, i + 1)
|
|
||||||
|
|
||||||
const nextStep = shallowPath[i + 1]
|
|
||||||
if (
|
if (
|
||||||
nextStep &&
|
edgeTreatmentNode.node.type === 'ExpressionStatement' || // unassigned
|
||||||
nextStep[1] === 'index' &&
|
(edgeTreatmentNode.node.type === 'VariableDeclarator' && // assigned
|
||||||
typeof nextStep[0] === 'number'
|
edgeTreatmentNode.node.init?.type !== 'PipeExpression')
|
||||||
) {
|
) {
|
||||||
callIndex = nextStep[0]
|
// Handle both standalone cases (assigned and unassigned)
|
||||||
}
|
const deleteResult = deleteTopLevelStatement(
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pipeExpressionPath) {
|
|
||||||
return new Error('PipeExpression not found in path')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (callIndex === null) {
|
|
||||||
return new Error('Failed to extract CallExpressionKw index')
|
|
||||||
}
|
|
||||||
// Retrieve the PipeExpression node
|
|
||||||
const pipeExpressionNode = getNodeFromPath<PipeExpression>(
|
|
||||||
astClone,
|
astClone,
|
||||||
pipeExpressionPath,
|
selection.codeRef.pathToNode
|
||||||
'PipeExpression'
|
|
||||||
)
|
)
|
||||||
if (err(pipeExpressionNode)) return pipeExpressionNode
|
if (err(deleteResult)) return deleteResult
|
||||||
|
return astClone
|
||||||
// Ensure that the PipeExpression.body is an array
|
} else {
|
||||||
if (!isArray(pipeExpressionNode.node.body)) {
|
const deleteResult = deleteNodeInExtrudePipe(
|
||||||
return new Error('PipeExpression body is not an array')
|
astClone,
|
||||||
}
|
selection.codeRef.pathToNode
|
||||||
|
|
||||||
// Remove the CallExpression at the specified index
|
|
||||||
pipeExpressionNode.node.body.splice(callIndex, 1)
|
|
||||||
|
|
||||||
// Remove VariableDeclarator if PipeExpression.body is empty
|
|
||||||
if (pipeExpressionNode.node.body.length === 0) {
|
|
||||||
const varDecPathStep = varDec.shallowPath[1]
|
|
||||||
if (!isArray(varDecPathStep) || typeof varDecPathStep[0] !== 'number') {
|
|
||||||
return new Error(
|
|
||||||
'Invalid shallowPath structure: expected a number at shallowPath[1][0]'
|
|
||||||
)
|
)
|
||||||
}
|
if (err(deleteResult)) return deleteResult
|
||||||
const varDecIndex: number = varDecPathStep[0]
|
|
||||||
astClone.body.splice(varDecIndex, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return astClone
|
return astClone
|
||||||
}
|
}
|
||||||
|
|
||||||
return Error('Delete fillets not implemented')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Edit Edge Treatment
|
// Edit Edge Treatment
|
||||||
@ -786,7 +682,7 @@ export async function editEdgeTreatment(
|
|||||||
edgeTreatmentCall.node.arguments[index] = newArg
|
edgeTreatmentCall.node.arguments[index] = newArg
|
||||||
}
|
}
|
||||||
|
|
||||||
let pathToEdgeTreatmentNode = selection?.codeRef?.pathToNode
|
const pathToEdgeTreatmentNode = selection?.codeRef?.pathToNode
|
||||||
|
|
||||||
return { modifiedAst, pathToEdgeTreatmentNode }
|
return { modifiedAst, pathToEdgeTreatmentNode }
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
import type { Node } from '@rust/kcl-lib/bindings/Node'
|
import type { Node } from '@rust/kcl-lib/bindings/Node'
|
||||||
|
|
||||||
import type { PathToNode, Program } from '@src/lang/wasm'
|
import type { PathToNode, Program } from '@src/lang/wasm'
|
||||||
import { locateExtrudeDeclarator } from '@src/lang/modifyAst/addEdgeTreatment'
|
import { locateVariableWithCallOrPipe } from '@src/lang/queryAst'
|
||||||
import { err } from '@src/lib/trap'
|
import { err } from '@src/lib/trap'
|
||||||
|
|
||||||
export function deleteNodeInExtrudePipe(
|
export function deleteNodeInExtrudePipe(
|
||||||
node: PathToNode,
|
ast: Node<Program>,
|
||||||
ast: Node<Program>
|
node: PathToNode
|
||||||
): Error | void {
|
): Error | void {
|
||||||
const pipeIndex = node.findIndex(([_, type]) => type === 'PipeExpression') + 1
|
const pipeIndex = node.findIndex(([_, type]) => type === 'PipeExpression') + 1
|
||||||
if (!(node[pipeIndex][0] && typeof node[pipeIndex][0] === 'number')) {
|
if (!(node[pipeIndex][0] && typeof node[pipeIndex][0] === 'number')) {
|
||||||
return new Error("Couldn't find node to delete in ast")
|
return new Error("Couldn't find node to delete in ast")
|
||||||
}
|
}
|
||||||
|
|
||||||
const lookup = locateExtrudeDeclarator(ast, node)
|
const lookup = locateVariableWithCallOrPipe(ast, node)
|
||||||
if (err(lookup)) {
|
if (err(lookup)) {
|
||||||
return lookup
|
return lookup
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lookup.extrudeDeclarator.init.type !== 'PipeExpression') {
|
if (lookup.variableDeclarator.init.type !== 'PipeExpression') {
|
||||||
return new Error("Couldn't find node to delete in looked up extrusion")
|
return new Error("Couldn't find node to delete in looked up extrusion")
|
||||||
}
|
}
|
||||||
|
|
||||||
lookup.extrudeDeclarator.init.body.splice(node[pipeIndex][0], 1)
|
lookup.variableDeclarator.init.body.splice(node[pipeIndex][0], 1)
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
createPipeExpression,
|
createPipeExpression,
|
||||||
createPipeSubstitution,
|
createPipeSubstitution,
|
||||||
} from '@src/lang/create'
|
} from '@src/lang/create'
|
||||||
import { locateExtrudeDeclarator } from '@src/lang/modifyAst/addEdgeTreatment'
|
import { locateVariableWithCallOrPipe } from '@src/lang/queryAst'
|
||||||
import type { PathToNode, Program } from '@src/lang/wasm'
|
import type { PathToNode, Program } from '@src/lang/wasm'
|
||||||
import { COMMAND_APPEARANCE_COLOR_DEFAULT } from '@src/lib/commandBarConfigs/modelingCommandConfig'
|
import { COMMAND_APPEARANCE_COLOR_DEFAULT } from '@src/lib/commandBarConfigs/modelingCommandConfig'
|
||||||
import { err } from '@src/lib/trap'
|
import { err } from '@src/lib/trap'
|
||||||
@ -23,13 +23,13 @@ export function setAppearance({
|
|||||||
}): Error | { modifiedAst: Node<Program>; pathToNode: PathToNode } {
|
}): Error | { modifiedAst: Node<Program>; pathToNode: PathToNode } {
|
||||||
const modifiedAst = structuredClone(ast)
|
const modifiedAst = structuredClone(ast)
|
||||||
|
|
||||||
// Locate the call (not necessarily an extrude here)
|
// Locate the call
|
||||||
const result = locateExtrudeDeclarator(modifiedAst, nodeToEdit)
|
const result = locateVariableWithCallOrPipe(modifiedAst, nodeToEdit)
|
||||||
if (err(result)) {
|
if (err(result)) {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
const declarator = result.extrudeDeclarator
|
const declarator = result.variableDeclarator
|
||||||
const call = createCallExpressionStdLibKw(
|
const call = createCallExpressionStdLibKw(
|
||||||
'appearance',
|
'appearance',
|
||||||
createPipeSubstitution(),
|
createPipeSubstitution(),
|
||||||
|
@ -1175,6 +1175,41 @@ export function getSketchSelectionsFromOperation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function locateVariableWithCallOrPipe(
|
||||||
|
ast: Program,
|
||||||
|
pathToNode: PathToNode
|
||||||
|
): { variableDeclarator: VariableDeclarator; shallowPath: PathToNode } | Error {
|
||||||
|
const variableDeclarationNode = getNodeFromPath<VariableDeclaration>(
|
||||||
|
ast,
|
||||||
|
pathToNode,
|
||||||
|
'VariableDeclaration'
|
||||||
|
)
|
||||||
|
if (err(variableDeclarationNode)) return variableDeclarationNode
|
||||||
|
|
||||||
|
const { node: variableDecl } = variableDeclarationNode
|
||||||
|
const variableDeclarator = variableDecl.declaration
|
||||||
|
if (!variableDeclarator) {
|
||||||
|
return new Error('Variable Declarator not found.')
|
||||||
|
}
|
||||||
|
|
||||||
|
const initializer = variableDeclarator?.init
|
||||||
|
if (!initializer) {
|
||||||
|
return new Error('Initializer not found.')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
initializer.type !== 'CallExpressionKw' &&
|
||||||
|
initializer.type !== 'PipeExpression'
|
||||||
|
) {
|
||||||
|
return new Error('Initializer must be a PipeExpression or CallExpressionKw')
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
variableDeclarator,
|
||||||
|
shallowPath: variableDeclarationNode.shallowPath,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function findImportNodeAndAlias(
|
export function findImportNodeAndAlias(
|
||||||
ast: Node<Program>,
|
ast: Node<Program>,
|
||||||
pathToNode: PathToNode
|
pathToNode: PathToNode
|
||||||
|
Reference in New Issue
Block a user