From 63d9f1c0ebef1d5b87fd7a3d96357346f139ec04 Mon Sep 17 00:00:00 2001 From: Chet Joswig Date: Wed, 30 Oct 2024 17:34:54 -0700 Subject: [PATCH 01/18] support for seqN variables in form view --- .../sequencing/SequenceEditor.svelte | 5 +- .../sequencing/form/ArgEditor.svelte | 78 +++++++++++++------ .../sequencing/form/EnumEditor.svelte | 9 ++- .../sequencing/form/SelectedCommand.svelte | 18 ++++- .../sequence-editor/sequence-linter.ts | 2 +- 5 files changed, 83 insertions(+), 29 deletions(-) diff --git a/src/components/sequencing/SequenceEditor.svelte b/src/components/sequencing/SequenceEditor.svelte index e7850a9118..8830fae8cc 100644 --- a/src/components/sequencing/SequenceEditor.svelte +++ b/src/components/sequencing/SequenceEditor.svelte @@ -6,7 +6,7 @@ import { lintGutter } from '@codemirror/lint'; import { Compartment, EditorState } from '@codemirror/state'; import { type ViewUpdate } from '@codemirror/view'; - import type { SyntaxNode } from '@lezer/common'; + import type { SyntaxNode, Tree } from '@lezer/common'; import type { ChannelDictionary, CommandDictionary, ParameterDictionary } from '@nasa-jpl/aerie-ampcs'; import ChevronDownIcon from '@nasa-jpl/stellar/icons/chevron_down.svg?component'; import CollapseIcon from 'bootstrap-icons/icons/arrow-bar-down.svg?component'; @@ -102,6 +102,7 @@ let menu: Menu; let outputFormats: IOutputFormat[]; let selectedNode: SyntaxNode | null; + let currentTree: Tree; let commandInfoMapper: CommandInfoMapper = new SeqNCommandInfoMapper(); let selectedOutputFormat: IOutputFormat | undefined; let toggleSeqJsonPreview: boolean = false; @@ -361,6 +362,7 @@ commandInfoMapper = new SeqNCommandInfoMapper(); } selectedNode = updatedSelectionNode; + currentTree = tree; } } @@ -539,6 +541,7 @@ {#if !!commandDictionary && !!selectedNode} import type { SyntaxNode } from '@lezer/common'; - import type { CommandDictionary, FswCommandArgument } from '@nasa-jpl/aerie-ampcs'; + import type { CommandDictionary, FswCommandArgument, FswCommandArgumentEnum } from '@nasa-jpl/aerie-ampcs'; import type { CommandInfoMapper } from '../../../utilities/codemirror/commandInfoMapper'; import { getMissingArgDefs, isFswCommandArgumentBoolean, + isFswCommandArgumentEnum, isFswCommandArgumentRepeat, isFswCommandArgumentVarString, isNumberArg, @@ -26,16 +27,37 @@ export let setInEditor: (token: SyntaxNode, val: string) => void; export let addDefaultArgs: (commandNode: SyntaxNode, argDefs: FswCommandArgument[]) => void; export let commandInfoMapper: CommandInfoMapper; + export let variablesInScope: string[]; - $: enableRepeatAdd = - argInfo.argDef && - isFswCommandArgumentRepeat(argInfo.argDef) && + let argDef: FswCommandArgument | undefined = undefined; + let enableRepeatAdd: boolean = false; + + $: argDef = argInfo.argDef; + + $: { + if (argDef && argInfo.node?.name === 'Enum') { + argDef = { + arg_type: 'enum', + bit_length: null, + default_value: null, + description: argDef.description, + enum_name: 'variables', + name: argDef.name, + range: variablesInScope, + } as FswCommandArgumentEnum; + } + } + + $: enableRepeatAdd = !!( + argDef && + isFswCommandArgumentRepeat(argDef) && argInfo.children && - argInfo.argDef.repeat && - argInfo.children.length < argInfo.argDef.repeat.arguments.length * (argInfo.argDef.repeat.max ?? Infinity); + argDef.repeat && + argInfo.children.length < argDef.repeat.arguments.length * (argDef.repeat.max ?? Infinity) + ); function addRepeatTuple() { - const repeatArgs = argInfo.argDef && isFswCommandArgumentRepeat(argInfo.argDef) && argInfo.argDef.repeat?.arguments; + const repeatArgs = argDef && isFswCommandArgumentRepeat(argDef) && argDef.repeat?.arguments; if (argInfo.node && repeatArgs) { addDefaultArgs(argInfo.node, repeatArgs); } @@ -43,7 +65,7 @@
- {#if !argInfo.argDef} + {#if !argDef} {#if argInfo.text}
Unknown Argument
{/if} {:else} - - {#if argInfo.argDef.arg_type === 'enum' && argInfo.node} + + {#if argInfo.node?.name === 'Enum' && isFswCommandArgumentEnum(argDef)} +
Global/Parameter
+ { + if (argInfo.node) { + setInEditor(argInfo.node, val); + } + }} + useQuotes={false} + /> + {:else if argDef.arg_type === 'enum' && argInfo.node} {#if commandInfoMapper.nodeTypeEnumCompatible(argInfo.node)} { if (argInfo.node) { @@ -81,19 +115,19 @@ Convert to enum type {/if} - {:else if isNumberArg(argInfo.argDef) && commandInfoMapper.nodeTypeNumberCompatible(argInfo.node ?? null)} + {:else if isNumberArg(argDef) && commandInfoMapper.nodeTypeNumberCompatible(argInfo.node ?? null)} { if (argInfo.node) { setInEditor(argInfo.node, val.toString()); } }} /> - {:else if isFswCommandArgumentVarString(argInfo.argDef)} + {:else if isFswCommandArgumentVarString(argDef)} { if (argInfo.node) { @@ -101,9 +135,9 @@ } }} /> - {:else if isFswCommandArgumentBoolean(argInfo.argDef)} + {:else if isFswCommandArgumentBoolean(argDef)} { if (argInfo.node) { @@ -111,7 +145,7 @@ } }} /> - {:else if isFswCommandArgumentRepeat(argInfo.argDef) && !!argInfo.children} + {:else if isFswCommandArgumentRepeat(argDef) && !!argInfo.children} {#each argInfo.children as childArgInfo} {#if childArgInfo.node} @@ -125,15 +159,15 @@ } }} /> - {:else if !!argInfo.argDef.repeat} + {:else if !!argDef.repeat}
{/if} diff --git a/src/components/sequencing/form/EnumEditor.svelte b/src/components/sequencing/form/EnumEditor.svelte index 0557b43b67..be43ce967e 100644 --- a/src/components/sequencing/form/EnumEditor.svelte +++ b/src/components/sequencing/form/EnumEditor.svelte @@ -10,19 +10,20 @@ const MAX_SEARCH_ITEMS = 1_000; export let argDef: FswCommandArgumentEnum; - export let commandDictionary: CommandDictionary; + export let commandDictionary: CommandDictionary | null = null; export let initVal: string; export let setInEditor: (val: string) => void; + export let useQuotes: boolean = true; let enumValues: string[]; let isValueInEnum: boolean = false; let value: string; - $: value = unquoteUnescape(initVal); - $: enumValues = commandDictionary.enumMap[argDef.enum_name]?.values?.map(v => v.symbol) ?? argDef.range ?? []; + $: value = useQuotes ? unquoteUnescape(initVal) : initVal; + $: enumValues = commandDictionary?.enumMap[argDef.enum_name]?.values?.map(v => v.symbol) ?? argDef.range ?? []; $: isValueInEnum = !!enumValues.find(ev => ev === value); $: { - setInEditor(quoteEscape(value)); + setInEditor(useQuotes ? quoteEscape(value) : value); } $: options = enumValues.map(ev => ({ display: ev, diff --git a/src/components/sequencing/form/SelectedCommand.svelte b/src/components/sequencing/form/SelectedCommand.svelte index 0c1feff70f..52b0bbf096 100644 --- a/src/components/sequencing/form/SelectedCommand.svelte +++ b/src/components/sequencing/form/SelectedCommand.svelte @@ -1,7 +1,7 @@ -
- {argDef.description} +
+ {#if formattedRange} +
Range
+
{formattedRange}
+ {/if} + + {#if typeInfo} +
Type
+
{typeInfo}
+ {/if} + +
Description
+
+ {argDef.description} +
+ +
Value Type
+ +
+ + diff --git a/src/utilities/codemirror/commandInfoMapper.ts b/src/utilities/codemirror/commandInfoMapper.ts index 4ecfaf6347..b04269e0a4 100644 --- a/src/utilities/codemirror/commandInfoMapper.ts +++ b/src/utilities/codemirror/commandInfoMapper.ts @@ -1,4 +1,5 @@ import type { SyntaxNode, Tree } from '@lezer/common'; +import type { EnumMap, FswCommandArgument } from '@nasa-jpl/aerie-ampcs'; export interface CommandInfoMapper { /** format string of multiple arguments */ @@ -16,6 +17,8 @@ export interface CommandInfoMapper { /** ascends parse tree to find scope to display in form editor */ getContainingCommand(node: SyntaxNode | null): SyntaxNode | null; + getDefaultValueForArgumentDef(argDef: FswCommandArgument, enumMap: EnumMap): string; + /** finds the node in the parse tree containing the name */ getNameNode(stepNode: SyntaxNode | null): SyntaxNode | null; diff --git a/src/utilities/codemirror/seq-n-tree-utils.ts b/src/utilities/codemirror/seq-n-tree-utils.ts index 38d733d6c9..12045baa5a 100644 --- a/src/utilities/codemirror/seq-n-tree-utils.ts +++ b/src/utilities/codemirror/seq-n-tree-utils.ts @@ -1,4 +1,5 @@ import type { SyntaxNode, Tree } from '@lezer/common'; +import type { EnumMap, FswCommandArgument } from '@nasa-jpl/aerie-ampcs'; import { RULE_ARGS, RULE_COMMAND, @@ -16,6 +17,7 @@ import { TOKEN_REQUEST, TOKEN_STRING, } from '../../constants/seq-n-grammar-constants'; +import { fswCommandArgDefault } from '../sequence-editor/command-dictionary'; import { validateVariables } from '../sequence-editor/sequence-linter'; import { getFromAndTo, getNearestAncestorNodeOfType } from '../sequence-editor/tree-utils'; import type { CommandInfoMapper } from './commandInfoMapper'; @@ -86,6 +88,10 @@ export class SeqNCommandInfoMapper implements CommandInfoMapper { return getAncestorStepOrRequest(node); } + getDefaultValueForArgumentDef(argDef: FswCommandArgument, enumMap: EnumMap): string { + return fswCommandArgDefault(argDef, enumMap); + } + getNameNode(stepNode: SyntaxNode | null): SyntaxNode | null { return getNameNode(stepNode); } diff --git a/src/utilities/codemirror/vml/vmlAdaptation.ts b/src/utilities/codemirror/vml/vmlAdaptation.ts index 8436915b47..cce847c934 100644 --- a/src/utilities/codemirror/vml/vmlAdaptation.ts +++ b/src/utilities/codemirror/vml/vmlAdaptation.ts @@ -1,6 +1,6 @@ import { type CompletionContext, type CompletionResult } from '@codemirror/autocomplete'; import { syntaxTree } from '@codemirror/language'; -import type { CommandDictionary, FswCommand, FswCommandArgument } from '@nasa-jpl/aerie-ampcs'; +import type { CommandDictionary, EnumMap, FswCommand, FswCommandArgument } from '@nasa-jpl/aerie-ampcs'; import { getNearestAncestorNodeOfType } from '../../sequence-editor/tree-utils'; import { RULE_FUNCTION_NAME, RULE_ISSUE, RULE_STATEMENT, TOKEN_STRING_CONST } from './vmlConstants'; import { getArgumentPosition } from './vmlTreeUtils'; @@ -72,12 +72,12 @@ export function vmlAutoComplete( function getStemAndDefaultArguments(commandDictionary: CommandDictionary, cmd: FswCommand): string { if (cmd.arguments.length) { - return `${cmd.stem} ${cmd.arguments.map(argNode => getDefaultArgumentValue(commandDictionary, argNode)).join(',')}`; + return `${cmd.stem} ${cmd.arguments.map(argNode => getDefaultArgumentValue(argNode, commandDictionary.enumMap)).join(',')}`; } return cmd.stem; } -function getDefaultArgumentValue(commandDictionary: CommandDictionary, argDef: FswCommandArgument): string { +export function getDefaultArgumentValue(argDef: FswCommandArgument, enumMap: EnumMap): string { switch (argDef.arg_type) { case 'boolean': return argDef.default_value ?? 'TRUE'; @@ -88,7 +88,7 @@ function getDefaultArgumentValue(commandDictionary: CommandDictionary, argDef: F // ignores conversion setting return (argDef.default_value ?? argDef.range?.min)?.toString(10) ?? '0'; case 'enum': - return `"${commandDictionary.enumMap[argDef.enum_name]?.values[0]?.symbol ?? ''}"`; + return `"${enumMap[argDef.enum_name]?.values[0]?.symbol ?? ''}"`; case 'var_string': return '""'; } diff --git a/src/utilities/codemirror/vml/vmlTreeUtils.ts b/src/utilities/codemirror/vml/vmlTreeUtils.ts index 177c59a22c..72915573b2 100644 --- a/src/utilities/codemirror/vml/vmlTreeUtils.ts +++ b/src/utilities/codemirror/vml/vmlTreeUtils.ts @@ -1,4 +1,5 @@ import type { SyntaxNode, Tree } from '@lezer/common'; +import type { EnumMap, FswCommandArgument } from '@nasa-jpl/aerie-ampcs'; import { filterNodesToArray, getChildrenNode, @@ -6,6 +7,7 @@ import { isDefined, } from '../../sequence-editor/tree-utils'; import type { CommandInfoMapper } from '../commandInfoMapper'; +import { getDefaultArgumentValue } from './vmlAdaptation'; import { RULE_CALL_PARAMETER, RULE_CALL_PARAMETERS, @@ -65,6 +67,10 @@ export class VmlCommandInfoMapper implements CommandInfoMapper { return getNearestAncestorNodeOfType(node, [RULE_TIME_TAGGED_STATEMENT]); } + getDefaultValueForArgumentDef(argDef: FswCommandArgument, enumMap: EnumMap): string { + return getDefaultArgumentValue(argDef, enumMap); + } + getNameNode(statementNode: SyntaxNode | null): SyntaxNode | null { const statementSubNode = statementNode?.getChild(RULE_STATEMENT)?.getChild(RULE_ISSUE); if (statementSubNode?.name === RULE_ISSUE) { From 6f19573909d84e837d8b2a8a997f09146dbefe90 Mon Sep 17 00:00:00 2001 From: Chet Joswig Date: Tue, 5 Nov 2024 07:10:44 -0800 Subject: [PATCH 07/18] change term reference to symbol --- src/components/sequencing/form/ArgEditor.svelte | 10 +++++----- src/components/sequencing/form/ArgTitle.svelte | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/sequencing/form/ArgEditor.svelte b/src/components/sequencing/form/ArgEditor.svelte index 064560850e..e23d5be9ee 100644 --- a/src/components/sequencing/form/ArgEditor.svelte +++ b/src/components/sequencing/form/ArgEditor.svelte @@ -31,13 +31,13 @@ let argDef: FswCommandArgument | undefined = undefined; let enableRepeatAdd: boolean = false; - let isVariable: boolean = false; + let isSymbol: boolean = false; $: argDef = argInfo.argDef; $: { - isVariable = commandInfoMapper.isArgumentNodeOfVariableType(argInfo.node ?? null); - if (!!argDef && isVariable) { + isSymbol = commandInfoMapper.isArgumentNodeOfVariableType(argInfo.node ?? null); + if (!!argDef && isSymbol) { argDef = { arg_type: 'enum', bit_length: null, @@ -84,7 +84,7 @@ { if (argInfo.node) { setInEditor(argInfo.node, val); @@ -92,7 +92,7 @@ }} /> {/if} - {#if isVariable && isFswCommandArgumentEnum(argDef)} + {#if isSymbol && isFswCommandArgumentEnum(argDef)}
Reference
void; - export let argumentValueCategory: 'Literal' | 'Reference'; + export let argumentValueCategory: 'Literal' | 'Symbol'; let title: string = ''; let typeInfo: string = ''; @@ -105,7 +105,7 @@
From 60c7f57731bfa33a823323b44631ad6dac2c2a18 Mon Sep 17 00:00:00 2001 From: Chet Joswig Date: Tue, 5 Nov 2024 16:18:34 -0800 Subject: [PATCH 08/18] readability of enable repeat args check --- src/components/sequencing/form/ArgEditor.svelte | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/components/sequencing/form/ArgEditor.svelte b/src/components/sequencing/form/ArgEditor.svelte index e23d5be9ee..ed1b665a0b 100644 --- a/src/components/sequencing/form/ArgEditor.svelte +++ b/src/components/sequencing/form/ArgEditor.svelte @@ -50,13 +50,12 @@ } } - $: enableRepeatAdd = !!( - argDef && + $: enableRepeatAdd = + argDef !== undefined && isFswCommandArgumentRepeat(argDef) && - argInfo.children && - argDef.repeat && - argInfo.children.length < argDef.repeat.arguments.length * (argDef.repeat.max ?? Infinity) - ); + argInfo.children !== undefined && + argDef.repeat !== null && + argInfo.children.length < argDef.repeat.arguments.length * (argDef.repeat.max ?? Infinity); function addRepeatTuple() { const repeatArgs = argDef && isFswCommandArgumentRepeat(argDef) && argDef.repeat?.arguments; From 9eea635fea3281d0a27e9ceb53aea46f7585545a Mon Sep 17 00:00:00 2001 From: Chet Joswig Date: Tue, 5 Nov 2024 16:38:12 -0800 Subject: [PATCH 09/18] don't use symbol for boolean test --- e2e-tests/fixtures/Sequence.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e-tests/fixtures/Sequence.ts b/e2e-tests/fixtures/Sequence.ts index 9a01ce501a..45c2d05a56 100644 --- a/e2e-tests/fixtures/Sequence.ts +++ b/e2e-tests/fixtures/Sequence.ts @@ -165,14 +165,14 @@ export class Sequence { await this.page.waitForTimeout(1000); expect(await this.linter.count()).toBe(0); - await expect(this.command).toHaveText('C FSW_CMD_0 "ON" false 1'); + await expect(this.command).toHaveText('C FSW_CMD_0 "ON" "false" 1'); await this.page .locator('fieldset') .filter({ hasText: 'enum_arg_0 ONOFF' }) .getByRole('combobox') .selectOption('OFF'); - await expect(this.command).toHaveText('C FSW_CMD_0 "OFF" false 1'); + await expect(this.command).toHaveText('C FSW_CMD_0 "OFF" "false" 1'); await this.page.getByRole('button', { name: 'Save' }).click(); await this.page.getByRole('button', { name: 'Close' }).click(); From ab58482c3f3a3275b5055cac6b6995528a482758 Mon Sep 17 00:00:00 2001 From: Chet Joswig Date: Tue, 5 Nov 2024 18:51:14 -0800 Subject: [PATCH 10/18] pr feedback reactive statement not triggered --- e2e-tests/fixtures/Sequence.ts | 4 ++-- src/components/sequencing/form/ArgTitle.svelte | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/e2e-tests/fixtures/Sequence.ts b/e2e-tests/fixtures/Sequence.ts index 45c2d05a56..9a01ce501a 100644 --- a/e2e-tests/fixtures/Sequence.ts +++ b/e2e-tests/fixtures/Sequence.ts @@ -165,14 +165,14 @@ export class Sequence { await this.page.waitForTimeout(1000); expect(await this.linter.count()).toBe(0); - await expect(this.command).toHaveText('C FSW_CMD_0 "ON" "false" 1'); + await expect(this.command).toHaveText('C FSW_CMD_0 "ON" false 1'); await this.page .locator('fieldset') .filter({ hasText: 'enum_arg_0 ONOFF' }) .getByRole('combobox') .selectOption('OFF'); - await expect(this.command).toHaveText('C FSW_CMD_0 "OFF" "false" 1'); + await expect(this.command).toHaveText('C FSW_CMD_0 "OFF" false 1'); await this.page.getByRole('button', { name: 'Save' }).click(); await this.page.getByRole('button', { name: 'Close' }).click(); diff --git a/src/components/sequencing/form/ArgTitle.svelte b/src/components/sequencing/form/ArgTitle.svelte index 0a82c125a0..69bb0bdb08 100644 --- a/src/components/sequencing/form/ArgTitle.svelte +++ b/src/components/sequencing/form/ArgTitle.svelte @@ -23,8 +23,8 @@ let typeInfo: string = ''; let formattedRange: string = ''; - $: title = getArgTitle(argDef); $: typeInfo = compactType(argDef); + $: title = getArgTitle(argDef, typeInfo); $: formattedRange = formatRange(argDef); function compactType(argDef: FswCommandArgument): string { @@ -52,7 +52,7 @@ return ''; } - function getArgTitle(argDef: FswCommandArgument): string { + function getArgTitle(argDef: FswCommandArgument, typeInfo: string): string { if ( isFswCommandArgumentRepeat(argDef) && typeof argDef.repeat?.max === 'number' && @@ -96,10 +96,12 @@
{typeInfo}
{/if} -
Description
-
- {argDef.description} -
+ {#if argDef.description} +
Description
+
+ {argDef.description} +
+ {/if}
Value Type
From ccd57ec47a50c836d876f86e3f875ab726f7f987 Mon Sep 17 00:00:00 2001 From: Chet Joswig Date: Tue, 5 Nov 2024 19:05:05 -0800 Subject: [PATCH 11/18] pr feedback - combine template literals where possible --- src/components/sequencing/form/ArgTitle.svelte | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/sequencing/form/ArgTitle.svelte b/src/components/sequencing/form/ArgTitle.svelte index 69bb0bdb08..40003a9e45 100644 --- a/src/components/sequencing/form/ArgTitle.svelte +++ b/src/components/sequencing/form/ArgTitle.svelte @@ -61,11 +61,8 @@ return `${argDef.name} - [${argDef.repeat?.min}, ${argDef.repeat?.max}] sets`; } - let compactTypeInfo = typeInfo; - if (compactTypeInfo) { - compactTypeInfo = ` [${compactTypeInfo}]`; - } - let base = `${argDef.name}${compactTypeInfo}${formatRange(argDef)}`; + const bracketedTypeInfo = typeInfo && ` [${typeInfo}]`; + const base = `${argDef.name}${bracketedTypeInfo} ${formatRange(argDef)}`; if ('units' in argDef) { return `${base} – (${argDef.units})`; From d2b41146f5d8a85041a2500aa41c5fd9809563ca Mon Sep 17 00:00:00 2001 From: Chet Joswig Date: Tue, 5 Nov 2024 19:14:29 -0800 Subject: [PATCH 12/18] pr feedback variable name --- src/components/sequencing/form/SelectedCommand.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/sequencing/form/SelectedCommand.svelte b/src/components/sequencing/form/SelectedCommand.svelte index d49363f4a5..af6d3fb448 100644 --- a/src/components/sequencing/form/SelectedCommand.svelte +++ b/src/components/sequencing/form/SelectedCommand.svelte @@ -67,7 +67,7 @@ $: variablesInScope = getVariablesInScope(tree, commandNode?.from); function getVariablesInScope(tree: Tree | null, cursorPosition?: number): string[] { - const globalNames = ($sequenceAdaptation.globals ?? []).map(v => v.name); + const globalNames = ($sequenceAdaptation.globals ?? []).map(globalVariable => globalVariable.name); if (tree && cursorPosition !== undefined) { const docText = editorSequenceView.state.doc.toString(); return [...globalNames, ...commandInfoMapper.getVariables(docText, tree, cursorPosition)]; From c1a4b18d1ee92a43a5692fe0fc577a92f82d300f Mon Sep 17 00:00:00 2001 From: Chet Joswig Date: Tue, 5 Nov 2024 19:29:23 -0800 Subject: [PATCH 13/18] use filterEmpty instead of new duplicate function --- src/utilities/codemirror/vml/vmlBlockLibrary.ts | 8 ++++---- src/utilities/codemirror/vml/vmlFormatter.ts | 8 ++++---- src/utilities/codemirror/vml/vmlTreeUtils.ts | 12 ++++-------- src/utilities/sequence-editor/tree-utils.ts | 4 ---- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/utilities/codemirror/vml/vmlBlockLibrary.ts b/src/utilities/codemirror/vml/vmlBlockLibrary.ts index fe60a16575..7d6e460e91 100644 --- a/src/utilities/codemirror/vml/vmlBlockLibrary.ts +++ b/src/utilities/codemirror/vml/vmlBlockLibrary.ts @@ -8,7 +8,7 @@ import type { HwCommand, NumericRange, } from '@nasa-jpl/aerie-ampcs'; -import { isDefined } from '../../sequence-editor/tree-utils'; +import { filterEmpty } from '../../generic'; import { VmlLanguage } from './vml'; import { RULE_BLOCK, @@ -50,7 +50,7 @@ export function vmlBlockLibraryToCommandDictionary(vml: string, id?: string, pat ...(parsed.topNode.getChild(RULE_FUNCTIONS)?.getChildren(RULE_FUNCTION) ?? []).map(blockNode => blockToCommandDef(blockNode, vml), ), - ].filter(isDefined); + ].filter(filterEmpty); const mission_name = ''; const spacecraft_ids = [0]; @@ -85,7 +85,7 @@ function blockToCommandDef(functionNode: SyntaxNode, vml: string): FswCommand | const parameterNodes = commonFunctionNode?.getChild(RULE_PARAMETERS)?.getChildren(RULE_PARAMETER) ?? []; const fswArguments: FswCommandArgument[] = parameterNodes ?.map(parameterNode => inputToArgument(parameterNode, vml)) - .filter(isDefined); + .filter(filterEmpty); if (stem) { return { @@ -206,7 +206,7 @@ function parseRange(parameterNode: SyntaxNode | null, vml: string): null | strin } return null; }) - .filter(isDefined); + .filter(filterEmpty); // mixed arrays aren't resolved due to undefined meaning if (rangeValues.every(rangeValue => typeof rangeValue === 'number')) { diff --git a/src/utilities/codemirror/vml/vmlFormatter.ts b/src/utilities/codemirror/vml/vmlFormatter.ts index 95ae50edaa..fd796a719e 100644 --- a/src/utilities/codemirror/vml/vmlFormatter.ts +++ b/src/utilities/codemirror/vml/vmlFormatter.ts @@ -2,7 +2,7 @@ import { syntaxTree } from '@codemirror/language'; import type { ChangeSpec, EditorState } from '@codemirror/state'; import type { SyntaxNode } from '@lezer/common'; import { EditorView } from 'codemirror'; -import { isDefined } from '../../sequence-editor/tree-utils'; +import { filterEmpty } from '../../generic'; import { RULE_ASSIGNMENT, RULE_CALL_PARAMETERS, @@ -143,7 +143,7 @@ export function vmlFormat(view: EditorView): void { const docText = state.toText(state.sliceDoc()); const maybeChanges = linesToFormat.flatMap((line: LineOfNodes) => { - const firstNode = line.find(isDefined); + const firstNode = line.find(filterEmpty); if (firstNode === undefined) { // unexpected case of no nodes on line return []; @@ -151,7 +151,7 @@ export function vmlFormat(view: EditorView): void { const commandLine = docText.lineAt(firstNode.from); - const filteredArray: SyntaxNode[] = line.filter(isDefined); + const filteredArray: SyntaxNode[] = line.filter(filterEmpty); const deletions: ChangeSpec[] = []; // remove indentation at start of line @@ -210,7 +210,7 @@ export function vmlFormat(view: EditorView): void { return [...deletions, ...insertions]; }); - const changes = [...commandIndentChangeMap.values(), ...maybeChanges.filter(isDefined)]; + const changes = [...commandIndentChangeMap.values(), ...maybeChanges.filter(filterEmpty)]; // Consider delete end of line whitespace // Consider alignment of comments diff --git a/src/utilities/codemirror/vml/vmlTreeUtils.ts b/src/utilities/codemirror/vml/vmlTreeUtils.ts index 72915573b2..a3c7cf3f22 100644 --- a/src/utilities/codemirror/vml/vmlTreeUtils.ts +++ b/src/utilities/codemirror/vml/vmlTreeUtils.ts @@ -1,11 +1,7 @@ import type { SyntaxNode, Tree } from '@lezer/common'; import type { EnumMap, FswCommandArgument } from '@nasa-jpl/aerie-ampcs'; -import { - filterNodesToArray, - getChildrenNode, - getNearestAncestorNodeOfType, - isDefined, -} from '../../sequence-editor/tree-utils'; +import { filterEmpty } from '../../generic'; +import { filterNodesToArray, getChildrenNode, getNearestAncestorNodeOfType } from '../../sequence-editor/tree-utils'; import type { CommandInfoMapper } from '../commandInfoMapper'; import { getDefaultArgumentValue } from './vmlAdaptation'; import { @@ -94,7 +90,7 @@ export class VmlCommandInfoMapper implements CommandInfoMapper { ?.getChild(RULE_VARIABLE_NAME_CONSTANT) ?.getChild(RULE_VARIABLE_NAME), ) - .filter(isDefined) + .filter(filterEmpty) .map(node => docText.slice(node.from, node.to)); const positionNode = tree.resolveInner(position); @@ -105,7 +101,7 @@ export class VmlCommandInfoMapper implements CommandInfoMapper { [RULE_INPUT_PARAMETER, RULE_INPUT_OUTPUT_PARAMETER, RULE_VARIABLE_NAME_CONSTANT].includes(node.name), ) .map(node => node.getChild(RULE_VARIABLE_NAME)) - .filter(isDefined) + .filter(filterEmpty) .map(node => docText.slice(subTreeOffset + node.from, subTreeOffset + node.to)); return [...moduleVariables, ...commonFunctionParametersAndVariables]; } diff --git a/src/utilities/sequence-editor/tree-utils.ts b/src/utilities/sequence-editor/tree-utils.ts index 5ecd03611c..6f8b58c5f2 100644 --- a/src/utilities/sequence-editor/tree-utils.ts +++ b/src/utilities/sequence-editor/tree-utils.ts @@ -93,7 +93,3 @@ export function filterNodesToArray(cursor: TreeCursor, filter?: (node: SyntaxNod export function nodeContents(input: string, node: SyntaxNode): string { return input.substring(node.from, node.to); } - -export function isDefined(maybeValue: Type | null | undefined): maybeValue is Type { - return maybeValue !== null && maybeValue !== undefined; -} From c22075141cf1b178fe1a314234859948f3957d75 Mon Sep 17 00:00:00 2001 From: Chet Joswig Date: Thu, 7 Nov 2024 16:26:32 -0800 Subject: [PATCH 14/18] move CSS attribute to parent, playwrigth selector update --- e2e-tests/fixtures/Sequence.ts | 2 +- src/components/sequencing/form/ArgTitle.svelte | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/e2e-tests/fixtures/Sequence.ts b/e2e-tests/fixtures/Sequence.ts index 9a01ce501a..55e588b2c8 100644 --- a/e2e-tests/fixtures/Sequence.ts +++ b/e2e-tests/fixtures/Sequence.ts @@ -168,7 +168,7 @@ export class Sequence { await expect(this.command).toHaveText('C FSW_CMD_0 "ON" false 1'); await this.page .locator('fieldset') - .filter({ hasText: 'enum_arg_0 ONOFF' }) + .filter({ hasText: 'enum_arg_0 Value Type Literal' }) .getByRole('combobox') .selectOption('OFF'); diff --git a/src/components/sequencing/form/ArgTitle.svelte b/src/components/sequencing/form/ArgTitle.svelte index 40003a9e45..41116053d3 100644 --- a/src/components/sequencing/form/ArgTitle.svelte +++ b/src/components/sequencing/form/ArgTitle.svelte @@ -112,16 +112,13 @@