123456789_123456789_123456789_123456789_123456789_

Class: RuboCop::CachedData Private

Relationships & Source Files
Inherits: Object
Defined in: lib/rubocop/cached_data.rb

Overview

Converts RuboCop objects to and from the serialization format JSON.

Class Method Summary

Instance Method Summary

Constructor Details

.new(filename) ⇒ CachedData

[ GitHub ]

  
# File 'lib/rubocop/cached_data.rb', line 9

def initialize(filename)
  @filename = filename
end

Instance Method Details

#add_corrections(hash, offense) (private)

A corrector cannot be serialized, so the edits it would make are cached separately; without this a cache hit would report no corrections.

[ GitHub ]

  
# File 'lib/rubocop/cached_data.rb', line 67

def add_corrections(hash, offense)
  return if offense.corrections.empty?

  hash[:corrections] = offense.corrections.map do |correction|
    { begin_pos: correction.begin_pos,
      end_pos: correction.end_pos,
      replacement: encode_to_utf8(correction.replacement) }
  end
  hash[:correction_safe] = offense.correction_safe
end

#add_justification(hash, offense) (private)

Only offenses suppressed by a directive can carry one, so keep the key out of the common case rather than writing a null for every cached offense.

[ GitHub ]

  
# File 'lib/rubocop/cached_data.rb', line 59

def add_justification(hash, offense)
  return unless offense.justification

  hash[:justification] = encode_to_utf8(offense.justification)
end

#corrections_from_cache(offense) (private)

[ GitHub ]

  
# File 'lib/rubocop/cached_data.rb', line 89

def corrections_from_cache(offense)
  cached = offense['corrections']
  return [] unless cached

  cached.map do |correction|
    Cop::Offense::Correction.new(correction['begin_pos'], correction['end_pos'],
                                 correction['replacement']).freeze
  end
end

#deserialize_offenses(offenses) (private)

Restore an offense object loaded from a JSON file.

[ GitHub ]

  
# File 'lib/rubocop/cached_data.rb', line 79

def deserialize_offenses(offenses)
  offenses.map! do |o|
    location = location_from_source_buffer(o)
    Cop::Offense.new(o['severity'], location, o['message'], o['cop_name'], o['status'].to_sym,
                     justification: o['justification'],
                     corrections: corrections_from_cache(o),
                     correction_safe: o.fetch('correction_safe', true))
  end
end

#encode_to_utf8(value) (private)

[ GitHub ]

  
# File 'lib/rubocop/cached_data.rb', line 47

def encode_to_utf8(value)
  string = value.to_s

  if string.encoding == ::Encoding::BINARY
    string.dup.force_encoding(::Encoding::UTF_8).scrub
  else
    string.encode(::Encoding::UTF_8, invalid: :replace, undef: :replace)
  end
end

#from_json(text)

[ GitHub ]

  
# File 'lib/rubocop/cached_data.rb', line 13

def from_json(text)
  deserialize_offenses(JSON.parse(text))
end

#location_from_source_buffer(offense) (private)

[ GitHub ]

  
# File 'lib/rubocop/cached_data.rb', line 99

def location_from_source_buffer(offense)
  begin_pos = offense['location']['begin_pos']
  end_pos = offense['location']['end_pos']
  if begin_pos.zero? && end_pos.zero?
    Cop::Offense::NO_LOCATION
  else
    Parser::Source::Range.new(source_buffer, begin_pos, end_pos)
  end
end

#message(offense) (private)

[ GitHub ]

  
# File 'lib/rubocop/cached_data.rb', line 43

def message(offense)
  encode_to_utf8(offense.message)
end

#serialize_offense(offense) (private)

[ GitHub ]

  
# File 'lib/rubocop/cached_data.rb', line 23

def serialize_offense(offense)
  status = :uncorrected if %i[corrected corrected_with_todo].include?(offense.status)
  hash = {
    # Calling #to_s here ensures that the serialization works when using
    # other json serializers such as Oj. Some of these gems do not call
    # #to_s implicitly.
    severity: offense.severity.to_s,
    location: {
      begin_pos: offense.location.begin_pos,
      end_pos: offense.location.end_pos
    },
    message:  message(offense),
    cop_name: offense.cop_name,
    status:   status || offense.status
  }
  add_justification(hash, offense)
  add_corrections(hash, offense)
  hash
end

#source_buffer (private)

Delay creation until needed. Some type of offenses will have no buffer associated with them and be global only. For these, trying to create the buffer will likely fail, for example because of unknown encoding comments.

[ GitHub ]

  
# File 'lib/rubocop/cached_data.rb', line 112

def source_buffer
  @source_buffer ||= begin
    source = File.read(@filename, encoding: Encoding::UTF_8)
    Parser::Source::Buffer.new(@filename, source: source)
  end
end

#to_json(offenses)

[ GitHub ]

  
# File 'lib/rubocop/cached_data.rb', line 17

def to_json(offenses)
  JSON.dump(offenses.map { |o| serialize_offense(o) })
end