Skip to content

Commit

Permalink
Added optional objects to input parameters (#1437)
Browse files Browse the repository at this point in the history
* Rough prototype of workspaces

* Added the sequence header back in

* More workspace improvements, navigation and persistance working now

* Added optional objects to input parameters

* Added the parsed input_parameter fields to seqjson

* Added linting rules for input parameter objects

* Added input param metadata parsing to from-seq-json

* Fixed a duplicated style in the SequenceTable

* Fixed 2 from-seq-json unit tests
  • Loading branch information
cohansen authored Sep 3, 2024
1 parent 0af6fc4 commit dbccc45
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/components/sequencing/Sequences.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
export let user: User | null;
let filterText: string = '';
let filterText = '';
let parcel: Parcel | null;
let selectedSequence: UserSequence | null = null;
let workspace: Workspace | undefined;
Expand Down
2 changes: 1 addition & 1 deletion src/utilities/codemirror/sequence.grammar
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ IdDeclaration {
}

ParameterDeclaration {
parameterDirective (whiteSpace Enum)+ newLine
parameterDirective whiteSpace ((Enum whiteSpace?) | (Enum whiteSpace? Object whiteSpace?))+ newLine
}

LocalDeclaration {
Expand Down
2 changes: 1 addition & 1 deletion src/utilities/sequence-editor/from-seq-json.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ C FSW_CMD_3
};
const sequence = await seqJsonToSequence(JSON.stringify(seqJson));
const expectedSequence = `@ID "testVariable"
@INPUT_PARAMS L00INT L01STR L02FLT L03UINT L01ENUM
@INPUT_PARAMS L00INT { "type": "INT" } L01STR { "type": "STRING" } L02FLT { "type": "FLOAT" } L03UINT { "type": "UINT" } L01ENUM { "type": "ENUM" }
@LOCALS L00INT L01STR L02FLT L03UINT L01ENUM
`;
expect(sequence).toEqual(expectedSequence);
Expand Down
25 changes: 24 additions & 1 deletion src/utilities/sequence-editor/from-seq-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,30 @@ function seqJsonVariableToSequence(
variables: [VariableDeclaration, ...VariableDeclaration[]],
type: 'INPUT_PARAMS' | 'LOCALS',
): string {
return `@${type} ${variables.map(variable => variable.name).join(' ')}\n`;
let sequence = `@${type}`;

if (type === 'INPUT_PARAMS') {
variables.forEach(variable => {
sequence += ` ${variable.name} `;

if (Object.keys(variable).length > 1) {
sequence += '{ ';

for (const key of Object.keys(variable)) {
if (key !== 'name') {
sequence += `"${key}": "${variable[key]}", `;
}
}

// Remove the trailing space and commma from the last property.
sequence = `${sequence.substring(0, sequence.length - 2)} }`;
}
});
} else {
sequence += ` ${variables.map(variable => variable.name).join(' ')}`;
}

return sequence.trim() + '\n';
}

function seqJsonDescriptionToSequence(description: Description): string {
Expand Down
4 changes: 2 additions & 2 deletions src/utilities/sequence-editor/grammar.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ RepeatArg(Number,Number)
[
'Locals and commands',
`# comment before parameter
@INPUT_PARAMS L02INT
@INPUT_PARAMS L02INT { "name": "test" }
# declare my local variables, types are defined in adaptation
# comment before directive
@LOCALS L01STRING L02INT
Expand All @@ -111,7 +111,7 @@ FSW_CMD 1 2
FSW_CMD2`,
`Sequence(
LineComment,
ParameterDeclaration(Enum),
ParameterDeclaration(Enum,Object(Property(PropertyName(String),String))),
LineComment,
LineComment,
LocalDeclaration(Enum,Enum),
Expand Down
68 changes: 64 additions & 4 deletions src/utilities/sequence-editor/sequence-linter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -392,26 +392,86 @@ export function sequenceLinter(
}) as const,
),
);

inputParams.forEach(inputParam => {
let child = inputParam.firstChild;

while (child) {
if (child.name !== 'Enum') {
if (child.name !== 'Enum' && child.name !== 'Object') {
diagnostics.push({
from: child.from,
message: `@INPUT_PARAMS values are required to be Enums`,
severity: 'error',
to: child.to,
});
} else {
variables.push({
const variable = {
name: text.slice(child.from, child.to),
// TODO - hook to check mission specific nomenclature
type: 'STRING',
});
} as VariableDeclaration;

variables.push(variable);

const metadata: SyntaxNode | null = child?.nextSibling;

if (metadata !== null) {
const properties = metadata.getChildren('Property');
let allowableRanges: string | undefined = undefined;
let isEnum = false;
let isString = false;
let enumName: string | undefined = undefined;

properties.forEach(property => {
const propertyNameNode = property.getChild('PropertyName');
const propertyValueNode = propertyNameNode?.nextSibling;

if (propertyNameNode !== null && propertyValueNode !== null && propertyValueNode !== undefined) {
const propertyName = text.slice(propertyNameNode.from, propertyNameNode.to);
const propertyValue = text.slice(propertyValueNode.from, propertyValueNode.to);

switch (propertyName.toLowerCase()) {
case '"allowable_ranges"':
allowableRanges = propertyValue;
break;
case '"enum_name"':
enumName = propertyValue;
break;
case '"type"':
isEnum = propertyValue === '"ENUM"';
isString = propertyValue === '"STRING"';
break;
}
}
});

if (isEnum && enumName === undefined) {
diagnostics.push({
from: child.from,
message: '"enum_name" is required for ENUM type.',
severity: 'error',
to: child.to,
});
} else if (!isEnum && enumName !== undefined) {
diagnostics.push({
from: child.from,
message: `"enum_name": ${enumName} is not required for non-ENUM type.`,
severity: 'error',
to: child.to,
});
} else if (isString && allowableRanges !== undefined) {
diagnostics.push({
from: child.from,
message: `'allowable_ranges' is not required for STRING type.`,
severity: 'error',
to: child.to,
});
}
}
}
child = child.nextSibling;
}
});

return {
diagnostics,
variables,
Expand Down
57 changes: 42 additions & 15 deletions src/utilities/sequence-editor/to-seq-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,36 +454,63 @@ function parseVariables(
return undefined;
}

return variables.map((variable: SyntaxNode) => {
const variableText = text.slice(variable.from, variable.to);
const objects = variableContainer.getChildren('Object');

return variables.map((variableNode: SyntaxNode) => {
const variableText = text.slice(variableNode.from, variableNode.to);
const variable: Omit<VariableDeclaration, 'allowable_ranges' | 'allowable_values'> & {
allowable_ranges?: string;
allowable_values?: string;
} = { name: variableText, type: 'UNKNOWN' };

for (const object of objects) {
const properties = object.getChildren('Property');

properties.forEach(property => {
const propertyName = property.getChild('PropertyName');
const propertyValue = propertyName?.nextSibling;
const propertyNameString = text.slice(propertyName?.from, propertyName?.to).replaceAll('"', '');
const propertyValueString = text.slice(propertyValue?.from, propertyValue?.to).replaceAll('"', '');

switch (propertyNameString.toLowerCase()) {
case 'allowable_ranges':
variable.allowable_ranges = propertyValueString;
break;
case 'allowable_values':
variable.allowable_values = propertyValueString;
break;
case 'enum_name':
variable.enum_name = propertyValueString;
break;
case 'sc_name':
variable.sc_name = propertyValueString;
break;
case 'type':
variable.type = propertyValueString;
break;
}
});
}

//parse the text [a-z]D*("UINT"|"INT"|"FLOAT"|"ENUM"|"STR")L07
const match = /(?:[a-zA-Z]*)(?:[0-9]{2})(INT|UINT|FLT|ENUM|STR)/g.exec(variableText);
if (match) {
const kind = match[1];

let type = 'UNKNOWN';
switch (kind) {
case 'STR':
type = 'STRING';
variable.type = 'STRING';
break;
case 'FLT':
type = 'FLOAT';
variable.type = 'FLOAT';
break;
default:
type = kind;
variable.type = kind;
break;
}

return {
name: variableText,
type: type as VariableDeclaration['type'],
};
return variable;
} else {
return {
name: variableText,
type: 'UNKNOWN' as VariableDeclaration['type'],
};
return variable;
}
}) as VariableDeclarationArray;
}
Expand Down

0 comments on commit dbccc45

Please sign in to comment.