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 in the example, constant attibutes for all documents may be accessed from Document[].

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.



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

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



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

def comments
  @comments
end

#default_const_nameObject

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



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

def default_const_name
  @default_const_name
end

#resolvedObject

Flag indicating whether or not self has been resolved



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

def resolved
  @resolved
end

#source_fileObject

The source file for self, used during resolve



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

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.



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

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.



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

def const_attrs
  @const_attrs ||= {}
end

.scan(str, key = '[a-z_]+') ⇒ 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.



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

def scan(str, key='[a-z_]+') # :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.

Note this method will return ALL attributes associated with const_name, not just attributes associated with self.



141
142
143
144
# File 'lib/lazydoc/document.rb', line 141

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.



165
166
167
168
169
# File 'lib/lazydoc/document.rb', line 165

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"


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

def register___(comment_class=Comment, caller_index=0)
  caller[caller_index] =~ CALLER_REGEXP
  block = lambda do |scanner, lines|
    n = $2.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.



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
239
240
# File 'lib/lazydoc/document.rb', line 202

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) 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 $3 == '-' && $2 == 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.



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

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