rubocop 0.60.0 → 0.61.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -4
  3. data/config/default.yml +573 -560
  4. data/lib/rubocop.rb +5 -0
  5. data/lib/rubocop/ast/node.rb +1 -1
  6. data/lib/rubocop/ast/sexp.rb +1 -1
  7. data/lib/rubocop/cli.rb +9 -14
  8. data/lib/rubocop/config.rb +4 -3
  9. data/lib/rubocop/config_loader.rb +25 -22
  10. data/lib/rubocop/config_loader_resolver.rb +3 -2
  11. data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +53 -0
  12. data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +73 -0
  13. data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +138 -0
  14. data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +52 -46
  15. data/lib/rubocop/cop/generator.rb +13 -17
  16. data/lib/rubocop/cop/generator/configuration_injector.rb +60 -0
  17. data/lib/rubocop/cop/layout/align_hash.rb +3 -0
  18. data/lib/rubocop/cop/layout/comment_indentation.rb +32 -2
  19. data/lib/rubocop/cop/layout/indent_heredoc.rb +11 -5
  20. data/lib/rubocop/cop/layout/indentation_width.rb +7 -1
  21. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +11 -11
  22. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +1 -1
  23. data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +1 -1
  24. data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +1 -1
  25. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +16 -3
  26. data/lib/rubocop/cop/layout/space_around_block_parameters.rb +30 -17
  27. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +11 -0
  28. data/lib/rubocop/cop/lint/shadowed_exception.rb +2 -5
  29. data/lib/rubocop/cop/lint/useless_access_modifier.rb +1 -1
  30. data/lib/rubocop/cop/metrics/line_length.rb +2 -2
  31. data/lib/rubocop/cop/mixin/trailing_comma.rb +11 -15
  32. data/lib/rubocop/cop/offense.rb +1 -1
  33. data/lib/rubocop/cop/performance/open_struct.rb +46 -0
  34. data/lib/rubocop/cop/performance/redundant_merge.rb +18 -4
  35. data/lib/rubocop/cop/rails/bulk_change_table.rb +2 -2
  36. data/lib/rubocop/cop/rails/dynamic_find_by.rb +15 -8
  37. data/lib/rubocop/cop/rails/http_positional_arguments.rb +17 -14
  38. data/lib/rubocop/cop/rails/http_status.rb +4 -4
  39. data/lib/rubocop/cop/rails/inverse_of.rb +2 -2
  40. data/lib/rubocop/cop/rails/reversible_migration.rb +1 -1
  41. data/lib/rubocop/cop/rails/skips_model_validations.rb +1 -1
  42. data/lib/rubocop/cop/rails/validation.rb +4 -4
  43. data/lib/rubocop/cop/security/open.rb +31 -11
  44. data/lib/rubocop/cop/style/begin_block.rb +6 -0
  45. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +1 -1
  46. data/lib/rubocop/cop/style/empty_case_condition.rb +13 -7
  47. data/lib/rubocop/cop/style/for.rb +9 -78
  48. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +6 -4
  49. data/lib/rubocop/cop/style/global_vars.rb +1 -1
  50. data/lib/rubocop/cop/style/infinite_loop.rb +42 -6
  51. data/lib/rubocop/cop/style/lambda.rb +4 -87
  52. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +221 -16
  53. data/lib/rubocop/cop/style/raise_args.rb +1 -1
  54. data/lib/rubocop/cop/style/regexp_literal.rb +62 -10
  55. data/lib/rubocop/cop/style/unneeded_condition.rb +2 -2
  56. data/lib/rubocop/cop/variable_force.rb +4 -2
  57. data/lib/rubocop/cop/variable_force/variable.rb +2 -0
  58. data/lib/rubocop/magic_comment.rb +1 -1
  59. data/lib/rubocop/remote_config.rb +13 -4
  60. data/lib/rubocop/rspec/expect_offense.rb +1 -1
  61. data/lib/rubocop/runner.rb +15 -4
  62. data/lib/rubocop/version.rb +1 -1
  63. metadata +7 -2
