rubocop-solidus 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Solidus
6
+ # This cop finds existing_card_id occurrences and suggest using wallet_payment_source_id instead.
7
+ #
8
+ # @example
9
+ #
10
+ # # bad
11
+ # {
12
+ # name: payment_method.name,
13
+ # existing_card_id: payment_source.id
14
+ # }
15
+ #
16
+ # # good
17
+ # {
18
+ # name: payment_method.name,
19
+ # wallet_payment_source_id: payment_source.wallet.wallet_payment_sources.first.id
20
+ # }
21
+ #
22
+ class ExistingCardIdDeprecated < Base
23
+ include TargetSolidusVersion
24
+ minimum_solidus_version 2.2
25
+
26
+ MSG = 'Use `wallet_payment_source_id` instead of `existing_card_id`.'
27
+
28
+ def_node_matcher :existing_card_id?, <<~PATTERN
29
+ (send ... :existing_card_id)
30
+ PATTERN
31
+
32
+ def on_send(node)
33
+ return unless existing_card_id?(node)
34
+
35
+ add_offense(node, severity: :warning)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -5,6 +5,23 @@ module RuboCop
5
5
  module Solidus
6
6
  # This cop finds reimbursement_success_hooks and reimbursement_failed_hooks calls and
7
7
  # asks to remove them and subscribe to reimbursement_reimbursed event instead.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # reimbursement_success_hooks.each { |h| h.call self }
13
+ # reimbursement_failed_hooks.each { |h| h.call self }
14
+ #
15
+ # # good
16
+ #
17
+ # @example
18
+ #
19
+ # # bad
20
+ # reimbursement_success_hooks.any?
21
+ # reimbursement_failed_hooks.any?
22
+ #
23
+ # # good
24
+ #
8
25
  class ReimbursementHookDeprecated < Base
9
26
  include TargetSolidusVersion
10
27
  minimum_solidus_version 2.11
@@ -6,6 +6,13 @@ module RuboCop
6
6
  # This cop finds Spree::Calculator::FreeShipping calls.
7
7
  # This cop is needed as they have been deprecated in future version.
8
8
  #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # Spree::Calculator::FreeShipping
13
+ #
14
+ # # good
15
+ #
9
16
  class SpreeCalculatorFreeShippingDeprecated < Base
10
17
  MSG = 'Spree::Calculator::FreeShipping is deprecated.'
11
18
 
@@ -6,10 +6,18 @@ module RuboCop
6
6
  # This cop finds Spree::Calculator::PercentPerItem calls.
7
7
  # This cop is needed as they have been deprecated in future version.
8
8
  #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # Spree::Calculator::PercentPerItem
13
+ #
14
+ # # good
15
+ # Spree::Calculator::PercentOnLineItem
16
+ #
9
17
  class SpreeCalculatorPercentPerItemDeprecated < Base
10
18
  extend AutoCorrector
11
19
 
12
- MSG = 'Spree::Calculator::PercentPerItem is deprecated.'
20
+ MSG = 'Spree::Calculator::PercentPerItem is deprecated. Use Spree::Calculator::PercentOnLineItem instead.'
13
21
 
14
22
  def_node_matcher :percent_per_item?, <<~PATTERN
15
23
  (send (... (... :Calculator) :PercentPerItem) $_)
@@ -6,6 +6,13 @@ module RuboCop
6
6
  # This cop finds Spree::Calculator::PriceSack calls.
7
7
  # This cop is needed as they have been deprecated in future version.
8
8
  #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # Spree::Calculator::PriceSack
13
+ #
14
+ # # good
15
+ #
9
16
  class SpreeCalculatorPriceSackDeprecated < Base
10
17
  MSG = 'Spree::Calculator::PriceSack is deprecated.'
11
18
 
@@ -3,16 +3,16 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Solidus
6
- # This cop finds user.default_credit_card suggest using user.wallet.default_wallet_payment_source
6
+ # This cop finds user.default_credit_card suggest using user.wallet.default_wallet_payment_source.
7
+ #
8
+ # @example
7
9
  #
8
- # @example EnforcedStyle:
9
10
  # # bad
10
11
  # user.default_credit_card
11
12
  #
12
13
  # # good
13
14
  # user.wallet.default_wallet_payment_source
14
15
  #
15
- #
16
16
  class SpreeDefaultCreditCardDeprecated < Base
17
17
  extend AutoCorrector
18
18
  include TargetSolidusVersion
@@ -20,7 +20,6 @@ module RuboCop
20
20
 
21
21
  MSG = 'user.default_credit_card is deprecated. Please use user.wallet.default_wallet_payment_source instead.'
22
22
 
