Check for local name clash with existing variables in Insert flow (#6375)

Check for local name alias clashes with extisting var in Insert flow
Fixes #6230
This commit is contained in:
Pierre Jacquier
2025-04-21 06:35:43 -04:00
committed by GitHub
parent 790613e708
commit 0dee219e46
5 changed files with 62 additions and 13 deletions

View File

@ -143,28 +143,45 @@ test.describe('Point-and-click assemblies tests', () => {
await scene.settled(cmdBar) await scene.settled(cmdBar)
}) })
await test.step('Insert a second time and expect error', async () => { await test.step('Insert a second time with the same name and expect error', async () => {
// TODO: revisit once we have clone with #6209 await toolbar.insertButton.click()
await insertPartIntoAssembly( await cmdBar.selectOption({ name: 'bracket.kcl' }).click()
'bracket.kcl', await cmdBar.expectState({
'bracket', stage: 'arguments',
toolbar, currentArgKey: 'localName',
cmdBar, currentArgValue: '',
page headerArguments: { Path: 'bracket.kcl', LocalName: '' },
) highlightedHeaderArg: 'localName',
commandName: 'Insert',
})
await page.keyboard.insertText('bracket')
await cmdBar.progressCmdBar()
await expect(
page.getByText('This variable name is already in use')
).toBeVisible()
})
await test.step('Insert a second time with a different name and expect error', async () => {
await page.keyboard.insertText('2')
await cmdBar.progressCmdBar()
await cmdBar.expectState({
stage: 'review',
headerArguments: { Path: 'bracket.kcl', LocalName: 'bracket2' },
commandName: 'Insert',
})
await cmdBar.progressCmdBar()
await editor.expectEditor.toContain( await editor.expectEditor.toContain(
` `
import "cylinder.kcl" as cylinder import "cylinder.kcl" as cylinder
import "bracket.kcl" as bracket import "bracket.kcl" as bracket
import "bracket.kcl" as bracket import "bracket.kcl" as bracket2
cylinder cylinder
bracket bracket
bracket bracket2
`, `,
{ shouldNormalise: true } { shouldNormalise: true }
) )
await scene.settled(cmdBar) // TODO: update once we have clone() with #6209
await expect(page.locator('.cm-lint-marker-error')).toBeVisible()
}) })
} }
) )

View File

@ -220,6 +220,13 @@ export type CommandArgumentConfig<
machineContext?: C machineContext?: C
) => OutputType) ) => OutputType)
defaultValueFromContext?: (context: C) => OutputType defaultValueFromContext?: (context: C) => OutputType
validation?: ({
data,
context,
}: {
data: any
context: CommandBarContext
}) => Promise<boolean | string>
} }
| { | {
inputType: 'text' inputType: 'text'
@ -343,6 +350,13 @@ export type CommandArgument<
commandBarContext: ContextFrom<typeof commandBarMachine>, commandBarContext: ContextFrom<typeof commandBarMachine>,
machineContext?: ContextFrom<T> machineContext?: ContextFrom<T>
) => OutputType) ) => OutputType)
validation?: ({
data,
context,
}: {
data: any
context: CommandBarContext
}) => Promise<boolean | string>
} }
| { | {
inputType: 'path' inputType: 'path'

View File

@ -211,6 +211,15 @@ export function buildCommandArgument<
defaultValue: arg.defaultValue, defaultValue: arg.defaultValue,
...baseCommandArgument, ...baseCommandArgument,
} satisfies CommandArgument<O, T> & { inputType: 'kcl' } } satisfies CommandArgument<O, T> & { inputType: 'kcl' }
} else if (arg.inputType === 'string') {
return {
inputType: arg.inputType,
defaultValue: arg.defaultValueFromContext
? arg.defaultValueFromContext(context)
: arg.defaultValue,
validation: arg.validation,
...baseCommandArgument,
} satisfies CommandArgument<O, T> & { inputType: 'string' }
} else { } else {
return { return {
inputType: arg.inputType, inputType: arg.inputType,

View File

@ -133,6 +133,14 @@ export function kclCommands(commandProps: KclCommandConfig): Command[] {
const path = context.argumentsToSubmit['path'] as string const path = context.argumentsToSubmit['path'] as string
return getPathFilenameInVariableCase(path) return getPathFilenameInVariableCase(path)
}, },
validation: async ({ data, context }) => {
const variableExists = kclManager.variables[data.localName]
if (variableExists) {
return 'This variable name is already in use.'
}
return true
},
}, },
}, },
onSubmit: (data) => { onSubmit: (data) => {

View File

@ -307,6 +307,7 @@ export const commandBarMachine = setup({
context.currentArgument && context.currentArgument &&
context.selectedCommand && context.selectedCommand &&
(argConfig?.inputType === 'selection' || (argConfig?.inputType === 'selection' ||
argConfig?.inputType === 'string' ||
argConfig?.inputType === 'selectionMixed') && argConfig?.inputType === 'selectionMixed') &&
argConfig?.validation argConfig?.validation
) { ) {