diff --git a/lib/jsduck/doc_parser.rb b/lib/jsduck/doc_parser.rb index b6551fe1fed7a6f226c4405aa55bfa2fa950f73d..b82bf50d84786295df5f159d01d0e1ed9db84817 100644 --- a/lib/jsduck/doc_parser.rb +++ b/lib/jsduck/doc_parser.rb @@ -23,7 +23,8 @@ module JsDuck class DocParser # Pass in :css to be able to parse CSS doc-comments def initialize(mode = :js) - @ident_pattern = (mode == :css) ? /\$[a-zA-Z0-9_-]*/ : /\w+/ + @ident_pattern = (mode == :css) ? /\$[\w-]*/ : /\w+/ + @ident_chain_pattern = (mode == :css) ? /\$[\w.-]*/ : /[\w.]+/ end def parse(input) @@ -183,12 +184,13 @@ module JsDuck skip_white end - # matches @param {type} variable ... + # matches @param {type} name ... def at_param match(/@param/) add_tag(:param) maybe_type - maybe_name + #maybe_name + maybe_ident_chain(:name) skip_white end @@ -278,7 +280,7 @@ module JsDuck match(/@alias/) add_tag(:alias) skip_horiz_white - if look(/\w/) + if look(@ident_chain_pattern) @current_tag[:cls] = ident_chain if look(/#\w/) @input.scan(/#/) @@ -347,7 +349,7 @@ module JsDuck # matches ident.chain if possible and sets it on @current_tag def maybe_ident_chain(propname) skip_horiz_white - if look(/\w/) + if look(@ident_chain_pattern) @current_tag[propname] = ident_chain end end @@ -364,7 +366,7 @@ module JsDuck def class_list skip_horiz_white classes = [] - while look(/\w/) + while look(@ident_chain_pattern) classes << ident_chain skip_horiz_white end @@ -373,7 +375,7 @@ module JsDuck # matches chained.identifier.name and returns it def ident_chain - @input.scan(/[\w.]+/) + @input.scan(@ident_chain_pattern) end # matches identifier and returns its name diff --git a/lib/jsduck/merger.rb b/lib/jsduck/merger.rb index 6c938d6d091e5fa7e683773cd96c8cbedabc8a4c..90fa0106c82364a7cbc7a7fe75c855e5e469705c 100644 --- a/lib/jsduck/merger.rb +++ b/lib/jsduck/merger.rb @@ -318,6 +318,7 @@ module JsDuck :doc => doc, # convert to boolean for JavaScript export, otherwise it's 0 or nil :optional => !!(doc =~ /\(optional\)/i), + :properties => ex[:properties] || [], } end params @@ -334,7 +335,23 @@ module JsDuck end def detect_explicit_params(docs) - docs.find_all {|tag| tag[:tagname] == :param} + combine_properties(docs.find_all {|tag| tag[:tagname] == :param}) + end + + def combine_properties(raw_items) + items = [] + previous = {} + raw_items.each do |it| + if it[:name] =~ /\.(.*)$/ + it[:name] = $1 + previous[:properties] = [] unless previous[:properties] + previous[:properties] << it + else + items << it + previous = it + end + end + items end def detect_return(doc_map, default_type="undefined") diff --git a/spec/aggregator_methods_and_events_spec.rb b/spec/aggregator_methods_and_events_spec.rb index ac3d5fcef70c07e5ba2bef06265d35bbbc447ffe..4fda2e89c065b1a5d891c96d5baf23e169c36408 100644 --- a/spec/aggregator_methods_and_events_spec.rb +++ b/spec/aggregator_methods_and_events_spec.rb @@ -267,6 +267,82 @@ describe JsDuck::Aggregator do end end + describe "method parameter with properties" do + before do + @doc = parse(<<-EOS)[0] + /** + * Some function + * @param {Object} coord Geographical coordinates + * @param {Number} coord.lat Latitude + * @param {Number} coord.lng Longitude + */ + function foo(x, y) {} + EOS + end + + it "interprets as single parameter" do + @doc[:params].length.should == 1 + end + + describe "single param" do + before do + @param = @doc[:params][0] + end + + it "has name" do + @param[:name].should == "coord" + end + + it "has type" do + @param[:type].should == "Object" + end + + it "has doc" do + @param[:doc].should == "Geographical coordinates" + end + + it "contains 2 properties" do + @param[:properties].length.should == 2 + end + + describe "first property" do + before do + @prop = @param[:properties][0] + end + + it "has name without namespace" do + @prop[:name].should == "lat" + end + + it "has type" do + @prop[:type].should == "Number" + end + + it "has doc" do + @prop[:doc].should == "Latitude" + end + end + + describe "second property" do + before do + @prop = @param[:properties][1] + end + + it "has name without namespace" do + @prop[:name].should == "lng" + end + + it "has type" do + @prop[:type].should == "Number" + end + + it "has doc" do + @prop[:doc].should == "Longitude" + end + end + end + end + describe "@return documenting return value" do before do @doc = parse(<<-EOS)[0] diff --git a/template/app/view/cls/Overview.js b/template/app/view/cls/Overview.js index 9c88dc69e994382ac4ec079cd577ffdda7a35d16..e3dda5c0ce1f6e8aa0c33a528d45b9eb81f65c82 100644 --- a/template/app/view/cls/Overview.js +++ b/template/app/view/cls/Overview.js @@ -406,8 +406,7 @@ Ext.define('Docs.view.cls.Overview', { if (member.params && member.params.length > 0) { doc += '

Parameters

'; - var ps = Ext.Array.map(member.params, this.renderLongParam, this).join(""); - doc += ""; + doc += this.renderParams(member.params); } if (member["return"]) { @@ -417,14 +416,24 @@ Ext.define('Docs.view.cls.Overview', { return doc; }, + renderParams: function(params) { + return ""; + }, + renderLongParam: function(param) { this.paramTpl = this.paramTpl || new Ext.XTemplate( '
  • ', '{name} : {type}', '
    ', '{doc}', + '', + '{[this.renderParams(values.properties)]}', + '', '
    ', - '
  • ' + '', + { + renderParams: Ext.Function.bind(this.renderParams, this) + } ); return this.paramTpl.apply(param);