Skip to content

Commit

Permalink
Support @attr* on non-struct classes
Browse files Browse the repository at this point in the history
  • Loading branch information
lsegal committed Oct 14, 2010
1 parent 9ee74ef commit 57a56dc
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 48 deletions.
6 changes: 5 additions & 1 deletion lib/yard/handlers/ruby/class_handler.rb
Expand Up @@ -18,7 +18,11 @@ class YARD::Handlers::Ruby::ClassHandler < YARD::Handlers::Ruby::Base
o.superclass = superclass if superclass
o.superclass.type = :class if o.superclass.is_a?(Proxy)
end
parse_struct_superclass(klass, statement[1]) if is_a_struct
if is_a_struct
parse_struct_superclass(klass, statement[1])
elsif klass
create_attributes(klass, members_from_tags(klass))
end
parse_block(statement[2], namespace: klass)

if undocsuper
Expand Down
6 changes: 5 additions & 1 deletion lib/yard/handlers/ruby/legacy/class_handler.rb
Expand Up @@ -19,7 +19,11 @@ class YARD::Handlers::Ruby::Legacy::ClassHandler < YARD::Handlers::Ruby::Legacy:
o.superclass = superclass if superclass
o.superclass.type = :class if o.superclass.is_a?(Proxy)
end
parse_struct_subclass(klass, superclass_def) if is_a_struct
if is_a_struct
parse_struct_subclass(klass, superclass_def)
elsif klass
create_attributes(klass, members_from_tags(klass))
end
parse_block(:namespace => klass)

if undocsuper
Expand Down
11 changes: 10 additions & 1 deletion lib/yard/handlers/ruby/struct_handler_methods.rb
@@ -1,4 +1,4 @@
# Helper methods to parse @attr_* tags on a Struct class.
# Helper methods to parse @attr_* tags on a class.
#
# @since 0.5.6
module YARD::Handlers::Ruby::StructHandlerMethods
Expand All @@ -15,6 +15,15 @@ def member_tag_for_member(klass, member, type = :read)
specific_tag = type == :read ? :attr_reader : :attr_writer
(klass.tags(specific_tag) + klass.tags(:attr)).find {|tag| tag.name == member}
end

# Retrieves all members defined in @attr* tags
#
# @param [ClassObject] klass the class with the attributes
# @return [Array<String>] the list of members defined as attributes on the class
def members_from_tags(klass)
tags = klass.tags(:attr) + klass.tags(:attr_reader) + klass.tags(:attr_writer)
tags.map {|t| t.name }.uniq
end

# Determines whether to create an attribute method based on the class's
# tags.
Expand Down
94 changes: 49 additions & 45 deletions spec/handlers/class_handler_spec.rb
Expand Up @@ -174,60 +174,64 @@ class Exception
obj.tag(:param).types.should == ["IO"]
end

it "defines both readers and writers when @attr is used on Structs" do
obj = Registry.at("SemiDoccedStruct")
attrs = obj.attributes[:instance]
attrs[:first][:read].should_not be_nil
attrs[:first][:write].should_not be_nil
end
["SemiDoccedStruct", "NotAStruct"].each do |struct|
describe("Attributes on a " + (struct == "NotAStruct" ? "class" : "struct")) do
it "defines both readers and writers when @attr is used on Structs" do
obj = Registry.at(struct)
attrs = obj.attributes[:instance]
attrs[:first][:read].should_not be_nil
attrs[:first][:write].should_not be_nil
end

it "defines only a reader when only @attr_reader is used on Structs" do
obj = Registry.at("SemiDoccedStruct")
attrs = obj.attributes[:instance]
attrs[:second][:read].should_not be_nil
attrs[:second][:write].should be_nil
end
it "defines only a reader when only @attr_reader is used on Structs" do
obj = Registry.at(struct)
attrs = obj.attributes[:instance]
attrs[:second][:read].should_not be_nil
attrs[:second][:write].should be_nil
end

it "defines only a writer when only @attr_writer is used on Structs" do
obj = Registry.at("SemiDoccedStruct")
attrs = obj.attributes[:instance]
attrs[:third][:read].should be_nil
attrs[:third][:write].should_not be_nil
end
it "defines only a writer when only @attr_writer is used on Structs" do
obj = Registry.at(struct)
attrs = obj.attributes[:instance]
attrs[:third][:read].should be_nil
attrs[:third][:write].should_not be_nil
end

it "defines a reader with correct return types when @attr_reader is used on Structs" do
obj = Registry.at("SemiDoccedStruct#second")
obj.tag(:return).types.should == ["Fixnum"]
end
it "defines a reader with correct return types when @attr_reader is used on Structs" do
obj = Registry.at("#{struct}#second")
obj.tag(:return).types.should == ["Fixnum"]
end

it "defines a writer with correct parameter types when @attr_writer is used on Structs" do
obj = Registry.at("SemiDoccedStruct#third=")
obj.tag(:param).types.should == ["Array"]
end
it "defines a writer with correct parameter types when @attr_writer is used on Structs" do
obj = Registry.at("#{struct}#third=")
obj.tag(:param).types.should == ["Array"]
end

it "defines a reader and a writer when both @attr_reader and @attr_writer are used" do
obj = Registry.at("SemiDoccedStruct")
attrs = obj.attributes[:instance]
attrs[:fourth][:read].should_not be_nil
attrs[:fourth][:write].should_not be_nil
end
it "defines a reader and a writer when both @attr_reader and @attr_writer are used" do
obj = Registry.at(struct)
attrs = obj.attributes[:instance]
attrs[:fourth][:read].should_not be_nil
attrs[:fourth][:write].should_not be_nil
end

it "uses @attr_reader for the getter when both @attr_reader and @attr_writer are given" do
obj = Registry.at("SemiDoccedStruct#fourth")
obj.tag(:return).types.should == ["#read"]
end
it "uses @attr_reader for the getter when both @attr_reader and @attr_writer are given" do
obj = Registry.at("#{struct}#fourth")
obj.tag(:return).types.should == ["#read"]
end

it "uses @attr_writer for the setter when both @attr_reader and @attr_writer are given" do
obj = Registry.at("SemiDoccedStruct#fourth=")
obj.tag(:param).types.should == ["IO"]
end
it "uses @attr_writer for the setter when both @attr_reader and @attr_writer are given" do
obj = Registry.at("#{struct}#fourth=")
obj.tag(:param).types.should == ["IO"]
end

it "extracts text from @attr_reader" do
Registry.at("SemiDoccedStruct#fourth").docstring.should == "returns a proc that reads"
end
it "extracts text from @attr_reader" do
Registry.at("#{struct}#fourth").docstring.should == "returns a proc that reads"
end

it "extracts text from @attr_writer" do
Registry.at("SemiDoccedStruct#fourth=").docstring.should == "sets the proc that writes stuff"
it "extracts text from @attr_writer" do
Registry.at("#{struct}#fourth=").docstring.should == "sets the proc that writes stuff"
end
end
end

it "should inherit from a regular struct" do
Expand Down
7 changes: 7 additions & 0 deletions spec/handlers/examples/class_handler_001.rb.txt
Expand Up @@ -107,6 +107,13 @@ end
class SemiDoccedStruct < Struct.new(:first, :second, :third, :fourth)
end

# @attr [String] first the first entry
# @attr_reader [Fixnum] second this only has a reader
# @attr_writer [Array] third this only has a writer
# @attr_reader [#read] fourth returns a proc that reads
# @attr_writer [IO] fourth sets the proc that writes stuff
class NotAStruct; end

class Outer1
class Inner1 < self; end
end

0 comments on commit 57a56dc

Please sign in to comment.