Skip to content

Commit

Permalink
Make Kernel#public_methods spec-compliant
Browse files Browse the repository at this point in the history
  • Loading branch information
seven1m committed Jul 7, 2024
1 parent ed4accb commit f6b7aa4
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 1 deletion.
1 change: 1 addition & 0 deletions include/natalie/kernel_module.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class KernelModule : public Object {
bool neqtilde(Env *, Value);
Value private_methods(Env *, Value = nullptr);
Value protected_methods(Env *, Value = nullptr);
Value public_methods(Env *, Value = nullptr);
Value remove_instance_variable(Env *env, Value name_val);
Value tap(Env *env, Block *block);
bool is_a(Env *env, Value module);
Expand Down
2 changes: 1 addition & 1 deletion lib/natalie/compiler/binding_gen.rb
Original file line number Diff line number Diff line change
Expand Up @@ -997,7 +997,7 @@ def generate_name
gen.binding('Kernel', 'methods', 'KernelModule', 'methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('Kernel', 'private_methods', 'KernelModule', 'private_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('Kernel', 'protected_methods', 'KernelModule', 'protected_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('Kernel', 'public_methods', 'KernelModule', 'methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('Kernel', 'public_methods', 'KernelModule', 'public_methods', argc: 0..1, pass_env: true, pass_block: false, return_type: :Object)
gen.binding('Kernel', 'public_send', 'Object', 'public_send', argc: 1.., pass_env: true, pass_block: true, return_type: :Object)
gen.binding('Kernel', 'object_id', 'Object', 'object_id', argc: 0, pass_env: false, pass_block: false, return_type: :int)
gen.binding('Kernel', 'remove_instance_variable', 'KernelModule', 'remove_instance_variable', argc: 1, pass_env: true, pass_block: false, return_type: :Object)
Expand Down
76 changes: 76 additions & 0 deletions spec/core/kernel/public_methods_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative '../../fixtures/reflection'

# TODO: rewrite
describe "Kernel#public_methods" do
it "returns a list of the names of publicly accessible methods in the object" do
KernelSpecs::Methods.public_methods(false).sort.should include(:hachi,
:ichi, :juu, :juu_ni, :roku, :san, :shi)
KernelSpecs::Methods.new.public_methods(false).sort.should include(:juu_san, :ni)
end

it "returns a list of names without protected accessible methods in the object" do
KernelSpecs::Methods.public_methods(false).sort.should_not include(:juu_ichi)
KernelSpecs::Methods.new.public_methods(false).sort.should_not include(:ku)
end

it "returns a list of the names of publicly accessible methods in the object and its ancestors and mixed-in modules" do
(KernelSpecs::Methods.public_methods(false) & KernelSpecs::Methods.public_methods).sort.should include(
:hachi, :ichi, :juu, :juu_ni, :roku, :san, :shi)
m = KernelSpecs::Methods.new.public_methods
m.should include(:ni, :juu_san)
end

it "returns methods mixed in to the metaclass" do
m = KernelSpecs::Methods.new
m.extend(KernelSpecs::Methods::MetaclassMethods)
m.public_methods.should include(:peekaboo)
end

it "returns public methods for immediates" do
10.public_methods.should include(:divmod)
end
end

describe :kernel_public_methods_supers, shared: true do
it "returns a unique list for an object extended by a module" do
m = ReflectSpecs.oed.public_methods(*@object)
m.select { |x| x == :pub }.sort.should == [:pub]
end

it "returns a unique list for a class including a module" do
m = ReflectSpecs::D.new.public_methods(*@object)
m.select { |x| x == :pub }.sort.should == [:pub]
end

it "returns a unique list for a subclass of a class that includes a module" do
m = ReflectSpecs::E.new.public_methods(*@object)
m.select { |x| x == :pub }.sort.should == [:pub]
end
end

describe :kernel_public_methods_with_falsy, shared: true do
it "returns a list of public methods in without its ancestors" do
ReflectSpecs::F.public_methods(@object).select{|m|/_pub\z/ =~ m}.sort.should == [:ds_pub, :fs_pub]
ReflectSpecs::F.new.public_methods(@object).should == [:f_pub]
end
end

describe "Kernel#public_methods" do
describe "when not passed an argument" do
it_behaves_like :kernel_public_methods_supers, nil, []
end

describe "when passed true" do
it_behaves_like :kernel_public_methods_supers, nil, true
end

describe "when passed false" do
it_behaves_like :kernel_public_methods_with_falsy, nil, false
end

describe "when passed nil" do
it_behaves_like :kernel_public_methods_with_falsy, nil, nil
end
end
7 changes: 7 additions & 0 deletions src/kernel_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,13 @@ Value KernelModule::protected_methods(Env *env, Value recur) {
return klass()->protected_instance_methods(env, FalseObject::the());
}

Value KernelModule::public_methods(Env *env, Value recur) {
if (singleton_class())
return singleton_class()->public_instance_methods(env, recur);
else
return klass()->public_instance_methods(env, FalseObject::the());
}

Value KernelModule::proc(Env *env, Block *block) {
if (block) {
return new ProcObject { block };
Expand Down

0 comments on commit f6b7aa4

Please sign in to comment.