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

feat(format): rules for hasMacroNameInMend

This commit is contained in:
Saad Jutt
2021-04-21 16:25:36 +05:00
parent 59f7e71919
commit db2dbb1c69
3 changed files with 137 additions and 33 deletions

View File

@@ -339,6 +339,7 @@ describe('hasMacroNameInMend', () => {
}
])
})
it('should add macro name to the mend statement if not present', () => {
const content = ` %macro somemacro;\n %put &sysmacroname;\n %mend;`
const expectedContent = ` %macro somemacro;\n %put &sysmacroname;\n %mend somemacro;`
@@ -349,8 +350,8 @@ describe('hasMacroNameInMend', () => {
})
it('should add macro name to the mend statement if not present ( code in single line )', () => {
const content = `%macro somemacro; %put &sysmacroname; %mend;`
const expectedContent = `%macro somemacro; %put &sysmacroname; %mend somemacro;`
const content = `%macro somemacro; %put &sysmacroname; %mend; some code;`
const expectedContent = `%macro somemacro; %put &sysmacroname; %mend somemacro; some code;`
const formattedContent = hasMacroNameInMend.fix!(content, new LintConfig())
@@ -380,9 +381,77 @@ describe('hasMacroNameInMend', () => {
expect(formattedContent).toEqual(expectedContent)
})
it('should remove redundant %mend statement', () => {
const content = `
%macro somemacro;
%put &sysmacroname;
%mend somemacro;
%mend something;`
const expectedContent = `
%macro somemacro;
%put &sysmacroname;
%mend somemacro;
`
const formattedContent = hasMacroNameInMend.fix!(content, new LintConfig())
expect(formattedContent).toEqual(expectedContent)
})
it('should remove redundant %mend statement with comments', () => {
const content = `
%macro somemacro;
%put &sysmacroname;
%mend somemacro;
/* some comment */
/* some comment */ %mend something; some code;
/* some comment */`
const expectedContent = `
%macro somemacro;
%put &sysmacroname;
%mend somemacro;
/* some comment */
/* some comment */ some code;
/* some comment */`
const formattedContent = hasMacroNameInMend.fix!(content, new LintConfig())
expect(formattedContent).toEqual(expectedContent)
})
it('should correct mismatched macro name', () => {
const content = `
%macro somemacro;
%put &sysmacroname;
%mend someanothermacro;`
const expectedContent = `
%macro somemacro;
%put &sysmacroname;
%mend somemacro;`
const formattedContent = hasMacroNameInMend.fix!(content, new LintConfig())
expect(formattedContent).toEqual(expectedContent)
})
it('should correct mismatched macro name with comments', () => {
const content = `
%macro somemacro;
/* some comments */
%put &sysmacroname;
/* some comments */
%mend someanothermacro ;`
const expectedContent = `
%macro somemacro;
/* some comments */
%put &sysmacroname;
/* some comments */
%mend somemacro ;`
const formattedContent = hasMacroNameInMend.fix!(content, new LintConfig())
expect(formattedContent).toEqual(expectedContent)
})
it('should use the configured line ending while applying the fix', () => {
const content = `%macro somemacro();\r\n%put &sysmacroname;\r\n%mend;`
const expectedContent = `%macro somemacro();\r\n%put &sysmacroname;\r\n%mend somemacro;\r\n`
const content = `%macro somemacro();\r\n%put &sysmacroname;\r\n%mend ;`
const expectedContent = `%macro somemacro();\r\n%put &sysmacroname;\r\n%mend somemacro ;`
const formattedContent = hasMacroNameInMend.fix!(
content,

View File

@@ -18,17 +18,14 @@ const test = (value: string, config?: LintConfig) => {
const diagnostics: Diagnostic[] = []
macros.forEach((macro) => {
if (macro.startLineNumber === null && macro.endLineNumber !== null) {
const endLine = lines[macro.endLineNumber - 1]
diagnostics.push({
message: `%mend statement is redundant`,
lineNumber: macro.endLineNumber,
startColumnNumber: getColumnNumber(
lines[macro.endLineNumber - 1],
'%mend'
),
startColumnNumber: getColumnNumber(endLine, '%mend'),
endColumnNumber:
getColumnNumber(lines[macro.endLineNumber - 1], '%mend') +
lines[macro.endLineNumber - 1].trim().length -
1,
getColumnNumber(endLine, '%mend') +
macro.terminationTrimmedStatement.length,
severity: Severity.Warning
})
} else if (macro.endLineNumber === null && macro.startLineNumber !== null) {
@@ -40,35 +37,29 @@ const test = (value: string, config?: LintConfig) => {
severity: Severity.Warning
})
} else if (macro.mismatchedMendMacroName) {
const endLine = lines[(macro.endLineNumber as number) - 1]
diagnostics.push({
message: `%mend statement has mismatched macro name, it should be '${
macro!.name
}'`,
lineNumber: macro.endLineNumber as number,
startColumnNumber: getColumnNumber(
lines[(macro.endLineNumber as number) - 1],
endLine,
macro.mismatchedMendMacroName
),
endColumnNumber:
getColumnNumber(
lines[(macro.endLineNumber as number) - 1],
macro.mismatchedMendMacroName
) +
getColumnNumber(endLine, macro.mismatchedMendMacroName) +
macro.mismatchedMendMacroName.length -
1,
severity: Severity.Warning
})
} else if (!macro.hasMacroNameInMend) {
const endLine = lines[(macro.endLineNumber as number) - 1]
diagnostics.push({
message: `%mend statement is missing macro name - ${macro.name}`,
lineNumber: macro.endLineNumber as number,
startColumnNumber: getColumnNumber(
lines[(macro.endLineNumber as number) - 1],
'%mend'
),
endColumnNumber:
getColumnNumber(lines[(macro.endLineNumber as number) - 1], '%mend') +
6,
startColumnNumber: getColumnNumber(endLine, '%mend'),
endColumnNumber: getColumnNumber(endLine, '%mend') + 6,
severity: Severity.Warning
})
}
@@ -79,16 +70,53 @@ const test = (value: string, config?: LintConfig) => {
const fix = (value: string, config?: LintConfig): string => {
const lineEnding = config?.lineEndings === LineEndings.CRLF ? '\r\n' : '\n'
let formattedText = value
const lines: string[] = value ? value.split(lineEnding) : []
const macros = parseMacros(value, config)
macros
.filter((macro) => !macro.hasMacroNameInMend)
.forEach((macro) => {
formattedText = formattedText.replace(
macro.termination,
`%mend ${macro.name};${lineEnding}`
macros.forEach((macro) => {
if (macro.startLineNumber === null && macro.endLineNumber !== null) {
// %mend statement is redundant
const endLine = lines[macro.endLineNumber - 1]
const startColumnNumber = getColumnNumber(endLine, '%mend')
const endColumnNumber =
getColumnNumber(endLine, '%mend') +
macro.terminationTrimmedStatement.length
const beforeStatement = endLine.slice(0, startColumnNumber - 1)
const afterStatement = endLine.slice(endColumnNumber)
lines[macro.endLineNumber - 1] = beforeStatement + afterStatement
} else if (macro.endLineNumber === null && macro.startLineNumber !== null) {
// missing %mend statement
} else if (macro.mismatchedMendMacroName) {
// mismatched macro name
const endLine = lines[(macro.endLineNumber as number) - 1]
const startColumnNumber = getColumnNumber(
endLine,
macro.mismatchedMendMacroName
)
})
const endColumnNumber =
getColumnNumber(endLine, macro.mismatchedMendMacroName) +
macro.mismatchedMendMacroName.length -
1
const beforeMacroName = endLine.slice(0, startColumnNumber - 1)
const afterMacroName = endLine.slice(endColumnNumber)
lines[(macro.endLineNumber as number) - 1] =
beforeMacroName + macro.name + afterMacroName
} else if (!macro.hasMacroNameInMend) {
// %mend statement is missing macro name
const endLine = lines[(macro.endLineNumber as number) - 1]
const startColumnNumber = getColumnNumber(endLine, '%mend')
const endColumnNumber = getColumnNumber(endLine, '%mend') + 4
const beforeStatement = endLine.slice(0, startColumnNumber - 1)
const afterStatement = endLine.slice(endColumnNumber)
lines[(macro.endLineNumber as number) - 1] =
beforeStatement + `%mend ${macro.name}` + afterStatement
}
})
const formattedText = lines.join(lineEnding)
return formattedText
}

View File

@@ -8,6 +8,8 @@ interface Macro {
endLineNumber: number | null
declaration: string
termination: string
declarationTrimmedStatement: string
terminationTrimmedStatement: string
parentMacro: string
hasMacroNameInMend: boolean
hasParentheses: boolean
@@ -53,7 +55,9 @@ export const parseMacros = (text: string, config?: LintConfig): Macro[] => {
hasMacroNameInMend: false,
mismatchedMendMacroName: '',
declaration: line,
termination: ''
termination: '',
declarationTrimmedStatement: trimmedStatement,
terminationTrimmedStatement: ''
})
} else if (trimmedStatement.startsWith('%mend')) {
if (macroStack.length) {
@@ -66,6 +70,7 @@ export const parseMacros = (text: string, config?: LintConfig): Macro[] => {
? ''
: mendMacroName
macro.termination = line
macro.terminationTrimmedStatement = trimmedStatement
macros.push(macro)
} else {
macros.push({
@@ -77,7 +82,9 @@ export const parseMacros = (text: string, config?: LintConfig): Macro[] => {
hasMacroNameInMend: false,
mismatchedMendMacroName: '',
declaration: '',
termination: line
termination: line,
declarationTrimmedStatement: '',
terminationTrimmedStatement: trimmedStatement
})
}
}