Class: Audition::Fixer

Inherits:
Object
  • Object
show all
Defined in:
lib/audition/fixer.rb

Overview

Applies machine-generated corrections (rubocop-style --fix). Two tiers: safe inline autofixes attached to findings, and, under unsafe: true, file-level rewrites planned by Audition::Rewriters. Byte offsets come from Prism, so edits are applied bottom-up to keep earlier offsets valid.

Defined Under Namespace

Classes: Plan

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(unsafe: false) ⇒ Fixer

Returns a new instance of Fixer.

Parameters:

  • unsafe (Boolean) (defaults to: false)

    also apply :unsafe autofixes and the multi-site rewriters



16
17
18
# File 'lib/audition/fixer.rb', line 16

def initialize(unsafe: false)
  @unsafe = unsafe
end

Class Method Details

.unsafe_gain(findings) ⇒ Integer

How many additional edits the unsafe tier would unlock; used for the "N more with --fix-unsafe" summary hint.

Parameters:

Returns:

  • (Integer)


51
52
53
54
# File 'lib/audition/fixer.rb', line 51

def self.unsafe_gain(findings)
  new(unsafe: true).edit_count(findings) -
    new(unsafe: false).edit_count(findings)
end

Instance Method Details

#apply(findings) ⇒ Hash{String => Integer}

Applies planned edits to the files on disk.

Parameters:

Returns:

  • (Hash{String => Integer})

    path => applied edit count



24
25
26
27
28
29
# File 'lib/audition/fixer.rb', line 24

def apply(findings)
  plans(findings).to_h do |plan|
    File.write(plan.path, patched(plan))
    [plan.path, plan.edits.size]
  end
end

#edit_count(findings) ⇒ Object



42
43
44
# File 'lib/audition/fixer.rb', line 42

def edit_count(findings)
  plans(findings).sum { |plan| plan.edits.size }
end

#plans(findings) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/audition/fixer.rb', line 56

def plans(findings)
  findings.group_by(&:path).filter_map do |path, group|
    next unless path && File.file?(path)

    source = File.read(path)
    edits = build_edits(path, source, group)
    next if edits.empty?

    Plan.new(path: path, source: source,
      edits: edits.sort_by { |e| -e.start_offset })
  end
end

#preview(findings) ⇒ Array<Hash>

For --dry-run: what would change, without touching anything.

Parameters:

Returns:

  • (Array<Hash>)

    per file: :path and :hunks (:line, :old, :new)



36
37
38
39
40
# File 'lib/audition/fixer.rb', line 36

def preview(findings)
  plans(findings).map do |plan|
    {path: plan.path, hunks: hunks(plan)}
  end
end