Skip to content

Commit

Permalink
Merge branch 'since-params'
Browse files Browse the repository at this point in the history
  • Loading branch information
nene committed Oct 28, 2013
2 parents 16a77bc + 657541e commit 3916999
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 59 deletions.
21 changes: 17 additions & 4 deletions lib/jsduck/news.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,11 @@ def filter_new_items(relations)
new_items
end

# Returns all members of a class that have been marked as new, or
# have parameters marked as new.
def filter_new_members(cls)
members = []
cls.all_local_members.each do |m|
members << m if m[:new] && visible?(m)
members = cls.all_local_members.find_all do |m|
visible?(m) && (m[:new] || new_params?(m))
end
members = discard_accessors(members)
members.sort! {|a, b| a[:name] <=> b[:name] }
Expand All @@ -76,6 +77,10 @@ def visible?(member)
!member[:private] && !member[:hide]
end

def new_params?(member)
Array(member[:params]).any? {|p| p[:new] }
end

def discard_accessors(members)
accessors = {}
members.find_all {|m| m[:accessor] }.each do |cfg|
Expand Down Expand Up @@ -127,7 +132,15 @@ def link(m)
if m[:tagname] == :class
@doc_formatter.link(m[:name], nil, m[:name])
else
@doc_formatter.link(m[:owner], m[:name], m[:name], m[:tagname], m[:static])
@doc_formatter.link(m[:owner], m[:name], m[:name], m[:tagname], m[:static]) + params_note(m)
end
end

def params_note(m)
if !m[:new] && new_params?(m)
" <small>+parameters</small>"
else
""
end
end

Expand Down
3 changes: 3 additions & 0 deletions lib/jsduck/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,9 @@ def parse!(argv)
# definitions multiple times.
TagRegistry.instance
end

# The tooltip of @new can now be configured.
TagRegistry.get_by_name(:new).init_tooltip!(self)
end

private
Expand Down
7 changes: 5 additions & 2 deletions lib/jsduck/process/importer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ def import(versions)
private

def current_version
Util::NullObject.new(:[] => Util::NullObject.new(:[] => true))
JsDuck::Util::NullObject.new(
:[] => JsDuck::Util::NullObject.new( # class
:[] => JsDuck::Util::NullObject.new( # member
:length => 1.0 / 0))) # params count == Infinity
end

# Reads in data from all .json files in directory
Expand Down Expand Up @@ -61,7 +64,7 @@ def correct_format?(json)
def members_id_index(json)
index = {}
json["members"].each do |m|
index[m["id"]] = true
index[m["id"]] = m["params"] ? m["params"].map {|p| p["name"] } : true
end
index
end
Expand Down
134 changes: 84 additions & 50 deletions lib/jsduck/process/versions.rb
Original file line number Diff line number Diff line change
@@ -1,82 +1,70 @@
require 'jsduck/process/importer'
require 'jsduck/tag_registry'

module JsDuck
module Process

# Generates @since and @new tags by importing JSDuck exports of
# older versions of the same project and looking in which version
# a class or method first appeared.
#
# Additionally here the tooltip text for @new tag gets injected.
class Versions
def initialize(relations, opts={}, importer=nil)
def initialize(relations, opts={}, importer=Process::Importer.new)
@relations = relations
@opts = opts
# Allow different importer to be injected for testing
@importer = importer || Process::Importer.new
@importer = importer
end

# Loads in exported docs and generates @since and @new tags.
def process_all!
init_new_tag_tooltip!

if @opts[:imports].length > 0
generate_since_tags(@importer.import(@opts[:imports]))
@versions = @importer.import(@opts[:imports])
add_since_tags
end
end

private

# Initializes the tooltip text for the signature of @new tag.
def init_new_tag_tooltip!
signature = TagRegistry.get_by_name(:new).signature
if @opts[:new_since]
signature[:tooltip] = "New since #{@opts[:new_since]}"
elsif @opts[:imports].length > 0
signature[:tooltip] = "New since #{@opts[:imports].last[:version]}"
end
end
# classes...

# Using the imported versions data, adds @since tags to all
# classes/members.
def generate_since_tags(versions)
new_versions = build_new_versions_map(versions)

# classes/members/params.
def add_since_tags
@relations.each do |cls|
v = cls[:since] || class_since(versions, cls)
v = cls[:since] || class_since(cls)
cls[:since] = v
cls[:new] = true if new_versions[v]
cls[:new] = true if is_new?(v)

cls.all_local_members.each do |m|
v = m[:since] || member_since(versions, cls, m)
m[:since] = v
m[:new] = true if new_versions[v]
end
add_members_since_tags(cls)
end
end

# Generates a lookup table of versions that we are going to label
# with @new tags. By default we use the latest version, otherwise
# use all versions since the latest.
def build_new_versions_map(versions)
new_versions = {}

if @opts[:new_since]
versions.map {|v| v[:version] }.each do |v|
if v == @opts[:new_since] || !new_versions.empty?
new_versions[v] = true
end
# Returns name of the version since which the class is available
def class_since(cls)
@versions.each do |ver|
return ver[:version] if ver[:classes][cls[:name]]
cls[:alternateClassNames].each do |name|
return ver[:version] if ver[:classes][name]
end
else
new_versions[versions.last[:version]] = true
end
end

