Commit 8c986c7c authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Auto-generate enum values from aliases.

So one can declare:

    @enum [xtypes=widget.*]

and it will be automatically populated with all available widget types.
parent ed17942c
Loading
Loading
Loading
Loading
+1 −5
Original line number Diff line number Diff line
@@ -231,11 +231,7 @@ module JsDuck

    # Loops through all enums and auto-detects their types if needed.
    def process_enums
      @classes.each_value do |cls|
        if cls[:enum]
          Enum.process(cls)
        end
      end
      Enum.new(@classes).process_all!
    end

    # Are we dealing with ExtJS 4?
+2 −1
Original line number Diff line number Diff line
@@ -281,7 +281,8 @@ module JsDuck
      return nil unless extract(doc_map, :class, :enum)

      return {
        :type => extract(doc_map, :class, :type)
        :type => extract(doc_map, :class, :type),
        :default => extract(doc_map, :class, :default),
      }
    end

+49 −6
Original line number Diff line number Diff line
@@ -3,16 +3,30 @@ require 'jsduck/logger'
module JsDuck

  class Enum
    # Applies additional processing to enum-class.
    def self.process(cls)
      cls[:enum][:type] = self.infer_type(cls) unless cls[:enum][:type]
      self.unsure_public(cls)
    def initialize(classes)
      @classes = classes
    end

    # Applies additional processing to all enum-classes.
    def process_all!
      @classes.each_value do |cls|
        if cls[:enum]
          process(cls)
        end
      end
    end

    private

    # processes single class
    def process(cls)
      cls[:enum][:type] = infer_type(cls) unless cls[:enum][:type]
      expand_default(cls)
      unsure_public(cls)
    end

    # Given an enum class, returns the type infered from its values.
    def self.infer_type(cls)
    def infer_type(cls)
      if cls[:members][:property].length > 0
        types = cls[:members][:property].map {|p| p[:type] }
        types.sort.uniq.join("/")
@@ -24,9 +38,38 @@ module JsDuck
      end
    end

    # Expands default value like widget.* into list of properties
    def expand_default(cls)
      if cls[:enum][:default] =~ /\A(.*)\.\*\Z/
        gather_aliases($1).each do |name|
          cls[:members][:property] << {
            :tagname => :property,
            :id => 'property-' + name,
            :name => name,
            :default => "'" + name + "'",
            :type => "String",
            :meta => {},
            :files => cls[:files],
            :owner => cls[:name],
            :doc => "",
          }
        end
      end
    end

    def gather_aliases(prefix)
      result = []
      @classes.each_value do |cls|
        if cls[:aliases] && cls[:aliases][prefix]
          result += cls[:aliases][prefix]
        end
      end
      result
    end

    # Ensures that enum values are all public.
    # For this we remove the auto-inserted inheritdoc tag.
    def self.unsure_public(cls)
    def unsure_public(cls)
      cls[:members][:property].each do |p|
        p[:inheritdoc] = nil if p[:autodetected]
      end
+27 −0
Original line number Diff line number Diff line
@@ -174,4 +174,31 @@ describe JsDuck::Aggregator do
    end
  end

  describe "enum of widget.*" do
    let(:props) do
      parse(<<-EOS)[0][:members][:property]
        /** @enum [xtype=widget.*] */
        /** @class Form @alias widget.form */
        /** @class Button @alias widget.button */
        /** @class TextArea @alias widget.textarea */
      EOS
    end

    it "gathers all 3 widget.* aliases" do
      props.length.should == 3
    end

    it "lists all widget.* names" do
      Set.new(props.map {|p| p[:name] }).should == Set.new(["form", "button", "textarea"])
    end

    it "auto-generates property default values" do
      Set.new(props.map {|p| p[:default] }).should == Set.new(["'form'", "'button'", "'textarea'"])
    end

    it "sets property type to String" do
      props[0][:type].should == "String"
    end
  end

end