mirror of
https://github.com/sasjs/lint.git
synced 2025-12-11 01:44:36 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8dec4f7129 | ||
|
|
fb4cc2dd20 | ||
|
|
09e2d051c4 |
@@ -6,57 +6,61 @@ describe('lintFolder', () => {
|
|||||||
it('should identify lint issues in a given folder', async () => {
|
it('should identify lint issues in a given folder', async () => {
|
||||||
const results = await lintFolder(path.join(__dirname, '..'))
|
const results = await lintFolder(path.join(__dirname, '..'))
|
||||||
|
|
||||||
expect(results.length).toEqual(8)
|
expect(results.size).toEqual(1)
|
||||||
expect(results).toContainEqual({
|
const diagnostics = results.get(
|
||||||
|
path.join(__dirname, '..', 'Example File.sas')
|
||||||
|
)!
|
||||||
|
expect(diagnostics.length).toEqual(8)
|
||||||
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'Line contains trailing spaces',
|
message: 'Line contains trailing spaces',
|
||||||
lineNumber: 1,
|
lineNumber: 1,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
endColumnNumber: 2,
|
endColumnNumber: 2,
|
||||||
severity: Severity.Warning
|
severity: Severity.Warning
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'Line contains trailing spaces',
|
message: 'Line contains trailing spaces',
|
||||||
lineNumber: 2,
|
lineNumber: 2,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
endColumnNumber: 2,
|
endColumnNumber: 2,
|
||||||
severity: Severity.Warning
|
severity: Severity.Warning
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'File name contains spaces',
|
message: 'File name contains spaces',
|
||||||
lineNumber: 1,
|
lineNumber: 1,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
endColumnNumber: 1,
|
endColumnNumber: 1,
|
||||||
severity: Severity.Warning
|
severity: Severity.Warning
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'File name contains uppercase characters',
|
message: 'File name contains uppercase characters',
|
||||||
lineNumber: 1,
|
lineNumber: 1,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
endColumnNumber: 1,
|
endColumnNumber: 1,
|
||||||
severity: Severity.Warning
|
severity: Severity.Warning
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'File missing Doxygen header',
|
message: 'File missing Doxygen header',
|
||||||
lineNumber: 1,
|
lineNumber: 1,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
endColumnNumber: 1,
|
endColumnNumber: 1,
|
||||||
severity: Severity.Warning
|
severity: Severity.Warning
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'Line contains encoded password',
|
message: 'Line contains encoded password',
|
||||||
lineNumber: 5,
|
lineNumber: 5,
|
||||||
startColumnNumber: 10,
|
startColumnNumber: 10,
|
||||||
endColumnNumber: 18,
|
endColumnNumber: 18,
|
||||||
severity: Severity.Error
|
severity: Severity.Error
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'Line is indented with a tab',
|
message: 'Line is indented with a tab',
|
||||||
lineNumber: 7,
|
lineNumber: 7,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
endColumnNumber: 1,
|
endColumnNumber: 1,
|
||||||
severity: Severity.Warning
|
severity: Severity.Warning
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'Line has incorrect indentation - 3 spaces',
|
message: 'Line has incorrect indentation - 3 spaces',
|
||||||
lineNumber: 6,
|
lineNumber: 6,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
|
|||||||
@@ -20,19 +20,18 @@ const excludeFolders = [
|
|||||||
* Analyses and produces a set of diagnostics for the folder at the given path.
|
* Analyses and produces a set of diagnostics for the folder at the given path.
|
||||||
* @param {string} folderPath - the path to the folder to be linted.
|
* @param {string} folderPath - the path to the folder to be linted.
|
||||||
* @param {LintConfig} configuration - an optional configuration. When not passed in, this is read from the .sasjslint file.
|
* @param {LintConfig} configuration - an optional configuration. When not passed in, this is read from the .sasjslint file.
|
||||||
* @returns {Diagnostic[]} array of diagnostic objects, each containing a warning, line number and column number.
|
* @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 lintFolder = async (
|
export const lintFolder = async (
|
||||||
folderPath: string,
|
folderPath: string,
|
||||||
configuration?: LintConfig
|
configuration?: LintConfig
|
||||||
) => {
|
) => {
|
||||||
const config = configuration || (await getLintConfig())
|
const config = configuration || (await getLintConfig())
|
||||||
const diagnostics: Diagnostic[] = []
|
let diagnostics: Map<string, Diagnostic[]> = new Map<string, Diagnostic[]>()
|
||||||
const fileNames = await listSasFiles(folderPath)
|
const fileNames = await listSasFiles(folderPath)
|
||||||
await asyncForEach(fileNames, async (fileName) => {
|
await asyncForEach(fileNames, async (fileName) => {
|
||||||
diagnostics.push(
|
const filePath = path.join(folderPath, fileName)
|
||||||
...(await lintFile(path.join(folderPath, fileName), config))
|
diagnostics.set(filePath, await lintFile(filePath, config))
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const subFolders = (await listSubFoldersInFolder(folderPath)).filter(
|
const subFolders = (await listSubFoldersInFolder(folderPath)).filter(
|
||||||
@@ -40,9 +39,11 @@ export const lintFolder = async (
|
|||||||
)
|
)
|
||||||
|
|
||||||
await asyncForEach(subFolders, async (subFolder) => {
|
await asyncForEach(subFolders, async (subFolder) => {
|
||||||
diagnostics.push(
|
const subFolderDiagnostics = await lintFolder(
|
||||||
...(await lintFolder(path.join(folderPath, subFolder), config))
|
path.join(folderPath, subFolder),
|
||||||
|
config
|
||||||
)
|
)
|
||||||
|
diagnostics = new Map([...diagnostics, ...subFolderDiagnostics])
|
||||||
})
|
})
|
||||||
|
|
||||||
return diagnostics
|
return diagnostics
|
||||||
|
|||||||
@@ -1,62 +1,71 @@
|
|||||||
import { lintProject } from './lintProject'
|
import { lintProject } from './lintProject'
|
||||||
import { Severity } from '../types/Severity'
|
import { Severity } from '../types/Severity'
|
||||||
|
import * as utils from '../utils'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
jest.mock('../utils')
|
||||||
|
|
||||||
describe('lintProject', () => {
|
describe('lintProject', () => {
|
||||||
it('should identify lint issues in a given project', async () => {
|
it('should identify lint issues in a given project', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(utils, 'getProjectRoot')
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(path.join(__dirname, '..')))
|
||||||
const results = await lintProject()
|
const results = await lintProject()
|
||||||
|
|
||||||
expect(results.length).toEqual(8)
|
expect(results.size).toEqual(1)
|
||||||
expect(results).toContainEqual({
|
const diagnostics = results.get(
|
||||||
|
path.join(__dirname, '..', 'Example File.sas')
|
||||||
|
)!
|
||||||
|
expect(diagnostics.length).toEqual(8)
|
||||||
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'Line contains trailing spaces',
|
message: 'Line contains trailing spaces',
|
||||||
lineNumber: 1,
|
lineNumber: 1,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
endColumnNumber: 2,
|
endColumnNumber: 2,
|
||||||
severity: Severity.Warning
|
severity: Severity.Warning
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'Line contains trailing spaces',
|
message: 'Line contains trailing spaces',
|
||||||
lineNumber: 2,
|
lineNumber: 2,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
endColumnNumber: 2,
|
endColumnNumber: 2,
|
||||||
severity: Severity.Warning
|
severity: Severity.Warning
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'File name contains spaces',
|
message: 'File name contains spaces',
|
||||||
lineNumber: 1,
|
lineNumber: 1,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
endColumnNumber: 1,
|
endColumnNumber: 1,
|
||||||
severity: Severity.Warning
|
severity: Severity.Warning
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'File name contains uppercase characters',
|
message: 'File name contains uppercase characters',
|
||||||
lineNumber: 1,
|
lineNumber: 1,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
endColumnNumber: 1,
|
endColumnNumber: 1,
|
||||||
severity: Severity.Warning
|
severity: Severity.Warning
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'File missing Doxygen header',
|
message: 'File missing Doxygen header',
|
||||||
lineNumber: 1,
|
lineNumber: 1,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
endColumnNumber: 1,
|
endColumnNumber: 1,
|
||||||
severity: Severity.Warning
|
severity: Severity.Warning
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'Line contains encoded password',
|
message: 'Line contains encoded password',
|
||||||
lineNumber: 5,
|
lineNumber: 5,
|
||||||
startColumnNumber: 10,
|
startColumnNumber: 10,
|
||||||
endColumnNumber: 18,
|
endColumnNumber: 18,
|
||||||
severity: Severity.Error
|
severity: Severity.Error
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'Line is indented with a tab',
|
message: 'Line is indented with a tab',
|
||||||
lineNumber: 7,
|
lineNumber: 7,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
endColumnNumber: 1,
|
endColumnNumber: 1,
|
||||||
severity: Severity.Warning
|
severity: Severity.Warning
|
||||||
})
|
})
|
||||||
expect(results).toContainEqual({
|
expect(diagnostics).toContainEqual({
|
||||||
message: 'Line has incorrect indentation - 3 spaces',
|
message: 'Line has incorrect indentation - 3 spaces',
|
||||||
lineNumber: 6,
|
lineNumber: 6,
|
||||||
startColumnNumber: 1,
|
startColumnNumber: 1,
|
||||||
@@ -64,4 +73,14 @@ describe('lintProject', () => {
|
|||||||
severity: Severity.Warning
|
severity: Severity.Warning
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should throw an error when a project root is not found', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(utils, 'getProjectRoot')
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(''))
|
||||||
|
|
||||||
|
await expect(lintProject()).rejects.toThrowError(
|
||||||
|
'SASjs Project Root was not found.'
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { lintFolder } from './lintFolder'
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Analyses and produces a set of diagnostics for the current project.
|
* Analyses and produces a set of diagnostics for the current project.
|
||||||
* @returns {Diagnostic[]} array of diagnostic objects, each containing a warning, line number and column number.
|
* @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 =
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ export async function getLintConfig(): Promise<LintConfig> {
|
|||||||
const configuration = await readFile(
|
const configuration = await readFile(
|
||||||
path.join(projectRoot, '.sasjslint')
|
path.join(projectRoot, '.sasjslint')
|
||||||
).catch((_) => {
|
).catch((_) => {
|
||||||
console.warn('Unable to load .sasjslint file. Using default configuration.')
|
|
||||||
return JSON.stringify(DefaultLintConfiguration)
|
return JSON.stringify(DefaultLintConfiguration)
|
||||||
})
|
})
|
||||||
return new LintConfig(JSON.parse(configuration))
|
return new LintConfig(JSON.parse(configuration))
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
],
|
],
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
|
"downlevelIteration": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user