@@ -76,6 +76,7 @@ require_relative 'rubocop/cop/corrector'
76
76
  require_relative 'rubocop/cop/force'
77
77
  require_relative 'rubocop/cop/severity'
78
78
  require_relative 'rubocop/cop/generator'
79
+ require_relative 'rubocop/cop/generator/configuration_injector'
79
80
  require_relative 'rubocop/cop/generator/require_file_injector'
80
81
 
81
82
  require_relative 'rubocop/cop/variable_force'
@@ -150,7 +151,10 @@ require_relative 'rubocop/cop/mixin/unused_argument'
150
151
 
151
152
  require_relative 'rubocop/cop/correctors/alignment_corrector'
152
153
  require_relative 'rubocop/cop/correctors/condition_corrector'
154
+ require_relative 'rubocop/cop/correctors/each_to_for_corrector'
153
155
  require_relative 'rubocop/cop/correctors/empty_line_corrector'
156
+ require_relative 'rubocop/cop/correctors/for_to_each_corrector'
157
+ require_relative 'rubocop/cop/correctors/lambda_literal_to_method_corrector'
154
158
  require_relative 'rubocop/cop/correctors/line_break_corrector'
155
159
  require_relative 'rubocop/cop/correctors/multiline_literal_brace_corrector'
156
160
  require_relative 'rubocop/cop/correctors/ordered_gem_corrector'
@@ -368,6 +372,7 @@ require_relative 'rubocop/cop/performance/fixed_size'
368
372
  require_relative 'rubocop/cop/performance/flat_map'
369
373
  require_relative 'rubocop/cop/performance/inefficient_hash_search'
370
374
  require_relative 'rubocop/cop/performance/lstrip_rstrip'
375
+ require_relative 'rubocop/cop/performance/open_struct'
371
376
  require_relative 'rubocop/cop/performance/range_include'
372
377
  require_relative 'rubocop/cop/performance/redundant_block_call'
373
378
  require_relative 'rubocop/cop/performance/redundant_match'
@@ -54,7 +54,7 @@ module RuboCop
54
54
  OPERATOR_KEYWORDS = %i[and or].freeze
55
55
  SPECIAL_KEYWORDS = %w[__FILE__ __LINE__ __ENCODING__].freeze
56
56
 
57
- # @see http://rubydoc.info/gems/ast/AST/Node:initialize
57
+ # @see https://www.rubydoc.info/gems/ast/AST/Node:initialize
58
58
  def initialize(type, children = [], properties = {})
59
59
  @mutable_attributes = {}
60
60
 
@@ -5,7 +5,7 @@ module RuboCop
5
5
  # This module provides a shorthand method to create a {Node} like
6
6
  # `Parser::AST::Sexp`.
7
7
  #
8
- # @see http://rubydoc.info/gems/ast/AST/Sexp
8
+ # @see https://www.rubydoc.info/gems/ast/AST/Sexp
9
9
  module Sexp
10
10
  # Creates a {Node} with type `type` and children `children`.
11
11
  def s(type, *children)
@@ -10,9 +10,10 @@ module RuboCop
10
10
  SKIPPED_PHASE_1 = 'Phase 1 of 2: run Metrics/LineLength cop (skipped ' \
11
11
  'because the default Metrics/LineLength:Max is ' \
12
12
  'overridden)'.freeze
13
- STATUS_SUCCESS = 0
14
- STATUS_OFFENSES = 1
15
- STATUS_ERROR = 2
13
+ STATUS_SUCCESS = 0
14
+ STATUS_OFFENSES = 1
15
+ STATUS_ERROR = 2
16
+ STATUS_INTERRUPTED = 128 + Signal.list['INT']
16
17
 
17
18
  class Finished < RuntimeError; end
18
19
 
@@ -58,15 +59,6 @@ module RuboCop
58
59
  end
59
60
  # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
60
61
 
61
- def trap_interrupt(runner)
62
- Signal.trap('INT') do
63
- exit!(1) if runner.aborting?
64
- runner.abort
65
- warn
66
- warn 'Exiting... Interrupt again to exit immediately.'
67
- end
68
- end
69
-
70
62
  private
71
63
 
