Loading lib/jsduck/class.rb +52 −9 Original line number Diff line number Diff line Loading @@ -8,8 +8,16 @@ module JsDuck class Class attr_accessor :relations def initialize(doc) # Creates JSDuck class. # # Pass true as second parameter to create a placeholder class. def initialize(doc, class_exists=true) @doc = doc # Wrap classname into custom string class that allows # differenciating between existing and missing classes. @doc[:name] = ClassNameString.new(@doc[:name], class_exists) @doc[:members] = Class.default_members_hash if !@doc[:members] @doc[:statics] = Class.default_members_hash if !@doc[:statics] @relations = nil Loading Loading @@ -44,15 +52,25 @@ module JsDuck p ? p.superclasses + [p] : [] end # Returns array of mixin class instances. # Returns empty array if no mixins # Returns all direct mixins of this class. Same as #deps(:mixins). def mixins @doc[:mixins] ? @doc[:mixins].collect {|classname| lookup(classname) }.compact : [] deps(:mixins) end # Returns an array of class instances this class directly depends on. # Possible types are: # # - :mixins # - :requires # - :uses # def deps(type) @doc[type] ? @doc[type].collect {|classname| lookup(classname) } : [] end # Returns all mixins this class and its parent classes def all_mixins mixins + (parent ? parent.all_mixins : []) # Same ase #deps, but pulls out the dependencies from all parent classes. def parent_deps(type) parent ? parent.deps(type) + parent.parent_deps(type) : [] end # Looks up class object by name Loading @@ -60,10 +78,18 @@ module JsDuck def lookup(classname) if @relations[classname] @relations[classname] elsif !@relations.ignore?(classname) elsif @relations.ignore?(classname) || classname =~ /\*/ # Ignore explicitly ignored classes and classnames with # wildcards in them. We could expand the wildcard, but that # can result in a very long list of classes, like when # somebody requires 'Ext.form.*', so for now we do the # simplest thing and ignore it. Class.new({:name => classname}, false) else context = @doc[:files][0] Logger.instance.warn(:extend, "Class #{classname} not found", context[:filename], context[:linenr]) nil # Create placeholder class Class.new({:name => classname}, false) end end Loading Loading @@ -276,4 +302,21 @@ module JsDuck end end # String class for classnames that has extra method #exists? which # returns false when class with such name doesn't exist. # # This ability is used by JsDuck::Renderer, which only receives # names of various classes but needs to only render existing classes # as links. class ClassNameString < String def initialize(str, exists=true) super(str) @exists = exists end def exists? @exists end end end lib/jsduck/full_exporter.rb +6 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,12 @@ module JsDuck h[:superclasses] = cls.superclasses.collect {|c| c.full_name } h[:subclasses] = @relations.subclasses(cls).collect {|c| c.full_name } h[:mixedInto] = @relations.mixed_into(cls).collect {|c| c.full_name } h[:allMixins] = cls.all_mixins.collect {|c| c.full_name } h[:mixins] = cls.deps(:mixins).collect {|c| c.full_name } h[:parentMixins] = cls.parent_deps(:mixins).collect {|c| c.full_name } h[:requires] = cls.deps(:requires).collect {|c| c.full_name } h[:uses] = cls.deps(:uses).collect {|c| c.full_name } h end Loading lib/jsduck/logger.rb +1 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ module JsDuck @warning_docs = [ [:global, "Member doesn't belong to any class"], [:inheritdoc, "@inheritdoc referring to unknown class or member"], [:extend, "@extend or @mixin referring to unknown class"], [:extend, "@extend/mixin/requires/uses referring to unknown class"], [:link, "{@link} to unknown class or member"], [:link_ambiguous, "{@link} is ambiguous"], [:link_auto, "Auto-detected link to unknown class or member"], Loading lib/jsduck/renderer.rb +13 −14 Original line number Diff line number Diff line Loading @@ -43,7 +43,8 @@ module JsDuck items = [ render_alternate_class_names, render_tree, render_dependencies(:allMixins, "Mixins"), render_dependencies(:mixins, "Mixins"), render_dependencies(:parentMixins, "Inherited mixins"), render_dependencies(:requires, "Requires"), render_dependencies(:subclasses, "Subclasses"), render_dependencies(:mixedInto, "Mixed into"), Loading @@ -69,7 +70,7 @@ module JsDuck return if !@cls[type] || @cls[type].length == 0 return [ "<h4>#{title}</h4>", @cls[type].sort.map {|name| "<div class='dependency'>#{render_link(name)}</div>" }, @cls[type].sort.map {|name| "<div class='dependency'>#{name.exists? ? render_link(name) : name}</div>" }, ] end Loading @@ -90,23 +91,21 @@ module JsDuck # We still create the tree, but without links in it. def render_tree return if !@cls[:extends] || @cls[:extends] == "Object" tree = ["<h4>Hierarchy</h4>"] if @cls[:superclasses].length > 0 tree + render_class_tree(@cls[:superclasses].concat([@cls[:name]]), {:first => true, :links => true}) else tree + render_class_tree([@cls[:extends], @cls[:name]], {:first => true}) end return [ "<h4>Hierarchy</h4>", render_class_tree(@cls[:superclasses] + [@cls[:name]]) ] end def render_class_tree(superclasses, o) return "" if superclasses.length == 0 def render_class_tree(classes, i=0) return "" if classes.length <= i name = superclasses[0] name = classes[i] return [ "<div class='subclass #{o[:first] ? 'first-child' : ''}'>", superclasses.length > 1 ? (o[:links] ? render_link(name) : name) : "<strong>#{name}</strong>", render_class_tree(superclasses.slice(1, superclasses.length-1), {:links => o[:links]}), "<div class='subclass #{i == 0 ? 'first-child' : ''}'>", classes.length-1 == i ? "<strong>#{name}</strong>" : (name.exists? ? render_link(name) : name), render_class_tree(classes, i+1), "</div>", ] end Loading Loading
lib/jsduck/class.rb +52 −9 Original line number Diff line number Diff line Loading @@ -8,8 +8,16 @@ module JsDuck class Class attr_accessor :relations def initialize(doc) # Creates JSDuck class. # # Pass true as second parameter to create a placeholder class. def initialize(doc, class_exists=true) @doc = doc # Wrap classname into custom string class that allows # differenciating between existing and missing classes. @doc[:name] = ClassNameString.new(@doc[:name], class_exists) @doc[:members] = Class.default_members_hash if !@doc[:members] @doc[:statics] = Class.default_members_hash if !@doc[:statics] @relations = nil Loading Loading @@ -44,15 +52,25 @@ module JsDuck p ? p.superclasses + [p] : [] end # Returns array of mixin class instances. # Returns empty array if no mixins # Returns all direct mixins of this class. Same as #deps(:mixins). def mixins @doc[:mixins] ? @doc[:mixins].collect {|classname| lookup(classname) }.compact : [] deps(:mixins) end # Returns an array of class instances this class directly depends on. # Possible types are: # # - :mixins # - :requires # - :uses # def deps(type) @doc[type] ? @doc[type].collect {|classname| lookup(classname) } : [] end # Returns all mixins this class and its parent classes def all_mixins mixins + (parent ? parent.all_mixins : []) # Same ase #deps, but pulls out the dependencies from all parent classes. def parent_deps(type) parent ? parent.deps(type) + parent.parent_deps(type) : [] end # Looks up class object by name Loading @@ -60,10 +78,18 @@ module JsDuck def lookup(classname) if @relations[classname] @relations[classname] elsif !@relations.ignore?(classname) elsif @relations.ignore?(classname) || classname =~ /\*/ # Ignore explicitly ignored classes and classnames with # wildcards in them. We could expand the wildcard, but that # can result in a very long list of classes, like when # somebody requires 'Ext.form.*', so for now we do the # simplest thing and ignore it. Class.new({:name => classname}, false) else context = @doc[:files][0] Logger.instance.warn(:extend, "Class #{classname} not found", context[:filename], context[:linenr]) nil # Create placeholder class Class.new({:name => classname}, false) end end Loading Loading @@ -276,4 +302,21 @@ module JsDuck end end # String class for classnames that has extra method #exists? which # returns false when class with such name doesn't exist. # # This ability is used by JsDuck::Renderer, which only receives # names of various classes but needs to only render existing classes # as links. class ClassNameString < String def initialize(str, exists=true) super(str) @exists = exists end def exists? @exists end end end
lib/jsduck/full_exporter.rb +6 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,12 @@ module JsDuck h[:superclasses] = cls.superclasses.collect {|c| c.full_name } h[:subclasses] = @relations.subclasses(cls).collect {|c| c.full_name } h[:mixedInto] = @relations.mixed_into(cls).collect {|c| c.full_name } h[:allMixins] = cls.all_mixins.collect {|c| c.full_name } h[:mixins] = cls.deps(:mixins).collect {|c| c.full_name } h[:parentMixins] = cls.parent_deps(:mixins).collect {|c| c.full_name } h[:requires] = cls.deps(:requires).collect {|c| c.full_name } h[:uses] = cls.deps(:uses).collect {|c| c.full_name } h end Loading
lib/jsduck/logger.rb +1 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,7 @@ module JsDuck @warning_docs = [ [:global, "Member doesn't belong to any class"], [:inheritdoc, "@inheritdoc referring to unknown class or member"], [:extend, "@extend or @mixin referring to unknown class"], [:extend, "@extend/mixin/requires/uses referring to unknown class"], [:link, "{@link} to unknown class or member"], [:link_ambiguous, "{@link} is ambiguous"], [:link_auto, "Auto-detected link to unknown class or member"], Loading
lib/jsduck/renderer.rb +13 −14 Original line number Diff line number Diff line Loading @@ -43,7 +43,8 @@ module JsDuck items = [ render_alternate_class_names, render_tree, render_dependencies(:allMixins, "Mixins"), render_dependencies(:mixins, "Mixins"), render_dependencies(:parentMixins, "Inherited mixins"), render_dependencies(:requires, "Requires"), render_dependencies(:subclasses, "Subclasses"), render_dependencies(:mixedInto, "Mixed into"), Loading @@ -69,7 +70,7 @@ module JsDuck return if !@cls[type] || @cls[type].length == 0 return [ "<h4>#{title}</h4>", @cls[type].sort.map {|name| "<div class='dependency'>#{render_link(name)}</div>" }, @cls[type].sort.map {|name| "<div class='dependency'>#{name.exists? ? render_link(name) : name}</div>" }, ] end Loading @@ -90,23 +91,21 @@ module JsDuck # We still create the tree, but without links in it. def render_tree return if !@cls[:extends] || @cls[:extends] == "Object" tree = ["<h4>Hierarchy</h4>"] if @cls[:superclasses].length > 0 tree + render_class_tree(@cls[:superclasses].concat([@cls[:name]]), {:first => true, :links => true}) else tree + render_class_tree([@cls[:extends], @cls[:name]], {:first => true}) end return [ "<h4>Hierarchy</h4>", render_class_tree(@cls[:superclasses] + [@cls[:name]]) ] end def render_class_tree(superclasses, o) return "" if superclasses.length == 0 def render_class_tree(classes, i=0) return "" if classes.length <= i name = superclasses[0] name = classes[i] return [ "<div class='subclass #{o[:first] ? 'first-child' : ''}'>", superclasses.length > 1 ? (o[:links] ? render_link(name) : name) : "<strong>#{name}</strong>", render_class_tree(superclasses.slice(1, superclasses.length-1), {:links => o[:links]}), "<div class='subclass #{i == 0 ? 'first-child' : ''}'>", classes.length-1 == i ? "<strong>#{name}</strong>" : (name.exists? ? render_link(name) : name), render_class_tree(classes, i+1), "</div>", ] end Loading