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

Add warning for unsupported tags.

When encountering an unsupported @tag, JSDuck now prints a warning.

To achieve this, I've enhanced the doc-comment parser to only accept
@tags when they have a space in front of them.  Previously this would
have been detected as @method tag:

    /** foo@method.com */

Now it's treated as plain text as it should be. Only when separated
with spaces, the @method tag gets detected:

    /** foo @method .com */
parent 261a9f1a
Loading
Loading
Loading
Loading
+46 −9
Original line number Diff line number Diff line
require 'strscan'
require 'jsduck/meta_tag_registry'
require 'jsduck/logger'

module JsDuck

@@ -28,7 +29,9 @@ module JsDuck
      @meta_tags = MetaTagRegistry.instance
    end

    def parse(input)
    def parse(input, filename="", linenr=0)
      @filename = filename
      @linenr = linenr
      @tags = []
      @input = StringScanner.new(purify(input))
      parse_loop
@@ -145,18 +148,46 @@ module JsDuck
          boolean_at_tag(/@accessor/, :accessor)
        elsif look(/@evented\b/)
          boolean_at_tag(/@evented/, :evented)
        elsif look(/@example\b/)
          at_example
        elsif look(/@/)
          other_at_tag
        elsif look(/[^@]/)
          skip_to_next_at_tag
        end
      end
    end

    # Skips until the beginning of next @tag.
    #
    # There must be space before the next @tag - this ensures that we
    # don't detect tags inside "foo@example.com" or "{@link}".
    def skip_to_next_at_tag
      @current_tag[:doc] += match(/[^@]+/)

      while @current_tag[:doc][-1] =~ /\S/ && look(/@/)
        @current_tag[:doc] += match(/@+[^@]+/)
      end
    end

    # Processes anything else beginning with @-sign.
    #
    # - When @ is not followed by any word chards, do nothing.
    # - When it's one of the meta-tags, process it as such.
    # - When it's something else, print a warning.
    #
    def other_at_tag
      match(/@/)
          tag = @meta_tags[look(/\w+/)]

      name = look(/\w+/)
      tag = @meta_tags[name]

      if tag
        meta_at_tag(tag)
          else
      elsif name
        Logger.warn(:tag, "Unsupported tag: @#{name}", @filename, @linenr)
        @current_tag[:doc] += "@"
      end
        elsif look(/[^@]/)
          @current_tag[:doc] += match(/[^@]+/)
        end
      end
    end

    # Matches the given meta-tag
@@ -185,6 +216,12 @@ module JsDuck
      end
    end

    # A special case for @example tag,
    # which we leave as is to be processed later in DocFormatter
    def at_example
      @current_tag[:doc] += match(/@example/) + skip_white
    end

    # matches @class name ...
    def at_class
      match(/@class/)
+1 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ module JsDuck
        [:global, "Member doesn't belong to any class"],
        [:inheritdoc, "@inheritdoc referring to unknown class or member"],
        [:extend, "@extend/mixin/requires/uses referring to unknown class"],
        [:tag, "Use of unsupported @tag"],
        [:link, "{@link} to unknown class or member"],
        [:link_ambiguous, "{@link} is ambiguous"],
        [:link_auto, "Auto-detected link to unknown class or member"],
+1 −1
Original line number Diff line number Diff line
@@ -49,7 +49,7 @@ module JsDuck

      # Parses the docs, detects tagname and expands class docset
      def expand(docset)
        docset[:comment] = @doc_parser.parse(docset[:comment])
        docset[:comment] = @doc_parser.parse(docset[:comment], @doc_ast.filename, docset[:linenr])
        docset[:tagname] = @doc_type.detect(docset[:comment], docset[:code])

        if docset[:tagname] == :class
+33 −1
Original line number Diff line number Diff line
@@ -124,5 +124,37 @@ describe JsDuck::DocParser do
    end
  end

  describe "e-mail address containing a valid @tag" do
    before do
      @tag = parse_single(<<-EOS.strip)[0]
         * john@method.com
      EOS
    end
    it "is treated as plain text" do
      @tag[:doc].should == "john@method.com"
    end
  end

  describe "{@inline} tag" do
    before do
      @tag = parse_single(<<-EOS.strip)[0]
         * {@inline Some#method}
      EOS
    end
    it "is treated as plain text, to be processed later" do
      @tag[:doc].should == "{@inline Some#method}"
    end
  end

  describe "@example tag" do
    before do
      @tag = parse_single(<<-EOS.strip)[0]
         * @example blah
      EOS
    end
    it "is treated as plain text, to be processed later" do
      @tag[:doc].should == "@example blah"
    end
  end

end