Permalink
Browse files

Handle private_class_method and public_class_method correctly by copy…

…ing methods from superclasses when visibility needs to be changed
  • Loading branch information...
1 parent 1877775 commit 5fb832a017acf08e9139dc8ce271500c231f887c @drbrain drbrain committed May 13, 2011
View
@@ -14,6 +14,8 @@
* Completing IO::o in `ri -i` now returns results. Ruby Bug #3167
* RDoc::Parser::C ignores prototypes better. Pull Request #34 by Pete
Higgins.
+ * private_class_method and public_class_method are now parsed correctly for
+ inherited methods. Issue #16 by gitsucks.
=== 3.5.3 / 2010-02-06
View
@@ -138,11 +138,21 @@ def complete min_visibility
end
##
+ # Iterates the ancestors of this class or module for which an
+ # RDoc::ClassModule exists.
+
+ def each_ancestor # :yields: module
+ ancestors.each do |mod|
+ next if String === mod
+ yield mod
+ end
+ end
+
+ ##
# Looks for a symbol in the #ancestors. See Context#find_local_symbol.
def find_ancestor_local_symbol symbol
- ancestors.each do |m|
- next if m.is_a?(String)
+ each_ancestor do |m|
res = m.find_local_symbol(symbol)
return res if res
end
View
@@ -181,6 +181,20 @@ def done_documenting=(value)
end
##
+ # Yields each parent of this CodeObject. See also
+ # RDoc::ClassModule#each_ancestor
+
+ def each_parent
+ code_object = self
+
+ while code_object = code_object.parent do
+ yield code_object
+ end
+
+ self
+ end
+
+ ##
# Force the documentation of this object unless documentation
# has been turned off by :endoc:
#--
View
@@ -950,10 +950,14 @@ def methods_by_type section = nil
##
# Yields AnyMethod and Attr entries matching the list of names in +methods+.
- def methods_matching(methods, singleton = false)
+ def methods_matching(methods, singleton = false, &block)
(@method_list + @attributes).each do |m|
yield m if methods.include?(m.name) and m.singleton == singleton
end
+
+ each_ancestor do |parent|
+ parent.methods_matching(methods, singleton, &block)
+ end
end
##
View
@@ -1558,32 +1558,45 @@ def parse_visibility(container, single, tk)
when TkNL, TkUNLESS_MOD, TkIF_MOD, TkSEMICOLON then
container.ongoing_visibility = vis
else
- if vis_type == 'module_function' then
+ new_methods = []
+
+ case vis_type
+ when 'module_function' then
args = parse_symbol_arg
container.set_visibility_for args, :private, false
- module_functions = []
-
container.methods_matching args do |m|
s_m = m.dup
s_m.record_location @top_level
s_m.singleton = true
- s_m.visibility = :public
- module_functions << s_m
+ new_methods << s_m
end
+ when 'public_class_method', 'private_class_method' then
+ args = parse_symbol_arg
- module_functions.each do |s_m|
- case s_m
- when RDoc::AnyMethod then
- container.add_method s_m
- when RDoc::Attr then
- container.add_attribute s_m
+ container.methods_matching args, true do |m|
+ if m.parent != container then
+ m = m.dup
+ m.record_location @top_level
+ new_methods << m
end
+
+ m.visibility = vis
end
else
args = parse_symbol_arg
container.set_visibility_for args, vis, singleton
end
+
+ new_methods.each do |method|
+ case method
+ when RDoc::AnyMethod then
+ container.add_method method
+ when RDoc::Attr then
+ container.add_attribute method
+ end
+ method.visibility = vis
+ end
end
end
@@ -8,6 +8,10 @@ def setup
@RM = RDoc::Markup
end
+ def test_ancestors
+ assert_equal [@parent], @child.ancestors
+ end
+
def test_comment_equals
cm = RDoc::ClassModule.new 'Klass'
cm.comment = '# comment 1'
@@ -23,6 +27,16 @@ def test_comment_equals
assert_equal "comment 1\n---\ncomment 2\n---\n* comment 3", cm.comment
end
+ def test_each_ancestor
+ ancestors = []
+
+ @child.each_ancestor do |mod|
+ ancestors << mod
+ end
+
+ assert_equal [@parent], ancestors
+ end
+
# handle making a short module alias of yourself
def test_find_class_named
@@ -119,6 +119,16 @@ def test_done_documenting
assert @co.document_children
end
+ def test_each_parent
+ parents = []
+
+ @parent_m.each_parent do |code_object|
+ parents << code_object
+ end
+
+ assert_equal [@parent, @xref_data], parents
+ end
+
def test_full_name_equals
@co.full_name = 'hi'
View
@@ -448,5 +448,35 @@ def test_methods_by_type_section
assert_equal expected, @c1.methods_by_type(separate)
end
+ def test_methods_matching
+ methods = []
+
+ @parent.methods_matching 'm' do |m|
+ methods << m
+ end
+
+ assert_equal [@parent_m], methods
+ end
+
+ def test_methods_matching_singleton
+ methods = []
+
+ @parent.methods_matching 'm', true do |m|
+ methods << m
+ end
+
+ assert_equal [@parent__m], methods
+ end
+
+ def test_methods_matching_inherit
+ methods = []
+
+ @child.methods_matching 'm' do |m|
+ methods << m
+ end
+
+ assert_equal [@parent_m], methods
+ end
+
end
@@ -1799,6 +1799,56 @@ def test_parse_statements_identifier_private
assert_equal :private, foo.visibility
end
+ def test_parse_statements_identifier_public_class_method
+ content = <<-CONTENT
+class Date
+ def self.now; end
+ private_class_method :now
+end
+
+class DateTime < Date
+ public_class_method :now
+end
+ CONTENT
+
+ util_parser content
+
+ @parser.parse_statements @top_level
+
+ date, date_time = @top_level.classes
+
+ date_now = date.method_list.first
+ date_time_now = date_time.method_list.first
+
+ assert_equal :private, date_now.visibility
+ assert_equal :public, date_time_now.visibility
+ end
+
+ def test_parse_statements_identifier_private_class_method
+ content = <<-CONTENT
+class Date
+ def self.now; end
+ public_class_method :now
+end
+
+class DateTime < Date
+ private_class_method :now
+end
+ CONTENT
+
+ util_parser content
+
+ @parser.parse_statements @top_level
+
+ date, date_time = @top_level.classes
+
+ date_now = date.method_list.first
+ date_time_now = date_time.method_list.first
+
+ assert_equal :public, date_now.visibility, date_now.full_name
+ assert_equal :private, date_time_now.visibility, date_time_now.full_name
+ end
+
def test_parse_statements_identifier_require
content = "require 'bar'"
@@ -12,7 +12,10 @@ def setup
def test_class_all_classes_and_modules
expected = %w[
- C1 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 M1 M1::M2
+ C1 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1
+ Child
+ M1 M1::M2
+ Parent
]
assert_equal expected,
@@ -22,6 +25,7 @@ def test_class_all_classes_and_modules
def test_class_classes
expected = %w[
C1 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1
+ Child Parent
]
assert_equal expected, RDoc::TopLevel.classes.map { |m| m.full_name }.sort
View
@@ -63,5 +63,14 @@ def m
module M1::M2
end
+
+class Parent
+ def m() end
+ def self.m() end
+end
+
+class Child < Parent
+end
+
XREF_DATA
View
@@ -38,7 +38,6 @@ def generator.file_dir() nil end
@c1_m = @c1.method_list.last # C1#m
@c1__m = @c1.method_list.first # C1::m
-
@c2 = @xref_data.find_module_named 'C2'
@c2_a = @c2.method_list.last
@c2_b = @c2.method_list.first
@@ -55,6 +54,12 @@ def generator.file_dir() nil end
@m1_m = @m1.method_list.first
@m1_m2 = @xref_data.find_module_named 'M1::M2'
+
+ @parent = @xref_data.find_module_named 'Parent'
+ @child = @xref_data.find_module_named 'Child'
+
+ @parent_m = @parent.method_list.first # Parent#m
+ @parent__m = @parent.method_list.last # Parent::m
end
end

0 comments on commit 5fb832a

Please sign in to comment.