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