Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Strange behavior in parsing private methods #1496

Open
unurgunite opened this issue May 8, 2023 · 0 comments
Open

Strange behavior in parsing private methods #1496

unurgunite opened this issue May 8, 2023 · 0 comments

Comments

@unurgunite
Copy link

unurgunite commented May 8, 2023

There is a strange behavior while parsing singleton methods within YARD

Steps to reproduce

Let's check for class methods in plain Ruby:

class T
  def m1
    T.m2
  end

  private

  def self.m2
    print 123
  end

  class << self
    private

    def m3; end
  end
end

T.private_methods.include?(:m2) #=> false
T.private_methods.include?(:m3) #=> true
T.m2 #=> 123=> nil
T.m3 #=> 
(irb):19:in `<main>': private method `m3' called for T:Class (NoMethodError)
	from /home/$USER/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.6.4/exe/irb:9:in `<top (required)>'
	from /home/$USER/.rbenv/versions/3.2.2/bin/irb:25:in `load'
	from /home/$USER/.rbenv/versions/3.2.2/bin/irb:25:in `<main>'

Look, method T.m3 is private and T.m2 -- not. There is additional notes from RuboCop report:

RuboCop: `private` (on line 6) does not make singleton methods private. Use `private_class_method` or `private` inside a `class << self` block instead. [Lint/IneffectiveAccessModifier]

Actual output

Here is output within YARD:

require 'yard'

code = <<~CODE
  class T
    def m1
      T.m2
    end

    private

    def self.m2
      print 123
    end

    class << self
      private

      def m3; end
    end
  end
CODE

def detect_private_methods(code)
  YARD.parse_string(code)
  YARD::Registry.all(:class).map do |class_obj|
    class_obj.meths(inherited: false).map do |method_obj|
      if method_obj.scope == :class && method_obj.visibility == :private
        puts "Method #{method_obj.name} is a #{method_obj.visibility} #{method_obj.scope} method!"
      end
    end
  end
end

detect_private_methods(code)
# Method m2 is a private class method!
# Method m3 is a private class method!
# => [[nil, nil, nil]]

Expected Output

In expected output only method T.m3 should be detected and nothing else:

require 'yard'

code = <<~CODE
  class T
    def m1
      T.m2
    end

    private

    def self.m2
      print 123
    end

    class << self
      private

      def m3; end
    end
  end
CODE

def detect_private_methods(code)
  YARD.parse_string(code)
  YARD::Registry.all(:class).map do |class_obj|
    class_obj.meths(inherited: false).map do |method_obj|
      if method_obj.scope == :class && method_obj.visibility == :private
        puts "Method #{method_obj.name} is a #{method_obj.visibility} #{method_obj.scope} method!"
      end
    end
  end
end

detect_private_methods(code)
# Method m3 is a private class method!
# => [[nil, nil, nil]]

Notes

YARD correctly parses methods scope if we change private keyword to private_class_method:

require 'yard'

code = <<~CODE
  class T
    def m1
      T.m2
    end

    private_class_method def self.m2
      print 123
    end

    class << self
      private

      def m3; end
    end
  end
CODE

def detect_private_methods(code)
  YARD.parse_string(code)
  YARD::Registry.all(:class).map do |class_obj|
    class_obj.meths(inherited: false).map do |method_obj|
      if method_obj.scope == :class && method_obj.visibility == :private
        puts "Method #{method_obj.name} is a #{method_obj.visibility} #{method_obj.scope} method!"
      end
    end
  end
end

detect_private_methods(code)
# Method m2 is a private class method!
# Method m3 is a private class method!
# => [[nil, nil, nil]]

Environment details:

  • OS: Linux archlinux 6.3.1-arch1-1 #1 SMP PREEMPT_DYNAMIC Mon, 01 May 2023 17:42:39 +0000 x86_64 GNU/Linux
  • Ruby version (ruby -v): ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]
  • YARD version (yard -v): yard 0.9.34

I have read the Contributing Guide.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant