rubocop-sketchup 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +21 -20
- data/assets/output.html.erb +301 -301
- data/config/default.yml +400 -379
- data/lib/rubocop/sketchup/config.rb +63 -63
- data/lib/rubocop/sketchup/cop/bugs/material_name.rb +108 -108
- data/lib/rubocop/sketchup/cop/bugs/render_mode.rb +72 -72
- data/lib/rubocop/sketchup/cop/bugs/uniform_scaling.rb +36 -36
- data/lib/rubocop/sketchup/cop/deprecations/add_separator_to_menu.rb +25 -25
- data/lib/rubocop/sketchup/cop/deprecations/operation_next_transparent.rb +30 -30
- data/lib/rubocop/sketchup/cop/deprecations/require_all.rb +27 -27
- data/lib/rubocop/sketchup/cop/deprecations/set_texture_projection.rb +26 -26
- data/lib/rubocop/sketchup/cop/deprecations/show_ruby_panel.rb +25 -25
- data/lib/rubocop/sketchup/cop/deprecations/sketchup_set.rb +30 -30
- data/lib/rubocop/sketchup/cop/performance/openssl.rb +41 -41
- data/lib/rubocop/sketchup/cop/performance/operation_disable_ui.rb +33 -33
- data/lib/rubocop/sketchup/cop/performance/selection_bulk.rb +79 -79
- data/lib/rubocop/sketchup/cop/performance/type_check.rb +63 -63
- data/lib/rubocop/sketchup/cop/performance/typename.rb +24 -24
- data/lib/rubocop/sketchup/cop/requirements/api_namespace.rb +30 -30
- data/lib/rubocop/sketchup/cop/requirements/debug_mode.rb +27 -0
- data/lib/rubocop/sketchup/cop/requirements/exit.rb +33 -33
- data/lib/rubocop/sketchup/cop/requirements/extension_namespace.rb +125 -125
- data/lib/rubocop/sketchup/cop/requirements/file_structure.rb +97 -97
- data/lib/rubocop/sketchup/cop/requirements/gem_install.rb +45 -45
- data/lib/rubocop/sketchup/cop/requirements/get_extension_license.rb +95 -95
- data/lib/rubocop/sketchup/cop/requirements/global_constants.rb +38 -38
- data/lib/rubocop/sketchup/cop/requirements/global_include.rb +42 -42
- data/lib/rubocop/sketchup/cop/requirements/global_methods.rb +65 -65
- data/lib/rubocop/sketchup/cop/requirements/global_variables.rb +95 -95
- data/lib/rubocop/sketchup/cop/requirements/initialize_entity.rb +76 -0
- data/lib/rubocop/sketchup/cop/requirements/language_handler_globals.rb +46 -46
- data/lib/rubocop/sketchup/cop/requirements/load_path.rb +83 -83
- data/lib/rubocop/sketchup/cop/requirements/minimal_registration.rb +73 -73
- data/lib/rubocop/sketchup/cop/requirements/observers_start_operation.rb +161 -161
- data/lib/rubocop/sketchup/cop/requirements/register_extension.rb +45 -45
- data/lib/rubocop/sketchup/cop/requirements/ruby_core_namespace.rb +291 -291
- data/lib/rubocop/sketchup/cop/requirements/ruby_stdlib_namespace.rb +634 -634
- data/lib/rubocop/sketchup/cop/requirements/shipped_extensions_namespace.rb +61 -61
- data/lib/rubocop/sketchup/cop/requirements/sketchup_extension.rb +119 -119
- data/lib/rubocop/sketchup/cop/requirements/sketchup_require.rb +150 -150
- data/lib/rubocop/sketchup/cop/suggestions/add_group.rb +49 -49
- data/lib/rubocop/sketchup/cop/suggestions/compatibility.rb +128 -128
- data/lib/rubocop/sketchup/cop/suggestions/dc_internals.rb +34 -34
- data/lib/rubocop/sketchup/cop/suggestions/file_encoding.rb +78 -78
- data/lib/rubocop/sketchup/cop/suggestions/model_entities.rb +58 -58
- data/lib/rubocop/sketchup/cop/suggestions/monkey_patched_api.rb +45 -45
- data/lib/rubocop/sketchup/cop/suggestions/operation_name.rb +137 -137
- data/lib/rubocop/sketchup/cop/suggestions/sketchup_find_support_file.rb +39 -39
- data/lib/rubocop/sketchup/cop/suggestions/sleep.rb +25 -0
- data/lib/rubocop/sketchup/cop/suggestions/tool_drawing_bounds.rb +45 -45
- data/lib/rubocop/sketchup/cop/suggestions/tool_invalidate.rb +68 -68
- data/lib/rubocop/sketchup/cop/suggestions/tool_user_input.rb +41 -41
- data/lib/rubocop/sketchup/cop/suggestions/toolbar_timer.rb +65 -65
- data/lib/rubocop/sketchup/cop.rb +110 -110
- data/lib/rubocop/sketchup/dc_globals.rb +24 -24
- data/lib/rubocop/sketchup/dc_methods.rb +130 -130
- data/lib/rubocop/sketchup/extension_project.rb +65 -65
- data/lib/rubocop/sketchup/features.rb +1514 -1477
- data/lib/rubocop/sketchup/formatter/extension_review.rb +269 -269
- data/lib/rubocop/sketchup/generator.rb +21 -0
- data/lib/rubocop/sketchup/inject.rb +19 -19
- data/lib/rubocop/sketchup/namespace.rb +49 -49
- data/lib/rubocop/sketchup/namespace_checker.rb +103 -103
- data/lib/rubocop/sketchup/no_comment_disable.rb +17 -17
- data/lib/rubocop/sketchup/range_help.rb +52 -52
- data/lib/rubocop/sketchup/sketchup_target_range.rb +75 -75
- data/lib/rubocop/sketchup/sketchup_version.rb +131 -129
- data/lib/rubocop/sketchup/tool_checker.rb +41 -41
- data/lib/rubocop/sketchup/version.rb +7 -7
- data/lib/rubocop/sketchup.rb +14 -14
- data/lib/rubocop-sketchup.rb +53 -53
- data/rubocop-sketchup.gemspec +28 -29
- metadata +7 -23
@@ -1,269 +1,269 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'cgi'
|
4
|
-
require 'erb'
|
5
|
-
require 'ostruct'
|
6
|
-
require 'base64'
|
7
|
-
require 'rubocop/formatter/text_util'
|
8
|
-
|
9
|
-
module RuboCop
|
10
|
-
module Formatter
|
11
|
-
# This formatter saves the output as an html file.
|
12
|
-
class ExtensionReviewFormatter < BaseFormatter
|
13
|
-
ELLIPSES = '<span class="extra-code">...</span>'
|
14
|
-
TEMPLATE_PATH =
|
15
|
-
File.expand_path('../../../../assets/output.html.erb', __dir__)
|
16
|
-
|
17
|
-
Color = Struct.new(:red, :green, :blue, :alpha) do
|
18
|
-
def to_s
|
19
|
-
"rgba(#{values.join(', ')})"
|
20
|
-
end
|
21
|
-
|
22
|
-
def fade_out(amount)
|
23
|
-
dup.tap do |color|
|
24
|
-
color.alpha -= amount
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
attr_reader :categories, :files, :summary
|
30
|
-
|
31
|
-
def initialize(output, options = {})
|
32
|
-
super
|
33
|
-
@categories = {}
|
34
|
-
@files = []
|
35
|
-
@summary = OpenStruct.new(offense_count: 0)
|
36
|
-
end
|
37
|
-
|
38
|
-
def started(target_files)
|
39
|
-
summary.target_files = target_files
|
40
|
-
end
|
41
|
-
|
42
|
-
def file_finished(file, offenses)
|
43
|
-
files << file
|
44
|
-
offenses.each { |offense|
|
45
|
-
# Report only SketchUp related cops.
|
46
|
-
next unless offense.cop_name.start_with?('Sketchup')
|
47
|
-
|
48
|
-
report = OpenStruct.new(path: file, offense: offense)
|
49
|
-
categories[offense.cop_name] ||= []
|
50
|
-
categories[offense.cop_name] << report
|
51
|
-
summary.offense_count += 1
|
52
|
-
}
|
53
|
-
end
|
54
|
-
|
55
|
-
def finished(inspected_files)
|
56
|
-
summary.inspected_files = inspected_files
|
57
|
-
|
58
|
-
render_html
|
59
|
-
end
|
60
|
-
|
61
|
-
def render_html
|
62
|
-
context = ERBContext.new(categories, files, summary)
|
63
|
-
|
64
|
-
template = File.read(TEMPLATE_PATH, encoding: Encoding::UTF_8)
|
65
|
-
erb = ERB.new(template, trim_mode: '-')
|
66
|
-
html = erb.result(context.binding)
|
67
|
-
|
68
|
-
output.write html
|
69
|
-
end
|
70
|
-
|
71
|
-
# This class provides helper methods used in the ERB template.
|
72
|
-
class ERBContext
|
73
|
-
include PathUtil
|
74
|
-
include TextUtil
|
75
|
-
|
76
|
-
SEVERITY_COLORS = {
|
77
|
-
refactor: Color.new(0x29, 0x6B, 0xF0, 1.0),
|
78
|
-
convention: Color.new(0x29, 0x6B, 0xF0, 1.0),
|
79
|
-
warning: Color.new(0xED, 0x9C, 0x28, 1.0),
|
80
|
-
error: Color.new(0xD2, 0x32, 0x2D, 1.0),
|
81
|
-
fatal: Color.new(0xD2, 0x32, 0x2D, 1.0),
|
82
|
-
}.freeze
|
83
|
-
|
84
|
-
LOGO_IMAGE_PATH =
|
85
|
-
File.expand_path('../../../../assets/logo.png', __dir__)
|
86
|
-
|
87
|
-
SORT_ORDER = %w[
|
88
|
-
SketchupRequirements
|
89
|
-
SketchupDeprecations
|
90
|
-
SketchupPerformance
|
91
|
-
SketchupSuggestions
|
92
|
-
SketchupBugs
|
93
|
-
].freeze
|
94
|
-
|
95
|
-
DEPARTMENT_DESCRIPTIONS = {
|
96
|
-
'SketchupRequirements' => <<-DESCRIPTION,
|
97
|
-
This is the most important set of checks. They represent a large
|
98
|
-
part of the technical requirements an extension must pass in order
|
99
|
-
to be hosted on Extension Warehouse.
|
100
|
-
|
101
|
-
They have been designed to prevent extensions from conflicting with
|
102
|
-
each other as well as avoiding bad side-effects for the end user.
|
103
|
-
|
104
|
-
Please address these as soon as possible.
|
105
|
-
DESCRIPTION
|
106
|
-
'SketchupDeprecations' => <<-DESCRIPTION,
|
107
|
-
This department checks for usage of deprecated features. It's
|
108
|
-
recommended that you migrate your code away from deprecated features
|
109
|
-
of the SketchUp API.
|
110
|
-
|
111
|
-
This department is not a requirement for submission to
|
112
|
-
Extension Warehouse.
|
113
|
-
DESCRIPTION
|
114
|
-
'SketchupPerformance' => <<-DESCRIPTION,
|
115
|
-
This department looks for known patterns that have noticeable
|
116
|
-
performance impact on SketchUp and/or your extension. It's worth
|
117
|
-
looking into these warnings and investigate whether performance
|
118
|
-
can be improved.
|
119
|
-
|
120
|
-
This department is not a requirement for submission to
|
121
|
-
Extension Warehouse.
|
122
|
-
DESCRIPTION
|
123
|
-
'SketchupSuggestions' => <<-DESCRIPTION,
|
124
|
-
This department is a collection of suggestions for best practices
|
125
|
-
that aim to improve the general quality of your extension. Some of
|
126
|
-
these might be more noisy than the rest of the cops. Disable as
|
127
|
-
needed after reviewing the suggestions.
|
128
|
-
|
129
|
-
This department is not a requirement for submission to
|
130
|
-
Extension Warehouse.
|
131
|
-
DESCRIPTION
|
132
|
-
'SketchupBugs' => <<-DESCRIPTION,
|
133
|
-
This department warns about known bugs in the SketchUp API. It uses
|
134
|
-
the TargetSketchUpVersion configuration to determine if the bug is
|
135
|
-
relevant for your project. This department isn't a collection of all
|
136
|
-
known bugs. But only a subset which can be reasonable detected..
|
137
|
-
|
138
|
-
This department is not a requirement for submission to
|
139
|
-
Extension Warehouse.
|
140
|
-
DESCRIPTION
|
141
|
-
}.freeze
|
142
|
-
|
143
|
-
attr_reader :categories, :files, :summary
|
144
|
-
|
145
|
-
def initialize(categories, files, summary)
|
146
|
-
@categories = sort_categories(categories)
|
147
|
-
@files = files.sort
|
148
|
-
@summary = summary
|
149
|
-
end
|
150
|
-
|
151
|
-
def department(cop_name)
|
152
|
-
cop_name.split('/').first
|
153
|
-
end
|
154
|
-
|
155
|
-
def department_description(cop_name)
|
156
|
-
dep = department(cop_name)
|
157
|
-
text = DEPARTMENT_DESCRIPTIONS[dep] || 'MISSING DESCRIPTION'
|
158
|
-
format_plain_text(text)
|
159
|
-
end
|
160
|
-
|
161
|
-
def department_offense_count(cop_name)
|
162
|
-
dep = department(cop_name)
|
163
|
-
count = 0
|
164
|
-
categories.each { |category, offenses|
|
165
|
-
next unless department(category) == dep
|
166
|
-
|
167
|
-
count += offenses.size
|
168
|
-
}
|
169
|
-
count
|
170
|
-
end
|
171
|
-
|
172
|
-
def new_department?(cop_name)
|
173
|
-
@processed_departments ||= Set.new
|
174
|
-
dep = department(cop_name)
|
175
|
-
unless @processed_departments.include?(dep)
|
176
|
-
@processed_departments << dep
|
177
|
-
return true
|
178
|
-
end
|
179
|
-
false
|
180
|
-
end
|
181
|
-
|
182
|
-
def format_plain_text(text)
|
183
|
-
paragraphs = text.split(/(\n\r|\r\n|\r|\n){2,}/m)
|
184
|
-
"<p>#{paragraphs.join('</p><p>')}</p>"
|
185
|
-
end
|
186
|
-
|
187
|
-
def sort_categories(categories)
|
188
|
-
categories.sort { |a, b|
|
189
|
-
# First sort departments by custom ordering (of importance).
|
190
|
-
# Then sort by cop name.
|
191
|
-
a_department, a_name = a[0].split('/')
|
192
|
-
b_department, b_name = b[0].split('/')
|
193
|
-
# Sort SketchUp cops at the top, then all the rest comes after.
|
194
|
-
# First sorting by department.
|
195
|
-
sort_order_a = SORT_ORDER.index(a_department)
|
196
|
-
sort_order_b = SORT_ORDER.index(b_department)
|
197
|
-
if sort_order_a.nil? && sort_order_b.nil?
|
198
|
-
n = a_department <=> b_department
|
199
|
-
else
|
200
|
-
sort_order_a ||= SORT_ORDER.size
|
201
|
-
sort_order_b ||= SORT_ORDER.size
|
202
|
-
n = sort_order_a <=> sort_order_b
|
203
|
-
end
|
204
|
-
# Them sort by name if departments match.
|
205
|
-
n == 0 ? a_name <=> b_name : n
|
206
|
-
}.to_h
|
207
|
-
end
|
208
|
-
|
209
|
-
# Make Kernel#binding public.
|
210
|
-
def binding # rubocop:disable Lint/UselessMethodDefinition
|
211
|
-
super
|
212
|
-
end
|
213
|
-
|
214
|
-
def decorated_message(offense)
|
215
|
-
offense.message
|
216
|
-
.gsub(/`(.+?)`/) do
|
217
|
-
"<code>#{Regexp.last_match(1)}</code>"
|
218
|
-
end
|
219
|
-
.gsub(/\((http[^ ]+)\)/) do
|
220
|
-
url = Regexp.last_match(1)
|
221
|
-
"<br><a href=\"#{url}\">#{url}</a>"
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
def highlighted_source_line(offense)
|
226
|
-
source_before_highlight(offense) +
|
227
|
-
hightlight_source_tag(offense) +
|
228
|
-
source_after_highlight(offense) +
|
229
|
-
possible_ellipses(offense.location)
|
230
|
-
end
|
231
|
-
|
232
|
-
def hightlight_source_tag(offense)
|
233
|
-
"<span class=\"highlight #{offense.severity}\">" \
|
234
|
-
"#{escape(offense.highlighted_area.source)}" \
|
235
|
-
'</span>'
|
236
|
-
end
|
237
|
-
|
238
|
-
def source_before_highlight(offense)
|
239
|
-
source_line = offense.location.source_line
|
240
|
-
escape(source_line[0...offense.highlighted_area.begin_pos])
|
241
|
-
end
|
242
|
-
|
243
|
-
def source_after_highlight(offense)
|
244
|
-
source_line = offense.location.source_line
|
245
|
-
escape(source_line[offense.highlighted_area.end_pos..])
|
246
|
-
end
|
247
|
-
|
248
|
-
def possible_ellipses(location)
|
249
|
-
location.first_line == location.last_line ? '' : " #{ELLIPSES}"
|
250
|
-
end
|
251
|
-
|
252
|
-
def cop_anchor(cop_name)
|
253
|
-
title = cop_name.downcase
|
254
|
-
title.tr!('/', '_')
|
255
|
-
"offense_#{title}"
|
256
|
-
end
|
257
|
-
|
258
|
-
def escape(string)
|
259
|
-
CGI.escapeHTML(string)
|
260
|
-
end
|
261
|
-
|
262
|
-
def base64_encoded_logo_image
|
263
|
-
image = File.read(LOGO_IMAGE_PATH, binmode: true)
|
264
|
-
Base64.encode64(image)
|
265
|
-
end
|
266
|
-
end
|
267
|
-
end
|
268
|
-
end
|
269
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cgi'
|
4
|
+
require 'erb'
|
5
|
+
require 'ostruct'
|
6
|
+
require 'base64'
|
7
|
+
require 'rubocop/formatter/text_util'
|
8
|
+
|
9
|
+
module RuboCop
|
10
|
+
module Formatter
|
11
|
+
# This formatter saves the output as an html file.
|
12
|
+
class ExtensionReviewFormatter < BaseFormatter
|
13
|
+
ELLIPSES = '<span class="extra-code">...</span>'
|
14
|
+
TEMPLATE_PATH =
|
15
|
+
File.expand_path('../../../../assets/output.html.erb', __dir__)
|
16
|
+
|
17
|
+
Color = Struct.new(:red, :green, :blue, :alpha) do
|
18
|
+
def to_s
|
19
|
+
"rgba(#{values.join(', ')})"
|
20
|
+
end
|
21
|
+
|
22
|
+
def fade_out(amount)
|
23
|
+
dup.tap do |color|
|
24
|
+
color.alpha -= amount
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :categories, :files, :summary
|
30
|
+
|
31
|
+
def initialize(output, options = {})
|
32
|
+
super
|
33
|
+
@categories = {}
|
34
|
+
@files = []
|
35
|
+
@summary = OpenStruct.new(offense_count: 0)
|
36
|
+
end
|
37
|
+
|
38
|
+
def started(target_files)
|
39
|
+
summary.target_files = target_files
|
40
|
+
end
|
41
|
+
|
42
|
+
def file_finished(file, offenses)
|
43
|
+
files << file
|
44
|
+
offenses.each { |offense|
|
45
|
+
# Report only SketchUp related cops.
|
46
|
+
next unless offense.cop_name.start_with?('Sketchup')
|
47
|
+
|
48
|
+
report = OpenStruct.new(path: file, offense: offense)
|
49
|
+
categories[offense.cop_name] ||= []
|
50
|
+
categories[offense.cop_name] << report
|
51
|
+
summary.offense_count += 1
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
def finished(inspected_files)
|
56
|
+
summary.inspected_files = inspected_files
|
57
|
+
|
58
|
+
render_html
|
59
|
+
end
|
60
|
+
|
61
|
+
def render_html
|
62
|
+
context = ERBContext.new(categories, files, summary)
|
63
|
+
|
64
|
+
template = File.read(TEMPLATE_PATH, encoding: Encoding::UTF_8)
|
65
|
+
erb = ERB.new(template, trim_mode: '-')
|
66
|
+
html = erb.result(context.binding)
|
67
|
+
|
68
|
+
output.write html
|
69
|
+
end
|
70
|
+
|
71
|
+
# This class provides helper methods used in the ERB template.
|
72
|
+
class ERBContext
|
73
|
+
include PathUtil
|
74
|
+
include TextUtil
|
75
|
+
|
76
|
+
SEVERITY_COLORS = {
|
77
|
+
refactor: Color.new(0x29, 0x6B, 0xF0, 1.0),
|
78
|
+
convention: Color.new(0x29, 0x6B, 0xF0, 1.0),
|
79
|
+
warning: Color.new(0xED, 0x9C, 0x28, 1.0),
|
80
|
+
error: Color.new(0xD2, 0x32, 0x2D, 1.0),
|
81
|
+
fatal: Color.new(0xD2, 0x32, 0x2D, 1.0),
|
82
|
+
}.freeze
|
83
|
+
|
84
|
+
LOGO_IMAGE_PATH =
|
85
|
+
File.expand_path('../../../../assets/logo.png', __dir__)
|
86
|
+
|
87
|
+
SORT_ORDER = %w[
|
88
|
+
SketchupRequirements
|
89
|
+
SketchupDeprecations
|
90
|
+
SketchupPerformance
|
91
|
+
SketchupSuggestions
|
92
|
+
SketchupBugs
|
93
|
+
].freeze
|
94
|
+
|
95
|
+
DEPARTMENT_DESCRIPTIONS = {
|
96
|
+
'SketchupRequirements' => <<-DESCRIPTION,
|
97
|
+
This is the most important set of checks. They represent a large
|
98
|
+
part of the technical requirements an extension must pass in order
|
99
|
+
to be hosted on Extension Warehouse.
|
100
|
+
|
101
|
+
They have been designed to prevent extensions from conflicting with
|
102
|
+
each other as well as avoiding bad side-effects for the end user.
|
103
|
+
|
104
|
+
Please address these as soon as possible.
|
105
|
+
DESCRIPTION
|
106
|
+
'SketchupDeprecations' => <<-DESCRIPTION,
|
107
|
+
This department checks for usage of deprecated features. It's
|
108
|
+
recommended that you migrate your code away from deprecated features
|
109
|
+
of the SketchUp API.
|
110
|
+
|
111
|
+
This department is not a requirement for submission to
|
112
|
+
Extension Warehouse.
|
113
|
+
DESCRIPTION
|
114
|
+
'SketchupPerformance' => <<-DESCRIPTION,
|
115
|
+
This department looks for known patterns that have noticeable
|
116
|
+
performance impact on SketchUp and/or your extension. It's worth
|
117
|
+
looking into these warnings and investigate whether performance
|
118
|
+
can be improved.
|
119
|
+
|
120
|
+
This department is not a requirement for submission to
|
121
|
+
Extension Warehouse.
|
122
|
+
DESCRIPTION
|
123
|
+
'SketchupSuggestions' => <<-DESCRIPTION,
|
124
|
+
This department is a collection of suggestions for best practices
|
125
|
+
that aim to improve the general quality of your extension. Some of
|
126
|
+
these might be more noisy than the rest of the cops. Disable as
|
127
|
+
needed after reviewing the suggestions.
|
128
|
+
|
129
|
+
This department is not a requirement for submission to
|
130
|
+
Extension Warehouse.
|
131
|
+
DESCRIPTION
|
132
|
+
'SketchupBugs' => <<-DESCRIPTION,
|
133
|
+
This department warns about known bugs in the SketchUp API. It uses
|
134
|
+
the TargetSketchUpVersion configuration to determine if the bug is
|
135
|
+
relevant for your project. This department isn't a collection of all
|
136
|
+
known bugs. But only a subset which can be reasonable detected..
|
137
|
+
|
138
|
+
This department is not a requirement for submission to
|
139
|
+
Extension Warehouse.
|
140
|
+
DESCRIPTION
|
141
|
+
}.freeze
|
142
|
+
|
143
|
+
attr_reader :categories, :files, :summary
|
144
|
+
|
145
|
+
def initialize(categories, files, summary)
|
146
|
+
@categories = sort_categories(categories)
|
147
|
+
@files = files.sort
|
148
|
+
@summary = summary
|
149
|
+
end
|
150
|
+
|
151
|
+
def department(cop_name)
|
152
|
+
cop_name.split('/').first
|
153
|
+
end
|
154
|
+
|
155
|
+
def department_description(cop_name)
|
156
|
+
dep = department(cop_name)
|
157
|
+
text = DEPARTMENT_DESCRIPTIONS[dep] || 'MISSING DESCRIPTION'
|
158
|
+
format_plain_text(text)
|
159
|
+
end
|
160
|
+
|
161
|
+
def department_offense_count(cop_name)
|
162
|
+
dep = department(cop_name)
|
163
|
+
count = 0
|
164
|
+
categories.each { |category, offenses|
|
165
|
+
next unless department(category) == dep
|
166
|
+
|
167
|
+
count += offenses.size
|
168
|
+
}
|
169
|
+
count
|
170
|
+
end
|
171
|
+
|
172
|
+
def new_department?(cop_name)
|
173
|
+
@processed_departments ||= Set.new
|
174
|
+
dep = department(cop_name)
|
175
|
+
unless @processed_departments.include?(dep)
|
176
|
+
@processed_departments << dep
|
177
|
+
return true
|
178
|
+
end
|
179
|
+
false
|
180
|
+
end
|
181
|
+
|
182
|
+
def format_plain_text(text)
|
183
|
+
paragraphs = text.split(/(\n\r|\r\n|\r|\n){2,}/m)
|
184
|
+
"<p>#{paragraphs.join('</p><p>')}</p>"
|
185
|
+
end
|
186
|
+
|
187
|
+
def sort_categories(categories)
|
188
|
+
categories.sort { |a, b|
|
189
|
+
# First sort departments by custom ordering (of importance).
|
190
|
+
# Then sort by cop name.
|
191
|
+
a_department, a_name = a[0].split('/')
|
192
|
+
b_department, b_name = b[0].split('/')
|
193
|
+
# Sort SketchUp cops at the top, then all the rest comes after.
|
194
|
+
# First sorting by department.
|
195
|
+
sort_order_a = SORT_ORDER.index(a_department)
|
196
|
+
sort_order_b = SORT_ORDER.index(b_department)
|
197
|
+
if sort_order_a.nil? && sort_order_b.nil?
|
198
|
+
n = a_department <=> b_department
|
199
|
+
else
|
200
|
+
sort_order_a ||= SORT_ORDER.size
|
201
|
+
sort_order_b ||= SORT_ORDER.size
|
202
|
+
n = sort_order_a <=> sort_order_b
|
203
|
+
end
|
204
|
+
# Them sort by name if departments match.
|
205
|
+
n == 0 ? a_name <=> b_name : n
|
206
|
+
}.to_h
|
207
|
+
end
|
208
|
+
|
209
|
+
# Make Kernel#binding public.
|
210
|
+
def binding # rubocop:disable Lint/UselessMethodDefinition
|
211
|
+
super
|
212
|
+
end
|
213
|
+
|
214
|
+
def decorated_message(offense)
|
215
|
+
offense.message
|
216
|
+
.gsub(/`(.+?)`/) do
|
217
|
+
"<code>#{Regexp.last_match(1)}</code>"
|
218
|
+
end
|
219
|
+
.gsub(/\((http[^ ]+)\)/) do
|
220
|
+
url = Regexp.last_match(1)
|
221
|
+
"<br><a href=\"#{url}\">#{url}</a>"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
def highlighted_source_line(offense)
|
226
|
+
source_before_highlight(offense) +
|
227
|
+
hightlight_source_tag(offense) +
|
228
|
+
source_after_highlight(offense) +
|
229
|
+
possible_ellipses(offense.location)
|
230
|
+
end
|
231
|
+
|
232
|
+
def hightlight_source_tag(offense)
|
233
|
+
"<span class=\"highlight #{offense.severity}\">" \
|
234
|
+
"#{escape(offense.highlighted_area.source)}" \
|
235
|
+
'</span>'
|
236
|
+
end
|
237
|
+
|
238
|
+
def source_before_highlight(offense)
|
239
|
+
source_line = offense.location.source_line
|
240
|
+
escape(source_line[0...offense.highlighted_area.begin_pos])
|
241
|
+
end
|
242
|
+
|
243
|
+
def source_after_highlight(offense)
|
244
|
+
source_line = offense.location.source_line
|
245
|
+
escape(source_line[offense.highlighted_area.end_pos..])
|
246
|
+
end
|
247
|
+
|
248
|
+
def possible_ellipses(location)
|
249
|
+
location.first_line == location.last_line ? '' : " #{ELLIPSES}"
|
250
|
+
end
|
251
|
+
|
252
|
+
def cop_anchor(cop_name)
|
253
|
+
title = cop_name.downcase
|
254
|
+
title.tr!('/', '_')
|
255
|
+
"offense_#{title}"
|
256
|
+
end
|
257
|
+
|
258
|
+
def escape(string)
|
259
|
+
CGI.escapeHTML(string)
|
260
|
+
end
|
261
|
+
|
262
|
+
def base64_encoded_logo_image
|
263
|
+
image = File.read(LOGO_IMAGE_PATH, binmode: true)
|
264
|
+
Base64.encode64(image)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rubocop'
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
module SketchUp
|
7
|
+
class Generator < RuboCop::Cop::Generator
|
8
|
+
def source_path
|
9
|
+
department = snake_case(badge.department.to_s).gsub(/^sketchup_/, '')
|
10
|
+
File.join(
|
11
|
+
'lib',
|
12
|
+
'rubocop',
|
13
|
+
'sketchup', # We have our cops nested one extra level.
|
14
|
+
'cop',
|
15
|
+
department,
|
16
|
+
"#{snake_case(badge.cop_name.to_s)}.rb"
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,19 +1,19 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RuboCop
|
4
|
-
# Ripped directly from rubocop-rspec.
|
5
|
-
module SketchUp
|
6
|
-
# Because RuboCop doesn't yet support plugins, we have to monkey patch in a
|
7
|
-
# bit of our configuration.
|
8
|
-
module Inject
|
9
|
-
def self.defaults!
|
10
|
-
path = CONFIG_DEFAULT.to_s
|
11
|
-
hash = ConfigLoader.send(:load_yaml_configuration, path)
|
12
|
-
config = RuboCop::Config.new(hash, path)
|
13
|
-
puts "configuration from #{path}" if ConfigLoader.debug?
|
14
|
-
config = ConfigLoader.merge_with_default(config, path)
|
15
|
-
ConfigLoader.instance_variable_set(:@default_configuration, config)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
# Ripped directly from rubocop-rspec.
|
5
|
+
module SketchUp
|
6
|
+
# Because RuboCop doesn't yet support plugins, we have to monkey patch in a
|
7
|
+
# bit of our configuration.
|
8
|
+
module Inject
|
9
|
+
def self.defaults!
|
10
|
+
path = CONFIG_DEFAULT.to_s
|
11
|
+
hash = ConfigLoader.send(:load_yaml_configuration, path)
|
12
|
+
config = RuboCop::Config.new(hash, path)
|
13
|
+
puts "configuration from #{path}" if ConfigLoader.debug?
|
14
|
+
config = ConfigLoader.merge_with_default(config, path)
|
15
|
+
ConfigLoader.instance_variable_set(:@default_configuration, config)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|