class Guard::Eslint::Runner

This class runs `eslint` command, retrieves result and notifies. An instance of this class is intended to invoke `eslint` only once in its lifetime.

Attributes

check_stderr[RW]
check_stdout[RW]
options[R]

Public Class Methods

new(options) click to toggle source
# File lib/guard/eslint/runner.rb, line 11
def initialize(options)
  @options = options
end

Public Instance Methods

failed_paths() click to toggle source
# File lib/guard/eslint/runner.rb, line 33
def failed_paths
  result.reject { |f| f[:messages].empty? }.map { |f| f[:filePath] }
end
run(paths) click to toggle source
# File lib/guard/eslint/runner.rb, line 17
def run(paths)
  paths = options[:default_paths] unless paths

  passed = run_for_check(paths)
  case options[:notification]
  when :failed
    notify(passed) unless passed
  when true
    notify(passed)
  end

  run_for_output(paths)

  passed
end

Private Instance Methods

args_specified_by_user() click to toggle source
# File lib/guard/eslint/runner.rb, line 72
def args_specified_by_user
  @args_specified_by_user ||= begin
    args = options[:cli]
    case args
    when Array    then args
    when String   then args.shellsplit
    when NilClass then []
    else fail ':cli option must be either an array or string'
    end
  end
end
command_for_check(paths) click to toggle source
# File lib/guard/eslint/runner.rb, line 64
def command_for_check(paths)
  command = [options[:command]]

  command.concat(args_specified_by_user)
  command.concat(['-f', 'json', '-o', json_file_path])
  command.concat(paths)
end
json_file() click to toggle source

Keep the Tempfile instance around so it isn't garbage-collected and therefore deleted.

# File lib/guard/eslint/runner.rb, line 93
def json_file
  @json_file ||= begin
    # Just generate random tempfile path.
    basename = self.class.name.downcase.gsub('::', '_')
    Tempfile.new(basename)
  end
end
json_file_path() click to toggle source
# File lib/guard/eslint/runner.rb, line 84
def json_file_path
  @json_file_path ||= begin
    json_file.close
    json_file.path
  end
end
notify(passed) click to toggle source
# File lib/guard/eslint/runner.rb, line 112
def notify(passed)
  image = passed ? :success : :failed
  Notifier.notify(summary_text, title: 'ESLint results', image: image)
end
pluralize(number, thing, options = {}) click to toggle source

rubocop:enable Metric/AbcSize

# File lib/guard/eslint/runner.rb, line 138
def pluralize(number, thing, options = {})
  text = ''

  if number == 0 && options[:no_for_zero]
    text = 'no'
  else
    text << number.to_s
  end

  text << " #{thing}"
  text << 's' unless number == 1

  text
end
result() click to toggle source
# File lib/guard/eslint/runner.rb, line 101
def result
  @result ||= begin
    File.open(json_file_path) do |file|
      # Rubinius 2.0.0.rc1 does not support `JSON.load` with 3 args.
      JSON.parse(file.read, symbolize_names: true)
    end
  end
rescue JSON::ParserError
  fail "eslint JSON output could not be parsed. Output from eslint was:\n#{check_stderr}\n#{check_stdout}"
end
run_for_check(paths) click to toggle source
# File lib/guard/eslint/runner.rb, line 41
def run_for_check(paths)
  command = command_for_check(paths)
  (stdout, stderr, status) = Open3.capture3(*command)
  self.check_stdout = stdout
  self.check_stderr = stderr
  status
rescue SystemCallError => e
  fail "The eslint command failed with #{e.message}: `#{command}`"
end
run_for_output(paths) click to toggle source

Once eslint reports a failure, we have to run it again to show the results using the formatter that it uses for output. This because eslint doesn't support multiple formatters during the same run.

# File lib/guard/eslint/runner.rb, line 55
def run_for_output(paths)
  command = [options[:command]]

  command.concat(args_specified_by_user)
  command.concat(['-f', options[:formatter]]) if options[:formatter]
  command.concat(paths)
  system(*command)
end
summary_text() click to toggle source

rubocop:disable Metric/AbcSize

# File lib/guard/eslint/runner.rb, line 118
def summary_text
  summary = {
    files_inspected: result.count,
    errors: result.map { |x| x[:errorCount] }.reduce(:+),
    warnings: result.map { |x| x[:warningCount] }.reduce(:+)
  }

  text = pluralize(summary[:files_inspected], 'file')
  text << ' inspected, '

  errors_count = summary[:errors]
  text << pluralize(errors_count, 'error', no_for_zero: true)
  text << ' detected, '

  warning_count = summary[:warnings]
  text << pluralize(warning_count, 'warning', no_for_zero: true)
  text << ' detected'
end