class JsDuck::Aggregator
Groups parsed documentation data from source files into classes.
Produces Hash of classes as result. When a member is found that doesn't belong to any class, it's placed into special “global” class.
Public Class Methods
# File lib/jsduck/aggregator.rb, line 11 def initialize @classes = {} @alt_names = {} @orphans = [] @current_class = nil end
Public Instance Methods
Combines chunk of parsed JavaScript together with previously added chunks. The resulting documentation is accumulated inside this class and can be later accessed through result
method.
-
file SoureFile class instance
# File lib/jsduck/aggregator.rb, line 24 def aggregate(file) @current_class = nil file.each {|doc| register(doc) } end
Returns the final result which is a Hash of all classes indexed by name. It's a hash because some processors applied to this returned classes list need a random-access look up classes by name.
# File lib/jsduck/aggregator.rb, line 33 def result classify_orphans create_global_class @classes end
Private Instance Methods
When class exists, merge it with class node. Otherwise add as new class.
# File lib/jsduck/aggregator.rb, line 53 def add_class(cls) old_cls = @classes[cls[:name]] if !old_cls && @alt_names[cls[:name]] old_cls = @alt_names[cls[:name]] warn_alt_name(cls) end if old_cls merge_classes(old_cls, cls) @current_class = old_cls else @current_class = cls @classes[cls[:name]] = cls # Register all alternate names of class for lookup too cls[:alternateClassNames].each do |altname| if cls[:name] == altname # A buggy documentation, warn. warn_alt_name(cls) else @alt_names[altname] = cls # When an alternate name has been used as a class name before, # then this is one crappy documentation, but attempt to handle # it by merging the class with alt-name into this class. if @classes[altname] merge_classes(cls, @classes[altname]) @classes.delete(altname) warn_alt_name(cls) end end end insert_orphans(cls) end end
# File lib/jsduck/aggregator.rb, line 187 def add_empty_class(name, doc = "") add_class({ :tagname => :class, :name => name, :doc => doc, :alternateClassNames => [], :members => [], :aliases => {}, :files => [{:filename => "", :linenr => 0, :href => ""}], }) end
Tries to place members into classes where they belong.
@member explicitly defines the containing class, but we can meet item with @member=Foo before we actually meet class Foo - in that case we register them as orphans. (Later when we finally meet class Foo, orphans are inserted into it.)
Items without @member belong by default to the preceding class. When no class precedes them - they too are orphaned.
# File lib/jsduck/aggregator.rb, line 123 def add_member(node) # Completely ignore member if @ignore used return if node[:ignore] if node[:owner] if @classes[node[:owner]] add_to_class(@classes[node[:owner]], node) else add_orphan(node) end elsif @current_class node[:owner] = @current_class[:name] add_to_class(@current_class, node) else add_orphan(node) end end
# File lib/jsduck/aggregator.rb, line 145 def add_orphan(node) @orphans << node end
# File lib/jsduck/aggregator.rb, line 141 def add_to_class(cls, member) cls[:members] << member end
Creates classes for orphans that have :owner property defined, and then inserts orphans to these classes.
# File lib/jsduck/aggregator.rb, line 160 def classify_orphans # Clone the orphans array first to avoid problems with # #inster_orphan method deleting items from @orphans array. @orphans.clone.each do |orph| if orph[:owner] class_name = orph[:owner] if !@classes[class_name] # this will add the class and add all orphans to it add_empty_class(class_name) end end end end
Creates class with name “global” and inserts all the remaining orphans into it (but only if there are any orphans).
# File lib/jsduck/aggregator.rb, line 176 def create_global_class return if @orphans.length == 0 add_empty_class("global", "Global variables and functions.") @orphans.each do |orph| orph[:owner] = "global" add_member(orph) end @orphans = [] end
Inserts available orphans to class
# File lib/jsduck/aggregator.rb, line 150 def insert_orphans(cls) members = @orphans.find_all {|node| node[:owner] == cls[:name] } members.each do |node| add_to_class(cls, node) @orphans.delete(node) end end
Merges new class-doc into old one.
# File lib/jsduck/aggregator.rb, line 94 def merge_classes(old, new) # Merge booleans [:extends, :singleton, :private].each do |tag| old[tag] = old[tag] || new[tag] end # Merge arrays [:mixins, :alternateClassNames, :requires, :uses, :files].each do |tag| old[tag] = (old[tag] || []) + (new[tag] || []) end # Merge hashes of arrays [:aliases].each do |tag| new[tag].each_pair do |key, contents| old[tag][key] = (old[tag][key] || []) + contents end end old[:doc] = old[:doc].length > 0 ? old[:doc] : new[:doc] # Additionally the doc-comment can contain configs and constructor old[:members] += new[:members] end
Registers documentation node either as class or as member of some class.
# File lib/jsduck/aggregator.rb, line 43 def register(node) if node[:tagname] == :class add_class(node) else add_member(node) end end
# File lib/jsduck/aggregator.rb, line 89 def warn_alt_name(cls) Logger.warn(:alt_name, "Name #{cls[:name]} used as both classname and alternate classname", cls[:files][0]) end