diff --git a/src/rules/file/hasDoxygenHeader.spec.ts b/src/rules/file/hasDoxygenHeader.spec.ts index e29c59c..23af9c6 100644 --- a/src/rules/file/hasDoxygenHeader.spec.ts +++ b/src/rules/file/hasDoxygenHeader.spec.ts @@ -17,6 +17,32 @@ describe('hasDoxygenHeader - test', () => { expect(hasDoxygenHeader.test(content)).toEqual([]) }) + 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([ + { + message: + 'File not following Doxygen header style, use double asterisks', + lineNumber: 4, + startColumnNumber: 1, + endColumnNumber: 1, + severity: Severity.Warning + } + ]) + }) + it('should return an array with a single diagnostic when the file has no header', () => { const content = ` %macro mf_getuniquelibref(prefix=mclib,maxtries=1000); @@ -86,7 +112,33 @@ describe('hasDoxygenHeader - fix', () => { expect(hasDoxygenHeader.fix!(content)).toEqual(content) }) - it('should should add a doxygen header if not present', () => { + it('should update single asterisks to double if a doxygen header is already present', () => { + const contentOriginal = ` + /* + @file + @brief Returns an unused libref + */ + + %macro mf_getuniquelibref(prefix=mclib,maxtries=1000); + %local x libref; + %let x={SAS002}; + %do x=0 %to &maxtries;` + + const contentExpected = ` + /** + @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.fix!(contentOriginal)).toEqual(contentExpected) + }) + + it('should add a doxygen header if not present', () => { const content = `%macro mf_getuniquelibref(prefix=mclib,maxtries=1000); %local x libref; %let x={SAS002}; diff --git a/src/rules/file/hasDoxygenHeader.ts b/src/rules/file/hasDoxygenHeader.ts index 2a5c75b..2a81d55 100644 --- a/src/rules/file/hasDoxygenHeader.ts +++ b/src/rules/file/hasDoxygenHeader.ts @@ -10,10 +10,28 @@ const name = 'hasDoxygenHeader' const description = 'Enforce the presence of a Doxygen header at the start of each file.' const message = 'File missing Doxygen header' -const test = (value: string) => { +const messageForSingleAsterisk = + 'File not following Doxygen header style, use double asterisks' +const test = (value: string, config?: LintConfig) => { + const lineEnding = config?.lineEndings === LineEndings.CRLF ? '\r\n' : '\n' try { - const hasFileHeader = value.trimStart().startsWith('/*') + const hasFileHeader = value.trimStart().startsWith('/**') if (hasFileHeader) return [] + + const hasFileHeaderWithSingleAsterisk = value.trimStart().startsWith('/*') + if (hasFileHeaderWithSingleAsterisk) + return [ + { + message: messageForSingleAsterisk, + lineNumber: + (value.split('/*')![0]!.match(new RegExp(lineEnding, 'g')) ?? []) + .length + 1, + startColumnNumber: 1, + endColumnNumber: 1, + severity: Severity.Warning + } + ] + return [ { message, @@ -37,9 +55,12 @@ const test = (value: string) => { } const fix = (value: string, config?: LintConfig): string => { - if (test(value).length === 0) { + const result = test(value, config) + if (result.length === 0) { return value - } + } else if (result[0].message == messageForSingleAsterisk) + return value.replace('/*', '/**') + const lineEndingConfig = config?.lineEndings || LineEndings.LF const lineEnding = lineEndingConfig === LineEndings.LF ? '\n' : '\r\n'