From 8996af88683f9dc3d2fb214454e4707bf3eff75f Mon Sep 17 00:00:00 2001 From: worksofliam Date: Wed, 11 Dec 2024 12:41:16 -0500 Subject: [PATCH] Support for C spec definitions Signed-off-by: worksofliam --- language/models/cache.ts | 17 ++++++++++------- language/models/fixed.js | 7 +++++++ language/parser.ts | 25 +++++++++++++++++++++++++ tests/suite/fixed.test.ts | 11 ++++++++++- tests/suite/references.test.ts | 7 +++++++ 5 files changed, 59 insertions(+), 8 deletions(-) diff --git a/language/models/cache.ts b/language/models/cache.ts index 5b913b1b..64d55d24 100644 --- a/language/models/cache.ts +++ b/language/models/cache.ts @@ -99,12 +99,7 @@ export default class Cache { return (lines.length >= 1 ? lines[0] : 0); } - /** - * - * @param {string} name - * @returns {Declaration} - */ - find(name) { + find(name: string, includeProcedure?: string): Declaration|undefined { name = name.toUpperCase(); const fileStructs = this.files.flatMap(file => file.subItems); @@ -127,6 +122,14 @@ export default class Cache { if (found) return found; } + if (includeProcedure) { + const procedureScope = this.procedures.find(proc => proc.name.toUpperCase() === includeProcedure); + if (procedureScope) { + const found = procedureScope.scope.find(name); + if (found) return found; + } + } + if (allStructs.length > 0) { for (const def of allStructs) { if (def.keyword[`QUALIFIED`] !== true) { @@ -136,7 +139,7 @@ export default class Cache { } } - return null; + return; } findDefinition(lineNumber, word) { diff --git a/language/models/fixed.js b/language/models/fixed.js index d045a0ef..d5efc040 100644 --- a/language/models/fixed.js +++ b/language/models/fixed.js @@ -60,6 +60,9 @@ export function parseCLine(lineNumber, lineIndex, content) { const extended = content.substr(35); const result = content.substr(49, 14); + const fieldLength = content.substr(63, 5); + const fieldDecimals = content.substr(68, 2); + const ind1 = content.substr(70, 2); const ind2 = content.substr(72, 2); const ind3 = content.substr(74, 2); @@ -71,6 +74,10 @@ export function parseCLine(lineNumber, lineIndex, content) { factor2: calculateToken(lineNumber, lineIndex+35, factor2), result: calculateToken(lineNumber, lineIndex+49, result), extended: calculateToken(lineNumber, lineIndex+35, extended), + + fieldLength: calculateToken(lineNumber, lineIndex+63, fieldLength), + fieldDecimals: calculateToken(lineNumber, lineIndex+68, fieldDecimals), + ind1: calculateToken(lineNumber, lineIndex+70, ind1, `special-ind`), ind2: calculateToken(lineNumber, lineIndex+72, ind2, `special-ind`), ind3: calculateToken(lineNumber, lineIndex+74, ind3, `special-ind`) diff --git a/language/parser.ts b/language/parser.ts index 0bf5500c..e13db9c8 100644 --- a/language/parser.ts +++ b/language/parser.ts @@ -1300,6 +1300,31 @@ export default class Parser { ...fromToken(cSpec.factor2), ...fromToken(cSpec.result), ); + + if (cSpec.result && cSpec.fieldLength) { + // This means we need to dynamically define this field + const fieldName = cSpec.result.value; + // Don't redefine this field. + if (!scopes[0].find(fieldName, currentProcName)) { + const fieldLength = parseInt(cSpec.fieldLength.value); + const decimals = cSpec.fieldDecimals ? parseInt(cSpec.fieldDecimals.value) : undefined; + const type = decimals !== undefined ? `PACKED`: `CHAR`; + + currentItem = new Declaration(`variable`); + currentItem.name = fieldName; + currentItem.keyword = {[type]: `${fieldLength}${decimals !== undefined ? `:${decimals}` : ``}`}; + currentItem.position = { + path: fileUri, + line: lineNumber + }; + currentItem.range = { + start: lineNumber, + end: lineNumber + }; + + scope.variables.push(currentItem); + } + } } potentialName = cSpec.factor1 ? cSpec.factor1.value : ``; diff --git a/tests/suite/fixed.test.ts b/tests/suite/fixed.test.ts index 8ed4e933..d9815c75 100644 --- a/tests/suite/fixed.test.ts +++ b/tests/suite/fixed.test.ts @@ -1144,7 +1144,16 @@ test('plist_test', async () => { const cache = await parser.getDocs(uri, lines, { ignoreCache: true, withIncludes: true }); - expect(cache.variables.length).to.equal(0); + expect(cache.variables.length).toBe(11); + + const atPGMID = cache.find(`@PGMID`); + expect(atPGMID.keyword[`CHAR`]).toBe(`10`); + + const atSON = cache.find(`@SQN`); + expect(atSON.keyword[`PACKED`]).toBe(`2:0`); + + const atPVSELECTION = cache.find(`@PVSELECTION`); + expect(atPVSELECTION.keyword[`CHAR`]).toBe(`256`); }); test(`range test 2`, async () => { diff --git a/tests/suite/references.test.ts b/tests/suite/references.test.ts index be868b0a..6d6f974d 100644 --- a/tests/suite/references.test.ts +++ b/tests/suite/references.test.ts @@ -895,6 +895,9 @@ test('references_15_fixed_4', async () => { const r_transf = cache.find(`r_transf`); expect(r_transf.references.length).toBe(3); expect(r_transf.references.every(ref => lines.substring(ref.offset.position, ref.offset.end) === `r_transf`)).toBe(true); + + const r_long_lue = cache.find(`r_long_lue`); + expect(r_long_lue.references.length).toBe(1); }); test('references_16_fixed_5', async () => { @@ -1117,6 +1120,10 @@ test('references_16_fixed_5', async () => { const mntJtot = cache.find(`mntJtot`); expect(mntJtot.references.length).toBe(2); expect(mntJtot.references.every(ref => lines.substring(ref.offset.position, ref.offset.end) === `mntJtot`)).toBe(true); + + const syde = cache.find(`syde`); + expect(syde.references.length).toBe(2); + expect(syde.references.every(ref => lines.substring(ref.offset.position, ref.offset.end) === `syde`)).toBe(true); }); test('references_17_fixed_6', async () => {