Skip to content

Commit 6535a83

Browse files
committed
[Kernel] Add Kernel.trace_var and Kernel.untrace_var
1 parent 4482ed2 commit 6535a83

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

core/kernel.rbs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2203,6 +2203,19 @@ module Kernel : BasicObject
22032203
def self?.system: (String command, *String args, ?unsetenv_others: boolish, ?pgroup: true | Integer, ?umask: Integer, ?in: redirect_fd, ?out: redirect_fd, ?err: redirect_fd, ?close_others: boolish, ?chdir: String, ?exception: bool) -> (NilClass | FalseClass | TrueClass)
22042204
| (Hash[string, string?] env, String command, *String args, ?unsetenv_others: boolish, ?pgroup: true | Integer, ?umask: Integer, ?in: redirect_fd, ?out: redirect_fd, ?err: redirect_fd, ?close_others: boolish, ?chdir: String, ?exception: bool) -> (NilClass | FalseClass | TrueClass)
22052205

2206+
interface _Tracer
2207+
def call: (untyped argument) -> void
2208+
end
2209+
2210+
def self?.trace_var: (interned name, String | _Tracer cmd) -> nil
2211+
| (interned name) { (untyped value) -> void } -> nil
2212+
| (interned name, nil) -> Array[String | _Tracer]?
2213+
2214+
def self?.untrace_var: (interned name, ?nil) -> Array[String | _Tracer]
2215+
| (interned name, String cmd) -> [String]?
2216+
| [T < _Tracer] (interned name, T cmd) -> [T]?
2217+
| (interned name, untyped cmd) -> nil
2218+
22062219
# <!--
22072220
# rdoc-file=object.c
22082221
# - obj !~ other -> true or false

test/stdlib/Kernel_test.rb

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,81 @@ def test_rand
112112
assert_send_type "(Range[Float]) -> Float", Kernel, :rand, 0.0...10.0
113113
assert_send_type "(Range[Float]) -> nil", Kernel, :rand, 0.0...0.0
114114
end
115+
116+
def test_trace_var
117+
tracer = BlankSlate.new
118+
def tracer.call(new) nil end
119+
120+
with_interned '$__TEST_TRACE_VAR' do |name|
121+
assert_send_type '(interned, String) -> nil',
122+
Kernel, :trace_var, name, '1'
123+
assert_send_type '(interned, ::Kernel::_Tracer) -> nil',
124+
Kernel, :trace_var, name, tracer
125+
assert_send_type '(interned) { (any) -> void } -> nil',
126+
Kernel, :trace_var, name do |x| 0 end
127+
128+
# `Kernel.trace_var` doesn't actually check the type of its second argument,
129+
# but instead defers until the global is actually assigned. To ensure that
130+
# our signatures are correct, we assign the global here (which, if our
131+
# signatures are incorrect, will raise an exception)
132+
$__TEST_TRACE_VAR = 1
133+
134+
# Acts the same as `untrace_var`, so this performs the untracing for us.
135+
assert_send_type '(interned, nil) -> Array[String | ::Kernel::_Tracer]',
136+
Kernel, :trace_var, name, nil
137+
end
138+
ensure
139+
# Just in case an exception stopped it, we don't want to continue tracing.
140+
# We do `defined?` as `untrace_var :$some_undefined_global` fails
141+
untrace_var :$__TEST_TRACE_VAR if defined? $__TEST_TRACE_VAR
142+
end
143+
144+
def test_untrace_var
145+
tracer = BlankSlate.new
146+
def tracer.call(new) nil end
147+
148+
with_interned '$__TEST_UNTRACE_VAR' do |name|
149+
# No argument yields all traces
150+
trace_var :$__TEST_UNTRACE_VAR, '"string"'
151+
trace_var :$__TEST_UNTRACE_VAR do "proc" end
152+
trace_var :$__TEST_UNTRACE_VAR, tracer
153+
assert_send_type '(interned) -> Array[String | ::Kernel::_Tracer]',
154+
Kernel, :untrace_var, name
155+
156+
# `nil` also yields all traces
157+
trace_var :$__TEST_UNTRACE_VAR, '"string"'
158+
trace_var :$__TEST_UNTRACE_VAR do "proc" end
159+
trace_var :$__TEST_UNTRACE_VAR, tracer
160+
assert_send_type '(interned, nil) -> Array[String | ::Kernel::_Tracer]',
161+
Kernel, :untrace_var, name, nil
162+
163+
# Passing a String in yields the string if they're the same, or `nil`
164+
string = '"string"'
165+
trace_var :$__TEST_UNTRACE_VAR, string
166+
assert_send_type '(interned, String) -> [String]',
167+
Kernel, :untrace_var, name, string
168+
assert_send_type '(interned, String) -> nil',
169+
Kernel, :untrace_var, name, 'not a trace'
170+
171+
# Passing a `tracer` yields the tracer if it's set, or `nil` otherwise
172+
trace_var :$__TEST_UNTRACE_VAR, tracer
173+
assert_send_type '[T < ::Kernel::_Tracer] (interned, T) -> [T]',
174+
Kernel, :untrace_var, name, tracer
175+
assert_send_type '[T < ::Kernel::_Tracer] (interned, T) -> nil',
176+
Kernel, :untrace_var, name, tracer
177+
178+
# Anything else is `nil`
179+
with_untyped do |trace|
180+
next if nil == trace
181+
assert_send_type '(interned, untyped) -> nil',
182+
Kernel, :untrace_var, name, trace
183+
end
184+
end
185+
ensure
186+
# Just in case an exception stopped it, we don't want to continue tracing.
187+
# We do `defined?` as `untrace_var :$some_undefined_global` fails
188+
untrace_var :$__TEST_UNTRACE_VAR if defined? $__TEST_UNTRACE_VAR
189+
end
115190
end
116191

117192
class KernelInstanceTest < Test::Unit::TestCase

0 commit comments

Comments
 (0)