forked from todogroup/repolinter
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
151 lines (131 loc) · 4.89 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Copyright 2017 TODO Group. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
const jsonfile = require('jsonfile')
const path = require('path')
const fs = require('fs')
const findConfig = require('find-config')
const Result = require('./lib/result')
const FileSystem = require('./lib/file_system')
const fileSystem = new FileSystem()
module.exports.defaultFormatter = require('./formatters/symbol_formatter')
module.exports.jsonFormatter = require('./formatters/json_formatter')
module.exports.resultFormatter = exports.defaultFormatter
module.exports.outputInfo = console.log
module.exports.outputResult = console.log
module.exports.lint = function lint (targetDir, filterPaths = [], ruleset = null) {
fileSystem.targetDir = targetDir
exports.outputInfo(`Target directory: ${targetDir}`)
if (filterPaths.length > 0) {
exports.outputInfo(`Paths to include in checks:\n\t${filterPaths.join('\n\t')}`)
fileSystem.filterPaths = filterPaths
}
if (!ruleset) {
let rulesetPath = findConfig('repolint.json', { cwd: targetDir })
rulesetPath = rulesetPath || findConfig('repolinter.json', { cwd: targetDir })
rulesetPath = rulesetPath || path.join(__dirname, 'rulesets/default.json')
exports.outputInfo(`Ruleset: ${path.relative(targetDir, rulesetPath)}`)
ruleset = jsonfile.readFileSync(rulesetPath)
}
let targets = ['all']
// Identify axioms and execute them
if (ruleset.axioms) {
Object.getOwnPropertyNames(ruleset.axioms).forEach(axiomId => {
const axiomName = ruleset.axioms[axiomId]
// TODO: Do something more secure
// Execute axiom
const axiomFunction = require(path.join(__dirname, 'axioms', axiomId))
targets = targets.concat(axiomName + '=*')
targets = targets.concat(axiomFunction(fileSystem).map(axiomOutput => axiomName + '=' + axiomOutput))
})
}
let anyFailures = false
// Execute all rule targets
// global variable for return statement
let evaluation = []
targets.forEach(target => {
const targetRules = ruleset.rules[target]
if (targetRules) {
Object.getOwnPropertyNames(targetRules).forEach(ruleId => {
const rule = parseRule(targetRules[ruleId])
const ruleIdParts = ruleId.split(':')
rule.id = ruleIdParts[0]
rule.module = ruleIdParts.length === 2 ? ruleIdParts[1] : ruleIdParts[0]
if (rule.enabled) {
// TODO: Do something more secure
let results = []
try {
// Does a .js file exist?
let ruleFile = path.join(__dirname, 'rules', rule.module)
if (fs.existsSync(ruleFile + '.js')) {
const ruleFunction = require(ruleFile)
results = ruleFunction(fileSystem, rule)
evaluation.push(results)
anyFailures = anyFailures || results.some(result => !result.passed && result.rule.level === 'error')
} else
// Otherwise, does a .json file exist?
if (fs.existsSync(ruleFile + '.json')) {
// We have a json file and need to recurse into this code
let childRuleset = jsonfile.readFileSync(ruleFile + '.json')
lint(targetDir, filterPaths, childRuleset)
}
} catch (error) {
results.push(new Result(rule, error.message, null, false))
evaluation.push(results)
}
}
})
}
})
evaluation.forEach(singleResult => {
renderResults(singleResult.filter(result => !result.passed))
renderResults(singleResult.filter(result => result.passed))
})
if (anyFailures) {
process.exitCode = 1
}
return evaluation
function renderResults (results) {
formatResults(results).filter(x => !!x).forEach(renderResult)
}
function formatResults (results) {
return results.map(formatResult)
}
function renderResult (result) {
exports.outputResult(result)
}
function formatResult (result) {
return exports.resultFormatter.format(result)
}
function parseRule (configItem) {
const rule = {}
if (Array.isArray(configItem) && configItem.length > 0) {
rule.enabled = parseEnabled(configItem[0])
rule.level = parseLevel(configItem[0])
rule.options = configItem.length > 1 ? configItem[1] : {}
} else if (typeof configItem === 'boolean' || typeof configItem === 'string') {
rule.enabled = parseEnabled(configItem)
rule.level = parseLevel(configItem)
rule.options = {}
}
if (!rule.options.fs) {
rule.options.fs = fileSystem
}
return rule
}
function parseEnabled (value) {
if (typeof value === 'boolean') {
return value
} else if (typeof value === 'string') {
return value.toLowerCase() !== 'off'
} else if (typeof value === 'object') {
return value.enabled || true
}
return true
}
function parseLevel (value) {
if (typeof value === 'string') {
return value.trim().toLowerCase()
}
return 'error'
}
}