72
64
  def execute_runners(paths)
@@ -118,6 +110,7 @@ module RuboCop
118
110
 
119
111
  def reset_config_and_auto_gen_file
120
112
  @config_store = ConfigStore.new
113
+ @config_store.options_config = @options[:config] if @options[:config]
121
114
  File.open(ConfigLoader::AUTO_GENERATED_FILE, 'w') {}
122
115
  ConfigLoader.add_inheritance_from_auto_generated_file
123
116
  end
@@ -135,6 +128,7 @@ module RuboCop
135
128
  ConfigLoader.debug = @options[:debug]
136
129
  ConfigLoader.auto_gen_config = @options[:auto_gen_config]
137
130
  ConfigLoader.ignore_parent_exclusion = @options[:ignore_parent_exclusion]
131
+ ConfigLoader.options_config = @options[:config]
138
132
 
139
133
  @config_store.options_config = @options[:config] if @options[:config]
140
134
  @config_store.force_default_config! if @options[:force_default_config]
@@ -153,7 +147,6 @@ module RuboCop
153
147
  def execute_runner(paths)
154
148
  runner = Runner.new(@options, @config_store)
155
149
 
156
- trap_interrupt(runner)
157
150
  all_passed = runner.run(paths)
158
151
  display_warning_summary(runner.warnings)
159
152
  display_error_summary(runner.errors)
@@ -161,7 +154,9 @@ module RuboCop
161
154
 
162
155
  all_pass_or_excluded = all_passed || @options[:auto_gen_config]
163
156
 
164
- if all_pass_or_excluded && !runner.aborting? && runner.errors.empty?
157
+ if runner.aborting?
158
+ STATUS_INTERRUPTED
159
+ elsif all_pass_or_excluded && runner.errors.empty?
165
160
  STATUS_SUCCESS
166
161
  else
167
162
  STATUS_OFFENSES
@@ -14,7 +14,7 @@ module RuboCop
14
14
  include PathUtil
15
15
  include FileFinder
16
16
 
