-
Notifications
You must be signed in to change notification settings - Fork 55
/
Copy pathrunner.rb
128 lines (105 loc) · 3.19 KB
/
runner.rb
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
# coding: utf-8
require 'json'
# rubocop:disable Documentation
module Guard
class Rubocop
# This class runs `rubocop` command, retrieves result and notifies.
# An instance of this class is intended to invoke `rubocop` only once in its lifetime.
class Runner
# rubocop:enable Documentation
#
def initialize(options)
@options = options
end
def run(paths = [])
command = build_command(paths)
passed = system(*command)
case @options[:notification]
when :failed
notify(passed) unless passed
when true
notify(passed)
end
passed
end
def build_command(paths)
command = ['rubocop']
unless include_formatter_for_console?(args_specified_by_user)
command.concat(%w(--format progress)) # Keep default formatter for console.
end
command.concat(['--format', 'json', '--out', json_file_path])
command.concat(args_specified_by_user)
command.concat(paths)
end
def args_specified_by_user
@args_specified_by_user ||= begin
args = @options[:cli]
case args
when Array then args
when String then args.shellsplit
when NilClass then []
else fail ':cli option must be either an array or string'
end
end
end
def include_formatter_for_console?(cli_args)
index = -1
formatter_args = cli_args.group_by do |arg|
index += 1 if arg == '--format' || arg.start_with?('-f')
index
end
formatter_args.delete(-1)
formatter_args.each_value.any? do |args|
args.none? { |a| a == '--out' || a.start_with?('-o') }
end
end
def json_file_path
@json_file_path ||= begin
# Just generate random tempfile path.
basename = self.class.name.downcase.gsub('::', '_')
tempfile = Tempfile.new(basename)
tempfile.close
tempfile.path
end
end
def result
@result ||= begin
File.open(json_file_path) do |file|
# Rubinius 2.0.0.rc1 does not support `JSON.load` with 3 args.
JSON.parse(file.read, symbolize_names: true)
end
end
end
def notify(passed)
image = passed ? :success : :failed
Notifier.notify(summary_text, title: 'RuboCop results', image: image)
end
def summary_text
summary = result[:summary]
text = pluralize(summary[:inspected_file_count], 'file')
text << ' inspected, '
text << pluralize(summary[:offence_count], 'offence', no_for_zero: true)
text << ' detected'
end
def failed_paths
failed_files = result[:files].reject do |file|
file[:offences].empty?
end
failed_files.map do |file|
file[:path]
end
end
def pluralize(number, thing, options = {})
text = ''
if number == 0 && options[:no_for_zero]
text = 'no'
else
text << number.to_s
end
text << " #{thing}"
text << 's' unless number == 1
text
end
end
end
end