Skip to content

Commit

Permalink
Merge pull request #352 from codefori/fix/program_parameters
Browse files Browse the repository at this point in the history
Support for free-format program parameters and related tests
  • Loading branch information
worksofliam authored Dec 12, 2024
2 parents 5746a86 + e8bd6ce commit 33796aa
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 26 deletions.
52 changes: 31 additions & 21 deletions language/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const lineTokens = (input: string, lineNumber: number, lineIndex: number): Token
return tokens;
}

const PROGRAMPARMS_NAME = `PROGRAMPARMS`;

export default class Parser {
parsedCache: {[thePath: string]: Cache} = {};
tables: TableDetail = {};
Expand Down Expand Up @@ -951,40 +953,48 @@ export default class Parser {

case `DCL-PI`:
//Procedures can only exist in the global scope.
if (currentProcName) {
if (parts.length > 0) {
if (parts.length > 0) {
if (currentProcName) {
currentGroup = `procedures`;
currentItem = scopes[0].procedures.find(proc => proc.name === currentProcName);
} else {
currentItem = new Declaration(`struct`);
currentItem.name = PROGRAMPARMS_NAME;
}

if (currentItem) {
const endInline = tokens.findIndex(part => part.value.toUpperCase() === `END-PI`);

if (currentItem) {

// Indicates that the PI starts and ends on the same line
if (endInline >= 0) {
tokens.splice(endInline, 1);
currentItem.readParms = false;
resetDefinition = true;
}

currentItem.keyword = {
...currentItem.keyword,
...Parser.expandKeywords(tokens.slice(2))
}
currentItem.readParms = true;
// Indicates that the PI starts and ends on the same line
if (endInline >= 0) {
tokens.splice(endInline, 1);
currentItem.readParms = false;
resetDefinition = true;
}

currentDescription = [];
currentItem.keyword = {
...currentItem.keyword,
...Parser.expandKeywords(tokens.slice(2))
}
currentItem.readParms = true;

currentDescription = [];
}
}
break;

case `END-PI`:
//Procedures can only exist in the global scope.
currentItem = scopes[0].procedures.find(proc => proc.name === currentProcName);
if (currentProcName) {
currentItem = scopes[0].procedures.find(proc => proc.name === currentProcName);

if (currentItem && currentItem.type === `procedure`) {
currentItem.readParms = false;
if (currentItem && currentItem.type === `procedure`) {
currentItem.readParms = false;
resetDefinition = true;
}
} else if (currentItem && currentItem.name === PROGRAMPARMS_NAME) {
// Assign this scopes parameters to the subitems of the program parameters struct
scopes[0].parameters = currentItem.subItems;
resetDefinition = true;
}
break;
Expand Down Expand Up @@ -1202,7 +1212,7 @@ export default class Parser {
currentItem.subItems.push(currentSub);
currentSub = undefined;

if (currentItem.type === `struct`) {
if (currentItem.type === `struct` && currentItem.name !== PROGRAMPARMS_NAME) {
resetDefinition = true;
}
}
Expand Down
10 changes: 6 additions & 4 deletions tests/suite/partial.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ test("Parser partial tests", { timeout }, async () => {
const parser = setupParser(projectPath);
const list = await getSourcesList(projectPath);

totalFiles += list.length;

for (let i = 0; i < list.length; i++) {
const relativePath = list[i];
const basename = path.basename(relativePath);
Expand Down Expand Up @@ -51,13 +53,13 @@ test("Parser partial tests", { timeout }, async () => {
lengths.push(pe - ps);
}

const lengthsAverage = lengths.reduce((a, b) => a + b, 0) / lengths.length;
const total = lengths.reduce((a, b) => a + b, 0);
const last = lengths[lengths.length - 1];
// const lengthsAverage = lengths.reduce((a, b) => a + b, 0) / lengths.length;
// const total = lengths.reduce((a, b) => a + b, 0);
// const last = lengths[lengths.length - 1];
// console.log(`\tAverage: ${lengthsAverage}ms, Full: ${last}ms, Total: ${total}`);
// console.log(``);
}
}

console.log(`Parsed ${totalFiles} files, ${SPLIT_SIZE} each.`);
console.log(`Parsed ${totalFiles} files, ${SPLIT_SIZE} times each.`);
});
53 changes: 52 additions & 1 deletion tests/suite/references.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -381,10 +381,14 @@ test("references_9", async () => {
const cache = await parser.getDocs(uri, lines, {ignoreCache: true, withIncludes: true, collectReferences: true});

const procedure = cache.find(`InputIsValid`);
const validationResult = procedure.scope.find(`validationResult`);

const validationResult = procedure.scope.find(`validationResult`);
expect(validationResult.references.length).toEqual(7);
expect(validationResult.references.every(ref => lines.substring(ref.offset.start, ref.offset.end) === `validationResult`)).toBe(true);

const comp = procedure.scope.find(`comp`);
expect(comp.references.length).toEqual(2);
expect(comp.references.every(ref => lines.substring(ref.offset.start, ref.offset.end) === `comp`)).toBe(true);
});

test('references_10', async () => {
Expand Down Expand Up @@ -1833,4 +1837,51 @@ test('references_27_fixed_reference', async () => {

expect(offsetContent.toUpperCase()).toBe(`WCFGKEY`);
}
});

test('reference_28_parameters', async () => {
const lines = [
`**free`,
``,
`ctl-opt dftactgrp(*no);`,
``,
`dcl-pi upddept;`,
` deptno char(3);`,
` deptname char(36);`,
` mgrno char(6);`,
` admrdept char(3);`,
` location char(16);`,
`end-pi;`,
``,
`dcl-ds result qualified dim(1);`,
` success char(1);`,
`end-ds;`,
``,
`exec sql`,
` update dept`,
` set deptname = :deptname,`,
` mgrno = :mgrno,`,
` admrdept = :admrdept,`,
` location = :location`,
` where deptno = :deptno;`,
``,
`if (SQLCOD = 0);`,
` result(1).success = 'Y';`,
`else;`,
` result(1).success = 'N';`,
`endif;`,
``,
`dcl-s return char(length) inz('Y');`,
``,
`exec sql set result sets array :result for 1 rows;`,
`// Hello`,
`return;`,
].join(`\n`);

const cache = await parser.getDocs(uri, lines, { ignoreCache: true, withIncludes: true, collectReferences: true });

const deptno = cache.find(`deptno`);
expect(deptno).toBeDefined();
expect(deptno.references.length).toBe(2);
expect(deptno.references.every(ref => lines.substring(ref.offset.start, ref.offset.end) === `deptno`)).toBe(true);
});

0 comments on commit 33796aa

Please sign in to comment.