mvz-live_ast 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGES.rdoc +93 -0
- data/README.rdoc +419 -0
- data/Rakefile +21 -0
- data/devel/levitate.rb +853 -0
- data/devel/levitate_config.rb +4 -0
- data/lib/live_ast.rb +4 -0
- data/lib/live_ast/ast_eval.rb +11 -0
- data/lib/live_ast/ast_load.rb +15 -0
- data/lib/live_ast/base.rb +73 -0
- data/lib/live_ast/common.rb +48 -0
- data/lib/live_ast/error.rb +20 -0
- data/lib/live_ast/evaler.rb +32 -0
- data/lib/live_ast/full.rb +2 -0
- data/lib/live_ast/irb_spy.rb +43 -0
- data/lib/live_ast/linker.rb +122 -0
- data/lib/live_ast/loader.rb +60 -0
- data/lib/live_ast/reader.rb +26 -0
- data/lib/live_ast/replace_eval.rb +121 -0
- data/lib/live_ast/replace_load.rb +14 -0
- data/lib/live_ast/replace_raise.rb +18 -0
- data/lib/live_ast/ruby_parser.rb +36 -0
- data/lib/live_ast/ruby_parser/test.rb +197 -0
- data/lib/live_ast/ruby_parser/unparser.rb +13 -0
- data/lib/live_ast/to_ast.rb +26 -0
- data/lib/live_ast/to_ruby.rb +24 -0
- data/lib/live_ast/version.rb +3 -0
- data/test/ast_eval_feature_test.rb +11 -0
- data/test/ast_load_feature_test.rb +11 -0
- data/test/attr_test.rb +24 -0
- data/test/backtrace_test.rb +158 -0
- data/test/covert_define_method_test.rb +23 -0
- data/test/def_test.rb +35 -0
- data/test/define_method_test.rb +67 -0
- data/test/define_singleton_method_test.rb +15 -0
- data/test/encoding_test.rb +52 -0
- data/test/encoding_test/bad.rb +1 -0
- data/test/encoding_test/cp932.rb +6 -0
- data/test/encoding_test/default.rb +5 -0
- data/test/encoding_test/eucjp.rb +6 -0
- data/test/encoding_test/koi8.rb +6 -0
- data/test/encoding_test/koi8_shebang.rb +7 -0
- data/test/encoding_test/koi8_with_utf8bom.rb +6 -0
- data/test/encoding_test/usascii.rb +6 -0
- data/test/encoding_test/usascii_with_utf8bom.rb +6 -0
- data/test/encoding_test/utf8.rb +6 -0
- data/test/encoding_test/utf8bom.rb +6 -0
- data/test/encoding_test/utf8bom_only.rb +5 -0
- data/test/encoding_test/utf8dos.rb +6 -0
- data/test/encoding_test/utf8mac.rb +6 -0
- data/test/encoding_test/utf8mac_alt.rb +6 -0
- data/test/encoding_test/utf8unix.rb +6 -0
- data/test/error_test.rb +116 -0
- data/test/eval_test.rb +269 -0
- data/test/flush_cache_test.rb +98 -0
- data/test/irb_test.rb +25 -0
- data/test/lambda_test.rb +56 -0
- data/test/load_path_test.rb +78 -0
- data/test/load_test.rb +123 -0
- data/test/main.rb +140 -0
- data/test/nested_test.rb +29 -0
- data/test/noninvasive_test.rb +51 -0
- data/test/readme_test.rb +16 -0
- data/test/recursive_eval_test.rb +52 -0
- data/test/redefine_method_test.rb +83 -0
- data/test/reload_test.rb +105 -0
- data/test/replace_eval_test.rb +405 -0
- data/test/rubygems_test.rb +25 -0
- data/test/rubyspec_test.rb +39 -0
- data/test/singleton_test.rb +25 -0
- data/test/stdlib_test.rb +13 -0
- data/test/thread_test.rb +44 -0
- data/test/to_ast_feature_test.rb +15 -0
- data/test/to_ruby_feature_test.rb +15 -0
- data/test/to_ruby_test.rb +87 -0
- metadata +275 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'live_ast/base'
|
2
|
+
|
3
|
+
[Method, UnboundMethod, Proc].each do |klass|
|
4
|
+
klass.class_eval do
|
5
|
+
def to_ruby #:nodoc:
|
6
|
+
LiveAST.parser::Unparser.unparse(LiveAST.ast(self))
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Method
|
12
|
+
# :method: to_ruby
|
13
|
+
# Generate ruby code which reflects the AST of this object.
|
14
|
+
end
|
15
|
+
|
16
|
+
class UnboundMethod
|
17
|
+
# :method: to_ruby
|
18
|
+
# Generate ruby code which reflects the AST of this object.
|
19
|
+
end
|
20
|
+
|
21
|
+
class Proc
|
22
|
+
# :method: to_ruby
|
23
|
+
# Generate ruby code which reflects the AST of this object.
|
24
|
+
end
|
data/test/attr_test.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
|
3
|
+
class AttrTest < RegularTest
|
4
|
+
class A
|
5
|
+
attr_accessor :f
|
6
|
+
attr_reader :g
|
7
|
+
attr_writer :h
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_attr
|
11
|
+
assert_raises LiveAST::ASTNotFoundError do
|
12
|
+
A.instance_method(:f).to_ast
|
13
|
+
end
|
14
|
+
assert_raises LiveAST::ASTNotFoundError do
|
15
|
+
A.instance_method(:f=).to_ast
|
16
|
+
end
|
17
|
+
assert_raises LiveAST::ASTNotFoundError do
|
18
|
+
A.instance_method(:g).to_ast
|
19
|
+
end
|
20
|
+
assert_raises LiveAST::ASTNotFoundError do
|
21
|
+
A.instance_method(:h=).to_ast
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
|
3
|
+
# test for raise redefinition side-effects: unsort this TestCase from
|
4
|
+
# other TestCases.
|
5
|
+
|
6
|
+
define_unsorted_test_case "BacktraceTest", RegularTest do
|
7
|
+
def test_raise_in_eval
|
8
|
+
3.times do
|
9
|
+
orig = exception_backtrace do
|
10
|
+
eval %{
|
11
|
+
|
12
|
+
raise
|
13
|
+
|
14
|
+
|
15
|
+
}, binding, "somewhere", 1000
|
16
|
+
end
|
17
|
+
|
18
|
+
live = exception_backtrace do
|
19
|
+
ast_eval %{
|
20
|
+
|
21
|
+
raise
|
22
|
+
|
23
|
+
|
24
|
+
}, binding, "somewhere", 1000
|
25
|
+
end
|
26
|
+
|
27
|
+
assert_equal orig.first, live.first
|
28
|
+
assert_match(/somewhere:1002/, live.first)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_raise_no_overrides
|
33
|
+
3.times do
|
34
|
+
orig = exception_backtrace do
|
35
|
+
eval %{
|
36
|
+
|
37
|
+
|
38
|
+
raise
|
39
|
+
|
40
|
+
}, binding, __FILE__, (__LINE__ + 9)
|
41
|
+
end
|
42
|
+
|
43
|
+
live = exception_backtrace do
|
44
|
+
ast_eval %{
|
45
|
+
|
46
|
+
|
47
|
+
raise
|
48
|
+
|
49
|
+
}, binding
|
50
|
+
end
|
51
|
+
|
52
|
+
assert_equal orig.first, live.first
|
53
|
+
here = Regexp.quote __FILE__
|
54
|
+
assert_match(/#{here}/, live.first)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_raise_using_overrides
|
59
|
+
3.times do
|
60
|
+
orig = exception_backtrace do
|
61
|
+
eval %{
|
62
|
+
|
63
|
+
|
64
|
+
raise
|
65
|
+
|
66
|
+
}, binding, __FILE__, (__LINE__ + 9)
|
67
|
+
end
|
68
|
+
|
69
|
+
live = exception_backtrace do
|
70
|
+
ast_eval %{
|
71
|
+
|
72
|
+
|
73
|
+
raise
|
74
|
+
|
75
|
+
}, binding, __FILE__, __LINE__
|
76
|
+
end
|
77
|
+
|
78
|
+
assert_equal orig.first, live.first
|
79
|
+
here = Regexp.quote __FILE__
|
80
|
+
assert_match(/#{here}/, live.first)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_raise_using_only_file_override
|
85
|
+
3.times do
|
86
|
+
orig = exception_backtrace do
|
87
|
+
eval %{
|
88
|
+
|
89
|
+
|
90
|
+
raise
|
91
|
+
|
92
|
+
}, binding, __FILE__
|
93
|
+
end
|
94
|
+
|
95
|
+
live = exception_backtrace do
|
96
|
+
ast_eval %{
|
97
|
+
|
98
|
+
|
99
|
+
raise
|
100
|
+
|
101
|
+
}, binding, __FILE__
|
102
|
+
end
|
103
|
+
|
104
|
+
assert_equal orig.first, live.first
|
105
|
+
here = Regexp.quote __FILE__
|
106
|
+
assert_match(/#{here}/, live.first)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_raise_after_eval
|
111
|
+
raise_after_eval("raise", false)
|
112
|
+
raise_after_eval("1/0", false)
|
113
|
+
|
114
|
+
require 'live_ast/replace_raise'
|
115
|
+
|
116
|
+
raise_after_eval("raise", true)
|
117
|
+
raise_after_eval("1/0", false)
|
118
|
+
end
|
119
|
+
|
120
|
+
def raise_after_eval(code, will_succeed)
|
121
|
+
3.times do
|
122
|
+
orig = eval %{
|
123
|
+
|
124
|
+
lambda { #{code} }
|
125
|
+
|
126
|
+
|
127
|
+
}, binding, "somewhere", 1000
|
128
|
+
|
129
|
+
live = ast_eval %{
|
130
|
+
|
131
|
+
lambda { #{code} }
|
132
|
+
|
133
|
+
|
134
|
+
}, binding, "somewhere", 1000
|
135
|
+
|
136
|
+
orig_top = exception_backtrace { orig.call }.first
|
137
|
+
live_top = exception_backtrace { live.call }.first
|
138
|
+
|
139
|
+
assert_equal orig_top, LiveAST.strip_token(live_top)
|
140
|
+
|
141
|
+
if will_succeed
|
142
|
+
assert_equal orig_top, live_top
|
143
|
+
assert_match(/somewhere:1002/, live_top)
|
144
|
+
else
|
145
|
+
assert_not_equal orig_top, live_top
|
146
|
+
assert_match(/somewhere.*?:1002/, live_top)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def test_tokens_stripped
|
152
|
+
exception_backtrace do
|
153
|
+
ast_eval %{ ast_eval %{ ast_eval %{raise}, binding }, binding }, binding
|
154
|
+
end.each do |line|
|
155
|
+
assert_nil line.index(LiveAST::Linker::REVISION_TOKEN)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
|
3
|
+
class CovertDefineMethodTest < RegularTest
|
4
|
+
DEFINE = lambda do
|
5
|
+
class A
|
6
|
+
def A.my_def(*args, &block)
|
7
|
+
define_method(*args, &block)
|
8
|
+
end
|
9
|
+
|
10
|
+
my_def :h do |x, y|
|
11
|
+
x + y
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_covert_define_method
|
17
|
+
DEFINE.call
|
18
|
+
assert_equal 77, A.new.h(33, 44)
|
19
|
+
|
20
|
+
assert_equal binop_define_method(:h, :+, :my_def),
|
21
|
+
A.instance_method(:h).to_ast
|
22
|
+
end
|
23
|
+
end
|
data/test/def_test.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
|
3
|
+
class DefTest < RegularTest
|
4
|
+
class A
|
5
|
+
def f
|
6
|
+
"A#f"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_def_unbound_method_a
|
11
|
+
expected = no_arg_def(:f, "A#f")
|
12
|
+
assert_equal expected, A.instance_method(:f).to_ast
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_def_method_a
|
16
|
+
expected = no_arg_def(:f, "A#f")
|
17
|
+
assert_equal expected, A.new.method(:f).to_ast
|
18
|
+
end
|
19
|
+
|
20
|
+
class B
|
21
|
+
def f(x, y)
|
22
|
+
x + y
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_def_unbound_method_b
|
27
|
+
expected = binop_def(:f, :+)
|
28
|
+
assert_equal expected, B.instance_method(:f).to_ast
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_def_instance_method_b
|
32
|
+
expected = binop_def(:f, :+)
|
33
|
+
assert_equal expected, B.new.method(:f).to_ast
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
|
3
|
+
class DefineMethodTest < RegularTest
|
4
|
+
WITH_BLOCKS = lambda do
|
5
|
+
class A
|
6
|
+
{
|
7
|
+
:f => :+,
|
8
|
+
:g => :*,
|
9
|
+
:h => :-,
|
10
|
+
}.each_pair do |name, op|
|
11
|
+
case op
|
12
|
+
when :+
|
13
|
+
define_method name do |x, y|
|
14
|
+
x + y
|
15
|
+
end
|
16
|
+
when :*
|
17
|
+
define_method name do |x, y|
|
18
|
+
x * y
|
19
|
+
end
|
20
|
+
when :-
|
21
|
+
define_method name do |x, y|
|
22
|
+
x - y
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_with_block
|
30
|
+
WITH_BLOCKS.call
|
31
|
+
|
32
|
+
assert_equal binop_define_method_with_var(:name, :+),
|
33
|
+
A.instance_method(:f).to_ast
|
34
|
+
|
35
|
+
assert_equal binop_define_method_with_var(:name, :*),
|
36
|
+
A.instance_method(:g).to_ast
|
37
|
+
|
38
|
+
assert_equal binop_define_method_with_var(:name, :-),
|
39
|
+
A.instance_method(:h).to_ast
|
40
|
+
end
|
41
|
+
|
42
|
+
WITH_PROCS = lambda do
|
43
|
+
class B
|
44
|
+
op = lambda { |x, y| x / y }
|
45
|
+
|
46
|
+
no_arg = proc { "B#f" }
|
47
|
+
|
48
|
+
define_method :g, &no_arg ; define_method :f, &op
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_via_block
|
53
|
+
WITH_PROCS.call
|
54
|
+
|
55
|
+
assert_equal binop_block(:lambda, :/),
|
56
|
+
B.instance_method(:f).to_ast
|
57
|
+
|
58
|
+
assert_equal binop_block(:lambda, :/),
|
59
|
+
B.new.method(:f).to_ast
|
60
|
+
|
61
|
+
assert_equal no_arg_block(:proc, "B#f"),
|
62
|
+
B.instance_method(:g).to_ast
|
63
|
+
|
64
|
+
assert_equal no_arg_block(:proc, "B#f"),
|
65
|
+
B.new.method(:g).to_ast
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
|
3
|
+
class DefineSingletonMethodTest < RegularTest
|
4
|
+
def test_define_singleton_method
|
5
|
+
a = Object.new
|
6
|
+
a.define_singleton_method :f do |x, y|
|
7
|
+
x + y
|
8
|
+
end
|
9
|
+
|
10
|
+
assert_equal 77, a.f(33, 44)
|
11
|
+
|
12
|
+
assert_equal binop_define_singleton_method(:f, :+, :a),
|
13
|
+
a.singleton_class.instance_method(:f).to_ast
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'main'
|
2
|
+
|
3
|
+
class AllEncodingTest < RegularTest
|
4
|
+
ENC_TESTS = Hash[*%w[
|
5
|
+
default US-ASCII
|
6
|
+
usascii US-ASCII
|
7
|
+
utf8 UTF-8
|
8
|
+
utf8unix UTF-8
|
9
|
+
utf8mac UTF-8
|
10
|
+
utf8mac_alt UTF8-MAC
|
11
|
+
utf8dos UTF-8
|
12
|
+
utf8bom UTF-8
|
13
|
+
utf8bom_only UTF-8
|
14
|
+
usascii_with_utf8bom US-ASCII
|
15
|
+
koi8_with_utf8bom KOI8-R
|
16
|
+
cp932 Windows-31J
|
17
|
+
eucjp EUC-JP
|
18
|
+
koi8 KOI8-R
|
19
|
+
koi8_shebang KOI8-R
|
20
|
+
]]
|
21
|
+
|
22
|
+
ENC_TESTS.each_pair do |abbr, name|
|
23
|
+
define_method "test_#{abbr}" do
|
24
|
+
require_relative "encoding_test/#{abbr}"
|
25
|
+
self.class.class_eval { include EncodingTest }
|
26
|
+
|
27
|
+
str = send("#{abbr}_string")
|
28
|
+
assert_equal name, str.encoding.to_s
|
29
|
+
|
30
|
+
ast = EncodingTest.instance_method("#{abbr}_string").to_ast
|
31
|
+
assert_equal "UTF-8", no_arg_def_return(ast).encoding.to_s
|
32
|
+
|
33
|
+
LiveAST.load "./test/encoding_test/#{abbr}.rb"
|
34
|
+
|
35
|
+
ast = EncodingTest.instance_method("#{abbr}_string").to_ast
|
36
|
+
assert_equal "UTF-8", no_arg_def_return(ast).encoding.to_s
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_bad
|
41
|
+
orig = assert_raises ArgumentError do
|
42
|
+
live_ast_original_load "./test/encoding_test/bad.rb"
|
43
|
+
end
|
44
|
+
live = assert_raises ArgumentError do
|
45
|
+
LiveAST.load "./test/encoding_test/bad.rb"
|
46
|
+
end
|
47
|
+
# inconsistent punctuation from Ruby
|
48
|
+
re = %r!\Aunknown encoding name\s*[-:]\s*feynman-diagram\Z!
|
49
|
+
assert_match re, orig.message
|
50
|
+
assert_match re, live.message
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# encoding: feynman-diagram
|