]>
Commit | Line | Data |
---|---|---|
9be00a32 | 1 | require 'pronto' |
2950a68a | 2 | require 'shellwords' |
9be00a32 MM |
3 | |
4 | module Pronto | |
5001cb27 | 5 | class ESLintNpm < Runner |
1845f2e3 | 6 | CONFIG_FILE = '.pronto_eslint_npm.yml'.freeze |
212da35b | 7 | CONFIG_KEYS = %w(eslint_executable files_to_lint).freeze |
3403f9d1 | 8 | |
1845f2e3 MD |
9 | attr_writer :eslint_executable |
10 | ||
11 | def eslint_executable | |
12 | @eslint_executable || 'eslint'.freeze | |
13 | end | |
14 | ||
15 | def files_to_lint | |
16 | @files_to_lint || /(\.js|\.es6)$/ | |
17 | end | |
18 | ||
19 | def files_to_lint=(regexp) | |
20 | @files_to_lint = regexp.is_a?(Regexp) && regexp || Regexp.new(regexp) | |
21 | end | |
22 | ||
23 | def read_config | |
24 | config_file = File.join(repo_path, CONFIG_FILE) | |
25 | return unless File.exist?(config_file) | |
26 | config = YAML.load_file(config_file) | |
3403f9d1 | 27 | |
1845f2e3 MD |
28 | CONFIG_KEYS.each do |config_key| |
29 | next unless config[config_key] | |
30 | send("#{config_key}=", config[config_key]) | |
3403f9d1 MD |
31 | end |
32 | end | |
33 | ||
b338a7ad | 34 | def run |
1845f2e3 MD |
35 | return [] if !@patches || @patches.count.zero? |
36 | ||
37 | read_config | |
9be00a32 | 38 | |
3403f9d1 MD |
39 | @patches |
40 | .select { |patch| patch.additions > 0 } | |
9be00a32 MM |
41 | .select { |patch| js_file?(patch.new_file_full_path) } |
42 | .map { |patch| inspect(patch) } | |
43 | .flatten.compact | |
44 | end | |
45 | ||
3403f9d1 MD |
46 | private |
47 | ||
1845f2e3 | 48 | def repo_path |
29509625 | 49 | @_repo_path ||= @patches.first.repo.path |
1845f2e3 | 50 | end |
29509625 | 51 | |
1845f2e3 | 52 | def inspect(patch) |
156f8167 MD |
53 | offences = run_eslint(patch) |
54 | clean_up_eslint_output(offences) | |
55 | .map do |offence| | |
56 | patch | |
57 | .added_lines | |
58 | .select { |line| line.new_lineno == offence['line'] } | |
59 | .map { |line| new_message(offence, line) } | |
29509625 | 60 | end |
9be00a32 MM |
61 | end |
62 | ||
63 | def new_message(offence, line) | |
64 | path = line.patch.delta.new_file[:path] | |
65 | level = :warning | |
66 | ||
b338a7ad | 67 | Message.new(path, line, level, offence['message'], nil, self.class) |
9be00a32 MM |
68 | end |
69 | ||
70 | def js_file?(path) | |
1845f2e3 | 71 | files_to_lint =~ path.to_s |
9be00a32 | 72 | end |
156f8167 MD |
73 | |
74 | def run_eslint(patch) | |
1845f2e3 | 75 | Dir.chdir(repo_path) do |
3403f9d1 | 76 | escaped_file_path = Shellwords.escape(patch.new_file_full_path.to_s) |
156f8167 | 77 | JSON.parse( |
1845f2e3 | 78 | `#{eslint_executable} #{escaped_file_path} -f json` |
156f8167 MD |
79 | ) |
80 | end | |
81 | end | |
82 | ||
156f8167 MD |
83 | def clean_up_eslint_output(output) |
84 | # 1. Filter out offences without a warning or error | |
85 | # 2. Get the messages for that file | |
86 | # 3. Ignore errors without a line number for now | |
87 | output | |
88 | .select { |offence| offence['errorCount'] + offence['warningCount'] > 0 } | |
89 | .map { |offence| offence['messages'] } | |
90 | .flatten.select { |offence| offence['line'] } | |
91 | end | |
9be00a32 MM |
92 | end |
93 | end |