-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from sasjs/add-lint-rules
- Loading branch information
Showing
23 changed files
with
490 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
|
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export { lintText, lintFile } from './lint' | ||
export * from './types' | ||
export * from './utils' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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([]) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
Oops, something went wrong.