mirror of
https://github.com/sasjs/lint.git
synced 2026-01-08 13:00:06 +00:00
feat(lint): add rules for lowercase file names, max line length and no tab indentation
This commit is contained in:
27
src/rules/lowerCaseFileNames.spec.ts
Normal file
27
src/rules/lowerCaseFileNames.spec.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Severity } from '../types/Severity'
|
||||
import { lowerCaseFileNames } from './lowerCaseFileNames'
|
||||
|
||||
describe('lowerCaseFileNames', () => {
|
||||
it('should return an empty array when the file name has no uppercase characters', () => {
|
||||
const filePath = '/code/sas/my_sas_file.sas'
|
||||
expect(lowerCaseFileNames.test(filePath)).toEqual([])
|
||||
})
|
||||
|
||||
it('should return an empty array when the file name has no uppercase characters, even if the containing folder has uppercase characters', () => {
|
||||
const filePath = '/code/SAS Projects/my_sas_file.sas'
|
||||
expect(lowerCaseFileNames.test(filePath)).toEqual([])
|
||||
})
|
||||
|
||||
it('should return an array with a single diagnostic when the file name has uppercase characters', () => {
|
||||
const filePath = '/code/sas/my SAS file.sas'
|
||||
expect(lowerCaseFileNames.test(filePath)).toEqual([
|
||||
{
|
||||
message: 'File name contains uppercase characters',
|
||||
lineNumber: 1,
|
||||
startColumnNumber: 1,
|
||||
endColumnNumber: 1,
|
||||
severity: Severity.Warning
|
||||
}
|
||||
])
|
||||
})
|
||||
})
|
||||
32
src/rules/lowerCaseFileNames.ts
Normal file
32
src/rules/lowerCaseFileNames.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { PathLintRule } from '../types/LintRule'
|
||||
import { LintRuleType } from '../types/LintRuleType'
|
||||
import { Severity } from '../types/Severity'
|
||||
import path from 'path'
|
||||
|
||||
const name = 'lowerCaseFileNames'
|
||||
const description = 'Enforce the use of lower case file names.'
|
||||
const message = 'File name contains uppercase characters'
|
||||
const test = (value: string) => {
|
||||
const fileName = path.basename(value)
|
||||
if (fileName.toLocaleLowerCase() === fileName) return []
|
||||
return [
|
||||
{
|
||||
message,
|
||||
lineNumber: 1,
|
||||
startColumnNumber: 1,
|
||||
endColumnNumber: 1,
|
||||
severity: Severity.Warning
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Lint rule that checks for the absence of uppercase characters in a given file name.
|
||||
*/
|
||||
export const lowerCaseFileNames: PathLintRule = {
|
||||
type: LintRuleType.Path,
|
||||
name,
|
||||
description,
|
||||
message,
|
||||
test
|
||||
}
|
||||
44
src/rules/maxLineLength.spec.ts
Normal file
44
src/rules/maxLineLength.spec.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { LintConfig, Severity } from '../types'
|
||||
import { maxLineLength } from './maxLineLength'
|
||||
|
||||
describe('maxLineLength', () => {
|
||||
it('should return an empty array when the line is within the specified length', () => {
|
||||
const line = "%put 'hello';"
|
||||
const config = new LintConfig({ maxLineLength: 60 })
|
||||
expect(maxLineLength.test(line, 1, config)).toEqual([])
|
||||
})
|
||||
|
||||
it('should return an array with a single diagnostic when the line exceeds the specified length', () => {
|
||||
const line = "%put 'hello';"
|
||||
const config = new LintConfig({ maxLineLength: 10 })
|
||||
expect(maxLineLength.test(line, 1, config)).toEqual([
|
||||
{
|
||||
message: `Line exceeds maximum length by 3 characters`,
|
||||
lineNumber: 1,
|
||||
startColumnNumber: 1,
|
||||
endColumnNumber: 1,
|
||||
severity: Severity.Warning
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
it('should fall back to a default of 80 characters', () => {
|
||||
const line =
|
||||
'Prow scuttle parrel provost Sail ho shrouds spirits boom mizzenmast yardarm. Pinnace holystone.'
|
||||
expect(maxLineLength.test(line, 1)).toEqual([
|
||||
{
|
||||
message: `Line exceeds maximum length by 15 characters`,
|
||||
lineNumber: 1,
|
||||
startColumnNumber: 1,
|
||||
endColumnNumber: 1,
|
||||
severity: Severity.Warning
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
it('should return an empty array for lines within the default length', () => {
|
||||
const line =
|
||||
'Prow scuttle parrel provost Sail ho shrouds spirits boom mizzenmast yard'
|
||||
expect(maxLineLength.test(line, 1)).toEqual([])
|
||||
})
|
||||
})
|
||||
32
src/rules/maxLineLength.ts
Normal file
32
src/rules/maxLineLength.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { LintConfig } from '../types'
|
||||
import { LineLintRule } from '../types/LintRule'
|
||||
import { LintRuleType } from '../types/LintRuleType'
|
||||
import { Severity } from '../types/Severity'
|
||||
|
||||
const name = 'maxLineLength'
|
||||
const description = 'Restrict lines to the specified length.'
|
||||
const message = 'Line exceeds maximum length'
|
||||
const test = (value: string, lineNumber: number, config?: LintConfig) => {
|
||||
const maxLineLength = config?.maxLineLength || 80
|
||||
if (value.length <= maxLineLength) return []
|
||||
return [
|
||||
{
|
||||
message: `${message} by ${value.length - maxLineLength} characters`,
|
||||
lineNumber,
|
||||
startColumnNumber: 1,
|
||||
endColumnNumber: 1,
|
||||
severity: Severity.Warning
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Lint rule that checks if a line has exceeded the configured maximum length.
|
||||
*/
|
||||
export const maxLineLength: LineLintRule = {
|
||||
type: LintRuleType.Line,
|
||||
name,
|
||||
description,
|
||||
message,
|
||||
test
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { PathLintRule } from '../types/LintRule'
|
||||
import { LintRuleType } from '../types/LintRuleType'
|
||||
import path from 'path'
|
||||
import { Severity } from '../types/Severity'
|
||||
import path from 'path'
|
||||
|
||||
const name = 'noSpacesInFileNames'
|
||||
const description = 'Enforce the absence of spaces within file names.'
|
||||
|
||||
22
src/rules/noTabIndentation.spec.ts
Normal file
22
src/rules/noTabIndentation.spec.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Severity } from '../types/Severity'
|
||||
import { noTabIndentation } from './noTabIndentation'
|
||||
|
||||
describe('noTabs', () => {
|
||||
it('should return an empty array when the line is not indented with a tab', () => {
|
||||
const line = "%put 'hello';"
|
||||
expect(noTabIndentation.test(line, 1)).toEqual([])
|
||||
})
|
||||
|
||||
it('should return an array with a single diagnostic when the line is indented with a tab', () => {
|
||||
const line = "\t%put 'hello';"
|
||||
expect(noTabIndentation.test(line, 1)).toEqual([
|
||||
{
|
||||
message: 'Line is indented with a tab',
|
||||
lineNumber: 1,
|
||||
startColumnNumber: 1,
|
||||
endColumnNumber: 1,
|
||||
severity: Severity.Warning
|
||||
}
|
||||
])
|
||||
})
|
||||
})
|
||||
30
src/rules/noTabIndentation.ts
Normal file
30
src/rules/noTabIndentation.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { LineLintRule } from '../types/LintRule'
|
||||
import { LintRuleType } from '../types/LintRuleType'
|
||||
import { Severity } from '../types/Severity'
|
||||
|
||||
const name = 'noTabs'
|
||||
const description = 'Disallow indenting with tabs.'
|
||||
const message = 'Line is indented with a tab'
|
||||
const test = (value: string, lineNumber: number) => {
|
||||
if (!value.startsWith('\t')) return []
|
||||
return [
|
||||
{
|
||||
message,
|
||||
lineNumber,
|
||||
startColumnNumber: 1,
|
||||
endColumnNumber: 1,
|
||||
severity: Severity.Warning
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* Lint rule that checks if a given line of text is indented with a tab.
|
||||
*/
|
||||
export const noTabIndentation: LineLintRule = {
|
||||
type: LintRuleType.Line,
|
||||
name,
|
||||
description,
|
||||
message,
|
||||
test
|
||||
}
|
||||
Reference in New Issue
Block a user