Skip to content

Commit

Permalink
Merge pull request #191 from sasjs/issue-190
Browse files Browse the repository at this point in the history
fix: added more gremlin characters
  • Loading branch information
allanbowe authored Dec 30, 2022
2 parents f6ddfa8 + 5245246 commit f59fd4c
Show file tree
Hide file tree
Showing 11 changed files with 403 additions and 168 deletions.
12 changes: 2 additions & 10 deletions src/format/formatFile.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,8 @@ describe('formatFile', () => {
const expectedContent = `/**\r\n @file\r\n @brief <Your brief here>\r\n <h4> SAS Macros </h4>\r\n**/\r\n%macro somemacro();\r\n%put 'hello';\r\n%mend;`
const expectedResult = {
updatedFilePaths: [path.join(__dirname, 'format-file-config.sas')],
fixedDiagnosticsCount: 2,
unfixedDiagnostics: [
{
endColumnNumber: 7,
lineNumber: 8,
message: '%mend statement is missing macro name - somemacro',
severity: 1,
startColumnNumber: 1
}
]
fixedDiagnosticsCount: 4,
unfixedDiagnostics: []
}
await createFile(path.join(__dirname, 'format-file-config.sas'), content)

Expand Down
4 changes: 2 additions & 2 deletions src/format/formatFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const formatFile = async (
configuration?: LintConfig
): Promise<FormatResult> => {
const config = configuration || (await getLintConfig())
const diagnosticsBeforeFormat = await lintFile(filePath)
const diagnosticsBeforeFormat = await lintFile(filePath, config)
const diagnosticsCountBeforeFormat = diagnosticsBeforeFormat.length

const text = await readFile(filePath)
Expand All @@ -25,7 +25,7 @@ export const formatFile = async (

await createFile(filePath, formattedText)

const diagnosticsAfterFormat = await lintFile(filePath)
const diagnosticsAfterFormat = await lintFile(filePath, config)
const diagnosticsCountAfterFormat = diagnosticsAfterFormat.length

const fixedDiagnosticsCount =
Expand Down
2 changes: 1 addition & 1 deletion src/format/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const processLine = (config: LintConfig, line: string): string => {
config.lineLintRules
.filter((r) => !!r.fix)
.forEach((rule) => {
processedLine = rule.fix!(line, config)
processedLine = rule.fix!(processedLine, config)
})

return processedLine
Expand Down
71 changes: 1 addition & 70 deletions src/rules/line/noGremlins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Diagnostic, LintConfig } from '../../types'
import { LineLintRule } from '../../types/LintRule'
import { LintRuleType } from '../../types/LintRuleType'
import { Severity } from '../../types/Severity'
import { gremlinCharacters } from '../../utils'

const name = 'noGremlins'
const description = 'Disallow characters specified in gremlins array'
Expand Down Expand Up @@ -56,73 +57,3 @@ export const noGremlins: LineLintRule = {
}

const charFromHex = (hexCode: string) => String.fromCodePoint(parseInt(hexCode))

const gremlinCharacters = {
'0x2013': {
description: 'en dash'
},
'0x2018': {
description: 'left single quotation mark'
},
'0x2019': {
description: 'right single quotation mark'
},
'0x2029': {
zeroWidth: true,
description: 'paragraph separator'
},
'0x2066': {
zeroWidth: true,
description: 'Left to right'
},
'0x2069': {
zeroWidth: true,
description: 'Pop directional'
},
'0x0003': {
description: 'end of text'
},
'0x000b': {
description: 'line tabulation'
},
'0x00a0': {
description: 'non breaking space'
},
'0x00ad': {
description: 'soft hyphen'
},
'0x200b': {
zeroWidth: true,
description: 'zero width space'
},
'0x200c': {
zeroWidth: true,
description: 'zero width non-joiner'
},
'0x200e': {
zeroWidth: true,
description: 'left-to-right mark'
},
'0x201c': {
description: 'left double quotation mark'
},
'0x201d': {
description: 'right double quotation mark'
},
'0x202c': {
zeroWidth: true,
description: 'pop directional formatting'
},
'0x202d': {
zeroWidth: true,
description: 'left-to-right override'
},
'0x202e': {
zeroWidth: true,
description: 'right-to-left override'
},
'0xfffc': {
zeroWidth: true,
description: 'object replacement character'
}
}
116 changes: 51 additions & 65 deletions src/types/LintConfig.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,96 +4,75 @@ import { LintRuleType } from './LintRuleType'
import { Severity } from './Severity'

describe('LintConfig', () => {
it('should create an empty instance', () => {
it('should create an instance with default values when no configuration is provided', () => {
const config = new LintConfig()

expect(config).toBeTruthy()
expect(config.fileLintRules.length).toEqual(0)
expect(config.lineLintRules.length).toEqual(0)
})

it('should create an instance with the noTrailingSpaces flag set', () => {
const config = new LintConfig({ noTrailingSpaces: true })

expect(config).toBeTruthy()
expect(config.lineLintRules.length).toEqual(1)
expect(config.lineLintRules[0].name).toEqual('noTrailingSpaces')
expect(config.lineLintRules[0].type).toEqual(LintRuleType.Line)
expect(config.fileLintRules.length).toEqual(0)
})

it('should create an instance with the noEncodedPasswords flag set', () => {
const config = new LintConfig({ noEncodedPasswords: true })
it('should create an instance with the noTrailingSpaces flag off', () => {
const config = new LintConfig({ noTrailingSpaces: false })

expect(config).toBeTruthy()
expect(config.lineLintRules.length).toEqual(1)
expect(config.lineLintRules[0].name).toEqual('noEncodedPasswords')
expect(config.lineLintRules[0].type).toEqual(LintRuleType.Line)
expect(config.fileLintRules.length).toEqual(0)
expect(config.lineLintRules.length).toBeGreaterThan(0)
expect(config.fileLintRules.length).toBeGreaterThan(0)
expect(
config.lineLintRules.find((rule) => rule.name === 'noTrailingSpaces')
).toBeUndefined()
})

it('should create an instance with the hasDoxygenHeader flag set', () => {
const config = new LintConfig({ hasDoxygenHeader: true })
it('should create an instance with the noEncodedPasswords flag off', () => {
const config = new LintConfig({ noEncodedPasswords: false })

expect(config).toBeTruthy()
expect(config.lineLintRules.length).toEqual(0)
expect(config.fileLintRules.length).toEqual(1)
expect(config.fileLintRules[0].name).toEqual('hasDoxygenHeader')
expect(config.fileLintRules[0].type).toEqual(LintRuleType.File)
expect(config.lineLintRules.length).toBeGreaterThan(0)
expect(config.fileLintRules.length).toBeGreaterThan(0)
expect(
config.lineLintRules.find((rule) => rule.name === 'noEncodedPasswords')
).toBeUndefined()
})

it('should create an instance with the hasMacroNameInMend flag set', () => {
const config = new LintConfig({ hasMacroNameInMend: true })
it('should create an instance with the hasDoxygenHeader flag off', () => {
const config = new LintConfig({ hasDoxygenHeader: false })

expect(config).toBeTruthy()
expect(config.lineLintRules.length).toEqual(0)
expect(config.fileLintRules.length).toEqual(1)
expect(config.fileLintRules[0].name).toEqual('hasMacroNameInMend')
expect(config.fileLintRules[0].type).toEqual(LintRuleType.File)
expect(config.lineLintRules.length).toBeGreaterThan(0)
expect(config.fileLintRules.length).toBeGreaterThan(0)
expect(
config.fileLintRules.find((rule) => rule.name === 'hasDoxygenHeader')
).toBeUndefined()
})

it('should create an instance with the hasMacroNameInMend flag off', () => {
const config = new LintConfig({ hasMacroNameInMend: false })

expect(config).toBeTruthy()
expect(config.lineLintRules.length).toEqual(0)
expect(config.fileLintRules.length).toEqual(0)
})

it('should create an instance with the noNestedMacros flag set', () => {
const config = new LintConfig({ noNestedMacros: true })

expect(config).toBeTruthy()
expect(config.lineLintRules.length).toEqual(0)
expect(config.fileLintRules.length).toEqual(1)
expect(config.fileLintRules[0].name).toEqual('noNestedMacros')
expect(config.fileLintRules[0].type).toEqual(LintRuleType.File)
expect(config.lineLintRules.length).toBeGreaterThan(0)
expect(config.fileLintRules.length).toBeGreaterThan(0)
expect(
config.fileLintRules.find((rule) => rule.name === 'hasMacroNameInMend')
).toBeUndefined()
})

it('should create an instance with the noNestedMacros flag off', () => {
const config = new LintConfig({ noNestedMacros: false })

expect(config).toBeTruthy()
expect(config.lineLintRules.length).toEqual(0)
expect(config.fileLintRules.length).toEqual(0)
})

it('should create an instance with the hasMacroParentheses flag set', () => {
const config = new LintConfig({ hasMacroParentheses: true })

expect(config).toBeTruthy()
expect(config.lineLintRules.length).toEqual(0)
expect(config.fileLintRules.length).toEqual(1)
expect(config.fileLintRules[0].name).toEqual('hasMacroParentheses')
expect(config.fileLintRules[0].type).toEqual(LintRuleType.File)
expect(config.lineLintRules.length).toBeGreaterThan(0)
expect(config.fileLintRules.length).toBeGreaterThan(0)
expect(
config.fileLintRules.find((rule) => rule.name === 'noNestedMacros')
).toBeUndefined()
})

it('should create an instance with the hasMacroParentheses flag off', () => {
const config = new LintConfig({ hasMacroParentheses: false })

expect(config).toBeTruthy()
expect(config.lineLintRules.length).toEqual(0)
expect(config.fileLintRules.length).toEqual(0)
expect(config.lineLintRules.length).toBeGreaterThan(0)
expect(config.fileLintRules.length).toBeGreaterThan(0)
expect(
config.fileLintRules.find((rule) => rule.name === 'hasMacroParentheses')
).toBeUndefined()
})

it('should create an instance with the indentation multiple set', () => {
Expand Down Expand Up @@ -166,11 +145,12 @@ describe('LintConfig', () => {
indentationMultiple: 2,
hasMacroNameInMend: true,
noNestedMacros: true,
hasMacroParentheses: true
hasMacroParentheses: true,
noGremlins: true
})

expect(config).toBeTruthy()
expect(config.lineLintRules.length).toEqual(5)
expect(config.lineLintRules.length).toEqual(6)
expect(config.lineLintRules[0].name).toEqual('noTrailingSpaces')
expect(config.lineLintRules[0].type).toEqual(LintRuleType.Line)
expect(config.lineLintRules[1].name).toEqual('noEncodedPasswords')
Expand All @@ -181,16 +161,22 @@ describe('LintConfig', () => {
expect(config.lineLintRules[3].type).toEqual(LintRuleType.Line)
expect(config.lineLintRules[4].name).toEqual('indentationMultiple')
expect(config.lineLintRules[4].type).toEqual(LintRuleType.Line)
expect(config.lineLintRules[5].name).toEqual('noGremlins')
expect(config.lineLintRules[5].type).toEqual(LintRuleType.Line)

expect(config.fileLintRules.length).toEqual(4)
expect(config.fileLintRules[0].name).toEqual('hasDoxygenHeader')
expect(config.fileLintRules.length).toEqual(6)
expect(config.fileLintRules[0].name).toEqual('lineEndings')
expect(config.fileLintRules[0].type).toEqual(LintRuleType.File)
expect(config.fileLintRules[1].name).toEqual('hasMacroNameInMend')
expect(config.fileLintRules[1].name).toEqual('hasDoxygenHeader')
expect(config.fileLintRules[1].type).toEqual(LintRuleType.File)
expect(config.fileLintRules[2].name).toEqual('noNestedMacros')
expect(config.fileLintRules[2].name).toEqual('hasMacroNameInMend')
expect(config.fileLintRules[2].type).toEqual(LintRuleType.File)
expect(config.fileLintRules[3].name).toEqual('hasMacroParentheses')
expect(config.fileLintRules[3].name).toEqual('noNestedMacros')
expect(config.fileLintRules[3].type).toEqual(LintRuleType.File)
expect(config.fileLintRules[4].name).toEqual('hasMacroParentheses')
expect(config.fileLintRules[4].type).toEqual(LintRuleType.File)
expect(config.fileLintRules[5].name).toEqual('strictMacroDefinition')
expect(config.fileLintRules[5].type).toEqual(LintRuleType.File)

expect(config.pathLintRules.length).toEqual(2)
expect(config.pathLintRules[0].name).toEqual('noSpacesInFileNames')
Expand Down
31 changes: 16 additions & 15 deletions src/types/LintConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,23 +53,25 @@ export class LintConfig {
}
}

if (json?.noTrailingSpaces) {
if (json?.noTrailingSpaces !== false) {
this.lineLintRules.push(noTrailingSpaces)
}

if (json?.noEncodedPasswords) {
if (json?.noEncodedPasswords !== false) {
this.lineLintRules.push(noEncodedPasswords)
}

if (json?.noTabs || json?.noTabIndentation) {
this.lineLintRules.push(noTabs)
this.lineLintRules.push(noTabs)
if (json?.noTabs === false || json?.noTabIndentation === false) {
this.lineLintRules.pop()
}

if (json?.maxLineLength) {
this.lineLintRules.push(maxLineLength)
if (!isNaN(json?.maxLineLength)) {
this.maxLineLength = json.maxLineLength
this.lineLintRules.push(maxLineLength)
}

this.fileLintRules.push(lineEndings)
if (json?.lineEndings) {
if (
json.lineEndings !== LineEndings.LF &&
Expand All @@ -80,47 +82,46 @@ export class LintConfig {
)
}
this.lineEndings = json.lineEndings
this.fileLintRules.push(lineEndings)
}

this.lineLintRules.push(indentationMultiple)
if (!isNaN(json?.indentationMultiple)) {
this.indentationMultiple = json.indentationMultiple as number
this.lineLintRules.push(indentationMultiple)
}

if (json?.hasDoxygenHeader) {
if (json?.hasDoxygenHeader !== false) {
this.fileLintRules.push(hasDoxygenHeader)
}

if (json?.defaultHeader) {
this.defaultHeader = json.defaultHeader
}

if (json?.noSpacesInFileNames) {
if (json?.noSpacesInFileNames !== false) {
this.pathLintRules.push(noSpacesInFileNames)
}

if (json?.lowerCaseFileNames) {
if (json?.lowerCaseFileNames !== false) {
this.pathLintRules.push(lowerCaseFileNames)
}

if (json?.hasMacroNameInMend) {
this.fileLintRules.push(hasMacroNameInMend)
}

if (json?.noNestedMacros) {
if (json?.noNestedMacros !== false) {
this.fileLintRules.push(noNestedMacros)
}

if (json?.hasMacroParentheses) {
if (json?.hasMacroParentheses !== false) {
this.fileLintRules.push(hasMacroParentheses)
}

if (json?.strictMacroDefinition) {
if (json?.strictMacroDefinition !== false) {
this.fileLintRules.push(strictMacroDefinition)
}

if (json?.noGremlins) {
if (json?.noGremlins !== false) {
this.lineLintRules.push(noGremlins)
}

Expand Down
Loading

0 comments on commit f59fd4c

Please sign in to comment.