fix: updated the LiteralValue dereferencing and added some type narrowing helpers
This commit is contained in:
@ -6,6 +6,8 @@ import {
|
||||
ArrayExpression,
|
||||
BinaryExpression,
|
||||
ArtifactGraph,
|
||||
LiteralValue,
|
||||
NumericSuffix,
|
||||
} from './wasm'
|
||||
import { filterArtifacts } from 'lang/std/artifactGraph'
|
||||
import { isOverlap } from 'lib/utils'
|
||||
@ -69,3 +71,9 @@ export function isLiteral(e: any): e is Literal {
|
||||
export function isBinaryExpression(e: any): e is BinaryExpression {
|
||||
return e && e.type === 'BinaryExpression'
|
||||
}
|
||||
|
||||
export function isLiteralValueNotStringAndBoolean(
|
||||
e: any
|
||||
): e is { value: number; suffix: NumericSuffix } {
|
||||
return e && 'value' in e && 'suffix' in e
|
||||
}
|
||||
|
@ -90,6 +90,7 @@ export type { Literal } from '../wasm-lib/kcl/bindings/Literal'
|
||||
export type { LiteralValue } from '../wasm-lib/kcl/bindings/LiteralValue'
|
||||
export type { ArrayExpression } from '../wasm-lib/kcl/bindings/ArrayExpression'
|
||||
export type { SourceRange } from 'wasm-lib/kcl/bindings/SourceRange'
|
||||
export type { NumericSuffix } from 'wasm-lib/kcl/bindings/NumericSuffix'
|
||||
|
||||
export type SyntaxType =
|
||||
| 'Program'
|
||||
|
87
src/lib/rectangleTool.test.ts
Normal file
87
src/lib/rectangleTool.test.ts
Normal file
@ -0,0 +1,87 @@
|
||||
import { expect } from 'vitest'
|
||||
import {
|
||||
recast,
|
||||
assertParse,
|
||||
topLevelRange,
|
||||
VariableDeclaration,
|
||||
} from 'lang/wasm'
|
||||
import { updateCenterRectangleSketch } from './rectangleTool'
|
||||
import { getNodePathFromSourceRange } from 'lang/queryAstNodePathUtils'
|
||||
import { getNodeFromPath } from 'lang/queryAst'
|
||||
import { findUniqueName } from 'lang/modifyAst'
|
||||
import { err, trap } from './trap'
|
||||
|
||||
describe('library rectangleTool helper functions', () => {
|
||||
describe('updateCenterRectangleSketch', () => {
|
||||
// regression test for https://github.com/KittyCAD/modeling-app/issues/5157
|
||||
test('should update AST and source code', async () => {
|
||||
// Base source code that will be edited in place
|
||||
const sourceCode = `sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([120.37, 162.76], %)
|
||||
|> angledLine([0, 0], %, $rectangleSegmentA001)
|
||||
|> angledLine([segAng(rectangleSegmentA001) + 90, 0], %, $rectangleSegmentB001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001),
|
||||
-segLen(rectangleSegmentA001)
|
||||
], %, $rectangleSegmentC001)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)
|
||||
`
|
||||
// Create ast
|
||||
const _ast = assertParse(sourceCode)
|
||||
let ast = structuredClone(_ast)
|
||||
|
||||
// Find some nodes and paths to reference
|
||||
const sketchSnippet = `startProfileAt([120.37, 162.76], %)`
|
||||
const sketchRange = topLevelRange(
|
||||
sourceCode.indexOf(sketchSnippet),
|
||||
sourceCode.indexOf(sketchSnippet) + sketchSnippet.length
|
||||
)
|
||||
const sketchPathToNode = getNodePathFromSourceRange(ast, sketchRange)
|
||||
const _node = getNodeFromPath<VariableDeclaration>(
|
||||
ast,
|
||||
sketchPathToNode || [],
|
||||
'VariableDeclaration'
|
||||
)
|
||||
if (trap(_node)) return
|
||||
const sketchInit = _node.node?.declaration.init
|
||||
|
||||
// Hard code inputs that a user would have taken with their mouse
|
||||
const x = 40
|
||||
const y = 60
|
||||
const rectangleOrigin = [120, 180]
|
||||
const tags: [string, string, string] = [
|
||||
'rectangleSegmentA001',
|
||||
'rectangleSegmentB001',
|
||||
'rectangleSegmentC001',
|
||||
]
|
||||
|
||||
// Update the ast
|
||||
if (sketchInit.type === 'PipeExpression') {
|
||||
updateCenterRectangleSketch(
|
||||
sketchInit,
|
||||
x,
|
||||
y,
|
||||
tags[0],
|
||||
rectangleOrigin[0],
|
||||
rectangleOrigin[1]
|
||||
)
|
||||
}
|
||||
|
||||
// ast is edited in place from the updateCenterRectangleSketch
|
||||
const expectedSourceCode = `sketch001 = startSketchOn('XZ')
|
||||
|> startProfileAt([80, 120], %)
|
||||
|> angledLine([0, 80], %, $rectangleSegmentA001)
|
||||
|> angledLine([segAng(rectangleSegmentA001) + 90, 120], %, $rectangleSegmentB001)
|
||||
|> angledLine([
|
||||
segAng(rectangleSegmentA001),
|
||||
-segLen(rectangleSegmentA001)
|
||||
], %, $rectangleSegmentC001)
|
||||
|> lineTo([profileStartX(%), profileStartY(%)], %)
|
||||
|> close(%)
|
||||
`
|
||||
const recasted = recast(ast)
|
||||
expect(recasted).toEqual(expectedSourceCode)
|
||||
})
|
||||
})
|
||||
})
|
@ -8,13 +8,19 @@ import {
|
||||
createTagDeclarator,
|
||||
createUnaryExpression,
|
||||
} from 'lang/modifyAst'
|
||||
import { ArrayExpression, CallExpression, PipeExpression } from 'lang/wasm'
|
||||
import {
|
||||
ArrayExpression,
|
||||
CallExpression,
|
||||
PipeExpression,
|
||||
recast,
|
||||
} from 'lang/wasm'
|
||||
import { roundOff } from 'lib/utils'
|
||||
import {
|
||||
isCallExpression,
|
||||
isArrayExpression,
|
||||
isLiteral,
|
||||
isBinaryExpression,
|
||||
isLiteralValueNotStringAndBoolean,
|
||||
} from 'lang/util'
|
||||
|
||||
/**
|
||||
@ -140,6 +146,7 @@ export function updateCenterRectangleSketch(
|
||||
if (isArrayExpression(arrayExpression)) {
|
||||
const literal = arrayExpression.elements[0]
|
||||
if (isLiteral(literal)) {
|
||||
if (isLiteralValueNotStringAndBoolean(literal.value)) {
|
||||
callExpression.arguments[0] = createArrayExpression([
|
||||
createLiteral(literal.value.value),
|
||||
createLiteral(Math.abs(twoX)),
|
||||
@ -147,6 +154,7 @@ export function updateCenterRectangleSketch(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callExpression = pipeExpression.body[3]
|
||||
if (isCallExpression(callExpression)) {
|
||||
|
Reference in New Issue
Block a user