-
Notifications
You must be signed in to change notification settings - Fork 71
Expand file tree
/
Copy pathoffense_line.rb
More file actions
150 lines (119 loc) · 3.68 KB
/
offense_line.rb
File metadata and controls
150 lines (119 loc) · 3.68 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# frozen_string_literal: true
module Pronto
class Rubocop < Runner
class OffenseLine
def initialize(patch_cop, offense, line)
@patch_cop = patch_cop
@offense = offense
@line = line
end
def message
Message.new(path, line, level, message_text, nil, Pronto::Rubocop)
end
private
attr_reader :patch_cop, :offense, :line
def path
line.patch.delta.new_file[:path]
end
def processed_source
patch_cop.processed_source
end
def message_text
return "#{indirect_message}#{offense_message}" unless suggestable?
"#{offense_message}\n\n#{indirect_suggestion}#{suggestion_text}"
end
def suggestion_text
return unless suggestable?
"```#{code_type}\n#{corrected_lines[offense.line - 1]}```"
end
def suggestable?
# `corrector.nil?`` possible after optimisation in https://github.com/rubocop/rubocop/pull/11264
patch_cop.runner.pronto_rubocop_config.fetch('suggestions', false) &&
(!corrections_count.zero? && !corrector.nil? && differing_lines_count == corrections_count)
end
def code_type
indirect_offense? ? 'ruby' : 'suggestion'
end
def offense_message
if documentation_url
offense.message.gsub(
offense.cop_name, "[#{offense.cop_name}](#{documentation_url})"
)
else
offense.message
end
end
def indirect_offense?
offense.location.first_line != line.new_lineno
end
def indirect_message
"Offense generated for line #{offense.location.first_line}:\n\n" if indirect_offense?
end
def indirect_suggestion
"Suggestion for line #{offense.location.first_line}:\n\n" if indirect_offense?
end
def corrected_lines
@corrected_lines ||= corrector.rewrite.lines
end
def differing_lines_count
original_lines.each_with_index.count { |line, index| line != corrected_lines[index] }
end
def original_lines
processed_source.lines.join("\n").lines
end
# rubocop 1.30.0 renamed from auto_correct to autocorrect
AUTOCORRECT =
if Gem::Version.new(::RuboCop::Version::STRING) >= Gem::Version.new('1.30.0')
:autocorrect
else
:auto_correct
end
def report
@report ||= autocorrect_team.investigate(processed_source).cop_reports.first
end
def corrector
report.corrector
end
def corrections_count
# Some lines may contain more than one offense
report.offenses.map(&:line).uniq.size
end
def autocorrect_team
@autocorrect_team ||= ::RuboCop::Cop::Team.mobilize(
::RuboCop::Cop::Registry.new([cop_class]),
patch_cop.rubocop_config,
**{ AUTOCORRECT => true, stdin: true }
)
end
def cop_class
patch_cop.registry.find_by_cop_name(offense.cop_name)
end
def documentation_url
cop_class&.documentation_url
end
def level
severities.fetch(offense.severity.name)
end
def severities
@severities ||= DEFAULT_SEVERITIES.merge(config_severities)
end
def config_severities
patch_cop
.runner
.pronto_rubocop_config
.fetch('severities', {})
.map { |k, v| [k.to_sym, v.to_sym] }
.to_h
end
DEFAULT_SEVERITIES = {
info: :info,
refactor: :warning,
convention: :warning,
warning: :warning,
error: :error,
fatal: :fatal
}.freeze
private_constant :DEFAULT_SEVERITIES
end
end
end