new_versions
# members...

def add_members_since_tags(cls)
cls.all_local_members.each do |m|
# Remember the initial explicit @since tag value
# to disable params processing when it's present.
explicit_since = m[:since]

v = m[:since] || member_since(cls, m)
m[:since] = v
m[:new] = true if is_new?(v)

add_params_since_tags(cls, m, v) unless explicit_since
end
end

def member_since(versions, cls, m)
versions.each do |ver|
def member_since(cls, m)
@versions.each do |ver|
c = ver[:classes][cls[:name]]
return ver[:version] if c && c[m[:id]]
cls[:alternateClassNames].each do |name|
Expand All @@ -86,14 +74,60 @@ def member_since(versions, cls, m)
end
end

# Returns name of the version since which the class is available
def class_since(versions, cls)
versions.each do |ver|
return ver[:version] if ver[:classes][cls[:name]]
# params...

def add_params_since_tags(cls, member, member_version)
Array(member[:params]).each_with_index do |p, i|
v = param_since(cls, member, i)
if v != member_version
p[:since] = v
p[:new] = true if is_new?(v)
end
end
end

def param_since(cls, m, i)
@versions.each do |ver|
c = ver[:classes][cls[:name]]
return ver[:version] if c && has_param?(c[m[:id]], i)
cls[:alternateClassNames].each do |name|
return ver[:version] if ver[:classes][name]
c = ver[:classes][name]
return ver[:version] if c && has_param?(c[m[:id]], i)
end
end
end

# Because parameters can be renamed between versions, only
# consider parameter count.
def has_param?(member, param_index)
member && member.respond_to?(:length) && member.length > param_index
end

# helpers...

# Should items introduced in given version be marked as new?
def is_new?(version_nr)
@new_versions = new_versions_map unless @new_versions
@new_versions[version_nr]
end

# Generates a lookup table of versions that we are going to label
# with @new tags. By default we use the latest version, otherwise
# use all versions since the latest.
def new_versions_map
new_versions = {}

if @opts[:new_since]
@versions.map {|v| v[:version] }.each do |v|
if v == @opts[:new_since] || !new_versions.empty?
new_versions[v] = true
end
end
else
new_versions[@versions.last[:version]] = true
end

new_versions
end

end
Expand Down
18 changes: 18 additions & 0 deletions lib/jsduck/render/subproperties.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'jsduck/util/html'
require 'jsduck/util/singleton'
require 'jsduck/tag_registry'

module JsDuck
module Render
Expand Down Expand Up @@ -54,15 +55,32 @@ def render_single_param(p)
"<span class='pre'>#{p[:name]}</span> : ",
p[:html_type],
p[:optional] ? " (optional)" : "",
p[:new] ? render_new : "",
"<div class='sub-desc'>",
p[:doc],
p[:default] ? "<p>Defaults to: <code>#{Util::HTML.escape(p[:default])}</code></p>" : "",
p[:since] ? render_since(p) : "",
p[:properties] && p[:properties].length > 0 ? render(p) : "",
"</div>",
"</li>",
]
end

def render_new
signature = TagRegistry.get_by_name(:new).signature
return [
"<span class='signature'>",
"<span class='new' title='#{signature[:tooltip]}'>",
signature[:long],
"</span>",
"</span>",
]
end

def render_since(param)
TagRegistry.get_by_name(:since).to_html(param)
end

def render_return(ret)
return [
"<h3 class='pa'>Returns</h3>",
Expand Down
13 changes: 13 additions & 0 deletions lib/jsduck/tag/new.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,18 @@ def initialize
EOCSS
super
end

# Initializes the tooltip text based on the --new-since and
# --import options passed from command line.
#
# NOTE: This method is explicitly called from JsDuck::Options class.
def init_tooltip!(opts)
if opts[:new_since]
@signature[:tooltip] = "New since #{opts[:new_since]}"
elsif opts[:imports].length > 0
@signature[:tooltip] = "New since #{opts[:imports].last[:version]}"
end
end

end
end
4 changes: 2 additions & 2 deletions lib/jsduck/tag/since.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require "jsduck/tag/tag"
require "jsduck/logger"
require 'jsduck/util/html'

module JsDuck::Tag
class Since < Tag
Expand All @@ -22,7 +22,7 @@ def process_doc(h, tags, pos)

def to_html(context)
<<-EOHTML
<p>Available since: <b>#{context[:since]}</b></p>
<p>Available since: <b>#{JsDuck::Util::HTML.escape(context[:since])}</b></p>
EOHTML
end

Expand Down
4 changes: 4 additions & 0 deletions lib/jsduck/util/null_object.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ def initialize(methods={})
def method_missing(meth, *args, &block)
@methods.has_key?(meth) ? @methods[meth] : self
end

def respond_to?(meth)
@methods.has_key?(meth)
end
end

end
Expand Down
Loading

0 comments on commit 3916999

Please sign in to comment.