Class: Lazydoc::Document

Inherits:
Object
  • Object
show all
Defined in:
lib/lazydoc/document.rb

Overview

A Document resolves constant attributes and code comments for a particular source file. Documents may be assigned a default_const_name to be used when a constant attribute does not specify a constant.

# Const::Name::key value a
# ::key value b

doc = Document.new(__FILE__, 'Default')
doc.resolve

Document['Const::Name']['key'].value      # => 'value a'
Document['Default']['key'].value          # => 'value b'

As shown in the example, constant attibutes for all documents are cached in the class-level const_attrs hash and are normally consumed through Document itself.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source_file = nil, default_const_name = nil) ⇒ Document

Returns a new instance of Document.



129
130
131
132
133
134
# File 'lib/lazydoc/document.rb', line 129

def initialize(source_file=nil, default_const_name=nil)
  self.source_file = source_file
  @default_const_name = default_const_name
  @comments = []
  @resolved = false
end

Instance Attribute Details

#commentsObject (readonly)

An array of Comment objects registered to self



124
125
126
# File 'lib/lazydoc/document.rb', line 124

def comments
  @comments
end

#default_const_nameObject

The default constant name used when no constant name is specified for a constant attribute



121
122
123
# File 'lib/lazydoc/document.rb', line 121

def default_const_name
  @default_const_name
end

#resolvedObject

Flag indicating whether or not self has been resolved



127
128
129
# File 'lib/lazydoc/document.rb', line 127

def resolved
  @resolved
end

#source_fileObject

The source file for self, used during resolve



117
118
119
# File 'lib/lazydoc/document.rb', line 117

def source_file
  @source_file
end

Class Method Details

.[](const_name) ⇒ Object

Returns the hash of (key, comment) pairs for const_name stored in const_attrs. If no such hash exists, one will be created.



57
58
59
# File 'lib/lazydoc/document.rb', line 57

def [](const_name)
  const_attrs[const_name] ||= {}
end

.const_attrsObject

A nested hash of (const_name, (key, comment)) pairs tracking the constant attributes assigned to a constant name.



51
52
53
# File 'lib/lazydoc/document.rb', line 51

def const_attrs
  @const_attrs ||= {}
end

.scan(str, key) ⇒ Object

Scans the string or StringScanner for attributes matching the key (keys may be patterns; they are incorporated into a regexp). Regions delimited by the stop and start keys :::- and :::+ are skipped. Yields each (const_name, key, value) triplet to the block.

str = %Q{
# Name::Space::key value
# ::alt alt_value
#
# Ignored::Attribute::not_matched value
# :::-
# Also::Ignored::key value
# :::+
# Another::key another value

Ignored::key value
}

results = []
Document.scan(str, 'key|alt') do |const_name, key, value|
  results << [const_name, key, value]
end

results    
# => [
# ['Name::Space', 'key', 'value'], 
# ['', 'alt', 'alt_value'], 
# ['Another', 'key', 'another value']]

Returns the StringScanner used during scanning.



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/lazydoc/document.rb', line 92

def scan(str, key) # :yields: const_name, key, value
  scanner = case str
  when StringScanner then str
  when String then StringScanner.new(str)
  else raise TypeError, "can't convert #{str.class} into StringScanner or String"
  end
  
  regexp = /^(.*?)::(:-|#{key})/
  while !scanner.eos?
    break if scanner.skip_until(regexp) == nil

    if scanner[2] == ":-"
      scanner.skip_until(/:::\+/)
    else
      next unless scanner[1] =~ CONSTANT_REGEXP
      key = scanner[2]
      yield($1.to_s, key, scanner.matched.strip) if scanner.scan(/[ \r\t].*$|$/)
    end
  end

  scanner
end

Instance Method Details

#[](const_name) ⇒ Object

Returns the attributes for the specified const_name. If an empty const_name (”) is specified, and a default_const_name is set, the default_const_name will be used instead.



139
140
141
142
# File 'lib/lazydoc/document.rb', line 139

def [](const_name)
  const_name = default_const_name if default_const_name && const_name == ''
  Document[const_name]
end

#register(line_number, comment_class = Comment) ⇒ Object

Registers the specified line number to self. Register may take an integer or a regexp for dynamic evaluation. See Comment#resolve for more details.

Returns the newly registered comment.



163
164
165
166
167
# File 'lib/lazydoc/document.rb', line 163

def register(line_number, comment_class=Comment)
  comment = comment_class.new(line_number, self)
  comments << comment
  comment
end

#register___(comment_class = Comment, caller_index = 0) ⇒ Object

Registers the next comment.

lazydoc = Document.new(__FILE__)

c = lazydoc.register___
# this is the comment
# that is registered
def method(a,b,c)
end

lazydoc.resolve

c.subject      # => "def method(a,b,c)"
c.comment      # => "this is the comment that is registered"


184
185
186
187
188
189
190
191
192
# File 'lib/lazydoc/document.rb', line 184

def register___(comment_class=Comment, caller_index=0)
  caller[caller_index] =~ CALLER_REGEXP
  block = lambda do |scanner, lines|
    n = $3.to_i
    n += 1 while lines[n] =~ /^\s*(#.*)?$/
    n
  end
  register(block, comment_class)
end

#resolve(str = nil, force = false) ⇒ Object

Scans str for constant attributes and adds them to Document.const_attrs. Comments registered with self are also resolved against str. If no str is specified, the contents of source_file are used instead.

Resolve does nothing if resolved == true, unless force is also specified. Returns true if str was resolved, or false otherwise.



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/lazydoc/document.rb', line 200

def resolve(str=nil, force=false)
  return false if resolved && !force
  @resolved = true
  
  str = File.read(source_file) if str == nil
  lines = Utils.split_lines(str)
  scanner = Utils.convert_to_scanner(str)
  
  Document.scan(scanner, '[a-z_]+') do |const_name, key, value|
    # get or initialize the comment that will be parsed
    comment = (self[const_name][key] ||= Subject.new(nil, self))
    
    # skip non-comment constant attributes
    next unless comment.kind_of?(Comment)
    
    # parse the comment
    comment.parse_down(scanner, lines) do |line|
      if line =~ ATTRIBUTE_REGEXP
        # rewind to capture the next attribute unless an end is specified.
        scanner.unscan unless $4 == '-' && $3 == key && $1.to_s == const_name
        true
      else false
      end
    end
    
    # set the subject
    comment.subject = value
  end
  
  # resolve registered comments
  comments.each do |comment|
    comment.parse_up(scanner, lines)
    
    n = comment.line_number
    comment.subject = n.kind_of?(Integer) ? lines[n] : nil
  end
  
  true
end

#summarizeObject

Summarizes constant attributes registered to self by collecting them into a nested hash of (const_name, (key, comment)) pairs. A block may be provided to collect values from the comments; each comment is yielded to the block and the return stored in it’s place.



244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/lazydoc/document.rb', line 244

def summarize
  const_hash = {}
  Document.const_attrs.each_pair do |const_name, attributes|
    next if attributes.empty?

    const_hash[const_name] = attr_hash = {}
    attributes.each_pair do |key, comment|
      next unless comment.document == self
      attr_hash[key] = (block_given? ? yield(comment) : comment)
    end
  end
  const_hash
end