rubocop-solidus 0.1.3 → 0.2.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/.rubocop.yml +8 -0
- data/CHANGELOG.md +17 -1
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -1
- data/README.md +60 -12
- data/Rakefile +6 -1
- data/config/default.yml +16 -10
- data/docs/cops.md +20 -0
- data/docs/cops_solidus.md +304 -0
- data/lib/rubocop/cop/mixin/target_solidus_version.rb +5 -1
- data/lib/rubocop/cop/solidus/class_eval_decorator.rb +12 -16
- data/lib/rubocop/cop/solidus/existing_card_id_deprecated.rb +40 -0
- data/lib/rubocop/cop/solidus/reimbursement_hook_deprecated.rb +17 -0
- data/lib/rubocop/cop/solidus/spree_calculator_free_shipping_deprecated.rb +7 -0
- data/lib/rubocop/cop/solidus/spree_calculator_percent_per_item_deprecated.rb +9 -1
- data/lib/rubocop/cop/solidus/spree_calculator_price_sack_deprecated.rb +7 -0
- data/lib/rubocop/cop/solidus/spree_default_credit_card_deprecated.rb +3 -4
- data/lib/rubocop/cop/solidus/spree_gateway_bogus_deprecated.rb +4 -14
- data/lib/rubocop/cop/solidus/spree_icon_deprecated.rb +3 -3
- data/lib/rubocop/cop/solidus/spree_refund_call_perform.rb +9 -2
- data/lib/rubocop/cop/solidus/spree_t_deprecated.rb +16 -4
- data/lib/rubocop/cop/solidus_cops.rb +1 -0
- data/lib/rubocop/solidus/version.rb +1 -1
- data/relnotes/v0.1.4.md +5 -0
- data/relnotes/v0.2.0.md +9 -0
- data/rubocop-solidus.gemspec +2 -1
- data/tasks/changelog.rb +1 -1
- data/tasks/cops_documentation.rake +322 -0
- data/tasks/cut_release.rake +2 -2
- metadata +11 -4
@@ -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
|
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
|
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'
|
data/relnotes/v0.1.4.md
ADDED
data/relnotes/v0.2.0.md
ADDED
@@ -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
|
data/rubocop-solidus.gemspec
CHANGED
@@ -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("##
|
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
|