lib/standard/lsp/standardizer.rb in standard-1.24.2 vs lib/standard/lsp/standardizer.rb in standard-1.24.3

- old
+ new

@@ -1,50 +1,66 @@ require_relative "../runners/rubocop" -require "tempfile" module Standard module Lsp class Standardizer - def initialize(config) - @template_options = config - @runner = Standard::Runners::Rubocop.new + def initialize(config, logger) + @config = config + @logger = logger + @rubocop_runner = Standard::Runners::Rubocop.new end - def format(text) - run_standard(text, format: true) + # This abuses the --stdin option of rubocop and reads the formatted text + # from the options[:stdin] that rubocop mutates. This depends on + # parallel: false as well as the fact that rubocop doesn't otherwise dup + # or reassign that options object. Risky business! + # + # Reassigning options[:stdin] is done here: + # https://github.com/rubocop/rubocop/blob/master/lib/rubocop/cop/team.rb#L131 + # Printing options[:stdin] + # https://github.com/rubocop/rubocop/blob/master/lib/rubocop/cli/command/execute_runner.rb#L95 + # Setting `parallel: true` would break this here: + # https://github.com/rubocop/rubocop/blob/master/lib/rubocop/runner.rb#L72 + def format(path, text) + ad_hoc_config = fork_config(path, text, format: true) + capture_rubocop_stdout(ad_hoc_config) + ad_hoc_config.rubocop_options[:stdin] end - def offenses(text) - results = run_standard(text, format: false) - JSON.parse(results, symbolize_names: true).dig(:files, 0, :offenses) + def offenses(path, text) + results = JSON.parse( + capture_rubocop_stdout(fork_config(path, text, format: false)), + symbolize_names: true + ) + if results[:files].empty? + @logger.puts_once "Ignoring file, per configuration: #{path}" + [] + else + results.dig(:files, 0, :offenses) + end end private - BASENAME = ["source", ".rb"].freeze - def run_standard(text, format:) - Tempfile.open(BASENAME) do |temp| - temp.write(text) - temp.flush - stdout = capture_rubocop_stdout(make_config(temp.path, format)) - format ? File.read(temp.path) : stdout - end - end - - def make_config(file, format) - # Can't make frozen versions of this hash because RuboCop mutates it - o = if format - {autocorrect: true, formatters: [["Standard::Formatter", nil]], parallel: true, todo_file: nil, todo_ignore_files: [], safe_autocorrect: true} + BASE_OPTIONS = { + force_exclusion: true, + parallel: false, + todo_file: nil, + todo_ignore_files: [] + } + def fork_config(path, text, format:) + options = if format + {stdin: text, autocorrect: true, formatters: [], safe_autocorrect: true} else - {autocorrect: false, formatters: [["json"]], parallel: true, todo_file: nil, todo_ignore_files: [], format: "json"} + {stdin: text, autocorrect: false, formatters: [["json"]], format: "json"} end - Standard::Config.new(@template_options.runner, [file], o, @template_options.rubocop_config_store) + Standard::Config.new(@config.runner, [path], BASE_OPTIONS.merge(options), @config.rubocop_config_store) end def capture_rubocop_stdout(config) redir = StringIO.new $stdout = redir - @runner.call(config) + @rubocop_runner.call(config) redir.string ensure $stdout = STDOUT end end