diff --git a/sasjslint-schema.json b/sasjslint-schema.json index e04e84f..11734f2 100644 --- a/sasjslint-schema.json +++ b/sasjslint-schema.json @@ -31,6 +31,7 @@ "lowerCaseFileNames": true, "maxLineLength": 80, "noGremlins": true, + "allowedGremlins": ["0x0080", "0x3000"], "noTabs": true, "indentationMultiple": 4, "hasMacroNameInMend": true, @@ -74,6 +75,18 @@ "default": [true], "examples": [true, false] }, + "allowedGremlins": { + "$id": "#/properties/allowedGremlins", + "type": "array", + "items": { + "type": "string", + "pattern": "^0x[0-9A-Fa-f]{4}$" + }, + "title": "allowedGremlins", + "description": "An array of hex codes that represents allowed gremlins.", + "default": [], + "examples": ["0x0080", "0x3000"] + }, "hasMacroNameInMend": { "$id": "#/properties/hasMacroNameInMend", "type": "boolean", diff --git a/src/rules/line/noGremlins.spec.ts b/src/rules/line/noGremlins.spec.ts index 6f60703..a439a6b 100644 --- a/src/rules/line/noGremlins.spec.ts +++ b/src/rules/line/noGremlins.spec.ts @@ -1,5 +1,5 @@ -import { Severity } from '../../types/Severity' -import { noGremlins } from './noGremlins' +import { noGremlins, charFromHex } from './noGremlins' +import { LintConfig } from '../../types' describe('noTabs', () => { it('should return an empty array when the line does not have any gremlin', () => { @@ -8,8 +8,19 @@ describe('noTabs', () => { }) it('should return a diagnostic array when the line contains gremlins', () => { - const line = "– ‘ %put 'hello';" + const line = `${charFromHex('0x0080')} ${charFromHex( + '0x3000' + )} %put 'hello';` const diagnostics = noGremlins.test(line, 1) expect(diagnostics.length).toEqual(2) }) + + it('should return an empty array when the line contains gremlins but those gremlins are allowed', () => { + const config = new LintConfig({ allowedGremlins: ['0x0080', '0x3000'] }) + const line = `${charFromHex('0x0080')} ${charFromHex( + '0x3000' + )} %put 'hello';` + const diagnostics = noGremlins.test(line, 1, config) + expect(diagnostics.length).toEqual(0) + }) }) diff --git a/src/rules/line/noGremlins.ts b/src/rules/line/noGremlins.ts index ee1e4bc..c640cbe 100644 --- a/src/rules/line/noGremlins.ts +++ b/src/rules/line/noGremlins.ts @@ -10,15 +10,18 @@ const message = 'Line contains a gremlin' const test = (value: string, lineNumber: number, config?: LintConfig) => { const severity = config?.severityLevel[name] || Severity.Warning + const allowedGremlins = config?.allowedGremlins || [] const diagnostics: Diagnostic[] = [] const gremlins: any = {} - for (const [hexCode, config] of Object.entries(gremlinCharacters)) { - gremlins[charFromHex(hexCode)] = Object.assign({}, config, { - hexCode - }) + for (const [hexCode, gremlinConfig] of Object.entries(gremlinCharacters)) { + if (!allowedGremlins.includes(hexCode)) { + gremlins[charFromHex(hexCode)] = Object.assign({}, gremlinConfig, { + hexCode + }) + } } const regexpWithAllChars = new RegExp( @@ -56,4 +59,5 @@ export const noGremlins: LineLintRule = { test } -const charFromHex = (hexCode: string) => String.fromCodePoint(parseInt(hexCode)) +export const charFromHex = (hexCode: string) => + String.fromCodePoint(parseInt(hexCode)) diff --git a/src/types/LintConfig.ts b/src/types/LintConfig.ts index 4f0eb74..850f37e 100644 --- a/src/types/LintConfig.ts +++ b/src/types/LintConfig.ts @@ -29,6 +29,7 @@ import { Severity } from './Severity' */ export class LintConfig { readonly ignoreList: string[] = [] + readonly allowedGremlins: string[] = [] readonly lineLintRules: LineLintRule[] = [] readonly fileLintRules: FileLintRule[] = [] readonly pathLintRules: PathLintRule[] = [] @@ -123,6 +124,23 @@ export class LintConfig { if (json?.noGremlins !== false) { this.lineLintRules.push(noGremlins) + + if (json?.allowedGremlins) { + if (Array.isArray(json.allowedGremlins)) { + json.allowedGremlins.forEach((item: any) => { + if (typeof item === 'string' && /^0x[0-9a-f]{4}$/i.test(item)) + this.allowedGremlins.push(item) + else + throw new Error( + `Property "allowedGremlins" has invalid type of values. It can contain only strings of form hexcode like '["0x0080", "0x3000"]'` + ) + }) + } else { + throw new Error( + `Property "allowedGremlins" can only be an array of strings of form hexcode like '["0x0080", "0x3000"]'` + ) + } + } } if (json?.severityLevel) {