mirror of
https://github.com/sasjs/lint.git
synced 2026-01-05 03:30:06 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8badfd9358 | ||
| 0dfd1fb85b | |||
|
|
04cfa454f8 | ||
| 2cb73da0eb | |||
|
|
22cc42446c | ||
|
|
0fe79273e0 | ||
|
|
3d7f88aacb | ||
|
|
1677eca957 | ||
|
|
a1ebb51230 | ||
| 496e0bc8fc |
13
README.md
13
README.md
@@ -23,7 +23,7 @@ Configuration is via a `.sasjslint` file with the following structure (these are
|
|||||||
"hasDoxygenHeader": true,
|
"hasDoxygenHeader": true,
|
||||||
"hasMacroNameInMend": true,
|
"hasMacroNameInMend": true,
|
||||||
"hasMacroParentheses": true,
|
"hasMacroParentheses": true,
|
||||||
"ignoreList": ["sajsbuild/", "sasjsresults/"],
|
"ignoreList": ["sasjsbuild/", "sasjsresults/"],
|
||||||
"indentationMultiple": 2,
|
"indentationMultiple": 2,
|
||||||
"lineEndings": "off",
|
"lineEndings": "off",
|
||||||
"lowerCaseFileNames": true,
|
"lowerCaseFileNames": true,
|
||||||
@@ -49,9 +49,11 @@ Each setting can have three states:
|
|||||||
|
|
||||||
For more details, and the default state, see the description of each rule below. It is also possible to change whether a rule returns ERROR or WARN using the `severityLevels` object.
|
For more details, and the default state, see the description of each rule below. It is also possible to change whether a rule returns ERROR or WARN using the `severityLevels` object.
|
||||||
|
|
||||||
|
Configuring a non-zero return code (ERROR) is helpful when running `sasjs lint` as part of a git pre-commit hook. An example is available [here](https://github.com/sasjs/template_jobs/blob/main/.git-hooks/pre-commit).
|
||||||
|
|
||||||
### allowedGremlins
|
### allowedGremlins
|
||||||
|
|
||||||
An array of hex codes that represents allowed gremlins (invisible / undesirable characters). To allow all gremlins, you can also set the `noGremlins` rule to `false`.
|
An array of hex codes that represents allowed gremlins (invisible / undesirable characters). To allow all gremlins, you can also set the `noGremlins` rule to `false`. The full gremlin list is [here](https://github.com/sasjs/lint/blob/main/src/utils/gremlinCharacters.ts).
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@@ -228,6 +230,13 @@ In addition, when such files are used in URLs, they are often padded with a mess
|
|||||||
- Default: true
|
- Default: true
|
||||||
- Severity: WARNING
|
- Severity: WARNING
|
||||||
|
|
||||||
|
As an alternative (or in addition) to using a lint rule, you can also set the following in your `.gitignore` file to prevent files with spaces from being committed:
|
||||||
|
|
||||||
|
```
|
||||||
|
# prevent files/folders with spaces
|
||||||
|
**\ **
|
||||||
|
```
|
||||||
|
|
||||||
### noTabs
|
### noTabs
|
||||||
|
|
||||||
Whilst there are some arguments for using tabs (such as the ability to set your own indentation width, and to reduce character count) there are many, many, many developers who think otherwise. We're in that camp. Sorry (not sorry).
|
Whilst there are some arguments for using tabs (such as the ability to set your own indentation width, and to reduce character count) there are many, many, many developers who think otherwise. We're in that camp. Sorry (not sorry).
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
"noSpacesInFileNames": true,
|
"noSpacesInFileNames": true,
|
||||||
"noTabs": true,
|
"noTabs": true,
|
||||||
"noTrailingSpaces": true,
|
"noTrailingSpaces": true,
|
||||||
"lineEndings": "lf",
|
"lineEndings": "off",
|
||||||
"strictMacroDefinition": true,
|
"strictMacroDefinition": true,
|
||||||
"ignoreList": ["sajsbuild", "sasjsresults"]
|
"ignoreList": ["sajsbuild", "sasjsresults"]
|
||||||
},
|
},
|
||||||
@@ -185,7 +185,7 @@
|
|||||||
"enum": ["lf", "crlf", "off"],
|
"enum": ["lf", "crlf", "off"],
|
||||||
"title": "lineEndings",
|
"title": "lineEndings",
|
||||||
"description": "Enforces the configured terminating character for each line. Shows a warning when incorrect line endings are present.",
|
"description": "Enforces the configured terminating character for each line. Shows a warning when incorrect line endings are present.",
|
||||||
"default": "lf",
|
"default": "off",
|
||||||
"examples": ["lf", "crlf"]
|
"examples": ["lf", "crlf"]
|
||||||
},
|
},
|
||||||
"strictMacroDefinition": {
|
"strictMacroDefinition": {
|
||||||
|
|||||||
@@ -8,11 +8,12 @@ import { formatFolder } from './formatFolder'
|
|||||||
* @returns {Promise<FormatResult>} Resolves successfully when all SAS files in the current project have been formatted.
|
* @returns {Promise<FormatResult>} Resolves successfully when all SAS files in the current project have been formatted.
|
||||||
*/
|
*/
|
||||||
export const formatProject = async (): Promise<FormatResult> => {
|
export const formatProject = async (): Promise<FormatResult> => {
|
||||||
const projectRoot =
|
const projectRoot = (await getProjectRoot()) || process.currentDir
|
||||||
(await getProjectRoot()) || process.projectDir || process.currentDir
|
|
||||||
if (!projectRoot) {
|
if (!projectRoot) {
|
||||||
throw new Error('SASjs Project Root was not found.')
|
throw new Error('SASjs Project Root was not found.')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.info(`Formatting all .sas files under ${projectRoot}`)
|
||||||
|
|
||||||
return await formatFolder(projectRoot)
|
return await formatFolder(projectRoot)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const lintFile = async (
|
|||||||
filePath: string,
|
filePath: string,
|
||||||
configuration?: LintConfig
|
configuration?: LintConfig
|
||||||
): Promise<Diagnostic[]> => {
|
): Promise<Diagnostic[]> => {
|
||||||
if (await isIgnored(filePath)) return []
|
if (await isIgnored(filePath, configuration)) return []
|
||||||
|
|
||||||
const config = configuration || (await getLintConfig())
|
const config = configuration || (await getLintConfig())
|
||||||
const text = await readFile(filePath)
|
const text = await readFile(filePath)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export const lintFolder = async (
|
|||||||
const config = configuration || (await getLintConfig())
|
const config = configuration || (await getLintConfig())
|
||||||
let diagnostics: Map<string, Diagnostic[]> = new Map<string, Diagnostic[]>()
|
let diagnostics: Map<string, Diagnostic[]> = new Map<string, Diagnostic[]>()
|
||||||
|
|
||||||
if (await isIgnored(folderPath)) return diagnostics
|
if (await isIgnored(folderPath, config)) return diagnostics
|
||||||
|
|
||||||
const fileNames = await listSasFiles(folderPath)
|
const fileNames = await listSasFiles(folderPath)
|
||||||
await asyncForEach(fileNames, async (fileName) => {
|
await asyncForEach(fileNames, async (fileName) => {
|
||||||
|
|||||||
@@ -6,10 +6,12 @@ import { lintFolder } from './lintFolder'
|
|||||||
* @returns {Promise<Map<string, Diagnostic[]>>} Resolves with a map with array of diagnostic objects, each containing a warning, line number and column number, and grouped by file path.
|
* @returns {Promise<Map<string, Diagnostic[]>>} Resolves with a map with array of diagnostic objects, each containing a warning, line number and column number, and grouped by file path.
|
||||||
*/
|
*/
|
||||||
export const lintProject = async () => {
|
export const lintProject = async () => {
|
||||||
const projectRoot =
|
const projectRoot = (await getProjectRoot()) || process.currentDir
|
||||||
(await getProjectRoot()) || process.projectDir || process.currentDir
|
|
||||||
if (!projectRoot) {
|
if (!projectRoot) {
|
||||||
throw new Error('SASjs Project Root was not found.')
|
throw new Error('SASjs Project Root was not found.')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.info(`Linting all .sas files under ${projectRoot}`)
|
||||||
|
|
||||||
return await lintFolder(projectRoot)
|
return await lintFolder(projectRoot)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
import os from 'os'
|
||||||
import { LintConfig } from '../types/LintConfig'
|
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'
|
||||||
|
import { LineEndings } from '../types/LineEndings'
|
||||||
|
|
||||||
export const getDefaultHeader = () =>
|
export const getDefaultHeader = () =>
|
||||||
`/**{lineEnding} @file{lineEnding} @brief <Your brief here>{lineEnding} <h4> SAS Macros </h4>{lineEnding}**/`
|
`/**{lineEnding} @file{lineEnding} @brief <Your brief here>{lineEnding} <h4> SAS Macros </h4>{lineEnding}**/`
|
||||||
@@ -10,6 +12,7 @@ export const getDefaultHeader = () =>
|
|||||||
* Default configuration that is used when a .sasjslint file is not found
|
* Default configuration that is used when a .sasjslint file is not found
|
||||||
*/
|
*/
|
||||||
export const DefaultLintConfiguration = {
|
export const DefaultLintConfiguration = {
|
||||||
|
lineEndings: LineEndings.OFF,
|
||||||
noTrailingSpaces: true,
|
noTrailingSpaces: true,
|
||||||
noEncodedPasswords: true,
|
noEncodedPasswords: true,
|
||||||
hasDoxygenHeader: true,
|
hasDoxygenHeader: true,
|
||||||
@@ -29,14 +32,15 @@ export const DefaultLintConfiguration = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the config from the .sasjslint file and creates a LintConfig object.
|
* Fetches the config from the .sasjslint file (at project root or home directory) and creates a LintConfig object.
|
||||||
* Returns the default configuration when a .sasjslint file is unavailable.
|
* Returns the default configuration when a .sasjslint file is unavailable.
|
||||||
* @returns {Promise<LintConfig>} resolves with an object representing the current lint configuration.
|
* @returns {Promise<LintConfig>} resolves with an object representing the current lint configuration.
|
||||||
*/
|
*/
|
||||||
export async function getLintConfig(): Promise<LintConfig> {
|
export async function getLintConfig(): Promise<LintConfig> {
|
||||||
const projectRoot = await getProjectRoot()
|
const projectRoot = await getProjectRoot()
|
||||||
|
const lintFileLocation = projectRoot || os.homedir()
|
||||||
const configuration = await readFile(
|
const configuration = await readFile(
|
||||||
path.join(projectRoot, '.sasjslint')
|
path.join(lintFileLocation, '.sasjslint')
|
||||||
).catch((_) => {
|
).catch((_) => {
|
||||||
return JSON.stringify(DefaultLintConfiguration)
|
return JSON.stringify(DefaultLintConfiguration)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
import os from 'os'
|
||||||
import { fileExists } from '@sasjs/utils/file'
|
import { fileExists } from '@sasjs/utils/file'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -11,10 +12,11 @@ export async function getProjectRoot(): Promise<string> {
|
|||||||
let rootFound = false
|
let rootFound = false
|
||||||
let i = 1
|
let i = 1
|
||||||
let currentLocation = process.cwd()
|
let currentLocation = process.cwd()
|
||||||
|
const homeDir = os.homedir()
|
||||||
|
|
||||||
const maxLevels = currentLocation.split(path.sep).length
|
const maxLevels = currentLocation.split(path.sep).length
|
||||||
|
|
||||||
while (i <= maxLevels && !rootFound) {
|
while (i <= maxLevels && !rootFound && currentLocation !== homeDir) {
|
||||||
const isRoot = await fileExists(path.join(currentLocation, '.sasjslint'))
|
const isRoot = await fileExists(path.join(currentLocation, '.sasjslint'))
|
||||||
|
|
||||||
if (isRoot) {
|
if (isRoot) {
|
||||||
|
|||||||
Reference in New Issue
Block a user