Loading lib/jsduck/class.rb +69 −0 Original line number Diff line number Diff line Loading @@ -276,6 +276,75 @@ module JsDuck @members_map = nil end # Generates local members hash by ID def new_local_members_hash unless @map_by_id @map_by_id = {} @doc[:members].each do |m| @map_by_id[m[:id]] = m end end @map_by_id end # Generates global members hash by ID def new_global_members_hash unless @global_map_by_id @global_map_by_id = parent ? parent.new_global_members_hash : {} mixins.each do |mix| merge!(@global_map_by_id, mix.new_global_members_hash) end # Exclude all non-inheritable static members @global_map_by_id.delete_if {|id, m| m[:meta][:static] && !m[:inheritable] } merge!(@global_map_by_id, new_local_members_hash) end @global_map_by_id end # Generates global members hash by name def new_global_members_hash_by_name unless @global_map_by_name @global_map_by_name = {} new_global_members_hash.each_pair do |id, m| @global_map_by_name[m[:name]] = [] unless @global_map_by_name[m[:name]] @global_map_by_name[m[:name]] << m end end @global_map_by_name end # Searches members by name. Finds both local members and those # inherited from parents and mixins. # # Returns an array of members found or empty array def find_members(query={}) if query[:name] ms = new_global_members_hash_by_name[query[:name]] || [] else ms = new_global_members_hash.values end if query[:tagname] ms = ms.find_all {|m| m[:tagname] == query[:tagname] } end if query[:static] ms = ms.find_all {|m| m[:meta] && m[:meta][:static] } end ms end # Returns all members of class, including the inherited and mixed in ones def all_members all = [] Loading spec/class_spec.rb +162 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,168 @@ require "jsduck/class" describe JsDuck::Class do def make_class(cfg) cfg[:members].each do |m| m[:tagname] = :property unless m[:tagname] m[:owner] = cfg[:name] m[:id] = (m[:static] ? "static-" : "") + (m[:tagname] ? "#{m[:tagname]}-" : "property-") + m[:name] m[:meta] = {} unless m[:meta] m[:meta][:static] = true if m[:static] end JsDuck::Class.new(cfg) end describe "#find_members" do let (:cls) do classes = {} parent = make_class({ :name => "ParentClass", :members => [ {:name => "inParent"}, {:name => "alsoInParent"}, ] }); classes["ParentClass"] = parent parent.relations = classes parent = make_class({ :name => "MixinClass", :members => [ {:name => "inMixin"}, {:name => "alsoInMixin"}, ] }); classes["MixinClass"] = parent parent.relations = classes child = make_class({ :name => "ChildClass", :extends => "ParentClass", :mixins => ["MixinClass"], :members => [ {:name => "inChild", :tagname => :method}, {:name => "alsoInParent"}, {:name => "alsoInMixin"}, {:name => "childEvent", :tagname => :event}, ] }); classes["ChildClass"] = child child.relations = classes child end it "finds all members when called without arguments" do cls.find_members().length.should == 6 end it "finds all properties by specifying tagname" do cls.find_members(:tagname => :property).length.should == 4 end it "finds all methods by specifying tagname" do cls.find_members(:tagname => :method).length.should == 1 end it "finds no members when specifying non-existing tagname" do cls.find_members(:tagname => :cfg).length.should == 0 end it "finds no statics when there are no static members" do cls.find_members(:static => true).length.should == 0 end it "finds member in itself" do cls.find_members(:name => "inChild").length.should == 1 end it "finds member in parent" do cls.find_members(:name => "inParent").length.should == 1 end it "finds member in mixin" do cls.find_members(:name => "inMixin").length.should == 1 end it "finds overridden parent member" do cls.find_members(:name => "alsoInParent")[0][:owner].should == "ChildClass" end it "finds overridden mixin member" do cls.find_members(:name => "alsoInMixin")[0][:owner].should == "ChildClass" end end describe "#find_members with statics" do let (:cls) do classes = {} parent = make_class({ :name => "ParentClass", :members => [ {:name => "inParent", :static => true}, {:name => "inParentInheritable", :static => true, :inheritable => true}, ] }); classes["ParentClass"] = parent parent.relations = classes parent = make_class({ :name => "MixinClass", :members => [ {:name => "inMixin", :static => true}, {:name => "inMixinInheritable", :static => true, :inheritable => true}, ] }); classes["MixinClass"] = parent parent.relations = classes child = make_class({ :name => "ChildClass", :extends => "ParentClass", :mixins => ["MixinClass"], :members => [ {:name => "inChild", :static => true}, {:name => "inChildInheritable", :static => true, :inheritable => true}, ] }); classes["ChildClass"] = child child.relations = classes child end it "finds the static member in child" do cls.find_members(:name => "inChild", :static => true).length.should == 1 end it "finds the static inheritable member in child" do cls.find_members(:name => "inChildInheritable", :static => true).length.should == 1 end it "doesn't find the normal parent static member" do cls.find_members(:name => "inParent", :static => true).length.should == 0 end it "finds the inheritable parent static member" do cls.find_members(:name => "inParentInheritable", :static => true).length.should == 1 end it "doesn't find the normal parent mixin member" do cls.find_members(:name => "inMixin", :static => true).length.should == 0 end it "finds the inheritable mixin static member" do cls.find_members(:name => "inMixinInheritable", :static => true).length.should == 1 end it "finds all static members" do cls.find_members(:static => true).length.should == 4 end end describe "#members" do before do Loading Loading
lib/jsduck/class.rb +69 −0 Original line number Diff line number Diff line Loading @@ -276,6 +276,75 @@ module JsDuck @members_map = nil end # Generates local members hash by ID def new_local_members_hash unless @map_by_id @map_by_id = {} @doc[:members].each do |m| @map_by_id[m[:id]] = m end end @map_by_id end # Generates global members hash by ID def new_global_members_hash unless @global_map_by_id @global_map_by_id = parent ? parent.new_global_members_hash : {} mixins.each do |mix| merge!(@global_map_by_id, mix.new_global_members_hash) end # Exclude all non-inheritable static members @global_map_by_id.delete_if {|id, m| m[:meta][:static] && !m[:inheritable] } merge!(@global_map_by_id, new_local_members_hash) end @global_map_by_id end # Generates global members hash by name def new_global_members_hash_by_name unless @global_map_by_name @global_map_by_name = {} new_global_members_hash.each_pair do |id, m| @global_map_by_name[m[:name]] = [] unless @global_map_by_name[m[:name]] @global_map_by_name[m[:name]] << m end end @global_map_by_name end # Searches members by name. Finds both local members and those # inherited from parents and mixins. # # Returns an array of members found or empty array def find_members(query={}) if query[:name] ms = new_global_members_hash_by_name[query[:name]] || [] else ms = new_global_members_hash.values end if query[:tagname] ms = ms.find_all {|m| m[:tagname] == query[:tagname] } end if query[:static] ms = ms.find_all {|m| m[:meta] && m[:meta][:static] } end ms end # Returns all members of class, including the inherited and mixed in ones def all_members all = [] Loading
spec/class_spec.rb +162 −0 Original line number Diff line number Diff line Loading @@ -2,6 +2,168 @@ require "jsduck/class" describe JsDuck::Class do def make_class(cfg) cfg[:members].each do |m| m[:tagname] = :property unless m[:tagname] m[:owner] = cfg[:name] m[:id] = (m[:static] ? "static-" : "") + (m[:tagname] ? "#{m[:tagname]}-" : "property-") + m[:name] m[:meta] = {} unless m[:meta] m[:meta][:static] = true if m[:static] end JsDuck::Class.new(cfg) end describe "#find_members" do let (:cls) do classes = {} parent = make_class({ :name => "ParentClass", :members => [ {:name => "inParent"}, {:name => "alsoInParent"}, ] }); classes["ParentClass"] = parent parent.relations = classes parent = make_class({ :name => "MixinClass", :members => [ {:name => "inMixin"}, {:name => "alsoInMixin"}, ] }); classes["MixinClass"] = parent parent.relations = classes child = make_class({ :name => "ChildClass", :extends => "ParentClass", :mixins => ["MixinClass"], :members => [ {:name => "inChild", :tagname => :method}, {:name => "alsoInParent"}, {:name => "alsoInMixin"}, {:name => "childEvent", :tagname => :event}, ] }); classes["ChildClass"] = child child.relations = classes child end it "finds all members when called without arguments" do cls.find_members().length.should == 6 end it "finds all properties by specifying tagname" do cls.find_members(:tagname => :property).length.should == 4 end it "finds all methods by specifying tagname" do cls.find_members(:tagname => :method).length.should == 1 end it "finds no members when specifying non-existing tagname" do cls.find_members(:tagname => :cfg).length.should == 0 end it "finds no statics when there are no static members" do cls.find_members(:static => true).length.should == 0 end it "finds member in itself" do cls.find_members(:name => "inChild").length.should == 1 end it "finds member in parent" do cls.find_members(:name => "inParent").length.should == 1 end it "finds member in mixin" do cls.find_members(:name => "inMixin").length.should == 1 end it "finds overridden parent member" do cls.find_members(:name => "alsoInParent")[0][:owner].should == "ChildClass" end it "finds overridden mixin member" do cls.find_members(:name => "alsoInMixin")[0][:owner].should == "ChildClass" end end describe "#find_members with statics" do let (:cls) do classes = {} parent = make_class({ :name => "ParentClass", :members => [ {:name => "inParent", :static => true}, {:name => "inParentInheritable", :static => true, :inheritable => true}, ] }); classes["ParentClass"] = parent parent.relations = classes parent = make_class({ :name => "MixinClass", :members => [ {:name => "inMixin", :static => true}, {:name => "inMixinInheritable", :static => true, :inheritable => true}, ] }); classes["MixinClass"] = parent parent.relations = classes child = make_class({ :name => "ChildClass", :extends => "ParentClass", :mixins => ["MixinClass"], :members => [ {:name => "inChild", :static => true}, {:name => "inChildInheritable", :static => true, :inheritable => true}, ] }); classes["ChildClass"] = child child.relations = classes child end it "finds the static member in child" do cls.find_members(:name => "inChild", :static => true).length.should == 1 end it "finds the static inheritable member in child" do cls.find_members(:name => "inChildInheritable", :static => true).length.should == 1 end it "doesn't find the normal parent static member" do cls.find_members(:name => "inParent", :static => true).length.should == 0 end it "finds the inheritable parent static member" do cls.find_members(:name => "inParentInheritable", :static => true).length.should == 1 end it "doesn't find the normal parent mixin member" do cls.find_members(:name => "inMixin", :static => true).length.should == 0 end it "finds the inheritable mixin static member" do cls.find_members(:name => "inMixinInheritable", :static => true).length.should == 1 end it "finds all static members" do cls.find_members(:static => true).length.should == 4 end end describe "#members" do before do Loading