@ -2,6 +2,7 @@ import { useModelingContext } from 'hooks/useModelingContext'
|
||||
import { editorManager, kclManager } from 'lib/singletons'
|
||||
import { getNodeFromPath, getNodePathFromSourceRange } from 'lang/queryAst'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import { trap } from 'lib/trap'
|
||||
|
||||
export function AstExplorer() {
|
||||
const { context } = useModelingContext()
|
||||
@ -10,9 +11,12 @@ export function AstExplorer() {
|
||||
kclManager.ast,
|
||||
context.selectionRanges.codeBasedSelections?.[0]?.range
|
||||
)
|
||||
const node = getNodeFromPath(kclManager.ast, pathToNode).node
|
||||
const [filterKeys, setFilterKeys] = useState<string[]>(['start', 'end'])
|
||||
|
||||
const _node = getNodeFromPath(kclManager.ast, pathToNode)
|
||||
if (trap(_node)) return
|
||||
const node = _node
|
||||
|
||||
return (
|
||||
<div id="ast-explorer" className="relative">
|
||||
<div className="">
|
||||
|
@ -11,6 +11,7 @@ import { engineCommandManager, kclManager } from 'lib/singletons'
|
||||
import { useKclContext } from 'lang/KclProvider'
|
||||
import { useModelingContext } from 'hooks/useModelingContext'
|
||||
import { executeAst } from 'useStore'
|
||||
import { trap } from 'lib/trap'
|
||||
|
||||
export const AvailableVars = ({
|
||||
onVarClick,
|
||||
@ -141,6 +142,7 @@ export function useCalc({
|
||||
try {
|
||||
const code = `const __result__ = ${value}`
|
||||
const ast = parse(code)
|
||||
if (trap(ast)) return
|
||||
const _programMem: any = { root: {}, return: null }
|
||||
availableVarInfo.variables.forEach(({ key, value }) => {
|
||||
_programMem.root[key] = { type: 'userVal', value, __meta: [] }
|
||||
|
@ -24,7 +24,7 @@ export const CommandBar = () => {
|
||||
}, [pathname])
|
||||
|
||||
// Hook up keyboard shortcuts
|
||||
useHotkeyWrapper(['mod+k', 'mod+/'], () => {
|
||||
useHotkeyWrapper(['mod+k', 'ctrl+c'], () => {
|
||||
if (commandBarState.context.commands.length === 0) return
|
||||
if (commandBarState.matches('Closed')) {
|
||||
commandBarSend({ type: 'Open' })
|
||||
|
@ -1,6 +1,12 @@
|
||||
import { LanguageServerClient } from 'editor/plugins/lsp'
|
||||
import type * as LSP from 'vscode-languageserver-protocol'
|
||||
import React, { createContext, useMemo, useEffect, useContext } from 'react'
|
||||
import React, {
|
||||
createContext,
|
||||
useMemo,
|
||||
useEffect,
|
||||
useContext,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { FromServer, IntoServer } from 'editor/plugins/lsp/codec'
|
||||
import Client from '../editor/plugins/lsp/client'
|
||||
import { TEST, VITE_KC_API_BASE_URL } from 'env'
|
||||
@ -24,6 +30,7 @@ import { wasmUrl } from 'lang/wasm'
|
||||
import { PROJECT_ENTRYPOINT } from 'lib/constants'
|
||||
import { useNetworkContext } from 'hooks/useNetworkContext'
|
||||
import { NetworkHealthState } from 'hooks/useNetworkStatus'
|
||||
import { err, trap } from 'lib/trap'
|
||||
|
||||
function getWorkspaceFolders(): LSP.WorkspaceFolder[] {
|
||||
return []
|
||||
@ -76,6 +83,8 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
setIsCopilotLspServerReady: s.setIsCopilotLspServerReady,
|
||||
isStreamReady: s.isStreamReady,
|
||||
}))
|
||||
const [isLspReady, setIsLspReady] = useState(false)
|
||||
const [isCopilotReady, setIsCopilotReady] = useState(false)
|
||||
|
||||
const {
|
||||
auth,
|
||||
@ -111,14 +120,17 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
eventData: initEvent,
|
||||
})
|
||||
lspWorker.onmessage = function (e) {
|
||||
if (err(fromServer)) return
|
||||
fromServer.add(e.data)
|
||||
}
|
||||
|
||||
const intoServer: IntoServer = new IntoServer(LspWorker.Kcl, lspWorker)
|
||||
const fromServer: FromServer = FromServer.create()
|
||||
const fromServer: FromServer | Error = FromServer.create()
|
||||
if (err(fromServer)) return { lspClient: null }
|
||||
|
||||
const client = new Client(fromServer, intoServer)
|
||||
|
||||
setIsKclLspServerReady(true)
|
||||
setIsLspReady(true)
|
||||
|
||||
const lspClient = new LanguageServerClient({ client, name: LspWorker.Kcl })
|
||||
return { lspClient }
|
||||
@ -185,14 +197,17 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
eventData: initEvent,
|
||||
})
|
||||
lspWorker.onmessage = function (e) {
|
||||
if (err(fromServer)) return
|
||||
fromServer.add(e.data)
|
||||
}
|
||||
|
||||
const intoServer: IntoServer = new IntoServer(LspWorker.Copilot, lspWorker)
|
||||
const fromServer: FromServer = FromServer.create()
|
||||
const fromServer: FromServer | Error = FromServer.create()
|
||||
if (err(fromServer)) return { lspClient: null }
|
||||
|
||||
const client = new Client(fromServer, intoServer)
|
||||
|
||||
setIsCopilotLspServerReady(true)
|
||||
setIsCopilotReady(true)
|
||||
|
||||
const lspClient = new LanguageServerClient({
|
||||
client,
|
||||
@ -230,6 +245,13 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
lspClients.push(copilotLspClient)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setIsKclLspServerReady(isLspReady)
|
||||
}, [isLspReady])
|
||||
useEffect(() => {
|
||||
setIsCopilotLspServerReady(isCopilotReady)
|
||||
}, [isCopilotReady])
|
||||
|
||||
const onProjectClose = (
|
||||
file: FileEntry | null,
|
||||
projectPath: string | null,
|
||||
|
@ -29,7 +29,6 @@ import {
|
||||
applyConstraintAngleBetween,
|
||||
} from './Toolbar/SetAngleBetween'
|
||||
import { applyConstraintAngleLength } from './Toolbar/setAngleLength'
|
||||
import { pathMapToSelections } from 'lang/util'
|
||||
import { useStore } from 'useStore'
|
||||
import {
|
||||
Selections,
|
||||
@ -37,6 +36,7 @@ import {
|
||||
handleSelectionBatch,
|
||||
isSelectionLastLine,
|
||||
isSketchPipe,
|
||||
updateSelections,
|
||||
} from 'lib/selections'
|
||||
import { applyConstraintIntersect } from './Toolbar/Intersect'
|
||||
import { applyConstraintAbsDistance } from './Toolbar/SetAbsDistance'
|
||||
@ -77,6 +77,7 @@ import { letEngineAnimateAndSyncCamAfter } from 'clientSideScene/CameraControls'
|
||||
import { getVarNameModal } from 'hooks/useToolbarGuards'
|
||||
import useHotkeyWrapper from 'lib/hotkeyWrapper'
|
||||
import { uuidv4 } from 'lib/utils'
|
||||
import { err, trap } from 'lib/trap'
|
||||
|
||||
type MachineContext<T extends AnyStateMachine> = {
|
||||
state: StateFrom<T>
|
||||
@ -459,12 +460,17 @@ export const ModelingMachineProvider = ({
|
||||
|
||||
return canExtrudeSelection(selectionRanges)
|
||||
},
|
||||
'Sketch is empty': ({ sketchDetails }) =>
|
||||
getNodeFromPath<VariableDeclaration>(
|
||||
'Sketch is empty': ({ sketchDetails }) => {
|
||||
const node = getNodeFromPath<VariableDeclaration>(
|
||||
kclManager.ast,
|
||||
sketchDetails?.sketchPathToNode || [],
|
||||
'VariableDeclaration'
|
||||
)?.node?.declarations?.[0]?.init.type !== 'PipeExpression',
|
||||
)
|
||||
// This should not be returning false, and it should be caught
|
||||
// but we need to simulate old behavior to move on.
|
||||
if (err(node)) return false
|
||||
return node.node?.declarations?.[0]?.init.type !== 'PipeExpression'
|
||||
},
|
||||
'Selection is on face': ({ selectionRanges }, { data }) => {
|
||||
if (data?.forceNewSketch) return false
|
||||
if (!isSingleCursorInPipe(selectionRanges, kclManager.ast))
|
||||
@ -507,14 +513,16 @@ export const ModelingMachineProvider = ({
|
||||
},
|
||||
'animate-to-face': async (_, { data }) => {
|
||||
if (data.type === 'extrudeFace') {
|
||||
const { modifiedAst, pathToNode: pathToNewSketchNode } =
|
||||
sketchOnExtrudedFace(
|
||||
kclManager.ast,
|
||||
data.sketchPathToNode,
|
||||
data.extrudePathToNode,
|
||||
kclManager.programMemory,
|
||||
data.cap
|
||||
)
|
||||
const sketched = sketchOnExtrudedFace(
|
||||
kclManager.ast,
|
||||
data.sketchPathToNode,
|
||||
data.extrudePathToNode,
|
||||
kclManager.programMemory,
|
||||
data.cap
|
||||
)
|
||||
if (trap(sketched)) return Promise.reject(sketched)
|
||||
const { modifiedAst, pathToNode: pathToNewSketchNode } = sketched
|
||||
|
||||
await kclManager.executeAstMock(modifiedAst)
|
||||
|
||||
await letEngineAnimateAndSyncCamAfter(
|
||||
@ -535,10 +543,12 @@ export const ModelingMachineProvider = ({
|
||||
)
|
||||
await kclManager.updateAst(modifiedAst, false)
|
||||
sceneInfra.camControls.syncDirection = 'clientToEngine'
|
||||
|
||||
await letEngineAnimateAndSyncCamAfter(
|
||||
engineCommandManager,
|
||||
data.planeId
|
||||
)
|
||||
|
||||
return {
|
||||
sketchPathToNode: pathToNode,
|
||||
zAxis: data.zAxis,
|
||||
@ -576,25 +586,29 @@ export const ModelingMachineProvider = ({
|
||||
selectionRanges,
|
||||
})
|
||||
const _modifiedAst = parse(recast(modifiedAst))
|
||||
if (!sketchDetails) throw new Error('No sketch details')
|
||||
if (!sketchDetails)
|
||||
return Promise.reject(new Error('No sketch details'))
|
||||
const updatedPathToNode = updatePathToNodeFromMap(
|
||||
sketchDetails.sketchPathToNode,
|
||||
pathToNodeMap
|
||||
)
|
||||
await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
pathToNodeMap,
|
||||
selectionRanges,
|
||||
updatedAst.newAst
|
||||
)
|
||||
if (err(selection)) return Promise.reject(selection)
|
||||
return {
|
||||
selectionType: 'completeSelection',
|
||||
selection: pathMapToSelections(
|
||||
kclManager.ast,
|
||||
selectionRanges,
|
||||
pathToNodeMap
|
||||
),
|
||||
selection,
|
||||
updatedPathToNode,
|
||||
}
|
||||
},
|
||||
@ -608,25 +622,29 @@ export const ModelingMachineProvider = ({
|
||||
selectionRanges,
|
||||
})
|
||||
const _modifiedAst = parse(recast(modifiedAst))
|
||||
if (!sketchDetails) throw new Error('No sketch details')
|
||||
if (!sketchDetails)
|
||||
return Promise.reject(new Error('No sketch details'))
|
||||
const updatedPathToNode = updatePathToNodeFromMap(
|
||||
sketchDetails.sketchPathToNode,
|
||||
pathToNodeMap
|
||||
)
|
||||
await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
pathToNodeMap,
|
||||
selectionRanges,
|
||||
updatedAst.newAst
|
||||
)
|
||||
if (err(selection)) return Promise.reject(selection)
|
||||
return {
|
||||
selectionType: 'completeSelection',
|
||||
selection: pathMapToSelections(
|
||||
kclManager.ast,
|
||||
selectionRanges,
|
||||
pathToNodeMap
|
||||
),
|
||||
selection,
|
||||
updatedPathToNode,
|
||||
}
|
||||
},
|
||||
@ -634,9 +652,11 @@ export const ModelingMachineProvider = ({
|
||||
selectionRanges,
|
||||
sketchDetails,
|
||||
}): Promise<SetSelections> => {
|
||||
const { modifiedAst, pathToNodeMap } = await (angleBetweenInfo({
|
||||
const info = angleBetweenInfo({
|
||||
selectionRanges,
|
||||
}).enabled
|
||||
})
|
||||
if (err(info)) return Promise.reject(info)
|
||||
const { modifiedAst, pathToNodeMap } = await (info.enabled
|
||||
? applyConstraintAngleBetween({
|
||||
selectionRanges,
|
||||
})
|
||||
@ -645,25 +665,31 @@ export const ModelingMachineProvider = ({
|
||||
angleOrLength: 'setAngle',
|
||||
}))
|
||||
const _modifiedAst = parse(recast(modifiedAst))
|
||||
if (!sketchDetails) throw new Error('No sketch details')
|
||||
if (err(_modifiedAst)) return Promise.reject(_modifiedAst)
|
||||
|
||||
if (!sketchDetails)
|
||||
return Promise.reject(new Error('No sketch details'))
|
||||
const updatedPathToNode = updatePathToNodeFromMap(
|
||||
sketchDetails.sketchPathToNode,
|
||||
pathToNodeMap
|
||||
)
|
||||
await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
pathToNodeMap,
|
||||
selectionRanges,
|
||||
updatedAst.newAst
|
||||
)
|
||||
if (err(selection)) return Promise.reject(selection)
|
||||
return {
|
||||
selectionType: 'completeSelection',
|
||||
selection: pathMapToSelections(
|
||||
_modifiedAst,
|
||||
selectionRanges,
|
||||
pathToNodeMap
|
||||
),
|
||||
selection,
|
||||
updatedPathToNode,
|
||||
}
|
||||
},
|
||||
@ -674,25 +700,29 @@ export const ModelingMachineProvider = ({
|
||||
const { modifiedAst, pathToNodeMap } =
|
||||
await applyConstraintAngleLength({ selectionRanges })
|
||||
const _modifiedAst = parse(recast(modifiedAst))
|
||||
if (!sketchDetails) throw new Error('No sketch details')
|
||||
if (!sketchDetails)
|
||||
return Promise.reject(new Error('No sketch details'))
|
||||
const updatedPathToNode = updatePathToNodeFromMap(
|
||||
sketchDetails.sketchPathToNode,
|
||||
pathToNodeMap
|
||||
)
|
||||
await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
pathToNodeMap,
|
||||
selectionRanges,
|
||||
updatedAst.newAst
|
||||
)
|
||||
if (err(selection)) return Promise.reject(selection)
|
||||
return {
|
||||
selectionType: 'completeSelection',
|
||||
selection: pathMapToSelections(
|
||||
kclManager.ast,
|
||||
selectionRanges,
|
||||
pathToNodeMap
|
||||
),
|
||||
selection,
|
||||
updatedPathToNode,
|
||||
}
|
||||
},
|
||||
@ -706,25 +736,29 @@ export const ModelingMachineProvider = ({
|
||||
}
|
||||
)
|
||||
const _modifiedAst = parse(recast(modifiedAst))
|
||||
if (!sketchDetails) throw new Error('No sketch details')
|
||||
if (!sketchDetails)
|
||||
return Promise.reject(new Error('No sketch details'))
|
||||
const updatedPathToNode = updatePathToNodeFromMap(
|
||||
sketchDetails.sketchPathToNode,
|
||||
pathToNodeMap
|
||||
)
|
||||
await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
pathToNodeMap,
|
||||
selectionRanges,
|
||||
updatedAst.newAst
|
||||
)
|
||||
if (err(selection)) return Promise.reject(selection)
|
||||
return {
|
||||
selectionType: 'completeSelection',
|
||||
selection: pathMapToSelections(
|
||||
kclManager.ast,
|
||||
selectionRanges,
|
||||
pathToNodeMap
|
||||
),
|
||||
selection,
|
||||
updatedPathToNode,
|
||||
}
|
||||
},
|
||||
@ -738,25 +772,29 @@ export const ModelingMachineProvider = ({
|
||||
selectionRanges,
|
||||
})
|
||||
const _modifiedAst = parse(recast(modifiedAst))
|
||||
if (!sketchDetails) throw new Error('No sketch details')
|
||||
if (!sketchDetails)
|
||||
return Promise.reject(new Error('No sketch details'))
|
||||
const updatedPathToNode = updatePathToNodeFromMap(
|
||||
sketchDetails.sketchPathToNode,
|
||||
pathToNodeMap
|
||||
)
|
||||
await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
pathToNodeMap,
|
||||
selectionRanges,
|
||||
updatedAst.newAst
|
||||
)
|
||||
if (err(selection)) return Promise.reject(selection)
|
||||
return {
|
||||
selectionType: 'completeSelection',
|
||||
selection: pathMapToSelections(
|
||||
kclManager.ast,
|
||||
selectionRanges,
|
||||
pathToNodeMap
|
||||
),
|
||||
selection,
|
||||
updatedPathToNode,
|
||||
}
|
||||
},
|
||||
@ -770,48 +808,77 @@ export const ModelingMachineProvider = ({
|
||||
selectionRanges,
|
||||
})
|
||||
const _modifiedAst = parse(recast(modifiedAst))
|
||||
if (!sketchDetails) throw new Error('No sketch details')
|
||||
if (!sketchDetails)
|
||||
return Promise.reject(new Error('No sketch details'))
|
||||
const updatedPathToNode = updatePathToNodeFromMap(
|
||||
sketchDetails.sketchPathToNode,
|
||||
pathToNodeMap
|
||||
)
|
||||
await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
updatedPathToNode,
|
||||
_modifiedAst,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
)
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
pathToNodeMap,
|
||||
selectionRanges,
|
||||
updatedAst.newAst
|
||||
)
|
||||
if (err(selection)) return Promise.reject(selection)
|
||||
return {
|
||||
selectionType: 'completeSelection',
|
||||
selection: pathMapToSelections(
|
||||
kclManager.ast,
|
||||
selectionRanges,
|
||||
pathToNodeMap
|
||||
),
|
||||
selection,
|
||||
updatedPathToNode,
|
||||
}
|
||||
},
|
||||
'Get convert to variable info': async ({ sketchDetails }, { data }) => {
|
||||
if (!sketchDetails) return []
|
||||
'Get convert to variable info': async (
|
||||
{ sketchDetails, selectionRanges },
|
||||
{ data }
|
||||
): Promise<SetSelections> => {
|
||||
if (!sketchDetails)
|
||||
return Promise.reject(new Error('No sketch details'))
|
||||
const { variableName } = await getVarNameModal({
|
||||
valueName: data.variableName || 'var',
|
||||
})
|
||||
let parsed = parse(recast(kclManager.ast))
|
||||
if (trap(parsed)) return Promise.reject(parsed)
|
||||
parsed = parsed as Program
|
||||
|
||||
const { modifiedAst: _modifiedAst, pathToReplacedNode } =
|
||||
moveValueIntoNewVariablePath(
|
||||
parse(recast(kclManager.ast)),
|
||||
parsed,
|
||||
kclManager.programMemory,
|
||||
data.pathToNode,
|
||||
variableName
|
||||
)
|
||||
await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
parsed = parse(recast(_modifiedAst))
|
||||
if (trap(parsed)) return Promise.reject(parsed)
|
||||
parsed = parsed as Program
|
||||
if (!pathToReplacedNode)
|
||||
return Promise.reject(new Error('No path to replaced node'))
|
||||
|
||||
const updatedAst = await sceneEntitiesManager.updateAstAndRejigSketch(
|
||||
pathToReplacedNode || [],
|
||||
parse(recast(_modifiedAst)),
|
||||
parsed,
|
||||
sketchDetails.zAxis,
|
||||
sketchDetails.yAxis,
|
||||
sketchDetails.origin
|
||||
)
|
||||
return pathToReplacedNode || sketchDetails.sketchPathToNode
|
||||
if (err(updatedAst)) return Promise.reject(updatedAst)
|
||||
const selection = updateSelections(
|
||||
{ 0: pathToReplacedNode },
|
||||
selectionRanges,
|
||||
updatedAst.newAst
|
||||
)
|
||||
if (err(selection)) return Promise.reject(selection)
|
||||
return {
|
||||
selectionType: 'completeSelection',
|
||||
selection,
|
||||
updatedPathToNode: pathToReplacedNode,
|
||||
}
|
||||
},
|
||||
},
|
||||
devTools: true,
|
||||
|
@ -1,10 +1,11 @@
|
||||
import toast from 'react-hot-toast'
|
||||
import ReactJson from 'react-json-view'
|
||||
import { useMemo } from 'react'
|
||||
import { ProgramMemory, Path, ExtrudeSurface } from 'lang/wasm'
|
||||
import { useKclContext } from 'lang/KclProvider'
|
||||
import { useResolvedTheme } from 'hooks/useResolvedTheme'
|
||||
import { ActionButton } from 'components/ActionButton'
|
||||
import toast from 'react-hot-toast'
|
||||
import { trap } from 'lib/trap'
|
||||
import Tooltip from 'components/Tooltip'
|
||||
import { useModelingContext } from 'hooks/useModelingContext'
|
||||
|
||||
@ -13,12 +14,12 @@ export const MemoryPaneMenu = () => {
|
||||
|
||||
function copyProgramMemoryToClipboard() {
|
||||
if (globalThis && 'navigator' in globalThis) {
|
||||
try {
|
||||
navigator.clipboard.writeText(JSON.stringify(programMemory))
|
||||
toast.success('Program memory copied to clipboard')
|
||||
} catch (e) {
|
||||
toast.error('Failed to copy program memory to clipboard')
|
||||
}
|
||||
navigator.clipboard
|
||||
.writeText(JSON.stringify(programMemory))
|
||||
.then(() => toast.success('Program memory copied to clipboard'))
|
||||
.catch((e) =>
|
||||
trap(new Error('Failed to copy program memory to clipboard'))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,28 +10,46 @@ import {
|
||||
transformSecondarySketchLinesTagFirst,
|
||||
getTransformInfos,
|
||||
PathToNodeMap,
|
||||
TransformInfo,
|
||||
} from '../../lang/std/sketchcombos'
|
||||
import { kclManager } from 'lib/singletons'
|
||||
import { err } from 'lib/trap'
|
||||
|
||||
export function equalAngleInfo({
|
||||
selectionRanges,
|
||||
}: {
|
||||
selectionRanges: Selections
|
||||
}) {
|
||||
}):
|
||||
| {
|
||||
transforms: TransformInfo[]
|
||||
enabled: boolean
|
||||
}
|
||||
| Error {
|
||||
const paths = selectionRanges.codeBasedSelections.map(({ range }) =>
|
||||
getNodePathFromSourceRange(kclManager.ast, range)
|
||||
)
|
||||
const nodes = paths.map(
|
||||
(pathToNode) => getNodeFromPath<Value>(kclManager.ast, pathToNode).node
|
||||
)
|
||||
const varDecs = paths.map(
|
||||
(pathToNode) =>
|
||||
getNodeFromPath<VariableDeclarator>(
|
||||
kclManager.ast,
|
||||
pathToNode,
|
||||
'VariableDeclarator'
|
||||
)?.node
|
||||
)
|
||||
const _nodes = paths.map((pathToNode) => {
|
||||
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
|
||||
if (err(tmp)) return tmp
|
||||
return tmp.node
|
||||
})
|
||||
const _err1 = _nodes.find(err)
|
||||
if (err(_err1)) return _err1
|
||||
const nodes = _nodes as Value[]
|
||||
|
||||
const _varDecs = paths.map((pathToNode) => {
|
||||
const tmp = getNodeFromPath<VariableDeclarator>(
|
||||
kclManager.ast,
|
||||
pathToNode,
|
||||
'VariableDeclarator'
|
||||
)
|
||||
if (err(tmp)) return tmp
|
||||
return tmp.node
|
||||
})
|
||||
const _err2 = _varDecs.find(err)
|
||||
if (err(_err2)) return _err2
|
||||
const varDecs = _varDecs as VariableDeclarator[]
|
||||
|
||||
const primaryLine = varDecs[0]
|
||||
const secondaryVarDecs = varDecs.slice(1)
|
||||
const isOthersLinkedToPrimary = secondaryVarDecs.every((secondary) =>
|
||||
@ -51,6 +69,7 @@ export function equalAngleInfo({
|
||||
kclManager.ast,
|
||||
'equalAngle'
|
||||
)
|
||||
if (err(transforms)) return transforms
|
||||
|
||||
const enabled =
|
||||
!!secondaryVarDecs.length &&
|
||||
@ -64,16 +83,24 @@ export function applyConstraintEqualAngle({
|
||||
selectionRanges,
|
||||
}: {
|
||||
selectionRanges: Selections
|
||||
}): {
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
} {
|
||||
const { transforms } = equalAngleInfo({ selectionRanges })
|
||||
const { modifiedAst, pathToNodeMap } = transformSecondarySketchLinesTagFirst({
|
||||
}):
|
||||
| {
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
}
|
||||
| Error {
|
||||
const info = equalAngleInfo({ selectionRanges })
|
||||
if (err(info)) return info
|
||||
const { transforms } = info
|
||||
|
||||
const transform = transformSecondarySketchLinesTagFirst({
|
||||
ast: kclManager.ast,
|
||||
selectionRanges,
|
||||
transformInfos: transforms,
|
||||
programMemory: kclManager.programMemory,
|
||||
})
|
||||
if (err(transform)) return transform
|
||||
const { modifiedAst, pathToNodeMap } = transform
|
||||
|
||||
return { modifiedAst, pathToNodeMap }
|
||||
}
|
||||
|
@ -10,28 +10,46 @@ import {
|
||||
transformSecondarySketchLinesTagFirst,
|
||||
getTransformInfos,
|
||||
PathToNodeMap,
|
||||
TransformInfo,
|
||||
} from '../../lang/std/sketchcombos'
|
||||
import { kclManager } from 'lib/singletons'
|
||||
import { err } from 'lib/trap'
|
||||
|
||||
export function setEqualLengthInfo({
|
||||
selectionRanges,
|
||||
}: {
|
||||
selectionRanges: Selections
|
||||
}) {
|
||||
}):
|
||||
| {
|
||||
transforms: TransformInfo[]
|
||||
enabled: boolean
|
||||
}
|
||||
| Error {
|
||||
const paths = selectionRanges.codeBasedSelections.map(({ range }) =>
|
||||
getNodePathFromSourceRange(kclManager.ast, range)
|
||||
)
|
||||
const nodes = paths.map(
|
||||
(pathToNode) => getNodeFromPath<Value>(kclManager.ast, pathToNode).node
|
||||
)
|
||||
const varDecs = paths.map(
|
||||
(pathToNode) =>
|
||||
getNodeFromPath<VariableDeclarator>(
|
||||
kclManager.ast,
|
||||
pathToNode,
|
||||
'VariableDeclarator'
|
||||
)?.node
|
||||
)
|
||||
const _nodes = paths.map((pathToNode) => {
|
||||
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
|
||||
if (err(tmp)) return tmp
|
||||
return tmp.node
|
||||
})
|
||||
const _err1 = _nodes.find(err)
|
||||
if (err(_err1)) return _err1
|
||||
const nodes = _nodes as Value[]
|
||||
|
||||
const _varDecs = paths.map((pathToNode) => {
|
||||
const tmp = getNodeFromPath<VariableDeclarator>(
|
||||
kclManager.ast,
|
||||
pathToNode,
|
||||
'VariableDeclarator'
|
||||
)
|
||||
if (err(tmp)) return tmp
|
||||
return tmp.node
|
||||
})
|
||||
const _err2 = _varDecs.find(err)
|
||||
if (err(_err2)) return _err2
|
||||
const varDecs = _varDecs as VariableDeclarator[]
|
||||
|
||||
const primaryLine = varDecs[0]
|
||||
const secondaryVarDecs = varDecs.slice(1)
|
||||
const isOthersLinkedToPrimary = secondaryVarDecs.every((secondary) =>
|
||||
@ -51,6 +69,7 @@ export function setEqualLengthInfo({
|
||||
kclManager.ast,
|
||||
'equalLength'
|
||||
)
|
||||
if (err(transforms)) return transforms
|
||||
|
||||
const enabled =
|
||||
!!secondaryVarDecs.length &&
|
||||
@ -65,16 +84,24 @@ export function applyConstraintEqualLength({
|
||||
selectionRanges,
|
||||
}: {
|
||||
selectionRanges: Selections
|
||||
}): {
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
} {
|
||||
const { transforms } = setEqualLengthInfo({ selectionRanges })
|
||||
const { modifiedAst, pathToNodeMap } = transformSecondarySketchLinesTagFirst({
|
||||
}):
|
||||
| {
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
}
|
||||
| Error {
|
||||
const info = setEqualLengthInfo({ selectionRanges })
|
||||
if (err(info)) return info
|
||||
const { transforms } = info
|
||||
|
||||
const transform = transformSecondarySketchLinesTagFirst({
|
||||
ast: kclManager.ast,
|
||||
selectionRanges,
|
||||
transformInfos: transforms,
|
||||
programMemory: kclManager.programMemory,
|
||||
})
|
||||
if (err(transform)) return transform
|
||||
const { modifiedAst, pathToNodeMap } = transform
|
||||
|
||||
return { modifiedAst, pathToNodeMap }
|
||||
}
|
||||
|
@ -9,19 +9,32 @@ import {
|
||||
PathToNodeMap,
|
||||
getTransformInfos,
|
||||
transformAstSketchLines,
|
||||
TransformInfo,
|
||||
} from '../../lang/std/sketchcombos'
|
||||
import { kclManager } from 'lib/singletons'
|
||||
import { err } from 'lib/trap'
|
||||
|
||||
export function horzVertInfo(
|
||||
selectionRanges: Selections,
|
||||
horOrVert: 'vertical' | 'horizontal'
|
||||
) {
|
||||
):
|
||||
| {
|
||||
transforms: TransformInfo[]
|
||||
enabled: boolean
|
||||
}
|
||||
| Error {
|
||||
const paths = selectionRanges.codeBasedSelections.map(({ range }) =>
|
||||
getNodePathFromSourceRange(kclManager.ast, range)
|
||||
)
|
||||
const nodes = paths.map(
|
||||
(pathToNode) => getNodeFromPath<Value>(kclManager.ast, pathToNode).node
|
||||
)
|
||||
const _nodes = paths.map((pathToNode) => {
|
||||
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
|
||||
if (err(tmp)) return tmp
|
||||
return tmp.node
|
||||
})
|
||||
const _err1 = _nodes.find(err)
|
||||
if (err(_err1)) return _err1
|
||||
const nodes = _nodes as Value[]
|
||||
|
||||
const isAllTooltips = nodes.every(
|
||||
(node) =>
|
||||
node?.type === 'CallExpression' &&
|
||||
@ -33,6 +46,8 @@ export function horzVertInfo(
|
||||
kclManager.ast,
|
||||
horOrVert
|
||||
)
|
||||
if (err(theTransforms)) return theTransforms
|
||||
|
||||
const _enableHorz = isAllTooltips && theTransforms.every(Boolean)
|
||||
return { enabled: _enableHorz, transforms: theTransforms }
|
||||
}
|
||||
@ -42,11 +57,16 @@ export function applyConstraintHorzVert(
|
||||
horOrVert: 'vertical' | 'horizontal',
|
||||
ast: Program,
|
||||
programMemory: ProgramMemory
|
||||
): {
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
} {
|
||||
const transformInfos = horzVertInfo(selectionRanges, horOrVert).transforms
|
||||
):
|
||||
| {
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
}
|
||||
| Error {
|
||||
const info = horzVertInfo(selectionRanges, horOrVert)
|
||||
if (err(info)) return info
|
||||
const transformInfos = info.transforms
|
||||
|
||||
return transformAstSketchLines({
|
||||
ast,
|
||||
selectionRanges,
|
||||
|
@ -11,11 +11,13 @@ import {
|
||||
transformSecondarySketchLinesTagFirst,
|
||||
getTransformInfos,
|
||||
PathToNodeMap,
|
||||
TransformInfo,
|
||||
} from '../../lang/std/sketchcombos'
|
||||
import { GetInfoModal, createInfoModal } from '../SetHorVertDistanceModal'
|
||||
import { createVariableDeclaration } from '../../lang/modifyAst'
|
||||
import { removeDoubleNegatives } from '../AvailableVarsHelpers'
|
||||
import { kclManager } from 'lib/singletons'
|
||||
import { err } from 'lib/trap'
|
||||
|
||||
const getModalInfo = createInfoModal(GetInfoModal)
|
||||
|
||||
@ -23,7 +25,13 @@ export function intersectInfo({
|
||||
selectionRanges,
|
||||
}: {
|
||||
selectionRanges: Selections
|
||||
}) {
|
||||
}):
|
||||
| {
|
||||
transforms: TransformInfo[]
|
||||
enabled: boolean
|
||||
forcedSelectionRanges: Selections
|
||||
}
|
||||
| Error {
|
||||
if (selectionRanges.codeBasedSelections.length < 2) {
|
||||
return {
|
||||
enabled: false,
|
||||
@ -40,6 +48,8 @@ export function intersectInfo({
|
||||
selectionRanges.codeBasedSelections[0],
|
||||
selectionRanges.codeBasedSelections[1]
|
||||
)
|
||||
if (err(previousSegment)) return previousSegment
|
||||
|
||||
const shouldUsePreviousSegment =
|
||||
selectionRanges.codeBasedSelections?.[1]?.type !== 'line-end' &&
|
||||
previousSegment &&
|
||||
@ -61,17 +71,28 @@ export function intersectInfo({
|
||||
const paths = _forcedSelectionRanges.codeBasedSelections.map(({ range }) =>
|
||||
getNodePathFromSourceRange(kclManager.ast, range)
|
||||
)
|
||||
const nodes = paths.map(
|
||||
(pathToNode) => getNodeFromPath<Value>(kclManager.ast, pathToNode).node
|
||||
)
|
||||
const varDecs = paths.map(
|
||||
(pathToNode) =>
|
||||
getNodeFromPath<VariableDeclarator>(
|
||||
kclManager.ast,
|
||||
pathToNode,
|
||||
'VariableDeclarator'
|
||||
)?.node
|
||||
)
|
||||
const _nodes = paths.map((pathToNode) => {
|
||||
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
|
||||
if (err(tmp)) return tmp
|
||||
return tmp.node
|
||||
})
|
||||
const _err1 = _nodes.find(err)
|
||||
if (err(_err1)) return _err1
|
||||
const nodes = _nodes as Value[]
|
||||
|
||||
const _varDecs = paths.map((pathToNode) => {
|
||||
const tmp = getNodeFromPath<VariableDeclarator>(
|
||||
kclManager.ast,
|
||||
pathToNode,
|
||||
'VariableDeclarator'
|
||||
)
|
||||
if (err(tmp)) return tmp
|
||||
return tmp.node
|
||||
})
|
||||
const _err2 = _varDecs.find(err)
|
||||
if (err(_err2)) return _err2
|
||||
const varDecs = _varDecs as VariableDeclarator[]
|
||||
|
||||
const primaryLine = varDecs[0]
|
||||
const secondaryVarDecs = varDecs.slice(1)
|
||||
const isOthersLinkedToPrimary = secondaryVarDecs.every((secondary) =>
|
||||
@ -117,16 +138,22 @@ export async function applyConstraintIntersect({
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
}> {
|
||||
const { transforms, forcedSelectionRanges } = intersectInfo({
|
||||
const info = intersectInfo({
|
||||
selectionRanges,
|
||||
})
|
||||
if (err(info)) return Promise.reject(info)
|
||||
const { transforms, forcedSelectionRanges } = info
|
||||
|
||||
const transform1 = transformSecondarySketchLinesTagFirst({
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges: forcedSelectionRanges,
|
||||
transformInfos: transforms,
|
||||
programMemory: kclManager.programMemory,
|
||||
})
|
||||
if (err(transform1)) return Promise.reject(transform1)
|
||||
const { modifiedAst, tagInfo, valueUsedInTransform, pathToNodeMap } =
|
||||
transformSecondarySketchLinesTagFirst({
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges: forcedSelectionRanges,
|
||||
transformInfos: transforms,
|
||||
programMemory: kclManager.programMemory,
|
||||
})
|
||||
transform1
|
||||
|
||||
const {
|
||||
segName,
|
||||
value,
|
||||
@ -156,15 +183,18 @@ export async function applyConstraintIntersect({
|
||||
sign,
|
||||
variableName
|
||||
)
|
||||
const transform2 = transformSecondarySketchLinesTagFirst({
|
||||
ast: kclManager.ast,
|
||||
selectionRanges: forcedSelectionRanges,
|
||||
transformInfos: transforms,
|
||||
programMemory: kclManager.programMemory,
|
||||
forceSegName: segName,
|
||||
forceValueUsedInTransform: finalValue,
|
||||
})
|
||||
if (err(transform2)) return Promise.reject(transform2)
|
||||
const { modifiedAst: _modifiedAst, pathToNodeMap: _pathToNodeMap } =
|
||||
transformSecondarySketchLinesTagFirst({
|
||||
ast: kclManager.ast,
|
||||
selectionRanges: forcedSelectionRanges,
|
||||
transformInfos: transforms,
|
||||
programMemory: kclManager.programMemory,
|
||||
forceSegName: segName,
|
||||
forceValueUsedInTransform: finalValue,
|
||||
})
|
||||
transform2
|
||||
|
||||
if (variableName) {
|
||||
const newBody = [..._modifiedAst.body]
|
||||
newBody.splice(
|
||||
|
@ -9,8 +9,10 @@ import {
|
||||
PathToNodeMap,
|
||||
getRemoveConstraintsTransforms,
|
||||
transformAstSketchLines,
|
||||
TransformInfo,
|
||||
} from '../../lang/std/sketchcombos'
|
||||
import { kclManager } from 'lib/singletons'
|
||||
import { err } from 'lib/trap'
|
||||
|
||||
export function removeConstrainingValuesInfo({
|
||||
selectionRanges,
|
||||
@ -18,15 +20,27 @@ export function removeConstrainingValuesInfo({
|
||||
}: {
|
||||
selectionRanges: Selections
|
||||
pathToNodes?: Array<PathToNode>
|
||||
}) {
|
||||
}):
|
||||
| {
|
||||
transforms: TransformInfo[]
|
||||
enabled: boolean
|
||||
updatedSelectionRanges: Selections
|
||||
}
|
||||
| Error {
|
||||
const paths =
|
||||
pathToNodes ||
|
||||
selectionRanges.codeBasedSelections.map(({ range }) =>
|
||||
getNodePathFromSourceRange(kclManager.ast, range)
|
||||
)
|
||||
const nodes = paths.map(
|
||||
(pathToNode) => getNodeFromPath<Value>(kclManager.ast, pathToNode).node
|
||||
)
|
||||
const _nodes = paths.map((pathToNode) => {
|
||||
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
|
||||
if (err(tmp)) return tmp
|
||||
return tmp.node
|
||||
})
|
||||
const _err1 = _nodes.find(err)
|
||||
if (err(_err1)) return _err1
|
||||
const nodes = _nodes as Value[]
|
||||
|
||||
const updatedSelectionRanges = pathToNodes
|
||||
? {
|
||||
otherSelections: [],
|
||||
@ -44,19 +58,15 @@ export function removeConstrainingValuesInfo({
|
||||
toolTips.includes(node.callee.name as any)
|
||||
)
|
||||
|
||||
try {
|
||||
const transforms = getRemoveConstraintsTransforms(
|
||||
updatedSelectionRanges,
|
||||
kclManager.ast,
|
||||
'removeConstrainingValues'
|
||||
)
|
||||
const transforms = getRemoveConstraintsTransforms(
|
||||
updatedSelectionRanges,
|
||||
kclManager.ast,
|
||||
'removeConstrainingValues'
|
||||
)
|
||||
if (err(transforms)) return transforms
|
||||
|
||||
const enabled = isAllTooltips && transforms.every(Boolean)
|
||||
return { enabled, transforms, updatedSelectionRanges }
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
return { enabled: false, transforms: [], updatedSelectionRanges }
|
||||
}
|
||||
const enabled = isAllTooltips && transforms.every(Boolean)
|
||||
return { enabled, transforms, updatedSelectionRanges }
|
||||
}
|
||||
|
||||
export function applyRemoveConstrainingValues({
|
||||
@ -65,14 +75,19 @@ export function applyRemoveConstrainingValues({
|
||||
}: {
|
||||
selectionRanges: Selections
|
||||
pathToNodes?: Array<PathToNode>
|
||||
}): {
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
} {
|
||||
const { transforms, updatedSelectionRanges } = removeConstrainingValuesInfo({
|
||||
}):
|
||||
| {
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
}
|
||||
| Error {
|
||||
const constraint = removeConstrainingValuesInfo({
|
||||
selectionRanges,
|
||||
pathToNodes,
|
||||
})
|
||||
if (err(constraint)) return constraint
|
||||
const { transforms, updatedSelectionRanges } = constraint
|
||||
|
||||
return transformAstSketchLines({
|
||||
ast: kclManager.ast,
|
||||
selectionRanges: updatedSelectionRanges,
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
getTransformInfos,
|
||||
transformAstSketchLines,
|
||||
PathToNodeMap,
|
||||
TransformInfo,
|
||||
} from '../../lang/std/sketchcombos'
|
||||
import {
|
||||
SetAngleLengthModal,
|
||||
@ -20,6 +21,7 @@ import {
|
||||
} from '../../lang/modifyAst'
|
||||
import { removeDoubleNegatives } from '../AvailableVarsHelpers'
|
||||
import { kclManager } from 'lib/singletons'
|
||||
import { err } from 'lib/trap'
|
||||
|
||||
const getModalInfo = createSetAngleLengthModal(SetAngleLengthModal)
|
||||
|
||||
@ -31,7 +33,12 @@ export function absDistanceInfo({
|
||||
}: {
|
||||
selectionRanges: Selections
|
||||
constraint: Constraint
|
||||
}) {
|
||||
}):
|
||||
| {
|
||||
transforms: TransformInfo[]
|
||||
enabled: boolean
|
||||
}
|
||||
| Error {
|
||||
const disType =
|
||||
constraint === 'xAbs' || constraint === 'yAbs'
|
||||
? constraint
|
||||
@ -41,10 +48,19 @@ export function absDistanceInfo({
|
||||
const paths = selectionRanges.codeBasedSelections.map(({ range }) =>
|
||||
getNodePathFromSourceRange(kclManager.ast, range)
|
||||
)
|
||||
const nodes = paths.map(
|
||||
(pathToNode) =>
|
||||
getNodeFromPath<Value>(kclManager.ast, pathToNode, 'CallExpression').node
|
||||
)
|
||||
const _nodes = paths.map((pathToNode) => {
|
||||
const tmp = getNodeFromPath<Value>(
|
||||
kclManager.ast,
|
||||
pathToNode,
|
||||
'CallExpression'
|
||||
)
|
||||
if (err(tmp)) return tmp
|
||||
return tmp.node
|
||||
})
|
||||
const _err1 = _nodes.find(err)
|
||||
if (err(_err1)) return _err1
|
||||
const nodes = _nodes as Value[]
|
||||
|
||||
const isAllTooltips = nodes.every(
|
||||
(node) =>
|
||||
node?.type === 'CallExpression' &&
|
||||
@ -52,6 +68,7 @@ export function absDistanceInfo({
|
||||
)
|
||||
|
||||
const transforms = getTransformInfos(selectionRanges, kclManager.ast, disType)
|
||||
if (err(transforms)) return transforms
|
||||
|
||||
const enableY =
|
||||
disType === 'yAbs' &&
|
||||
@ -81,17 +98,23 @@ export async function applyConstraintAbsDistance({
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
}> {
|
||||
const transformInfos = absDistanceInfo({
|
||||
const info = absDistanceInfo({
|
||||
selectionRanges,
|
||||
constraint,
|
||||
}).transforms
|
||||
const { valueUsedInTransform } = transformAstSketchLines({
|
||||
})
|
||||
if (err(info)) return Promise.reject(info)
|
||||
const transformInfos = info.transforms
|
||||
|
||||
const transform1 = transformAstSketchLines({
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges: selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
referenceSegName: '',
|
||||
})
|
||||
if (err(transform1)) return Promise.reject(transform1)
|
||||
const { valueUsedInTransform } = transform1
|
||||
|
||||
let forceVal = valueUsedInTransform || 0
|
||||
const { valueNode, variableName, newVariableInsertIndex, sign } =
|
||||
await getModalInfo({
|
||||
@ -104,7 +127,7 @@ export async function applyConstraintAbsDistance({
|
||||
variableName
|
||||
)
|
||||
|
||||
const { modifiedAst: _modifiedAst, pathToNodeMap } = transformAstSketchLines({
|
||||
const transform2 = transformAstSketchLines({
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges: selectionRanges,
|
||||
transformInfos,
|
||||
@ -112,6 +135,9 @@ export async function applyConstraintAbsDistance({
|
||||
referenceSegName: '',
|
||||
forceValueUsedInTransform: finalValue,
|
||||
})
|
||||
if (err(transform2)) return Promise.reject(transform2)
|
||||
const { modifiedAst: _modifiedAst, pathToNodeMap } = transform2
|
||||
|
||||
if (variableName) {
|
||||
const newBody = [..._modifiedAst.body]
|
||||
newBody.splice(
|
||||
@ -134,14 +160,18 @@ export function applyConstraintAxisAlign({
|
||||
}: {
|
||||
selectionRanges: Selections
|
||||
constraint: 'snapToYAxis' | 'snapToXAxis'
|
||||
}): {
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
} {
|
||||
const transformInfos = absDistanceInfo({
|
||||
}):
|
||||
| {
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
}
|
||||
| Error {
|
||||
const info = absDistanceInfo({
|
||||
selectionRanges,
|
||||
constraint,
|
||||
}).transforms
|
||||
})
|
||||
if (err(info)) return info
|
||||
const transformInfos = info.transforms
|
||||
|
||||
let finalValue = createIdentifier('ZERO')
|
||||
|
||||
|
@ -10,11 +10,13 @@ import {
|
||||
transformSecondarySketchLinesTagFirst,
|
||||
getTransformInfos,
|
||||
PathToNodeMap,
|
||||
TransformInfo,
|
||||
} from '../../lang/std/sketchcombos'
|
||||
import { GetInfoModal, createInfoModal } from '../SetHorVertDistanceModal'
|
||||
import { createVariableDeclaration } from '../../lang/modifyAst'
|
||||
import { removeDoubleNegatives } from '../AvailableVarsHelpers'
|
||||
import { kclManager } from 'lib/singletons'
|
||||
import { err } from 'lib/trap'
|
||||
|
||||
const getModalInfo = createInfoModal(GetInfoModal)
|
||||
|
||||
@ -22,22 +24,38 @@ export function angleBetweenInfo({
|
||||
selectionRanges,
|
||||
}: {
|
||||
selectionRanges: Selections
|
||||
}) {
|
||||
}):
|
||||
| {
|
||||
transforms: TransformInfo[]
|
||||
enabled: boolean
|
||||
}
|
||||
| Error {
|
||||
const paths = selectionRanges.codeBasedSelections.map(({ range }) =>
|
||||
getNodePathFromSourceRange(kclManager.ast, range)
|
||||
)
|
||||
|
||||
const nodes = paths.map(
|
||||
(pathToNode) => getNodeFromPath<Value>(kclManager.ast, pathToNode).node
|
||||
)
|
||||
const varDecs = paths.map(
|
||||
(pathToNode) =>
|
||||
getNodeFromPath<VariableDeclarator>(
|
||||
kclManager.ast,
|
||||
pathToNode,
|
||||
'VariableDeclarator'
|
||||
)?.node
|
||||
)
|
||||
const _nodes = paths.map((pathToNode) => {
|
||||
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
|
||||
if (err(tmp)) return tmp
|
||||
return tmp.node
|
||||
})
|
||||
const _err1 = _nodes.find(err)
|
||||
if (err(_err1)) return _err1
|
||||
const nodes = _nodes as Value[]
|
||||
|
||||
const _varDecs = paths.map((pathToNode) => {
|
||||
const tmp = getNodeFromPath<VariableDeclarator>(
|
||||
kclManager.ast,
|
||||
pathToNode,
|
||||
'VariableDeclarator'
|
||||
)
|
||||
if (err(tmp)) return tmp
|
||||
return tmp.node
|
||||
})
|
||||
const _err2 = _varDecs.find(err)
|
||||
if (err(_err2)) return _err2
|
||||
const varDecs = _varDecs as VariableDeclarator[]
|
||||
|
||||
const primaryLine = varDecs[0]
|
||||
const secondaryVarDecs = varDecs.slice(1)
|
||||
const isOthersLinkedToPrimary = secondaryVarDecs.every((secondary) =>
|
||||
@ -77,14 +95,20 @@ export async function applyConstraintAngleBetween({
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
}> {
|
||||
const transformInfos = angleBetweenInfo({ selectionRanges }).transforms
|
||||
const info = angleBetweenInfo({ selectionRanges })
|
||||
if (err(info)) return Promise.reject(info)
|
||||
const transformInfos = info.transforms
|
||||
|
||||
const transformed1 = transformSecondarySketchLinesTagFirst({
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
})
|
||||
if (err(transformed1)) return Promise.reject(transformed1)
|
||||
const { modifiedAst, tagInfo, valueUsedInTransform, pathToNodeMap } =
|
||||
transformSecondarySketchLinesTagFirst({
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
})
|
||||
transformed1
|
||||
|
||||
const {
|
||||
segName,
|
||||
value,
|
||||
@ -115,15 +139,18 @@ export async function applyConstraintAngleBetween({
|
||||
variableName
|
||||
)
|
||||
// transform again but forcing certain values
|
||||
const transformed2 = transformSecondarySketchLinesTagFirst({
|
||||
ast: kclManager.ast,
|
||||
selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
forceSegName: segName,
|
||||
forceValueUsedInTransform: finalValue,
|
||||
})
|
||||
if (err(transformed2)) return Promise.reject(transformed2)
|
||||
const { modifiedAst: _modifiedAst, pathToNodeMap: _pathToNodeMap } =
|
||||
transformSecondarySketchLinesTagFirst({
|
||||
ast: kclManager.ast,
|
||||
selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
forceSegName: segName,
|
||||
forceValueUsedInTransform: finalValue,
|
||||
})
|
||||
transformed2
|
||||
|
||||
if (variableName) {
|
||||
const newBody = [..._modifiedAst.body]
|
||||
newBody.splice(
|
||||
|
@ -9,12 +9,14 @@ import {
|
||||
transformSecondarySketchLinesTagFirst,
|
||||
getTransformInfos,
|
||||
PathToNodeMap,
|
||||
TransformInfo,
|
||||
} from '../../lang/std/sketchcombos'
|
||||
import { GetInfoModal, createInfoModal } from '../SetHorVertDistanceModal'
|
||||
import { createLiteral, createVariableDeclaration } from '../../lang/modifyAst'
|
||||
import { removeDoubleNegatives } from '../AvailableVarsHelpers'
|
||||
import { kclManager } from 'lib/singletons'
|
||||
import { Selections } from 'lib/selections'
|
||||
import { cleanErrs, err } from 'lib/trap'
|
||||
|
||||
const getModalInfo = createInfoModal(GetInfoModal)
|
||||
|
||||
@ -24,21 +26,38 @@ export function horzVertDistanceInfo({
|
||||
}: {
|
||||
selectionRanges: Selections
|
||||
constraint: 'setHorzDistance' | 'setVertDistance'
|
||||
}) {
|
||||
}):
|
||||
| {
|
||||
transforms: TransformInfo[]
|
||||
enabled: boolean
|
||||
}
|
||||
| Error {
|
||||
const paths = selectionRanges.codeBasedSelections.map(({ range }) =>
|
||||
getNodePathFromSourceRange(kclManager.ast, range)
|
||||
)
|
||||
const nodes = paths.map(
|
||||
(pathToNode) => getNodeFromPath<Value>(kclManager.ast, pathToNode).node
|
||||
)
|
||||
const varDecs = paths.map(
|
||||
(pathToNode) =>
|
||||
getNodeFromPath<VariableDeclarator>(
|
||||
kclManager.ast,
|
||||
pathToNode,
|
||||
'VariableDeclarator'
|
||||
)?.node
|
||||
)
|
||||
const _nodes = paths.map((pathToNode) => {
|
||||
const tmp = getNodeFromPath<Value>(kclManager.ast, pathToNode)
|
||||
if (err(tmp)) return tmp
|
||||
return tmp.node
|
||||
})
|
||||
const [hasErr, , nodesWErrs] = cleanErrs(_nodes)
|
||||
|
||||
if (hasErr) return nodesWErrs[0]
|
||||
const nodes = _nodes as Value[]
|
||||
|
||||
const _varDecs = paths.map((pathToNode) => {
|
||||
const tmp = getNodeFromPath<VariableDeclarator>(
|
||||
kclManager.ast,
|
||||
pathToNode,
|
||||
'VariableDeclarator'
|
||||
)
|
||||
if (err(tmp)) return tmp
|
||||
return tmp.node
|
||||
})
|
||||
const _err2 = _varDecs.find(err)
|
||||
if (err(_err2)) return _err2
|
||||
const varDecs = _varDecs as VariableDeclarator[]
|
||||
|
||||
const primaryLine = varDecs[0]
|
||||
const secondaryVarDecs = varDecs.slice(1)
|
||||
const isOthersLinkedToPrimary = secondaryVarDecs.every((secondary) =>
|
||||
@ -82,17 +101,21 @@ export async function applyConstraintHorzVertDistance({
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
}> {
|
||||
const transformInfos = horzVertDistanceInfo({
|
||||
const info = horzVertDistanceInfo({
|
||||
selectionRanges,
|
||||
constraint,
|
||||
}).transforms
|
||||
})
|
||||
if (err(info)) return Promise.reject(info)
|
||||
const transformInfos = info.transforms
|
||||
const transformed = transformSecondarySketchLinesTagFirst({
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
})
|
||||
if (err(transformed)) return Promise.reject(transformed)
|
||||
const { modifiedAst, tagInfo, valueUsedInTransform, pathToNodeMap } =
|
||||
transformSecondarySketchLinesTagFirst({
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
})
|
||||
transformed
|
||||
const {
|
||||
segName,
|
||||
value,
|
||||
@ -120,15 +143,17 @@ export async function applyConstraintHorzVertDistance({
|
||||
? createLiteral(0)
|
||||
: removeDoubleNegatives(valueNode as BinaryPart, sign, variableName)
|
||||
// transform again but forcing certain values
|
||||
const { modifiedAst: _modifiedAst, pathToNodeMap } =
|
||||
transformSecondarySketchLinesTagFirst({
|
||||
ast: kclManager.ast,
|
||||
selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
forceSegName: segName,
|
||||
forceValueUsedInTransform: finalValue,
|
||||
})
|
||||
const transformed = transformSecondarySketchLinesTagFirst({
|
||||
ast: kclManager.ast,
|
||||
selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
forceSegName: segName,
|
||||
forceValueUsedInTransform: finalValue,
|
||||
})
|
||||
|
||||
if (err(transformed)) return Promise.reject(transformed)
|
||||
const { modifiedAst: _modifiedAst, pathToNodeMap } = transformed
|
||||
if (variableName) {
|
||||
const newBody = [..._modifiedAst.body]
|
||||
newBody.splice(
|
||||
@ -155,22 +180,28 @@ export function applyConstraintHorzVertAlign({
|
||||
}: {
|
||||
selectionRanges: Selections
|
||||
constraint: 'setHorzDistance' | 'setVertDistance'
|
||||
}): {
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
} {
|
||||
const transformInfos = horzVertDistanceInfo({
|
||||
}):
|
||||
| {
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
}
|
||||
| Error {
|
||||
const info = horzVertDistanceInfo({
|
||||
selectionRanges,
|
||||
constraint,
|
||||
}).transforms
|
||||
})
|
||||
if (err(info)) return info
|
||||
const transformInfos = info.transforms
|
||||
let finalValue = createLiteral(0)
|
||||
const { modifiedAst, pathToNodeMap } = transformSecondarySketchLinesTagFirst({
|
||||
const retval = transformSecondarySketchLinesTagFirst({
|
||||
ast: kclManager.ast,
|
||||
selectionRanges,
|
||||
transformInfos,
|
||||
programMemory: kclManager.programMemory,
|
||||
forceValueUsedInTransform: finalValue,
|
||||
})
|
||||
if (err(retval)) return retval
|
||||
const { modifiedAst, pathToNodeMap } = retval
|
||||
return {
|
||||
modifiedAst: modifiedAst,
|
||||
pathToNodeMap,
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
PathToNodeMap,
|
||||
getTransformInfos,
|
||||
transformAstSketchLines,
|
||||
TransformInfo,
|
||||
} from '../../lang/std/sketchcombos'
|
||||
import {
|
||||
SetAngleLengthModal,
|
||||
@ -22,6 +23,7 @@ import {
|
||||
import { removeDoubleNegatives } from '../AvailableVarsHelpers'
|
||||
import { normaliseAngle } from '../../lib/utils'
|
||||
import { kclManager } from 'lib/singletons'
|
||||
import { err } from 'lib/trap'
|
||||
|
||||
const getModalInfo = createSetAngleLengthModal(SetAngleLengthModal)
|
||||
|
||||
@ -31,19 +33,29 @@ export function angleLengthInfo({
|
||||
}: {
|
||||
selectionRanges: Selections
|
||||
angleOrLength?: 'setLength' | 'setAngle'
|
||||
}) {
|
||||
}):
|
||||
| {
|
||||
transforms: TransformInfo[]
|
||||
enabled: boolean
|
||||
}
|
||||
| Error {
|
||||
const paths = selectionRanges.codeBasedSelections.map(({ range }) =>
|
||||
getNodePathFromSourceRange(kclManager.ast, range)
|
||||
)
|
||||
const nodes = paths.map(
|
||||
(pathToNode) =>
|
||||
getNodeFromPath<Value>(kclManager.ast, pathToNode, 'CallExpression').node
|
||||
)
|
||||
const isAllTooltips = nodes.every(
|
||||
(node) =>
|
||||
node?.type === 'CallExpression' &&
|
||||
toolTips.includes(node.callee.name as any)
|
||||
|
||||
const nodes = paths.map((pathToNode) =>
|
||||
getNodeFromPath<Value>(kclManager.ast, pathToNode, 'CallExpression')
|
||||
)
|
||||
const _err1 = nodes.find(err)
|
||||
if (err(_err1)) return _err1
|
||||
|
||||
const isAllTooltips = nodes.every((meta) => {
|
||||
if (err(meta)) return false
|
||||
return (
|
||||
meta.node?.type === 'CallExpression' &&
|
||||
toolTips.includes(meta.node.callee.name as any)
|
||||
)
|
||||
})
|
||||
|
||||
const transforms = getTransformInfos(
|
||||
selectionRanges,
|
||||
@ -67,88 +79,91 @@ export async function applyConstraintAngleLength({
|
||||
modifiedAst: Program
|
||||
pathToNodeMap: PathToNodeMap
|
||||
}> {
|
||||
const { transforms } = angleLengthInfo({ selectionRanges, angleOrLength })
|
||||
const { valueUsedInTransform } = transformAstSketchLines({
|
||||
const angleLength = angleLengthInfo({ selectionRanges, angleOrLength })
|
||||
if (err(angleLength)) return Promise.reject(angleLength)
|
||||
|
||||
const { transforms } = angleLength
|
||||
const sketched = transformAstSketchLines({
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges,
|
||||
transformInfos: transforms,
|
||||
programMemory: kclManager.programMemory,
|
||||
referenceSegName: '',
|
||||
})
|
||||
try {
|
||||
const isReferencingYAxis =
|
||||
selectionRanges.otherSelections.length === 1 &&
|
||||
selectionRanges.otherSelections[0] === 'y-axis'
|
||||
const isReferencingYAxisAngle =
|
||||
isReferencingYAxis && angleOrLength === 'setAngle'
|
||||
if (err(sketched)) return Promise.reject(sketched)
|
||||
const { valueUsedInTransform } = sketched
|
||||
|
||||
const isReferencingXAxis =
|
||||
selectionRanges.otherSelections.length === 1 &&
|
||||
selectionRanges.otherSelections[0] === 'x-axis'
|
||||
const isReferencingXAxisAngle =
|
||||
isReferencingXAxis && angleOrLength === 'setAngle'
|
||||
const isReferencingYAxis =
|
||||
selectionRanges.otherSelections.length === 1 &&
|
||||
selectionRanges.otherSelections[0] === 'y-axis'
|
||||
const isReferencingYAxisAngle =
|
||||
isReferencingYAxis && angleOrLength === 'setAngle'
|
||||
|
||||
let forceVal = valueUsedInTransform || 0
|
||||
let calcIdentifier = createIdentifier('ZERO')
|
||||
if (isReferencingYAxisAngle) {
|
||||
calcIdentifier = createIdentifier(
|
||||
forceVal < 0 ? 'THREE_QUARTER_TURN' : 'QUARTER_TURN'
|
||||
)
|
||||
forceVal = normaliseAngle(forceVal + (forceVal < 0 ? 90 : -90))
|
||||
} else if (isReferencingXAxisAngle) {
|
||||
calcIdentifier = createIdentifier(
|
||||
Math.abs(forceVal) > 90 ? 'HALF_TURN' : 'ZERO'
|
||||
)
|
||||
forceVal =
|
||||
Math.abs(forceVal) > 90 ? normaliseAngle(forceVal - 180) : forceVal
|
||||
}
|
||||
const { valueNode, variableName, newVariableInsertIndex, sign } =
|
||||
await getModalInfo({
|
||||
value: forceVal,
|
||||
valueName: angleOrLength === 'setAngle' ? 'angle' : 'length',
|
||||
shouldCreateVariable: true,
|
||||
})
|
||||
const isReferencingXAxis =
|
||||
selectionRanges.otherSelections.length === 1 &&
|
||||
selectionRanges.otherSelections[0] === 'x-axis'
|
||||
const isReferencingXAxisAngle =
|
||||
isReferencingXAxis && angleOrLength === 'setAngle'
|
||||
|
||||
let finalValue = removeDoubleNegatives(
|
||||
valueNode as BinaryPart,
|
||||
sign,
|
||||
variableName
|
||||
let forceVal = valueUsedInTransform || 0
|
||||
let calcIdentifier = createIdentifier('ZERO')
|
||||
if (isReferencingYAxisAngle) {
|
||||
calcIdentifier = createIdentifier(
|
||||
forceVal < 0 ? 'THREE_QUARTER_TURN' : 'QUARTER_TURN'
|
||||
)
|
||||
if (
|
||||
isReferencingYAxisAngle ||
|
||||
(isReferencingXAxisAngle && calcIdentifier.name !== 'ZERO')
|
||||
) {
|
||||
finalValue = createBinaryExpressionWithUnary([calcIdentifier, finalValue])
|
||||
}
|
||||
forceVal = normaliseAngle(forceVal + (forceVal < 0 ? 90 : -90))
|
||||
} else if (isReferencingXAxisAngle) {
|
||||
calcIdentifier = createIdentifier(
|
||||
Math.abs(forceVal) > 90 ? 'HALF_TURN' : 'ZERO'
|
||||
)
|
||||
forceVal =
|
||||
Math.abs(forceVal) > 90 ? normaliseAngle(forceVal - 180) : forceVal
|
||||
}
|
||||
const { valueNode, variableName, newVariableInsertIndex, sign } =
|
||||
await getModalInfo({
|
||||
value: forceVal,
|
||||
valueName: angleOrLength === 'setAngle' ? 'angle' : 'length',
|
||||
shouldCreateVariable: true,
|
||||
})
|
||||
|
||||
const { modifiedAst: _modifiedAst, pathToNodeMap } =
|
||||
transformAstSketchLines({
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges,
|
||||
transformInfos: transforms,
|
||||
programMemory: kclManager.programMemory,
|
||||
referenceSegName: '',
|
||||
forceValueUsedInTransform: finalValue,
|
||||
})
|
||||
if (variableName) {
|
||||
const newBody = [..._modifiedAst.body]
|
||||
newBody.splice(
|
||||
newVariableInsertIndex,
|
||||
0,
|
||||
createVariableDeclaration(variableName, valueNode)
|
||||
)
|
||||
_modifiedAst.body = newBody
|
||||
Object.values(pathToNodeMap).forEach((pathToNode) => {
|
||||
const index = pathToNode.findIndex((a) => a[0] === 'body') + 1
|
||||
pathToNode[index][0] = Number(pathToNode[index][0]) + 1
|
||||
})
|
||||
}
|
||||
return {
|
||||
modifiedAst: _modifiedAst,
|
||||
pathToNodeMap,
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('error', e)
|
||||
throw e
|
||||
let finalValue = removeDoubleNegatives(
|
||||
valueNode as BinaryPart,
|
||||
sign,
|
||||
variableName
|
||||
)
|
||||
if (
|
||||
isReferencingYAxisAngle ||
|
||||
(isReferencingXAxisAngle && calcIdentifier.name !== 'ZERO')
|
||||
) {
|
||||
finalValue = createBinaryExpressionWithUnary([calcIdentifier, finalValue])
|
||||
}
|
||||
|
||||
const retval = transformAstSketchLines({
|
||||
ast: JSON.parse(JSON.stringify(kclManager.ast)),
|
||||
selectionRanges,
|
||||
transformInfos: transforms,
|
||||
programMemory: kclManager.programMemory,
|
||||
referenceSegName: '',
|
||||
forceValueUsedInTransform: finalValue,
|
||||
})
|
||||
if (err(retval)) return Promise.reject(retval)
|
||||
|
||||
const { modifiedAst: _modifiedAst, pathToNodeMap } = retval
|
||||
if (variableName) {
|
||||
const newBody = [..._modifiedAst.body]
|
||||
newBody.splice(
|
||||
newVariableInsertIndex,
|
||||
0,
|
||||
createVariableDeclaration(variableName, valueNode)
|
||||
)
|
||||
_modifiedAst.body = newBody
|
||||
Object.values(pathToNodeMap).forEach((pathToNode) => {
|
||||
const index = pathToNode.findIndex((a) => a[0] === 'body') + 1
|
||||
pathToNode[index][0] = Number(pathToNode[index][0]) + 1
|
||||
})
|
||||
}
|
||||
return {
|
||||
modifiedAst: _modifiedAst,
|
||||
pathToNodeMap,
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user