Sha256: e339b4b636202d2236bc0eaf4dd213c3a469575235f5954a445ed7a98291bae1

Contents?: true

Size: 1.96 KB

Versions: 2

Compression:

Stored size: 1.96 KB

Contents

require 'slim_lint/ruby_extractor'
require 'slim_lint/ruby_extract_engine'
require 'rubocop'
require 'tempfile'

module SlimLint
  # Runs RuboCop on Ruby code extracted from Slim templates.
  class Linter::RuboCop < Linter
    include LinterRegistry

    on_start do |_sexp|
      processed_sexp = SlimLint::RubyExtractEngine.new.call(document.source)

      extractor = SlimLint::RubyExtractor.new
      extracted_ruby = extractor.extract(processed_sexp)

      find_lints(extractor, extracted_ruby) unless extracted_ruby.empty?
    end

    private

    def find_lints(extractor, ruby)
      rubocop = ::RuboCop::CLI.new

      original_filename = document.file || 'ruby_script'
      filename = "#{File.basename(original_filename)}.slim_lint.tmp"
      directory = File.dirname(original_filename)

      Tempfile.open(filename, directory) do |f|
        begin
          f.write(ruby)
          f.close
          extract_lints_from_offences(lint_file(rubocop, f.path), extractor)
        ensure
          f.unlink
        end
      end
    end

    # Defined so we can stub the results in tests
    def lint_file(rubocop, file)
      rubocop.run(%w[--format SlimLint::OffenceCollector] << file)
      OffenceCollector.offences
    end

    def extract_lints_from_offences(offences, extractor)
      offences.select { |offence| !config['ignored_cops'].include?(offence.cop_name) }
              .each do |offence|
        @lints << Lint.new(self,
                           document.file,
                           extractor.source_map[offence.line],
                           "#{offence.cop_name}: #{offence.message}")
      end
    end
  end

  # Collects offences detected by RuboCop.
  class OffenceCollector < ::RuboCop::Formatter::BaseFormatter
    attr_accessor :offences

    class << self
      attr_accessor :offences
    end

    def started(_target_files)
      self.class.offences = []
    end

    def file_finished(_file, offences)
      self.class.offences += offences
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
slim_lint-0.2.0 lib/slim_lint/linter/rubocop.rb
slim_lint-0.1.0 lib/slim_lint/linter/rubocop.rb