From e36555b18abffc564351eb6385335b18926df60d Mon Sep 17 00:00:00 2001 From: USAMI Kenta Date: Sun, 11 Oct 2026 00:35:40 +0900 Subject: [PATCH] Add missing core singleton methods Add signatures for singleton methods that are defined in Ruby 4.0 but were missing from core/: - Hash.ruby2_keywords_hash, Hash.ruby2_keywords_hash? - Kernel.set_trace_func, Kernel.trap - Process.last_status, Process.setpgrp - Process::Status.wait - Process::Sys.getegid --- core/hash.rbs | 33 ++++++++++ core/kernel.rbs | 119 ++++++++++++++++++++++++++++++++++++ core/process.rbs | 76 +++++++++++++++++++++++ test/stdlib/Hash_test.rb | 14 +++++ test/stdlib/Kernel_test.rb | 25 ++++++++ test/stdlib/Process_test.rb | 79 ++++++++++++++++++++++++ 6 files changed, 346 insertions(+) create mode 100644 test/stdlib/Process_test.rb diff --git a/core/hash.rbs b/core/hash.rbs index 871c688895..fe76f6818d 100644 --- a/core/hash.rbs +++ b/core/hash.rbs @@ -532,6 +532,39 @@ class Hash[unchecked out K, unchecked out V] | [K, V] (array[ _Pair[K, V] ] two_element_arrays) -> instance | [T] (*T objects) -> Hash[T, T] + # + # Duplicates a given hash and adds a ruby2_keywords flag. This method is not for + # casual use; debugging, researching, and some truly necessary cases like + # deserialization of arguments. + # + # h = {k: 1} + # h = Hash.ruby2_keywords_hash(h) + # def foo(k: 42) + # k + # end + # foo(*[h]) #=> 1 with neither a warning or an error + # + def self.ruby2_keywords_hash: [H < Hash[untyped, untyped]] (H hash) -> H + + # + # Checks if a given hash is flagged by Module#ruby2_keywords (or + # Proc#ruby2_keywords). This method is not for casual use; debugging, + # researching, and some truly necessary cases like serialization of arguments. + # + # ruby2_keywords def foo(*args) + # Hash.ruby2_keywords_hash?(args.last) + # end + # foo(k: 1) #=> true + # foo({k: 1}) #=> false + # + def self.ruby2_keywords_hash?: (Hash[untyped, untyped] hash) -> bool + # + # Establishes *proc* as the handler for tracing, or disables tracing if the + # parameter is `nil`. + # + # Note: this method is obsolete, please use TracePoint instead. + # + # *proc* takes up to six parameters: + # + # * an event name string + # * a filename string + # * a line number + # * a method name symbol, or nil + # * a binding, or nil + # * the class, module, or nil + # + # *proc* is invoked whenever an event occurs. + # + # Events are: + # + # "c-call" + # : call a C-language routine + # + # "c-return" + # : return from a C-language routine + # + # "call" + # : call a Ruby method + # + # "class" + # : start a class or module definition + # + # "end" + # : finish a class or module definition + # + # "line" + # : execute code on a new line + # + # "raise" + # : raise an exception + # + # "return" + # : return from a Ruby method + # + # + # Tracing is disabled within the context of *proc*. + # + # class Test + # def test + # a = 1 + # b = 2 + # end + # end + # + # set_trace_func proc { |event, file, line, id, binding, class_or_module| + # printf "%8s %s:%-2d %16p %14p\n", event, file, line, id, class_or_module + # } + # t = Test.new + # t.test + # + # Produces: + # + # c-return prog.rb:8 :set_trace_func Kernel + # line prog.rb:11 nil nil + # c-call prog.rb:11 :new Class + # c-call prog.rb:11 :initialize BasicObject + # c-return prog.rb:11 :initialize BasicObject + # c-return prog.rb:11 :new Class + # line prog.rb:12 nil nil + # call prog.rb:2 :test Test + # line prog.rb:3 :test Test + # line prog.rb:4 :test Test + # return prog.rb:5 :test Test + # + def self?.set_trace_func: (Proc proc) -> Proc + | (nil) -> nil + # + # Specifies the handling of signals. Returns the previous handler for the given + # signal. + # + # Argument `signal` is a signal name (a string or symbol such as `SIGALRM` or + # `SIGUSR1`) or an integer signal number. When `signal` is a string or symbol, + # the leading characters `SIG` may be omitted. + # + # Argument `command` or block provided specifies code to be run when the signal + # is raised. + # + # Argument `command` may also be a string or symbol with the following special + # values: + # + # * `IGNORE`, `SIG_IGN`: the signal will be ignored. + # * `DEFAULT`, `SIG_DFL`: Ruby's default handler will be invoked. + # * `EXIT`: the process will be terminated by the signal. + # * `SYSTEM_DEFAULT`: the operating system's default handler will be invoked. + # + # The special signal name `EXIT` or signal number zero will be invoked just + # prior to program termination: + # + # Signal.trap(0, proc { puts "Terminating: #{$$}" }) + # Signal.trap("CLD") { puts "Child died" } + # fork && Process.wait + # + # Outputs: + # + # Terminating: 27461 + # Child died + # Terminating: 27460 + # + def self?.trap: (Integer | interned signal) { (Integer) -> void } -> Signal::trap_command + | (Integer | interned signal, Signal::trap_command command) -> Signal::trap_command + # + # Returns a Process::Status object representing the most recently exited child + # process in the current thread, or `nil` if none: + # + # Process.spawn('ruby', '-e', 'exit 13') + # Process.wait + # Process.last_status # => # + # + # Process.spawn('ruby', '-e', 'exit 14') + # Process.wait + # Process.last_status # => # + # + # Process.spawn('ruby', '-e', 'exit 15') + # # 'exit 15' has not been reaped by #wait. + # Process.last_status # => # + # Process.wait + # Process.last_status # => # + # + def self.last_status: () -> Process::Status? + # + # Equivalent to setpgid(0, 0). + # + # Not available on all platforms. + # + def self.setpgrp: () -> Integer + # + # Like Process.wait, but returns a Process::Status object (instead of an integer + # pid or nil); see Process.wait for the values of `pid` and `flags`. + # + # If there are child processes, waits for a child process to exit and returns a + # Process::Status object containing information on that process; sets + # thread-local variable $?: + # + # Process.spawn('cat /nop') # => 1155880 + # Process::Status.wait # => # + # $? # => # + # + # If there is no child process, returns an "empty" Process::Status object that + # does not represent an actual process; does not set thread-local variable + # $?: + # + # Process::Status.wait # => # + # $? # => # # Unchanged. + # + # May invoke the scheduler hook Fiber::Scheduler#process_wait. + # + # Not available on all platforms. + # + def self.wait: (?int pid) -> Process::Status + | (int pid, int flags) -> Process::Status? + # + # Returns the effective group ID for the current process: + # + # Process.egid # => 500 + # + # Not available on all platforms. + # + def self.getegid: () -> Integer + #