Skip to content

Commit

Permalink
Merge pull request #9409 from dvandersluis/eval-with-location
Browse files Browse the repository at this point in the history
Improve offense messages for `Style/EvalWithLocation`.
  • Loading branch information
koic authored Jan 26, 2021
2 parents 2a48e65 + 226fbcc commit bc2a35e
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 24 deletions.
38 changes: 24 additions & 14 deletions lib/rubocop/cop/style/eval_with_location.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
module RuboCop
module Cop
module Style
# This cop checks `eval` method usage. `eval` can receive source location
# metadata, that are filename and line number. The metadata is used by
# backtraces. This cop recommends to pass the metadata to `eval` method.
# This cop ensures that eval methods (`eval`, `instance_eval`, `class_eval`
# and `module_eval`) are given filename and line number values (`__FILE__`
# and `__LINE__`). This data is used to ensure that any errors raised
# within the evaluated code will be given the correct identification
# in a backtrace.
#
# The cop also checks that the line number given relative to `__LINE__` is
# correct.
#
# @example
# # bad
Expand All @@ -32,10 +37,10 @@ module Style
# end
# RUBY
class EvalWithLocation < Base
MSG = 'Pass `__FILE__` and `__LINE__` to `eval` method, ' \
'as they are used by backtraces.'
MSG_INCORRECT_LINE = 'Use `%<expected>s` instead of `%<actual>s`, ' \
'as they are used by backtraces.'
MSG = 'Pass `__FILE__` and `__LINE__` to `%<method_name>s`.'
MSG_EVAL = 'Pass a binding, `__FILE__` and `__LINE__` to `eval`.'
MSG_INCORRECT_LINE = 'Incorrect line number for `%<method_name>s`; ' \
'use `%<expected>s` instead of `%<actual>s`.'

RESTRICT_ON_SEND = %i[eval class_eval module_eval instance_eval].freeze

Expand Down Expand Up @@ -67,7 +72,8 @@ def on_send(node)
if with_lineno?(node)
on_with_lineno(node, code)
else
add_offense(node)
msg = node.method?(:eval) ? MSG_EVAL : format(MSG, method_name: node.method_name)
add_offense(node, message: msg)
end
end
end
Expand Down Expand Up @@ -95,14 +101,18 @@ def with_lineno?(node)
end
# rubocop:enable Style/ConditionalAssignment

def message_incorrect_line(actual, sign, line_diff)
def message_incorrect_line(method_name, actual, sign, line_diff)
expected =
if line_diff.zero?
'__LINE__'
else
"__LINE__ #{sign} #{line_diff}"
end
format(MSG_INCORRECT_LINE, actual: actual.source, expected: expected)

format(MSG_INCORRECT_LINE,
method_name: method_name,
actual: actual.source,
expected: expected)
end

def on_with_lineno(node, code)
Expand All @@ -124,22 +134,22 @@ def string_first_line(str_node)
end
end

def add_offense_for_same_line(_node, line_node)
def add_offense_for_same_line(node, line_node)
return if special_line_keyword?(line_node)

add_offense(
line_node.loc.expression,
message: message_incorrect_line(line_node, nil, 0)
message: message_incorrect_line(node.method_name, line_node, nil, 0)
)
end

def add_offense_for_different_line(_node, line_node, line_diff)
def add_offense_for_different_line(node, line_node, line_diff)
sign = line_diff.positive? ? :+ : :-
return if line_with_offset?(line_node, sign, line_diff.abs)

