class RuboCop::Cop::Style::EvalWithLocation
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.
@example
# bad eval <<-RUBY def do_something end RUBY # bad C.class_eval <<-RUBY def do_something end RUBY # good eval <<-RUBY, binding, __FILE__, __LINE__ + 1 def do_something end RUBY # good C.class_eval <<-RUBY, __FILE__, __LINE__ + 1 def do_something end RUBY
Constants
- MSG
- MSG_INCORRECT_LINE
Public Instance Methods
on_send(node)
click to toggle source
# File lib/rubocop/cop/style/eval_with_location.rb, line 63 def on_send(node) eval_without_location?(node) do |code| if with_lineno?(node) on_with_lineno(node, code) else add_offense(node) end end end
Private Instance Methods
add_offense_for_different_line(node, line_node, line_diff)
click to toggle source
# File lib/rubocop/cop/style/eval_with_location.rb, line 135 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( node, location: line_node.loc.expression, message: message_incorrect_line(line_node, sign, line_diff.abs) ) end
add_offense_for_same_line(node, line_node)
click to toggle source
# File lib/rubocop/cop/style/eval_with_location.rb, line 125 def add_offense_for_same_line(node, line_node) return if special_line_keyword?(line_node) add_offense( node, location: line_node.loc.expression, message: message_incorrect_line(line_node, nil, 0) ) end
message_incorrect_line(actual, sign, line_diff)
click to toggle source
rubocop:enable Style/ConditionalAssignment
# File lib/rubocop/cop/style/eval_with_location.rb, line 96 def message_incorrect_line(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) end
on_with_lineno(node, code)
click to toggle source
# File lib/rubocop/cop/style/eval_with_location.rb, line 106 def on_with_lineno(node, code) line_node = node.arguments.last lineno_range = line_node.loc.expression line_diff = string_first_line(code) - lineno_range.first_line if line_diff.zero? add_offense_for_same_line(node, line_node) else add_offense_for_different_line(node, line_node, line_diff) end end
special_file_keyword?(node)
click to toggle source
# File lib/rubocop/cop/style/eval_with_location.rb, line 75 def special_file_keyword?(node) node.str_type? && node.source == '__FILE__' end
special_line_keyword?(node)
click to toggle source
# File lib/rubocop/cop/style/eval_with_location.rb, line 80 def special_line_keyword?(node) node.int_type? && node.source == '__LINE__' end
string_first_line(str_node)
click to toggle source
# File lib/rubocop/cop/style/eval_with_location.rb, line 117 def string_first_line(str_node) if str_node.heredoc? str_node.loc.heredoc_body.first_line else str_node.loc.expression.first_line end end
with_lineno?(node)
click to toggle source
FIXME: It's a Style/ConditionalAssignment's false positive. rubocop:disable Style/ConditionalAssignment
# File lib/rubocop/cop/style/eval_with_location.rb, line 87 def with_lineno?(node) if node.method_name == :eval node.arguments.size == 4 else node.arguments.size == 3 end end