mirror of
https://github.com/sasjs/lint.git
synced 2026-01-10 14:00:05 +00:00
Merge pull request #179 from sasjs/issue-178
feat: customise the defaultHeader
This commit is contained in:
35
README.md
35
README.md
@@ -33,12 +33,33 @@ Configuration is via a `.sasjslint` file with the following structure (these are
|
|||||||
"noNestedMacros": true,
|
"noNestedMacros": true,
|
||||||
"noSpacesInFileNames": true,
|
"noSpacesInFileNames": true,
|
||||||
"noTabIndentation": true,
|
"noTabIndentation": true,
|
||||||
"noTrailingSpaces": true
|
"noTrailingSpaces": true,
|
||||||
|
"defaultHeader": "/**{lineEnding} @file{lineEnding} @brief <Your brief here>{lineEnding} <h4> SAS Macros </h4>{lineEnding}**/"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### SAS Lint Settings
|
### SAS Lint Settings
|
||||||
|
|
||||||
|
#### defaultHeader
|
||||||
|
|
||||||
|
This sets the default program header - applies when a SAS program does NOT begin with `/**`. The default header is as follows:
|
||||||
|
|
||||||
|
```sas
|
||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief <Your brief here>
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
**/
|
||||||
|
```
|
||||||
|
|
||||||
|
The default header is automatically applied when running `sasjs lint fix` in the SASjs CLI, or by hitting "save" when using the SASjs VS Code extension. If creating a new value, use `{lineEnding}` instead of `\n`, eg as follows:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"defaultHeader": "/**{lineEnding} @file{lineEnding} @brief Our Company Brief{lineEnding}**/"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
#### noEncodedPasswords
|
#### noEncodedPasswords
|
||||||
|
|
||||||
This will highlight any rows that contain a `{sas00X}` type password, or `{sasenc}`. These passwords (especially 001 and 002) are NOT secure, and should NEVER be pushed to source control or saved to the filesystem without special permissions applied.
|
This will highlight any rows that contain a `{sas00X}` type password, or `{sasenc}`. These passwords (especially 001 and 002) are NOT secure, and should NEVER be pushed to source control or saved to the filesystem without special permissions applied.
|
||||||
@@ -82,7 +103,7 @@ On *nix systems, it is imperative that autocall macros are in lowercase. When s
|
|||||||
#### maxLineLength
|
#### maxLineLength
|
||||||
Code becomes far more readable when line lengths are short. The most compelling reason for short line lengths is to avoid the need to scroll when performing a side-by-side 'compare' between two files (eg as part of a GIT feature branch review). A longer discussion on optimal code line length can be found [here](https://stackoverflow.com/questions/578059/studies-on-optimal-code-width)
|
Code becomes far more readable when line lengths are short. The most compelling reason for short line lengths is to avoid the need to scroll when performing a side-by-side 'compare' between two files (eg as part of a GIT feature branch review). A longer discussion on optimal code line length can be found [here](https://stackoverflow.com/questions/578059/studies-on-optimal-code-width)
|
||||||
|
|
||||||
In batch mode, long SAS code lines may also be truncated, causing hard-to-detect errors.
|
In batch mode, long SAS code lines may also be truncated, causing hard-to-detect errors.
|
||||||
|
|
||||||
We strongly recommend a line length limit, and set the bar at 80. To turn this feature off, set the value to 0.
|
We strongly recommend a line length limit, and set the bar at 80. To turn this feature off, set the value to 0.
|
||||||
|
|
||||||
@@ -90,7 +111,7 @@ We strongly recommend a line length limit, and set the bar at 80. To turn this
|
|||||||
* Severity: WARNING
|
* Severity: WARNING
|
||||||
|
|
||||||
#### noNestedMacros
|
#### noNestedMacros
|
||||||
Where macros are defined inside other macros, they are recompiled every time the outer macro is invoked. Hence, it is widely considered inefficient, and bad practice, to nest macro definitions.
|
Where macros are defined inside other macros, they are recompiled every time the outer macro is invoked. Hence, it is widely considered inefficient, and bad practice, to nest macro definitions.
|
||||||
|
|
||||||
* Default: true
|
* Default: true
|
||||||
* Severity: WARNING
|
* Severity: WARNING
|
||||||
@@ -120,7 +141,7 @@ This will highlight lines with trailing spaces. Trailing spaces serve no useful
|
|||||||
|
|
||||||
### Upcoming Linting Rules:
|
### Upcoming Linting Rules:
|
||||||
|
|
||||||
* `noTabs` -> does what it says on the tin
|
* `noTabs` -> does what it says on the tin
|
||||||
* `noGremlins` -> identifies all invisible characters, other than spaces / tabs / line endings. If you really need that bell character, use a hex literal!
|
* `noGremlins` -> identifies all invisible characters, other than spaces / tabs / line endings. If you really need that bell character, use a hex literal!
|
||||||
* `lineEndings` -> set a standard line ending, such as LF or CRLF
|
* `lineEndings` -> set a standard line ending, such as LF or CRLF
|
||||||
|
|
||||||
@@ -130,13 +151,13 @@ A formatter will automatically apply rules when you hit SAVE, which can save a L
|
|||||||
|
|
||||||
We've already implemented the following rules:
|
We've already implemented the following rules:
|
||||||
|
|
||||||
* Add the macro name to the %mend statement
|
* Add the macro name to the %mend statement
|
||||||
* Add a doxygen header template if none exists
|
* Add a doxygen header template if none exists
|
||||||
* Remove trailing spaces
|
* Remove trailing spaces
|
||||||
|
|
||||||
We're looking to implement the following rules:
|
We're looking to implement the following rules:
|
||||||
|
|
||||||
* Change tabs to spaces
|
* Change tabs to spaces
|
||||||
* zap gremlins
|
* zap gremlins
|
||||||
* fix line endings
|
* fix line endings
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const processContent = (config: LintConfig, content: string): string => {
|
|||||||
config.fileLintRules
|
config.fileLintRules
|
||||||
.filter((r) => !!r.fix)
|
.filter((r) => !!r.fix)
|
||||||
.forEach((rule) => {
|
.forEach((rule) => {
|
||||||
processedContent = rule.fix!(processedContent)
|
processedContent = rule.fix!(processedContent, config)
|
||||||
})
|
})
|
||||||
|
|
||||||
return processedContent
|
return processedContent
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ import { LineEndings } from '../../types/LineEndings'
|
|||||||
import { FileLintRule } from '../../types/LintRule'
|
import { FileLintRule } from '../../types/LintRule'
|
||||||
import { LintRuleType } from '../../types/LintRuleType'
|
import { LintRuleType } from '../../types/LintRuleType'
|
||||||
import { Severity } from '../../types/Severity'
|
import { Severity } from '../../types/Severity'
|
||||||
|
import { DefaultLintConfiguration } from '../../utils/getLintConfig'
|
||||||
const DoxygenHeader = `/**{lineEnding} @file{lineEnding} @brief <Your brief here>{lineEnding} <h4> SAS Macros </h4>{lineEnding}**/`
|
|
||||||
|
|
||||||
const name = 'hasDoxygenHeader'
|
const name = 'hasDoxygenHeader'
|
||||||
const description =
|
const description =
|
||||||
@@ -61,10 +60,11 @@ const fix = (value: string, config?: LintConfig): string => {
|
|||||||
} else if (result[0].message == messageForSingleAsterisk)
|
} else if (result[0].message == messageForSingleAsterisk)
|
||||||
return value.replace('/*', '/**')
|
return value.replace('/*', '/**')
|
||||||
|
|
||||||
|
config = config || new LintConfig(DefaultLintConfiguration)
|
||||||
const lineEndingConfig = config?.lineEndings || LineEndings.LF
|
const lineEndingConfig = config?.lineEndings || LineEndings.LF
|
||||||
const lineEnding = lineEndingConfig === LineEndings.LF ? '\n' : '\r\n'
|
const lineEnding = lineEndingConfig === LineEndings.LF ? '\n' : '\r\n'
|
||||||
|
|
||||||
return `${DoxygenHeader.replace(
|
return `${config?.defaultHeader.replace(
|
||||||
/{lineEnding}/g,
|
/{lineEnding}/g,
|
||||||
lineEnding
|
lineEnding
|
||||||
)}${lineEnding}${value}`
|
)}${lineEnding}${value}`
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
import { lowerCaseFileNames, noSpacesInFileNames } from '../rules/path'
|
import { lowerCaseFileNames, noSpacesInFileNames } from '../rules/path'
|
||||||
import { LineEndings } from './LineEndings'
|
import { LineEndings } from './LineEndings'
|
||||||
import { FileLintRule, LineLintRule, PathLintRule } from './LintRule'
|
import { FileLintRule, LineLintRule, PathLintRule } from './LintRule'
|
||||||
|
import { getDefaultHeader } from '../utils'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LintConfig is the logical representation of the .sasjslint file.
|
* LintConfig is the logical representation of the .sasjslint file.
|
||||||
@@ -32,6 +33,7 @@ export class LintConfig {
|
|||||||
readonly maxLineLength: number = 80
|
readonly maxLineLength: number = 80
|
||||||
readonly indentationMultiple: number = 2
|
readonly indentationMultiple: number = 2
|
||||||
readonly lineEndings: LineEndings = LineEndings.LF
|
readonly lineEndings: LineEndings = LineEndings.LF
|
||||||
|
readonly defaultHeader: string = getDefaultHeader()
|
||||||
|
|
||||||
constructor(json?: any) {
|
constructor(json?: any) {
|
||||||
if (json?.ignoreList) {
|
if (json?.ignoreList) {
|
||||||
@@ -87,6 +89,10 @@ export class LintConfig {
|
|||||||
this.fileLintRules.push(hasDoxygenHeader)
|
this.fileLintRules.push(hasDoxygenHeader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (json?.defaultHeader) {
|
||||||
|
this.defaultHeader = json.defaultHeader
|
||||||
|
}
|
||||||
|
|
||||||
if (json?.noSpacesInFileNames) {
|
if (json?.noSpacesInFileNames) {
|
||||||
this.pathLintRules.push(noSpacesInFileNames)
|
this.pathLintRules.push(noSpacesInFileNames)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,9 @@ import { LintConfig } from '../types/LintConfig'
|
|||||||
import { readFile } from '@sasjs/utils/file'
|
import { readFile } from '@sasjs/utils/file'
|
||||||
import { getProjectRoot } from './getProjectRoot'
|
import { getProjectRoot } from './getProjectRoot'
|
||||||
|
|
||||||
|
export const getDefaultHeader = () =>
|
||||||
|
`/**{lineEnding} @file{lineEnding} @brief <Your brief here>{lineEnding} <h4> SAS Macros </h4>{lineEnding}**/`
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default configuration that is used when a .sasjslint file is not found
|
* Default configuration that is used when a .sasjslint file is not found
|
||||||
*/
|
*/
|
||||||
@@ -18,7 +21,8 @@ export const DefaultLintConfiguration = {
|
|||||||
hasMacroNameInMend: true,
|
hasMacroNameInMend: true,
|
||||||
noNestedMacros: true,
|
noNestedMacros: true,
|
||||||
hasMacroParentheses: true,
|
hasMacroParentheses: true,
|
||||||
strictMacroDefinition: true
|
strictMacroDefinition: true,
|
||||||
|
defaultHeader: getDefaultHeader()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user