diff --git a/.sasjslint b/.sasjslint index 73e6a81..44e07e4 100644 --- a/.sasjslint +++ b/.sasjslint @@ -2,5 +2,9 @@ "noTrailingSpaces": true, "noEncodedPasswords": true, "hasDoxygenHeader": true, - "noSpacesInFileNames": true + "noSpacesInFileNames": true, + "maxLineLength": 80, + "lowerCaseFileNames": true, + "noTabIndentation": true, + "indentationMultiple": 2 } \ No newline at end of file diff --git a/sasjslint-schema.json b/sasjslint-schema.json index c7e519a..9af64c8 100644 --- a/sasjslint-schema.json +++ b/sasjslint-schema.json @@ -8,14 +8,22 @@ "noTrailingSpaces": true, "noEncodedPasswords": true, "hasDoxygenHeader": true, - "noSpacesInFileNames": true + "noSpacesInFileNames": true, + "lowerCaseFileNames": true, + "maxLineLength": 80, + "noTabIndentation": true, + "indentationMultiple": 2 }, "examples": [ { "noTrailingSpaces": true, "noEncodedPasswords": true, "hasDoxygenHeader": true, - "noSpacesInFileNames": true + "noSpacesInFileNames": true, + "lowerCaseFileNames": true, + "maxLineLength": 80, + "noTabIndentation": true, + "indentationMultiple": 4 } ], "properties": { @@ -50,6 +58,38 @@ "description": "Enforces no spaces in file names. Shows a warning when they are present.", "default": true, "examples": [true, false] + }, + "lowerCaseFileNames": { + "$id": "#/properties/lowerCaseFileNames", + "type": "boolean", + "title": "lowerCaseFileNames", + "description": "Enforces no uppercase characters in file names. Shows a warning when they are present.", + "default": true, + "examples": [true, false] + }, + "maxLineLength": { + "$id": "#/properties/maxLineLength", + "type": "number", + "title": "maxLineLength", + "description": "Enforces a configurable maximum line length. Shows a warning for lines exceeding this length.", + "default": 80, + "examples": [60, 80, 120] + }, + "noTabIndentation": { + "$id": "#/properties/noTabIndentation", + "type": "boolean", + "title": "noTabIndentation", + "description": "Enforces no indentation using tabs. Shows a warning when a line starts with a tab.", + "default": true, + "examples": [true, false] + }, + "indentationMultiple": { + "$id": "#/properties/indentationMultiple", + "type": "number", + "title": "indentationMultiple", + "description": "Enforces a configurable multiple for the number of spaces for indentation. Shows a warning for lines that are not indented by a multiple of this number.", + "default": 2, + "examples": [2, 3, 4] } } } diff --git a/src/Example File.sas b/src/Example File.sas new file mode 100644 index 0000000..4056077 --- /dev/null +++ b/src/Example File.sas @@ -0,0 +1,18 @@ + + +%macro mf_getuniquelibref(prefix=mclib,maxtries=1000); + %local x libref; + %let x={SAS002}; + %do x=0 %to &maxtries; + %if %sysfunc(libref(&prefix&x)) ne 0 %then %do; + %let libref=&prefix&x; + %let rc=%sysfunc(libname(&libref,%sysfunc(pathname(work)))); + %if &rc %then %put %sysfunc(sysmsg()); + &prefix&x + %*put &sysmacroname: Libref &libref assigned as WORK and returned; + %return; + %end; + %end; + %put unable to find available libref in range &prefix.0-&maxtries; + %mend; + diff --git a/src/example file.sas b/src/example file.sas deleted file mode 100644 index 3ff3243..0000000 --- a/src/example file.sas +++ /dev/null @@ -1,17 +0,0 @@ - - - %macro mf_getuniquelibref(prefix=mclib,maxtries=1000); - %local x libref; - %let x={SAS002}; - %do x=0 %to &maxtries; - %if %sysfunc(libref(&prefix&x)) ne 0 %then %do; - %let libref=&prefix&x; - %let rc=%sysfunc(libname(&libref,%sysfunc(pathname(work)))); - %if &rc %then %put %sysfunc(sysmsg()); - &prefix&x - %*put &sysmacroname: Libref &libref assigned as WORK and returned; - %return; - %end; - %end; - %put unable to find available libref in range &prefix.0-&maxtries; - %mend; \ No newline at end of file diff --git a/src/example.ts b/src/example.ts index 22a9a14..bae4de8 100644 --- a/src/example.ts +++ b/src/example.ts @@ -1,49 +1,58 @@ -import { lintText } from './lint' +import { lintFile, lintText } from './lint' +import path from 'path' /** * Example which tests a piece of text with all known violations. */ const text = `/** - @file - @brief Returns an unused libref - @details Use as follows: + @file + @brief Returns an unused libref + @details Use as follows: - libname mclib0 (work); - libname mclib1 (work); - libname mclib2 (work); + libname mclib0 (work); + libname mclib1 (work); + libname mclib2 (work); - %let libref=%mf_getuniquelibref({SAS001}); - %put &=libref; + %let libref=%mf_getuniquelibref({SAS001}); + %put &=libref; - which returns: + which returns: > mclib3 - @param prefix= first part of libref. Remember that librefs can only be 8 characters, - so a 7 letter prefix would mean that maxtries should be 10. - @param maxtries= the last part of the libref. Provide an integer value. + @param prefix= first part of libref. Remember that librefs can only be 8 characters, + so a 7 letter prefix would mean that maxtries should be 10. + @param maxtries= the last part of the libref. Provide an integer value. - @version 9.2 - @author Allan Bowe + @version 9.2 + @author Allan Bowe **/ - %macro mf_getuniquelibref(prefix=mclib,maxtries=1000); - %local x libref; - %let x={SAS002}; +%macro mf_getuniquelibref(prefix=mclib,maxtries=1000); + %local x libref; + %let x={SAS002}; %do x=0 %to &maxtries; - %if %sysfunc(libref(&prefix&x)) ne 0 %then %do; - %let libref=&prefix&x; - %let rc=%sysfunc(libname(&libref,%sysfunc(pathname(work)))); - %if &rc %then %put %sysfunc(sysmsg()); - &prefix&x - %*put &sysmacroname: Libref &libref assigned as WORK and returned; - %return; - %end; - %end; - %put unable to find available libref in range &prefix.0-&maxtries; - %mend; + %if %sysfunc(libref(&prefix&x)) ne 0 %then %do; + %let libref=&prefix&x; + %let rc=%sysfunc(libname(&libref,%sysfunc(pathname(work)))); + %if &rc %then %put %sysfunc(sysmsg()); + &prefix&x + %*put &sysmacroname: Libref &libref assigned as WORK and returned; + %return; + %end; + %end; + %put unable to find available libref in range &prefix.0-&maxtries; + %mend; ` -lintText(text).then((diagnostics) => console.table(diagnostics)) +lintText(text).then((diagnostics) => { + console.log('Text lint results:') + console.table(diagnostics) +}) + +lintFile(path.join(__dirname, 'Example File.sas')).then((diagnostics) => { + console.log('File lint results:') + console.table(diagnostics) +}) diff --git a/src/index.ts b/src/index.ts index b7c0c5c..a45d40e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,2 +1,3 @@ export { lintText, lintFile } from './lint' export * from './types' +export * from './utils' diff --git a/src/lint.spec.ts b/src/lint.spec.ts index 9b6f5e2..d6d5e21 100644 --- a/src/lint.spec.ts +++ b/src/lint.spec.ts @@ -71,9 +71,9 @@ describe('lintText', () => { describe('lintFile', () => { it('should identify lint issues in a given file', async () => { - const results = await lintFile(path.join(__dirname, 'example file.sas')) + const results = await lintFile(path.join(__dirname, 'Example File.sas')) - expect(results.length).toEqual(5) + expect(results.length).toEqual(8) expect(results).toContainEqual({ message: 'Line contains trailing spaces', lineNumber: 1, @@ -95,6 +95,13 @@ describe('lintFile', () => { endColumnNumber: 1, severity: Severity.Warning }) + expect(results).toContainEqual({ + message: 'File name contains uppercase characters', + lineNumber: 1, + startColumnNumber: 1, + endColumnNumber: 1, + severity: Severity.Warning + }) expect(results).toContainEqual({ message: 'File missing Doxygen header', lineNumber: 1, @@ -105,10 +112,24 @@ describe('lintFile', () => { expect(results).toContainEqual({ message: 'Line contains encoded password', lineNumber: 5, - startColumnNumber: 11, - endColumnNumber: 19, + startColumnNumber: 10, + endColumnNumber: 18, severity: Severity.Error }) + expect(results).toContainEqual({ + message: 'Line is indented with a tab', + lineNumber: 7, + startColumnNumber: 1, + endColumnNumber: 1, + severity: Severity.Warning + }) + expect(results).toContainEqual({ + message: 'Line has incorrect indentation - 3 spaces', + lineNumber: 6, + startColumnNumber: 1, + endColumnNumber: 1, + severity: Severity.Warning + }) }) }) diff --git a/src/lint.ts b/src/lint.ts index 5070def..8aba8df 100644 --- a/src/lint.ts +++ b/src/lint.ts @@ -65,7 +65,7 @@ const processLine = ( ): Diagnostic[] => { const diagnostics: Diagnostic[] = [] config.lineLintRules.forEach((rule) => { - diagnostics.push(...rule.test(line, lineNumber)) + diagnostics.push(...rule.test(line, lineNumber, config)) }) return diagnostics diff --git a/src/rules/indentationMultiple.spec.ts b/src/rules/indentationMultiple.spec.ts new file mode 100644 index 0000000..b5a84e0 --- /dev/null +++ b/src/rules/indentationMultiple.spec.ts @@ -0,0 +1,74 @@ +import { LintConfig, Severity } from '../types' +import { indentationMultiple } from './indentationMultiple' + +describe('indentationMultiple', () => { + it('should return an empty array when the line is indented by two spaces', () => { + const line = " %put 'hello';" + const config = new LintConfig({ indentationMultiple: 2 }) + expect(indentationMultiple.test(line, 1, config)).toEqual([]) + }) + + it('should return an empty array when the line is indented by a multiple of 2 spaces', () => { + const line = " %put 'hello';" + const config = new LintConfig({ indentationMultiple: 2 }) + expect(indentationMultiple.test(line, 1, config)).toEqual([]) + }) + + it('should ignore indentation when the multiple is set to 0', () => { + const line = " %put 'hello';" + const config = new LintConfig({ indentationMultiple: 0 }) + expect(indentationMultiple.test(line, 1, config)).toEqual([]) + }) + + it('should return an empty array when the line is not indented', () => { + const line = "%put 'hello';" + const config = new LintConfig({ indentationMultiple: 2 }) + expect(indentationMultiple.test(line, 1, config)).toEqual([]) + }) + + it('should return an array with a single diagnostic when the line is indented incorrectly', () => { + const line = " %put 'hello';" + const config = new LintConfig({ indentationMultiple: 2 }) + expect(indentationMultiple.test(line, 1, config)).toEqual([ + { + message: `Line has incorrect indentation - 3 spaces`, + lineNumber: 1, + startColumnNumber: 1, + endColumnNumber: 1, + severity: Severity.Warning + } + ]) + }) + + it('should return an array with a single diagnostic when the line is indented incorrectly', () => { + const line = " %put 'hello';" + const config = new LintConfig({ indentationMultiple: 3 }) + expect(indentationMultiple.test(line, 1, config)).toEqual([ + { + message: `Line has incorrect indentation - 2 spaces`, + lineNumber: 1, + startColumnNumber: 1, + endColumnNumber: 1, + severity: Severity.Warning + } + ]) + }) + + it('should fall back to a default of 2 spaces', () => { + const line = " %put 'hello';" + expect(indentationMultiple.test(line, 1)).toEqual([ + { + message: `Line has incorrect indentation - 1 space`, + lineNumber: 1, + startColumnNumber: 1, + endColumnNumber: 1, + severity: Severity.Warning + } + ]) + }) + + it('should return an empty array for lines within the default indentation', () => { + const line = " %put 'hello';" + expect(indentationMultiple.test(line, 1)).toEqual([]) + }) +}) diff --git a/src/rules/indentationMultiple.ts b/src/rules/indentationMultiple.ts new file mode 100644 index 0000000..b0a3874 --- /dev/null +++ b/src/rules/indentationMultiple.ts @@ -0,0 +1,41 @@ +import { LintConfig } from '../types' +import { LineLintRule } from '../types/LintRule' +import { LintRuleType } from '../types/LintRuleType' +import { Severity } from '../types/Severity' + +const name = 'indentationMultiple' +const description = 'Ensure indentation by a multiple of the configured number.' +const message = 'Line has incorrect indentation' +const test = (value: string, lineNumber: number, config?: LintConfig) => { + if (!value.startsWith(' ')) return [] + + const indentationMultiple = isNaN(config?.indentationMultiple as number) + ? 2 + : config?.indentationMultiple + + if (indentationMultiple === 0) return [] + const numberOfSpaces = value.search(/\S|$/) + if (numberOfSpaces % indentationMultiple! === 0) return [] + return [ + { + message: `${message} - ${numberOfSpaces} ${ + numberOfSpaces === 1 ? 'space' : 'spaces' + }`, + lineNumber, + startColumnNumber: 1, + endColumnNumber: 1, + severity: Severity.Warning + } + ] +} + +/** + * Lint rule that checks if a line is indented by a multiple of the configured indentation multiple. + */ +export const indentationMultiple: LineLintRule = { + type: LintRuleType.Line, + name, + description, + message, + test +} diff --git a/src/rules/lowerCaseFileNames.spec.ts b/src/rules/lowerCaseFileNames.spec.ts new file mode 100644 index 0000000..4ecaddb --- /dev/null +++ b/src/rules/lowerCaseFileNames.spec.ts @@ -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 + } + ]) + }) +}) diff --git a/src/rules/lowerCaseFileNames.ts b/src/rules/lowerCaseFileNames.ts new file mode 100644 index 0000000..2eb8e51 --- /dev/null +++ b/src/rules/lowerCaseFileNames.ts @@ -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 +} diff --git a/src/rules/maxLineLength.spec.ts b/src/rules/maxLineLength.spec.ts new file mode 100644 index 0000000..c763d26 --- /dev/null +++ b/src/rules/maxLineLength.spec.ts @@ -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([]) + }) +}) diff --git a/src/rules/maxLineLength.ts b/src/rules/maxLineLength.ts new file mode 100644 index 0000000..8d054c7 --- /dev/null +++ b/src/rules/maxLineLength.ts @@ -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 +} diff --git a/src/rules/noSpacesInFileNames.ts b/src/rules/noSpacesInFileNames.ts index cf9eb46..6723ea3 100644 --- a/src/rules/noSpacesInFileNames.ts +++ b/src/rules/noSpacesInFileNames.ts @@ -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.' diff --git a/src/rules/noTabIndentation.spec.ts b/src/rules/noTabIndentation.spec.ts new file mode 100644 index 0000000..ea300a8 --- /dev/null +++ b/src/rules/noTabIndentation.spec.ts @@ -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 + } + ]) + }) +}) diff --git a/src/rules/noTabIndentation.ts b/src/rules/noTabIndentation.ts new file mode 100644 index 0000000..af2a46b --- /dev/null +++ b/src/rules/noTabIndentation.ts @@ -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 +} diff --git a/src/types/LintConfig.spec.ts b/src/types/LintConfig.spec.ts index 2b4b1b1..e11cd83 100644 --- a/src/types/LintConfig.spec.ts +++ b/src/types/LintConfig.spec.ts @@ -40,6 +40,20 @@ describe('LintConfig', () => { expect(config.fileLintRules[0].type).toEqual(LintRuleType.File) }) + it('should create an instance with the indentation multiple set', () => { + const config = new LintConfig({ indentationMultiple: 5 }) + + expect(config).toBeTruthy() + expect(config.indentationMultiple).toEqual(5) + }) + + it('should create an instance with the indentation multiple turned off', () => { + const config = new LintConfig({ indentationMultiple: 0 }) + + expect(config).toBeTruthy() + expect(config.indentationMultiple).toEqual(0) + }) + it('should create an instance with all flags set', () => { const config = new LintConfig({ noTrailingSpaces: true, diff --git a/src/types/LintConfig.ts b/src/types/LintConfig.ts index ab65991..184202e 100644 --- a/src/types/LintConfig.ts +++ b/src/types/LintConfig.ts @@ -1,6 +1,10 @@ import { hasDoxygenHeader } from '../rules/hasDoxygenHeader' +import { indentationMultiple } from '../rules/indentationMultiple' +import { lowerCaseFileNames } from '../rules/lowerCaseFileNames' +import { maxLineLength } from '../rules/maxLineLength' import { noEncodedPasswords } from '../rules/noEncodedPasswords' import { noSpacesInFileNames } from '../rules/noSpacesInFileNames' +import { noTabIndentation } from '../rules/noTabIndentation' import { noTrailingSpaces } from '../rules/noTrailingSpaces' import { FileLintRule, LineLintRule, PathLintRule } from './LintRule' @@ -15,6 +19,8 @@ export class LintConfig { readonly lineLintRules: LineLintRule[] = [] readonly fileLintRules: FileLintRule[] = [] readonly pathLintRules: PathLintRule[] = [] + readonly maxLineLength: number = 80 + readonly indentationMultiple: number = 2 constructor(json?: any) { if (json?.noTrailingSpaces) { @@ -25,6 +31,20 @@ export class LintConfig { this.lineLintRules.push(noEncodedPasswords) } + if (json?.noTabIndentation) { + this.lineLintRules.push(noTabIndentation) + } + + if (json?.maxLineLength) { + this.maxLineLength = json.maxLineLength + this.lineLintRules.push(maxLineLength) + } + + if (!isNaN(json?.indentationMultiple)) { + this.indentationMultiple = json.indentationMultiple as number + this.lineLintRules.push(indentationMultiple) + } + if (json?.hasDoxygenHeader) { this.fileLintRules.push(hasDoxygenHeader) } @@ -32,5 +52,9 @@ export class LintConfig { if (json?.noSpacesInFileNames) { this.pathLintRules.push(noSpacesInFileNames) } + + if (json?.lowerCaseFileNames) { + this.pathLintRules.push(lowerCaseFileNames) + } } } diff --git a/src/types/LintRule.ts b/src/types/LintRule.ts index bb2bcb0..d3fbf29 100644 --- a/src/types/LintRule.ts +++ b/src/types/LintRule.ts @@ -1,4 +1,5 @@ import { Diagnostic } from './Diagnostic' +import { LintConfig } from './LintConfig' import { LintRuleType } from './LintRuleType' /** @@ -17,7 +18,7 @@ export interface LintRule { */ export interface LineLintRule extends LintRule { type: LintRuleType.Line - test: (value: string, lineNumber: number) => Diagnostic[] + test: (value: string, lineNumber: number, config?: LintConfig) => Diagnostic[] } /** diff --git a/src/utils/getLintConfig.spec.ts b/src/utils/getLintConfig.spec.ts index d5136d4..e7e4870 100644 --- a/src/utils/getLintConfig.spec.ts +++ b/src/utils/getLintConfig.spec.ts @@ -18,6 +18,7 @@ describe('getLintConfig', () => { expect(config).toBeInstanceOf(LintConfig) expect(config.fileLintRules.length).toEqual(1) - expect(config.lineLintRules.length).toEqual(2) + expect(config.lineLintRules.length).toEqual(5) + expect(config.pathLintRules.length).toEqual(2) }) }) diff --git a/src/utils/getLintConfig.ts b/src/utils/getLintConfig.ts index 97178cf..c90b15d 100644 --- a/src/utils/getLintConfig.ts +++ b/src/utils/getLintConfig.ts @@ -3,11 +3,20 @@ import { LintConfig } from '../types/LintConfig' import { readFile } from '@sasjs/utils/file' import { getProjectRoot } from './getProjectRoot' -const defaultConfiguration = { +/** + * Default configuration that is used when a .sasjslint file is not found + */ +export const DefaultLintConfiguration = { noTrailingSpaces: true, noEncodedPasswords: true, - hasDoxygenHeader: true + hasDoxygenHeader: true, + noSpacesInFileNames: true, + lowerCaseFileNames: true, + maxLineLength: 80, + noTabIndentation: true, + indentationMultiple: 2 } + /** * Fetches the config from the .sasjslint file and creates a LintConfig object. * Returns the default configuration when a .sasjslint file is unavailable. @@ -19,7 +28,7 @@ export async function getLintConfig(): Promise { path.join(projectRoot, '.sasjslint') ).catch((_) => { console.warn('Unable to load .sasjslint file. Using default configuration.') - return JSON.stringify(defaultConfiguration) + return JSON.stringify(DefaultLintConfiguration) }) return new LintConfig(JSON.parse(configuration)) } diff --git a/src/utils/index.ts b/src/utils/index.ts new file mode 100644 index 0000000..4bb8061 --- /dev/null +++ b/src/utils/index.ts @@ -0,0 +1,2 @@ +export * from './getLintConfig' +export * from './getProjectRoot'