1
0
mirror of https://github.com/sasjs/lint.git synced 2025-12-10 17:34:36 +00:00

feat: mult-line macro declarations

This commit is contained in:
Saad Jutt
2021-05-21 05:10:34 +05:00
parent 8bfb547427
commit af2d2c12c1
12 changed files with 325 additions and 86 deletions

View File

@@ -12,14 +12,14 @@ describe('formatText', () => {
new LintConfig(getLintConfigModule.DefaultLintConfiguration) new LintConfig(getLintConfigModule.DefaultLintConfiguration)
) )
) )
const text = `%macro test const text = `%macro test;
%put 'hello';\r\n%mend; ` %put 'hello';\r\n%mend; `
const expectedOutput = `/** const expectedOutput = `/**
@file @file
@brief <Your brief here> @brief <Your brief here>
<h4> SAS Macros </h4> <h4> SAS Macros </h4>
**/\n%macro test **/\n%macro test;
%put 'hello';\n%mend test;` %put 'hello';\n%mend test;`
const output = await formatText(text) const output = await formatText(text)
@@ -38,9 +38,9 @@ describe('formatText', () => {
}) })
) )
) )
const text = `%macro test\n %put 'hello';\r\n%mend; ` const text = `%macro test;\n %put 'hello';\r\n%mend; `
const expectedOutput = `/**\r\n @file\r\n @brief <Your brief here>\r\n <h4> SAS Macros </h4>\r\n**/\r\n%macro test\r\n %put 'hello';\r\n%mend test;` const expectedOutput = `/**\r\n @file\r\n @brief <Your brief here>\r\n <h4> SAS Macros </h4>\r\n**/\r\n%macro test;\r\n %put 'hello';\r\n%mend test;`
const output = await formatText(text) const output = await formatText(text)

View File

