diff --git a/lib/jsduck/doc_parser.rb b/lib/jsduck/doc_parser.rb index 3100144678b7f6902d6faa883a9b2176906dacdf..9dab1605c181aabf52e2a6e0cd8cce8de9090b1c 100644 --- a/lib/jsduck/doc_parser.rb +++ b/lib/jsduck/doc_parser.rb @@ -439,14 +439,24 @@ module JsDuck # matches {...=} and returns text inside brackets def typedef match(/\{/) - name = @input.scan(/[^}]+/) + name = @input.scan(/[^{}]*/) + + # Type definition can contain nested braces: {{foo:Number}} + # In such case we parse the definition so that the braces are balanced. + while @input.check(/[{]/) + name += "{" + typedef[:type] +"}" + name += @input.scan(/[^{}]*/) + end + if name =~ /=$/ name = name.chop optional = true else optional = false end + match(/\}/) + return {:type => name, :optional => optional} end diff --git a/lib/jsduck/type_parser.rb b/lib/jsduck/type_parser.rb index 873482279cc40752ce296882df45b5a66b38ee82..7e00185f51b068e95056d9982a4678fb08bbd0fe 100644 --- a/lib/jsduck/type_parser.rb +++ b/lib/jsduck/type_parser.rb @@ -23,6 +23,8 @@ module JsDuck # Array. # Object. # + # {myNum: number, myObject} + # # (number|boolean) # ?number # !Object @@ -35,10 +37,6 @@ module JsDuck # function(?string=, number=) # function(string, ...[number]) # - # Currently not supported: - # - # {myNum: number, myObject} - # class TypeParser # Allows to check the type of error that was encountered. # It will be either of the two: @@ -143,7 +141,7 @@ module JsDuck # # ::= [ "[]" ]* # - # ::= | | + # ::= | | | # def null_type if nullability = @input.scan(/[?!]/) @@ -152,6 +150,8 @@ module JsDuck if @input.check(/\(/) return false unless union_type + elsif @input.check(/\{/) + return false unless record_type elsif @input.check(/function\(/) return false unless function_type else @@ -179,6 +179,46 @@ module JsDuck true end + # + # ::= "{" [ "," ]* "}" + # + def record_type + @out << @input.scan(/\{/) + + return false unless rtype_item + + while @input.scan(/,/) + @out << "," + return false unless rtype_item + end + + return false unless @input.scan(/\}/) + @out << "}" + + true + end + + # + # ::= ":" + # | + # + def rtype_item + skip_whitespace + + key = @input.scan(/[a-zA-Z0-9_]+/) + return false unless key + + skip_whitespace + if @input.scan(/:/) + @out << ":" + skip_whitespace + return false unless null_type + skip_whitespace + end + + true + end + # # ::= "function(" ")" [ ":" ] # diff --git a/spec/doc_parser_spec.rb b/spec/doc_parser_spec.rb index 12af220a04820068365337ce4f32e5787734180a..9cb76b045bd0b1204cf6ee268519d806ce176eb3 100644 --- a/spec/doc_parser_spec.rb +++ b/spec/doc_parser_spec.rb @@ -117,5 +117,18 @@ describe JsDuck::DocParser do end end + describe "type definition with nested {braces}" do + before do + @tag = parse_single(<<-EOS.strip)[0] + /** + * @param {{foo:{bar:Number}}} x + */ + EOS + end + it "is parsed ensuring balanced braces" do + @tag[:type].should == "{foo:{bar:Number}}" + end + end + end diff --git a/spec/type_parser_spec.rb b/spec/type_parser_spec.rb index 0aa6e9e0d7b7f87fba80efd663251314c3f31fc2..c0503960107211d5d1f90c9c9888713fec5a4984 100644 --- a/spec/type_parser_spec.rb +++ b/spec/type_parser_spec.rb @@ -268,6 +268,24 @@ describe JsDuck::TypeParser do end end + describe "record type" do + it "matches list of properties" do + parse("{foo, bar, baz}").should == true + end + + it "matches properties with types" do + parse("{foo: String, bar: Number}").should == true + end + + it "matches property with complex type" do + parse("{foo: (String|Array.)}").should == true + end + + it "matches nested record type" do + parse("{foo: {bar}}").should == true + end + end + it "always matches primitive types" do parse("boolean").should == true parse("number").should == true