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

Support this: and new: inside function type.

Also now only allow optionality suffix "=" be used inside function type
arguments.
parent d50c7156
Loading
Loading
Loading
Loading
+48 −6
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ module JsDuck
    end

    #
    #     <alteration-type> ::= <varargs-type> [ ("/" | "|") <varargs-type> ]*  [ "=" ]
    #     <alteration-type> ::= <varargs-type> [ ("/" | "|") <varargs-type> ]*
    #
    def alteration_type
      skip_whitespace
@@ -78,9 +78,6 @@ module JsDuck
        skip_whitespace
      end

      @out << "=" if @input.scan(/=/)
      skip_whitespace

      true
    end

@@ -144,14 +141,14 @@ module JsDuck
    end

    #
    #     <function-type> ::= "function(" <type-arguments> ")" [ ":" <null-type> ]
    #     <function-type> ::= "function(" <function-type-arguments> ")" [ ":" <null-type> ]
    #
    def function_type
      @out << @input.scan(/function\(/)

      skip_whitespace
      if !@input.check(/\)/)
        return false unless type_arguments
        return false unless function_type_arguments
      end

      return false unless @input.scan(/\)/)
@@ -167,6 +164,51 @@ module JsDuck
      true
    end

    #
    #     <function-type-arguments> ::= <ftype-first-arg> [ "," <ftype-arg> ]*
    #
    #     <ftype-first-arg> ::= "new" ":" <type-name>
    #                         | "this" ":" <type-name>
    #                         | <ftype-arg>
    #
    def function_type_arguments
      skip_whitespace

      # First argument is special
      if s = @input.scan(/new\s*:\s*/)
        @out << s
        return false unless type_name
      elsif s = @input.scan(/this\s*:\s*/)
        @out << s
        return false unless type_name
      else
        return false unless ftype_arg
      end

      skip_whitespace

      # Go through additional arguments, separated with ","
      while @input.check(/,/)
        @out << @input.scan(/,/)
        return false unless ftype_arg
      end

      true
    end

    #
    #     <ftype-arg> ::= <alteration-type> [ "=" ]
    #
    def ftype_arg
      return false unless alteration_type

      # Each argument can be optional (ending with "=")
      @out << "=" if @input.scan(/[=]/)
      skip_whitespace

      true
    end

    #
    #     <type-name> ::= <type-application> | "*"
    #
+25 −6
Original line number Diff line number Diff line
@@ -173,12 +173,15 @@ describe JsDuck::TypeParser do
      parse("( String | Number )").should == true
    end

    # This is handled mainly inside DocParser, when it's detected over
    # there the "=" is removed from the end of type definition, so it
    # should never reach TypeParser.  But additionally it can be used
    # inside function type parameter list, so we need to support it.
    it "matches optional parameter notation" do
      parse("String=").should == true
    # This is handled inside DocParser, when it's detected over there
    # the "=" is removed from the end of type definition, so it should
    # never reach TypeParser if there is just one "=" at the end of
    # type definition.
    #
    # We do support the optional notation inside function type
    # parameter lists (see below).
    it "doesn't accept optional parameter notation" do
      parse("String=").should == false
    end

    it "matches single type argument" do
@@ -229,6 +232,22 @@ describe JsDuck::TypeParser do
      parse("function(Number=)").should == true
    end

    it "matches function type with this: argument" do
      parse("function(this:Array, Number)").should == true
    end

    it "matches function type with new: argument" do
      parse("function(new:Array)").should == true
    end

    it "matches function type with this: argument + ws" do
      parse("function(this : Array, Number)").should == true
    end

    it "matches function type with new: argument + ws" do
      parse("function(new : Array)").should == true
    end

    it "matches function type with extra whitespace" do
      parse("function(  ) : Array").should == true
    end