23
- # @!method bad_method?(node)
24
23
  def_node_matcher :default_credit_card?, <<~PATTERN
25
24
  (send ... :default_credit_card)
26
25
  PATTERN
@@ -3,29 +3,20 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Solidus
6
- # This cop finds Spree::Gateway::Bogus calls and replaces them with the Spree::PaymentMethod::BogusCreditCard call
6
+ # This cop finds Spree::Gateway::Bogus calls and replaces them with the Spree::PaymentMethod::BogusCreditCard.
7
7
  # This cop is needed as the Spree::Gateway::Bogus has been deprecated in future version.
8
8
  #
9
- # @example EnforcedStyle:
9
+ # @example
10
10
  # # bad
11
11
  # Spree::Gateway::Bogus.new
12
- #
13
- # # good
14
- # Spree::PaymentMethod::BogusCreditCard.new
15
- #
16
- # # bad
17
12
  # Spree::Gateway::Bogus.create
18
- #
19
- # # good
20
- # Spree::PaymentMethod::BogusCreditCard.create
21
- #
22
- # # bad
23
13
  # Spree::Gateway::Bogus.create!
24
14
  #
25
15
  # # good
16
+ # Spree::PaymentMethod::BogusCreditCard.new
17
+ # Spree::PaymentMethod::BogusCreditCard.create
26
18
  # Spree::PaymentMethod::BogusCreditCard.create!
27
19
  #
28
- #
29
20
  class SpreeGatewayBogusDeprecated < Base
30
21
  extend AutoCorrector
31
22
  include TargetSolidusVersion
@@ -33,7 +24,6 @@ module RuboCop
33
24
 
34
25
  MSG = 'Spree::Gateway::Bogus is deprecated. Please use Spree::PaymentMethod::BogusCreditCard instead.'
35
26
 
36
- # @!method bad_method?(node)
37
27
  def_node_matcher :bad_class?, <<~PATTERN
38
28
  (send (... (... :Gateway) :Bogus) $_)
39
29
  PATTERN
@@ -3,16 +3,16 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Solidus
6
- # This cop finds icon helper calls and suggest using solidus_icon
6
+ # This cop finds icon helper calls and suggest using solidus_icon.
7
+ #
8
+ # @example
7
9
  #
8
- # @example EnforcedStyle:
9
10
  # # bad
10
11
  # helper.icon('example')
11
12
  #
12
13
  # # good
13
14
  # helper.solidus_icon('example')
14
15
  #
15
- #
16
16
  class SpreeIconDeprecated < Base
17
17
  extend AutoCorrector
18
18
  include TargetSolidusVersion
@@ -4,7 +4,15 @@ module RuboCop
4
4
  module Cop
5
5
  module Solidus
6
6
  # This cop finds Spree::Refund.create(your: attributes) calls and
7
- # replaces them with the Spree::Refund.create(your: attributes, perform_after_create: false).perform! call
7
+ # replaces them with the Spree::Refund.create(your: attributes, perform_after_create: false).perform! call.
8
+ #
9
+ # @example
10
+ #
11
+ # # bad
12
+ # Spree::Refund.create(your: attributes)
13
+ #
14
+ # # good
15
+ # Spree::Refund.create(your: attributes, perform_after_create: false).perform!
8
16
  #
9
17
  class SpreeRefundCallPerform < Base
10
18
  include TargetSolidusVersion
@@ -16,7 +24,6 @@ module RuboCop
16
24
 
17
25
  RESTRICT_ON_SEND = %i[create].freeze
18
26
 
19
- # @!method bad_method?(node)
20
27
  def_node_matcher :create_refund?, <<~PATTERN
21
28
  (send (const (const nil? :Spree) :Refund) :create ...)
22
29
  PATTERN
@@ -3,43 +3,52 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Solidus
6
- # This cop finds Spree.t method calls and replaces them with the I18n,t method call
6
+ # This cop finds Spree.t method calls and replaces them with the I18n,t method call.
7
7
  # This cop is needed as the Spree.t version has been deprecated in future version.
8
8
  #
9
+ # @example
10
+ # # Without any parameters
9
11
  #
10
- # @example EnforcedStyle: bar (default)
11
12
  # # bad
12
13
  # Spree.t(:bar)
13
14
  #
14
15
  # # good
15
16
  # I18n.t(:bar, scope: :spree)
16
17
  #
18
+ # @example
19
+ # # With the scope parameter
20
+ #
17
21
  # # bad
18
22
  # Spree.t(:bar, scope: [:city])
19
23
  #
20
24
  # # good
21
25
  # I18n.t(:bar, scope: [:spree, :city])
22
26
  #