@@ -56,7 +56,7 @@ describe('hasMacroNameInMend - test', () => {
it('should return an array with a diagnostic for each macro missing an %mend statement', () => { it('should return an array with a diagnostic for each macro missing an %mend statement', () => {
const content = `%macro somemacro; const content = `%macro somemacro;
%put &sysmacroname; %put &sysmacroname;
%macro othermacro` %macro othermacro;`
expect(hasMacroNameInMend.test(content)).toEqual([ expect(hasMacroNameInMend.test(content)).toEqual([
{ {

View File

@@ -17,7 +17,7 @@ const test = (value: string, config?: LintConfig) => {
const macros = parseMacros(value, config) const macros = parseMacros(value, config)
const diagnostics: Diagnostic[] = [] const diagnostics: Diagnostic[] = []
macros.forEach((macro) => { macros.forEach((macro) => {
if (macro.startLineNumber === null && macro.endLineNumber !== null) { if (macro.startLineNumbers.length === 0 && macro.endLineNumber !== null) {
const endLine = lines[macro.endLineNumber - 1] const endLine = lines[macro.endLineNumber - 1]
diagnostics.push({ diagnostics.push({
message: `%mend statement is redundant`, message: `%mend statement is redundant`,
@@ -27,10 +27,13 @@ const test = (value: string, config?: LintConfig) => {
getColumnNumber(endLine, '%mend') + macro.termination.length, getColumnNumber(endLine, '%mend') + macro.termination.length,
severity: Severity.Warning severity: Severity.Warning
}) })
} else if (macro.endLineNumber === null && macro.startLineNumber !== null) { } else if (
macro.endLineNumber === null &&
macro.startLineNumbers.length !== 0
) {
diagnostics.push({ diagnostics.push({
message: `Missing %mend statement for macro - ${macro.name}`, message: `Missing %mend statement for macro - ${macro.name}`,
lineNumber: macro.startLineNumber, lineNumber: macro.startLineNumbers![0],
startColumnNumber: 1, startColumnNumber: 1,
endColumnNumber: 1, endColumnNumber: 1,
severity: Severity.Warning severity: Severity.Warning
@@ -73,7 +76,7 @@ const fix = (value: string, config?: LintConfig): string => {
const macros = parseMacros(value, config) const macros = parseMacros(value, config)
macros.forEach((macro) => { macros.forEach((macro) => {
if (macro.startLineNumber === null && macro.endLineNumber !== null) { if (macro.startLineNumbers.length === 0 && macro.endLineNumber !== null) {
// %mend statement is redundant // %mend statement is redundant
const endLine = lines[macro.endLineNumber - 1] const endLine = lines[macro.endLineNumber - 1]
const startColumnNumber = getColumnNumber(endLine, '%mend') const startColumnNumber = getColumnNumber(endLine, '%mend')
@@ -83,7 +86,10 @@ const fix = (value: string, config?: LintConfig): string => {
const beforeStatement = endLine.slice(0, startColumnNumber - 1) const beforeStatement = endLine.slice(0, startColumnNumber - 1)
const afterStatement = endLine.slice(endColumnNumber) const afterStatement = endLine.slice(endColumnNumber)
lines[macro.endLineNumber - 1] = beforeStatement + afterStatement lines[macro.endLineNumber - 1] = beforeStatement + afterStatement
} else if (macro.endLineNumber === null && macro.startLineNumber !== null) { } else if (
macro.endLineNumber === null &&
macro.startLineNumbers.length !== 0
) {
// missing %mend statement // missing %mend statement
} else if (macro.mismatchedMendMacroName) { } else if (macro.mismatchedMendMacroName) {
// mismatched macro name // mismatched macro name

View File

@@ -140,17 +140,17 @@ describe('hasMacroParentheses', () => {
}) })
}) })
it('should return an array with a single diagnostic when a macro definition contains a space', () => { // it('should return an array with a single diagnostic when a macro definition contains a space', () => {
const content = `%macro test ()` // const content = `%macro test ()`
expect(hasMacroParentheses.test(content)).toEqual([ // expect(hasMacroParentheses.test(content)).toEqual([
{ // {
message: 'Macro definition contains space(s)', // message: 'Macro definition contains space(s)',
lineNumber: 1, // lineNumber: 1,
startColumnNumber: 8, // startColumnNumber: 8,
endColumnNumber: 14, // endColumnNumber: 14,
severity: Severity.Warning // severity: Severity.Warning
} // }
]) // ])
}) // })
}) })

View File

@@ -16,36 +16,48 @@ const test = (value: string, config?: LintConfig) => {
if (!macro.name) { if (!macro.name) {
diagnostics.push({ diagnostics.push({
message: 'Macro definition missing name', message: 'Macro definition missing name',
lineNumber: macro.startLineNumber!, lineNumber: macro.startLineNumbers![0],
startColumnNumber: getColumnNumber(macro.declarationLine, '%macro'), startColumnNumber: getColumnNumber(
macro.declarationLines![0],
'%macro'
),
endColumnNumber: endColumnNumber:
getColumnNumber(macro.declarationLine, '%macro') + getColumnNumber(macro.declarationLines![0], '%macro') +
macro.declaration.length, macro.declaration.length,
severity: Severity.Warning severity: Severity.Warning
}) })
} else if (!macro.declarationLine.includes('(')) { } else if (!macro.declarationLines.find((dl) => dl.includes('('))) {
const macroNameLineIndex = macro.declarationLines.findIndex((dl) =>
dl.includes(macro.name)
)
diagnostics.push({ diagnostics.push({
message, message,
lineNumber: macro.startLineNumber!, lineNumber: macro.startLineNumbers![macroNameLineIndex],
startColumnNumber: getColumnNumber(macro.declarationLine, macro.name), startColumnNumber: getColumnNumber(
macro.declarationLines[macroNameLineIndex],
macro.name
),
endColumnNumber: endColumnNumber:
getColumnNumber(macro.declarationLine, macro.name) + getColumnNumber(
macro.declarationLines[macroNameLineIndex],
macro.name
) +
macro.name.length - macro.name.length -
1, 1,
severity: Severity.Warning severity: Severity.Warning
}) })
} else if (macro.name !== macro.name.trim()) { // } else if (macro.name !== macro.name.trim()) {
diagnostics.push({ // diagnostics.push({
message: 'Macro definition contains space(s)', // message: 'Macro definition contains space(s)',
lineNumber: macro.startLineNumber!, // lineNumber: macro.startLineNumber!,
startColumnNumber: getColumnNumber(macro.declarationLine, macro.name), // startColumnNumber: getColumnNumber(macro.declarationLine, macro.name),
endColumnNumber: // endColumnNumber:
getColumnNumber(macro.declarationLine, macro.name) + // getColumnNumber(macro.declarationLine, macro.name) +
macro.name.length - // macro.name.length -
1 + // 1 +
`()`.length, // `()`.length,
severity: Severity.Warning // severity: Severity.Warning
}) // })
} }
}) })

View File

@@ -22,17 +22,17 @@ const test = (value: string, config?: LintConfig) => {
message: message message: message
.replace('{macro}', macro.name) .replace('{macro}', macro.name)
.replace('{parent}', macro.parentMacro), .replace('{parent}', macro.parentMacro),
lineNumber: macro.startLineNumber as number, lineNumber: macro.startLineNumbers![0] as number,
startColumnNumber: getColumnNumber( startColumnNumber: getColumnNumber(
lines[(macro.startLineNumber as number) - 1], lines[(macro.startLineNumbers![0] as number) - 1],
'%macro' '%macro'
), ),
endColumnNumber: endColumnNumber:
getColumnNumber( getColumnNumber(
lines[(macro.startLineNumber as number) - 1], lines[(macro.startLineNumbers![0] as number) - 1],
'%macro' '%macro'
) + ) +
lines[(macro.startLineNumber as number) - 1].trim().length - lines[(macro.startLineNumbers![0] as number) - 1].trim().length -
1, 1,
severity: Severity.Warning severity: Severity.Warning
}) })

View File

@@ -24,6 +24,19 @@ describe('strictMacroDefinition', () => {
const line7 = const line7 =
' /* Some Comment */ %macro somemacro(var1, var2) /minoperator ; /* Some Comment */' ' /* Some Comment */ %macro somemacro(var1, var2) /minoperator ; /* Some Comment */'
expect(strictMacroDefinition.test(line7, 1)).toEqual([]) expect(strictMacroDefinition.test(line7, 1)).toEqual([])
const line8 =
'%macro macroName( arr, arr/* / store source */3 ) /* / store source */;/* / store source */'
expect(strictMacroDefinition.test(line8, 1)).toEqual([])
const line9 = '%macro macroName(var1, var2=with space, var3=);'
expect(strictMacroDefinition.test(line9, 1)).toEqual([])
const line10 = '%macro macroName()/ /* some comment */ store source;'
expect(strictMacroDefinition.test(line10, 1)).toEqual([])
const line11 = '`%macro macroName() /* / store source */;'
expect(strictMacroDefinition.test(line11, 1)).toEqual([])
}) })
it('should return an array with a single diagnostic when Macro definition has space in param', () => { it('should return an array with a single diagnostic when Macro definition has space in param', () => {
@@ -39,7 +52,7 @@ describe('strictMacroDefinition', () => {
]) ])
}) })
it('should return an array with a two diagnostics when Macro definition has space in param', () => { it('should return an array with a two diagnostics when Macro definition has space in params', () => {
const line = '%macro somemacro(var1, var 2, v ar3, var4);' const line = '%macro somemacro(var1, var 2, v ar3, var4);'
expect(strictMacroDefinition.test(line, 1)).toEqual([ expect(strictMacroDefinition.test(line, 1)).toEqual([
{ {
@@ -59,6 +72,20 @@ describe('strictMacroDefinition', () => {
]) ])
}) })
it('should return an array with a two diagnostics when Macro definition has space in params - special case', () => {
const line =
'%macro macroName( arr, ar r/* / store source */ 3 ) /* / store source */;/* / store source */'
expect(strictMacroDefinition.test(line, 1)).toEqual([
{
message: `Param 'ar r 3' cannot have space`,
lineNumber: 1,
startColumnNumber: 24,
endColumnNumber: 49,
severity: Severity.Warning
}
])
})
it('should return an array with a single diagnostic when Macro definition has invalid option', () => { it('should return an array with a single diagnostic when Macro definition has invalid option', () => {
const line = '%macro somemacro(var1, var2)/minXoperator;' const line = '%macro somemacro(var1, var2)/minXoperator;'
expect(strictMacroDefinition.test(line, 1)).toEqual([ expect(strictMacroDefinition.test(line, 1)).toEqual([

View File

@@ -42,12 +42,34 @@ const test = (value: string, lineNumber: number) => {
const params = paramsTrimmed.split(',') const params = paramsTrimmed.split(',')
params.forEach((param) => { params.forEach((param) => {
const trimedParam = param.split('=')[0].trim() const trimedParam = param.split('=')[0].trim()
let paramStartIndex: number = 1,
paramEndIndex: number = value.length
if (value.indexOf(trimedParam) === -1) {
const comment = '/\\*(.*?)\\*/'
for (let i = 1; i < trimedParam.length; i++) {
const paramWithComment =
trimedParam.slice(0, i) + comment + trimedParam.slice(i)
const regEx = new RegExp(paramWithComment)
const result = regEx.exec(value)
if (result) {
paramStartIndex = value.indexOf(result[0])
paramEndIndex = value.indexOf(result[0]) + result[0].length
break
}
}
} else {
paramStartIndex = value.indexOf(trimedParam)
paramEndIndex = value.indexOf(trimedParam) + trimedParam.length
}
if (trimedParam.includes(' ')) { if (trimedParam.includes(' ')) {
diagnostics.push({ diagnostics.push({
message: `Param '${trimedParam}' cannot have space`, message: `Param '${trimedParam}' cannot have space`,
lineNumber, lineNumber,
startColumnNumber: value.indexOf(trimedParam) + 1, startColumnNumber: paramStartIndex + 1,
endColumnNumber: value.indexOf(trimedParam) + trimedParam.length, endColumnNumber: paramEndIndex,
severity: Severity.Warning severity: Severity.Warning
}) })
} }

View File

@@ -3,7 +3,7 @@ import { parseMacros } from './parseMacros'
describe('parseMacros', () => { describe('parseMacros', () => {
it('should return an array with a single macro', () => { it('should return an array with a single macro', () => {
const text = `%macro test; const text = ` %macro test;
%put 'hello'; %put 'hello';
%mend` %mend`
@@ -12,11 +12,11 @@ describe('parseMacros', () => {
expect(macros.length).toEqual(1) expect(macros.length).toEqual(1)
expect(macros).toContainEqual({ expect(macros).toContainEqual({
name: 'test', name: 'test',
declarationLine: '%macro test;', declarationLines: [' %macro test;'],
terminationLine: '%mend', terminationLine: '%mend',
declaration: '%macro test', declaration: '%macro test',
termination: '%mend', termination: '%mend',
startLineNumber: 1, startLineNumbers: [1],
endLineNumber: 3, endLineNumber: 3,
parentMacro: '', parentMacro: '',
hasMacroNameInMend: false, hasMacroNameInMend: false,
@@ -34,11 +34,11 @@ describe('parseMacros', () => {
expect(macros.length).toEqual(1) expect(macros.length).toEqual(1)
expect(macros).toContainEqual({ expect(macros).toContainEqual({
name: 'test', name: 'test',
declarationLine: '%macro test(var,sum);', declarationLines: ['%macro test(var,sum);'],
terminationLine: '%mend', terminationLine: '%mend',
declaration: '%macro test(var,sum)', declaration: '%macro test(var,sum)',
termination: '%mend', termination: '%mend',
startLineNumber: 1, startLineNumbers: [1],
endLineNumber: 3, endLineNumber: 3,
parentMacro: '', parentMacro: '',
hasMacroNameInMend: false, hasMacroNameInMend: false,
@@ -56,11 +56,11 @@ describe('parseMacros', () => {
expect(macros.length).toEqual(1) expect(macros.length).toEqual(1)
expect(macros).toContainEqual({ expect(macros).toContainEqual({
name: 'test', name: 'test',
declarationLine: '%macro test/parmbuff;', declarationLines: ['%macro test/parmbuff;'],
terminationLine: '%mend', terminationLine: '%mend',
declaration: '%macro test/parmbuff', declaration: '%macro test/parmbuff',
termination: '%mend', termination: '%mend',
startLineNumber: 1, startLineNumbers: [1],
endLineNumber: 3, endLineNumber: 3,
parentMacro: '', parentMacro: '',
hasMacroNameInMend: false, hasMacroNameInMend: false,
@@ -79,11 +79,15 @@ describe('parseMacros', () => {
expect(macros.length).toEqual(1) expect(macros.length).toEqual(1)
expect(macros).toContainEqual({ expect(macros).toContainEqual({
name: 'foobar', name: 'foobar',
declarationLine: '/* commentary */ %macro foobar(arg) /store source', declarationLines: [
'/* commentary */ %macro foobar(arg) /store source',
' des="This macro does not do much";'
],
terminationLine: '%mend', terminationLine: '%mend',
declaration: '%macro foobar(arg) /store source', declaration:
'%macro foobar(arg) /store source des="This macro does not do much"',
termination: '%mend', termination: '%mend',
startLineNumber: 1, startLineNumbers: [1, 2],
endLineNumber: 4, endLineNumber: 4,
parentMacro: '', parentMacro: '',
hasMacroNameInMend: false, hasMacroNameInMend: false,
@@ -104,11 +108,11 @@ describe('parseMacros', () => {
expect(macros.length).toEqual(2) expect(macros.length).toEqual(2)
expect(macros).toContainEqual({ expect(macros).toContainEqual({
name: 'foo', name: 'foo',
declarationLine: '%macro foo;', declarationLines: ['%macro foo;'],
terminationLine: '%mend;', terminationLine: '%mend;',
declaration: '%macro foo', declaration: '%macro foo',
termination: '%mend', termination: '%mend',
startLineNumber: 1, startLineNumbers: [1],
endLineNumber: 3, endLineNumber: 3,
parentMacro: '', parentMacro: '',
hasMacroNameInMend: false, hasMacroNameInMend: false,
@@ -116,11 +120,11 @@ describe('parseMacros', () => {
}) })
expect(macros).toContainEqual({ expect(macros).toContainEqual({
name: 'bar', name: 'bar',
declarationLine: '%macro bar();', declarationLines: ['%macro bar();'],
terminationLine: '%mend bar;', terminationLine: '%mend bar;',
declaration: '%macro bar()', declaration: '%macro bar()',
termination: '%mend bar', termination: '%mend bar',
startLineNumber: 4, startLineNumbers: [4],
endLineNumber: 6, endLineNumber: 6,
parentMacro: '', parentMacro: '',
hasMacroNameInMend: true, hasMacroNameInMend: true,
@@ -129,9 +133,9 @@ describe('parseMacros', () => {
}) })
it('should detect nested macro definitions', () => { it('should detect nested macro definitions', () => {
const text = `%macro test() const text = `%macro test();
%put 'hello'; %put 'hello';
%macro test2 %macro test2;
%put 'world; %put 'world;
%mend %mend
%mend test` %mend test`
@@ -141,11 +145,11 @@ describe('parseMacros', () => {
expect(macros.length).toEqual(2) expect(macros.length).toEqual(2)
expect(macros).toContainEqual({ expect(macros).toContainEqual({
name: 'test', name: 'test',
declarationLine: '%macro test()', declarationLines: ['%macro test();'],
terminationLine: '%mend test', terminationLine: '%mend test',
declaration: '%macro test()', declaration: '%macro test()',
termination: '%mend test', termination: '%mend test',
startLineNumber: 1, startLineNumbers: [1],
endLineNumber: 6, endLineNumber: 6,
parentMacro: '', parentMacro: '',
hasMacroNameInMend: true, hasMacroNameInMend: true,
@@ -153,15 +157,125 @@ describe('parseMacros', () => {
}) })
expect(macros).toContainEqual({ expect(macros).toContainEqual({
name: 'test2', name: 'test2',
declarationLine: ' %macro test2', declarationLines: [' %macro test2;'],
terminationLine: ' %mend', terminationLine: ' %mend',
declaration: '%macro test2', declaration: '%macro test2',
termination: '%mend', termination: '%mend',
startLineNumber: 3, startLineNumbers: [3],
endLineNumber: 5, endLineNumber: 5,
parentMacro: 'test', parentMacro: 'test',
hasMacroNameInMend: false, hasMacroNameInMend: false,
mismatchedMendMacroName: '' mismatchedMendMacroName: ''
}) })
}) })
describe(`multi-line macro declarations`, () => {
it('should return an array with a single macro', () => {
const text = `%macro
test;
%put 'hello';
%mend`
const macros = parseMacros(text, new LintConfig())
expect(macros.length).toEqual(1)
expect(macros).toContainEqual({
name: 'test',
declarationLines: ['%macro ', ' test;'],
terminationLine: '%mend',
declaration: '%macro test',
termination: '%mend',
startLineNumbers: [1, 2],
endLineNumber: 4,
parentMacro: '',
hasMacroNameInMend: false,
mismatchedMendMacroName: ''
})
})
it('should return an array with a single macro having parameters', () => {
const text = `%macro
test(
var,
sum);%put 'hello';
%mend`
const macros = parseMacros(text, new LintConfig())
expect(macros.length).toEqual(1)
expect(macros).toContainEqual({
name: 'test',
declarationLines: [
'%macro ',
` test(`,
` var,`,
` sum);%put 'hello';`
],
terminationLine: '%mend',
declaration: '%macro test( var, sum)',
termination: '%mend',
startLineNumbers: [1, 2, 3, 4],
endLineNumber: 5,
parentMacro: '',
hasMacroNameInMend: false,
mismatchedMendMacroName: ''
})
})
it('should return an array with a single macro having PARMBUFF option', () => {
const text = `%macro test
/parmbuff;
%put 'hello';
%mend`
const macros = parseMacros(text, new LintConfig())
expect(macros.length).toEqual(1)
expect(macros).toContainEqual({
name: 'test',
declarationLines: ['%macro test', ' /parmbuff;'],
terminationLine: '%mend',
declaration: '%macro test /parmbuff',
termination: '%mend',
startLineNumbers: [1, 2],
endLineNumber: 4,
parentMacro: '',
hasMacroNameInMend: false,
mismatchedMendMacroName: ''
})
})
it('should return an array with a single macro having paramerter & SOURCE option', () => {
const text = `/* commentary */ %macro foobar/* commentary */(arg)
/* commentary */
/store
/* commentary */source
des="This macro does not do much";
%put 'hello';
%mend`
const macros = parseMacros(text, new LintConfig())
expect(macros.length).toEqual(1)
expect(macros).toContainEqual({
name: 'foobar',
declarationLines: [
'/* commentary */ %macro foobar/* commentary */(arg) ',
' /* commentary */',
' /store',
' /* commentary */source',
' des="This macro does not do much";'
],
terminationLine: '%mend',
declaration:
'%macro foobar(arg) /store source des="This macro does not do much"',
termination: '%mend',
startLineNumbers: [1, 2, 3, 4, 5],
endLineNumber: 7,
parentMacro: '',
hasMacroNameInMend: false,
mismatchedMendMacroName: ''
})
})
})
}) })

View File

@@ -4,9 +4,9 @@ import { trimComments } from './trimComments'
interface Macro { interface Macro {
name: string name: string
startLineNumber: number | null startLineNumbers: number[]
endLineNumber: number | null endLineNumber: number | null
declarationLine: string declarationLines: string[]
terminationLine: string terminationLine: string
declaration: string declaration: string
termination: string termination: string
@@ -22,38 +22,92 @@ export const parseMacros = (text: string, config?: LintConfig): Macro[] => {
let isCommentStarted = false let isCommentStarted = false
let macroStack: Macro[] = [] let macroStack: Macro[] = []
lines.forEach((line, index) => { let isReadingMacroDefinition = false
let isStatementContinues = true
let tempMacroDeclaration = ''
let tempMacroDeclarationLines: string[] = []
let tempStartLineNumbers: number[] = []
lines.forEach((line, lineIndex) => {
const { statement: trimmedLine, commentStarted } = trimComments( const { statement: trimmedLine, commentStarted } = trimComments(
line, line,
isCommentStarted isCommentStarted
) )
isCommentStarted = commentStarted isCommentStarted = commentStarted
const statements: string[] = trimmedLine ? trimmedLine.split(';') : []
statements.forEach((statement) => { isStatementContinues = !trimmedLine.endsWith(';')
const statements: string[] = trimmedLine.split(';')
statements.forEach((statement, statementIndex) => {
const { statement: trimmedStatement, commentStarted } = trimComments( const { statement: trimmedStatement, commentStarted } = trimComments(
statement, statement,
isCommentStarted isCommentStarted
) )
isCommentStarted = commentStarted isCommentStarted = commentStarted
if (isReadingMacroDefinition) {
tempMacroDeclaration =
tempMacroDeclaration +
(trimmedStatement ? ' ' + trimmedStatement : '')
tempMacroDeclarationLines.push(line)
tempStartLineNumbers.push(lineIndex + 1)
if (!Object.is(statements.length - 1, statementIndex)) {
isReadingMacroDefinition = false
const name = tempMacroDeclaration
.slice(7, tempMacroDeclaration.length)
.trim()
.split('/')[0]
.split('(')[0]
.trim()
macroStack.push({
name,
startLineNumbers: tempStartLineNumbers,
endLineNumber: null,
parentMacro: macroStack.length
? macroStack[macroStack.length - 1].name
: '',
hasMacroNameInMend: false,
mismatchedMendMacroName: '',
declarationLines: tempMacroDeclarationLines,
terminationLine: '',
declaration: tempMacroDeclaration,
termination: ''
})
}
}
if (trimmedStatement.startsWith('%macro')) { if (trimmedStatement.startsWith('%macro')) {
const startLineNumber = index + 1 const startLineNumber = lineIndex + 1
if (
isStatementContinues &&
Object.is(statements.length - 1, statementIndex)
) {
tempMacroDeclaration = trimmedStatement
tempMacroDeclarationLines = [line]
tempStartLineNumbers = [startLineNumber]
isReadingMacroDefinition = true
return
}
const name = trimmedStatement const name = trimmedStatement
.slice(7, trimmedStatement.length) .slice(7, trimmedStatement.length)
.trim() .trim()
.split('/')[0] .split('/')[0]
.split('(')[0] .split('(')[0]
.trim()
macroStack.push({ macroStack.push({
name, name,
startLineNumber, startLineNumbers: [startLineNumber],
endLineNumber: null, endLineNumber: null,
parentMacro: macroStack.length parentMacro: macroStack.length
? macroStack[macroStack.length - 1].name ? macroStack[macroStack.length - 1].name
: '', : '',
hasMacroNameInMend: false, hasMacroNameInMend: false,
mismatchedMendMacroName: '', mismatchedMendMacroName: '',
declarationLine: line, declarationLines: [line],
terminationLine: '', terminationLine: '',
declaration: trimmedStatement, declaration: trimmedStatement,
termination: '' termination: ''
@@ -63,7 +117,7 @@ export const parseMacros = (text: string, config?: LintConfig): Macro[] => {
const macro = macroStack.pop() as Macro const macro = macroStack.pop() as Macro
const mendMacroName = const mendMacroName =
trimmedStatement.split(' ').filter((s: string) => !!s)[1] || '' trimmedStatement.split(' ').filter((s: string) => !!s)[1] || ''
macro.endLineNumber = index + 1 macro.endLineNumber = lineIndex + 1
macro.hasMacroNameInMend = mendMacroName === macro.name macro.hasMacroNameInMend = mendMacroName === macro.name
macro.mismatchedMendMacroName = macro.hasMacroNameInMend macro.mismatchedMendMacroName = macro.hasMacroNameInMend
? '' ? ''
@@ -74,12 +128,12 @@ export const parseMacros = (text: string, config?: LintConfig): Macro[] => {
} else { } else {
macros.push({ macros.push({
name: '', name: '',
startLineNumber: null, startLineNumbers: [],
endLineNumber: index + 1, endLineNumber: lineIndex + 1,
parentMacro: '', parentMacro: '',
hasMacroNameInMend: false, hasMacroNameInMend: false,
mismatchedMendMacroName: '', mismatchedMendMacroName: '',
declarationLine: '', declarationLines: [],
terminationLine: line, terminationLine: line,
declaration: '', declaration: '',
termination: trimmedStatement termination: trimmedStatement

View File

@@ -13,7 +13,7 @@ describe('trimComments', () => {
/* some comment */ CODE_Keyword1 /* some comment */ CODE_Keyword2/* some comment */;/* some comment */ /* some comment */ CODE_Keyword1 /* some comment */ CODE_Keyword2/* some comment */;/* some comment */
/* some comment */`) /* some comment */`)
).toEqual({ ).toEqual({
statement: 'CODE_Keyword1 CODE_Keyword2;', statement: 'CODE_Keyword1 CODE_Keyword2;',
commentStarted: false commentStarted: false
}) })
}) })

View File

@@ -1,8 +1,9 @@
export const trimComments = ( export const trimComments = (
statement: string, statement: string,
commentStarted: boolean = false commentStarted: boolean = false,
trimEnd: boolean = false
): { statement: string; commentStarted: boolean } => { ): { statement: string; commentStarted: boolean } => {
let trimmed = (statement || '').trim() let trimmed = trimEnd ? (statement || '').trimEnd() : (statement || '').trim()
if (commentStarted || trimmed.startsWith('/*')) { if (commentStarted || trimmed.startsWith('/*')) {
const parts = trimmed.split('*/') const parts = trimmed.split('*/')
@@ -20,13 +21,16 @@ export const trimComments = (
} else if (trimmed.includes('/*')) { } else if (trimmed.includes('/*')) {
const statementBeforeCommentStarts = trimmed.slice(0, trimmed.indexOf('/*')) const statementBeforeCommentStarts = trimmed.slice(0, trimmed.indexOf('/*'))
const remainingStatement = trimmed.slice( const remainingStatement = trimmed.slice(
trimmed.indexOf('/*'), trimmed.indexOf('*/') + 2,
trimmed.length trimmed.length
) )
const result = trimComments(remainingStatement, false) const result = trimComments(remainingStatement, false, true)
const completeStatement = statementBeforeCommentStarts + result.statement
return { return {
statement: statementBeforeCommentStarts + result.statement, statement: trimEnd
? completeStatement.trimEnd()
: completeStatement.trim(),
commentStarted: result.commentStarted commentStarted: result.commentStarted
} }
} }