* Fix to use more accurate types with custom isArray() * Add lint against Array.isArray()
128 lines
3.1 KiB
TypeScript
128 lines
3.1 KiB
TypeScript
import { Selections } from 'lib/selections'
|
|
import {
|
|
PathToNode,
|
|
CallExpression,
|
|
Literal,
|
|
ArrayExpression,
|
|
BinaryExpression,
|
|
ArtifactGraph,
|
|
CallExpressionKw,
|
|
Expr,
|
|
LiteralValue,
|
|
NumericSuffix,
|
|
} from './wasm'
|
|
import { filterArtifacts } from 'lang/std/artifactGraph'
|
|
import { isArray, isOverlap } from 'lib/utils'
|
|
|
|
export function updatePathToNodeFromMap(
|
|
oldPath: PathToNode,
|
|
pathToNodeMap: { [key: number]: PathToNode }
|
|
): PathToNode {
|
|
const updatedPathToNode = structuredClone(oldPath)
|
|
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
|
|
}
|
|
|
|
export function isCursorInSketchCommandRange(
|
|
artifactGraph: ArtifactGraph,
|
|
selectionRanges: Selections
|
|
): string | false {
|
|
const overlappingEntries = filterArtifacts(
|
|
{
|
|
types: ['segment', 'path'],
|
|
predicate: (artifact) => {
|
|
return selectionRanges.graphSelections.some(
|
|
(selection) =>
|
|
isArray(selection?.codeRef?.range) &&
|
|
isArray(artifact?.codeRef?.range) &&
|
|
isOverlap(selection?.codeRef?.range, artifact.codeRef.range)
|
|
)
|
|
},
|
|
},
|
|
artifactGraph
|
|
)
|
|
const firstEntry = [...overlappingEntries.values()]?.[0]
|
|
const parentId = firstEntry?.type === 'segment' ? firstEntry.pathId : false
|
|
|
|
return parentId
|
|
? parentId
|
|
: [...overlappingEntries].find(
|
|
([, artifact]) => artifact.type === 'path'
|
|
)?.[0] || false
|
|
}
|
|
|
|
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'
|
|
}
|
|
|
|
/**
|
|
Search the keyword arguments from a call for an argument with this label.
|
|
*/
|
|
export function findKwArg(
|
|
label: string,
|
|
call: CallExpressionKw
|
|
): Expr | undefined {
|
|
return call.arguments.find((arg) => {
|
|
return arg.label.name === label
|
|
})?.arg
|
|
}
|
|
|
|
/**
|
|
Search the keyword arguments from a call for an argument with one of these labels.
|
|
*/
|
|
export function findKwArgAny(
|
|
labels: string[],
|
|
call: CallExpressionKw
|
|
): Expr | undefined {
|
|
return call.arguments.find((arg) => {
|
|
return labels.includes(arg.label.name)
|
|
})?.arg
|
|
}
|
|
|
|
/**
|
|
Search the keyword arguments from a call for an argument with one of these labels.
|
|
*/
|
|
export function findKwArgAnyIndex(
|
|
labels: string[],
|
|
call: CallExpressionKw
|
|
): number | undefined {
|
|
return call.arguments.findIndex((arg) => {
|
|
return labels.includes(arg.label.name)
|
|
})
|
|
}
|
|
|
|
export function isAbsolute(call: CallExpressionKw): boolean {
|
|
return findKwArgAny(['endAbsolute'], call) !== undefined
|
|
}
|
|
|
|
export function isLiteralValueNumber(
|
|
e: LiteralValue
|
|
): e is { value: number; suffix: NumericSuffix } {
|
|
return (
|
|
typeof e === 'object' &&
|
|
'value' in e &&
|
|
typeof e.value === 'number' &&
|
|
'suffix' in e &&
|
|
typeof e.suffix === 'string'
|
|
)
|
|
}
|