Skip to content

Commit e1db224

Browse files
committed
Add support to fold Parameter and Local blocks
* Updated the unit test
1 parent 28ae4b5 commit e1db224

File tree

3 files changed

+93
-1
lines changed

3 files changed

+93
-1
lines changed

src/utilities/codemirror/custom-folder.test.ts

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { EditorState } from '@codemirror/state';
22
import { describe, expect, test } from 'vitest';
3-
import { foldRequest, foldSteps } from './custom-folder';
3+
import { foldRequest, foldSteps, foldVariables } from './custom-folder';
44
import { parser } from './sequence.grammar';
55

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

26+
const PARAMETERS = [
27+
`@INPUT_PARAMS_BEGIN
28+
VARIABLE INT "MIN...MAX | ...MAX | MIN..." "VALUE_1, VALUE_2, ..."
29+
@INPUT_PARAMS_END`,
30+
`@INPUT_PARAMS_BEGIN
31+
@INPUT_PARAMS_END`,
32+
];
33+
34+
const LOCALS = [
35+
`@LOCALS_BEGIN
36+
VARIABLE INT
37+
TEST FLOAT ENUM
38+
@LOCALS_END`,
39+
];
40+
2641
const REQUEST_ACTIVITIES = [
2742
`G+00:00:00 "Name" @REQUEST_BEGIN("request.name")
2843
C SEQ_ECHO ""
@@ -345,3 +360,42 @@ describe('foldRequest', () => {
345360
});
346361
});
347362
});
363+
364+
describe('foldVariables', () => {
365+
test('Parameters should return the correct from and to', () => {
366+
PARAMETERS.forEach(parameter => {
367+
const doc = `${parameter}`;
368+
const tree = parser.parse(doc);
369+
const state = EditorState.create({ doc });
370+
371+
const node = tree.topNode.getChild('ParameterDeclaration');
372+
if (!node) {
373+
throw new Error('node not found');
374+
} else {
375+
expect(node).not.toBeNull();
376+
expect(foldVariables(node, state)).toStrictEqual({
377+
from: '@INPUT_PARAMS_BEGIN'.length,
378+
to: doc.length,
379+
});
380+
}
381+
});
382+
});
383+
test('Parameters should return the correct from and to', () => {
384+
LOCALS.forEach(local => {
385+
const doc = `${local}`;
386+
const tree = parser.parse(doc);
387+
const state = EditorState.create({ doc });
388+
389+
const node = tree.topNode.getChild('LocalDeclaration');
390+
if (!node) {
391+
throw new Error('node not found');
392+
} else {
393+
expect(node).not.toBeNull();
394+
expect(foldVariables(node, state)).toStrictEqual({
395+
from: '@LOCALS_BEGIN'.length,
396+
to: doc.length,
397+
});
398+
}
399+
});
400+
});
401+
});

src/utilities/codemirror/custom-folder.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ export function customFoldInside(node: SyntaxNode, state: EditorState): { from:
2020
return foldMetadataOrModel(node, state, '@Metadata');
2121
case 'Models':
2222
return foldMetadataOrModel(node, state, '@Model');
23+
case 'ParameterDeclaration':
24+
case 'LocalDeclaration':
25+
return foldVariables(node, state);
2326
}
2427
return null;
2528
}
@@ -107,6 +110,39 @@ export function foldRequest(requestNode: SyntaxNode, state: EditorState): { from
107110
return { from, to: endRequest };
108111
}
109112

113+
/**
114+
* Calculate the fold range for a block of variables.
115+
* The fold range starts after the prefix of the block (e.g. "@INPUT_PARAMETERS_BEGIN" or "@LOCALS_BEGIN")
116+
* and ends of the block.
117+
* If the text ends with a line break, the end of the fold range will be adjusted to the start of the line break.
118+
*
119+
* @param containerNode - The node containing the variables (e.g. ParameterDeclaration or LocalDeclaration).
120+
* @param state - The EditorState object.
121+
* @returns A fold range object with "from" and "to" properties.
122+
* Returns null if any of the necessary nodes are not present.
123+
*/
124+
export function foldVariables(containerNode: SyntaxNode, state: EditorState): { from: number; to: number } | null {
125+
// Get all the Variable nodes in the container node
126+
const variablesNodes = containerNode.getChildren('Variable');
127+
128+
// Calculate the length of the directive (e.g. "@INPUT_PARAMETERS_BEGIN" or "@LOCALS_BEGIN")
129+
const directiveLength = state
130+
.sliceDoc(containerNode.from, containerNode.to - variablesNodes.length ? getFromAndTo([...variablesNodes]).from : 0)
131+
.split('\n')[0].length;
132+
133+
// Calculate the start of the fold range after the directive
134+
const from = containerNode.from + directiveLength;
135+
136+
// Calculate the end of the fold range after the last Variable node
137+
let endBlock = getFromAndTo([containerNode]).to;
138+
139+
// If the text ends with a line break, adjust the end of the fold range to the start of the line break
140+
const text = state.sliceDoc(containerNode.from + directiveLength, endBlock).trimEnd() + '\n';
141+
endBlock = from + text.lastIndexOf('\n');
142+
143+
return { from, to: endBlock };
144+
}
145+
110146
/**
111147
* Calculate the fold range for a Metadata or Model node.
112148
* The fold range starts after the node's prefix (e.g. "@Metadata" or "@Model") and ends after the node.

src/utilities/codemirror/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ export const SeqLanguage = LRLanguage.define({
1919
GroundBlock: customFoldInside,
2020
GroundEvent: customFoldInside,
2121
Load: customFoldInside,
22+
LocalDeclaration: customFoldInside,
2223
Metadata: customFoldInside,
2324
Models: customFoldInside,
25+
ParameterDeclaration: customFoldInside,
2426
Request: customFoldInside,
2527
}),
2628
styleTags({

0 commit comments

Comments
 (0)