Commit 9c204761 authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

New JsDuck::Class#find_members method.

parent dbce16de
Loading
Loading
Loading
Loading
+69 −0
Original line number Diff line number Diff line
@@ -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 = []
+162 −0
Original line number Diff line number Diff line
@@ -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