blob: e334860b5b93b0e607846d26e90d5515c91c56e3 (
plain) (
tree)
|
|
# frozen_string_literal: true
require 'pronto'
require 'shellwords'
module Pronto
module Hlint
class Runner < Pronto::Runner
CONFIG_FILE = '.pronto_hlint.yml'.freeze
CONFIG_KEYS = %w[hlint_executable files_to_lint cmd_line_opts].freeze
attr_writer :hlint_executable, :cmd_line_opts
def hlint_executable
@hlint_executable || 'hlint'
end
def files_to_lint
@files_to_lint || /(\.hs)$/
end
def cmd_line_opts
@cmd_line_opts || ''
end
def files_to_lint=(regexp)
@files_to_lint = regexp.is_a?(Regexp) && regexp || Regexp.new(regexp)
end
def config_options
@config_options ||=
begin
config_file = File.join(repo_path, CONFIG_FILE)
File.exist?(config_file) && YAML.load_file(config_file) || {}
end
end
def read_config
config_options.each do |key, val|
next unless CONFIG_KEYS.include?(key.to_s)
send("#{key}=", val)
end
end
def run
return [] if !@patches || @patches.count.zero?
read_config
@patches
.select { |patch| patch.additions > 0 }
.select { |patch| hs_file?(patch.new_file_full_path) }
.map { |patch| inspect(patch) }
.flatten.compact
end
private
def repo_path
@repo_path ||= @patches.first.repo.path
end
def inspect(patch)
offences = run_hlint(patch)
offences
.map do |offence|
patch
.added_lines
.select { |line| (offence['startLine']..offence['endLine']).include?(line.new_lineno) }
.map { |line| new_message(offence, line) }
end
end
def new_message(offence, line)
path = line.patch.delta.new_file[:path]
level = hlint_severity_to_pronto_level(offence['severity']) || :warning
text = <<~EOF
#{offence['severity']} offence detected by Hlint. Hint is: `#{offence['hint']}`.
Consider changing the code from
```
#{offence['from']}
```
to
```
#{offence['to']}
```
EOF
Message.new(path, line, level, text, nil, self.class)
end
def hlint_severity_to_pronto_level(severity)
case severity
when "Error"
:error
when "Warning"
:warning
when "Suggestion"
:info
end
end
def hs_file?(path)
files_to_lint =~ path.to_s
end
def run_hlint(patch)
Dir.chdir(repo_path) do
JSON.parse `#{hlint_command_line(patch.new_file_full_path.to_s)}`
end
end
def hlint_command_line(path)
"#{hlint_executable} #{cmd_line_opts} #{Shellwords.escape(path)} --json"
end
end
end
end
|