17
- COMMON_PARAMS = %w[Exclude Include Severity
17
+ COMMON_PARAMS = %w[Exclude Include Severity inherit_mode
18
18
  AutoCorrect StyleGuide Details].freeze
19
19
  # 2.2 is the oldest officially supported Ruby version.
20
20
  DEFAULT_RUBY_VERSION = 2.2
@@ -440,11 +440,11 @@ module RuboCop
440
440
  end
441
441
 
442
442
  def target_ruby_version
443
- @target_ruby_version ||=
443
+ @target_ruby_version ||= begin
444
444
  if for_all_cops['TargetRubyVersion']
445
445
  @target_ruby_version_source = :rubocop_yml
446
446
 
447
- for_all_cops['TargetRubyVersion']
447
+ for_all_cops['TargetRubyVersion'].to_f
448
448
  elsif target_ruby_version_from_version_file
449
449
  @target_ruby_version_source = :ruby_version_file
450
450
 
@@ -456,6 +456,7 @@ module RuboCop
456
456
  else
457
457
  DEFAULT_RUBY_VERSION
458
458
  end
459
+ end
459
460
  end
460
461
 
461
462
  def target_rails_version
@@ -22,7 +22,8 @@ module RuboCop
22
22
  class << self
23
23
  include FileFinder
24
24
 
25
- attr_accessor :debug, :auto_gen_config, :ignore_parent_exclusion
25
+ attr_accessor :debug, :auto_gen_config, :ignore_parent_exclusion,
26
+ :options_config
26
27
  attr_writer :default_configuration
27
28
 
28
29
  alias debug? debug
@@ -30,7 +31,7 @@ module RuboCop
30
31
  alias ignore_parent_exclusion? ignore_parent_exclusion
31
32
 
32
33
  def clear_options
33
- @debug = @auto_gen_config = nil
34
+ @debug = @auto_gen_config = @options_config = nil
34
35
  FileFinder.root_level = nil
35
36
  end
36
37
 
@@ -43,7 +44,6 @@ module RuboCop
43
44
  resolver.resolve_requires(path, hash)
44
45
 
45
46
  add_missing_namespaces(path, hash)
46
- target_ruby_version_to_f!(hash)
47
47
 
48
48
  resolver.resolve_inheritance_from_gems(hash, hash.delete('inherit_gem'))
49
49
  resolver.resolve_inheritance(path, hash, file, debug?)
@@ -117,36 +117,38 @@ module RuboCop
117
117
  resolver.merge_with_default(config, config_file)
118
118
  end
119
119
 
120
- def target_ruby_version_to_f!(hash)
121
- version = 'TargetRubyVersion'
122
- return unless hash['AllCops'] && hash['AllCops'][version]
123
-
124
- hash['AllCops'][version] = hash['AllCops'][version].to_f
125
- end
126
-
127
120
  def add_inheritance_from_auto_generated_file
128
121
  file_string = " #{AUTO_GENERATED_FILE}"
129
122
 
130
- if File.exist?(DOTFILE)
131
- files = Array(load_yaml_configuration(DOTFILE)['inherit_from'])
123
+ config_file = options_config || DOTFILE
124
+
125
+ if File.exist?(config_file)
126
+ files = Array(load_yaml_configuration(config_file)['inherit_from'])
127
+
132
128
  return if files.include?(AUTO_GENERATED_FILE)
133
129
 
134
130
  files.unshift(AUTO_GENERATED_FILE)
135
131
  file_string = "\n - " + files.join("\n - ") if files.size > 1
136
- rubocop_yml_contents = IO.read(DOTFILE, encoding: Encoding::UTF_8)
137
- .sub(/^inherit_from: *[.\w]+/, '')
138
- .sub(/^inherit_from: *(\n *- *[.\w]+)+/, '')
132
+ rubocop_yml_contents = existing_configuration(config_file)
139
133
  end
140
- write_dotfile(file_string, rubocop_yml_contents)
134
+
135
+ write_config_file(config_file, file_string, rubocop_yml_contents)
136
+
141
137
  puts "Added inheritance from `#{AUTO_GENERATED_FILE}` in `#{DOTFILE}`."
142
138
  end
143
139
 
144
140
  private
145
141
 
146
- def write_dotfile(file_string, rubocop_yml_contents)
147
- File.open(DOTFILE, 'w') do |f|
142
+ def existing_configuration(config_file)
143
+ IO.read(config_file, encoding: Encoding::UTF_8)
144
+ .sub(%r{^inherit_from: *[.\/\w]+}, '')
145
+ .sub(%r{^inherit_from: *(\n *- *[.\/\w]+)+}, '')
146
+ end
147
+
148
+ def write_config_file(file_name, file_string, rubocop_yml_contents)
149
+ File.open(file_name, 'w') do |f|
148
150
  f.write "inherit_from:#{file_string}\n"
149
- f.write "\n#{rubocop_yml_contents}" if rubocop_yml_contents
151
+ f.write "\n#{rubocop_yml_contents}" if rubocop_yml_contents =~ /\S/
150
152
  end
151
153
  end
152
154
 
@@ -181,11 +183,12 @@ module RuboCop
181
183
  if defined?(SafeYAML) && SafeYAML.respond_to?(:load)
182
184
  SafeYAML.load(yaml_code, filename,
183
185
  whitelisted_tags: %w[!ruby/regexp])
184
- elsif RUBY_VERSION >= '2.6'
186
+ # Ruby 2.6+
187
+ elsif Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0.pre1')
185
188
  YAML.safe_load(
186
189
  yaml_code,
187
- whitelist_classes: [Regexp, Symbol],
188
- whitelist_symbols: [],
190
+ permitted_classes: [Regexp, Symbol],
191
+ permitted_symbols: [],
189
192
  aliases: false,
190
193
  filename: filename
191
194
  )
@@ -76,11 +76,11 @@ module RuboCop
76
76
  config_file)
77
77
  end
78
78
 
79
- # Returns a new hash where the parameters of the given config hash have
80
- # been replaced by parameters returned by the given block.
81
79
  # Return a recursive merge of two hashes. That is, a normal hash merge,
82
80
  # with the addition that any value that is a hash, and occurs in both
