rubocop-minitest 0.6.2 → 0.10.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 +5 -5
- data/.circleci/config.yml +0 -3
- data/.gitattributes +1 -0
- data/.rubocop.yml +2 -1
- data/.rubocop_todo.yml +0 -7
- data/CHANGELOG.md +65 -0
- data/Gemfile +1 -1
- data/README.md +5 -1
- data/Rakefile +29 -0
- data/config/default.yml +103 -18
- 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 +1 -0
- data/{manual → legacy-docs}/cops_minitest.md +64 -41
- 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.rb +4 -30
- 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_includes.rb +4 -4
- data/lib/rubocop/cop/minitest/assert_instance_of.rb +4 -38
- data/lib/rubocop/cop/minitest/assert_kind_of.rb +25 -0
- data/lib/rubocop/cop/minitest/assert_match.rb +4 -39
- data/lib/rubocop/cop/minitest/assert_nil.rb +2 -2
- 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_respond_to.rb +10 -45
- data/lib/rubocop/cop/minitest/assert_silent.rb +45 -0
- data/lib/rubocop/cop/minitest/assert_truthy.rb +2 -2
- data/lib/rubocop/cop/minitest/assertion_in_lifecycle_hook.rb +43 -0
- data/lib/rubocop/cop/minitest/global_expectations.rb +95 -0
- 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_empty.rb +4 -30
- data/lib/rubocop/cop/minitest/refute_false.rb +3 -3
- data/lib/rubocop/cop/minitest/refute_in_delta.rb +27 -0
- data/lib/rubocop/cop/minitest/refute_includes.rb +4 -4
- data/lib/rubocop/cop/minitest/refute_instance_of.rb +4 -38
- data/lib/rubocop/cop/minitest/refute_kind_of.rb +25 -0
- data/lib/rubocop/cop/minitest/refute_match.rb +4 -39
- data/lib/rubocop/cop/minitest/refute_nil.rb +2 -2
- data/lib/rubocop/cop/minitest/refute_path_exists.rb +58 -0
- data/lib/rubocop/cop/minitest/refute_respond_to.rb +10 -45
- 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 +17 -1
- 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 +102 -0
- 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.6.2.md +5 -0
- data/relnotes/v0.7.0.md +13 -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 -52
- data/tasks/cut_release.rake +16 -0
- metadata +45 -15
- data/lib/rubocop/cop/mixin/includes_cop_rule.rb +0 -78
@@ -14,38 +14,9 @@ module RuboCop
|
|
14
14
|
# assert_equal("rubocop-minitest", actual)
|
15
15
|
#
|
16
16
|
class AssertEqual < Cop
|
17
|
-
|
17
|
+
extend MinitestCopRule
|
18
18
|
|
19
|
-
|
20
|
-
'`assert(%<over>s)`.'
|
21
|
-
|
22
|
-
def_node_matcher :assert_equal, <<~PATTERN
|
23
|
-
(send nil? :assert $(send $_ :== $_) $...)
|
24
|
-
PATTERN
|
25
|
-
|
26
|
-
def on_send(node)
|
27
|
-
assert_equal(node) do |first_receiver_arg, expected, actual, rest_receiver_arg|
|
28
|
-
message = rest_receiver_arg.first
|
29
|
-
preferred = [expected.source, actual.source, message&.source]
|
30
|
-
.compact.join(', ')
|
31
|
-
over = [first_receiver_arg.source, message&.source].compact.join(', ')
|
32
|
-
|
33
|
-
offense_message = format(MSG, preferred: preferred, over: over)
|
34
|
-
|
35
|
-
add_offense(node, message: offense_message)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def autocorrect(node)
|
40
|
-
lambda do |corrector|
|
41
|
-
assert_equal(node) do |_, expected, actual|
|
42
|
-
corrector.replace(node.loc.selector, 'assert_equal')
|
43
|
-
|
44
|
-
replacement = [expected, actual].map(&:source).join(', ')
|
45
|
-
corrector.replace(first_argument_range(node), replacement)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
19
|
+
define_rule :assert, target_method: :==, preferred_method: :assert_equal
|
49
20
|
end
|
50
21
|
end
|
51
22
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Minitest
|
6
|
+
# This cop enforces the test to use `assert_in_delta`
|
7
|
+
# instead of using `assert_equal` to compare floats.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# assert_equal(0.2, actual)
|
12
|
+
# assert_equal(0.2, actual, 'message')
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# assert_in_delta(0.2, actual)
|
16
|
+
# assert_in_delta(0.2, actual, 0.001, 'message')
|
17
|
+
#
|
18
|
+
class AssertInDelta < Cop
|
19
|
+
include InDeltaMixin
|
20
|
+
|
21
|
+
def_node_matcher :equal_floats_call, <<~PATTERN
|
22
|
+
(send nil? :assert_equal $_ $_ $...)
|
23
|
+
PATTERN
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -9,16 +9,16 @@ module RuboCop
|
|
9
9
|
# @example
|
10
10
|
# # bad
|
11
11
|
# assert(collection.include?(object))
|
12
|
-
# assert(collection.include?(object), '
|
12
|
+
# assert(collection.include?(object), 'message')
|
13
13
|
#
|
14
14
|
# # good
|
15
15
|
# assert_includes(collection, object)
|
16
|
-
# assert_includes(collection, object, '
|
16
|
+
# assert_includes(collection, object, 'message')
|
17
17
|
#
|
18
18
|
class AssertIncludes < Cop
|
19
|
-
extend
|
19
|
+
extend MinitestCopRule
|
20
20
|
|
21
|
-
|
21
|
+
define_rule :assert, target_method: :include?, preferred_method: :assert_includes
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
@@ -9,50 +9,16 @@ module RuboCop
|
|
9
9
|
# @example
|
10
10
|
# # bad
|
11
11
|
# assert(object.instance_of?(Class))
|
12
|
-
# assert(object.instance_of?(Class), '
|
12
|
+
# assert(object.instance_of?(Class), 'message')
|
13
13
|
#
|
14
14
|
# # good
|
15
15
|
# assert_instance_of(Class, object)
|
16
|
-
# assert_instance_of(Class, object, '
|
16
|
+
# assert_instance_of(Class, object, 'message')
|
17
17
|
#
|
18
18
|
class AssertInstanceOf < Cop
|
19
|
-
|
19
|
+
extend MinitestCopRule
|
20
20
|
|
21
|
-
|
22
|
-
'`assert(%<receiver>s)`.'
|
23
|
-
|
24
|
-
def_node_matcher :assert_with_instance_of, <<~PATTERN
|
25
|
-
(send nil? :assert $(send $_ :instance_of? $_) $...)
|
26
|
-
PATTERN
|
27
|
-
|
28
|
-
def on_send(node)
|
29
|
-
assert_with_instance_of(node) do |first_receiver_arg, object, method, rest_args|
|
30
|
-
message = rest_args.first
|
31
|
-
arguments = node_arguments(object, method, message)
|
32
|
-
receiver = [first_receiver_arg.source, message&.source].compact.join(', ')
|
33
|
-
|
34
|
-
offense_message = format(MSG, arguments: arguments, receiver: receiver)
|
35
|
-
|
36
|
-
add_offense(node, message: offense_message)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def autocorrect(node)
|
41
|
-
lambda do |corrector|
|
42
|
-
assert_with_instance_of(node) do |_, object, method|
|
43
|
-
corrector.replace(node.loc.selector, 'assert_instance_of')
|
44
|
-
|
45
|
-
replacement = [method, object].map(&:source).join(', ')
|
46
|
-
corrector.replace(first_argument_range(node), replacement)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
private
|
52
|
-
|
53
|
-
def node_arguments(object, method, message)
|
54
|
-
[method, object, message].compact.map(&:source).join(', ')
|
55
|
-
end
|
21
|
+
define_rule :assert, target_method: :instance_of?, inverse: true
|
56
22
|
end
|
57
23
|
end
|
58
24
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Minitest
|
6
|
+
# This cop enforces the test to use `assert_kind_of(Class, object)`
|
7
|
+
# over `assert(object.kind_of?(Class))`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# assert(object.kind_of?(Class))
|
12
|
+
# assert(object.kind_of?(Class), 'message')
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# assert_kind_of(Class, object)
|
16
|
+
# assert_kind_of(Class, object, 'message')
|
17
|
+
#
|
18
|
+
class AssertKindOf < Cop
|
19
|
+
extend MinitestCopRule
|
20
|
+
|
21
|
+
define_rule :assert, target_method: :kind_of?, inverse: true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -9,51 +9,16 @@ module RuboCop
|
|
9
9
|
# @example
|
10
10
|
# # bad
|
11
11
|
# assert(matcher.match(string))
|
12
|
-
# assert(matcher.match(string), '
|
12
|
+
# assert(matcher.match(string), 'message')
|
13
13
|
#
|
14
14
|
# # good
|
15
15
|
# assert_match(regex, string)
|
16
|
-
# assert_match(matcher, string, '
|
16
|
+
# assert_match(matcher, string, 'message')
|
17
17
|
#
|
18
18
|
class AssertMatch < Cop
|
19
|
-
|
19
|
+
extend MinitestCopRule
|
20
20
|
|
21
|
-
|
22
|
-
'`assert(%<receiver>s)`.'
|
23
|
-
|
24
|
-
def_node_matcher :assert_with_match, <<~PATTERN
|
25
|
-
(send nil? :assert $(send $_ :match $_) $...)
|
26
|
-
PATTERN
|
27
|
-
|
28
|
-
def on_send(node)
|
29
|
-
assert_with_match(node) do
|
30
|
-
|first_receiver_arg, matcher, actual, rest_receiver_arg|
|
31
|
-
message = rest_receiver_arg.first
|
32
|
-
arguments = node_arguments(matcher, actual, message)
|
33
|
-
receiver = [first_receiver_arg.source, message&.source].compact.join(', ')
|
34
|
-
|
35
|
-
offense_message = format(MSG, arguments: arguments, receiver: receiver)
|
36
|
-
|
37
|
-
add_offense(node, message: offense_message)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def autocorrect(node)
|
42
|
-
lambda do |corrector|
|
43
|
-
assert_with_match(node) do |_, matcher, actual|
|
44
|
-
corrector.replace(node.loc.selector, 'assert_match')
|
45
|
-
|
46
|
-
replacement = [matcher, actual].map(&:source).join(', ')
|
47
|
-
corrector.replace(first_argument_range(node), replacement)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
def node_arguments(matcher, actual, message)
|
55
|
-
[matcher.source, actual.source, message&.source].compact.join(', ')
|
56
|
-
end
|
21
|
+
define_rule :assert, target_method: :match
|
57
22
|
end
|
58
23
|
end
|
59
24
|
end
|
@@ -9,11 +9,11 @@ module RuboCop
|
|
9
9
|
# @example
|
10
10
|
# # bad
|
11
11
|
# assert_equal(nil, actual)
|
12
|
-
# assert_equal(nil, actual, '
|
12
|
+
# assert_equal(nil, actual, 'message')
|
13
13
|
#
|
14
14
|
# # good
|
15
15
|
# assert_nil(actual)
|
16
|
-
# assert_nil(actual, '
|
16
|
+
# assert_nil(actual, 'message')
|
17
17
|
#
|
18
18
|
class AssertNil < Cop
|
19
19
|
include ArgumentRangeHelper
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Minitest
|
6
|
+
# This cop checks for opportunities to use `assert_output`.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# $stdout = StringIO.new
|
11
|
+
# puts object.method
|
12
|
+
# $stdout.rewind
|
13
|
+
# assert_match expected, $stdout.read
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# assert_output(expected) { puts object.method }
|
17
|
+
#
|
18
|
+
class AssertOutput < Cop
|
19
|
+
include MinitestExplorationHelpers
|
20
|
+
|
21
|
+
MSG = 'Use `assert_output` instead of mutating %<name>s.'
|
22
|
+
OUTPUT_GLOBAL_VARIABLES = %i[$stdout $stderr].freeze
|
23
|
+
|
24
|
+
def on_gvasgn(node)
|
25
|
+
test_case_node = find_test_case(node)
|
26
|
+
return unless test_case_node
|
27
|
+
|
28
|
+
gvar_name = node.children.first
|
29
|
+
return unless OUTPUT_GLOBAL_VARIABLES.include?(gvar_name)
|
30
|
+
|
31
|
+
assertions(test_case_node).each do |assertion|
|
32
|
+
add_offense(assertion, message: format(MSG, name: gvar_name)) if references_gvar?(assertion, gvar_name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def find_test_case(node)
|
39
|
+
def_ancestor = node.each_ancestor(:def).first
|
40
|
+
def_ancestor if test_case?(def_ancestor)
|
41
|
+
end
|
42
|
+
|
43
|
+
def references_gvar?(assertion, gvar_name)
|
44
|
+
assertion.each_descendant(:gvar).any? { |d| d.children.first == gvar_name }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Minitest
|
6
|
+
# This cop enforces the test to use `assert_path_exists`
|
7
|
+
# instead of using `assert(File.exist?(path))`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# assert(File.exist?(path))
|
12
|
+
# assert(File.exist?(path), 'message')
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# assert_path_exists(path)
|
16
|
+
# assert_path_exists(path, 'message')
|
17
|
+
#
|
18
|
+
class AssertPathExists < Cop
|
19
|
+
MSG = 'Prefer using `%<good_method>s` over `%<bad_method>s`.'
|
20
|
+
|
21
|
+
def_node_matcher :assert_file_exists, <<~PATTERN
|
22
|
+
(send nil? :assert
|
23
|
+
(send
|
24
|
+
(const _ :File) {:exist? :exists?} $_)
|
25
|
+
$...)
|
26
|
+
PATTERN
|
27
|
+
|
28
|
+
def on_send(node)
|
29
|
+
assert_file_exists(node) do |path, failure_message|
|
30
|
+
failure_message = failure_message.first
|
31
|
+
good_method = build_good_method(path, failure_message)
|
32
|
+
message = format(MSG, good_method: good_method, bad_method: node.source)
|
33
|
+
|
34
|
+
add_offense(node, message: message)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def autocorrect(node)
|
39
|
+
assert_file_exists(node) do |path, failure_message|
|
40
|
+
failure_message = failure_message.first
|
41
|
+
|
42
|
+
lambda do |corrector|
|
43
|
+
replacement = build_good_method(path, failure_message)
|
44
|
+
corrector.replace(node, replacement)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def build_good_method(path, message)
|
52
|
+
args = [path.source, message&.source].compact.join(', ')
|
53
|
+
"assert_path_exists(#{args})"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -3,59 +3,24 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Minitest
|
6
|
-
# This cop enforces the use of `assert_respond_to(object, :
|
7
|
-
# over `assert(object.respond_to?(:
|
6
|
+
# This cop enforces the use of `assert_respond_to(object, :do_something)`
|
7
|
+
# over `assert(object.respond_to?(:do_something))`.
|
8
8
|
#
|
9
9
|
# @example
|
10
10
|
# # bad
|
11
|
-
# assert(object.respond_to?(:
|
12
|
-
# assert(object.respond_to?(:
|
13
|
-
# assert(respond_to?(:
|
11
|
+
# assert(object.respond_to?(:do_something))
|
12
|
+
# assert(object.respond_to?(:do_something), 'message')
|
13
|
+
# assert(respond_to?(:do_something))
|
14
14
|
#
|
15
15
|
# # good
|
16
|
-
# assert_respond_to(object, :
|
17
|
-
# assert_respond_to(object, :
|
18
|
-
# assert_respond_to(self,
|
16
|
+
# assert_respond_to(object, :do_something)
|
17
|
+
# assert_respond_to(object, :do_something, 'message')
|
18
|
+
# assert_respond_to(self, :do_something)
|
19
19
|
#
|
20
20
|
class AssertRespondTo < Cop
|
21
|
-
|
21
|
+
extend MinitestCopRule
|
22
22
|
|
23
|
-
|
24
|
-
'`assert(%<over>s)`.'
|
25
|
-
|
26
|
-
def_node_matcher :assert_with_respond_to, <<~PATTERN
|
27
|
-
(send nil? :assert $(send $_ :respond_to? $_) $...)
|
28
|
-
PATTERN
|
29
|
-
|
30
|
-
def on_send(node)
|
31
|
-
assert_with_respond_to(node) do |over, object, method, rest_args|
|
32
|
-
custom_message = rest_args.first
|
33
|
-
preferred = build_preferred_arguments(object, method, custom_message)
|
34
|
-
over = [over, custom_message].compact.map(&:source).join(', ')
|
35
|
-
message = format(MSG, preferred: preferred, over: over)
|
36
|
-
add_offense(node, message: message)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def autocorrect(node)
|
41
|
-
lambda do |corrector|
|
42
|
-
assert_with_respond_to(node) do |_, object, method|
|
43
|
-
corrector.replace(node.loc.selector, 'assert_respond_to')
|
44
|
-
|
45
|
-
object = object ? object.source : 'self'
|
46
|
-
replacement = [object, method.source].join(', ')
|
47
|
-
corrector.replace(first_argument_range(node), replacement)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
private
|
53
|
-
|
54
|
-
def build_preferred_arguments(receiver, method, message)
|
55
|
-
receiver = receiver ? receiver.source : 'self'
|
56
|
-
|
57
|
-
[receiver, method.source, message&.source].compact.join(', ')
|
58
|
-
end
|
23
|
+
define_rule :assert, target_method: :respond_to?
|
59
24
|
end
|
60
25
|
end
|
61
26
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Minitest
|
6
|
+
# This cop enforces the test to use `assert_silent { ... }`
|
7
|
+
# instead of using `assert_output('', '') { ... }`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# assert_output('', '') { puts object.do_something }
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# assert_silent { puts object.do_something }
|
15
|
+
#
|
16
|
+
class AssertSilent < Cop
|
17
|
+
MSG = 'Prefer using `assert_silent` over `assert_output("", "")`.'
|
18
|
+
|
19
|
+
def_node_matcher :assert_silent_candidate?, <<~PATTERN
|
20
|
+
(block
|
21
|
+
(send nil? :assert_output
|
22
|
+
#empty_string?
|
23
|
+
#empty_string?)
|
24
|
+
...)
|
25
|
+
PATTERN
|
26
|
+
|
27
|
+
def on_block(node)
|
28
|
+
add_offense(node.send_node) if assert_silent_candidate?(node)
|
29
|
+
end
|
30
|
+
|
31
|
+
def autocorrect(node)
|
32
|
+
lambda do |corrector|
|
33
|
+
corrector.replace(node, 'assert_silent')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def empty_string?(node)
|
40
|
+
node.str_type? && node.value.empty?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|