From f0d46ff3e8915a8c3debb0ffa78ab0bf2e5600cf Mon Sep 17 00:00:00 2001 From: worksofliam Date: Mon, 9 Dec 2024 09:05:58 -0500 Subject: [PATCH] Support for fixed-format SQL references Signed-off-by: worksofliam --- language/parser.ts | 25 +++++++++++++++++++++++-- language/tokens.ts | 2 +- tests/suite/references.test.ts | 11 ++++++++++- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/language/parser.ts b/language/parser.ts index 14db31bb..aafdba8b 100644 --- a/language/parser.ts +++ b/language/parser.ts @@ -418,6 +418,8 @@ export default class Parser { } }; + let fixedExec = false; + for (let li = 0; li < lines.length; li++) { if (li >= 1) { lineIndex += lines[li-1].length + (eol === `\r\n` ? 2 : 1); @@ -427,7 +429,7 @@ export default class Parser { const scope = scopes[scopes.length - 1]; let baseLine = lines[li]; - let spec; + let spec: string|undefined; lineIsFree = false; lineNumber += 1; @@ -443,7 +445,7 @@ export default class Parser { const comment = baseLine[6]; spec = baseLine[5].toUpperCase(); - if ([spec, comment].includes(`*`) || [`*`, `+`].includes(comment)) { + if ([spec, comment].includes(`*`)) { continue; } @@ -451,6 +453,11 @@ export default class Parser { // Directives can be parsed by the free format parser baseLine = ``.padEnd(6) + baseLine.substring(6); lineIsFree = true; + } else if (comment === `+` && fixedExec && currentStmtStart.content) { + // Fixed format EXEC SQL + baseLine = ``.padEnd(7) + baseLine.substring(7); + currentStmtStart.content += baseLine + ''.padEnd(eol.length); + continue; } else { if (spec === ` `) { //Clear out stupid comments @@ -498,6 +505,20 @@ export default class Parser { return; } else { switch (parts[0]) { + case '/EXEC': + fixedExec = true; + baseLine = ``.padEnd(7) + baseLine.substring(7); + currentStmtStart = { + line: lineNumber, + index: lineIndex, + content: baseLine + ''.padEnd(eol.length) + } + continue; + case '/END': + line = `;`; + baseLine = ``.padEnd(baseLine.length) + `;`; + fixedExec = false; + break; case `/COPY`: case `/INCLUDE`: if (options.withIncludes && this.includeFileFetch && lineCanRun()) { diff --git a/language/tokens.ts b/language/tokens.ts index c8f03b16..bcb1703c 100644 --- a/language/tokens.ts +++ b/language/tokens.ts @@ -35,7 +35,7 @@ const commonMatchers: Matcher[] = [ { type: `divide` }, { type: `word`, - match: (word) => [`TITLE`, `EJECT`, `SPACE`, `COPY`, `INCLUDE`, `SET`, `RESTORE`, `OVERLOAD`, `DEFINE`, `UNDEFINE`, `IF`, `ELSE`, `ELSEIF`, `ENDIF`, `EOF`, `CHARCOUNT`].includes(word.toUpperCase()) + match: (word) => [`TITLE`, `EJECT`, `SPACE`, `COPY`, `INCLUDE`, `SET`, `RESTORE`, `OVERLOAD`, `DEFINE`, `UNDEFINE`, `IF`, `ELSE`, `ELSEIF`, `ENDIF`, `EOF`, `CHARCOUNT`, `EXEC`, `END`].includes(word.toUpperCase()) }, ], becomes: { diff --git a/tests/suite/references.test.ts b/tests/suite/references.test.ts index 940fbe40..b26636a8 100644 --- a/tests/suite/references.test.ts +++ b/tests/suite/references.test.ts @@ -793,7 +793,16 @@ test('references_14_fixed_3', async () => { const cache = await parser.getDocs(uri, lines, { ignoreCache: true, withIncludes: true, collectReferences: true }); const per = cache.find(`per`); - expect(per.references.length).toBe(6); + expect(per.references.length).toBe(7); + + // for (const ref of per.references) { + // console.log({ + // ref, + // text: lines.substring(ref.offset.position, ref.offset.end), + // about: lines.substring(ref.offset.position - 10, ref.offset.end + 10) + // }) + // } + expect(per.references.every(ref => lines.substring(ref.offset.position, ref.offset.end) === `per`)).toBe(true); const pmyy = cache.find(`pmyy`);