Commit 2c55613d authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Describe validation rules inside Options::Parser.

Eliminate the Validator class and attatch all the validation rules to
the Options::Record object, on which we can later simply call #validate!
to perform its own validations.
parent a24e9440
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -47,6 +47,11 @@ module JsDuck
          optparser.separator ""

          @opts.attribute(:input_files, [])
          @opts.validator do
            if @opts.input_files.empty? && !@opts.welcome && !@opts.guides && !@opts.videos && !@opts.examples
              "Please specify some input files, otherwise there's nothing I can do :("
            end
          end

          @opts.attribute(:output_dir)
          optparser.on('-o', '--output=PATH',
@@ -62,6 +67,20 @@ module JsDuck
              @opts.cache_dir = @opts.output_dir + "/.cache" unless @opts.cache_dir
            end
          end
          @opts.validator do
            if @opts.output_dir == :stdout
              # No output dir needed for export
              if !@opts.export
                "Output to STDOUT only works when using --export option"
              end
            elsif !@opts.output_dir
              "Please specify an output directory, where to write all this amazing documentation"
            elsif File.exists?(@opts.output_dir) && !File.directory?(@opts.output_dir)
              "The output directory is not really a directory at all :("
            elsif !File.exists?(File.dirname(@opts.output_dir))
              "The parent directory for #{@opts.output_dir} doesn't exist"
            end
          end

          @opts.attribute(:export)
          optparser.on('--export=full/examples',
@@ -74,6 +93,11 @@ module JsDuck
            "- examples - inline examples from classes and guides.") do |format|
            @opts.export = format.to_sym
          end
          @opts.validator do
            if ![nil, :full, :examples].include?(@opts.export)
              "Unknown export format: #{@opts.export}"
            end
          end

          optparser.on('--builtin-classes',
            "Includes docs for JavaScript builtins.",
@@ -261,6 +285,11 @@ module JsDuck
            "6 - <H2>,<H3>,<H4>,<H5>,<H6> headings are included.") do |level|
            @opts.guides_toc_level = level.to_i
          end
          @opts.validator do
            if !(1..6).include?(@opts.guides_toc_level)
              "Unsupported --guides-toc-level: '#{@opts.guides_toc_level}'"
            end
          end

          @opts.attribute(:videos)
          optparser.on('--videos=PATH',
@@ -739,6 +768,25 @@ module JsDuck
            "Useful when developing the template files.") do |path|
            @opts.template_dir = canonical(path)
          end
          @opts.validator do
            if @opts.export
              # Don't check these things when exporting
            elsif !File.exists?(@opts.template_dir + "/extjs")
              [
                "Oh noes!  The template directory does not contain extjs/ directory :(",
                "Please copy ExtJS over to template/extjs or create symlink.",
                "For example:",
                "    $ cp -r /path/to/ext-4.0.0 " + @opts.template_dir + "/extjs",
              ]
            elsif !File.exists?(@opts.template_dir + "/resources/css")
              [
                "Oh noes!  CSS files for custom ExtJS theme missing :(",
                "Please compile SASS files in template/resources/sass with compass.",
                "For example:",
                "    $ compass compile " + @opts.template_dir + "/resources/sass",
              ]
            end
          end

          @opts.attribute(:template_links, false)
          optparser.on('--template-links',
+6 −3
Original line number Diff line number Diff line
require 'jsduck/options/parser'
require 'jsduck/options/input_files'
require 'jsduck/options/validator'
require 'jsduck/logger'
require 'jsduck/util/json'
require 'jsduck/util/io'
@@ -22,8 +21,12 @@ module JsDuck
        # Expand list of input files
        Options::InputFiles.new(opts).expand!

        # Check for fatal problems (possibly exit the program).
        Options::Validator.new(opts).validate!
        # Validate the options.
        # Exit program when there's an error.
        if err = opts.validate!
          Array(err).each {|line| Logger.fatal(line) }
          exit(1)
        end

        # Configure various objects with these options
        Logger.configure(opts)
+23 −0
Original line number Diff line number Diff line
@@ -10,6 +10,9 @@ module JsDuck
    # ensures that accessing an unexisting option will result in an
    # error.
    class Record
      def initialize
        @validators = []
      end

      # Defines accessor for an option,
      # and assigns a default value for it.
@@ -30,6 +33,26 @@ module JsDuck
        instance_variable_set("@#{key}", value)
      end

      # Defines a validator function that gets run after all the
      # options have been parsed.  When validation fails, the function
      # should return an error message string (or an array of string
      # for multi-line error message) otherwise nil, to signify
      # success.
      def validator(&block)
        @validators << block
      end

      # Runs all the validators.  Returns an error message string from
      # the first failed validation or nil when everything is OK.
      def validate!
        @validators.each do |block|
          if err = block.call()
            return err
          end
        end
        return nil
      end

    end

  end

lib/jsduck/options/validator.rb

deleted100644 → 0
+0 −81
Original line number Diff line number Diff line
require 'jsduck/logger'

module JsDuck
  module Options

    # Validates command line options.
    class Validator
      def initialize(opts)
        @opts = opts
      end

      # Checks for fatal problems in command line options.
      # Exits with error message when such problem found.
      def validate!
        input_files_present
        output_dir_present
        valid_export_format
        template_files_present
        valid_guides_toc_level
      end

      private

      def input_files_present
        if @opts.input_files.empty? && !@opts.welcome && !@opts.guides && !@opts.videos && !@opts.examples
          fatal("Please specify some input files, otherwise there's nothing I can do :(")
        end
      end

      def output_dir_present
        if @opts.output_dir == :stdout
          # No output dir needed for export
          if !@opts.export
            fatal("Output to STDOUT only works when using --export option")
          end
        elsif !@opts.output_dir
          fatal("Please specify an output directory, where to write all this amazing documentation")
        elsif File.exists?(@opts.output_dir) && !File.directory?(@opts.output_dir)
          fatal("The output directory is not really a directory at all :(")
        elsif !File.exists?(File.dirname(@opts.output_dir))
          fatal("The parent directory for #{@opts.output_dir} doesn't exist")
        end
      end

      def valid_export_format
        if ![nil, :full, :examples].include?(@opts.export)
          fatal("Unknown export format: #{@export}")
        end
      end

      def template_files_present
        if @opts.export
          # Don't check these things when exporting
        elsif !File.exists?(@opts.template_dir + "/extjs")
          fatal("Oh noes!  The template directory does not contain extjs/ directory :(")
          fatal("Please copy ExtJS over to template/extjs or create symlink.")
          fatal("For example:")
          fatal("    $ cp -r /path/to/ext-4.0.0 " + @opts.template_dir + "/extjs")
        elsif !File.exists?(@opts.template_dir + "/resources/css")
          fatal("Oh noes!  CSS files for custom ExtJS theme missing :(")
          fatal("Please compile SASS files in template/resources/sass with compass.")
          fatal("For example:")
          fatal("    $ compass compile " + @opts.template_dir + "/resources/sass")
        end
      end

      def valid_guides_toc_level
        if !(1..6).include?(@opts.guides_toc_level)
          fatal("Unsupported --guides-toc-level: '#{@opts.guides_toc_level}'")
        end
      end

      def fatal(smg)
        Logger.fatal(msg)
        exit(1)
      end

    end

  end
end