-
Notifications
You must be signed in to change notification settings - Fork 1
/
denali-build.js
104 lines (85 loc) · 3.26 KB
/
denali-build.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
const path = require('path');
const { AddonBuilder } = require('@denali-js/cli');
const Funnel = require('broccoli-funnel');
const Concat = require('broccoli-concat');
const MergeTree = require('broccoli-merge-trees');
const escape = require('js-string-escape');
const Filter = require('broccoli-filter');
const chalk = require('chalk');
const dedent = require('dedent-js');
module.exports = class DenaliEslintBuilder extends AddonBuilder {
processParent(tree, dir) {
return this.lint(tree, dir);
}
lint(tree, dir) {
// If it's in test environment, generate test modules for each linted file
if (this.environment === 'test') {
let lintTestTree = new LintTree(tree, { generateTests: true, rootDir: dir });
lintTestTree = new Funnel(lintTestTree, { destDir: 'test/lint' });
lintTestTree = new Concat(lintTestTree, {
outputFile: 'test/linting.js',
header: `import test from 'ava';`,
inputFiles: [ '**/*.lint-test.js' ],
sourceMapConfig: { enabled: true },
allowNone: true
});
return new MergeTree([ lintTestTree, tree ]);
}
// Otherwise, just lint and move on
return new LintTree(tree, { rootDir: dir });
}
}
const IGNORED_FILE_MESSAGE_REGEXP = /(?:File ignored by default\.)|(?:File ignored because of a matching ignore pattern\.)/;
class LintTree extends Filter {
constructor(inputNode, options = {}) {
super(inputNode, options);
this.extensions = [ 'js' ];
this.targetExtension = 'js';
this.rootDir = options.rootDir;
this.generateTests = options.generateTests;
if (this.generateTests) {
this.targetExtension = 'lint-test.js';
}
const { CLIEngine } = require('eslint');
this.cli = new CLIEngine({ cwd: this.rootDir });
}
processString(content, relativePath) {
let report = this.cli.executeOnText(content, path.join(this.rootDir, relativePath));
let result = report.results[0] || {};
let messages = result.messages || [];
messages = messages.filter((msg) => !IGNORED_FILE_MESSAGE_REGEXP.test(msg.message));
if (this.generateTests) {
return this.testGenerator(relativePath, messages);
}
if (messages.length > 0) {
// eslint-disable-next-line no-console
console.log(chalk.yellow(`\n${ path.join(this.rootDir, relativePath) } has ${ result.errorCount } errors and ${ result.warningCount } warnings.`));
messages.forEach((error, index) => {
// eslint-disable-next-line no-console
console.log(chalk.yellow(dedent`
${ index + 1 }: ${ error.message } (${ error.ruleId }) at line ${ error.line }:${ error.column }
${ error.source }
`));
});
}
return content;
}
testGenerator(relativePath, errors) {
let passed = errors.length === 0;
let messages = `${ relativePath } should pass ESLint`;
if (!passed) {
messages += '\n\n';
messages += errors.map((error) => {
return `${ error.line }:${ error.column } - ${ error.message } (${ error.ruleId })`;
}).join('\n');
}
let output = `test('${ relativePath } passes ESLint', (t) => {`;
if (passed) {
output += " t.pass('Linting passed.')\n";
} else {
output += ` t.fail('${ escape(messages) }');\n`;
}
output += '});\n';
return output;
}
}