Class: RuboCop::Cop::Corrector

Inherits:
Object
  • Object
show all
Defined in:
lib/rubocop/cop/corrector.rb

Overview

This class takes a source buffer and rewrite its source based on the different correction rules supplied.

Important! The nodes modified by the corrections should be part of the AST of the source_buffer.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source_buffer, corrections = []) ⇒ Corrector

Returns a new instance of Corrector.

Examples:


class AndOrCorrector
  def initialize(node)
    @node = node
  end

  def call(corrector)
    replacement = (@node.type == :and ? '&&' : '||')
    corrector.replace(@node.loc.operator, replacement)
  end
end

corrections = [AndOrCorrector.new(node)]
corrector = Corrector.new(source_buffer, corrections)

Parameters:

  • source_buffer (Parser::Source::Buffer)
  • corrections (Array(#call)) (defaults to: [])

    Array of Objects that respond to #call. They will receive the corrector itself and should use its method to modify the source.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/rubocop/cop/corrector.rb', line 33

def initialize(source_buffer, corrections = [])
  @source_buffer = source_buffer
  raise 'source_buffer should be a Parser::Source::Buffer' unless \
    source_buffer.is_a? Parser::Source::Buffer

  @corrections = corrections
  @source_rewriter = Parser::Source::TreeRewriter.new(
    source_buffer,
    different_replacements: :raise,
    swallowed_insertions: :raise,
    crossing_deletions: :accept
  )

  @diagnostics = []
  # Don't print warnings to stderr if corrections conflict with each other
  @source_rewriter.diagnostics.consumer = lambda do |diagnostic|
    @diagnostics << diagnostic
  end
end

Instance Attribute Details

#correctionsObject (readonly)

Returns the value of attribute corrections.



53
54
55
# File 'lib/rubocop/cop/corrector.rb', line 53

def corrections
  @corrections
end

#diagnosticsObject (readonly)

Returns the value of attribute diagnostics.



53
54
55
# File 'lib/rubocop/cop/corrector.rb', line 53

def diagnostics
  @diagnostics
end

Instance Method Details

#insert_after(node_or_range, content) ⇒ Object

Inserts new code after the given source range.

Parameters:

  • range (Parser::Source::Range, Rubocop::AST::Node)

    or node

  • content (String)


99
100
101
102
# File 'lib/rubocop/cop/corrector.rb', line 99

def insert_after(node_or_range, content)
  range = to_range(node_or_range)
  @source_rewriter.insert_after(range, content)
end

#insert_before(node_or_range, content) ⇒ Object

Inserts new code before the given source range.

Parameters:

  • range (Parser::Source::Range, Rubocop::AST::Node)

    or node

  • content (String)


85
86
87
88
89
90
91
92
93
# File 'lib/rubocop/cop/corrector.rb', line 85

def insert_before(node_or_range, content)
  range = to_range(node_or_range)
  # TODO: Fix Cops using bad ranges instead
  if range.end_pos > @source_buffer.source.size
    range = range.with(end_pos: @source_buffer.source.size)
  end

  @source_rewriter.insert_before(range, content)
end

#remove(node_or_range) ⇒ Object

Removes the source range.

Parameters:

  • range (Parser::Source::Range, Rubocop::AST::Node)

    or node



76
77
78
79
# File 'lib/rubocop/cop/corrector.rb', line 76

def remove(node_or_range)
  range = to_range(node_or_range)
  @source_rewriter.remove(range)
end

#remove_leading(node_or_range, size) ⇒ Object

Removes ‘size` characters from the beginning of the given range. If `size` is greater than the size of `range`, the removed region can overrun the end of `range`.

Parameters:

  • range (Parser::Source::Range, Rubocop::AST::Node)

    or node

  • size (Integer)


141
142
143
144
145
146
147
# File 'lib/rubocop/cop/corrector.rb', line 141

def remove_leading(node_or_range, size)
  range = to_range(node_or_range)
  to_remove = Parser::Source::Range.new(range.source_buffer,
                                        range.begin_pos,
                                        range.begin_pos + size)
  @source_rewriter.remove(to_remove)
end

#remove_preceding(node_or_range, size) ⇒ Object

Removes ‘size` characters prior to the source range.

Parameters:

  • range (Parser::Source::Range, Rubocop::AST::Node)

    or node

  • size (Integer)


127
128
129
130
131
132
133
# File 'lib/rubocop/cop/corrector.rb', line 127

def remove_preceding(node_or_range, size)
  range = to_range(node_or_range)
  to_remove = Parser::Source::Range.new(range.source_buffer,
                                        range.begin_pos - size,
                                        range.begin_pos)
  @source_rewriter.remove(to_remove)
end

#remove_trailing(node_or_range, size) ⇒ Object

Removes ‘size` characters from the end of the given range. If `size` is greater than the size of `range`, the removed region can overrun the beginning of `range`.

Parameters:

  • range (Parser::Source::Range, Rubocop::AST::Node)

    or node

  • size (Integer)


155
156
157
158
159
160
161
# File 'lib/rubocop/cop/corrector.rb', line 155

def remove_trailing(node_or_range, size)
  range = to_range(node_or_range)
  to_remove = Parser::Source::Range.new(range.source_buffer,
                                        range.end_pos - size,
                                        range.end_pos)
  @source_rewriter.remove(to_remove)
end

#replace(node_or_range, content) ⇒ Object

Replaces the code of the source range ‘range` with `content`.

Parameters:

  • range (Parser::Source::Range, Rubocop::AST::Node)

    or node

  • content (String)


118
119
120
121
# File 'lib/rubocop/cop/corrector.rb', line 118

def replace(node_or_range, content)
  range = to_range(node_or_range)
  @source_rewriter.replace(range, content)
end

#rewriteString

Does the actual rewrite and returns string corresponding to the rewritten source.

Returns:



59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/rubocop/cop/corrector.rb', line 59

def rewrite
  @corrections.each do |correction|
    begin
      @source_rewriter.transaction do
        correction.call(self)
      end
    rescue ErrorWithAnalyzedFileLocation => e
      raise e unless e.cause.is_a?(::Parser::ClobberingError)
    end
  end

  @source_rewriter.process
end

#wrap(node_or_range, before, after) ⇒ Object

Wraps the given source range with the given before and after texts

Parameters:

  • range (Parser::Source::Range, Rubocop::AST::Node)

    or node

  • before (String)
  • after (String)


109
110
111
112
# File 'lib/rubocop/cop/corrector.rb', line 109

def wrap(node_or_range, before, after)
  range = to_range(node_or_range)
  @source_rewriter.wrap(range, before, after)
end