Fix type-check error due to field addition (#4010)

This commit is contained in:
Jonathan Tran
2024-09-27 09:37:27 -04:00
committed by GitHub
parent e53bb07843
commit 47b1c1654a
2 changed files with 42 additions and 28 deletions

View File

@ -7,7 +7,7 @@ import {
} from 'lib/singletons' } from 'lib/singletons'
import { CallExpression, SourceRange, Expr, parse } from 'lang/wasm' import { CallExpression, SourceRange, Expr, parse } from 'lang/wasm'
import { ModelingMachineEvent } from 'machines/modelingMachine' import { ModelingMachineEvent } from 'machines/modelingMachine'
import { uuidv4 } from 'lib/utils' import { isNonNullable, uuidv4 } from 'lib/utils'
import { EditorSelection, SelectionRange } from '@codemirror/state' import { EditorSelection, SelectionRange } from '@codemirror/state'
import { getNormalisedCoordinates, isOverlap } from 'lib/utils' import { getNormalisedCoordinates, isOverlap } from 'lib/utils'
import { isCursorInSketchCommandRange } from 'lang/util' import { isCursorInSketchCommandRange } from 'lang/util'
@ -34,6 +34,7 @@ import {
getSweepEdgeCodeRef, getSweepEdgeCodeRef,
getSolid2dCodeRef, getSolid2dCodeRef,
getWallCodeRef, getWallCodeRef,
ArtifactId,
} from 'lang/std/artifactGraph' } from 'lang/std/artifactGraph'
export const X_AXIS_UUID = 'ad792545-7fd3-482a-a602-a93924e3055b' export const X_AXIS_UUID = 'ad792545-7fd3-482a-a602-a93924e3055b'
@ -574,20 +575,21 @@ function codeToIdSelections(
codeBasedSelections: Selection[] codeBasedSelections: Selection[]
): SelectionToEngine[] { ): SelectionToEngine[] {
return codeBasedSelections return codeBasedSelections
.flatMap(({ type, range, ...rest }): null | SelectionToEngine[] => { .flatMap((selection): null | SelectionToEngine[] => {
const { type } = selection
// TODO #868: loops over all artifacts will become inefficient at a large scale // TODO #868: loops over all artifacts will become inefficient at a large scale
const overlappingEntries = Array.from(engineCommandManager.artifactGraph) const overlappingEntries = Array.from(engineCommandManager.artifactGraph)
.map(([id, artifact]) => { .map(([id, artifact]) => {
if (!('codeRef' in artifact)) return false if (!('codeRef' in artifact)) return null
return isOverlap(artifact.codeRef.range, range) return isOverlap(artifact.codeRef.range, selection.range)
? { ? {
artifact, artifact,
selection: { type, range, ...rest }, selection,
id, id,
} }
: false : null
}) })
.filter(Boolean) .filter(isNonNullable)
/** TODO refactor /** TODO refactor
* selections in our app is a sourceRange plus some metadata * selections in our app is a sourceRange plus some metadata
@ -600,9 +602,14 @@ function codeToIdSelections(
* In the case of a user moving the cursor them, we will still need to figure out what artifact from the graph matches best, but we will just need sane defaults * In the case of a user moving the cursor them, we will still need to figure out what artifact from the graph matches best, but we will just need sane defaults
* and most of the time we can expect the user to be clicking in the 3d scene instead. * and most of the time we can expect the user to be clicking in the 3d scene instead.
*/ */
let bestCandidate let bestCandidate:
| {
id: ArtifactId
artifact: unknown
selection: Selection
}
| undefined
overlappingEntries.forEach((entry) => { overlappingEntries.forEach((entry) => {
if (!entry) return
if (type === 'default' && entry.artifact.type === 'segment') { if (type === 'default' && entry.artifact.type === 'segment') {
bestCandidate = entry bestCandidate = entry
return return
@ -612,9 +619,15 @@ function codeToIdSelections(
entry.artifact.solid2dId || '' entry.artifact.solid2dId || ''
) )
if (solid?.type !== 'solid2D') return if (solid?.type !== 'solid2D') return
if (!entry.artifact.solid2dId) {
console.error(
'Expected PathArtifact to have solid2dId, but none found'
)
return
}
bestCandidate = { bestCandidate = {
artifact: solid, artifact: solid,
selection: { type, range, ...rest }, selection,
id: entry.artifact.solid2dId, id: entry.artifact.solid2dId,
} }
} }
@ -625,7 +638,7 @@ function codeToIdSelections(
if (wall?.type !== 'wall') return if (wall?.type !== 'wall') return
bestCandidate = { bestCandidate = {
artifact: wall, artifact: wall,
selection: { type, range, ...rest }, selection,
id: entry.artifact.surfaceId, id: entry.artifact.surfaceId,
} }
return return
@ -639,7 +652,7 @@ function codeToIdSelections(
if (!edge) return if (!edge) return
bestCandidate = { bestCandidate = {
artifact: edge[1], artifact: edge[1],
selection: { type, range, ...rest }, selection,
id: edge[0], id: edge[0],
} }
} }
@ -655,7 +668,7 @@ function codeToIdSelections(
if (!edge) return if (!edge) return
bestCandidate = { bestCandidate = {
artifact: edge[1], artifact: edge[1],
selection: { type, range, ...rest }, selection,
id: edge[0], id: edge[0],
} }
} }
@ -681,7 +694,7 @@ function codeToIdSelections(
if (!cap) return if (!cap) return
bestCandidate = { bestCandidate = {
artifact: entry.artifact, artifact: entry.artifact,
selection: { type, range, ...rest }, selection,
id: cap[0], id: cap[0],
} }
return return
@ -700,12 +713,12 @@ function codeToIdSelections(
type === 'base-edgeCut' && type === 'base-edgeCut' &&
isOverlap( isOverlap(
consumedEdge.codeRef.range, consumedEdge.codeRef.range,
entry.selection?.secondaryRange || [0, 0] selection.secondaryRange || [0, 0]
) )
) { ) {
bestCandidate = { bestCandidate = {
artifact: entry.artifact, artifact: entry.artifact,
selection: { type, range, ...rest }, selection,
id: entry.id, id: entry.id,
} }
} else if ( } else if (
@ -721,14 +734,11 @@ function codeToIdSelections(
) )
if (err(seg)) return if (err(seg)) return
if ( if (
isOverlap( isOverlap(seg.codeRef.range, selection.secondaryRange || [0, 0])
seg.codeRef.range,
entry.selection?.secondaryRange || [0, 0]
)
) { ) {
bestCandidate = { bestCandidate = {
artifact: entry.artifact, artifact: entry.artifact,
selection: { type, range, ...rest }, selection,
id: entry.id, id: entry.id,
} }
} }
@ -737,21 +747,16 @@ function codeToIdSelections(
}) })
if (bestCandidate) { if (bestCandidate) {
const _bestCandidate = bestCandidate as {
artifact: any
selection: any
id: string
}
return [ return [
{ {
type, type,
id: _bestCandidate.id, id: bestCandidate.id,
}, },
] ]
} }
return null return null
}) })
.filter(Boolean) as any .filter(isNonNullable)
} }
export async function sendSelectEventToEngine( export async function sendSelectEventToEngine(

View File

@ -14,6 +14,15 @@ export function isArray(val: any): val is unknown[] {
return Array.isArray(val) return Array.isArray(val)
} }
/**
* Predicate that checks if a value is not null and not undefined. This is
* useful for functions like Array::filter() and Array::find() that have
* overloads that accept a type guard.
*/
export function isNonNullable<T>(val: T): val is NonNullable<T> {
return val !== null && val !== undefined
}
export function isOverlap(a: SourceRange, b: SourceRange) { export function isOverlap(a: SourceRange, b: SourceRange) {
const [startingRange, secondRange] = a[0] < b[0] ? [a, b] : [b, a] const [startingRange, secondRange] = a[0] < b[0] ? [a, b] : [b, a]
const [lastOfFirst, firstOfSecond] = [startingRange[1], secondRange[0]] const [lastOfFirst, firstOfSecond] = [startingRange[1], secondRange[0]]