rubocop-minitest 0.4.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +3 -0
  3. data/.github/FUNDING.yml +2 -1
  4. data/.rubocop_todo.yml +5 -5
  5. data/CHANGELOG.md +32 -0
  6. data/Gemfile +1 -1
  7. data/LICENSE.txt +1 -1
  8. data/README.md +2 -2
  9. data/config/default.yml +17 -0
  10. data/lib/rubocop/cop/minitest/assert_empty.rb +5 -5
  11. data/lib/rubocop/cop/minitest/assert_empty_literal.rb +36 -0
  12. data/lib/rubocop/cop/minitest/assert_equal.rb +8 -13
  13. data/lib/rubocop/cop/minitest/assert_includes.rb +2 -37
  14. data/lib/rubocop/cop/minitest/assert_instance_of.rb +7 -8
  15. data/lib/rubocop/cop/minitest/assert_match.rb +60 -0
  16. data/lib/rubocop/cop/minitest/assert_nil.rb +8 -3
  17. data/lib/rubocop/cop/minitest/assert_respond_to.rb +20 -9
  18. data/lib/rubocop/cop/minitest/assert_truthy.rb +8 -3
  19. data/lib/rubocop/cop/minitest/refute_empty.rb +5 -5
  20. data/lib/rubocop/cop/minitest/refute_equal.rb +7 -8
  21. data/lib/rubocop/cop/minitest/refute_false.rb +38 -9
  22. data/lib/rubocop/cop/minitest/refute_includes.rb +2 -37
  23. data/lib/rubocop/cop/minitest/refute_instance_of.rb +7 -8
  24. data/lib/rubocop/cop/minitest/refute_match.rb +60 -0
  25. data/lib/rubocop/cop/minitest/refute_nil.rb +8 -3
  26. data/lib/rubocop/cop/minitest/refute_respond_to.rb +20 -9
  27. data/lib/rubocop/cop/minitest_cops.rb +5 -0
  28. data/lib/rubocop/cop/mixin/argument_range_helper.rb +31 -0
  29. data/lib/rubocop/cop/mixin/includes_cop_rule.rb +78 -0
  30. data/lib/rubocop/minitest/inject.rb +1 -1
  31. data/lib/rubocop/minitest/version.rb +1 -1
  32. data/manual/cops.md +3 -0
  33. data/manual/cops_minitest.md +77 -0
  34. data/relnotes/v0.4.1.md +5 -0
  35. data/relnotes/v0.5.0.md +5 -0
  36. data/relnotes/v0.5.1.md +5 -0
  37. data/relnotes/v0.6.0.md +5 -0
  38. data/relnotes/v0.6.1.md +6 -0
  39. data/rubocop-minitest.gemspec +2 -2
  40. metadata +16 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: '06679af4eeb82332ac490d8aceb5cd0668cb3686e1bf7f7d8fb83d1bc6d99f50'
4
- data.tar.gz: f967a4cff6cfdc23182befb62fbc4363197213065acb21da6fc99e62d685951d
2
+ SHA1:
3
+ metadata.gz: ba7306fba69394bb98154a2d39b7f755587ad0e4
4
+ data.tar.gz: 9d20cb250e999413a04620cfbe0eb5c930a3b83e
5
5
  SHA512:
6
- metadata.gz: 3b2bbdefbd8de0346adb4b06884ab674ed88588bfaf8550ebcbadcd8f07be0199a0270c50ac15a9f36f607e157b3edde095db6e7caf3814cd8ff9ecc7350b9f3
7
- data.tar.gz: 0f45beaa717b0d0135dd41462d372a794a66aea60e700f6cd942b79cd01a61f69914d45ad83ccad26ca95aa88b681d20f04b6b2b2e0a5278464399ef1a8ee47c
6
+ metadata.gz: c9e12069624b30051284458118b7447fd5d52697d97cbd150f1062898cbd2a5975d2bb24d13185afd94b13ad40702a242ba180c1484e2b6761f0218f30e0bab3
7
+ data.tar.gz: f33c1179084c1ac358d702c4537b84eba697851368a6c3d9245e54abf20e4acd4149c7d0bfb833ee3c9b42537cde7d0bfca6bd30420fd1e1480e5386490d0d6c
@@ -35,6 +35,9 @@ workflows:
35
35
  - rake_default:
36
36
  name: Ruby 2.6
37
37
  image: circleci/ruby:2.6
