<commit_before># coding: utf-8

require 'transpec/ast/builder'
require 'parser/current'

module Transpec
  class BaseRewriter
    def rewrite_file!(file_path)
      source = File.read(file_path)
      rewritten_source = rewrite(source, file_path)
      return if source == rewritten_source
      File.write(file_path, rewritten_source)
    end

    def rewrite(source, name = '(string)')
      source_buffer = create_source_buffer(source, name)
      ast = parse(source_buffer)

      source_rewriter = Parser::Source::Rewriter.new(source_buffer)
      failed_overlapping_rewrite = false
      source_rewriter.diagnostics.consumer = proc do
        failed_overlapping_rewrite = true
        fail OverlappedRewriteError
      end

      process(ast, source_rewriter)

      rewritten_source = source_rewriter.process

      if failed_overlapping_rewrite
        rewriter = self.class.new(@configuration, @report)
        rewritten_source = rewriter.rewrite(rewritten_source, name)
      end

      rewritten_source
    end

    private

    def process(ast, source_rewriter)
      fail NotImplementedError
    end

    def create_source_buffer(source, name)
      source_buffer = Parser::Source::Buffer.new(name)
      source_buffer.source = source
      source_buffer
    end

    def parse(source_buffer)
      builder = AST::Builder.new
      parser = Parser::CurrentRuby.new(builder)
      ast = parser.parse(source_buffer)
      ast
    end

    class OverlappedRewriteError < StandardError; end
  end
end
<commit_msg>Call #rewrite recursively when retrying rewrite in BaseRewriter<commit_after># coding: utf-8

require 'transpec/ast/builder'
require 'parser/current'

module Transpec
  class BaseRewriter
    def rewrite_file!(file_path)
      source = File.read(file_path)
      rewritten_source = rewrite(source, file_path)
      return if source == rewritten_source
      File.write(file_path, rewritten_source)
    end

    def rewrite(source, name = '(string)')
      source_buffer = create_source_buffer(source, name)
      ast = parse(source_buffer)

      source_rewriter = Parser::Source::Rewriter.new(source_buffer)
      failed_overlapping_rewrite = false
      source_rewriter.diagnostics.consumer = proc do
        failed_overlapping_rewrite = true
        fail OverlappedRewriteError
      end

      process(ast, source_rewriter)

      rewritten_source = source_rewriter.process
      rewritten_source = rewrite(rewritten_source, name) if failed_overlapping_rewrite

      rewritten_source
    end

    private

    def process(ast, source_rewriter)
      fail NotImplementedError
    end

    def create_source_buffer(source, name)
      source_buffer = Parser::Source::Buffer.new(name)
      source_buffer.source = source
      source_buffer
    end

    def parse(source_buffer)
      builder = AST::Builder.new
      parser = Parser::CurrentRuby.new(builder)
      ast = parser.parse(source_buffer)
      ast
    end

    class OverlappedRewriteError < StandardError; end
  end
end

{'fraction_non_alphanumeric': 0.07050216162287995, 'fraction_numerical': 0.0006651147322913202, 'mean_word_length': 3.2545968882602545, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1980323', 'n_tokens_mistral': 927, 'n_tokens_neox': 870, 'n_words': 189}