rubocop-minitest 0.7.0 → 0.10.1
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/.circleci/config.yml +0 -3
- data/.rubocop.yml +2 -1
- data/.rubocop_todo.yml +0 -7
- data/CHANGELOG.md +58 -0
- data/Gemfile +1 -1
- data/README.md +2 -2
- data/Rakefile +29 -0
- data/config/default.yml +96 -16
- data/docs/antora.yml +7 -0
- data/docs/modules/ROOT/nav.adoc +6 -0
- data/docs/modules/ROOT/pages/cops.adoc +37 -0
- data/docs/modules/ROOT/pages/cops_minitest.adoc +1014 -0
- data/docs/modules/ROOT/pages/index.adoc +5 -0
- data/docs/modules/ROOT/pages/installation.adoc +15 -0
- data/docs/modules/ROOT/pages/usage.adoc +32 -0
- data/{manual → legacy-docs}/cops.md +0 -0
- data/{manual → legacy-docs}/cops_minitest.md +7 -5
- data/{manual → legacy-docs}/index.md +0 -0
- data/{manual → legacy-docs}/installation.md +0 -0
- data/{manual → legacy-docs}/usage.md +0 -0
- data/lib/rubocop/cop/generator.rb +56 -0
- data/lib/rubocop/cop/minitest/assert_empty_literal.rb +15 -0
- data/lib/rubocop/cop/minitest/assert_equal.rb +2 -31
- data/lib/rubocop/cop/minitest/assert_in_delta.rb +27 -0
- data/lib/rubocop/cop/minitest/assert_kind_of.rb +25 -0
- data/lib/rubocop/cop/minitest/assert_output.rb +49 -0
- data/lib/rubocop/cop/minitest/assert_path_exists.rb +58 -0
- data/lib/rubocop/cop/minitest/assert_silent.rb +45 -0
- data/lib/rubocop/cop/minitest/assertion_in_lifecycle_hook.rb +43 -0
- data/lib/rubocop/cop/minitest/global_expectations.rb +49 -28
- data/lib/rubocop/cop/minitest/literal_as_actual_argument.rb +52 -0
- data/lib/rubocop/cop/minitest/multiple_assertions.rb +63 -0
- data/lib/rubocop/cop/minitest/refute_in_delta.rb +27 -0
- data/lib/rubocop/cop/minitest/refute_kind_of.rb +25 -0
- data/lib/rubocop/cop/minitest/refute_path_exists.rb +58 -0
- data/lib/rubocop/cop/minitest/test_method_name.rb +70 -0
- data/lib/rubocop/cop/minitest/unspecified_exception.rb +36 -0
- data/lib/rubocop/cop/minitest_cops.rb +15 -0
- data/lib/rubocop/cop/mixin/argument_range_helper.rb +10 -0
- data/lib/rubocop/cop/mixin/in_delta_mixin.rb +50 -0
- data/lib/rubocop/cop/mixin/minitest_cop_rule.rb +1 -3
- data/lib/rubocop/cop/mixin/minitest_exploration_helpers.rb +84 -0
- data/lib/rubocop/minitest/version.rb +1 -1
- data/mkdocs.yml +2 -2
- data/relnotes/v0.10.0.md +21 -0
- data/relnotes/v0.10.1.md +5 -0
- data/relnotes/v0.8.0.md +12 -0
- data/relnotes/v0.8.1.md +5 -0
- data/relnotes/v0.9.0.md +10 -0
- data/rubocop-minitest.gemspec +4 -4
- data/tasks/cops_documentation.rake +83 -54
- data/tasks/cut_release.rake +16 -0
- metadata +40 -12
@@ -1,22 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'mixin/argument_range_helper'
|
4
|
+
require_relative 'mixin/in_delta_mixin'
|
4
5
|
require_relative 'mixin/minitest_cop_rule'
|
6
|
+
require_relative 'mixin/minitest_exploration_helpers'
|
5
7
|
require_relative 'minitest/assert_empty'
|
6
8
|
require_relative 'minitest/assert_empty_literal'
|
7
9
|
require_relative 'minitest/assert_equal'
|
10
|
+
require_relative 'minitest/assert_in_delta'
|
11
|
+
require_relative 'minitest/assertion_in_lifecycle_hook'
|
12
|
+
require_relative 'minitest/assert_kind_of'
|
8
13
|
require_relative 'minitest/assert_nil'
|
9
14
|
require_relative 'minitest/assert_includes'
|
10
15
|
require_relative 'minitest/assert_instance_of'
|
11
16
|
require_relative 'minitest/assert_match'
|
17
|
+
require_relative 'minitest/assert_output'
|
18
|
+
require_relative 'minitest/assert_path_exists'
|
12
19
|
require_relative 'minitest/assert_respond_to'
|
20
|
+
require_relative 'minitest/assert_silent'
|
13
21
|
require_relative 'minitest/assert_truthy'
|
14
22
|
require_relative 'minitest/global_expectations'
|
23
|
+
require_relative 'minitest/literal_as_actual_argument'
|
24
|
+
require_relative 'minitest/multiple_assertions'
|
15
25
|
require_relative 'minitest/refute_empty'
|
16
26
|
require_relative 'minitest/refute_false'
|
17
27
|
require_relative 'minitest/refute_equal'
|
28
|
+
require_relative 'minitest/refute_in_delta'
|
29
|
+
require_relative 'minitest/refute_kind_of'
|
18
30
|
require_relative 'minitest/refute_nil'
|
19
31
|
require_relative 'minitest/refute_includes'
|
20
32
|
require_relative 'minitest/refute_match'
|
21
33
|
require_relative 'minitest/refute_instance_of'
|
34
|
+
require_relative 'minitest/refute_path_exists'
|
22
35
|
require_relative 'minitest/refute_respond_to'
|
36
|
+
require_relative 'minitest/test_method_name'
|
37
|
+
require_relative 'minitest/unspecified_exception'
|
@@ -26,6 +26,16 @@ module RuboCop
|
|
26
26
|
second_argument.source_range.end_pos
|
27
27
|
)
|
28
28
|
end
|
29
|
+
|
30
|
+
def all_arguments_range(node)
|
31
|
+
first_argument = node.first_argument
|
32
|
+
last_argument = node.arguments.last
|
33
|
+
|
34
|
+
range_between(
|
35
|
+
first_argument.source_range.begin_pos,
|
36
|
+
last_argument.source_range.end_pos
|
37
|
+
)
|
38
|
+
end
|
29
39
|
end
|
30
40
|
end
|
31
41
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common functionality for `AssertInDelta` and `RefuteInDelta` cops.
|
6
|
+
module InDeltaMixin
|
7
|
+
MSG = 'Prefer using `%<good_method>s` over `%<bad_method>s`.'
|
8
|
+
|
9
|
+
def on_send(node)
|
10
|
+
equal_floats_call(node) do |expected, actual, message|
|
11
|
+
message = message.first
|
12
|
+
|
13
|
+
if expected.float_type? || actual.float_type?
|
14
|
+
message = format(MSG,
|
15
|
+
good_method: build_good_method(expected, actual, message),
|
16
|
+
bad_method: node.source)
|
17
|
+
|
18
|
+
add_offense(node, message: message)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def autocorrect(node)
|
24
|
+
equal_floats_call(node) do |expected, actual, message|
|
25
|
+
message = message.first
|
26
|
+
replacement = build_good_method(expected, actual, message)
|
27
|
+
|
28
|
+
lambda do |corrector|
|
29
|
+
corrector.replace(node, replacement)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def build_good_method(expected, actual, message)
|
37
|
+
if message
|
38
|
+
"#{assertion_method}_in_delta(#{expected.source}, #{actual.source}, 0.001, #{message.source})"
|
39
|
+
else
|
40
|
+
"#{assertion_method}_in_delta(#{expected.source}, #{actual.source})"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def assertion_method
|
45
|
+
class_name = self.class.name.split('::').last
|
46
|
+
class_name[/\A[[:upper:]][[:lower:]]+/].downcase
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -22,9 +22,7 @@ module RuboCop
|
|
22
22
|
# @param inverse [Boolean] An optional param. Order of arguments replaced by auto-correction.
|
23
23
|
#
|
24
24
|
def define_rule(assertion_method, target_method:, preferred_method: nil, inverse: false)
|
25
|
-
if preferred_method.nil?
|
26
|
-
preferred_method = "#{assertion_method}_#{target_method.to_s.delete('?')}"
|
27
|
-
end
|
25
|
+
preferred_method = "#{assertion_method}_#{target_method.to_s.delete('?')}" if preferred_method.nil?
|
28
26
|
|
29
27
|
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
30
28
|
include ArgumentRangeHelper
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
module Cop
|
7
|
+
# Helper methods for different explorations against test files and test cases.
|
8
|
+
module MinitestExplorationHelpers
|
9
|
+
extend NodePattern::Macros
|
10
|
+
|
11
|
+
ASSERTION_PREFIXES = %w[assert refute].freeze
|
12
|
+
|
13
|
+
LIFECYCLE_HOOK_METHODS = %i[
|
14
|
+
before_setup
|
15
|
+
setup
|
16
|
+
after_setup
|
17
|
+
before_teardown
|
18
|
+
teardown
|
19
|
+
after_teardown
|
20
|
+
].to_set.freeze
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def test_class?(class_node)
|
25
|
+
class_node.parent_class && class_node.identifier.source.end_with?('Test')
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_case?(node)
|
29
|
+
return false unless node&.def_type? && test_case_name?(node.method_name)
|
30
|
+
|
31
|
+
class_ancestor = node.each_ancestor(:class).first
|
32
|
+
test_class?(class_ancestor)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_cases(class_node)
|
36
|
+
class_def_nodes(class_node)
|
37
|
+
.select { |def_node| test_case_name?(def_node.method_name) }
|
38
|
+
end
|
39
|
+
|
40
|
+
def lifecycle_hooks(class_node)
|
41
|
+
class_def_nodes(class_node)
|
42
|
+
.select { |def_node| lifecycle_hook_method?(def_node) }
|
43
|
+
end
|
44
|
+
|
45
|
+
def class_def_nodes(class_node)
|
46
|
+
class_def = class_node.body
|
47
|
+
return [] unless class_def
|
48
|
+
|
49
|
+
if class_def.def_type?
|
50
|
+
[class_def]
|
51
|
+
else
|
52
|
+
class_def.each_child_node(:def).to_a
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_case_name?(name)
|
57
|
+
name.to_s.start_with?('test_')
|
58
|
+
end
|
59
|
+
|
60
|
+
def assertions(def_node)
|
61
|
+
method_def = def_node.body
|
62
|
+
return [] unless method_def
|
63
|
+
|
64
|
+
send_nodes =
|
65
|
+
if method_def.send_type?
|
66
|
+
[method_def]
|
67
|
+
else
|
68
|
+
method_def.each_child_node(:send)
|
69
|
+
end
|
70
|
+
|
71
|
+
send_nodes.select { |send_node| assertion?(send_node) }
|
72
|
+
end
|
73
|
+
|
74
|
+
def assertion?(node)
|
75
|
+
node.send_type? &&
|
76
|
+
ASSERTION_PREFIXES.any? { |prefix| node.method_name.to_s.start_with?(prefix) }
|
77
|
+
end
|
78
|
+
|
79
|
+
def lifecycle_hook_method?(node)
|
80
|
+
node.def_type? && LIFECYCLE_HOOK_METHODS.include?(node.method_name)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/mkdocs.yml
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
site_name: "A RuboCop extension focused on enforcing Minitest best practices and coding conventions."
|
2
2
|
repo_url: https://github.com/rubocop-hq/rubocop-minitest
|
3
|
-
edit_uri: edit/master/
|
3
|
+
edit_uri: edit/master/legacy-docs/
|
4
4
|
copyright: "Copyright © 2019 Bozhidar Batsov, Jonas Arvidsson, Koichi ITO, and RuboCop contributors"
|
5
|
-
docs_dir:
|
5
|
+
docs_dir: legacy-docs
|
6
6
|
pages:
|
7
7
|
- Home: index.md
|
8
8
|
- Installation: installation.md
|
data/relnotes/v0.10.0.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
### New features
|
2
|
+
|
3
|
+
* [#92](https://github.com/rubocop-hq/rubocop-minitest/pull/92): Add new `Minitest/LiteralAsActualArgument` cop. ([@fatkodima][], [@tsmmark][])
|
4
|
+
* [#95](https://github.com/rubocop-hq/rubocop-minitest/pull/95): Add new `Minitest/AssertionInLifecycleHook` cop. ([@fatkodima][])
|
5
|
+
* [#91](https://github.com/rubocop-hq/rubocop-minitest/pull/91): Add new `Minitest/AssertInDelta` and `Minitest/RefuteInDelta` cops. ([@fatkodima][])
|
6
|
+
* [#89](https://github.com/rubocop-hq/rubocop-minitest/pull/89): Add new `Minitest/TestMethodName` cop. ([@fatkodima][])
|
7
|
+
* [#83](https://github.com/rubocop-hq/rubocop-minitest/pull/83): New cops `AssertPathExists` and `RefutePathExists` check for use of `assert_path_exists`/`refute_path_exists` instead of `assert(File.exist?(path))`/`refute(File.exist?(path))`. ([@fatkodima][])
|
8
|
+
* [#88](https://github.com/rubocop-hq/rubocop-minitest/pull/88): Add new `Minitest/MultipleAssertions` cop. ([@fatkodima][])
|
9
|
+
* [#87](https://github.com/rubocop-hq/rubocop-minitest/pull/87): Add new `Minitest/AssertSilent` cop. ([@fatkodima][])
|
10
|
+
* [#96](https://github.com/rubocop-hq/rubocop-minitest/pull/96): Add new `Minitest/UnspecifiedException` cop. ([@fatkodima][])
|
11
|
+
* [#98](https://github.com/rubocop-hq/rubocop-minitest/pull/98): Add new `Minitest/AssertOutput` cop. ([@fatkodima][])
|
12
|
+
* [#84](https://github.com/rubocop-hq/rubocop-minitest/pull/84): New cops `AssertKindOf` and `RefuteKindOf` check for use of `assert_kind_of`/`refute_kind_of` instead of `assert(foo.kind_of?(Class))`/`refute(foo.kind_of?(Class))`. ([@fatkodima][])
|
13
|
+
* [#85](https://github.com/rubocop-hq/rubocop-minitest/pull/85): Add autocorrect to `Rails/AssertEmptyLiteral` cop. ([@fatkodima][])
|
14
|
+
|
15
|
+
### Changes
|
16
|
+
|
17
|
+
* [#104](https://github.com/rubocop-hq/rubocop-minitest/pull/104): Require RuboCop 0.87 or higher. ([@koic][])
|
18
|
+
|
19
|
+
[@fatkodima]: https://github.com/fatkodima
|
20
|
+
[@tsmmark]: https://github.com/tsmmark
|
21
|
+
[@koic]: https://github.com/koic
|
data/relnotes/v0.10.1.md
ADDED
data/relnotes/v0.8.0.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
### New features
|
2
|
+
|
3
|
+
* [#66](https://github.com/rubocop-hq/rubocop-minitest/issues/66): Support all expectations of `Minitest::Expectations` for `Minitest/GlobalExpectations` cop. ([@koic][])
|
4
|
+
|
5
|
+
### Bug fixes
|
6
|
+
|
7
|
+
* [#60](https://github.com/rubocop-hq/rubocop-minitest/issues/60): Fix `Minitest/GlobalExpectations` autocorrection for chained methods. ([@tejasbubane][])
|
8
|
+
* [#69](https://github.com/rubocop-hq/rubocop-minitest/pull/69): Fix a false negative for `Minitest/GlobalExpectations` cop when using a variable or a hash index for receiver. ([@koic][])
|
9
|
+
* [#71](https://github.com/rubocop-hq/rubocop-minitest/pull/71): Fix a false negative for `Minitest/AssertEqual` when an argument is enclosed in redundant parentheses. ([@koic][])
|
10
|
+
|
11
|
+
[@koic]: https://github.com/koic
|
12
|
+
[@tejasbubane]: https://github.com/tejasbubane
|
data/relnotes/v0.8.1.md
ADDED
data/relnotes/v0.9.0.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
### Bug fixes
|
2
|
+
|
3
|
+
* [#75](https://github.com/rubocop-hq/rubocop-minitest/issues/75): Fix a false negative for `Minitest/GlobalExpectations` when using global expectation methods with no arguments. ([@koic][])
|
4
|
+
|
5
|
+
### Changes
|
6
|
+
|
7
|
+
* [#73](https://github.com/rubocop-hq/rubocop-minitest/issues/73): The Minitest department works on file names end with `_test.rb` by default. ([@koic][])
|
8
|
+
* [#77](https://github.com/rubocop-hq/rubocop-minitest/pull/77): **(BREAKING)** Drop support for Ruby 2.3. ([@koic][])
|
9
|
+
|
10
|
+
[@koic]: https://github.com/koic
|
data/rubocop-minitest.gemspec
CHANGED
@@ -16,12 +16,12 @@ Gem::Specification.new do |spec|
|
|
16
16
|
DESCRIPTION
|
17
17
|
spec.license = 'MIT'
|
18
18
|
|
19
|
-
spec.required_ruby_version = '>= 2.
|
19
|
+
spec.required_ruby_version = '>= 2.4.0'
|
20
20
|
spec.metadata = {
|
21
|
-
'homepage_uri' => 'https://docs.rubocop.org/
|
21
|
+
'homepage_uri' => 'https://docs.rubocop.org/rubocop-minitest/',
|
22
22
|
'changelog_uri' => 'https://github.com/rubocop-hq/rubocop-minitest/blob/master/CHANGELOG.md',
|
23
23
|
'source_code_uri' => 'https://github.com/rubocop-hq/rubocop-minitest',
|
24
|
-
'documentation_uri' => 'https://docs.rubocop.org/
|
24
|
+
'documentation_uri' => 'https://docs.rubocop.org/rubocop-minitest/',
|
25
25
|
'bug_tracker_uri' => 'https://github.com/rubocop-hq/rubocop-minitest/issues'
|
26
26
|
}
|
27
27
|
|
@@ -34,6 +34,6 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
35
35
|
spec.require_paths = ['lib']
|
36
36
|
|
37
|
-
spec.add_runtime_dependency 'rubocop', '>= 0.
|
37
|
+
spec.add_runtime_dependency 'rubocop', '>= 0.87'
|
38
38
|
spec.add_development_dependency 'minitest', '~> 5.11'
|
39
39
|
end
|
@@ -17,7 +17,8 @@ task generate_cops_documentation: :yard_for_generate_documentation do
|
|
17
17
|
|
18
18
|
def cops_body(config, cop, description, examples_objects, pars)
|
19
19
|
content = h2(cop.cop_name)
|
20
|
-
content <<
|
20
|
+
content << required_ruby_version(cop)
|
21
|
+
content << properties(cop.new(config))
|
21
22
|
content << "#{description}\n"
|
22
23
|
content << examples(examples_objects) if examples_objects.count.positive?
|
23
24
|
content << configurations(pars)
|
@@ -27,60 +28,66 @@ task generate_cops_documentation: :yard_for_generate_documentation do
|
|
27
28
|
|
28
29
|
def examples(examples_object)
|
29
30
|
examples_object.each_with_object(h3('Examples').dup) do |example, content|
|
31
|
+
content << "\n" unless content.end_with?("\n\n")
|
30
32
|
content << h4(example.name) unless example.name == ''
|
31
33
|
content << code_example(example)
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
37
|
+
def required_ruby_version(cop)
|
38
|
+
return '' unless cop.respond_to?(:required_minimum_ruby_version)
|
39
|
+
|
40
|
+
"NOTE: Required Ruby version: #{cop.required_minimum_ruby_version}\n\n"
|
41
|
+
end
|
42
|
+
|
35
43
|
# rubocop:disable Metrics/MethodLength
|
36
|
-
def properties(
|
44
|
+
def properties(cop_instance)
|
37
45
|
header = [
|
38
46
|
'Enabled by default', 'Safe', 'Supports autocorrection', 'VersionAdded',
|
39
47
|
'VersionChanged'
|
40
48
|
]
|
41
|
-
|
42
|
-
|
43
|
-
autocorrect = if cop.new.support_autocorrect?
|
44
|
-
"Yes #{'(Unsafe)' unless safe_auto_correct}"
|
49
|
+
autocorrect = if cop_instance.support_autocorrect?
|
50
|
+
"Yes#{' (Unsafe)' unless cop_instance.safe_autocorrect?}"
|
45
51
|
else
|
46
52
|
'No'
|
47
53
|
end
|
54
|
+
cop_config = cop_instance.cop_config
|
48
55
|
content = [[
|
49
|
-
|
50
|
-
|
56
|
+
cop_status(cop_config.fetch('Enabled')),
|
57
|
+
cop_config.fetch('Safe', true) ? 'Yes' : 'No',
|
51
58
|
autocorrect,
|
52
|
-
|
53
|
-
|
59
|
+
cop_config.fetch('VersionAdded', '-'),
|
60
|
+
cop_config.fetch('VersionChanged', '-')
|
54
61
|
]]
|
55
|
-
to_table(header, content)
|
62
|
+
"#{to_table(header, content)}\n"
|
56
63
|
end
|
57
64
|
# rubocop:enable Metrics/MethodLength
|
58
65
|
|
59
66
|
def h2(title)
|
60
67
|
content = +"\n"
|
61
|
-
content << "
|
68
|
+
content << "== #{title}\n"
|
62
69
|
content << "\n"
|
63
70
|
content
|
64
71
|
end
|
65
72
|
|
66
73
|
def h3(title)
|
67
74
|
content = +"\n"
|
68
|
-
content << "
|
75
|
+
content << "=== #{title}\n"
|
69
76
|
content << "\n"
|
70
77
|
content
|
71
78
|
end
|
72
79
|
|
73
80
|
def h4(title)
|
74
|
-
content = +"
|
81
|
+
content = +"==== #{title}\n"
|
75
82
|
content << "\n"
|
76
83
|
content
|
77
84
|
end
|
78
85
|
|
79
86
|
def code_example(ruby_code)
|
80
|
-
content = +"
|
81
|
-
content << ruby_code.text
|
82
|
-
.gsub('@
|
83
|
-
content << "\n
|
87
|
+
content = +"[source,ruby]\n----\n"
|
88
|
+
content << ruby_code.text.gsub('@good', '# good')
|
89
|
+
.gsub('@bad', '# bad').strip
|
90
|
+
content << "\n----\n"
|
84
91
|
content
|
85
92
|
end
|
86
93
|
|
@@ -88,7 +95,10 @@ task generate_cops_documentation: :yard_for_generate_documentation do
|
|
88
95
|
return '' if pars.empty?
|
89
96
|
|
90
97
|
header = ['Name', 'Default value', 'Configurable values']
|
91
|
-
configs = pars
|
98
|
+
configs = pars
|
99
|
+
.each_key
|
100
|
+
.reject { |key| key.start_with?('Supported') }
|
101
|
+
.reject { |key| key.start_with?('AllowMultipleStyles') }
|
92
102
|
content = configs.map do |name|
|
93
103
|
configurable = configurable_values(pars, name)
|
94
104
|
default = format_table_value(pars[name])
|
@@ -106,8 +116,6 @@ task generate_cops_documentation: :yard_for_generate_documentation do
|
|
106
116
|
format_table_value(pars[supported_style_name])
|
107
117
|
when 'IndentationWidth'
|
108
118
|
'Integer'
|
109
|
-
when 'Database'
|
110
|
-
format_table_value(pars['SupportedDatabases'])
|
111
119
|
else
|
112
120
|
case pars[name]
|
113
121
|
when String
|
@@ -129,11 +137,14 @@ task generate_cops_documentation: :yard_for_generate_documentation do
|
|
129
137
|
|
130
138
|
def to_table(header, content)
|
131
139
|
table = [
|
132
|
-
|
133
|
-
|
134
|
-
]
|
135
|
-
|
136
|
-
|
140
|
+
'|===',
|
141
|
+
"| #{header.join(' | ')}\n\n"
|
142
|
+
].join("\n")
|
143
|
+
marked_contents = content.map do |plain_content|
|
144
|
+
plain_content.map { |c| "| #{c}" }.join("\n")
|
145
|
+
end
|
146
|
+
table << marked_contents.join("\n\n")
|
147
|
+
table << "\n|===\n"
|
137
148
|
end
|
138
149
|
|
139
150
|
def format_table_value(val)
|
@@ -146,11 +157,20 @@ task generate_cops_documentation: :yard_for_generate_documentation do
|
|
146
157
|
val.map { |config| format_table_value(config) }.join(', ')
|
147
158
|
end
|
148
159
|
else
|
149
|
-
|
160
|
+
wrap_backtick(val.nil? ? '<none>' : val)
|
150
161
|
end
|
151
162
|
value.gsub("#{Dir.pwd}/", '').rstrip
|
152
163
|
end
|
153
164
|
|
165
|
+
def wrap_backtick(value)
|
166
|
+
if value.is_a?(String)
|
167
|
+
# Use `+` to prevent text like `**/*.gemspec` from being bold.
|
168
|
+
value.start_with?('*') ? "`+#{value}+`" : "`#{value}`"
|
169
|
+
else
|
170
|
+
"`#{value}`"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
154
174
|
def references(config, cop)
|
155
175
|
cop_config = config.for_cop(cop)
|
156
176
|
urls = RuboCop::Cop::MessageAnnotator.new(
|
@@ -159,7 +179,7 @@ task generate_cops_documentation: :yard_for_generate_documentation do
|
|
159
179
|
return '' if urls.empty?
|
160
180
|
|
161
181
|
content = h3('References')
|
162
|
-
content << urls.map { |url| "*
|
182
|
+
content << urls.map { |url| "* #{url}" }.join("\n")
|
163
183
|
content << "\n"
|
164
184
|
content
|
165
185
|
end
|
@@ -170,14 +190,15 @@ task generate_cops_documentation: :yard_for_generate_documentation do
|
|
170
190
|
end
|
171
191
|
return if selected_cops.empty?
|
172
192
|
|
173
|
-
|
193
|
+
selected_cops = cops_of_department(cops, department)
|
194
|
+
content = +"= #{department}\n"
|
174
195
|
selected_cops.each do |cop|
|
175
196
|
content << print_cop_with_doc(cop, config)
|
176
197
|
end
|
177
|
-
file_name = "#{Dir.pwd}/
|
198
|
+
file_name = "#{Dir.pwd}/docs/modules/ROOT/pages/cops_#{department.downcase}.adoc"
|
178
199
|
File.open(file_name, 'w') do |file|
|
179
200
|
puts "* generated #{file_name}"
|
180
|
-
file.write(content.strip
|
201
|
+
file.write("#{content.strip}\n")
|
181
202
|
end
|
182
203
|
end
|
183
204
|
|
@@ -190,15 +211,21 @@ task generate_cops_documentation: :yard_for_generate_documentation do
|
|
190
211
|
pars = t.reject { |k| non_display_keys.include? k }
|
191
212
|
description = 'No documentation'
|
192
213
|
examples_object = []
|
193
|
-
|
194
|
-
next unless RuboCop::Cop::Badge.for(code_object.to_s) == cop.badge
|
195
|
-
|
214
|
+
cop_code(cop) do |code_object|
|
196
215
|
description = code_object.docstring unless code_object.docstring.blank?
|
197
216
|
examples_object = code_object.tags('example')
|
198
217
|
end
|
199
218
|
cops_body(config, cop, description, examples_object, pars)
|
200
219
|
end
|
201
220
|
|
221
|
+
def cop_code(cop)
|
222
|
+
YARD::Registry.all(:class).detect do |code_object|
|
223
|
+
next unless RuboCop::Cop::Badge.for(code_object.to_s) == cop.badge
|
224
|
+
|
225
|
+
yield code_object
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
202
229
|
# rubocop:disable Metrics/AbcSize
|
203
230
|
def table_of_content_for_department(cops, department)
|
204
231
|
selected_cops = cops_of_department(cops, department.to_sym).select do |cop|
|
@@ -207,11 +234,11 @@ task generate_cops_documentation: :yard_for_generate_documentation do
|
|
207
234
|
return if selected_cops.empty?
|
208
235
|
|
209
236
|
type_title = department[0].upcase + department[1..-1]
|
210
|
-
filename = "cops_#{department.downcase}.
|
211
|
-
content = +"
|
212
|
-
|
237
|
+
filename = "cops_#{department.downcase}.adoc"
|
238
|
+
content = +"= Department xref:#{filename}[#{type_title}]\n\n"
|
239
|
+
cops_of_department(cops, department.to_sym).each do |cop|
|
213
240
|
anchor = cop.cop_name.sub('/', '').downcase
|
214
|
-
content << "* [#{cop.cop_name}]
|
241
|
+
content << "* xref:#{filename}##{anchor}[#{cop.cop_name}]\n"
|
215
242
|
end
|
216
243
|
|
217
244
|
content
|
@@ -219,21 +246,17 @@ task generate_cops_documentation: :yard_for_generate_documentation do
|
|
219
246
|
# rubocop:enable Metrics/AbcSize
|
220
247
|
|
221
248
|
def print_table_of_contents(cops)
|
222
|
-
path = "#{Dir.pwd}/
|
249
|
+
path = "#{Dir.pwd}/docs/modules/ROOT/pages/cops.adoc"
|
223
250
|
original = File.read(path)
|
224
|
-
content = +"
|
251
|
+
content = +"// START_COP_LIST\n\n"
|
225
252
|
|
226
253
|
content << table_contents(cops)
|
227
254
|
|
228
|
-
content << "\n
|
255
|
+
content << "\n// END_COP_LIST"
|
229
256
|
|
230
|
-
content =
|
231
|
-
|
232
|
-
|
233
|
-
original.sub(
|
234
|
-
/<!-- START_COP_LIST -->.+<!-- END_COP_LIST -->/m, content
|
235
|
-
)
|
236
|
-
end
|
257
|
+
content = original.sub(
|
258
|
+
%r{// START_COP_LIST.+// END_COP_LIST}m, content
|
259
|
+
)
|
237
260
|
File.write(path, content)
|
238
261
|
end
|
239
262
|
|
@@ -243,19 +266,25 @@ task generate_cops_documentation: :yard_for_generate_documentation do
|
|
243
266
|
.map(&:to_s)
|
244
267
|
.sort
|
245
268
|
.map { |department| table_of_content_for_department(cops, department) }
|
246
|
-
.
|
269
|
+
.compact
|
247
270
|
.join("\n")
|
248
271
|
end
|
249
272
|
|
250
|
-
def
|
273
|
+
def cop_status(status)
|
274
|
+
return 'Disabled' unless status
|
275
|
+
|
276
|
+
status == 'pending' ? 'Pending' : 'Enabled'
|
277
|
+
end
|
278
|
+
|
279
|
+
def assert_docs_synchronized
|
251
280
|
# Do not print diff and yield whether exit code was zero
|
252
|
-
sh('git diff --quiet
|
281
|
+
sh('git diff --quiet docs') do |outcome, _|
|
253
282
|
return if outcome
|
254
283
|
|
255
284
|
# Output diff before raising error
|
256
|
-
sh('GIT_PAGER=cat git diff
|
285
|
+
sh('GIT_PAGER=cat git diff docs')
|
257
286
|
|
258
|
-
warn 'The
|
287
|
+
warn 'The docs directory is out of sync. ' \
|
259
288
|
'Run `rake generate_cops_documentation` and commit the results.'
|
260
289
|
exit!
|
261
290
|
end
|
@@ -272,7 +301,7 @@ task generate_cops_documentation: :yard_for_generate_documentation do
|
|
272
301
|
|
273
302
|
print_table_of_contents(cops)
|
274
303
|
|
275
|
-
|
304
|
+
assert_docs_synchronized if ENV['CI'] == 'true'
|
276
305
|
ensure
|
277
306
|
RuboCop::ConfigLoader.default_configuration = nil
|
278
307
|
end
|