class RuboCop::Cop::Style::EvalWithLocation
RUBY
end
def do_something
C.class_eval <<-RUBY, __FILE__, __LINE__ + 1
# good
RUBY
end
def do_something
eval <<-RUBY, binding, __FILE__, __LINE__ + 1
# good
RUBY
end
def do_something
C.class_eval <<-RUBY
# bad
RUBY
end
def do_something
eval <<-RUBY
# bad
@example
backtraces. This cop recommends to pass the metadata to ‘eval` method.
metadata, that are filename and line number. The metadata is used by
This cop checks `eval` method usage. `eval` can receive source location
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( node, location: line_node.loc.expression, message: message_incorrect_line(line_node, sign, line_diff.abs) ) 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( node, location: line_node.loc.expression, message: message_incorrect_line(line_node, nil, 0) ) end
def message_incorrect_line(actual, sign, line_diff)
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
def on_send(node)
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
def on_with_lineno(node, code)
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
def special_file_keyword?(node)
def special_file_keyword?(node) node.str_type? && node.source == '__FILE__' end
def special_line_keyword?(node)
def special_line_keyword?(node) node.int_type? && node.source == '__LINE__' end
def string_first_line(str_node)
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
def with_lineno?(node)
FIXME: It's a Style/ConditionalAssignment's false positive.
def with_lineno?(node) if node.method_name == :eval node.arguments.size == 4 else node.arguments.size == 3 end end