Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions lib/ruby-debug-ide/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ def method_missing(meth, *args, &block)
def options
@options ||= {}
end

def unescape_incoming(str)
str.gsub(/((?:^|[^\\])(?:\\\\)*)\\n/, "\\1\n").
gsub(/\\\\/, '\\')
end
end

def initialize(state, printer)
Expand Down Expand Up @@ -104,12 +109,12 @@ def timeout(sec)
y.kill if y and y.alive?
end
end

def debug_eval(str, b = get_binding)
begin
str = str.to_s
to_inspect = Command.unescape_incoming(str)
max_time = Debugger.evaluation_timeout
to_inspect = str.gsub(/\\n/, "\n")
@printer.print_debug("Evaluating #{str} with timeout after %i sec", max_time)
timeout(max_time) do
eval(to_inspect, b)
Expand Down
30 changes: 18 additions & 12 deletions lib/ruby-debug-ide/commands/expression_info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,11 @@ def regexp
end

def execute
string_to_parse = @match.post_match.gsub("\\n", "\n") + "\n\n\n"
string_to_parse = Command.unescape_incoming(@match.post_match) + "\n\n\n"
total_lines = string_to_parse.count("\n") + 1

lexer = RubyLex.new
io = StringIO.new(string_to_parse)
# for passing to the lexer
io.instance_exec(string_to_parse.encoding) do |string_encoding|
@my_encoding = string_encoding
def self.encoding
@my_encoding
end
end

lexer.set_input(io)
lexer.set_input(create_io_reader(string_to_parse))

last_statement = ''
last_prompt = ''
Expand All @@ -39,13 +30,28 @@ def self.encoding
end

incomplete = true
if /\A\s*\Z/m =~ last_statement[0]
if /\A\s*\Z/m =~ last_statement
incomplete = false
end

@printer.print_expression_info(incomplete, last_prompt, last_indent)
end

def create_io_reader(string_to_parse)
io = StringIO.new(string_to_parse)

if string_to_parse.respond_to?(:encoding)
io.instance_exec(string_to_parse.encoding) do |string_encoding|
@my_encoding = string_encoding
def self.encoding
@my_encoding
end
end
end

io
end

class << self
def help_command
"expression_info"
Expand Down
2 changes: 1 addition & 1 deletion lib/ruby-debug-ide/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Debugger
IDE_VERSION='0.4.27'
IDE_VERSION='0.4.28'
end
39 changes: 39 additions & 0 deletions test-base/expression_info_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/usr/bin/env ruby

$:.unshift File.join(File.dirname(__FILE__), "..", "lib")

require 'test_base'

module ExpressionInfoTest

def test_info_multiline_expression
create_socket ["sleep 0.1"]
run_to_line(1)
send_ruby('expression_info 1+')
expression_info = read_expression_info
assert_equal("true", expression_info.incomplete)

send_ruby('expression_info 1+\\n1')
expression_info = read_expression_info
assert_equal("false", expression_info.incomplete)

send_ruby('expression_info "')
expression_info = read_expression_info
assert_equal("true", expression_info.incomplete)

send_ruby('expression_info "\\\\"')
expression_info = read_expression_info
assert_equal("true", expression_info.incomplete)

send_ruby('expression_info "\\\\\\n"')
expression_info = read_expression_info
assert_equal("false", expression_info.incomplete)

send_ruby('expression_info def my_meth')
expression_info = read_expression_info
assert_equal("true", expression_info.incomplete)
send_cont
end

end

27 changes: 27 additions & 0 deletions test-base/inspect_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,32 @@ def test_inspect_multiline_expression
send_cont
end

def test_inspect_unescaping_escaped_newlines
create_socket ["sleep 0.1"]
run_to_line(1)

send_ruby('v inspect "\\\\n".size')
variables = read_variables
assert_equal(1, variables.length, "There is one variable returned.")
assert_equal("1", variables[0].value, "There is one char (newline)")

send_ruby('v inspect "\\\\\\n".size')
variables = read_variables
assert_equal(1, variables.length, "There is one variable returned.")
assert_equal("0", variables[0].value, "There are no chars, it's line continuation here")

send_ruby('v inspect "\\\\\\\\\\n".size')
variables = read_variables
assert_equal(1, variables.length, "There is one variable returned.")
assert_equal("2", variables[0].value, "There are two chars: escaped backslash and newline")

send_ruby('v inspect \'"\\\\n\'.size')
variables = read_variables
assert_equal(1, variables.length, "There is one variable returned.")
assert_equal("3", variables[0].value, "There are three chars: quote, backslash and n")

send_cont
end

end

12 changes: 12 additions & 0 deletions test-base/readers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module Readers
RubyThread = Struct.new("RubyThread", :id, :status)
Frame = Struct.new("Frame", :no, :file, :line)
Variable = Struct.new("Variable", :name, :kind, :value, :type, :hasChildren, :objectId)
ExpressionInfo = Struct.new("ExpressionInfo", :incomplete, :prompt, :indent)

def read_breakpoint_added
(@breakpoint_added_reader ||= BreakPointAddedReader.new(parser)).read
Expand Down Expand Up @@ -88,6 +89,10 @@ def read_processing_exception
(@processing_exception_reader ||= ProcessingExceptionReader.new(parser)).read
end

def read_expression_info
(@expression_info_reader ||= ExpressionInfoReader.new(parser)).read
end

def parser
fail '"parser" method must be defined'
end
Expand Down Expand Up @@ -315,4 +320,11 @@ def read
end
end

class ExpressionInfoReader < BaseReader
def read
data = read_element_data("expressionInfo")
ExpressionInfo.new(data['incomplete'], data['prompt'], data['indent'])
end
end

end
11 changes: 11 additions & 0 deletions test/rd_expression_info_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env ruby

require 'rd_test_base'
require 'expression_info_test'

class RDExpressionInfoTest < RDTestBase

include ExpressionInfoTest

end

34 changes: 34 additions & 0 deletions test/ruby-debug/unescape_incoming_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require 'test/unit'
require 'ruby-debug-ide/command'

class UnescaperTest < Test::Unit::TestCase

def test_empty
do_test('', '')
do_test('a', 'a')
end

def test_newline
do_test('\n', "\n")
do_test('a\n', "a\n")
end

def test_escaped_newline
do_test('\\\\n', '\n')
do_test('a\\\\n', 'a\n')
end

def test_backslash_and_newline
do_test('\\\\\\n', "\\\n")
do_test('a\\\\\\n', "a\\\n")
end

def test_something
do_test('hello\nthere\\\\n', "hello\nthere\\n")
do_test('"\\\\\\n".size', "\"\\\n\".size")
end

def do_test(input, expected_result)
assert_equal(expected_result, Debugger::Command.unescape_incoming(input))
end
end