rubocop-sketchup 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +19 -19
- data/assets/output.html.erb +301 -301
- data/config/default.yml +355 -355
- data/lib/rubocop/sketchup/config.rb +63 -63
- 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/exit.rb +32 -32
- data/lib/rubocop/sketchup/cop/requirements/extension_namespace.rb +108 -108
- 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/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 +163 -163
- data/lib/rubocop/sketchup/cop/suggestions/add_group.rb +49 -49
- data/lib/rubocop/sketchup/cop/suggestions/compatibility.rb +117 -117
- 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 +103 -103
- data/lib/rubocop/sketchup/cop/suggestions/sketchup_find_support_file.rb +39 -39
- data/lib/rubocop/sketchup/cop/suggestions/tool_drawing_bounds.rb +44 -44
- data/lib/rubocop/sketchup/cop/suggestions/tool_invalidate.rb +66 -66
- 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 +111 -111
- 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 +738 -738
- data/lib/rubocop/sketchup/formatter/extension_review.rb +259 -259
- data/lib/rubocop/sketchup/inject.rb +19 -19
- data/lib/rubocop/sketchup/namespace.rb +47 -47
- data/lib/rubocop/sketchup/namespace_checker.rb +46 -46
- data/lib/rubocop/sketchup/no_comment_disable.rb +17 -17
- data/lib/rubocop/sketchup/range_help.rb +52 -52
- data/lib/rubocop/sketchup/sketchup_version.rb +87 -87
- data/lib/rubocop/sketchup/tool_checker.rb +43 -43
- data/lib/rubocop/sketchup/version.rb +5 -5
- data/lib/rubocop/sketchup.rb +12 -12
- data/lib/rubocop-sketchup.rb +48 -48
- data/rubocop-sketchup.gemspec +27 -27
- metadata +4 -4
@@ -1,259 +1,259 @@
|
|
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>'.freeze
|
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, nil, '-')
|
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
|
-
].freeze
|
93
|
-
|
94
|
-
DEPARTMENT_DESCRIPTIONS = {
|
95
|
-
'SketchupRequirements' => <<-DESCRIPTION,
|
96
|
-
This is the most important set of checks. They represent a large
|
97
|
-
part of the technical requirements an extension must pass in order
|
98
|
-
to be hosted on Extension Warehouse.
|
99
|
-
|
100
|
-
They have been designed to prevent extensions from conflicting with
|
101
|
-
each other as well as avoiding bad side-effects for the end user.
|
102
|
-
|
103
|
-
Please address these as soon as possible.
|
104
|
-
DESCRIPTION
|
105
|
-
'SketchupDeprecations' => <<-DESCRIPTION,
|
106
|
-
This department checks for usage of deprecated features. It's
|
107
|
-
recommended that you migrate your code away from deprecated features
|
108
|
-
of the SketchUp API.
|
109
|
-
|
110
|
-
This department is not a requirement for submission to
|
111
|
-
Extension Warehouse.
|
112
|
-
DESCRIPTION
|
113
|
-
'SketchupPerformance' => <<-DESCRIPTION,
|
114
|
-
This department looks for known patterns that have noticeable
|
115
|
-
performance impact on SketchUp and/or your extension. It's worth
|
116
|
-
looking into these warnings and investigate whether performance
|
117
|
-
can be improved.
|
118
|
-
|
119
|
-
This department is not a requirement for submission to
|
120
|
-
Extension Warehouse.
|
121
|
-
DESCRIPTION
|
122
|
-
'SketchupSuggestions' => <<-DESCRIPTION,
|
123
|
-
This department is a collection of suggestions for best practices
|
124
|
-
that aim to improve the general quality of your extension. Some of
|
125
|
-
these might be more noisy than the rest of the cops. Disable as
|
126
|
-
needed after reviewing the suggestions.
|
127
|
-
|
128
|
-
This department is not a requirement for submission to
|
129
|
-
Extension Warehouse.
|
130
|
-
DESCRIPTION
|
131
|
-
}.freeze
|
132
|
-
|
133
|
-
attr_reader :categories, :files, :summary
|
134
|
-
|
135
|
-
def initialize(categories, files, summary)
|
136
|
-
@categories = sort_categories(categories)
|
137
|
-
@files = files.sort
|
138
|
-
@summary = summary
|
139
|
-
end
|
140
|
-
|
141
|
-
def department(cop_name)
|
142
|
-
cop_name.split('/').first
|
143
|
-
end
|
144
|
-
|
145
|
-
def department_description(cop_name)
|
146
|
-
dep = department(cop_name)
|
147
|
-
text = DEPARTMENT_DESCRIPTIONS[dep] || 'MISSING DESCRIPTION'
|
148
|
-
format_plain_text(text)
|
149
|
-
end
|
150
|
-
|
151
|
-
def department_offense_count(cop_name)
|
152
|
-
dep = department(cop_name)
|
153
|
-
count = 0
|
154
|
-
categories.each { |category, offenses|
|
155
|
-
next unless department(category) == dep
|
156
|
-
|
157
|
-
count += offenses.size
|
158
|
-
}
|
159
|
-
count
|
160
|
-
end
|
161
|
-
|
162
|
-
def new_department?(cop_name)
|
163
|
-
@processed_departments ||= Set.new
|
164
|
-
dep = department(cop_name)
|
165
|
-
unless @processed_departments.include?(dep)
|
166
|
-
@processed_departments << dep
|
167
|
-
return true
|
168
|
-
end
|
169
|
-
false
|
170
|
-
end
|
171
|
-
|
172
|
-
def format_plain_text(text)
|
173
|
-
paragraphs = text.split(/(\n\r|\r\n|\r|\n){2,}/m)
|
174
|
-
"<p>#{paragraphs.join('</p><p>')}</p>"
|
175
|
-
end
|
176
|
-
|
177
|
-
def sort_categories(categories)
|
178
|
-
categories.sort { |a, b|
|
179
|
-
# First sort departments by custom ordering (of importance).
|
180
|
-
# Then sort by cop name.
|
181
|
-
a_department, a_name = a[0].split('/')
|
182
|
-
b_department, b_name = b[0].split('/')
|
183
|
-
# Sort SketchUp cops at the top, then all the rest comes after.
|
184
|
-
# First sorting by department.
|
185
|
-
sort_order_a = SORT_ORDER.index(a_department)
|
186
|
-
sort_order_b = SORT_ORDER.index(b_department)
|
187
|
-
if sort_order_a.nil? && sort_order_b.nil?
|
188
|
-
n = a_department <=> b_department
|
189
|
-
else
|
190
|
-
sort_order_a ||= SORT_ORDER.size
|
191
|
-
sort_order_b ||= SORT_ORDER.size
|
192
|
-
n = sort_order_a <=> sort_order_b
|
193
|
-
end
|
194
|
-
# Them sort by name if departments match.
|
195
|
-
n == 0 ? a_name <=> b_name : n
|
196
|
-
}.to_h
|
197
|
-
end
|
198
|
-
|
199
|
-
# Make Kernel#binding public.
|
200
|
-
def binding
|
201
|
-
super
|
202
|
-
end
|
203
|
-
|
204
|
-
def decorated_message(offense)
|
205
|
-
offense.message
|
206
|
-
.gsub(/`(.+?)`/) do
|
207
|
-
"<code>#{Regexp.last_match(1)}</code>"
|
208
|
-
end
|
209
|
-
.gsub(/\((http[^ ]+)\)/) do
|
210
|
-
url = Regexp.last_match(1)
|
211
|
-
"<br><a href=\"#{url}\">#{url}</a>"
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
def highlighted_source_line(offense)
|
216
|
-
source_before_highlight(offense) +
|
217
|
-
hightlight_source_tag(offense) +
|
218
|
-
source_after_highlight(offense) +
|
219
|
-
possible_ellipses(offense.location)
|
220
|
-
end
|
221
|
-
|
222
|
-
def hightlight_source_tag(offense)
|
223
|
-
"<span class=\"highlight #{offense.severity}\">" \
|
224
|
-
"#{escape(offense.highlighted_area.source)}" \
|
225
|
-
'</span>'
|
226
|
-
end
|
227
|
-
|
228
|
-
def source_before_highlight(offense)
|
229
|
-
source_line = offense.location.source_line
|
230
|
-
escape(source_line[0...offense.highlighted_area.begin_pos])
|
231
|
-
end
|
232
|
-
|
233
|
-
def source_after_highlight(offense)
|
234
|
-
source_line = offense.location.source_line
|
235
|
-
escape(source_line[offense.highlighted_area.end_pos..-1])
|
236
|
-
end
|
237
|
-
|
238
|
-
def possible_ellipses(location)
|
239
|
-
location.first_line == location.last_line ? '' : " #{ELLIPSES}"
|
240
|
-
end
|
241
|
-
|
242
|
-
def cop_anchor(cop_name)
|
243
|
-
title = cop_name.downcase
|
244
|
-
title.tr!('/', '_')
|
245
|
-
"offense_#{title}"
|
246
|
-
end
|
247
|
-
|
248
|
-
def escape(string)
|
249
|
-
CGI.escapeHTML(string)
|
250
|
-
end
|
251
|
-
|
252
|
-
def base64_encoded_logo_image
|
253
|
-
image = File.read(LOGO_IMAGE_PATH, binmode: true)
|
254
|
-
Base64.encode64(image)
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
259
|
-
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>'.freeze
|
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, nil, '-')
|
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
|
+
].freeze
|
93
|
+
|
94
|
+
DEPARTMENT_DESCRIPTIONS = {
|
95
|
+
'SketchupRequirements' => <<-DESCRIPTION,
|
96
|
+
This is the most important set of checks. They represent a large
|
97
|
+
part of the technical requirements an extension must pass in order
|
98
|
+
to be hosted on Extension Warehouse.
|
99
|
+
|
100
|
+
They have been designed to prevent extensions from conflicting with
|
101
|
+
each other as well as avoiding bad side-effects for the end user.
|
102
|
+
|
103
|
+
Please address these as soon as possible.
|
104
|
+
DESCRIPTION
|
105
|
+
'SketchupDeprecations' => <<-DESCRIPTION,
|
106
|
+
This department checks for usage of deprecated features. It's
|
107
|
+
recommended that you migrate your code away from deprecated features
|
108
|
+
of the SketchUp API.
|
109
|
+
|
110
|
+
This department is not a requirement for submission to
|
111
|
+
Extension Warehouse.
|
112
|
+
DESCRIPTION
|
113
|
+
'SketchupPerformance' => <<-DESCRIPTION,
|
114
|
+
This department looks for known patterns that have noticeable
|
115
|
+
performance impact on SketchUp and/or your extension. It's worth
|
116
|
+
looking into these warnings and investigate whether performance
|
117
|
+
can be improved.
|
118
|
+
|
119
|
+
This department is not a requirement for submission to
|
120
|
+
Extension Warehouse.
|
121
|
+
DESCRIPTION
|
122
|
+
'SketchupSuggestions' => <<-DESCRIPTION,
|
123
|
+
This department is a collection of suggestions for best practices
|
124
|
+
that aim to improve the general quality of your extension. Some of
|
125
|
+
these might be more noisy than the rest of the cops. Disable as
|
126
|
+
needed after reviewing the suggestions.
|
127
|
+
|
128
|
+
This department is not a requirement for submission to
|
129
|
+
Extension Warehouse.
|
130
|
+
DESCRIPTION
|
131
|
+
}.freeze
|
132
|
+
|
133
|
+
attr_reader :categories, :files, :summary
|
134
|
+
|
135
|
+
def initialize(categories, files, summary)
|
136
|
+
@categories = sort_categories(categories)
|
137
|
+
@files = files.sort
|
138
|
+
@summary = summary
|
139
|
+
end
|
140
|
+
|
141
|
+
def department(cop_name)
|
142
|
+
cop_name.split('/').first
|
143
|
+
end
|
144
|
+
|
145
|
+
def department_description(cop_name)
|
146
|
+
dep = department(cop_name)
|
147
|
+
text = DEPARTMENT_DESCRIPTIONS[dep] || 'MISSING DESCRIPTION'
|
148
|
+
format_plain_text(text)
|
149
|
+
end
|
150
|
+
|
151
|
+
def department_offense_count(cop_name)
|
152
|
+
dep = department(cop_name)
|
153
|
+
count = 0
|
154
|
+
categories.each { |category, offenses|
|
155
|
+
next unless department(category) == dep
|
156
|
+
|
157
|
+
count += offenses.size
|
158
|
+
}
|
159
|
+
count
|
160
|
+
end
|
161
|
+
|
162
|
+
def new_department?(cop_name)
|
163
|
+
@processed_departments ||= Set.new
|
164
|
+
dep = department(cop_name)
|
165
|
+
unless @processed_departments.include?(dep)
|
166
|
+
@processed_departments << dep
|
167
|
+
return true
|
168
|
+
end
|
169
|
+
false
|
170
|
+
end
|
171
|
+
|
172
|
+
def format_plain_text(text)
|
173
|
+
paragraphs = text.split(/(\n\r|\r\n|\r|\n){2,}/m)
|
174
|
+
"<p>#{paragraphs.join('</p><p>')}</p>"
|
175
|
+
end
|
176
|
+
|
177
|
+
def sort_categories(categories)
|
178
|
+
categories.sort { |a, b|
|
179
|
+
# First sort departments by custom ordering (of importance).
|
180
|
+
# Then sort by cop name.
|
181
|
+
a_department, a_name = a[0].split('/')
|
182
|
+
b_department, b_name = b[0].split('/')
|
183
|
+
# Sort SketchUp cops at the top, then all the rest comes after.
|
184
|
+
# First sorting by department.
|
185
|
+
sort_order_a = SORT_ORDER.index(a_department)
|
186
|
+
sort_order_b = SORT_ORDER.index(b_department)
|
187
|
+
if sort_order_a.nil? && sort_order_b.nil?
|
188
|
+
n = a_department <=> b_department
|
189
|
+
else
|
190
|
+
sort_order_a ||= SORT_ORDER.size
|
191
|
+
sort_order_b ||= SORT_ORDER.size
|
192
|
+
n = sort_order_a <=> sort_order_b
|
193
|
+
end
|
194
|
+
# Them sort by name if departments match.
|
195
|
+
n == 0 ? a_name <=> b_name : n
|
196
|
+
}.to_h
|
197
|
+
end
|
198
|
+
|
199
|
+
# Make Kernel#binding public.
|
200
|
+
def binding
|
201
|
+
super
|
202
|
+
end
|
203
|
+
|
204
|
+
def decorated_message(offense)
|
205
|
+
offense.message
|
206
|
+
.gsub(/`(.+?)`/) do
|
207
|
+
"<code>#{Regexp.last_match(1)}</code>"
|
208
|
+
end
|
209
|
+
.gsub(/\((http[^ ]+)\)/) do
|
210
|
+
url = Regexp.last_match(1)
|
211
|
+
"<br><a href=\"#{url}\">#{url}</a>"
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
def highlighted_source_line(offense)
|
216
|
+
source_before_highlight(offense) +
|
217
|
+
hightlight_source_tag(offense) +
|
218
|
+
source_after_highlight(offense) +
|
219
|
+
possible_ellipses(offense.location)
|
220
|
+
end
|
221
|
+
|
222
|
+
def hightlight_source_tag(offense)
|
223
|
+
"<span class=\"highlight #{offense.severity}\">" \
|
224
|
+
"#{escape(offense.highlighted_area.source)}" \
|
225
|
+
'</span>'
|
226
|
+
end
|
227
|
+
|
228
|
+
def source_before_highlight(offense)
|
229
|
+
source_line = offense.location.source_line
|
230
|
+
escape(source_line[0...offense.highlighted_area.begin_pos])
|
231
|
+
end
|
232
|
+
|
233
|
+
def source_after_highlight(offense)
|
234
|
+
source_line = offense.location.source_line
|
235
|
+
escape(source_line[offense.highlighted_area.end_pos..-1])
|
236
|
+
end
|
237
|
+
|
238
|
+
def possible_ellipses(location)
|
239
|
+
location.first_line == location.last_line ? '' : " #{ELLIPSES}"
|
240
|
+
end
|
241
|
+
|
242
|
+
def cop_anchor(cop_name)
|
243
|
+
title = cop_name.downcase
|
244
|
+
title.tr!('/', '_')
|
245
|
+
"offense_#{title}"
|
246
|
+
end
|
247
|
+
|
248
|
+
def escape(string)
|
249
|
+
CGI.escapeHTML(string)
|
250
|
+
end
|
251
|
+
|
252
|
+
def base64_encoded_logo_image
|
253
|
+
image = File.read(LOGO_IMAGE_PATH, binmode: true)
|
254
|
+
Base64.encode64(image)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
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
|
@@ -1,47 +1,47 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RuboCop
|
4
|
-
module SketchUp
|
5
|
-
class Namespace
|
6
|
-
|
7
|
-
attr_reader :namespace
|
8
|
-
|
9
|
-
SEPARATOR = '::'.freeze
|
10
|
-
|
11
|
-
# @param [String] namespace
|
12
|
-
def initialize(namespace)
|
13
|
-
raise TypeError unless namespace.is_a?(String)
|
14
|
-
|
15
|
-
@namespace = namespace
|
16
|
-
end
|
17
|
-
|
18
|
-
# Get the first component of a namespace relative to Object.
|
19
|
-
# May return 'Object' if the namespace is in the global namespace.
|
20
|
-
def first
|
21
|
-
parts.find { |name| name != 'Object' } || 'Object'
|
22
|
-
end
|
23
|
-
|
24
|
-
# Get a namespace string that is relative to Object.
|
25
|
-
def from_root
|
26
|
-
items = parts
|
27
|
-
items.shift if items.size > 1 && items.first == 'Object'
|
28
|
-
items.join(SEPARATOR)
|
29
|
-
end
|
30
|
-
|
31
|
-
def join(other)
|
32
|
-
self.class.new("#{@namespace}#{SEPARATOR}#{other}")
|
33
|
-
end
|
34
|
-
|
35
|
-
# Get the first component of a namespace relative to Object.
|
36
|
-
# May return 'Object' if the namespace is in the global namespace.
|
37
|
-
def parts
|
38
|
-
namespace.split(SEPARATOR)
|
39
|
-
end
|
40
|
-
|
41
|
-
def top_level?
|
42
|
-
%w[Kernel Object].include?(parts.first)
|
43
|
-
end
|
44
|
-
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module SketchUp
|
5
|
+
class Namespace
|
6
|
+
|
7
|
+
attr_reader :namespace
|
8
|
+
|
9
|
+
SEPARATOR = '::'.freeze
|
10
|
+
|
11
|
+
# @param [String] namespace
|
12
|
+
def initialize(namespace)
|
13
|
+
raise TypeError unless namespace.is_a?(String)
|
14
|
+
|
15
|
+
@namespace = namespace
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get the first component of a namespace relative to Object.
|
19
|
+
# May return 'Object' if the namespace is in the global namespace.
|
20
|
+
def first
|
21
|
+
parts.find { |name| name != 'Object' } || 'Object'
|
22
|
+
end
|
23
|
+
|
24
|
+
# Get a namespace string that is relative to Object.
|
25
|
+
def from_root
|
26
|
+
items = parts
|
27
|
+
items.shift if items.size > 1 && items.first == 'Object'
|
28
|
+
items.join(SEPARATOR)
|
29
|
+
end
|
30
|
+
|
31
|
+
def join(other)
|
32
|
+
self.class.new("#{@namespace}#{SEPARATOR}#{other}")
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get the first component of a namespace relative to Object.
|
36
|
+
# May return 'Object' if the namespace is in the global namespace.
|
37
|
+
def parts
|
38
|
+
namespace.split(SEPARATOR)
|
39
|
+
end
|
40
|
+
|
41
|
+
def top_level?
|
42
|
+
%w[Kernel Object].include?(parts.first)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|