Skip to content

Commit

Permalink
Add support to fold Parameter and Local blocks
Browse files Browse the repository at this point in the history
* Updated the unit test
  • Loading branch information
goetzrrGit committed Oct 8, 2024
1 parent b0756cf commit 522e146
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 1 deletion.
56 changes: 55 additions & 1 deletion src/utilities/codemirror/custom-folder.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { EditorState } from '@codemirror/state';
import { describe, expect, test } from 'vitest';
import { foldRequest, foldSteps } from './custom-folder';
import { foldRequest, foldSteps, foldVariables } from './custom-folder';
import { parser } from './sequence.grammar';

const COMMANDS = [
Expand All @@ -23,6 +23,21 @@ const GROUND_ACTIVITIES = [
'E-00:00:00.001 @GROUND_EVENT("event1")',
];

const PARAMETERS = [
`@INPUT_PARAMS_BEGIN
VARIABLE INT "MIN...MAX | ...MAX | MIN..." "VALUE_1, VALUE_2, ..."
@INPUT_PARAMS_END`,
`@INPUT_PARAMS_BEGIN
@INPUT_PARAMS_END`,
];

const LOCALS = [
`@LOCALS_BEGIN
VARIABLE INT
TEST FLOAT ENUM
@LOCALS_END`,
];

const REQUEST_ACTIVITIES = [
`G+00:00:00 "Name" @REQUEST_BEGIN("request.name")
C SEQ_ECHO ""
Expand Down Expand Up @@ -345,3 +360,42 @@ describe('foldRequest', () => {
});
});
});

describe('foldVariables', () => {
test('Parameters should return the correct from and to', () => {
PARAMETERS.forEach(parameter => {
const doc = `${parameter}`;
const tree = parser.parse(doc);
const state = EditorState.create({ doc });

const node = tree.topNode.getChild('ParameterDeclaration');
if (!node) {
throw new Error('node not found');
} else {
expect(node).not.toBeNull();
expect(foldVariables(node, state)).toStrictEqual({
from: '@INPUT_PARAMS_BEGIN'.length,
to: doc.length,
});
}
});
});
test('Parameters should return the correct from and to', () => {
LOCALS.forEach(local => {
const doc = `${local}`;
const tree = parser.parse(doc);
const state = EditorState.create({ doc });

const node = tree.topNode.getChild('LocalDeclaration');
if (!node) {
throw new Error('node not found');
} else {
expect(node).not.toBeNull();
expect(foldVariables(node, state)).toStrictEqual({
from: '@LOCALS_BEGIN'.length,
to: doc.length,
});
}
});
});
});
36 changes: 36 additions & 0 deletions src/utilities/codemirror/custom-folder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ export function customFoldInside(node: SyntaxNode, state: EditorState): { from:
return foldMetadataOrModel(node, state, '@Metadata');
case 'Models':
return foldMetadataOrModel(node, state, '@Model');
case 'ParameterDeclaration':
case 'LocalDeclaration':
return foldVariables(node, state);
}
return null;
}
Expand Down Expand Up @@ -107,6 +110,39 @@ export function foldRequest(requestNode: SyntaxNode, state: EditorState): { from
return { from, to: endRequest };
}

/**
* Calculate the fold range for a block of variables.
* The fold range starts after the prefix of the block (e.g. "@INPUT_PARAMETERS_BEGIN" or "@LOCALS_BEGIN")
* and ends of the block.
* If the text ends with a line break, the end of the fold range will be adjusted to the start of the line break.
*
* @param containerNode - The node containing the variables (e.g. ParameterDeclaration or LocalDeclaration).
* @param state - The EditorState object.
* @returns A fold range object with "from" and "to" properties.
* Returns null if any of the necessary nodes are not present.
*/
export function foldVariables(containerNode: SyntaxNode, state: EditorState): { from: number; to: number } | null {
// Get all the Variable nodes in the container node
const variablesNodes = containerNode.getChildren('Variable');

// Calculate the length of the directive (e.g. "@INPUT_PARAMETERS_BEGIN" or "@LOCALS_BEGIN")
const directiveLength = state
.sliceDoc(containerNode.from, containerNode.to - variablesNodes.length ? getFromAndTo([...variablesNodes]).from : 0)
.split('\n')[0].length;

// Calculate the start of the fold range after the directive
const from = containerNode.from + directiveLength;

// Calculate the end of the fold range after the last Variable node
let endBlock = getFromAndTo([containerNode]).to;

// If the text ends with a line break, adjust the end of the fold range to the start of the line break
const text = state.sliceDoc(containerNode.from + directiveLength, endBlock).trimEnd() + '\n';
endBlock = from + text.lastIndexOf('\n');

return { from, to: endBlock };
}

/**
* Calculate the fold range for a Metadata or Model node.
* The fold range starts after the node's prefix (e.g. "@Metadata" or "@Model") and ends after the node.
Expand Down
2 changes: 2 additions & 0 deletions src/utilities/codemirror/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ export const SeqLanguage = LRLanguage.define({
GroundBlock: customFoldInside,
GroundEvent: customFoldInside,
Load: customFoldInside,
LocalDeclaration: customFoldInside,
Metadata: customFoldInside,
Models: customFoldInside,
ParameterDeclaration: customFoldInside,
Request: customFoldInside,
}),
styleTags({
Expand Down

0 comments on commit 522e146

Please sign in to comment.