Add grouping of module instances in Feature Tree (#6125)
* Rename operations to be more generic grouping * Add group enum * Add module instance groups * Change to export all operation ts-rs types to the same file * Fix Feature Tree display of modules to use name * Ignore clippy warning * Update output after operation changes * Change module instances in Feature Tree use to import icon * Fix error message when attempting to delete module instance
This commit is contained in:
@ -1,5 +1,4 @@
|
||||
import type { Operation } from '@rust/kcl-lib/bindings/Operation'
|
||||
import type { OpKclValue } from '@rust/kcl-lib/bindings/OpKclValue'
|
||||
import type { Operation, OpKclValue } from '@rust/kcl-lib/bindings/Operation'
|
||||
|
||||
import type { CustomIconName } from '@src/components/CustomIcon'
|
||||
import { getNodePathFromSourceRange } from '@src/lang/queryAstNodePathUtils'
|
||||
@ -1118,10 +1117,20 @@ export function getOperationLabel(op: Operation): string {
|
||||
return stdLibMap[op.name]?.label ?? op.name
|
||||
case 'KclStdLibCall':
|
||||
return stdLibMap[op.name]?.label ?? op.name
|
||||
case 'UserDefinedFunctionCall':
|
||||
return op.name ?? 'Anonymous custom function'
|
||||
case 'UserDefinedFunctionReturn':
|
||||
return 'User function return'
|
||||
case 'GroupBegin':
|
||||
if (op.group.type === 'FunctionCall') {
|
||||
return op.group.name ?? 'anonymous'
|
||||
} else if (op.group.type === 'ModuleInstance') {
|
||||
return op.group.name
|
||||
} else {
|
||||
const _exhaustiveCheck: never = op.group
|
||||
return '' // unreachable
|
||||
}
|
||||
case 'GroupEnd':
|
||||
return 'Group end'
|
||||
default:
|
||||
const _exhaustiveCheck: never = op
|
||||
return '' // unreachable
|
||||
}
|
||||
}
|
||||
|
||||
@ -1134,8 +1143,16 @@ export function getOperationIcon(op: Operation): CustomIconName {
|
||||
return stdLibMap[op.name]?.icon ?? 'questionMark'
|
||||
case 'KclStdLibCall':
|
||||
return stdLibMap[op.name]?.icon ?? 'questionMark'
|
||||
default:
|
||||
case 'GroupBegin':
|
||||
if (op.group.type === 'ModuleInstance') {
|
||||
return 'import' // TODO: Use insert icon.
|
||||
}
|
||||
return 'make-variable'
|
||||
case 'GroupEnd':
|
||||
return 'questionMark'
|
||||
default:
|
||||
const _exhaustiveCheck: never = op
|
||||
return 'questionMark' // unreachable
|
||||
}
|
||||
}
|
||||
|
||||
@ -1151,31 +1168,31 @@ export function filterOperations(operations: Operation[]): Operation[] {
|
||||
* for use in the feature tree UI
|
||||
*/
|
||||
const operationFilters = [
|
||||
isNotUserFunctionWithNoOperations,
|
||||
isNotInsideUserFunction,
|
||||
isNotUserFunctionReturn,
|
||||
isNotGroupWithNoOperations,
|
||||
isNotInsideGroup,
|
||||
isNotGroupEnd,
|
||||
]
|
||||
|
||||
/**
|
||||
* A filter to exclude everything that occurs inside a UserDefinedFunctionCall
|
||||
* and its corresponding UserDefinedFunctionReturn from a list of operations.
|
||||
* This works even when there are nested function calls.
|
||||
* A filter to exclude everything that occurs inside a GroupBegin and its
|
||||
* corresponding GroupEnd from a list of operations. This works even when there
|
||||
* are nested function calls and module instances.
|
||||
*/
|
||||
function isNotInsideUserFunction(operations: Operation[]): Operation[] {
|
||||
function isNotInsideGroup(operations: Operation[]): Operation[] {
|
||||
const ops: Operation[] = []
|
||||
let depth = 0
|
||||
for (const op of operations) {
|
||||
if (depth === 0) {
|
||||
ops.push(op)
|
||||
}
|
||||
if (op.type === 'UserDefinedFunctionCall') {
|
||||
if (op.type === 'GroupBegin') {
|
||||
depth++
|
||||
}
|
||||
if (op.type === 'UserDefinedFunctionReturn') {
|
||||
if (op.type === 'GroupEnd') {
|
||||
depth--
|
||||
console.assert(
|
||||
depth >= 0,
|
||||
'Unbalanced UserDefinedFunctionCall and UserDefinedFunctionReturn; too many returns'
|
||||
'Unbalanced GroupBegin and GroupEnd; too many ends'
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1184,26 +1201,23 @@ function isNotInsideUserFunction(operations: Operation[]): Operation[] {
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter to exclude UserDefinedFunctionCall operations and their
|
||||
* corresponding UserDefinedFunctionReturn that don't have any operations inside
|
||||
* them from a list of operations.
|
||||
* A filter to exclude GroupBegin operations and their corresponding GroupEnd
|
||||
* that don't have any operations inside them from a list of operations.
|
||||
*/
|
||||
function isNotUserFunctionWithNoOperations(
|
||||
operations: Operation[]
|
||||
): Operation[] {
|
||||
function isNotGroupWithNoOperations(operations: Operation[]): Operation[] {
|
||||
return operations.filter((op, index) => {
|
||||
if (
|
||||
op.type === 'UserDefinedFunctionCall' &&
|
||||
// If this is a call at the end of the array, it's preserved.
|
||||
op.type === 'GroupBegin' &&
|
||||
// If this is a begin at the end of the array, it's preserved.
|
||||
index < operations.length - 1 &&
|
||||
operations[index + 1].type === 'UserDefinedFunctionReturn'
|
||||
operations[index + 1].type === 'GroupEnd'
|
||||
)
|
||||
return false
|
||||
if (
|
||||
op.type === 'UserDefinedFunctionReturn' &&
|
||||
// If this return is at the beginning of the array, it's preserved.
|
||||
op.type === 'GroupEnd' &&
|
||||
// If this is an end at the beginning of the array, it's preserved.
|
||||
index > 0 &&
|
||||
operations[index - 1].type === 'UserDefinedFunctionCall'
|
||||
operations[index - 1].type === 'GroupBegin'
|
||||
)
|
||||
return false
|
||||
|
||||
@ -1212,11 +1226,10 @@ function isNotUserFunctionWithNoOperations(
|
||||
}
|
||||
|
||||
/**
|
||||
* A filter to exclude UserDefinedFunctionReturn operations from a list of
|
||||
* operations.
|
||||
* A filter to exclude GroupEnd operations from a list of operations.
|
||||
*/
|
||||
function isNotUserFunctionReturn(ops: Operation[]): Operation[] {
|
||||
return ops.filter((op) => op.type !== 'UserDefinedFunctionReturn')
|
||||
function isNotGroupEnd(ops: Operation[]): Operation[] {
|
||||
return ops.filter((op) => op.type !== 'GroupEnd')
|
||||
}
|
||||
|
||||
export interface EnterEditFlowProps {
|
||||
@ -1230,7 +1243,7 @@ export async function enterEditFlow({
|
||||
}: EnterEditFlowProps): Promise<Error | CommandBarMachineEvent> {
|
||||
if (operation.type !== 'StdLibCall' && operation.type !== 'KclStdLibCall') {
|
||||
return new Error(
|
||||
'Feature tree editing not yet supported for user-defined functions. Please edit in the code editor.'
|
||||
'Feature tree editing not yet supported for user-defined functions or modules. Please edit in the code editor.'
|
||||
)
|
||||
}
|
||||
const stdLibInfo = stdLibMap[operation.name]
|
||||
@ -1269,7 +1282,7 @@ export async function enterAppearanceFlow({
|
||||
}: EnterEditFlowProps): Promise<Error | CommandBarMachineEvent> {
|
||||
if (operation.type !== 'StdLibCall' && operation.type !== 'KclStdLibCall') {
|
||||
return new Error(
|
||||
'Appearance setting not yet supported for user-defined functions. Please edit in the code editor.'
|
||||
'Appearance setting not yet supported for user-defined functions or modules. Please edit in the code editor.'
|
||||
)
|
||||
}
|
||||
const stdLibInfo = stdLibMap[operation.name]
|
||||
|
Reference in New Issue
Block a user