2023-10-16 21:20:05 +11:00
|
|
|
import { Selections } from 'lib/selections'
|
2024-11-18 10:04:09 -05:00
|
|
|
import {
|
|
|
|
Program,
|
|
|
|
PathToNode,
|
|
|
|
CallExpression,
|
|
|
|
Literal,
|
|
|
|
ArrayExpression,
|
|
|
|
BinaryExpression,
|
|
|
|
} from './wasm'
|
2023-04-14 07:49:36 +10:00
|
|
|
import { getNodeFromPath } from './queryAst'
|
2024-08-03 18:08:51 +10:00
|
|
|
import { ArtifactGraph, filterArtifacts } from 'lang/std/artifactGraph'
|
2023-10-11 15:12:29 +11:00
|
|
|
import { isOverlap } from 'lib/utils'
|
2024-06-24 11:45:40 -04:00
|
|
|
import { err } from 'lib/trap'
|
2023-04-14 07:49:36 +10:00
|
|
|
|
2023-10-11 13:36:54 +11:00
|
|
|
export function pathMapToSelections(
|
|
|
|
ast: Program,
|
|
|
|
prevSelections: Selections,
|
2023-04-14 07:49:36 +10:00
|
|
|
pathToNodeMap: { [key: number]: PathToNode }
|
2023-10-11 13:36:54 +11:00
|
|
|
): Selections {
|
|
|
|
const newSelections: Selections = {
|
|
|
|
...prevSelections,
|
|
|
|
codeBasedSelections: [],
|
2023-04-14 07:49:36 +10:00
|
|
|
}
|
2023-10-11 13:36:54 +11:00
|
|
|
Object.entries(pathToNodeMap).forEach(([index, path]) => {
|
2024-06-24 11:45:40 -04:00
|
|
|
const nodeMeta = getNodeFromPath<any>(ast, path)
|
|
|
|
if (err(nodeMeta)) return
|
|
|
|
const node = nodeMeta.node as any
|
2024-09-26 18:25:05 +10:00
|
|
|
const selection = prevSelections.codeBasedSelections[Number(index)]
|
2023-10-11 13:36:54 +11:00
|
|
|
if (node) {
|
2024-09-26 18:25:05 +10:00
|
|
|
if (
|
|
|
|
selection.type === 'base-edgeCut' ||
|
|
|
|
selection.type === 'adjacent-edgeCut' ||
|
|
|
|
selection.type === 'opposite-edgeCut'
|
|
|
|
) {
|
|
|
|
newSelections.codeBasedSelections.push({
|
|
|
|
range: [node.start, node.end],
|
|
|
|
type: selection.type,
|
|
|
|
secondaryRange: selection.secondaryRange,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
newSelections.codeBasedSelections.push({
|
|
|
|
range: [node.start, node.end],
|
|
|
|
type: selection.type,
|
|
|
|
})
|
|
|
|
}
|
2023-10-11 13:36:54 +11:00
|
|
|
}
|
|
|
|
})
|
|
|
|
return newSelections
|
2023-04-14 07:49:36 +10:00
|
|
|
}
|
2023-08-28 18:48:31 +10:00
|
|
|
|
2024-05-31 11:36:08 +10:00
|
|
|
export function updatePathToNodeFromMap(
|
|
|
|
oldPath: PathToNode,
|
|
|
|
pathToNodeMap: { [key: number]: PathToNode }
|
|
|
|
): PathToNode {
|
2024-07-25 20:11:46 -04:00
|
|
|
const updatedPathToNode = structuredClone(oldPath)
|
2024-05-31 11:36:08 +10:00
|
|
|
let max = 0
|
|
|
|
Object.values(pathToNodeMap).forEach((path) => {
|
|
|
|
const index = Number(path[1][0])
|
|
|
|
if (index > max) {
|
|
|
|
max = index
|
|
|
|
}
|
|
|
|
})
|
|
|
|
updatedPathToNode[1][0] = max
|
|
|
|
return updatedPathToNode
|
|
|
|
}
|
|
|
|
|
2023-10-11 15:12:29 +11:00
|
|
|
export function isCursorInSketchCommandRange(
|
2024-08-03 18:08:51 +10:00
|
|
|
artifactGraph: ArtifactGraph,
|
2023-10-11 15:12:29 +11:00
|
|
|
selectionRanges: Selections
|
|
|
|
): string | false {
|
2024-08-03 18:08:51 +10:00
|
|
|
const overlappingEntries = filterArtifacts(
|
|
|
|
{
|
|
|
|
types: ['segment', 'path'],
|
|
|
|
predicate: (artifact) => {
|
|
|
|
return selectionRanges.codeBasedSelections.some(
|
|
|
|
(selection) =>
|
|
|
|
Array.isArray(selection?.range) &&
|
|
|
|
Array.isArray(artifact?.codeRef?.range) &&
|
|
|
|
isOverlap(selection.range, artifact.codeRef.range)
|
|
|
|
)
|
|
|
|
},
|
|
|
|
},
|
|
|
|
artifactGraph
|
|
|
|
)
|
|
|
|
const firstEntry = [...overlappingEntries.values()]?.[0]
|
|
|
|
const parentId = firstEntry?.type === 'segment' ? firstEntry.pathId : false
|
|
|
|
|
|
|
|
return parentId
|
2024-07-25 19:03:56 +10:00
|
|
|
? parentId
|
2024-08-03 18:08:51 +10:00
|
|
|
: [...overlappingEntries].find(
|
|
|
|
([, artifact]) => artifact.type === 'path'
|
2024-07-25 19:03:56 +10:00
|
|
|
)?.[0] || false
|
2023-10-11 15:12:29 +11:00
|
|
|
}
|
2024-11-18 10:04:09 -05:00
|
|
|
|
|
|
|
export function isCallExpression(e: any): e is CallExpression {
|
|
|
|
return e && e.type === 'CallExpression'
|
|
|
|
}
|
|
|
|
|
|
|
|
export function isArrayExpression(e: any): e is ArrayExpression {
|
|
|
|
return e && e.type === 'ArrayExpression'
|
|
|
|
}
|
|
|
|
|
|
|
|
export function isLiteral(e: any): e is Literal {
|
|
|
|
return e && e.type === 'Literal'
|
|
|
|
}
|
|
|
|
|
|
|
|
export function isBinaryExpression(e: any): e is BinaryExpression {
|
|
|
|
return e && e.type === 'BinaryExpression'
|
|
|
|
}
|