27
+ # @example
28
+ # # With the scope and other parameters
29
+ #
23
30
  # # bad
24
31
  # Spree.t(:bar, scope: [:city], email: email)
25
32
  #
26
33
  # # good
27
34
  # I18n.t(:bar, scope: [:spree, :city], email: email)
28
35
  #
36
+ # @example
37
+ # # With the scope parameter as a string
38
+ #
29
39
  # # bad
30
40
  # Spree.t('bar', scope: 'admin.city')
31
41
  #
32
42
  # # good
33
43
  # I18n.t('bar', scope: 'spree.admin.city')
34
44
  #
35
- #
36
45
  class SpreeTDeprecated < Base
37
46
  extend AutoCorrector
47
+ include IgnoredNode
38
48
  MSG = 'Use I18n.t instead of Spree.t which has been deprecated in future versions.'
39
49
 
40
50
  RESTRICT_ON_SEND = %i[t].freeze
41
51
 
42
- # @!method spree_t?(node)
43
52
  def_node_matcher :spree_t?, <<~PATTERN
44
53
  (send ($...) :t ...)
45
54
  PATTERN
@@ -50,8 +59,11 @@ module RuboCop
50
59
  return unless spree_t?(node).include?(:Spree)
51
60
 
52
61
  add_offense(node) do |corrector|
62
+ next if part_of_ignored_node?(node)
63
+
53
64
  corrector.replace(node, corrected_statement(node))
54
65
  end
66
+ ignore_node(node)
55
67
  end
56
68
 
57
69
  # rubocop:disable Metrics/MethodLength
@@ -3,6 +3,7 @@
3
3
  require_relative 'mixin/target_solidus_version'
4
4
 
5
5
  require_relative 'solidus/class_eval_decorator'
6
+ require_relative 'solidus/existing_card_id_deprecated'
6
7
  require_relative 'solidus/reimbursement_hook_deprecated'
7
8
  require_relative 'solidus/spree_calculator_free_shipping_deprecated'
8
9
  require_relative 'solidus/spree_calculator_percent_per_item_deprecated'
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RuboCop
4
4
  module Solidus
5
- VERSION = '0.1.3'
5
+ VERSION = '0.2.0'
6
6
  end
7
7
  end
@@ -0,0 +1,5 @@
1
+ ### New features
2
+
3
+ * [#51](https://github.com/solidusio/rubocop-solidus/pull/51): Create automatic documentation based on the cop's descriptions. ([@MassimilianoLattanzio][])
4
+
5
+ [@MassimilianoLattanzio]: https://github.com/MassimilianoLattanzio
@@ -0,0 +1,9 @@
1
+ ### New features
2
+
3
+ * [#60](https://github.com/solidusio/rubocop-solidus/issues/60): Create new cop to check existing_card_id. ([@MassimilianoLattanzio][])
4
+
5
+ ### Bug fixes
6
+
7
+ * [#60](https://github.com/solidusio/rubocop-solidus/issues/60): Fix overridden add_offense method. ([@MassimilianoLattanzio][])
8
+
9
+ [@MassimilianoLattanzio]: https://github.com/MassimilianoLattanzio
@@ -19,7 +19,8 @@ Gem::Specification.new do |spec|
19
19
 
20
20
  spec.metadata['homepage_uri'] = spec.homepage
21
21
  spec.metadata['source_code_uri'] = 'https://www.github.com/solidusio/rubocop-solidus'
22
- spec.metadata['changelog_uri'] = 'https://www.github.com/solidusio/rubocop-solidus'
22
+ spec.metadata['changelog_uri'] = 'https://www.github.com/solidusio/rubocop-solidus/blob/main/CHANGELOG.md'
23
+ spec.metadata['documentation_uri'] = 'https://www.github.com/solidusio/rubocop-solidus/blob/main/docs/cops.md'
23
24
 
24
25
  # Specify which files should be added to the gem when it is released.
25
26
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
data/tasks/changelog.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  # Changelog utility
4
4
  class Changelog
5
5
  ENTRIES_PATH = 'changelog/'
6
- FIRST_HEADER = /#{Regexp.escape("## master (unreleased)\n")}/m.freeze
6
+ FIRST_HEADER = /#{Regexp.escape("## main (unreleased)\n")}/m.freeze
7
7
  ENTRIES_PATH_TEMPLATE = "#{ENTRIES_PATH}%<type>s_%<name>s.md"
8
8
  TYPE_REGEXP = /#{Regexp.escape(ENTRIES_PATH)}([a-z]+)_/.freeze
9
9
  TYPE_TO_HEADER = { new: 'New features', fix: 'Bug fixes', change: 'Changes' }.freeze
@@ -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