rubocop-solidus 0.1.2 → 0.1.4

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.
@@ -0,0 +1,322 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yard'
4
+ require 'rubocop'
5
+ require 'rubocop-solidus'
6
+
7
+ YARD::Rake::YardocTask.new(:yard_for_generate_documentation) do |task|
8
+ task.files = ['lib/rubocop/cop/**/*.rb']
9
+ task.options = ['--no-output']
10
+ end
11
+
12
+ desc('Generate docs of all cops departments')
13
+ task generate_cops_documentation: :yard_for_generate_documentation do
14
+ def cops_of_department(cops, department)
15
+ cops.with_department(department).sort!
16
+ end
17
+
18
+ def cops_body(config, cop, description, examples_objects, pars)
19
+ content = h2(cop.cop_name)
20
+ content << required_ruby_version(cop)
21
+ content << properties(config, cop)
22
+ content << "#{description}\n"
23
+ content << examples(examples_objects) if examples_objects.count.positive?
24
+ content << configurations(pars)
25
+ content << references(config, cop)
26
+ content
27
+ end
28
+
29
+ def examples(examples_object)
30
+ examples_object.each_with_object(h3('Examples').dup) do |example, content|
31
+ content << h4(example.name) unless example.name == ''
32
+ content << code_example(example)
33
+ end
34
+ end
35
+
36
+ def required_ruby_version(cop)
37
+ return '' unless cop.respond_to?(:required_minimum_ruby_version)
38
+
39
+ <<~NOTE
40
+ !!! Note
41
+
42
+ Required Ruby version: #{cop.required_minimum_ruby_version}
43
+
44
+ NOTE
45
+ end
46
+
47
+ def properties(config, cop)
48
+ header = [
49
+ 'Enabled by default', 'Safe', 'Supports autocorrection', 'VersionAdded',
50
+ 'VersionChanged', 'Required Solidus Version'
51
+ ]
52
+ config = config.for_cop(cop)
53
+ safe_auto_correct = config.fetch('SafeAutoCorrect', true)
54
+ autocorrect = if cop.support_autocorrect?
55
+ "Yes #{'(Unsafe)' unless safe_auto_correct}"
56
+ else
57
+ 'No'
58
+ end
59
+ minimum_solidus_version = if cop.respond_to?(:required_minimum_solidus_version)
60
+ cop.required_minimum_solidus_version
61
+ else
62
+ '-'
63
+ end
64
+ content = [[
65
+ config.fetch('Enabled') ? 'Enabled' : 'Disabled',
66
+ config.fetch('Safe', true) ? 'Yes' : 'No',
67
+ autocorrect,
68
+ config.fetch('VersionAdded', '-'),
69
+ config.fetch('VersionChanged', '-'),
70
+ minimum_solidus_version
71
+ ]]
72
+ "#{to_table(header, content)}\n"
73
+ end
74
+
75
+ def h2(title)
76
+ content = +"\n"
77
+ content << "## #{title}\n"
78
+ content << "\n"
79
+ content
80
+ end
81
+
82
+ def h3(title)
83
+ content = +"\n"
84
+ content << "### #{title}\n"
85
+ content << "\n"
86
+ content
87
+ end
88
+
89
+ def h4(title)
90
+ content = +"#### #{title}\n"
91
+ content << "\n"
92
+ content
93
+ end
94
+
95
+ def code_example(ruby_code)
96
+ content = +"```ruby\n"
97
+ content << ruby_code.text
98
+ .gsub('@good', '# good').gsub('@bad', '# bad').strip
99
+ content << "\n```\n"
100
+ content
101
+ end
102
+
103
+ def configurations(pars)
104
+ return '' if pars.empty?
105
+
106
+ header = ['Name', 'Default value', 'Configurable values']
107
+ configs = pars.each_key.reject { |key| key.start_with?('Supported') }
108
+ content = configs.map do |name|
109
+ configurable = configurable_values(pars, name)
110
+ default = format_table_value(pars[name])
111
+ [name, default, configurable]
112
+ end
113
+
114
+ h3('Configurable attributes') + to_table(header, content)
115
+ end
116
+
117
+ # rubocop:disable Metrics/CyclomaticComplexity
118
+ def configurable_values(pars, name)
119
+ case name
120
+ when /^Enforced/
121
+ supported_style_name = RuboCop::Cop::Util.to_supported_styles(name)
122
+ format_table_value(pars[supported_style_name])
123
+ when 'IndentationWidth'
124
+ 'Integer'
125
+ when 'Database'
126
+ format_table_value(pars['SupportedDatabases'])
127
+ else
128
+ case pars[name]
129
+ when String
130
+ 'String'
131
+ when Integer
132
+ 'Integer'
133
+ when Float
134
+ 'Float'
135
+ when true, false
136
+ 'Boolean'
137
+ when Array
138
+ 'Array'
139
+ else
140
+ ''
141
+ end
142
+ end
143
+ end
144
+ # rubocop:enable Metrics/CyclomaticComplexity
145
+
146
+ def to_table(header, content)
147
+ table = [
148
+ header.join(' | '),
149
+ Array.new(header.size, '---').join(' | ')
150
+ ]
151
+ table.concat(content.map { |c| c.join(' | ') })
152
+ "#{table.join("\n")}\n"
153
+ end
154
+
155
+ def format_table_value(val)
156
+ value =
157
+ case val
158
+ when Array
159
+ if val.empty?
160
+ '`[]`'
161
+ else
162
+ val.map { |config| format_table_value(config) }.join(', ')
163
+ end
164
+ else
165
+ "`#{val.nil? ? '<none>' : val}`"
166
+ end
167
+ value.gsub("#{Dir.pwd}/", '').rstrip
168
+ end
169
+
170
+ def references(config, cop)
171
+ cop_config = config.for_cop(cop)
172
+ urls = RuboCop::Cop::MessageAnnotator.new(
173
+ config, cop.name, cop_config, {}
174
+ ).urls
175
+ return '' if urls.empty?
176
+
177
+ content = h3('References')
178
+ content << urls.map { |url| "* [#{url}](#{url})" }.join("\n")
179
+ content << "\n"
180
+ content
181
+ end
182
+
183
+ def print_cops_of_department(cops, department, config)
184
+ selected_cops = cops_of_department(cops, department).select do |cop|
185
+ cop.to_s.start_with?('RuboCop::Cop::Solidus')
186
+ end
187
+ return if selected_cops.empty?
188
+
189
+ content = +"# #{department}\n"
190
+ selected_cops.each do |cop|
191
+ content << print_cop_with_doc(cop, config)
192
+ end
193
+ file_name = "#{Dir.pwd}/docs/cops_#{department.downcase}.md"
194
+ File.open(file_name, 'w') do |file|
195
+ puts "* generated #{file_name}"
196
+ file.write("#{content.strip}\n")
197
+ end
198
+ end
199
+
200
+ def print_cop_with_doc(cop, config)
201
+ t = config.for_cop(cop)
202
+ non_display_keys = %w[Description Enabled StyleGuide Reference Safe SafeAutoCorrect VersionAdded
203
+ VersionChanged]
204
+ pars = t.reject { |k| non_display_keys.include?(k) }
205
+ description = 'No documentation'
206
+ examples_object = []
207
+ YARD::Registry.all(:class).detect do |code_object|
208
+ next unless RuboCop::Cop::Badge.for(code_object.to_s) == cop.badge
209
+
210
+ description = code_object.docstring unless code_object.docstring.blank?
211
+ examples_object = code_object.tags('example')
212
+ end
213
+ cops_body(config, cop, description, examples_object, pars)
214
+ end
215
+
216
+ # rubocop:disable Metrics/AbcSize
217
+ def table_of_content_for_department(cops, department)
218
+ selected_cops = cops_of_department(cops, department.to_sym).select do |cop|
219
+ cop.to_s.start_with?('RuboCop::Cop::Solidus')
220
+ end
221
+ return if selected_cops.empty?
222
+
223
+ type_title = department[0].upcase + department[1..]
224
+ filename = "cops_#{department.downcase}.md"
225
+ content = +"#### Department [#{type_title}](#{filename})\n\n"
226
+ selected_cops.each do |cop|
227
+ anchor = cop.cop_name.sub('/', '').downcase
228
+ content << "* [#{cop.cop_name}](#{filename}##{anchor})\n"
229
+ end
230
+
231
+ content
232
+ end
233
+ # rubocop:enable Metrics/AbcSize
234
+
235
+ def print_table_of_contents(cops)
236
+ path = "#{Dir.pwd}/docs/cops.md"
237
+ original = File.read(path)
238
+ content = +"<!-- START_COP_LIST -->\n"
239
+
240
+ content << table_contents(cops)
241
+
242
+ content << "\n<!-- END_COP_LIST -->"
243
+
244
+ unless original.empty?
245
+ content = original.sub(
246
+ /<!-- START_COP_LIST -->.+<!-- END_COP_LIST -->/m, content
247
+ )
248
+ end
249
+ File.write(path, content)
250
+ end
251
+
252
+ def table_contents(cops)
253
+ cops
254
+ .departments
255
+ .map(&:to_s)
256
+ .sort
257
+ .map { |department| table_of_content_for_department(cops, department) }
258
+ .compact
259
+ .join("\n")
260
+ end
261
+
262
+ def assert_docs_synchronized
263
+ # Do not print diff and yield whether exit code was zero
264
+ sh('git diff --quiet docs') do |outcome, _|
265
+ return if outcome
266
+
267
+ # Output diff before raising error
268
+ sh('GIT_PAGER=cat git diff docs')
269
+
270
+ warn('The docs directory is out of sync. ' \
271
+ 'Run `rake generate_cops_documentation` and commit the results.')
272
+ exit!
273
+ end
274
+ end
275
+
276
+ def main
277
+ cops = RuboCop::Cop::Cop.registry
278
+ config = RuboCop::ConfigLoader.load_file('config/default.yml')
279
+
280
+ YARD::Registry.load!
281
+ cops.departments.sort!.each do |department|
282
+ print_cops_of_department(cops, department, config)
283
+ end
284
+
285
+ print_table_of_contents(cops)
286
+
287
+ assert_docs_synchronized if ENV['CI'] == 'true'
288
+ ensure
289
+ RuboCop::ConfigLoader.default_configuration = nil
290
+ end
291
+
292
+ main
293
+ end
294
+
295
+ desc('Syntax check for the documentation comments')
296
+ task documentation_syntax_check: :yard_for_generate_documentation do
297
+ require 'parser/ruby27'
298
+
299
+ ok = true
300
+ YARD::Registry.load!
301
+ cops = RuboCop::Cop::Cop.registry
302
+ cops.each do |cop|
303
+ examples = YARD::Registry.all(:class).find do |code_object|
304
+ next unless RuboCop::Cop::Badge.for(code_object.to_s) == cop.badge
305
+
306
+ break code_object.tags('example')
307
+ end
308
+
309
+ examples.to_a.each do |example|
310
+ buffer = Parser::Source::Buffer.new('<code>', 1)
311
+ buffer.source = example.text
312
+ parser = Parser::Ruby27.new(RuboCop::AST::Builder.new)
313
+ parser.diagnostics.all_errors_are_fatal = true
314
+ parser.parse(buffer)
315
+ rescue Parser::SyntaxError => e
316
+ path = example.object.file
317
+ puts "#{path}: Syntax Error in an example. #{e}"
318
+ ok = false
319
+ end
320
+ end
321
+ abort unless ok
322
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop-solidus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - piyushswain
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-07-17 00:00:00.000000000 Z
11
+ date: 2023-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubocop
@@ -35,6 +35,7 @@ extra_rdoc_files: []
35
35
  files:
36
36
  - ".rspec"
37
37
  - ".rubocop.yml"
38
+ - ".rubocop_todo.yml"
38
39
  - CHANGELOG.md
39
40
  - Gemfile
40
41
  - Gemfile.lock
@@ -42,6 +43,8 @@ files:
42
43
  - README.md
43
44
  - Rakefile
44
45
  - config/default.yml
46
+ - docs/cops.md
47
+ - docs/cops_solidus.md
45
48
  - lib/rubocop-solidus.rb
46
49
  - lib/rubocop/cop/mixin/target_solidus_version.rb
47
50
  - lib/rubocop/cop/solidus/class_eval_decorator.rb
@@ -59,18 +62,23 @@ files:
59
62
  - lib/rubocop/solidus/inject.rb
60
63
  - lib/rubocop/solidus/version.rb
61
64
  - relnotes/v0.1.2.md
65
+ - relnotes/v0.1.3.md
66
+ - relnotes/v0.1.4.md
67
+ - rubocop-solidus.gemspec
62
68
  - sig/rubocop/solidus.rbs
63
69
  - tasks/changelog.rake
64
70
  - tasks/changelog.rb
71
+ - tasks/cops_documentation.rake
65
72
  - tasks/cut_release.rake
66
- homepage: https://www.github.com/nebulab/rubocop-solidus
73
+ homepage: https://www.github.com/solidusio/rubocop-solidus
67
74
  licenses:
68
75
  - MIT
69
76
  metadata:
70
- homepage_uri: https://www.github.com/nebulab/rubocop-solidus
71
- source_code_uri: https://www.github.com/nebulab/rubocop-solidus
72
- changelog_uri: https://www.github.com/nebulab/rubocop-solidus
73
- post_install_message:
77
+ homepage_uri: https://www.github.com/solidusio/rubocop-solidus
78
+ source_code_uri: https://www.github.com/solidusio/rubocop-solidus
79
+ changelog_uri: https://www.github.com/solidusio/rubocop-solidus/blob/master/CHANGELOG.md
80
+ documentation_uri: https://www.github.com/solidusio/rubocop-solidus/blob/master/docs/cops.md
81
+ post_install_message:
74
82
  rdoc_options: []
75
83
  require_paths:
76
84
  - lib
@@ -78,15 +86,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
78
86
  requirements:
79
87
  - - ">="
80
88
  - !ruby/object:Gem::Version
81
- version: 2.4.0
89
+ version: 2.7.0
82
90
  required_rubygems_version: !ruby/object:Gem::Requirement
83
91
  requirements:
84
92
  - - ">="
85
93
  - !ruby/object:Gem::Version
86
94
  version: '0'
87
95
  requirements: []
88
- rubygems_version: 3.3.17
89
- signing_key:
96
+ rubygems_version: 3.4.18
97
+ signing_key:
90
98
  specification_version: 4
91
99
  summary: Automatic Solidus code style checking tool.
92
100
  test_files: []