38
+ - rake_default:
39
+ name: Ruby 2.7
40
+ image: circleci/ruby:2.7
38
41
  - rake_default:
39
42
  name: Ruby HEAD
40
43
  image: rubocophq/circleci-ruby-snapshot:latest # Nightly snapshot build
@@ -1,6 +1,7 @@
1
1
  # These are supported funding model platforms
2
2
 
3
- github: bbatsov
3
+ github: [bbatsov, koic]
4
4
  patreon: bbatsov
5
5
  open_collective: rubocop
6
+ tidelift: "rubygems/rubocop"
6
7
  custom: https://www.paypal.me/bbatsov
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2019-08-07 15:41:02 +0900 using RuboCop version 0.74.0.
3
+ # on 2019-12-21 01:15:41 +0900 using RuboCop version 0.78.0.
4
4
  # The point is for the user to remove these configuration records
5
5
  # one by one as the offenses are removed from the code base.
6
6
  # Note that changes in the inspected code, or installation of new
@@ -10,14 +10,14 @@
10
10
  Metrics/AbcSize:
11
11
  Max: 17
12
12
 
13
- # Offense count: 5
13
+ # Offense count: 19
14
14
  # Configuration parameters: CountComments, ExcludedMethods.
15
15
  Metrics/MethodLength:
16
16
  Max: 14
17
17
 
18
- # Offense count: 2
18
+ # Offense count: 40
19
19
  # Cop supports --auto-correct.
20
20
  # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
21
21
  # URISchemes: http, https
22
- Metrics/LineLength:
23
- Max: 87
22
+ Layout/LineLength:
23
+ Max: 90
@@ -2,6 +2,37 @@
2
2
 
3
3
  ## master (unreleased)
4
4
 
