Commit e51e5dd8 authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Actual working detection of config: {} section.

Added Ast#detect_all! which performs detection on all docsets.
parent 8b806419
Loading
Loading
Loading
Loading
+51 −5
Original line number Diff line number Diff line
@@ -5,15 +5,43 @@ module JsDuck

  # Analyzes the AST produced by EsprimaParser.
  class Ast
    def initialize
    # Should be initialized with EsprimaParser#parse result.
    def initialize(docs = [])
      @serializer = JsDuck::Serializer.new
      @evaluator = JsDuck::Evaluator.new
      @docs = docs
    end

    # Given parsed code, returns the tagname for documentation item.
    # Performs the detection of code in all docsets.
    #
    # @returns the processes array of docsets. (But it does it
    # destructively by modifying the passed-in docsets.)
    #
    def detect_all!
      # For now only deal with doc-comments
      @docs = @docs.find_all {|d| d[:type] == :doc_comment }

      # Detect code in each docset.  Sometimes a docset has already
      # been as part of detecting some previous docset (like Class
      # detecting all of its configs) - in such case, skip.
      @docs.each do |docset|
        code = docset[:code]
        docset[:code] = detect(code) unless code && code[:tagname]
      end

      @docs
    end

    # Given Esprima-produced syntax tree, detects documentation data.
    #
    # This method is exposed for testing purposes only, JSDuck itself
    # only calls the above #detect_all method.
    #
    # @param ast :code from Result of EsprimaParser
    # @returns One of: :class, :method, :property
    # @returns Hash consisting of the detected :tagname, :name, and
    # other properties relative to the tag.  Like so:
    #
    #     { :tagname => :method, :name => "foo", ... }
    #
    def detect(ast)
      ast = ast || {}
@@ -208,12 +236,30 @@ module JsDuck
      return nil unless ast && ast["type"] == "ObjectExpression"

      configs = []
      object_expression_to_hash(ast).each_pair do |key, value|
        configs << make_property(key, value, :cfg)

      ast["properties"].each do |p|
        cfg = make_property(key_value(p["key"]), p["value"], :cfg)
        # When config has a comment, update the related docset,
        # otherwise add it as new config to current class.
        docset = find_docset(p)
        if docset
          docset[:code] = cfg
        else
          configs << cfg
        end
      end

      configs
    end

    # Looks up docset associated with given AST node.
    # A dead-stupid and -slow implementation, but works.
    def find_docset(ast)
      @docs.find do |docset|
        docset[:code] == ast
      end
    end

    def make_method(name, ast=nil)
      return {
        :tagname => :method,
+1 −3
Original line number Diff line number Diff line
@@ -31,10 +31,8 @@ module JsDuck
        :css_mixin
      elsif doc_map[:cfg]
        :cfg
      elsif code[:tagname] == :method
        :method
      else
        :property
        code[:tagname]
      end
    end

+5 −0
Original line number Diff line number Diff line
@@ -45,6 +45,11 @@ module JsDuck
      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

+1 −6
Original line number Diff line number Diff line
@@ -23,7 +23,6 @@ module JsDuck
      @options = options
      @html_filename = ""
      @links = {}
      @ast = Ast.new

      doc_parser = DocParser.new

@@ -92,11 +91,7 @@ module JsDuck
          CssParser.new(@contents, @options).parse
        else
          docs = EsprimaParser.new(@contents, @options).parse
          docs = docs.find_all {|d| d[:type] == :doc_comment }
          docs.each do |docset|
            docset[:code] = @ast.detect(docset[:code])
          end
          docs
          Ast.new(docs).detect_all!
        end
      rescue
        puts "Error while parsing #{@filename}: #{$!}"
+68 −0
Original line number Diff line number Diff line
require "jsduck/aggregator"
require "jsduck/source_file"

describe JsDuck::Aggregator do

  def parse(string)
    agr = JsDuck::Aggregator.new
    agr.aggregate(JsDuck::SourceFile.new(string))
    agr.result
  end

  describe "detecting Ext.define() with configs in code" do
    let(:cfg) do
      parse(<<-EOS)[0][:members][:cfg]
        /**
         * Some documentation.
         */
        Ext.define("MyClass", {
            config: {
                foo: 42,
                bar: "hello"
            }
        });
      EOS
    end

    it "finds configs" do
      cfg.should be_kind_of(Array)
    end

    it "finds two configs" do
      cfg.length.should == 2
    end
  end

  describe "detecting Ext.define() with commented config" do
    let(:docs) do
      parse(<<-EOS)
        /**
         * Some documentation.
         */
        Ext.define("MyClass", {
            config: {
                /** Docs for bar */
                bar: "hello"
            }
        });
      EOS
    end

    it "finds one docset" do
      docs.length.should == 1
    end

    it "detects it as class" do
      docs[0][:tagname] == :class
    end

    it "detects one config within class" do
      docs[0][:members][:cfg].length.should == 1
    end

    it "detects the config with docs" do
      docs[0][:members][:cfg][0][:doc].should == "Docs for bar"
    end
  end

end