83
81
  # arguments, will also be merged. And so on.
82
+ #
83
+ # rubocop:disable Metrics/AbcSize
84
84
  def merge(base_hash, derived_hash, **opts)
85
85
  result = base_hash.merge(derived_hash)
86
86
  keys_appearing_in_both = base_hash.keys & derived_hash.keys
@@ -95,6 +95,7 @@ module RuboCop
95
95
  end
96
96
  result
97
97
  end
98
+ # rubocop:enable Metrics/AbcSize
98
99
 
99
100
  private
100
101
 
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This class auto-corrects `#each` enumeration to `for` iteration.
6
+ class EachToForCorrector
7
+ extend NodePattern::Macros
8
+
9
+ CORRECTION_WITH_ARGUMENTS =
10
+ 'for %<variables>s in %<collection>s do'.freeze
11
+ CORRECTION_WITHOUT_ARGUMENTS = 'for _ in %<enumerable>s do'.freeze
12
+
13
+ def initialize(block_node)
14
+ @block_node = block_node
15
+ @collection_node = block_node.send_node.receiver
16
+ @argument_node = block_node.arguments
17
+ end
18
+
19
+ def call(corrector)
20
+ corrector.replace(offending_range, correction)
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :block_node, :collection_node, :argument_node
26
+
27
+ def correction
28
+ if block_node.arguments?
29
+ format(CORRECTION_WITH_ARGUMENTS,
30
+ collection: collection_node.source,
31
+ variables: argument_node.children.first.source)
32
+ else
33
+ format(CORRECTION_WITHOUT_ARGUMENTS,
34
+ enumerable: collection_node.source)
35
+ end
36
+ end
37
+
38
+ def offending_range
39
+ if block_node.arguments?
40
+ replacement_range(argument_node.loc.expression.end_pos)
41
+ else
42
+ replacement_range(block_node.loc.begin.end_pos)
43
+ end
44
+ end
45
+
46
+ def replacement_range(end_pos)
47
+ Parser::Source::Range.new(block_node.loc.expression.source_buffer,
48
+ block_node.loc.expression.begin_pos,
49
+ end_pos)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This class auto-corrects `for` iteration to `#each` enumeration.
6
+ class ForToEachCorrector
7
+ extend NodePattern::Macros
8
+
9
+ CORRECTION = '%<collection>s.each do |%<argument>s|'.freeze
10
+
11
+ def initialize(for_node)
12
+ @for_node = for_node
13
+ @variable_node = for_node.variable
14
+ @collection_node = for_node.collection
15
+ end
16
+
17
+ def call(corrector)
18
+ corrector.replace(offending_range, correction)
19
+ end
20
+
21
+ private
22
+
23
+ attr_reader :for_node, :variable_node, :collection_node
24
+
25
+ def correction
26
+ format(CORRECTION, collection: collection_source,
27
+ argument: variable_node.source)
28
+ end
29
+
30
+ def collection_source
31
+ if requires_parentheses?
32
+ "(#{collection_node.source})"
33
+ else
34
+ collection_node.source
35
+ end
36
+ end
37
+
38
+ def requires_parentheses?
39
+ collection_node.irange_type? || collection_node.erange_type?
40
+ end
41
+
42
+ def end_position
43
+ if for_node.do?
44
+ keyword_begin.end_pos
45
+ else
46
+ collection_end.end_pos
47
+ end
48
+ end
49
+
50
+ def keyword_begin
51
+ for_node.loc.begin
52
+ end
53
+
54
+ def collection_end
55
+ if collection_node.begin_type?
56
+ collection_node.loc.end
57
+ else
58
+ collection_node.loc.expression
59
+ end
60
+ end
61
+
62
+ def offending_range
63
+ replacement_range(end_position)
64
+ end
65
+
66
+ def replacement_range(end_pos)
67
+ Parser::Source::Range.new(for_node.loc.expression.source_buffer,
68
+ for_node.loc.expression.begin_pos,
69
+ end_pos)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ # This class auto-corrects lambda literal to method notation.
6
+ class LambdaLiteralToMethodCorrector
7
+ def initialize(block_node)
8
+ @block_node = block_node
9
+ @method = block_node.send_node
10
+ @arguments = block_node.arguments
11
+ end
12
+
13
+ def call(corrector)
14
+ # Check for unparenthesized args' preceding and trailing whitespaces.
15
+ remove_unparenthesized_whitespace(corrector)
16
+
17
+ # Avoid correcting to `lambdado` by inserting whitespace
18
+ # if none exists before or after the lambda arguments.
19
+ insert_separating_space(corrector)
20
+
21
+ replace_selector(corrector)
22
+ remove_arguments(corrector)
23
+
24
+ replace_delimiters(corrector)
25
+
26
+ insert_arguments(corrector)
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :block_node, :method, :arguments
32
+
33
+ def remove_unparenthesized_whitespace(corrector)
34
+ return unless !arguments.empty? && !arguments.parenthesized_call?
35
+
36
+ remove_leading_whitespace(corrector)
37
+ remove_trailing_whitespace(corrector)
38
+ end
39
+
40
+ def insert_separating_space(corrector)
41
+ return unless needs_separating_space?
42
+
43
+ corrector.insert_before(block_begin, ' ')
44
+ end
45
+
46
+ def replace_selector(corrector)
47
+ corrector.replace(method.source_range, 'lambda')
48
+ end
49
+
50
+ def remove_arguments(corrector)
51
+ return if arguments.empty_and_without_delimiters?
52
+
53
+ corrector.remove(arguments.source_range)
54
+ end
55
+
56
+ def insert_arguments(corrector)
57
+ return if arguments.empty?
58
+
59
+ arg_str = " |#{lambda_arg_string}|"
60
+ corrector.insert_after(block_node.loc.begin, arg_str)
61
+ end
62
+
63
+ def remove_leading_whitespace(corrector)
64
+ corrector.remove_preceding(
65
+ arguments.source_range,
66
+ arguments.source_range.begin_pos -
67
+ block_node.send_node.source_range.end_pos
68
+ )
69
+ end
70
+
71
+ def remove_trailing_whitespace(corrector)
72
+ corrector.remove_preceding(
73
+ block_begin,
74
+ block_begin.begin_pos - arguments.source_range.end_pos - 1
75
+ )
76
+ end
77
+
78
+ def replace_delimiters(corrector)
79
+ return if block_node.braces? || !arg_to_unparenthesized_call?
80
+
81
+ corrector.insert_after(block_begin, ' ') unless separating_space?
82
+
83
+ corrector.replace(block_begin, '{')
84
+ corrector.replace(block_end, '}')
85
+ end
86
+
87
+ def lambda_arg_string
88
+ arguments.children.map(&:source).join(', ')
89
+ end
90
+
91
+ def needs_separating_space?
92
+ block_begin.begin_pos == arguments_end_pos &&
93
+ selector_end.end_pos == arguments_begin_pos ||
94
+ block_begin.begin_pos == selector_end.end_pos
95
+ end
96
+
97
+ def arguments_end_pos
98
+ arguments.loc.end && arguments.loc.end.end_pos
99
+ end
100
+
101
+ def arguments_begin_pos
102
+ arguments.loc.begin && arguments.loc.begin.begin_pos
103
+ end
104
+
105
+ def block_end
106
+ block_node.loc.end
107
+ end
108
+
109
+ def block_begin
110
+ block_node.loc.begin
111
+ end
112
+
113
+ def selector_end
114
+ method.loc.selector.end
115
+ end
116
+
117
+ def arg_to_unparenthesized_call?
118
+ current_node = block_node
119
+
120
+ parent = current_node.parent
121
+
122
+ if parent && parent.pair_type?
123
+ current_node = parent.parent
124
+ parent = current_node.parent
125
+ end
126
+
127
+ return false unless parent && parent.send_type?
128
+ return false if parent.parenthesized_call?
129
+
130
+ current_node.sibling_index > 1
131
+ end
132
+
133
+ def separating_space?
134
+ block_begin.source_buffer.source[block_begin.begin_pos + 2].match(/\s/)
135
+ end
136
+ end
137
+ end
138
+ end