import { Diagnostic } from '@codemirror/lint' import { useMachine, useSelector } from '@xstate/react' import { ContextMenu, ContextMenuItem } from 'components/ContextMenu' import { CustomIcon, CustomIconName } from 'components/CustomIcon' import Loading from 'components/Loading' import { useModelingContext } from 'hooks/useModelingContext' import { useKclContext } from 'lang/KclProvider' import { codeRefFromRange, getArtifactFromRange } from 'lang/std/artifactGraph' import { sourceRangeFromRust } from 'lang/wasm' import { filterOperations, getOperationIcon, getOperationLabel, stdLibMap, } from 'lib/operations' import { editorManager, engineCommandManager, kclManager } from 'lib/singletons' import { ComponentProps, useEffect, useMemo, useRef, useState } from 'react' import { Operation } from 'wasm-lib/kcl/bindings/Operation' import { Actor, Prop } from 'xstate' import { featureTreeMachine } from 'machines/featureTreeMachine' import { editorIsMountedSelector, kclEditorActor, selectionEventSelector, } from 'machines/kclEditorMachine' export const FeatureTreePane = () => { const isEditorMounted = useSelector(kclEditorActor, editorIsMountedSelector) const lastSelectionEvent = useSelector(kclEditorActor, selectionEventSelector) const { send: modelingSend, state: modelingState } = useModelingContext() // eslint-disable-next-line @typescript-eslint/no-unused-vars const [_featureTreeState, featureTreeSend] = useMachine( featureTreeMachine.provide({ guards: { codePaneIsOpen: () => modelingState.context.store.openPanes.includes('code') && editorManager.editorView !== null, }, actions: { openCodePane: () => { modelingSend({ type: 'Set context', data: { openPanes: [...modelingState.context.store.openPanes, 'code'], }, }) }, sendEditFlowStart: () => { modelingSend({ type: 'Enter sketch' }) }, scrollToError: () => { editorManager.scrollToFirstErrorDiagnosticIfExists() }, sendSelectionEvent: ({ context }) => { if (!context.targetSourceRange) { return } const artifact = context.targetSourceRange ? getArtifactFromRange( context.targetSourceRange, engineCommandManager.artifactGraph ) : null if (!artifact) { modelingSend({ type: 'Set selection', data: { selectionType: 'singleCodeCursor', selection: { codeRef: codeRefFromRange( context.targetSourceRange, kclManager.ast ), }, scrollIntoView: true, }, }) } else { modelingSend({ type: 'Set selection', data: { selectionType: 'singleCodeCursor', selection: { artifact: artifact, codeRef: codeRefFromRange( context.targetSourceRange, kclManager.ast ), }, scrollIntoView: true, }, }) } }, }, }) ) // If there are parse errors we show the last successful operations // and overlay a message on top of the pane const parseErrors = kclManager.errors.filter((e) => e.kind !== 'engine') // If there are engine errors we show the successful operations // Errors return an operation list, so use the longest one if there are multiple const longestErrorOperationList = kclManager.errors.reduce((acc, error) => { return error.operations && error.operations.length > acc.length ? error.operations : acc }, [] as Operation[]) const unfilteredOperationList = !parseErrors.length ? !kclManager.errors.length ? kclManager.execState.operations : longestErrorOperationList : kclManager.lastSuccessfulOperations // We filter out operations that are not useful to show in the feature tree const operationList = filterOperations(unfilteredOperationList) // Watch for changes in the open panes and send an event to the feature tree machine useEffect(() => { const codeOpen = modelingState.context.store.openPanes.includes('code') if (codeOpen && isEditorMounted) { featureTreeSend({ type: 'codePaneOpened' }) } }, [modelingState.context.store.openPanes, isEditorMounted]) // Watch for changes in the selection and send an event to the feature tree machine useEffect(() => { featureTreeSend({ type: 'selected' }) }, [lastSelectionEvent]) function goToError() { featureTreeSend({ type: 'goToError' }) } return (
Errors found in KCL code.
Please fix them before continuing.