Commit 15bb57f3 authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Restructure docset merging.

Merger#merge now takes the full docset as single parameter.  But the
docsets get pre-processed in SourceFile where the tagname of each of
them gets detected and each class-docset gets expanded into multiple
ones (either because the doc-comment contained configs/constructor, or
because class members were auto-detected from code).

Therefore the merger is now much simpler, having not to deal with the
complexities of @class docset.
parent 2285d897
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -233,7 +233,7 @@ module JsDuck
    end

    def make_configs(ast)
      return nil unless ast && ast["type"] == "ObjectExpression"
      return [] unless ast && ast["type"] == "ObjectExpression"

      configs = []

+49 −3
Original line number Diff line number Diff line
@@ -4,6 +4,9 @@ module JsDuck
  # doc-comment.
  class ClassDocGrouper

    # Takes one docset as input, produces array of one or more docsets
    # as output.
    #
    # Gathers all tags until first @cfg or @constructor into the first
    # bare :class group.  We have a special case for @xtype which in
    # ExtJS comments often appears after @constructor - so we
@@ -14,7 +17,7 @@ module JsDuck
    # configs to be marked with @private or whatever else.
    #
    # Finally gathers tags after @constructor into its group.
    def self.group(docs)
    def self.group(docset)
      groups = {
        :class => [],
        :cfg => [],
@@ -24,7 +27,7 @@ module JsDuck
      # By default everything goes to :class group
      group_name = :class

      docs.each do |tag|
      docset[:comment].each do |tag|
        tagname = tag[:tagname]

        if tagname == :cfg || tagname == :constructor
@@ -44,7 +47,50 @@ module JsDuck
        end
      end

      groups
      # Turn groups hash into list of docsets
      results = []
      results << {
        :tagname => :class,
        :type => docset[:type],
        :comment => groups[:class],
        :code => docset[:code],
        :linenr => docset[:linenr],
      }
      groups[:cfg].each do |cfg|
        results << {
          :tagname => :cfg,
          :type => docset[:type],
          :comment => cfg,
          :code => {},
          :linenr => docset[:linenr],
        }
      end
      if groups[:constructor].length > 0
        results << {
          :tagname => :method,
          :type => docset[:type],
          :comment => groups[:constructor],
          :code => {},
          :linenr => docset[:linenr],
        }
      end

      # Turn all auto-detected members into separate docsets
      if docset[:code] && docset[:code][:members]
        docset[:code][:members].each_pair do |type, members|
          members.each do |m|
            results << {
              :tagname => m[:tagname],
              :type => :no_comment,
              :comment => [],
              :code => m,
              :linenr => docset[:linenr],
            }
          end
        end
      end

      results
    end

  end
+7 −28
Original line number Diff line number Diff line
require 'jsduck/logger'
require 'jsduck/meta_tag_registry'
require 'jsduck/doc_type'
require 'jsduck/class_doc_grouper'

module JsDuck
@@ -19,11 +18,13 @@ module JsDuck
      @filename = ""
      @linenr = 0
      @meta_tags = MetaTagRegistry.instance
      @doc_type = DocType.new
    end

    def merge(docs, code)
      case @doc_type.detect(docs, code)
    def merge(docset)
      docs = docset[:comment]
      code = docset[:code]

      case docset[:tagname]
      when :class
        create_class(docs, code)
      when :event
@@ -42,19 +43,6 @@ module JsDuck
    end

    def create_class(docs, code)
      groups = ClassDocGrouper.group(docs)
      result = create_bare_class(groups[:class], code)
      result[:members] = create_class_members(groups, result[:name])
      result[:statics] = Class.default_members_hash
      if code[:members] && code[:members][:cfg]
        code[:members][:cfg].each do |cfg|
          result[:members][:cfg] << create_cfg({}, cfg, result[:name])
        end
      end
      result
    end

    def create_bare_class(docs, code)
      doc_map = build_doc_map(docs)
      return add_shared({
        :tagname => :class,
@@ -69,20 +57,11 @@ module JsDuck
        :uses => detect_list(:uses, doc_map, code),
        # Used by Aggregator to determine if we're dealing with Ext4 code
        :code_type => code[:tagname],
        :members => Class.default_members_hash,
        :statics => Class.default_members_hash,
      }, doc_map)
    end

    def create_class_members(groups, owner)
      members = Class.default_members_hash
      members[:cfg] = groups[:cfg].map { |tags| create_cfg(tags, {}, owner) }
      if groups[:constructor].length > 0
        constr = create_method(groups[:constructor], {})
        constr[:owner] = owner
        members[:method] << constr
      end
      members
    end

    def create_method(docs, code)
      doc_map = build_doc_map(docs)
      name = detect_name(:method, doc_map, code)
+18 −6
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ require 'jsduck/css_parser'
require 'jsduck/doc_parser'
require 'jsduck/merger'
require 'jsduck/ast'
require 'jsduck/doc_type'
require "cgi"

module JsDuck
@@ -23,16 +24,15 @@ module JsDuck
      @options = options
      @html_filename = ""
      @links = {}

      doc_parser = DocParser.new
      @doc_type = DocType.new
      @doc_parser = DocParser.new

      merger = Merger.new
      merger.filename = @filename

      @docs = parse.map do |docset|
        merger.linenr = docset[:linenr]
        docset[:comment] = doc_parser.parse(docset[:comment])
        link(docset[:linenr], merger.merge(docset[:comment], docset[:code]))
        link(docset[:linenr], merger.merge(docset))
      end
    end

@@ -88,11 +88,23 @@ module JsDuck
    def parse
      begin
        if @filename =~ /\.s?css$/
          CssParser.new(@contents, @options).parse
          docs = CssParser.new(@contents, @options).parse
        else
          docs = EsprimaParser.new(@contents, @options).parse
          Ast.new(docs).detect_all!
          docs = Ast.new(docs).detect_all!
        end

        docs.map do |docset|
          docset[:comment] = @doc_parser.parse(docset[:comment])
          docset[:tagname] = @doc_type.detect(docset[:comment], docset[:code])

          if docset[:tagname] == :class
            ClassDocGrouper.group(docset)
          else
            docset
          end
        end.flatten

      rescue
        puts "Error while parsing #{@filename}: #{$!}"
        puts
+14 −10
Original line number Diff line number Diff line
@@ -2,17 +2,19 @@ require "jsduck/merger"

describe JsDuck::Merger do

  def merge(doc, code)
    return JsDuck::Merger.new.merge(doc, code)
  def merge(docset)
    return JsDuck::Merger.new.merge(docset)
  end

  describe "only name in code" do
    before do
      @doc = merge(
        [{:tagname => :cfg, :type => "String", :doc => "My Config"}],
        {
      @doc = merge({
        :tagname => :cfg,
        :comment => [{:tagname => :cfg, :type => "String", :doc => "My Config"}],
        :code => {
          :tagname => :property,
          :name => "option",
        }
      })
    end

@@ -32,12 +34,14 @@ describe JsDuck::Merger do

  describe "most stuff in code" do
    before do
      @doc = merge(
        [{:tagname => :default, :doc => "Hello world"}],
        {
      @doc = merge({
        :tagname => :property,
        :comment => [{:tagname => :default, :doc => "Hello world"}],
        :code => {
          :tagname => :property,
          :name => "some.prop",
          :type => "Boolean",
        }
      })
    end