mirror of
https://github.com/sasjs/lint.git
synced 2026-01-06 20:20:06 +00:00
feat(lint): implement v1 with 3 rules - trailing spaces, encoded passwords and Doxygen header
This commit is contained in:
37
src/rules/hasDoxygenHeader.spec.ts
Normal file
37
src/rules/hasDoxygenHeader.spec.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { hasDoxygenHeader } from './hasDoxygenHeader'
|
||||
|
||||
describe('hasDoxygenHeader', () => {
|
||||
it('should return an empty array when the file starts with a doxygen header', () => {
|
||||
const content = `/**
|
||||
@file
|
||||
@brief Returns an unused libref
|
||||
**/
|
||||
|
||||
%macro mf_getuniquelibref(prefix=mclib,maxtries=1000);
|
||||
%local x libref;
|
||||
%let x={SAS002};
|
||||
%do x=0 %to &maxtries;`
|
||||
|
||||
expect(hasDoxygenHeader.test(content)).toEqual([])
|
||||
})
|
||||
|
||||
it('should return an array with a single diagnostic when the file has no header', () => {
|
||||
const content = `
|
||||
%macro mf_getuniquelibref(prefix=mclib,maxtries=1000);
|
||||
%local x libref;
|
||||
%let x={SAS002};
|
||||
%do x=0 %to &maxtries;`
|
||||
|
||||
expect(hasDoxygenHeader.test(content)).toEqual([
|
||||
{ warning: 'File missing Doxygen header', lineNumber: 1, columnNumber: 1 }
|
||||
])
|
||||
})
|
||||
|
||||
it('should return an array with a single diagnostic when the file is undefined', () => {
|
||||
const content = undefined
|
||||
|
||||
expect(hasDoxygenHeader.test((content as unknown) as string)).toEqual([
|
||||
{ warning: 'File missing Doxygen header', lineNumber: 1, columnNumber: 1 }
|
||||
])
|
||||
})
|
||||
})
|
||||
24
src/rules/hasDoxygenHeader.ts
Normal file
24
src/rules/hasDoxygenHeader.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { FileLintRule } from '../types/LintRule'
|
||||
import { LintRuleType } from '../types/LintRuleType'
|
||||
|
||||
const name = 'hasDoxygenHeader'
|
||||
const description =
|
||||
'Enforce the presence of a Doxygen header at the start of each file.'
|
||||
const warning = 'File missing Doxygen header'
|
||||
const test = (value: string) => {
|
||||
try {
|
||||
const hasFileHeader = value.split('/**')[0] !== value
|
||||
if (hasFileHeader) return []
|
||||
return [{ warning, lineNumber: 1, columnNumber: 1 }]
|
||||
} catch (e) {
|
||||
return [{ warning, lineNumber: 1, columnNumber: 1 }]
|
||||
}
|
||||
}
|
||||
|
||||
export const hasDoxygenHeader: FileLintRule = {
|
||||
type: LintRuleType.File,
|
||||
name,
|
||||
description,
|
||||
warning,
|
||||
test
|
||||
}
|
||||
35
src/rules/noEncodedPasswords.spec.ts
Normal file
35
src/rules/noEncodedPasswords.spec.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { noEncodedPasswords } from './noEncodedPasswords'
|
||||
|
||||
describe('noEncodedPasswords', () => {
|
||||
it('should return an empty array when the line has no encoded passwords', () => {
|
||||
const line = "%put 'hello';"
|
||||
expect(noEncodedPasswords.test(line, 1)).toEqual([])
|
||||
})
|
||||
|
||||
it('should return an array with a single diagnostic when the line has an encoded password', () => {
|
||||
const line = "%put '{SAS001}'; "
|
||||
expect(noEncodedPasswords.test(line, 1)).toEqual([
|
||||
{
|
||||
warning: 'Line contains encoded password',
|
||||
lineNumber: 1,
|
||||
columnNumber: 7
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
it('should return an array with multiple diagnostics when the line has encoded passwords', () => {
|
||||
const line = "%put '{SAS001} {SAS002}'; "
|
||||
expect(noEncodedPasswords.test(line, 1)).toEqual([
|
||||
{
|
||||
warning: 'Line contains encoded password',
|
||||
lineNumber: 1,
|
||||
columnNumber: 7
|
||||
},
|
||||
{
|
||||
warning: 'Line contains encoded password',
|
||||
lineNumber: 1,
|
||||
columnNumber: 16
|
||||
}
|
||||
])
|
||||
})
|
||||
})
|
||||
24
src/rules/noEncodedPasswords.ts
Normal file
24
src/rules/noEncodedPasswords.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { LineLintRule } from '../types/LintRule'
|
||||
import { LintRuleType } from '../types/LintRuleType'
|
||||
|
||||
const name = 'noEncodedPasswords'
|
||||
const description = 'Disallow encoded passwords in SAS code.'
|
||||
const warning = 'Line contains encoded password'
|
||||
const test = (value: string, lineNumber: number) => {
|
||||
const regex = new RegExp(/{sas\d{2,4}}[^;"'\s]*/, 'gi')
|
||||
const matches = value.match(regex)
|
||||
if (!matches || !matches.length) return []
|
||||
return matches.map((match) => ({
|
||||
warning,
|
||||
lineNumber,
|
||||
columnNumber: value.indexOf(match) + 1
|
||||
}))
|
||||
}
|
||||
|
||||
export const noEncodedPasswords: LineLintRule = {
|
||||
type: LintRuleType.Line,
|
||||
name,
|
||||
description,
|
||||
warning,
|
||||
test
|
||||
}
|
||||
19
src/rules/noTrailingSpaces.spec.ts
Normal file
19
src/rules/noTrailingSpaces.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { noTrailingSpaces } from './noTrailingSpaces'
|
||||
|
||||
describe('noTrailingSpaces', () => {
|
||||
it('should return an empty array when the line has no trailing spaces', () => {
|
||||
const line = "%put 'hello';"
|
||||
expect(noTrailingSpaces.test(line, 1)).toEqual([])
|
||||
})
|
||||
|
||||
it('should return an array with a single diagnostic when the line has trailing spaces', () => {
|
||||
const line = "%put 'hello'; "
|
||||
expect(noTrailingSpaces.test(line, 1)).toEqual([
|
||||
{
|
||||
warning: 'Line contains trailing spaces',
|
||||
lineNumber: 1,
|
||||
columnNumber: 14
|
||||
}
|
||||
])
|
||||
})
|
||||
})
|
||||
18
src/rules/noTrailingSpaces.ts
Normal file
18
src/rules/noTrailingSpaces.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { LineLintRule } from '../types/LintRule'
|
||||
import { LintRuleType } from '../types/LintRuleType'
|
||||
|
||||
const name = 'noTrailingSpaces'
|
||||
const description = 'Disallow trailing spaces on lines.'
|
||||
const warning = 'Line contains trailing spaces'
|
||||
const test = (value: string, lineNumber: number) =>
|
||||
value.trimEnd() === value
|
||||
? []
|
||||
: [{ warning, lineNumber, columnNumber: value.trimEnd().length + 1 }]
|
||||
|
||||
export const noTrailingSpaces: LineLintRule = {
|
||||
type: LintRuleType.Line,
|
||||
name,
|
||||
description,
|
||||
warning,
|
||||
test
|
||||
}
|
||||
Reference in New Issue
Block a user