5
+ ## 0.6.1 (2020-02-18)
6
+
7
+ ### Bug fixes
8
+
9
+ * [#52](https://github.com/rubocop-hq/rubocop-minitest/issues/52): Make `Minitest/RefuteFalse` cop aware of `assert(!test)`. ([@koic][])
10
+ * [#52](https://github.com/rubocop-hq/rubocop-minitest/issues/52): Fix a false negative for `Minitest/AssertIncludes` and `Minitest/RefuteIncludes` when an argument is enclosed in redundant parentheses. ([@koic][])
11
+
12
+ ## 0.6.0 (2020-02-07)
13
+
14
+ ### New features
15
+
16
+ * [#49](https://github.com/rubocop-hq/rubocop-minitest/pull/49): New cops `AssertMatch` and `RefuteMatch` check for use of `assert_match`/`refute_match` instead of `assert(foo.match(bar))`/`refute(foo.match(bar))`. ([@fsateler][])
17
+
18
+ ## 0.5.1 (2019-12-25)
19
+
20
+ ### Bug fixes
21
+
22
+ * [#42](https://github.com/rubocop-hq/rubocop-minitest/issues/42): Fix an incorrect autocorrect for some cops of `Minitest` department when using heredoc message. ([@koic][])
23
+
24
+ ## 0.5.0 (2019-11-24)
25
+
26
+ ### New features
27
+
28
+ * [#32](https://github.com/rubocop-hq/rubocop-minitest/issues/32): Add new `Minitest/AssertEmptyLiteral` cop. ([@tejasbubane][])
29
+
30
+ ## 0.4.1 (2019-11-10)
31
+
32
+ ### Bug fixes
33
+
34
+ * [#39](https://github.com/rubocop-hq/rubocop-minitest/issues/39): Fix an incorrect autocorrect for `Minitest/AssertRespondTo` and `Minitest/RefuteRespondTo` when using assertion method calling `respond_to` with receiver omitted. ([@koic][])
35
+
5
36
  ## 0.4.0 (2019-11-07)
6
37
 
7
38
  ### New features
@@ -56,3 +87,4 @@
56
87
  [@tejasbubane]: https://github.com/tejasbubane
57
88
  [@abhaynikam]: https://github.com/abhaynikam
58
89
  [@herwinw]: https://github.com/herwinw
90
+ [@fsateler]: https://github.com/fsateler
data/Gemfile CHANGED
@@ -9,5 +9,5 @@ gemspec
9
9
  gem 'bump', require: false
10
10
  gem 'rake'
11
11
  gem 'rubocop', github: 'rubocop-hq/rubocop'
12
- gem 'rubocop-performance', '~> 1.4.0'
12
+ gem 'rubocop-performance', '~> 1.5.0'
13
13
  gem 'yard', '~> 0.9'
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2019 Bozhidar Batsov, Jonas Arvidsson, Koichi ITO
3
+ Copyright (c) 2019-2020 Bozhidar Batsov, Jonas Arvidsson, Koichi ITO
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -16,8 +16,8 @@ gem install rubocop-minitest
16
16
 
17
17
  or if you use bundler put this in your `Gemfile`
18
18
 
19
- ```
20
- gem 'rubocop-minitest'
19
+ ```ruby
20
+ gem 'rubocop-minitest', require: false
21
21
  ```
22
22
 
23
23
  ## Usage
@@ -9,12 +9,23 @@ Minitest/AssertEmpty:
9
9
  Enabled: true
10
10
  VersionAdded: '0.2'
11
11
 
12
+ Minitest/AssertEmptyLiteral:
13
+ Description: 'This cop enforces the test to use `assert_empty` instead of using `assert([], object)` or `assert({}, object)`.'
14
+ Enabled: true
15
+ VersionAdded: '0.5'
16
+
12
17
  Minitest/AssertEqual:
13
18
  Description: 'This cop enforces the test to use `assert_equal` instead of using `assert(expected == actual)`.'
14
19
  StyleGuide: 'https://github.com/rubocop-hq/minitest-style-guide#assert-equal-arguments-order'
15
20
  Enabled: true
16
21
  VersionAdded: '0.4'
17
22
 
23
+ Minitest/AssertMatch:
24
+ Description: 'This cop enforces the test to use `assert_match` instead of using `assert(matcher.match(object))`.'
25
+ StyleGuide: 'https://github.com/rubocop-hq/minitest-style-guide#assert-match'
26
+ Enabled: true
27
+ VersionAdded: '0.6'
28
+
18
29
  Minitest/AssertIncludes:
19
30
  Description: 'This cop enforces the test to use `assert_includes` instead of using `assert(collection.include?(object))`.'
20
31
  StyleGuide: 'https://github.com/rubocop-hq/minitest-style-guide#assert-includes'
@@ -69,6 +80,12 @@ Minitest/RefuteIncludes:
69
80
  Enabled: true
70
81
  VersionAdded: '0.3'
71
82
 
83
+ Minitest/RefuteMatch:
84
+ Description: 'This cop enforces the test to use `refute_match` instead of using `refute(matcher.match(object))`.'
85
+ StyleGuide: 'https://github.com/rubocop-hq/minitest-style-guide#refute-match'
86
+ Enabled: true
87
+ VersionAdded: '0.6'
88
+
72
89
  Minitest/RefuteInstanceOf:
73
90
  Description: 'This cop enforces the test to use `refute_instance_of(Class, object)` over `refute(object.instance_of?(Class))`.'
74
91
  StyleGuide: 'https://github.com/rubocop-hq/minitest-style-guide#refute-instance-of'
@@ -16,6 +16,8 @@ module RuboCop
16
16
  # assert_empty(object, 'the message')
17
17
  #
18
18
  class AssertEmpty < Cop
19
+ include ArgumentRangeHelper
20
+
19
21
  MSG = 'Prefer using `assert_empty(%<arguments>s)` over ' \
20
22
  '`assert(%<receiver>s)`.'
21
23
 
@@ -37,11 +39,9 @@ module RuboCop
37
39
 
38
40
  def autocorrect(node)
39
41
  lambda do |corrector|
40
- assert_with_empty(node) do |_first_receiver_arg, actual, rest_receiver_arg|
41
- message = rest_receiver_arg.first
42
-
43
- replacement = [actual.source, message&.source].compact.join(', ')
44
- corrector.replace(node.loc.expression, "assert_empty(#{replacement})")
42
+ assert_with_empty(node) do |_, actual_arg|
43
+ corrector.replace(node.loc.selector, 'assert_empty')
44
+ corrector.replace(first_argument_range(node), actual_arg.source)
45
45
  end
46
46
  end
47
47
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Minitest
6
+ # This cop enforces the test to use `assert_empty`
7
+ # instead of using `assert([], object)`.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # assert([], object)
12
+ # assert({}, object)
13
+ #
14
+ # # good
15
+ # assert_empty(object)
16
+ #
17
+ class AssertEmptyLiteral < Cop
18
+ MSG = 'Prefer using `assert_empty(%<arguments>s)` over ' \
19
+ '`assert(%<literal>s, %<arguments>s)`.'
20
+
21
+ def_node_matcher :assert_with_empty_literal, <<~PATTERN
22
+ (send nil? :assert ${hash array} $...)
23
+ PATTERN
24
+
25
+ def on_send(node)
26
+ assert_with_empty_literal(node) do |literal, matchers|
27
+ args = matchers.map(&:source).join(', ')
28
+
29
+ message = format(MSG, literal: literal.source, arguments: args)
30
+ add_offense(node, message: message)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -14,6 +14,8 @@ module RuboCop
14
14
  # assert_equal("rubocop-minitest", actual)
15
15
  #
16
16
  class AssertEqual < Cop
17
+ include ArgumentRangeHelper
18
+
17
19
  MSG = 'Prefer using `assert_equal(%<preferred>s)` over ' \
18
20
  '`assert(%<over>s)`.'
19
21
 
@@ -22,9 +24,7 @@ module RuboCop
22
24
  PATTERN
23
25
 
24
26
  def on_send(node)
25
- assert_equal(node) do
26
- |first_receiver_arg, expected, actual, rest_receiver_arg|
27
-
27
+ assert_equal(node) do |first_receiver_arg, expected, actual, rest_receiver_arg|
28
28
  message = rest_receiver_arg.first
29
29
  preferred = [expected.source, actual.source, message&.source]
30
30
  .compact.join(', ')
@@ -38,19 +38,14 @@ module RuboCop
38
38
 
39
39
  def autocorrect(node)
40
40
  lambda do |corrector|
41
- assert_equal(node) do |_receiver, expected, actual, rest_receiver_arg|
42
- message = rest_receiver_arg.first
43
- replacement = node_arguments(expected, actual, message)
44
- corrector.replace(node.loc.expression, "assert_equal(#{replacement})")
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)
45
46
  end
46
47
  end
47
48
  end
48
-
49
- private
50
-
51
- def node_arguments(expected, actual, message)
52
- [expected.source, actual.source, message&.source].compact.join(', ')
53
- end
54
49
  end
55
50
  end
56
51
  end
@@ -16,44 +16,9 @@ module RuboCop
16
16
  # assert_includes(collection, object, 'the message')
17
17
  #
18
18
  class AssertIncludes < Cop
19
- MSG = 'Prefer using `assert_includes(%<arguments>s)` over ' \
20
- '`assert(%<receiver>s)`.'
19
+ extend IncludesCopRule
21
20
 
22
- def_node_matcher :assert_with_includes, <<~PATTERN
23
- (send nil? :assert $(send $_ :include? $_) $...)
24
- PATTERN
25
-
26
- def on_send(node)
27
- assert_with_includes(node) do
28
- |first_receiver_arg, collection, actual, rest_receiver_arg|
29
-
30
- message = rest_receiver_arg.first
31
- arguments = node_arguments(collection, actual, 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_includes(node) do
43
- |_receiver, collection, actual, rest_receiver_arg|
44
-
45
- message = rest_receiver_arg.first
46
- replacement = node_arguments(collection, actual, message)
47
- corrector.replace(node.loc.expression, "assert_includes(#{replacement})")
48
- end
49
- end
50
- end
51
-
52
- private
53
-
54
- def node_arguments(collection, actual, message)
55
- [collection.source, actual.source, message&.source].compact.join(', ')
56
- end
21
+ rule target_method: :assert, prefer_method: :assert_includes
57
22
  end
58
23
  end
59
24
  end
@@ -16,6 +16,8 @@ module RuboCop
16
16
  # assert_instance_of(Class, object, 'the message')
17
17
  #
18
18
  class AssertInstanceOf < Cop
19
+ include ArgumentRangeHelper
20
+
19
21
  MSG = 'Prefer using `assert_instance_of(%<arguments>s)` over ' \
20
22
  '`assert(%<receiver>s)`.'
21
23
 
@@ -24,9 +26,7 @@ module RuboCop
24
26
  PATTERN
25
27
 
26
28
  def on_send(node)
27
- assert_with_instance_of(node) do
28
- |first_receiver_arg, object, method, rest_args|
29
-
29
+ assert_with_instance_of(node) do |first_receiver_arg, object, method, rest_args|
30
30
  message = rest_args.first
31
31
  arguments = node_arguments(object, method, message)
32
32
  receiver = [first_receiver_arg.source, message&.source].compact.join(', ')
@@ -39,12 +39,11 @@ module RuboCop
39
39
 
40
40
  def autocorrect(node)
41
41
  lambda do |corrector|
42
- assert_with_instance_of(node) do |_, object, method, rest_args|
43
- message = rest_args.first
44
- arguments = node_arguments(object, method, message)
42
+ assert_with_instance_of(node) do |_, object, method|
43
+ corrector.replace(node.loc.selector, 'assert_instance_of')
45
44
 
46
- replacement = "assert_instance_of(#{arguments})"
47
- corrector.replace(node.loc.expression, replacement)
45
+ replacement = [method, object].map(&:source).join(', ')
46
+ corrector.replace(first_argument_range(node), replacement)
48
47
  end
49
48
  end
50
49
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Minitest
6
+ # This cop enforces the test to use `assert_match`
7
+ # instead of using `assert(matcher.match(string))`.
8
+ #
9
+ # @example
10
+ # # bad
11
+ # assert(matcher.match(string))
12
+ # assert(matcher.match(string), 'the message')
13
+ #
14
+ # # good
15
+ # assert_match(regex, string)
16
+ # assert_match(matcher, string, 'the message')
17
+ #
18
+ class AssertMatch < Cop
19
+ include ArgumentRangeHelper
20
+
21
+ MSG = 'Prefer using `assert_match(%<arguments>s)` over ' \
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
57
+ end
58
+ end
59
+ end
60
+ end
@@ -16,6 +16,8 @@ module RuboCop
16
16
  # assert_nil(actual, 'the message')
17
17
  #
18
18
  class AssertNil < Cop
19
+ include ArgumentRangeHelper
20
+
19
21
  MSG = 'Prefer using `assert_nil(%<arguments>s)` over ' \
20
22
  '`assert_equal(nil, %<arguments>s)`.'
21
23
 
@@ -35,9 +37,12 @@ module RuboCop
35
37
 
36
38
  def autocorrect(node)
37
39
  lambda do |corrector|
38
- arguments = node.arguments.reject(&:nil_type?)
39
- replacement = arguments.map(&:source).join(', ')
40
- corrector.replace(node.loc.expression, "assert_nil(#{replacement})")
40
+ assert_equal_with_nil(node) do |actual|
41
+ corrector.replace(node.loc.selector, 'assert_nil')
42
+ corrector.replace(
43
+ first_and_second_arguments_range(node), actual.source
44
+ )
45
+ end
41
46
  end
42
47
  end
43
48
  end
@@ -10,12 +10,16 @@ module RuboCop
10
10
  # # bad
11
11
  # assert(object.respond_to?(:some_method))
12
12
  # assert(object.respond_to?(:some_method), 'the message')
13
+ # assert(respond_to?(:some_method))
13
14
  #
14
15
  # # good
15
16
  # assert_respond_to(object, :some_method)
16
17
  # assert_respond_to(object, :some_method, 'the message')
18
+ # assert_respond_to(self, some_method)
17
19
  #
18
20
  class AssertRespondTo < Cop
21
+ include ArgumentRangeHelper
22
+
19
23
  MSG = 'Prefer using `assert_respond_to(%<preferred>s)` over ' \
20
24
  '`assert(%<over>s)`.'
21
25
 
@@ -26,9 +30,8 @@ module RuboCop
26
30
  def on_send(node)
27
31
  assert_with_respond_to(node) do |over, object, method, rest_args|
28
32
  custom_message = rest_args.first
29
- preferred = [object, method, custom_message]
30
- .compact.map(&:source).join(', ')
31
- over = [over, custom_message].compact.map(&:source).join(', ')
33
+ preferred = build_preferred_arguments(object, method, custom_message)
34
+ over = [over, custom_message].compact.map(&:source).join(', ')
32
35
  message = format(MSG, preferred: preferred, over: over)
33
36
  add_offense(node, message: message)
34
37
  end
@@ -36,15 +39,23 @@ module RuboCop
36
39
 
37
40
  def autocorrect(node)
38
41
  lambda do |corrector|
39
- assert_with_respond_to(node) do |_, object, method, rest_args|
40
- custom_message = rest_args.first
41
- preferred = [object, method, custom_message]
42
- .compact.map(&:source).join(', ')
43
- replacement = "assert_respond_to(#{preferred})"
44
- corrector.replace(node.loc.expression, replacement)
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)
45
48
  end
46
49
  end
47
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
48
59
  end
49
60
  end
50
61
  end