1##
2# An attribute created by \#attr, \#attr_reader, \#attr_writer or
3# \#attr_accessor
4
5class RDoc::Attr < RDoc::MethodAttr
6
7  ##
8  # 3::
9  #   RDoc 4
10  #    Added parent name and class
11  #    Added section title
12
13  MARSHAL_VERSION = 3 # :nodoc:
14
15  ##
16  # Is the attribute readable ('R'), writable ('W') or both ('RW')?
17
18  attr_accessor :rw
19
20  ##
21  # Creates a new Attr with body +text+, +name+, read/write status +rw+ and
22  # +comment+.  +singleton+ marks this as a class attribute.
23
24  def initialize(text, name, rw, comment, singleton = false)
25    super text, name
26
27    @rw = rw
28    @singleton = singleton
29    self.comment = comment
30  end
31
32  ##
33  # Attributes are equal when their names, singleton and rw are identical
34
35  def == other
36    self.class == other.class and
37      self.name == other.name and
38      self.rw == other.rw and
39      self.singleton == other.singleton
40  end
41
42  ##
43  # Add +an_alias+ as an attribute in +context+.
44
45  def add_alias(an_alias, context)
46    new_attr = self.class.new(self.text, an_alias.new_name, self.rw,
47                              self.comment, self.singleton)
48
49    new_attr.record_location an_alias.file
50    new_attr.visibility = self.visibility
51    new_attr.is_alias_for = self
52    @aliases << new_attr
53    context.add_attribute new_attr
54    new_attr
55  end
56
57  ##
58  # The #aref prefix for attributes
59
60  def aref_prefix
61    'attribute'
62  end
63
64  ##
65  # Attributes never call super.  See RDoc::AnyMethod#calls_super
66  #
67  # An RDoc::Attr can show up in the method list in some situations (see
68  # Gem::ConfigFile)
69
70  def calls_super # :nodoc:
71    false
72  end
73
74  ##
75  # Returns attr_reader, attr_writer or attr_accessor as appropriate.
76
77  def definition
78    case @rw
79    when 'RW' then 'attr_accessor'
80    when 'R'  then 'attr_reader'
81    when 'W'  then 'attr_writer'
82    end
83  end
84
85  def inspect # :nodoc:
86    alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil
87    visibility = self.visibility
88    visibility = "forced #{visibility}" if force_documentation
89    "#<%s:0x%x %s %s (%s)%s>" % [
90      self.class, object_id,
91      full_name,
92      rw,
93      visibility,
94      alias_for,
95    ]
96  end
97
98  ##
99  # Dumps this Attr for use by ri.  See also #marshal_load
100
101  def marshal_dump
102    [ MARSHAL_VERSION,
103      @name,
104      full_name,
105      @rw,
106      @visibility,
107      parse(@comment),
108      singleton,
109      @file.relative_name,
110      @parent.full_name,
111      @parent.class,
112      @section.title
113    ]
114  end
115
116  ##
117  # Loads this Attr from +array+.  For a loaded Attr the following
118  # methods will return cached values:
119  #
120  # * #full_name
121  # * #parent_name
122
123  def marshal_load array
124    initialize_visibility
125
126    @aliases      = []
127    @parent       = nil
128    @parent_name  = nil
129    @parent_class = nil
130    @section      = nil
131    @file         = nil
132
133    version        = array[0]
134    @name          = array[1]
135    @full_name     = array[2]
136    @rw            = array[3]
137    @visibility    = array[4]
138    @comment       = array[5]
139    @singleton     = array[6] || false # MARSHAL_VERSION == 0
140    #                      7 handled below
141    @parent_name   = array[8]
142    @parent_class  = array[9]
143    @section_title = array[10]
144
145    @file = RDoc::TopLevel.new array[7] if version > 1
146
147    @parent_name ||= @full_name.split('#', 2).first
148  end
149
150  def pretty_print q # :nodoc:
151    q.group 2, "[#{self.class.name} #{full_name} #{rw} #{visibility}", "]" do
152      unless comment.empty? then
153        q.breakable
154        q.text "comment:"
155        q.breakable
156        q.pp @comment
157      end
158    end
159  end
160
161  def to_s # :nodoc:
162    "#{definition} #{name} in: #{parent}"
163  end
164
165  ##
166  # Attributes do not have token streams.
167  #
168  # An RDoc::Attr can show up in the method list in some situations (see
169  # Gem::ConfigFile)
170
171  def token_stream # :nodoc:
172  end
173
174end
175
176