mirror of
https://github.com/sasjs/lint.git
synced 2026-01-06 20:20:06 +00:00
386 lines
10 KiB
TypeScript
386 lines
10 KiB
TypeScript
import { LintConfig } from '../../types'
|
|
import { Severity } from '../../types/Severity'
|
|
import { hasMacroNameInMend } from './hasMacroNameInMend'
|
|
|
|
describe('hasMacroNameInMend', () => {
|
|
it('should return an empty array when %mend has correct macro name', () => {
|
|
const content = `
|
|
%macro somemacro();
|
|
%put &sysmacroname;
|
|
%mend somemacro;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([])
|
|
})
|
|
|
|
it('should return an empty array when %mend has correct macro name without parentheses', () => {
|
|
const content = `
|
|
%macro somemacro;
|
|
%put &sysmacroname;
|
|
%mend somemacro;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([])
|
|
})
|
|
|
|
it('should return an array with a single diagnostic when %mend has no macro name', () => {
|
|
const content = `
|
|
%macro somemacro;
|
|
%put &sysmacroname;
|
|
%mend;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([
|
|
{
|
|
message: '%mend statement is missing macro name - somemacro',
|
|
lineNumber: 4,
|
|
startColumnNumber: 3,
|
|
endColumnNumber: 9,
|
|
severity: Severity.Warning
|
|
}
|
|
])
|
|
})
|
|
|
|
it('should return an array with a single diagnostic when a macro is missing an %mend statement', () => {
|
|
const content = `%macro somemacro;
|
|
%put &sysmacroname;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([
|
|
{
|
|
message: 'Missing %mend statement for macro - somemacro',
|
|
lineNumber: 1,
|
|
startColumnNumber: 1,
|
|
endColumnNumber: 1,
|
|
severity: Severity.Warning
|
|
}
|
|
])
|
|
})
|
|
|
|
it('should return an array with a diagnostic for each macro missing an %mend statement', () => {
|
|
const content = `%macro somemacro;
|
|
%put &sysmacroname;
|
|
%macro othermacro`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([
|
|
{
|
|
message: 'Missing %mend statement for macro - somemacro',
|
|
lineNumber: 1,
|
|
startColumnNumber: 1,
|
|
endColumnNumber: 1,
|
|
severity: Severity.Warning
|
|
},
|
|
{
|
|
message: 'Missing %mend statement for macro - othermacro',
|
|
lineNumber: 3,
|
|
startColumnNumber: 1,
|
|
endColumnNumber: 1,
|
|
severity: Severity.Warning
|
|
}
|
|
])
|
|
})
|
|
|
|
it('should return an array with a single diagnostic when %mend has incorrect macro name', () => {
|
|
const content = `
|
|
%macro somemacro;
|
|
%put &sysmacroname;
|
|
%mend someanothermacro;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([
|
|
{
|
|
message: `%mend statement has mismatched macro name, it should be 'somemacro'`,
|
|
lineNumber: 4,
|
|
startColumnNumber: 9,
|
|
endColumnNumber: 24,
|
|
severity: Severity.Warning
|
|
}
|
|
])
|
|
})
|
|
|
|
it('should return an array with a single diagnostic when extra %mend statement is present', () => {
|
|
const content = `
|
|
%macro somemacro;
|
|
%put &sysmacroname;
|
|
%mend somemacro;
|
|
%mend something;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([
|
|
{
|
|
message: '%mend statement is redundant',
|
|
lineNumber: 5,
|
|
startColumnNumber: 3,
|
|
endColumnNumber: 18,
|
|
severity: Severity.Warning
|
|
}
|
|
])
|
|
})
|
|
|
|
it('should return an empty array when the file is undefined', () => {
|
|
const content = undefined
|
|
|
|
expect(hasMacroNameInMend.test((content as unknown) as string)).toEqual([])
|
|
})
|
|
|
|
describe('nestedMacros', () => {
|
|
it('should return an empty array when %mend has correct macro name', () => {
|
|
const content = `
|
|
%macro outer();
|
|
|
|
%macro inner();
|
|
%put inner;
|
|
%mend inner;
|
|
%inner()
|
|
%put outer;
|
|
%mend outer;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([])
|
|
})
|
|
|
|
it('should return an array with a single diagnostic when %mend has no macro name(inner)', () => {
|
|
const content = `
|
|
%macro outer();
|
|
|
|
%macro inner();
|
|
%put inner;
|
|
%mend;
|
|
%inner()
|
|
%put outer;
|
|
%mend outer;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([
|
|
{
|
|
message: '%mend statement is missing macro name - inner',
|
|
lineNumber: 6,
|
|
startColumnNumber: 5,
|
|
endColumnNumber: 11,
|
|
severity: Severity.Warning
|
|
}
|
|
])
|
|
})
|
|
|
|
it('should return an array with a single diagnostic when %mend has no macro name(outer)', () => {
|
|
const content = `
|
|
%macro outer();
|
|
|
|
%macro inner();
|
|
%put inner;
|
|
%mend inner;
|
|
%inner()
|
|
%put outer;
|
|
%mend;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([
|
|
{
|
|
message: '%mend statement is missing macro name - outer',
|
|
lineNumber: 9,
|
|
startColumnNumber: 3,
|
|
endColumnNumber: 9,
|
|
severity: Severity.Warning
|
|
}
|
|
])
|
|
})
|
|
|
|
it('should return an array with two diagnostics when %mend has no macro name(none)', () => {
|
|
const content = `
|
|
%macro outer();
|
|
|
|
%macro inner();
|
|
%put inner;
|
|
%mend;
|
|
%inner()
|
|
%put outer;
|
|
%mend;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([
|
|
{
|
|
message: '%mend statement is missing macro name - inner',
|
|
lineNumber: 6,
|
|
startColumnNumber: 5,
|
|
endColumnNumber: 11,
|
|
severity: Severity.Warning
|
|
},
|
|
{
|
|
message: '%mend statement is missing macro name - outer',
|
|
lineNumber: 9,
|
|
startColumnNumber: 3,
|
|
endColumnNumber: 9,
|
|
severity: Severity.Warning
|
|
}
|
|
])
|
|
})
|
|
})
|
|
|
|
describe('with extra spaces and comments', () => {
|
|
it('should return an empty array when %mend has correct macro name', () => {
|
|
const content = `
|
|
/* 1st comment */
|
|
%macro somemacro ;
|
|
|
|
%put &sysmacroname;
|
|
|
|
/* 2nd
|
|
comment */
|
|
/* 3rd comment */ %mend somemacro ;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([])
|
|
})
|
|
|
|
it('should return an array with a single diagnostic when %mend has correct macro name having code in comments', () => {
|
|
const content = `/**
|
|
@file examplemacro.sas
|
|
@brief an example of a macro to be used in a service
|
|
@details This macro is great. Yadda yadda yadda. Usage:
|
|
|
|
* code formatting applies when indented by 4 spaces; code formatting applies when indented by 4 spaces; code formatting applies when indented by 4 spaces; code formatting applies when indented by 4 spaces; code formatting applies when indented by 4 spaces;
|
|
|
|
some code
|
|
%macro examplemacro123();
|
|
|
|
%examplemacro()
|
|
|
|
<h4> SAS Macros </h4>
|
|
@li doesnothing.sas
|
|
|
|
@author Allan Bowe
|
|
**/
|
|
|
|
%macro examplemacro();
|
|
|
|
proc sql;
|
|
create table areas
|
|
as select area
|
|
|
|
from sashelp.springs;
|
|
|
|
%doesnothing();
|
|
|
|
%mend;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([
|
|
{
|
|
message: '%mend statement is missing macro name - examplemacro',
|
|
lineNumber: 29,
|
|
startColumnNumber: 5,
|
|
endColumnNumber: 11,
|
|
severity: Severity.Warning
|
|
}
|
|
])
|
|
})
|
|
|
|
it('should return an array with a single diagnostic when %mend has incorrect macro name', () => {
|
|
const content = `
|
|
%macro somemacro;
|
|
/* some comments */
|
|
%put &sysmacroname;
|
|
/* some comments */
|
|
%mend someanothermacro ;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([
|
|
{
|
|
message: `%mend statement has mismatched macro name, it should be 'somemacro'`,
|
|
lineNumber: 6,
|
|
startColumnNumber: 14,
|
|
endColumnNumber: 29,
|
|
severity: Severity.Warning
|
|
}
|
|
])
|
|
})
|
|
|
|
it('should return an array with a single diagnostic when %mend has no macro name', () => {
|
|
const content = `
|
|
%macro somemacro ;
|
|
/* some comments */%put &sysmacroname;
|
|
%mend ;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([
|
|
{
|
|
message: '%mend statement is missing macro name - somemacro',
|
|
lineNumber: 4,
|
|
startColumnNumber: 5,
|
|
endColumnNumber: 11,
|
|
severity: Severity.Warning
|
|
}
|
|
])
|
|
})
|
|
|
|
describe('nestedMacros', () => {
|
|
it('should return an empty array when %mend has correct macro name', () => {
|
|
const content = `
|
|
%macro outer( ) ;
|
|
|
|
|
|
%macro inner();
|
|
|
|
%put inner;
|
|
|
|
%mend inner;
|
|
|
|
%inner()
|
|
|
|
%put outer;
|
|
%mend outer;`
|
|
|
|
expect(hasMacroNameInMend.test(content)).toEqual([])
|
|
})
|
|
})
|
|
})
|
|
|
|
it('should use the configured line ending while testing content', () => {
|
|
const content = `%macro somemacro();\r\n%put &sysmacroname;\r\n%mend;`
|
|
|
|
const diagnostics = hasMacroNameInMend.test(
|
|
content,
|
|
new LintConfig({ lineEndings: 'crlf' })
|
|
)
|
|
|
|
expect(diagnostics).toEqual([
|
|
{
|
|
message: '%mend statement is missing macro name - somemacro',
|
|
lineNumber: 3,
|
|
startColumnNumber: 1,
|
|
endColumnNumber: 7,
|
|
severity: Severity.Warning
|
|
}
|
|
])
|
|
})
|
|
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;`
|
|
|
|
const formattedContent = hasMacroNameInMend.fix!(content, new LintConfig())
|
|
|
|
expect(formattedContent).toEqual(expectedContent)
|
|
})
|
|
|
|
it('should add macro name to the mend statement if not present ( with multiple macros )', () => {
|
|
const content = `
|
|
%macro somemacro;
|
|
%put &sysmacroname;
|
|
%mend somemacro;
|
|
|
|
%macro somemacro2;
|
|
%put &sysmacroname2;
|
|
%mend;`
|
|
const expectedContent = `
|
|
%macro somemacro;
|
|
%put &sysmacroname;
|
|
%mend somemacro;
|
|
|
|
%macro somemacro2;
|
|
%put &sysmacroname2;
|
|
%mend somemacro2;`
|
|
|
|
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 formattedContent = hasMacroNameInMend.fix!(
|
|
content,
|
|
new LintConfig({ lineEndings: 'crlf' })
|
|
)
|
|
|
|
expect(formattedContent).toEqual(expectedContent)
|
|
})
|
|
})
|