rbs 0.5.0 → 0.9.1
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 +4 -4
- data/CHANGELOG.md +33 -0
- data/Gemfile +2 -0
- data/Rakefile +2 -3
- data/docs/stdlib.md +0 -2
- data/docs/syntax.md +6 -3
- data/goodcheck.yml +65 -0
- data/lib/rbs.rb +1 -0
- data/lib/rbs/ast/comment.rb +6 -0
- data/lib/rbs/ast/declarations.rb +44 -6
- data/lib/rbs/cli.rb +21 -3
- data/lib/rbs/constant_table.rb +1 -1
- data/lib/rbs/definition_builder.rb +290 -124
- data/lib/rbs/environment.rb +50 -37
- data/lib/rbs/errors.rb +68 -25
- data/lib/rbs/factory.rb +14 -0
- data/lib/rbs/location.rb +15 -0
- data/lib/rbs/parser.y +89 -28
- data/lib/rbs/prototype/rb.rb +2 -2
- data/lib/rbs/prototype/rbi.rb +1 -1
- data/lib/rbs/prototype/runtime.rb +1 -1
- data/lib/rbs/substitution.rb +6 -2
- data/lib/rbs/test.rb +82 -3
- data/lib/rbs/test/errors.rb +5 -1
- data/lib/rbs/test/hook.rb +133 -259
- data/lib/rbs/test/observer.rb +17 -0
- data/lib/rbs/test/setup.rb +37 -20
- data/lib/rbs/test/setup_helper.rb +29 -0
- data/lib/rbs/test/spy.rb +0 -321
- data/lib/rbs/test/tester.rb +118 -0
- data/lib/rbs/test/type_check.rb +42 -5
- data/lib/rbs/validator.rb +4 -0
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +2 -2
- data/schema/decls.json +21 -10
- data/stdlib/builtin/enumerable.rbs +2 -2
- data/stdlib/builtin/proc.rbs +1 -2
- data/stdlib/json/json.rbs +6 -0
- data/stdlib/logger/formatter.rbs +23 -0
- data/stdlib/logger/log_device.rbs +39 -0
- data/stdlib/logger/logger.rbs +507 -0
- data/stdlib/logger/period.rbs +7 -0
- data/stdlib/logger/severity.rbs +8 -0
- data/stdlib/pty/pty.rbs +159 -0
- metadata +13 -3
- data/lib/rbs/test/test_helper.rb +0 -180
data/lib/rbs/prototype/rb.rb
CHANGED
@@ -81,7 +81,7 @@ module RBS
|
|
81
81
|
mod = AST::Declarations::Module.new(
|
82
82
|
name: const_to_name(module_name),
|
83
83
|
type_params: AST::Declarations::ModuleTypeParams.empty,
|
84
|
-
|
84
|
+
self_types: [],
|
85
85
|
members: [],
|
86
86
|
annotations: [],
|
87
87
|
location: nil,
|
@@ -134,7 +134,7 @@ module RBS
|
|
134
134
|
overload: false
|
135
135
|
)
|
136
136
|
|
137
|
-
decls.push member
|
137
|
+
decls.push member unless decls.include?(member)
|
138
138
|
|
139
139
|
when :FCALL
|
140
140
|
# Inside method definition cannot reach here.
|
data/lib/rbs/prototype/rbi.rb
CHANGED
data/lib/rbs/substitution.rb
CHANGED
@@ -11,7 +11,7 @@ module RBS
|
|
11
11
|
mapping[from] = to
|
12
12
|
end
|
13
13
|
|
14
|
-
def self.build(variables, types, instance_type:
|
14
|
+
def self.build(variables, types, instance_type: nil, &block)
|
15
15
|
unless variables.size == types.size
|
16
16
|
raise "Broken substitution: variables=#{variables}, types=#{types}"
|
17
17
|
end
|
@@ -33,7 +33,11 @@ module RBS
|
|
33
33
|
when Types::Variable
|
34
34
|
mapping[ty.name] || ty
|
35
35
|
when Types::Bases::Instance
|
36
|
-
instance_type
|
36
|
+
if instance_type
|
37
|
+
instance_type
|
38
|
+
else
|
39
|
+
ty
|
40
|
+
end
|
37
41
|
else
|
38
42
|
ty
|
39
43
|
end
|
data/lib/rbs/test.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
+
require "securerandom"
|
2
|
+
require "rbs/test/observer"
|
1
3
|
require "rbs/test/spy"
|
2
4
|
require "rbs/test/errors"
|
3
5
|
require "rbs/test/type_check"
|
6
|
+
require "rbs/test/tester"
|
4
7
|
require "rbs/test/hook"
|
8
|
+
require "rbs/test/setup_helper"
|
5
9
|
|
6
10
|
module RBS
|
7
11
|
module Test
|
@@ -16,11 +20,86 @@ module RBS
|
|
16
20
|
INSPECT = Kernel.instance_method(:inspect)
|
17
21
|
METHODS = Kernel.instance_method(:methods)
|
18
22
|
|
19
|
-
ArgumentsReturn
|
23
|
+
class ArgumentsReturn
|
24
|
+
attr_reader :arguments
|
25
|
+
attr_reader :exit_value
|
26
|
+
attr_reader :exit_type
|
27
|
+
|
28
|
+
def initialize(arguments:, exit_value:, exit_type:)
|
29
|
+
@arguments = arguments
|
30
|
+
@exit_value = exit_value
|
31
|
+
@exit_type = exit_type
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.return(arguments:, value:)
|
35
|
+
new(arguments: arguments, exit_value: value, exit_type: :return)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.exception(arguments:, exception:)
|
39
|
+
new(arguments: arguments, exit_value: exception, exit_type: :exception)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.break(arguments:)
|
43
|
+
new(arguments: arguments, exit_value: nil, exit_type: :break)
|
44
|
+
end
|
45
|
+
|
46
|
+
def return_value
|
47
|
+
raise unless exit_type == :return
|
48
|
+
exit_value
|
49
|
+
end
|
50
|
+
|
51
|
+
def exception
|
52
|
+
raise unless exit_type == :exception
|
53
|
+
exit_value
|
54
|
+
end
|
55
|
+
|
56
|
+
def return?
|
57
|
+
exit_type == :return
|
58
|
+
end
|
59
|
+
|
60
|
+
def exception?
|
61
|
+
exit_type == :exception
|
62
|
+
end
|
63
|
+
|
64
|
+
def break?
|
65
|
+
exit_type == :break
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
20
69
|
CallTrace = Struct.new(:method_name, :method_call, :block_calls, :block_given, keyword_init: true)
|
21
70
|
|
22
|
-
|
23
|
-
|
71
|
+
class <<self
|
72
|
+
attr_accessor :suffix
|
73
|
+
|
74
|
+
def reset_suffix
|
75
|
+
self.suffix = "RBS_TEST_#{SecureRandom.hex(3)}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
reset_suffix
|
80
|
+
|
81
|
+
if ::UnboundMethod.instance_methods.include?(:bind_call)
|
82
|
+
def self.call(receiver, method, *args, &block)
|
83
|
+
method.bind_call(receiver, *args, &block)
|
84
|
+
end
|
85
|
+
else
|
86
|
+
def self.call(receiver, method, *args, &block)
|
87
|
+
method.bind(receiver).call(*args, &block)
|
88
|
+
end
|
24
89
|
end
|
25
90
|
end
|
26
91
|
end
|
92
|
+
|
93
|
+
unless ::Module.private_instance_methods.include?(:ruby2_keywords)
|
94
|
+
class Module
|
95
|
+
private
|
96
|
+
def ruby2_keywords(*)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
unless ::Proc.instance_methods.include?(:ruby2_keywords)
|
102
|
+
class Proc
|
103
|
+
def ruby2_keywords; end
|
104
|
+
end
|
105
|
+
end
|
data/lib/rbs/test/errors.rb
CHANGED
@@ -28,7 +28,11 @@ module RBS
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.inspect_(obj)
|
31
|
-
|
31
|
+
if obj.respond_to?(:inspect)
|
32
|
+
obj.inspect
|
33
|
+
else
|
34
|
+
Test::INSPECT.bind(obj).call # For the case inspect is not defined (like BasicObject)
|
35
|
+
end
|
32
36
|
end
|
33
37
|
|
34
38
|
def self.to_string(error)
|
data/lib/rbs/test/hook.rb
CHANGED
@@ -3,291 +3,165 @@ require "pp"
|
|
3
3
|
|
4
4
|
module RBS
|
5
5
|
module Test
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
def
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
@logger = logger
|
38
|
-
@klass = klass
|
39
|
-
|
40
|
-
@instance_module = Module.new
|
41
|
-
@instance_methods = []
|
42
|
-
|
43
|
-
@singleton_module = Module.new
|
44
|
-
@singleton_methods = []
|
45
|
-
|
46
|
-
@errors = []
|
47
|
-
|
48
|
-
@raise_on_error = raise_on_error
|
49
|
-
end
|
50
|
-
|
51
|
-
def raise_on_error!(error = true)
|
52
|
-
@raise_on_error = error
|
53
|
-
self
|
54
|
-
end
|
55
|
-
|
56
|
-
def raise_on_error?
|
57
|
-
@raise_on_error
|
58
|
-
end
|
59
|
-
|
60
|
-
def prepend!
|
61
|
-
klass.prepend @instance_module
|
62
|
-
klass.singleton_class.prepend @singleton_module
|
6
|
+
module Hook
|
7
|
+
OPERATORS = {
|
8
|
+
:== => "eqeq",
|
9
|
+
:=== => "eqeqeq",
|
10
|
+
:+ => "plus",
|
11
|
+
:- => "minus",
|
12
|
+
:* => "star",
|
13
|
+
:/ => "slash",
|
14
|
+
:> => "gt",
|
15
|
+
:>= => "gteq",
|
16
|
+
:< => "lt",
|
17
|
+
:<= => "lteq",
|
18
|
+
:<=> => "ufo",
|
19
|
+
:& => "amp",
|
20
|
+
:| => "vbar",
|
21
|
+
:^ => "hat",
|
22
|
+
:! => "not",
|
23
|
+
:<< => "lshift",
|
24
|
+
:>> => "rshift",
|
25
|
+
:~ => "tilda"
|
26
|
+
}
|
27
|
+
def self.alias_names(target)
|
28
|
+
case target
|
29
|
+
when *OPERATORS.keys
|
30
|
+
name = OPERATORS[target]
|
31
|
+
[
|
32
|
+
"#{name}____with__#{Test.suffix}",
|
33
|
+
"#{name}____without__#{Test.suffix}"
|
34
|
+
]
|
35
|
+
else
|
36
|
+
aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
|
63
37
|
|
64
|
-
|
65
|
-
|
66
|
-
|
38
|
+
[
|
39
|
+
"#{aliased_target}__with__#{Test.suffix}#{punctuation}",
|
40
|
+
"#{aliased_target}__without__#{Test.suffix}#{punctuation}"
|
41
|
+
]
|
67
42
|
end
|
68
|
-
|
69
|
-
self
|
70
43
|
end
|
71
44
|
|
72
|
-
def self.
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
|
-
def refinement
|
77
|
-
klass = self.klass
|
78
|
-
instance_module = self.instance_module
|
79
|
-
singleton_module = self.singleton_module
|
80
|
-
|
81
|
-
Module.new do
|
82
|
-
refine klass do
|
83
|
-
prepend instance_module
|
84
|
-
end
|
85
|
-
|
86
|
-
refine klass.singleton_class do
|
87
|
-
prepend singleton_module
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
45
|
+
def self.setup_alias_method_chain(klass, target)
|
46
|
+
with_method, without_method = alias_names(target)
|
91
47
|
|
92
|
-
|
93
|
-
type_name = Namespace.parse(klass.name).to_type_name.absolute!
|
48
|
+
RBS.logger.debug "alias name: #{target}, #{with_method}, #{without_method}"
|
94
49
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
unless method.annotations.any? {|a| a.string == "rbs:test:skip" }
|
99
|
-
logger.info "Installing a hook on #{type_name}##{name}: #{method.method_types.join(" | ")}"
|
100
|
-
verify instance_method: name, types: method.method_types
|
101
|
-
else
|
102
|
-
logger.info "Skipping test of #{type_name}##{name}"
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
50
|
+
klass.instance_eval do
|
51
|
+
alias_method without_method, target
|
52
|
+
alias_method target, with_method
|
107
53
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
logger.info "Skipping test of #{type_name}.#{name}"
|
116
|
-
end
|
117
|
-
end
|
54
|
+
case
|
55
|
+
when public_method_defined?(without_method)
|
56
|
+
public target
|
57
|
+
when protected_method_defined?(without_method)
|
58
|
+
protected target
|
59
|
+
when private_method_defined?(without_method)
|
60
|
+
private target
|
118
61
|
end
|
119
62
|
end
|
120
|
-
|
121
|
-
self
|
122
|
-
end
|
123
|
-
|
124
|
-
def delegation(name, method_types, method_name)
|
125
|
-
hook = self
|
126
|
-
|
127
|
-
-> (*args, &block) do
|
128
|
-
hook.logger.debug { "#{method_name} receives arguments: #{hook.inspect_(args)}" }
|
129
|
-
|
130
|
-
block_calls = []
|
131
|
-
|
132
|
-
if block
|
133
|
-
original_block = block
|
134
|
-
|
135
|
-
block = hook.call(Object.new, INSTANCE_EVAL) do |fresh_obj|
|
136
|
-
->(*as) do
|
137
|
-
hook.logger.debug { "#{method_name} receives block arguments: #{hook.inspect_(as)}" }
|
138
|
-
|
139
|
-
ret = if self.equal?(fresh_obj)
|
140
|
-
original_block[*as]
|
141
|
-
else
|
142
|
-
hook.call(self, INSTANCE_EXEC, *as, &original_block)
|
143
|
-
end
|
144
|
-
|
145
|
-
block_calls << ArgumentsReturn.new(
|
146
|
-
arguments: as,
|
147
|
-
return_value: ret,
|
148
|
-
exception: nil
|
149
|
-
)
|
150
|
-
|
151
|
-
hook.logger.debug { "#{method_name} returns from block: #{hook.inspect_(ret)}" }
|
152
|
-
|
153
|
-
ret
|
154
|
-
end.ruby2_keywords
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
method = hook.call(self, METHOD, name)
|
159
|
-
klass = hook.call(self, CLASS)
|
160
|
-
singleton_klass = begin
|
161
|
-
hook.call(self, SINGLETON_CLASS)
|
162
|
-
rescue TypeError
|
163
|
-
nil
|
164
|
-
end
|
165
|
-
prepended = klass.ancestors.include?(hook.instance_module) || singleton_klass&.ancestors&.include?(hook.singleton_module)
|
166
|
-
exception = nil
|
167
|
-
result = begin
|
168
|
-
if prepended
|
169
|
-
method.super_method.call(*args, &block)
|
170
|
-
else
|
171
|
-
# Using refinement
|
172
|
-
method.call(*args, &block)
|
173
|
-
end
|
174
|
-
rescue Exception => e
|
175
|
-
exception = e
|
176
|
-
nil
|
177
|
-
end
|
178
|
-
|
179
|
-
hook.logger.debug { "#{method_name} returns: #{hook.inspect_(result)}" }
|
180
|
-
|
181
|
-
call = CallTrace.new(method_call: ArgumentsReturn.new(arguments: args, return_value: result, exception: exception),
|
182
|
-
block_calls: block_calls,
|
183
|
-
block_given: block != nil)
|
184
|
-
|
185
|
-
method_type_errors = method_types.map do |method_type|
|
186
|
-
hook.typecheck.method_call(method_name, method_type, call, errors: [])
|
187
|
-
end
|
188
|
-
|
189
|
-
new_errors = []
|
190
|
-
|
191
|
-
if method_type_errors.none?(&:empty?)
|
192
|
-
if (best_errors = hook.find_best_errors(method_type_errors))
|
193
|
-
new_errors.push(*best_errors)
|
194
|
-
else
|
195
|
-
new_errors << Errors::UnresolvedOverloadingError.new(
|
196
|
-
klass: hook.klass,
|
197
|
-
method_name: method_name,
|
198
|
-
method_types: method_types
|
199
|
-
)
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
unless new_errors.empty?
|
204
|
-
new_errors.each do |error|
|
205
|
-
hook.logger.error Errors.to_string(error)
|
206
|
-
end
|
207
|
-
|
208
|
-
hook.errors.push(*new_errors)
|
209
|
-
|
210
|
-
if hook.raise_on_error?
|
211
|
-
raise Error.new(new_errors)
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
result
|
216
|
-
end.ruby2_keywords
|
217
63
|
end
|
218
64
|
|
219
|
-
def
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
65
|
+
def self.hook_method_source(prefix, method_name, key)
|
66
|
+
with_name, without_name = alias_names(method_name)
|
67
|
+
full_method_name = "#{prefix}#{method_name}"
|
68
|
+
|
69
|
+
[__LINE__ + 1, <<RUBY]
|
70
|
+
def #{with_name}(*args)
|
71
|
+
::RBS.logger.debug { "#{full_method_name} with arguments: [" + args.map(&:inspect).join(", ") + "]" }
|
72
|
+
|
73
|
+
begin
|
74
|
+
return_from_call = false
|
75
|
+
block_calls = []
|
76
|
+
|
77
|
+
if block_given?
|
78
|
+
result = __send__(:"#{without_name}", *args) do |*block_args|
|
79
|
+
return_from_block = false
|
80
|
+
|
81
|
+
begin
|
82
|
+
block_result = yield(*block_args)
|
83
|
+
return_from_block = true
|
84
|
+
ensure
|
85
|
+
exn = $!
|
86
|
+
|
87
|
+
case
|
88
|
+
when return_from_block
|
89
|
+
# Returned from yield
|
90
|
+
block_calls << ::RBS::Test::ArgumentsReturn.return(
|
91
|
+
arguments: block_args,
|
92
|
+
value: block_result
|
93
|
+
)
|
94
|
+
when exn
|
95
|
+
# Exception
|
96
|
+
block_calls << ::RBS::Test::ArgumentsReturn.exception(
|
97
|
+
arguments: block_args,
|
98
|
+
exception: exn
|
99
|
+
)
|
224
100
|
else
|
225
|
-
|
101
|
+
# break?
|
102
|
+
block_calls << ::RBS::Test::ArgumentsReturn.break(
|
103
|
+
arguments: block_args
|
104
|
+
)
|
226
105
|
end
|
227
106
|
end
|
228
107
|
|
229
|
-
|
230
|
-
when instance_method
|
231
|
-
instance_methods << instance_method
|
232
|
-
call(self.instance_module, DEFINE_METHOD, instance_method, &delegation(instance_method, method_types, "##{instance_method}"))
|
233
|
-
when singleton_method
|
234
|
-
call(self.singleton_module, DEFINE_METHOD, singleton_method, &delegation(singleton_method, method_types, ".#{singleton_method}"))
|
235
|
-
end
|
236
|
-
|
237
|
-
self
|
108
|
+
block_result
|
238
109
|
end
|
110
|
+
else
|
111
|
+
result = __send__(:"#{without_name}", *args)
|
112
|
+
end
|
113
|
+
return_from_call = true
|
114
|
+
result
|
115
|
+
ensure
|
116
|
+
exn = $!
|
117
|
+
|
118
|
+
case
|
119
|
+
when return_from_call
|
120
|
+
::RBS.logger.debug { "#{full_method_name} return with value: " + result.inspect }
|
121
|
+
method_call = ::RBS::Test::ArgumentsReturn.return(
|
122
|
+
arguments: args,
|
123
|
+
value: result
|
124
|
+
)
|
125
|
+
when exn
|
126
|
+
::RBS.logger.debug { "#{full_method_name} exit with exception: " + exn.inspect }
|
127
|
+
method_call = ::RBS::Test::ArgumentsReturn.exception(
|
128
|
+
arguments: args,
|
129
|
+
exception: exn
|
130
|
+
)
|
131
|
+
else
|
132
|
+
::RBS.logger.debug { "#{full_method_name} exit with jump" }
|
133
|
+
method_call = ::RBS::Test::ArgumentsReturn.break(arguments: args)
|
134
|
+
end
|
239
135
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
error.is_a?(Errors::ArgumentError) ||
|
247
|
-
error.is_a?(Errors::BlockArgumentError) ||
|
248
|
-
error.is_a?(Errors::MissingBlockError) ||
|
249
|
-
error.is_a?(Errors::UnexpectedBlockError)
|
250
|
-
end
|
251
|
-
end
|
136
|
+
trace = ::RBS::Test::CallTrace.new(
|
137
|
+
method_name: #{method_name.inspect},
|
138
|
+
method_call: method_call,
|
139
|
+
block_calls: block_calls,
|
140
|
+
block_given: block_given?,
|
141
|
+
)
|
252
142
|
|
253
|
-
|
254
|
-
|
255
|
-
return no_arity_errors[0] if no_arity_errors.size == 1
|
256
|
-
end
|
257
|
-
end
|
258
|
-
end
|
143
|
+
::RBS::Test::Observer.notify(#{key.inspect}, self, trace)
|
144
|
+
end
|
259
145
|
|
260
|
-
|
261
|
-
|
262
|
-
rescue => exn
|
263
|
-
exn.backtrace.drop(skip)
|
264
|
-
end
|
146
|
+
result
|
147
|
+
end
|
265
148
|
|
266
|
-
|
267
|
-
|
268
|
-
self
|
269
|
-
ensure
|
270
|
-
disable
|
149
|
+
ruby2_keywords :#{with_name}
|
150
|
+
RUBY
|
271
151
|
end
|
272
152
|
|
273
|
-
def
|
274
|
-
|
275
|
-
end
|
153
|
+
def self.hook_instance_method(klass, method, key:)
|
154
|
+
line, source = hook_method_source("#{klass}#", method, key)
|
276
155
|
|
277
|
-
|
278
|
-
|
156
|
+
klass.module_eval(source, __FILE__, line)
|
157
|
+
setup_alias_method_chain klass, method
|
279
158
|
end
|
280
159
|
|
281
|
-
def self.
|
282
|
-
|
283
|
-
rescue
|
284
|
-
INSPECT.bind(obj).call()
|
285
|
-
end
|
160
|
+
def self.hook_singleton_method(klass, method, key:)
|
161
|
+
line, source = hook_method_source("#{klass}.",method, key)
|
286
162
|
|
287
|
-
|
288
|
-
|
289
|
-
self.singleton_module.remove_method(*singleton_methods)
|
290
|
-
self
|
163
|
+
klass.singleton_class.module_eval(source, __FILE__, line)
|
164
|
+
setup_alias_method_chain klass.singleton_class, method
|
291
165
|
end
|
292
166
|
end
|
293
167
|
end
|