Loading jsduck.rb +82 −23 Original line number Diff line number Diff line Loading @@ -94,16 +94,22 @@ module JsDuck class DocComment attr_accessor :function, :doc def initialize(input) @function = "" @doc = "" @params = [] @return = "void" @current_tag = {:doc => ""} @tags = {:default => @current_tag} parse(purify(input)) end # sets the name and properties of the default at-tag def set_default(tagname, attrs={}) @tags[tagname] = attrs @tags[tagname][:doc] = @tags[:default][:doc] end def [](tagname) @tags[tagname] end # Extracts content inside /** ... */ def purify(input) result = [] Loading @@ -121,25 +127,78 @@ module JsDuck end def parse(input) doc = [] input.each_line do |line| line.chomp! if line =~ /\A@param\b/ then @params << line elsif line =~ /\A@return\b/ then @return = line @input = StringScanner.new(input) while !@input.eos? do if look(/@return\b/) then at_return elsif look(/@param\b/) then at_param elsif look(/@/) then @current_tag[:doc] += @input.scan(/@/) elsif look(/[^@]/) then @current_tag[:doc] += @input.scan(/[^@]+/) end end end # matches @return {type} ... def at_return match(/@return/) @current_tag = @tags[:return] = {:doc => ""} skip_white if look(/\{/) then @current_tag[:type] = typedef end skip_white end # matches @param {type} variable ... def at_param match(/@param/) @current_tag = {:doc => ""} if @tags[:param] then @tags[:param] << @current_tag else doc << line @tags[:param] = [@current_tag] end skip_white if look(/\{/) then @current_tag[:type] = typedef end @doc = doc.join("\n") skip_white if look(/\w/) then @current_tag[:name] = ident end skip_white end # matches {...} and returns text inside brackets def typedef match(/\{/) name = @input.scan(/[^}]+/) match(/\}/) return name end # matches identifier and returns its name def ident @input.scan(/\w+/) end def look(re) @input.check(re) end def match(re) @input.scan(re) end def skip_white @input.scan(/\s+/) end def print puts "function: " + @function puts "doc: " + @doc puts "params: " + @params.join("\n") puts "return: " + @return pp @tags end end Loading @@ -153,16 +212,16 @@ module JsDuck if lex.look("function", :keyword) then lex.next # function name(){ doc.function = lex.next doc.set_default(:function, {:name => lex.next}) elsif lex.look("var", :keyword, "=", "function") then lex.next # var name = function(){ doc.function = lex.next doc.set_default(:function, {:name => lex.next}) elsif lex.look(:keyword, "=", "function") || lex.look(:keyword, ":", "function") || lex.look(:string, ":", "function") then # name: function(){ doc.function = lex.next doc.set_default(:function, {:name => lex.next}) end docs << doc else Loading tc_jsduck.rb +39 −7 Original line number Diff line number Diff line Loading @@ -15,6 +15,38 @@ class TestJsDuck < Test::Unit::TestCase assert_equal([], JsDuck.parse("/* ") ) end def test_return docs = JsDuck.parse(" /** * Some function * @return {String} some value * on several * lines */ ") assert_equal("String", docs[0][:return][:type]) assert_equal("some value\non several\nlines", docs[0][:return][:doc]) end def test_param docs = JsDuck.parse(" /** * Some function * @param {Number} x value 1 * @param {Float} y value 2 */ ") param1 = docs[0][:param][0] assert_equal("Number", param1[:type]) assert_equal("x", param1[:name]) assert_equal("value 1\n", param1[:doc]) param2 = docs[0][:param][1] assert_equal("Float", param2[:type]) assert_equal("y", param2[:name]) assert_equal("value 2", param2[:doc]) end def test_function docs = JsDuck.parse(" /** Loading @@ -23,8 +55,8 @@ class TestJsDuck < Test::Unit::TestCase function foo() { } ") assert_equal("Some function", docs[0].doc) assert_equal("foo", docs[0].function) assert_equal("Some function", docs[0][:function][:doc]) assert_equal("foo", docs[0][:function][:name]) end def test_function_with_var Loading @@ -34,7 +66,7 @@ function foo() { var foo = function() { } ") assert_equal("foo", docs[0].function) assert_equal("foo", docs[0][:function][:name]) end def test_function_without_var Loading @@ -44,7 +76,7 @@ var foo = function() { foo = function() { } ") assert_equal("foo", docs[0].function) assert_equal("foo", docs[0][:function][:name]) end def test_function_in_object_literal Loading @@ -54,7 +86,7 @@ foo = function() { foo: function() { } ") assert_equal("foo", docs[0].function) assert_equal("foo", docs[0][:function][:name]) end def test_function_in_object_literal_string Loading @@ -64,7 +96,7 @@ foo: function() { 'foo': function() { } ") assert_equal("foo", docs[0].function) assert_equal("foo", docs[0][:function][:name]) end def test_function_private Loading @@ -73,7 +105,7 @@ foo: function() { function foo() { } ") assert_equal(0, docs.length) assert_equal([], docs) end end Loading
jsduck.rb +82 −23 Original line number Diff line number Diff line Loading @@ -94,16 +94,22 @@ module JsDuck class DocComment attr_accessor :function, :doc def initialize(input) @function = "" @doc = "" @params = [] @return = "void" @current_tag = {:doc => ""} @tags = {:default => @current_tag} parse(purify(input)) end # sets the name and properties of the default at-tag def set_default(tagname, attrs={}) @tags[tagname] = attrs @tags[tagname][:doc] = @tags[:default][:doc] end def [](tagname) @tags[tagname] end # Extracts content inside /** ... */ def purify(input) result = [] Loading @@ -121,25 +127,78 @@ module JsDuck end def parse(input) doc = [] input.each_line do |line| line.chomp! if line =~ /\A@param\b/ then @params << line elsif line =~ /\A@return\b/ then @return = line @input = StringScanner.new(input) while !@input.eos? do if look(/@return\b/) then at_return elsif look(/@param\b/) then at_param elsif look(/@/) then @current_tag[:doc] += @input.scan(/@/) elsif look(/[^@]/) then @current_tag[:doc] += @input.scan(/[^@]+/) end end end # matches @return {type} ... def at_return match(/@return/) @current_tag = @tags[:return] = {:doc => ""} skip_white if look(/\{/) then @current_tag[:type] = typedef end skip_white end # matches @param {type} variable ... def at_param match(/@param/) @current_tag = {:doc => ""} if @tags[:param] then @tags[:param] << @current_tag else doc << line @tags[:param] = [@current_tag] end skip_white if look(/\{/) then @current_tag[:type] = typedef end @doc = doc.join("\n") skip_white if look(/\w/) then @current_tag[:name] = ident end skip_white end # matches {...} and returns text inside brackets def typedef match(/\{/) name = @input.scan(/[^}]+/) match(/\}/) return name end # matches identifier and returns its name def ident @input.scan(/\w+/) end def look(re) @input.check(re) end def match(re) @input.scan(re) end def skip_white @input.scan(/\s+/) end def print puts "function: " + @function puts "doc: " + @doc puts "params: " + @params.join("\n") puts "return: " + @return pp @tags end end Loading @@ -153,16 +212,16 @@ module JsDuck if lex.look("function", :keyword) then lex.next # function name(){ doc.function = lex.next doc.set_default(:function, {:name => lex.next}) elsif lex.look("var", :keyword, "=", "function") then lex.next # var name = function(){ doc.function = lex.next doc.set_default(:function, {:name => lex.next}) elsif lex.look(:keyword, "=", "function") || lex.look(:keyword, ":", "function") || lex.look(:string, ":", "function") then # name: function(){ doc.function = lex.next doc.set_default(:function, {:name => lex.next}) end docs << doc else Loading
tc_jsduck.rb +39 −7 Original line number Diff line number Diff line Loading @@ -15,6 +15,38 @@ class TestJsDuck < Test::Unit::TestCase assert_equal([], JsDuck.parse("/* ") ) end def test_return docs = JsDuck.parse(" /** * Some function * @return {String} some value * on several * lines */ ") assert_equal("String", docs[0][:return][:type]) assert_equal("some value\non several\nlines", docs[0][:return][:doc]) end def test_param docs = JsDuck.parse(" /** * Some function * @param {Number} x value 1 * @param {Float} y value 2 */ ") param1 = docs[0][:param][0] assert_equal("Number", param1[:type]) assert_equal("x", param1[:name]) assert_equal("value 1\n", param1[:doc]) param2 = docs[0][:param][1] assert_equal("Float", param2[:type]) assert_equal("y", param2[:name]) assert_equal("value 2", param2[:doc]) end def test_function docs = JsDuck.parse(" /** Loading @@ -23,8 +55,8 @@ class TestJsDuck < Test::Unit::TestCase function foo() { } ") assert_equal("Some function", docs[0].doc) assert_equal("foo", docs[0].function) assert_equal("Some function", docs[0][:function][:doc]) assert_equal("foo", docs[0][:function][:name]) end def test_function_with_var Loading @@ -34,7 +66,7 @@ function foo() { var foo = function() { } ") assert_equal("foo", docs[0].function) assert_equal("foo", docs[0][:function][:name]) end def test_function_without_var Loading @@ -44,7 +76,7 @@ var foo = function() { foo = function() { } ") assert_equal("foo", docs[0].function) assert_equal("foo", docs[0][:function][:name]) end def test_function_in_object_literal Loading @@ -54,7 +86,7 @@ foo = function() { foo: function() { } ") assert_equal("foo", docs[0].function) assert_equal("foo", docs[0][:function][:name]) end def test_function_in_object_literal_string Loading @@ -64,7 +96,7 @@ foo: function() { 'foo': function() { } ") assert_equal("foo", docs[0].function) assert_equal("foo", docs[0][:function][:name]) end def test_function_private Loading @@ -73,7 +105,7 @@ foo: function() { function foo() { } ") assert_equal(0, docs.length) assert_equal([], docs) end end