add_offense(
line_node.loc.expression,
message: message_incorrect_line(line_node, sign, line_diff.abs)
message: message_incorrect_line(node.method_name, line_node, sign, line_diff.abs)
)
end
end
Expand Down
20 changes: 10 additions & 10 deletions spec/rubocop/cop/style/eval_with_location_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
it 'registers an offense when using `#eval` without any arguments' do
expect_offense(<<~RUBY)
eval <<-CODE
^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `eval` method, as they are used by backtraces.
^^^^^^^^^^^^ Pass a binding, `__FILE__` and `__LINE__` to `eval`.
do_something
CODE
RUBY
Expand All @@ -17,7 +17,7 @@
it 'registers an offense when using `#eval` with `binding` only' do
expect_offense(<<~RUBY)
eval <<-CODE, binding
^^^^^^^^^^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `eval` method, as they are used by backtraces.
^^^^^^^^^^^^^^^^^^^^^ Pass a binding, `__FILE__` and `__LINE__` to `eval`.
do_something
CODE
RUBY
Expand All @@ -26,7 +26,7 @@
it 'registers an offense when using `#eval` without lineno' do
expect_offense(<<~RUBY)
eval <<-CODE, binding, __FILE__
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `eval` method, as they are used by backtraces.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Pass a binding, `__FILE__` and `__LINE__` to `eval`.
do_something
CODE
RUBY
Expand All @@ -35,15 +35,15 @@
it 'registers an offense when using `#eval` with an incorrect line number' do
expect_offense(<<~RUBY)
eval 'do_something', binding, __FILE__, __LINE__ + 1
^^^^^^^^^^^^ Use `__LINE__` instead of `__LINE__ + 1`, as they are used by backtraces.
^^^^^^^^^^^^ Incorrect line number for `eval`; use `__LINE__` instead of `__LINE__ + 1`.
RUBY
end

it 'registers an offense when using `#eval` with a heredoc and ' \
'an incorrect line number' do
expect_offense(<<~RUBY)
eval <<-CODE, binding, __FILE__, __LINE__ + 2
^^^^^^^^^^^^ Use `__LINE__ + 1` instead of `__LINE__ + 2`, as they are used by backtraces.
^^^^^^^^^^^^ Incorrect line number for `eval`; use `__LINE__ + 1` instead of `__LINE__ + 2`.
do_something
CODE
RUBY
Expand All @@ -55,14 +55,14 @@
binding,
__FILE__,
__LINE__)
^^^^^^^^ Use `__LINE__ - 3` instead of `__LINE__`, as they are used by backtraces.
^^^^^^^^ Incorrect line number for `eval`; use `__LINE__ - 3` instead of `__LINE__`.
RUBY
end

it 'registers an offense when using `#class_eval` without any arguments' do
expect_offense(<<~RUBY)
C.class_eval <<-CODE
^^^^^^^^^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `eval` method, as they are used by backtraces.
^^^^^^^^^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `class_eval`.
do_something
CODE
RUBY
Expand All @@ -71,7 +71,7 @@
it 'registers an offense when using `#module_eval` without any arguments' do
expect_offense(<<~RUBY)
M.module_eval <<-CODE
^^^^^^^^^^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `eval` method, as they are used by backtraces.
^^^^^^^^^^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `module_eval`.
do_something
CODE
RUBY
Expand All @@ -80,7 +80,7 @@
it 'registers an offense when using `#instance_eval` without any arguments' do
expect_offense(<<~RUBY)
foo.instance_eval <<-CODE
^^^^^^^^^^^^^^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `eval` method, as they are used by backtraces.
^^^^^^^^^^^^^^^^^^^^^^^^^ Pass `__FILE__` and `__LINE__` to `instance_eval`.
do_something
CODE
RUBY
Expand All @@ -89,7 +89,7 @@
it 'registers an offense when using `#class_eval` with an incorrect lineno' do
expect_offense(<<~RUBY)
C.class_eval <<-CODE, __FILE__, __LINE__
^^^^^^^^ Use `__LINE__ + 1` instead of `__LINE__`, as they are used by backtraces.
^^^^^^^^ Incorrect line number for `class_eval`; use `__LINE__ + 1` instead of `__LINE__`.
do_something
CODE
RUBY
Expand Down

0 comments on commit bc2a35e

Please sign in to comment.