]> git.immae.eu Git - github/fretlink/pronto-hlint.git/blob - lib/pronto/eslint_npm.rb
Load YAML configuration correctly
[github/fretlink/pronto-hlint.git] / lib / pronto / eslint_npm.rb
1 require 'pronto'
2 require 'shellwords'
3
4 module Pronto
5 class ESLintNpm < Runner
6 CONFIG_FILE = '.pronto_eslint_npm.yml'.freeze
7 CONFIG_KEYS = %w(eslint_executable files_to_lint).freeze
8
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)
27
28 CONFIG_KEYS.each do |config_key|
29 next unless config[config_key]
30 send("#{config_key}=", config[config_key])
31 end
32 end
33
34 def run
35 return [] if !@patches || @patches.count.zero?
36
37 read_config
38
39 @patches
40 .select { |patch| patch.additions > 0 }
41 .select { |patch| js_file?(patch.new_file_full_path) }
42 .map { |patch| inspect(patch) }
43 .flatten.compact
44 end
45
46 private
47
48 def repo_path
49 @_repo_path ||= @patches.first.repo.path
50 end
51
52 def inspect(patch)
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) }
60 end
61 end
62
63 def new_message(offence, line)
64 path = line.patch.delta.new_file[:path]
65 level = :warning
66
67 Message.new(path, line, level, offence['message'], nil, self.class)
68 end
69
70 def js_file?(path)
71 files_to_lint =~ path.to_s
72 end
73
74 def run_eslint(patch)
75 Dir.chdir(repo_path) do
76 escaped_file_path = Shellwords.escape(patch.new_file_full_path.to_s)
77 JSON.parse(
78 `#{eslint_executable} #{escaped_file_path} -f json`
79 )
80 end
81 end
82
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
92 end
93 end