├── lib ├── mry │ ├── version.rb │ ├── cli.rb │ ├── runner.rb │ ├── added_cops.rb │ └── rewriters.rb ├── yaml_rewriter │ ├── parser.rb │ ├── scalar_with_mark.rb │ ├── mark_handler.rb │ ├── rule.rb │ └── rewriter.rb ├── yaml_rewriter.rb └── mry.rb ├── exe └── mry ├── Gemfile ├── .gitignore ├── test ├── test_helper.rb ├── mry │ ├── test_integration.rb │ ├── test_added_cops.rb │ └── test_runner.rb └── yaml_rewriter │ ├── test_rule.rb │ └── test_rewriter.rb ├── bin ├── setup ├── renamed_cop.rb ├── console └── check_rubocop_update ├── .rubocop.yml ├── Rakefile ├── .travis.yml ├── CHANGELOG.md ├── mry.gemspec ├── README.md └── LICENSE /lib/mry/version.rb: -------------------------------------------------------------------------------- 1 | module Mry 2 | VERSION = "0.78.0.0" 3 | end 4 | -------------------------------------------------------------------------------- /exe/mry: -------------------------------------------------------------------------------- 1 | #!ruby 2 | 3 | require 'mry' 4 | 5 | exit Mry::CLI.run(ARGV) 6 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in mry.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | require 'minitest' 2 | require 'minitest/autorun' 3 | require 'minitest-power_assert' 4 | 5 | 6 | 7 | require 'mry' 8 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -euo pipefail 3 | IFS=$'\n\t' 4 | set -vx 5 | 6 | bundle install 7 | 8 | # Do any other automated setup that you need to do here 9 | -------------------------------------------------------------------------------- /lib/yaml_rewriter/parser.rb: -------------------------------------------------------------------------------- 1 | module YAMLRewriter 2 | class Parser < ::Psych::Parser 3 | def initialize 4 | super(MarkHandler.new(self)) 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/yaml_rewriter/scalar_with_mark.rb: -------------------------------------------------------------------------------- 1 | module YAMLRewriter 2 | module ScalarWithMark 3 | refine Psych::Nodes::Scalar do 4 | attr_accessor :mark 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | # To use the MeowCop gem. 2 | inherit_gem: 3 | meowcop: 4 | - config/rubocop.yml 5 | 6 | AllCops: 7 | TargetRubyVersion: 2.3 8 | 9 | Rails: 10 | Enabled: false 11 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | require 'rake/testtask' 3 | task :default => :test 4 | 5 | Rake::TestTask.new do |test| 6 | test.libs << 'test' 7 | test.test_files = Dir['test/**/test_*.rb'] 8 | test.verbose = true 9 | end 10 | -------------------------------------------------------------------------------- /test/mry/test_integration.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class TestIntegration < Minitest::Test 4 | def test_without_args 5 | out = `mry` 6 | assert { !$?.success? } 7 | assert { out == Mry::CLI.__send__(:option).help } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/yaml_rewriter.rb: -------------------------------------------------------------------------------- 1 | require 'psych' 2 | require 'yaml_rewriter/rule' 3 | require 'yaml_rewriter/scalar_with_mark' 4 | require 'yaml_rewriter/mark_handler' 5 | require 'yaml_rewriter/parser' 6 | require 'yaml_rewriter/rewriter' 7 | 8 | module YAMLRewriter 9 | end 10 | -------------------------------------------------------------------------------- /lib/mry.rb: -------------------------------------------------------------------------------- 1 | require 'yaml_rewriter' 2 | require 'optparse' 3 | require 'tmpdir' 4 | require 'pathname' 5 | 6 | require "mry/version" 7 | require 'mry/rewriters' 8 | require 'mry/runner' 9 | require 'mry/cli' 10 | require 'mry/added_cops' 11 | 12 | module Mry 13 | end 14 | -------------------------------------------------------------------------------- /bin/renamed_cop.rb: -------------------------------------------------------------------------------- 1 | require 'yaml' 2 | 3 | log = YAML.load_file('/tmp/mry_check_rubocop_update_log.yaml') 4 | log[:renamed].each do |before:, after:| 5 | raise 'before is not one' if before.size != 1 6 | raise 'after is not one' if after.size != 1 7 | 8 | puts "define_rule ['#{before.first}' => '#{after.first}']" 9 | end 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | 3 | rvm: 4 | - 2.4.9 5 | - 2.5.7 6 | - 2.6.5 7 | - 2.7.0 8 | - ruby-head 9 | 10 | cache: bundler 11 | bundler_args: --jobs=4 --retry=3 12 | 13 | before_install: 'gem update --system' 14 | 15 | script: 16 | - bundle exec rake test 17 | 18 | matrix: 19 | allow_failures: 20 | - rvm: ruby-head 21 | fast_finish: true 22 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require "bundler/setup" 4 | require "mry" 5 | 6 | # You can add fixtures and/or initialization code here to make experimenting 7 | # with your gem easier. You can also use a different console, if you like. 8 | 9 | # (If you use this, don't forget to add pry to your Gemfile!) 10 | # require "pry" 11 | # Pry.start 12 | 13 | require "irb" 14 | IRB.start(__FILE__) 15 | -------------------------------------------------------------------------------- /lib/yaml_rewriter/mark_handler.rb: -------------------------------------------------------------------------------- 1 | module YAMLRewriter 2 | class MarkHandler < ::Psych::TreeBuilder 3 | using ScalarWithMark 4 | 5 | def initialize(parser) 6 | @parser = parser 7 | super() 8 | end 9 | 10 | def scalar(value, anchor, tag, plain, quoted, style) 11 | mark = @parser.mark 12 | super.tap do |scalar| 13 | scalar.mark = mark 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /lib/yaml_rewriter/rule.rb: -------------------------------------------------------------------------------- 1 | module YAMLRewriter 2 | class Rule 3 | def initialize(rule) 4 | @rule = rule 5 | end 6 | 7 | def match?(path, reverse:) 8 | rule_path = @rule[0..-2] + 9 | (reverse ? [@rule.last.values.first] : [@rule.last.keys.first]) 10 | rule_path == (path[(path.size-@rule.size)..-1]) 11 | end 12 | 13 | def replacement(key, reverse:) 14 | reverse ? 15 | @rule.last.invert[key] : 16 | @rule.last[key] 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change log 2 | 3 | ## master (unreleased) 4 | 5 | ## 0.49.0.0 (2017-05-28) 6 | 7 | ### New Features 8 | 9 | - [#13](https://github.com/pocke/mry/pull/13): Support RuboCop 0.49.0. ([@pocke][]) 10 | 11 | ## 0.48.1.3 (2017-05-15) 12 | 13 | ### New Features 14 | 15 | - [#10](https://github.com/pocke/mry/pull/10): Support downgrading RuboCop version. ([@pocke][]) 16 | 17 | ## 0.48.1.2 (2017-05-5) 18 | 19 | ### Bug fixes 20 | 21 | - [#7](https://github.com/pocke/mry/issues/7): Prevent mry command from breaking without `--target` option. ([@pocke][]) 22 | 23 | 24 | 25 | 26 | [@pocke]: https://github.com/pocke 27 | -------------------------------------------------------------------------------- /test/yaml_rewriter/test_rule.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class TestRule < Minitest::Test 4 | def test_rule_match 5 | rule = YAMLRewriter::Rule.new(['foo', 'bar' => 'baz']) 6 | assert { rule.match?(['foo', 'bar'], reverse: false) } 7 | assert { not rule.match?(['foo', 'baz'], reverse: false) } 8 | end 9 | 10 | def test_rule_match_with_reverse 11 | rule = YAMLRewriter::Rule.new(['foo', 'bar' => 'baz']) 12 | assert { not rule.match?(['foo', 'bar'], reverse: true) } 13 | assert { rule.match?(['foo', 'baz'], reverse: true) } 14 | end 15 | 16 | def test_rule_replacement 17 | rule = YAMLRewriter::Rule.new(['foo', 'bar' => 'baz']) 18 | assert { rule.replacement('bar', reverse: false) == 'baz' } 19 | end 20 | 21 | def test_rule_replacement_with_reverse 22 | rule = YAMLRewriter::Rule.new(['foo', 'bar' => 'baz']) 23 | assert { rule.replacement('baz', reverse: true) == 'bar' } 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /lib/mry/cli.rb: -------------------------------------------------------------------------------- 1 | module Mry 2 | module CLI 3 | class << self 4 | # @param argv [Array] 5 | # @return [Integer] exit code 6 | def run(argv) 7 | parse_option(argv) 8 | if argv.empty? 9 | puts option.help 10 | return 1 11 | end 12 | Runner.run(argv, to: @target, from: @from) 13 | return 0 14 | end 15 | 16 | 17 | private 18 | 19 | def parse_option(argv) 20 | @target = Gem::Version.new('1000000') 21 | @from = nil 22 | option.parse!(argv) 23 | end 24 | 25 | def option 26 | opt = OptionParser.new 27 | opt.banner = 'Usage: mry [options] [.rubocop.yml]' 28 | opt.on('-t=TARGET_VERSION', '--target=TARGET_VERSION') do |t| 29 | @target = 30 | if t == 'master' 31 | :master 32 | else 33 | Gem::Version.new(t) 34 | end 35 | end 36 | 37 | opt.on('--from=CURRENT_VERSION') do |t| 38 | @from = Gem::Version.new(t) 39 | end 40 | end 41 | end 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/mry/runner.rb: -------------------------------------------------------------------------------- 1 | module Mry 2 | module Runner 3 | class << self 4 | def run(files, to: , from:) 5 | rewriters, reverse_rewriters = *Rewriters.rewriters(to) 6 | 7 | files.each do |file| 8 | yaml = File.read(file) 9 | reverse_rewriters.each do |r| 10 | yaml = r.new(yaml, reverse: true).rewrite 11 | end 12 | rewriters.each do |r| 13 | yaml = r.new(yaml).rewrite 14 | end 15 | yaml += added_cops(from: from, to: to) if from 16 | File.write(file, yaml) 17 | end 18 | end 19 | 20 | private 21 | 22 | def added_cops(from:, to:) 23 | yaml = AddedCops.added_cops_yaml(from: from, to: to) 24 | 25 | <<~MESSAGE.rstrip + "\n" 26 | 27 | 28 | # The following cops are added between #{from} and #{to}. 29 | # The configurations are default. 30 | # If you want to use a cop by default, remove a configuration for the cop from here. 31 | # If you want to disable a cop, change `Enabled` to false. 32 | 33 | #{yaml} 34 | MESSAGE 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /mry.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'mry/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "mry" 8 | spec.version = Mry::VERSION 9 | spec.authors = ["Masataka Kuwabara"] 10 | spec.email = ["kuwabara@pocke.me"] 11 | 12 | spec.summary = %q{Mry Migrates .rubocop.yml} 13 | spec.description = <<-EOF 14 | RuboCop has many breaking changes between releases. 15 | This tool migrates your RuboCop config, making updating RuboCop easier. 16 | EOF 17 | spec.homepage = "https://github.com/pocke/mry" 18 | spec.license = 'Apache-2.0' 19 | 20 | spec.files = `git ls-files -z`.split("\x0").reject do |f| 21 | f.match(%r{^(test|spec|features)/}) 22 | end 23 | spec.bindir = "exe" 24 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } 25 | spec.require_paths = ["lib"] 26 | 27 | spec.metadata = { 28 | "changelog_uri" => "https://github.com/pocke/mry/blob/master/CHANGELOG.md", 29 | "source_code_uri" => "https://github.com/pocke/mry", 30 | } 31 | 32 | spec.required_ruby_version = '>= 2.3.0' 33 | 34 | spec.add_runtime_dependency 'rubocop', '>= 0.41.0' 35 | 36 | spec.add_development_dependency "bundler" 37 | spec.add_development_dependency "rake", "~> 13.0" 38 | spec.add_development_dependency 'minitest', '~> 5' 39 | spec.add_development_dependency "minitest-power_assert", "~> 0.2.0" 40 | spec.add_development_dependency "pry" 41 | spec.add_development_dependency 'rubocop', '0.51.0' 42 | spec.add_development_dependency 'meowcop', '1.12.1' 43 | end 44 | -------------------------------------------------------------------------------- /lib/yaml_rewriter/rewriter.rb: -------------------------------------------------------------------------------- 1 | module YAMLRewriter 2 | # Usage: 3 | # class MyRewriter < YAMLRewriter::Rewriter 4 | # define_rule ['foo' => 'bar'] 5 | # define_rule ['one', 'two', 'threeee' => 'three'] 6 | # end 7 | # 8 | # MyRewriter.new('foo: baz').rewrite # => 'bar: baz' 9 | # 10 | # rewriter = MyRewriter.new(<<-END) 11 | # one: 12 | # two: 13 | # threeee: 123 14 | # END 15 | # rewriter.rewrite # => one: 16 | # two: 17 | # three: 123 18 | class Rewriter 19 | using ScalarWithMark 20 | # @param yaml [String] 21 | # @param reverse [true|false] 22 | def initialize(yaml, reverse: false) 23 | @yaml = yaml.dup 24 | @reverse = reverse 25 | @offset = 0 26 | end 27 | 28 | # @param rule [Array] 29 | def self.define_rule(rule) 30 | rules.push(Rule.new(rule)) 31 | end 32 | 33 | def self.rules 34 | @rules ||= [] 35 | end 36 | 37 | # @return [String] 38 | def rewrite 39 | tree = Parser.new.parse(@yaml).handler.root 40 | traverse(tree) 41 | @yaml 42 | end 43 | 44 | private 45 | 46 | def traverse(tree, path = []) 47 | case tree 48 | when Psych::Nodes::Mapping 49 | tree.children.each_slice(2) do |key, value| 50 | p = path + [key.value] 51 | rewrite_yaml(p, key) 52 | traverse(value, p) 53 | end 54 | else 55 | tree.children&.each do |c| 56 | traverse(c, path) 57 | end 58 | end 59 | end 60 | 61 | def rewrite_yaml(path, key) 62 | self.class.rules.each do |rule| 63 | next unless rule.match?(path, reverse: @reverse) 64 | 65 | index = key.mark.index + @offset 66 | prev = key.value 67 | new = rule.replacement(prev, reverse: @reverse) 68 | start_index = @yaml.rindex(prev, index) 69 | @yaml[start_index..(start_index+prev.size-1)] = new 70 | @offset += new.size-prev.size 71 | end 72 | end 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /test/yaml_rewriter/test_rewriter.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class TestRewriter < Minitest::Test 4 | def test_rewriter 5 | [ 6 | [ 7 | [['foo' => 'hello']], 8 | <<~END, 9 | foo: 10 | bar: 11 | hoge 12 | baz: 13 | fuga 14 | END 15 | <<~END, 16 | hello: 17 | bar: 18 | hoge 19 | baz: 20 | fuga 21 | END 22 | ], 23 | [ 24 | [['foo' => 'hello']], 25 | 'foo: hoge', 26 | 'hello: hoge', 27 | ], 28 | [ 29 | [['foo' => 'hello']], 30 | <<~END, 31 | bar: hoge 32 | foo: fuga 33 | baz: piyo 34 | END 35 | <<~END, 36 | bar: hoge 37 | hello: fuga 38 | baz: piyo 39 | END 40 | ], 41 | [ 42 | [['foo', 'bar', 'baz' => 'hello']], 43 | <<~END, 44 | foo: 45 | bar: 46 | baz: 'poyo' 47 | END 48 | <<~END, 49 | foo: 50 | bar: 51 | hello: 'poyo' 52 | END 53 | ], 54 | [ 55 | [ 56 | ['foo', 'bar', 'baz' => 'hello'], 57 | ['foo', 'cat', 'dog' => 'meow'] 58 | ], 59 | <<~END, 60 | foo: 61 | bar: 62 | baz: 'poyo' 63 | cat: 64 | dog: 42 65 | END 66 | <<~END, 67 | foo: 68 | bar: 69 | hello: 'poyo' 70 | cat: 71 | meow: 42 72 | END 73 | ], 74 | [ 75 | [ 76 | ['foo', 'bar', 'baz' => 'hello'], 77 | ['foo', 'cat', 'dog' => 'meow'] 78 | ], 79 | <<~END, 80 | # にゃーん 81 | foo: 82 | bar: 83 | baz: 'poyo' 84 | # にゃん🐱 85 | cat: 86 | dog: 42 87 | END 88 | <<~END, 89 | # にゃーん 90 | foo: 91 | bar: 92 | hello: 'poyo' 93 | # にゃん🐱 94 | cat: 95 | meow: 42 96 | END 97 | ], 98 | [ 99 | [ 100 | ['foo' => 'hello'], 101 | ['bar', 'baz' => 'world'], 102 | ], 103 | <<~END, 104 | { 105 | 'foo': 'hoge', 106 | 'bar': { 107 | 'baz': 'fuga', 108 | } 109 | } 110 | END 111 | <<~END, 112 | { 113 | 'hello': 'hoge', 114 | 'bar': { 115 | 'world': 'fuga', 116 | } 117 | } 118 | END 119 | ], 120 | [ 121 | [ 122 | ['foo' => 'hello'], 123 | ], 124 | <<~END, 125 | foo : bar 126 | END 127 | <<~END, 128 | hello : bar 129 | END 130 | ], 131 | ].each do |rules, src, expected| 132 | klass = Class.new(YAMLRewriter::Rewriter) do 133 | rules.each do |rule| 134 | define_rule rule 135 | end 136 | end 137 | rewrited = klass.new(src).rewrite 138 | assert { rewrited == expected } 139 | 140 | reversed_rewrited = klass.new(src, reverse: true).rewrite 141 | assert { reversed_rewrited == src } 142 | end 143 | end 144 | 145 | def test_rewriter_with_reverse 146 | klass = Class.new(YAMLRewriter::Rewriter) do 147 | define_rule ['foo', 'bar' => 'baz'] 148 | define_rule ['hello' => 'world'] 149 | end 150 | 151 | src = <<~END 152 | foo: 153 | baz: 42 154 | world: 155 | foo: 156 | baz: 424242 157 | END 158 | 159 | expected = <<~END 160 | foo: 161 | bar: 42 162 | hello: 163 | foo: 164 | bar: 424242 165 | END 166 | 167 | rewrited = klass.new(src, reverse: true).rewrite 168 | assert { rewrited == expected } 169 | end 170 | end 171 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mry 2 | 3 | Mry Migrates .Rubocop.Yml :muscle: 4 | 5 | 6 | RuboCop has many many breaking changes, because it is before version 1.0. 7 | So, if you update your RuboCop version, .rubocop.yml breaks in many cases... 8 | This tool supports migrating `.rubocop.yml`. It automatically renames the configuration in your `.rubocop.yml` that was renamed by the updated RuboCop version. So, with this tool, you do not have to be afraid of updating RuboCop anymore! 9 | 10 | ## Installation 11 | 12 | Add this line to your application's Gemfile: 13 | 14 | ```ruby 15 | gem 'mry' 16 | ``` 17 | 18 | And then execute: 19 | 20 | $ bundle 21 | 22 | Or install it yourself as: 23 | 24 | $ gem install mry 25 | 26 | ## Usage 27 | 28 | Update `.rubocop.yml` to latest release: 29 | 30 | ```bash 31 | $ mry .rubocop.yml 32 | ``` 33 | 34 | Update `.rubocop.yml` to a specified version: 35 | 36 | ```bash 37 | $ mry --target=0.51.0 .rubocop.yml 38 | ``` 39 | 40 | And you can specify the current RuboCop version. 41 | If you specify a new RuboCop version, mry adds cops that were added in this new RuboCop version to your `.rubocop.yml`. 42 | With this feature, you can check new RuboCop cops with mry. 43 | 44 | ```bash 45 | $ mry --from=0.50.0 --target=0.51.0 .rubocop.yml 46 | $ cat .rubocop.yml 47 | ... 48 | 49 | 50 | # The following cops are added between 0.50.0 and 0.51.0. 51 | # The configurations are default. 52 | # If you want to use a cop by default, remove a configuration for the cop from here. 53 | # If you want to disable a cop, change `Enabled` to false. 54 | 55 | # Supports --auto-correct 56 | Gemspec/OrderedDependencies: 57 | Description: Dependencies in the gemspec should be alphabetically sorted. 58 | Enabled: true 59 | Include: 60 | - "**/*.gemspec" 61 | TreatCommentsAsGroupSeparators: true 62 | 63 | # Supports --auto-correct 64 | Lint/RedundantWithObject: 65 | Description: Checks for redundant `with_object`. 66 | Enabled: true 67 | 68 | ... 69 | ``` 70 | 71 | ### Example 72 | 73 | 74 | ![Example Animation](https://cloud.githubusercontent.com/assets/4361134/25322816/8188f21a-28f5-11e7-9915-93f72034e3ea.gif) 75 | 76 | ## Development 77 | 78 | ### How to support new version RuboCop 79 | 80 | Run `bin/check_rubocop_update` script (depend on Ruby 2.6 or higher). 81 | This script displays renamed, added and deleted cop names. 82 | 83 | ```bash 84 | # Clone rubocop repository if it does not exist. 85 | $ git clone https://github.com/rubocop-hq/rubocop/ ~/path/to/rubocop/ 86 | $ bin/check_rubocop_update v0.55.0 v0.56.0 ~/path/to/rubocop/ 87 | 88 | (...log...) 89 | 90 | :added: 91 | - Lint/SplatKeywordArguments 92 | - Performance/InefficientHashSearch 93 | - Lint/ErbNewArguments 94 | - Rails/AssertNot 95 | - Rails/RefuteMethods 96 | :renamed: 97 | - :before: 98 | - Style/EmptyLineAfterGuardClause 99 | :after: 100 | - Layout/EmptyLineAfterGuardClause 101 | - :before: 102 | - Style/MethodMissing 103 | :after: 104 | - Style/MethodMissingSuper 105 | - Style/MissingRespondToMissing 106 | :deleted: [] 107 | ``` 108 | 109 | Update `lib/mry/added_cops.rb` and `lib/mry/rewriters.rb` with this result. 110 | 111 | Note: Mry does not support deleted cops and split cops. See [#37](https://github.com/pocke/mry/issues/37) and [#38](https://github.com/pocke/mry/issues/38). 112 | 113 | ## Contributing 114 | 115 | Bug reports and pull requests are welcome on GitHub at https://github.com/pocke/mry. 116 | 117 | ## License 118 | 119 | Copyright 2017-2018 Masataka Pocke Kuwabara 120 | 121 | Licensed under the Apache License, Version 2.0 (the "License"); 122 | you may not use this file except in compliance with the License. 123 | You may obtain a copy of the License at 124 | 125 | http://www.apache.org/licenses/LICENSE-2.0 126 | 127 | Unless required by applicable law or agreed to in writing, software 128 | distributed under the License is distributed on an "AS IS" BASIS, 129 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130 | See the License for the specific language governing permissions and 131 | limitations under the License. 132 | -------------------------------------------------------------------------------- /test/mry/test_added_cops.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | require 'yaml' 3 | 4 | class TestAddedCops < Minitest::Test 5 | def test_added_cops 6 | cops = Mry::AddedCops.added_cops( 7 | from: Gem::Version.new('0.50.0'), 8 | to: Gem::Version.new('0.51.0') 9 | ) 10 | 11 | assert_equal %w[ 12 | Rails/UnknownEnv 13 | Style/StderrPuts 14 | Lint/UnneededRequireStatement 15 | Lint/RedundantWithObject 16 | Style/CommentedKeyword 17 | Lint/RegexpAsCondition 18 | Style/MixinUsage 19 | Style/DateTime 20 | Gemspec/OrderedDependencies 21 | ], cops 22 | 23 | cops = Mry::AddedCops.added_cops( 24 | from: Gem::Version.new('0.49.0'), 25 | to: Gem::Version.new('0.50.0') 26 | ) 27 | 28 | assert_equal %w[ 29 | Style/RedundantConditional 30 | Naming/HeredocDelimiterNaming 31 | Lint/ReturnInVoidContext 32 | Lint/BooleanSymbol 33 | Rails/HasManyOrHasOneDependent 34 | Style/Dir 35 | Naming/HeredocDelimiterCase 36 | Lint/RescueWithoutErrorClass 37 | Performance/UnfreezeString 38 | Style/OrAssignment 39 | Style/ReturnNil 40 | Lint/UriEscapeUnescape 41 | Performance/UriDefaultParser 42 | Lint/UriRegexp 43 | Style/MinMax 44 | Bundler/InsecureProtocolSource 45 | Lint/RedundantWithIndex 46 | Lint/InterpolationCheck 47 | ], cops 48 | 49 | cops = Mry::AddedCops.added_cops( 50 | from: Gem::Version.new('0.47.0'), 51 | to: Gem::Version.new('0.49.0') 52 | ) 53 | 54 | assert_equal %w[ 55 | Rails/ApplicationJob 56 | Rails/ApplicationRecord 57 | Performance/Caller 58 | Style/FormatStringToken 59 | Lint/ScriptPermission 60 | Style/YodaCondition 61 | Style/MultipleComparison 62 | Lint/RescueType 63 | Performance/DoubleStartEndWith 64 | Layout/EmptyLineAfterMagicComment 65 | Style/MixinGrouping 66 | Layout/EmptyLinesAroundBeginBody 67 | Layout/EmptyLinesAroundExceptionHandlingKeywords 68 | Rails/RelativeDateConstant 69 | Layout/IndentHeredoc 70 | Style/InverseMethods 71 | Rails/ActiveSupportAliases 72 | Lint/AmbiguousBlockAssociation 73 | Rails/Blank 74 | Rails/Present 75 | ], cops 76 | end 77 | 78 | def test_added_cops_yaml 79 | yaml = Mry::AddedCops.added_cops_yaml( 80 | from: Gem::Version.new('0.50.0'), 81 | to: Gem::Version.new('0.51.0'), 82 | ) 83 | 84 | assert_equal <<~YAML, yaml 85 | # Supports --auto-correct 86 | Gemspec/OrderedDependencies: 87 | Description: Dependencies in the gemspec should be alphabetically sorted. 88 | Enabled: true 89 | Include: 90 | - "**/*.gemspec" 91 | TreatCommentsAsGroupSeparators: true 92 | 93 | # Supports --auto-correct 94 | Lint/RedundantWithObject: 95 | Description: Checks for redundant `with_object`. 96 | Enabled: true 97 | 98 | Lint/RegexpAsCondition: 99 | Description: Do not use regexp literal as a condition. The regexp literal matches 100 | `$_` implicitly. 101 | Enabled: true 102 | 103 | # Supports --auto-correct 104 | Lint/UnneededRequireStatement: 105 | Description: Checks for unnecessary `require` statement. 106 | Enabled: true 107 | 108 | Rails/UnknownEnv: 109 | Description: Use correct environment name. 110 | Enabled: true 111 | Environments: 112 | - development 113 | - test 114 | - production 115 | 116 | Style/CommentedKeyword: 117 | Description: Do not place comments on the same line as certain keywords. 118 | Enabled: true 119 | 120 | Style/DateTime: 121 | Description: Use Date or Time over DateTime. 122 | StyleGuide: "#date--time" 123 | Enabled: true 124 | 125 | Style/MixinUsage: 126 | Description: Checks that `include`, `extend` and `prepend` exists at the top level. 127 | Enabled: true 128 | 129 | # Supports --auto-correct 130 | Style/StderrPuts: 131 | Description: Use `warn` instead of `$stderr.puts`. 132 | StyleGuide: "#warn" 133 | Enabled: true 134 | 135 | YAML 136 | end 137 | end 138 | -------------------------------------------------------------------------------- /bin/check_rubocop_update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # Usage: bin/check_rubocop_update v0.52.1 v0.53.0 ~/path/to/rubocop/ 4 | 5 | require 'open3' 6 | require 'yaml' 7 | require 'tmpdir' 8 | require 'etc' 9 | 10 | def debug_print(mes) 11 | $stdout.puts mes 12 | end 13 | 14 | def sh!(*cmd, **opt) 15 | debug_print 'sh!: ' + cmd.join(' ') 16 | system(*cmd, opt.merge(exception: true)) 17 | end 18 | 19 | def capture3!(*cmd, **opt) 20 | debug_print 'capture3!: ' + cmd.join(' ') 21 | Open3.capture3(*cmd, **opt).tap do |out, err, status| 22 | raise "#{out} #{err}" unless status.success? 23 | end 24 | end 25 | 26 | def each_commit(before, after, &block) 27 | return enum_for(__method__, before, after) unless block_given? 28 | 29 | commits = capture3!('git', 'log', "#{before}..#{after}", '--format=tformat:%H').yield_self do |stdout, _stderr, _status| 30 | stdout.each_line.map(&:chomp) 31 | end 32 | commits.each do |commit| 33 | block.call commit 34 | end 35 | end 36 | 37 | def has_gemfile_change?(commit, repo) 38 | capture3!('git', 'show', '--name-only', '--format=tformat:', commit, chdir: repo).yield_self do |stdout, _stderr, _status| 39 | stdout.each_line.any? do |fname| 40 | fname.chomp! 41 | fname == 'Gemfile' || fname == 'rubocop.gemspec' 42 | end 43 | end 44 | end 45 | 46 | def chtmpdir(&block) 47 | Dir.mktmpdir do |dir| 48 | Dir.chdir(dir) do 49 | block.call 50 | end 51 | end 52 | end 53 | 54 | def with_repositories(remote, &block) 55 | if File.directory?(remote) 56 | Dir.chdir(remote) do 57 | sh! 'git', 'fetch', 'origin' 58 | end 59 | end 60 | 61 | chtmpdir do 62 | repos = Array.new(Etc.nprocessors*2) do |idx| 63 | sh! 'git', 'clone', remote, idx.to_s 64 | File.join(Dir.pwd, idx.to_s) 65 | end 66 | block.call(repos) 67 | end 68 | end 69 | 70 | def cops_each_commit(before, after, remote) 71 | with_repositories(remote) do |repos| 72 | q = Thread::Queue.new 73 | [].tap do |result| 74 | Dir.chdir(repos.first) do 75 | each_commit(before + '~', after).each.with_index do |commit, idx| 76 | q << [commit, idx] 77 | end 78 | end 79 | q.close 80 | repos.map do |repo| 81 | Thread.new do 82 | while v = q.pop 83 | commit, idx = *v 84 | sh! 'rm', '-f', 'Gemfile.lock', chdir: repo if File.exist?(File.join repo, 'Gemfile.lock') 85 | if has_gemfile_change?(commit, repo) 86 | begin 87 | sh! 'bundle', 'install', '--local', chdir: repo 88 | rescue RuntimeError 89 | sh! 'bundle', 'install', chdir: repo 90 | end 91 | end 92 | sh! 'git', 'checkout', commit, chdir: repo 93 | rubocop_path = 94 | if File.exist?(File.join(repo, 'bin/rubocop')) 95 | 'bin/rubocop' 96 | else 97 | 'exe/rubocop' 98 | end 99 | capture3!(rubocop_path, '--show-cops', '--force-default-config', chdir: repo).tap do |stdout, _, _| 100 | result << [idx, YAML.load(stdout)] 101 | end 102 | end 103 | end 104 | end.each(&:join) 105 | end.sort_by(&:first).map{|_, v| v} 106 | end 107 | end 108 | 109 | def main(before, after, remote) 110 | {}.tap do |result| 111 | result[:added] = [] 112 | result[:renamed] = [] 113 | result[:deleted] = [] 114 | 115 | cops = cops_each_commit(before, after, remote) 116 | cops.each_cons(2) do |new, old| 117 | added = new.keys - old.keys 118 | removed = old.keys - new.keys 119 | if added.size > removed.size && removed.size == 0 120 | result[:added].concat added 121 | elsif added.size < removed.size && added.size == 0 122 | result[:deleted].concat removed 123 | elsif added.size != 0 && removed.size != 0 124 | result[:renamed] << {before: removed, after: added} 125 | end 126 | end 127 | end 128 | end 129 | 130 | before = ARGV[0] || raise 131 | after = ARGV[1] || raise 132 | remote = ARGV[2] || raise 133 | 134 | out = main(before, after, remote) 135 | res = YAML.dump(out) 136 | puts res 137 | fname = '/tmp/mry_check_rubocop_update_log.yaml' 138 | File.write(fname, res) 139 | puts "Wrote: #{fname}" 140 | -------------------------------------------------------------------------------- /test/mry/test_runner.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class TestRunner < Minitest::Test 4 | def test_run_with_master 5 | prev = <<~END 6 | # master 7 | Style/VariableName: 8 | Enabled: true 9 | 10 | # 0.49.0 11 | Style/Tab: 12 | Enabled: true 13 | 14 | # 0.47.0 15 | Lint/Eval: 16 | Enabled: true 17 | 18 | # 0.46.0 19 | Performance/SortWithBlock: 20 | Enabled: false 21 | END 22 | expected = <<~END 23 | # master 24 | Naming/VariableName: 25 | Enabled: true 26 | 27 | # 0.49.0 28 | Layout/Tab: 29 | Enabled: true 30 | 31 | # 0.47.0 32 | Security/Eval: 33 | Enabled: true 34 | 35 | # 0.46.0 36 | Performance/CompareWithBlock: 37 | Enabled: false 38 | END 39 | 40 | check_run(prev, expected, :master) 41 | end 42 | 43 | def test_run_with_0_77_0 44 | prev = <<~END 45 | Bundler/GemComment: 46 | Whitelist: [] 47 | END 48 | 49 | expected = <<~END 50 | Bundler/GemComment: 51 | IgnoredGems: [] 52 | END 53 | 54 | check_run(prev, expected, '0.77.0') 55 | end 56 | 57 | def test_run_with_0_47_0 58 | prev = <<~END 59 | # master 60 | Style/Tab: 61 | Enabled: true 62 | 63 | # 0.47.0 64 | Lint/Eval: 65 | Enabled: true 66 | Style/CaseIndentation: 67 | IndentWhenRelativeTo: case 68 | Lint/BlockAlignment: 69 | AlignWith: either 70 | Lint/EndAlignment: 71 | AlignWith: either 72 | Lint/DefEndAlignment: 73 | AlignWith: either 74 | Rails/UniqBeforePluck: 75 | EnforcedMode: conservative 76 | Style/MethodCallParentheses: 77 | Enabled: false 78 | 79 | # 0.46.0 80 | Performance/SortWithBlock: 81 | Enabled: false 82 | END 83 | expected = <<~END 84 | # master 85 | Style/Tab: 86 | Enabled: true 87 | 88 | # 0.47.0 89 | Security/Eval: 90 | Enabled: true 91 | Style/CaseIndentation: 92 | EnforcedStyle: case 93 | Lint/BlockAlignment: 94 | EnforcedStyleAlignWith: either 95 | Lint/EndAlignment: 96 | EnforcedStyleAlignWith: either 97 | Lint/DefEndAlignment: 98 | EnforcedStyleAlignWith: either 99 | Rails/UniqBeforePluck: 100 | EnforcedStyle: conservative 101 | Style/MethodCallWithoutArgsParentheses: 102 | Enabled: false 103 | 104 | # 0.46.0 105 | Performance/CompareWithBlock: 106 | Enabled: false 107 | END 108 | 109 | check_run(prev, expected, '0.47.0') 110 | end 111 | 112 | def test_run_with_0_46_0 113 | prev = <<~END 114 | # 0.47.0 115 | Lint/Eval: 116 | Enabled: true 117 | Style/CaseIndentation: 118 | EnforcedStyle: case 119 | Style/MethodCallWithoutArgsParentheses: 120 | Description: 'Do not use parentheses for method calls with no arguments.' 121 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-args-no-parens' 122 | Enabled: false 123 | 124 | # 0.46.0 125 | Performance/SortWithBlock: 126 | Enabled: false 127 | END 128 | expected = <<~END 129 | # 0.47.0 130 | Lint/Eval: 131 | Enabled: true 132 | Style/CaseIndentation: 133 | IndentWhenRelativeTo: case 134 | Style/MethodCallParentheses: 135 | Description: 'Do not use parentheses for method calls with no arguments.' 136 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-args-no-parens' 137 | Enabled: false 138 | 139 | # 0.46.0 140 | Performance/CompareWithBlock: 141 | Enabled: false 142 | END 143 | 144 | check_run(prev, expected, '0.46.0') 145 | end 146 | 147 | def test_run_older 148 | prev = <<~END 149 | # 0.47.0 150 | Lint/Eval: 151 | Enabled: true 152 | 153 | # 0.46.0 154 | Performance/SortWithBlock: 155 | Enabled: false 156 | 157 | # Older 158 | Style/SingleSpaceBeforeFirstArg: 159 | Enabled: false 160 | Style/SpaceAroundOperators: 161 | MultiSpaceAllowedForOperators: true 162 | END 163 | expected = <<~END 164 | # 0.47.0 165 | Lint/Eval: 166 | Enabled: true 167 | 168 | # 0.46.0 169 | Performance/SortWithBlock: 170 | Enabled: false 171 | 172 | # Older 173 | Style/SpaceBeforeFirstArg: 174 | Enabled: false 175 | Style/SpaceAroundOperators: 176 | AllowForAlignment: true 177 | END 178 | 179 | check_run(prev, expected, '0') 180 | end 181 | 182 | def test_run_without_target_option 183 | prev = <<~END 184 | # 0.49.0 185 | Style/Tab: 186 | Enabled: true 187 | 188 | # 0.47.0 189 | Lint/Eval: 190 | Enabled: true 191 | Lint/BlockAlignment: 192 | AlignWith: either 193 | Lint/EndAlignment: 194 | AlignWith: either 195 | Lint/DefEndAlignment: 196 | AlignWith: either 197 | Rails/UniqBeforePluck: 198 | EnforcedMode: conservative 199 | Style/MethodCallParentheses: 200 | Enabled: false 201 | 202 | # 0.46.0 203 | Performance/SortWithBlock: 204 | Enabled: false 205 | END 206 | expected = <<~END 207 | # 0.49.0 208 | Layout/Tab: 209 | Enabled: true 210 | 211 | # 0.47.0 212 | Security/Eval: 213 | Enabled: true 214 | Layout/BlockAlignment: 215 | EnforcedStyleAlignWith: either 216 | Layout/EndAlignment: 217 | EnforcedStyleAlignWith: either 218 | Layout/DefEndAlignment: 219 | EnforcedStyleAlignWith: either 220 | Rails/UniqBeforePluck: 221 | EnforcedStyle: conservative 222 | Style/MethodCallWithoutArgsParentheses: 223 | Enabled: false 224 | 225 | # 0.46.0 226 | Performance/CompareWithBlock: 227 | Enabled: false 228 | END 229 | 230 | check_run(prev, expected, nil) 231 | end 232 | 233 | def test_run_with_from_option 234 | prev = <<~YAML 235 | # Renamed 236 | Lint/LiteralInCondition: 237 | Enabled: false 238 | YAML 239 | 240 | expected = <<~YAML 241 | # Renamed 242 | Lint/LiteralAsCondition: 243 | Enabled: false 244 | 245 | 246 | # The following cops are added between 0.50.0 and 0.51.0. 247 | # The configurations are default. 248 | # If you want to use a cop by default, remove a configuration for the cop from here. 249 | # If you want to disable a cop, change `Enabled` to false. 250 | 251 | # Supports --auto-correct 252 | Gemspec/OrderedDependencies: 253 | Description: Dependencies in the gemspec should be alphabetically sorted. 254 | Enabled: true 255 | Include: 256 | - "**/*.gemspec" 257 | TreatCommentsAsGroupSeparators: true 258 | 259 | # Supports --auto-correct 260 | Lint/RedundantWithObject: 261 | Description: Checks for redundant `with_object`. 262 | Enabled: true 263 | 264 | Lint/RegexpAsCondition: 265 | Description: Do not use regexp literal as a condition. The regexp literal matches 266 | `$_` implicitly. 267 | Enabled: true 268 | 269 | # Supports --auto-correct 270 | Lint/UnneededRequireStatement: 271 | Description: Checks for unnecessary `require` statement. 272 | Enabled: true 273 | 274 | Rails/UnknownEnv: 275 | Description: Use correct environment name. 276 | Enabled: true 277 | Environments: 278 | - development 279 | - test 280 | - production 281 | 282 | Style/CommentedKeyword: 283 | Description: Do not place comments on the same line as certain keywords. 284 | Enabled: true 285 | 286 | Style/DateTime: 287 | Description: Use Date or Time over DateTime. 288 | StyleGuide: "#date--time" 289 | Enabled: true 290 | 291 | Style/MixinUsage: 292 | Description: Checks that `include`, `extend` and `prepend` exists at the top level. 293 | Enabled: true 294 | 295 | # Supports --auto-correct 296 | Style/StderrPuts: 297 | Description: Use `warn` instead of `$stderr.puts`. 298 | StyleGuide: "#warn" 299 | Enabled: true 300 | YAML 301 | check_run(prev, expected, '0.51.0', from: '0.50.0') 302 | end 303 | 304 | def check_run(prev, expected, version, from: nil) 305 | # Check runner 306 | Tempfile.open do |file| 307 | file.write(prev) 308 | file.close 309 | v = 310 | case version 311 | when nil 312 | Gem::Version.new('1000000') 313 | when Symbol 314 | version 315 | else 316 | Gem::Version.new(version) 317 | end 318 | from_v = Gem::Version.new(from) if from 319 | 320 | Mry::Runner.run([file.path], to: v, from: from_v) 321 | got = File.read(file.path) 322 | assert_equal expected, got 323 | end 324 | 325 | # Check `mry` command 326 | Tempfile.open do |file| 327 | file.write(prev) 328 | file.close 329 | args = [ 330 | (['--target', version.to_s] if version), 331 | (['--from', from] if from), 332 | ].flatten.compact 333 | system('ruby', Pathname(__dir__).join('../../exe/mry').to_s, *args, file.path) || raise 334 | got = File.read(file.path) 335 | assert {expected == got} 336 | end 337 | end 338 | end 339 | -------------------------------------------------------------------------------- /lib/mry/added_cops.rb: -------------------------------------------------------------------------------- 1 | module Mry 2 | # TODO: Replace this list with VersionAdded 3 | module AddedCops 4 | Cops = { 5 | Gem::Version.new('0.78.0') => %w[ 6 | Lint/NonDeterministicRequireOrder 7 | ], 8 | Gem::Version.new('0.77.0') => %w[], 9 | Gem::Version.new('0.76.0') => %w[], 10 | Gem::Version.new('0.75.0') => %w[ 11 | Migration/DepartmentName 12 | Lint/SendWithMixinArgument 13 | ], 14 | Gem::Version.new('0.74.0') => %w[], 15 | Gem::Version.new('0.73.0') => %w[ 16 | Style/DoubleCopDisableDirective 17 | Style/MultilineWhenThen 18 | ], 19 | Gem::Version.new('0.72.0') => %w[ 20 | Style/FloatDivision 21 | Gemspec/RubyVersionGlobalsUsage 22 | ], 23 | Gem::Version.new('0.71.0') => %w[], 24 | Gem::Version.new('0.70.0') => %w[], 25 | Gem::Version.new('0.69.0') => %w[ 26 | Style/NegatedUnless 27 | ], 28 | Gem::Version.new('0.68.0') => %w[ 29 | Layout/HeredocArgumentClosingParenthesis 30 | Layout/IndentFirstParameter 31 | Lint/HeredocMethodCallPosition 32 | ], 33 | Gem::Version.new('0.67.0') => %w[ 34 | Naming/RescuedExceptionsVariableName 35 | Layout/MultilineArrayLineBreaks 36 | Layout/MultilineHashKeyLineBreaks 37 | Layout/MultilineMethodArgumentLineBreaks 38 | Rails/ActiveRecordOverride 39 | Rails/RedundantAllowNil 40 | ], 41 | Gem::Version.new('0.66.0') => %w[ 42 | Lint/SafeNavigationWithEmpty 43 | Lint/ToJSON 44 | Style/ConstantVisibility 45 | ], 46 | Gem::Version.new('0.65.0') => %w[], 47 | Gem::Version.new('0.64.0') => %w[ 48 | Rails/ReflectionClassName 49 | ], 50 | Gem::Version.new('0.63.0') => %w[ 51 | Rails/IgnoredSkipActionFilterOption 52 | Rails/BelongsTo 53 | ], 54 | Gem::Version.new('0.62.0') => %w[ 55 | Rails/LinkToBlank 56 | Lint/DisjunctiveAssignmentInConstructor 57 | ], 58 | Gem::Version.new('0.61.0') => %w[ 59 | Performance/OpenStruct 60 | ], 61 | Gem::Version.new('0.60.0') => %w[], 62 | Gem::Version.new('0.59.0') => %w[ 63 | Performance/ChainArrayAllocation 64 | Style/MultilineMethodSignature 65 | Bundler/GemComment 66 | ], 67 | Gem::Version.new('0.58.0') => %w[ 68 | Style/IpAddresses 69 | ], 70 | Gem::Version.new('0.57.0') => %w[ 71 | Layout/LeadingBlankLines 72 | Rails/BulkChangeTable 73 | Layout/ClosingHeredocIndentation 74 | Style/UnneededCondition 75 | Style/AccessModifierDeclarations 76 | ], 77 | Gem::Version.new('0.56.0') => %w[ 78 | Lint/SplatKeywordArguments 79 | Performance/InefficientHashSearch 80 | Lint/ErbNewArguments 81 | Rails/AssertNot 82 | Rails/RefuteMethods 83 | ], 84 | Gem::Version.new('0.55.0') => %w[ 85 | Performance/UnneededSort 86 | Lint/SafeNavigationConsistency 87 | ], 88 | Gem::Version.new('0.54.0') => %w[ 89 | Style/UnpackFirst 90 | ], 91 | Gem::Version.new('0.53.0') => %w[ 92 | Rails/ActiveRecordAliases 93 | Style/EmptyLineAfterGuardClause 94 | Naming/MemoizedInstanceVariableName 95 | Style/ExpandPathArguments 96 | Lint/OrderedMagicComments 97 | Layout/EmptyComment 98 | Style/TrailingBodyOnModule 99 | Style/TrailingBodyOnClass 100 | Lint/NumberConversion 101 | Lint/UnneededCopEnableDirective 102 | Naming/UncommunicativeBlockParamName 103 | Naming/UncommunicativeMethodArgName 104 | Security/Open 105 | Lint/BigDecimalNew 106 | ], 107 | Gem::Version.new('0.52.0') => %w[ 108 | Style/StringHashKeys 109 | Style/RandomWithOffset 110 | Lint/ShadowedArgument 111 | Lint/MissingCopEnableDirective 112 | Rails/EnvironmentComparison 113 | Style/EmptyBlockParameter 114 | Style/EmptyLambdaParameter 115 | Style/TrailingBodyOnMethodDefinition 116 | Rails/InverseOf 117 | Style/TrailingMethodEndStatement 118 | Gemspec/RequiredRubyVersion 119 | Lint/NestedPercentLiteral 120 | Gemspec/DuplicatedAssignment 121 | Style/ColonMethodDefinition 122 | Layout/ClassStructure 123 | Rails/CreateTableWithTimestamps 124 | Rails/RedundantReceiverInWithOptions 125 | Style/EvalWithLocation 126 | Layout/EmptyLinesAroundArguments 127 | Layout/SpaceInsideReferenceBrackets 128 | Layout/SpaceInsideArrayLiteralBrackets 129 | Rails/LexicallyScopedActionFilter 130 | Rails/Presence 131 | ], 132 | Gem::Version.new('0.51.0') => %w[ 133 | Rails/UnknownEnv 134 | Style/StderrPuts 135 | Lint/UnneededRequireStatement 136 | Lint/RedundantWithObject 137 | Style/CommentedKeyword 138 | Lint/RegexpAsCondition 139 | Style/MixinUsage 140 | Style/DateTime 141 | Gemspec/OrderedDependencies 142 | ], 143 | Gem::Version.new('0.50.0') => %w[ 144 | Style/RedundantConditional 145 | Naming/HeredocDelimiterNaming 146 | Lint/ReturnInVoidContext 147 | Lint/BooleanSymbol 148 | Rails/HasManyOrHasOneDependent 149 | Style/Dir 150 | Naming/HeredocDelimiterCase 151 | Lint/RescueWithoutErrorClass 152 | Performance/UnfreezeString 153 | Style/OrAssignment 154 | Style/ReturnNil 155 | Lint/UriEscapeUnescape 156 | Performance/UriDefaultParser 157 | Lint/UriRegexp 158 | Style/MinMax 159 | Bundler/InsecureProtocolSource 160 | Lint/RedundantWithIndex 161 | Lint/InterpolationCheck 162 | ], 163 | Gem::Version.new('0.49.0') => %w[ 164 | Rails/ApplicationJob 165 | Rails/ApplicationRecord 166 | Performance/Caller 167 | Style/FormatStringToken 168 | Lint/ScriptPermission 169 | Style/YodaCondition 170 | Style/MultipleComparison 171 | Lint/RescueType 172 | ], 173 | Gem::Version.new('0.48.0') => %w[ 174 | Performance/DoubleStartEndWith 175 | Style/EmptyLineAfterMagicComment 176 | Style/MixinGrouping 177 | Style/EmptyLinesAroundBeginBody 178 | Style/EmptyLinesAroundExceptionHandlingKeywords 179 | Rails/RelativeDateConstant 180 | Style/IndentHeredoc 181 | Style/InverseMethods 182 | Rails/ActiveSupportAliases 183 | Lint/AmbiguousBlockAssociation 184 | Rails/Blank 185 | Rails/Present 186 | ], 187 | Gem::Version.new('0.47.0') => %w[ 188 | Lint/MultipleCompare 189 | Lint/SafeNavigationChain 190 | Security/MarshalLoad 191 | Security/YAMLLoad 192 | Performance/RegexpMatch 193 | Rails/FilePath 194 | Rails/SkipsModelValidations 195 | Style/MethodCallWithArgsParentheses 196 | Rails/ReversibleMigration 197 | ], 198 | Gem::Version.new('0.46.0') => %w[ 199 | Bundler/DuplicatedGem 200 | Style/EmptyMethod 201 | Rails/EnumUniqueness 202 | Bundler/OrderedGems 203 | ], 204 | Gem::Version.new('0.45.0') => %w[ 205 | Lint/DuplicateCaseCondition 206 | Lint/EmptyWhen 207 | Style/MultilineIfModifier 208 | Style/SpaceInLambdaLiteral 209 | Lint/EmptyExpression 210 | ], 211 | Gem::Version.new('0.44.0') => %w[ 212 | Rails/HttpPositionalArguments 213 | Metrics/BlockLength 214 | Rails/DynamicFindBy 215 | Rails/DelegateAllowBlank 216 | Style/MultilineMemoization 217 | ], 218 | Gem::Version.new('0.43.0') => %w[ 219 | Style/DocumentationMethod 220 | Rails/SafeNavigation 221 | Rails/NotNullColumn 222 | Style/VariableNumber 223 | Security/JSONLoad 224 | Style/SafeNavigation 225 | Performance/SortWithBlock 226 | Lint/UnifiedInteger 227 | ], 228 | Gem::Version.new('0.42.0') => %w[ 229 | Style/TernaryParentheses 230 | Style/MethodMissing 231 | Rails/SaveBang 232 | Style/NumericPredicate 233 | ], 234 | Gem::Version.new('0.41.0') => %w[ 235 | Style/SpaceInsidePercentLiteralDelimiters 236 | Style/SpaceInsideArrayPercentLiteral 237 | Style/NumericLiteralPrefix 238 | Style/ImplicitRuntimeError 239 | Style/EachForSimpleLoop 240 | Lint/ShadowedException 241 | Lint/PercentSymbolArray 242 | Lint/PercentStringArray 243 | Lint/InheritException 244 | Performance/PushSplat 245 | Rails/RequestReferer 246 | Rails/OutputSafety 247 | Rails/Exit 248 | ], 249 | }.freeze 250 | 251 | class RuboCopVersionMismatchError < StandardError 252 | def initialize(expected:) 253 | @expected = expected 254 | end 255 | 256 | def message 257 | <<~MES 258 | 259 | `require 'rubocop'` is failed because mry can't find rubocop v#{@expected}. 260 | Execute `gem install rubocop -v #{@expected}`. 261 | Or update rubocop version in your Gemfile, and execute `bundle install` if you use `bundle exec`. 262 | 263 | MES 264 | end 265 | end 266 | 267 | class << self 268 | def added_cops_yaml(from:, to:) 269 | begin 270 | gem 'rubocop', "= #{to}" 271 | require 'rubocop' 272 | rescue Gem::MissingSpecVersionError, Gem::LoadError 273 | raise RuboCopVersionMismatchError.new(expected: to) 274 | end 275 | cops = added_cops(from: from, to: to) 276 | return if cops.empty? 277 | 278 | in_tmpdir do |dir| 279 | dir.join('.rubocop.yml').write(<<~YAML) 280 | Rails: 281 | Enabled: true 282 | YAML 283 | stdout do 284 | RuboCop::CLI.new.run(['--show-cops', cops.join(',')]) 285 | end 286 | end 287 | end 288 | 289 | def added_cops(from:, to:) 290 | range = from..to 291 | Cops 292 | .flat_map {|key, cops| range.cover?(key) && from != key ? cops : [] } 293 | .map {|cop| update_name(cop: cop, to: to) } 294 | end 295 | 296 | private 297 | 298 | def update_name(cop:, to:) 299 | rewriters, reverse_rewriters = *Rewriters.rewriters(to) 300 | reverse_rewriters.each do |rew| 301 | rew.rules.each do |rule| 302 | cop = rule.replacement(cop, reverse: true) if rule.match?([cop], reverse: true) 303 | end 304 | end 305 | rewriters.each do |rew| 306 | rew.rules.each do |rule| 307 | cop = rule.replacement(cop, reverse: false) if rule.match?([cop], reverse: false) 308 | end 309 | end 310 | 311 | cop 312 | end 313 | 314 | def stdout(&block) 315 | stdout_back = $stdout 316 | $stdout = StringIO.new 317 | block.call 318 | $stdout.string 319 | ensure 320 | $stdout = stdout_back 321 | end 322 | 323 | def in_tmpdir(&block) 324 | Dir.mktmpdir do |dir| 325 | Dir.chdir(dir) do 326 | block.call(Pathname(dir)) 327 | end 328 | end 329 | end 330 | end 331 | end 332 | end 333 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2017-2018 Masataka Pocke Kuwabara 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /lib/mry/rewriters.rb: -------------------------------------------------------------------------------- 1 | module Mry 2 | module Rewriters 3 | class Rewriter_Master < YAMLRewriter::Rewriter 4 | end 5 | 6 | class Rewriter_0_78_0 < YAMLRewriter::Rewriter 7 | define_rule ['Metrics/LineLength' => 'Layout/LineLength'] 8 | end 9 | 10 | class Rewriter_0_77_0 < YAMLRewriter::Rewriter 11 | define_rule ['Naming/UncommunicativeMethodParamName' => 'Naming/MethodParameterName'] 12 | define_rule ['Naming/UncommunicativeBlockParamName' => 'Naming/BlockParameterName'] 13 | define_rule ['Lint/StringConversionInInterpolation' => 'Lint/RedundantStringCoercion'] 14 | define_rule ['Lint/MultipleCompare' => 'Lint/MultipleComparison'] 15 | define_rule ['Lint/HandleExceptions' => 'Lint/SuppressedException'] 16 | define_rule ['Lint/DuplicatedKey' => 'Lint/DuplicateHashKey'] 17 | define_rule ['Layout/TrailingBlankLines' => 'Layout/TrailingEmptyLines'] 18 | define_rule ['Layout/LeadingBlankLines' => 'Layout/LeadingEmptyLines'] 19 | define_rule ['Layout/IndentHeredoc' => 'Layout/HeredocIndentation'] 20 | define_rule ['Layout/IndentFirstParameter' => 'Layout/FirstParameterIndentation'] 21 | define_rule ['Layout/IndentFirstHashElement' => 'Layout/FirstHashElementIndentation'] 22 | define_rule ['Layout/IndentFirstArrayElement' => 'Layout/FirstArrayElementIndentation'] 23 | define_rule ['Layout/IndentFirstArgument' => 'Layout/FirstArgumentIndentation'] 24 | define_rule ['Layout/IndentAssignment' => 'Layout/AssignmentIndentation'] 25 | define_rule ['Layout/AlignParameters' => 'Layout/ParameterAlignment'] 26 | define_rule ['Layout/AlignHash' => 'Layout/HashAlignment'] 27 | define_rule ['Layout/AlignArray' => 'Layout/ArrayAlignment'] 28 | define_rule ['Layout/AlignArguments' => 'Layout/ArgumentAlignment'] 29 | 30 | define_rule ['Bundler/GemComment', 'Whitelist' => 'IgnoredGems'] 31 | define_rule ['Lint/SafeNavigationChain', 'Whitelist' => 'AllowedMethods'] 32 | define_rule ['Lint/SafeNavigationConsistency', 'Whitelist' => 'AllowedMethods'] 33 | define_rule ['Naming/HeredocDelimiterNaming', 'Blacklist' => 'ForbiddenDelimiters'] 34 | define_rule ['Naming/PredicateName', 'NamePrefixBlacklist' => 'ForbiddenPrefixes'] 35 | define_rule ['Naming/PredicateName', 'NameWhitelist' => 'AllowedMethods'] 36 | define_rule ['Style/IpAddresses', 'Whitelist' => 'AllowedAddresses'] 37 | define_rule ['Style/NestedParenthesizedCalls', 'Whitelist' => 'AllowedMethods'] 38 | define_rule ['Style/SafeNavigation', 'Whitelist' => 'AllowedMethods'] 39 | define_rule ['Style/TrivialAccessors', 'Whitelist' => 'AllowedMethods'] 40 | end 41 | 42 | class Rewriter_0_76_0 < YAMLRewriter::Rewriter 43 | define_rule ['Lint/UnneededSplatExpansion' => 'Lint/RedundantSplatExpansion'] 44 | define_rule ['Lint/UnneededRequireStatement' => 'Lint/RedundantRequireStatement'] 45 | define_rule ['Lint/UnneededCopEnableDirective' => 'Lint/RedundantCopEnableDirective'] 46 | define_rule ['Lint/UnneededCopDisableDirective' => 'Lint/RedundantCopDisableDirective'] 47 | define_rule ['Style/UnneededSort' => 'Style/RedundantSort'] 48 | define_rule ['Style/UnneededPercentQ' => 'Style/RedundantPercentQ'] 49 | define_rule ['Style/UnneededInterpolation' => 'Style/RedundantInterpolation'] 50 | define_rule ['Style/UnneededCondition' => 'Style/RedundantCondition'] 51 | define_rule ['Style/UnneededCapitalW' => 'Style/RedundantCapitalW'] 52 | end 53 | 54 | class Rewriter_0_75_0 < YAMLRewriter::Rewriter 55 | end 56 | 57 | class Rewriter_0_74_0 < YAMLRewriter::Rewriter 58 | end 59 | 60 | class Rewriter_0_73_0 < YAMLRewriter::Rewriter 61 | end 62 | 63 | class Rewriter_0_72_0 < YAMLRewriter::Rewriter 64 | end 65 | 66 | class Rewriter_0_71_0 < YAMLRewriter::Rewriter 67 | end 68 | 69 | class Rewriter_0_70_0 < YAMLRewriter::Rewriter 70 | end 71 | 72 | class Rewriter_0_69_0 < YAMLRewriter::Rewriter 73 | end 74 | 75 | class Rewriter_0_68_0 < YAMLRewriter::Rewriter 76 | define_rule ['Layout/FirstParameterIndentation' => 'Layout/IndentFirstArgument'] 77 | end 78 | 79 | class Rewriter_0_67_0 < YAMLRewriter::Rewriter 80 | define_rule ['Performance/RedundantSortBy' => 'Style/RedundantSortBy'] 81 | define_rule ['PerfoPerformance/Sample' => 'Style/Sample'] 82 | define_rule ['PerfoPerformance/UnneededSort' => 'Style/UnneededSort'] 83 | define_rule ['Style/LstripRstrip' => 'Style/Strip'] 84 | define_rule ['Performance/LstripRstrip' => 'Style/LstripRstrip'] 85 | end 86 | 87 | class Rewriter_0_66_0 < YAMLRewriter::Rewriter 88 | end 89 | 90 | class Rewriter_0_65_0 < YAMLRewriter::Rewriter 91 | end 92 | 93 | class Rewriter_0_64_0 < YAMLRewriter::Rewriter 94 | end 95 | 96 | class Rewriter_0_63_0 < YAMLRewriter::Rewriter 97 | define_rule ['Style/FlipFlop' => 'Lint/FlipFlop'] 98 | end 99 | 100 | class Rewriter_0_62_0 < YAMLRewriter::Rewriter 101 | end 102 | 103 | class Rewriter_0_61_0 < YAMLRewriter::Rewriter 104 | end 105 | 106 | class Rewriter_0_60_0 < YAMLRewriter::Rewriter 107 | end 108 | 109 | class Rewriter_0_59_0 < YAMLRewriter::Rewriter 110 | end 111 | 112 | class Rewriter_0_58_0 < YAMLRewriter::Rewriter 113 | end 114 | 115 | class Rewriter_0_57_0 < YAMLRewriter::Rewriter 116 | end 117 | 118 | class Rewriter_0_56_0 < YAMLRewriter::Rewriter 119 | define_rule ['Style/EmptyLineAfterGuardClause' => 'Layout/EmptyLineAfterGuardClause'] 120 | end 121 | 122 | class Rewriter_0_55_0 < YAMLRewriter::Rewriter 123 | end 124 | 125 | class Rewriter_0_54_0 < YAMLRewriter::Rewriter 126 | end 127 | 128 | class Rewriter_0_53_0 < YAMLRewriter::Rewriter 129 | define_rule ['Naming/UncommunicativeMethodArgName' => 'Naming/UncommunicativeMethodParamName'] 130 | define_rule ['Lint/ConditionPosition' => 'Layout/ConditionPosition'] 131 | define_rule ['Lint/BlockAlignment' => 'Layout/BlockAlignment'] 132 | define_rule ['Lint/DefEndAlignment' => 'Layout/DefEndAlignment'] 133 | define_rule ['Lint/EndAlignment' => 'Layout/EndAlignment'] 134 | define_rule ['Lint/UnneededDisable' => 'Lint/UnneededCopDisableDirective'] 135 | end 136 | 137 | class Rewriter_0_52_0 < YAMLRewriter::Rewriter 138 | define_rule ['Lint/RescueWithoutErrorClass' => 'Style/RescueStandardError'] 139 | end 140 | 141 | class Rewriter_0_51_0 < YAMLRewriter::Rewriter 142 | define_rule ['Lint/LiteralInCondition' => 'Lint/LiteralAsCondition'] 143 | end 144 | 145 | class Rewriter_0_50_0 < YAMLRewriter::Rewriter 146 | define_rule ['Style/AccessorMethodName' => 'Naming/AccessorMethodName'] 147 | define_rule ['Style/AsciiIdentifiers' => 'Naming/AsciiIdentifiers'] 148 | define_rule ['Style/OpMethod' => 'Naming/BinaryOperatorParameterName'] 149 | define_rule ['Style/ClassAndModuleCamelCase' => 'Naming/ClassAndModuleCamelCase'] 150 | define_rule ['Style/ConstantName' => 'Naming/ConstantName'] 151 | define_rule ['Style/FileName' => 'Naming/FileName'] 152 | define_rule ['Style/MethodName' => 'Naming/MethodName'] 153 | define_rule ['Style/PredicateName' => 'Naming/PredicateName'] 154 | define_rule ['Style/VariableName' => 'Naming/VariableName'] 155 | define_rule ['Style/VariableNumber' => 'Naming/VariableNumber'] 156 | end 157 | 158 | class Rewriter_0_49_0 < YAMLRewriter::Rewriter 159 | layout_cops = %w[ 160 | Layout/AccessModifierIndentation 161 | Layout/AlignArray 162 | Layout/AlignHash 163 | Layout/AlignParameters 164 | Layout/BlockEndNewline 165 | Layout/CaseIndentation 166 | Layout/ClosingParenthesisIndentation 167 | Layout/CommentIndentation 168 | Layout/DotPosition 169 | Layout/ElseAlignment 170 | Layout/EmptyLineAfterMagicComment 171 | Layout/EmptyLineBetweenDefs 172 | Layout/EmptyLinesAroundAccessModifier 173 | Layout/EmptyLinesAroundBeginBody 174 | Layout/EmptyLinesAroundBlockBody 175 | Layout/EmptyLinesAroundClassBody 176 | Layout/EmptyLinesAroundExceptionHandlingKeywords 177 | Layout/EmptyLinesAroundMethodBody 178 | Layout/EmptyLinesAroundModuleBody 179 | Layout/EmptyLines 180 | Layout/EndOfLine 181 | Layout/ExtraSpacing 182 | Layout/FirstArrayElementLineBreak 183 | Layout/FirstHashElementLineBreak 184 | Layout/FirstMethodArgumentLineBreak 185 | Layout/FirstMethodParameterLineBreak 186 | Layout/FirstParameterIndentation 187 | Layout/IndentArray 188 | Layout/IndentAssignment 189 | Layout/IndentationConsistency 190 | Layout/IndentationWidth 191 | Layout/IndentHash 192 | Layout/IndentHeredoc 193 | Layout/InitialIndentation 194 | Layout/LeadingCommentSpace 195 | Layout/MultilineArrayBraceLayout 196 | Layout/MultilineAssignmentLayout 197 | Layout/MultilineBlockLayout 198 | Layout/MultilineHashBraceLayout 199 | Layout/MultilineMethodCallBraceLayout 200 | Layout/MultilineMethodCallIndentation 201 | Layout/MultilineMethodDefinitionBraceLayout 202 | Layout/MultilineOperationIndentation 203 | Layout/RescueEnsureAlignment 204 | Layout/SpaceAfterColon 205 | Layout/SpaceAfterComma 206 | Layout/SpaceAfterMethodName 207 | Layout/SpaceAfterNot 208 | Layout/SpaceAfterSemicolon 209 | Layout/SpaceAroundBlockParameters 210 | Layout/SpaceAroundEqualsInParameterDefault 211 | Layout/SpaceAroundKeyword 212 | Layout/SpaceAroundOperators 213 | Layout/SpaceBeforeBlockBraces 214 | Layout/SpaceBeforeComma 215 | Layout/SpaceBeforeComment 216 | Layout/SpaceBeforeFirstArg 217 | Layout/SpaceBeforeSemicolon 218 | Layout/SpaceInLambdaLiteral 219 | Layout/SpaceInsideArrayPercentLiteral 220 | Layout/SpaceInsideBlockBraces 221 | Layout/SpaceInsideBrackets 222 | Layout/SpaceInsideHashLiteralBraces 223 | Layout/SpaceInsideParens 224 | Layout/SpaceInsidePercentLiteralDelimiters 225 | Layout/SpaceInsideRangeLiteral 226 | Layout/SpaceInsideStringInterpolation 227 | Layout/Tab 228 | Layout/TrailingBlankLines 229 | Layout/TrailingWhitespace 230 | ] 231 | 232 | layout_cops.each do |cop| 233 | define_rule [cop.sub('Layout', 'Style') => cop] 234 | end 235 | end 236 | 237 | class Rewriter_0_48_0 < YAMLRewriter::Rewriter 238 | # 0.48.0 release does not have renaming. 239 | end 240 | 241 | class Rewriter_0_47_0 < YAMLRewriter::Rewriter 242 | define_rule ['Lint/Eval' => 'Security/Eval'] 243 | define_rule ['Style/CaseIndentation', 'IndentWhenRelativeTo' => 'EnforcedStyle'] 244 | define_rule ['Lint/BlockAlignment', 'AlignWith' => 'EnforcedStyleAlignWith'] 245 | define_rule ['Lint/EndAlignment', 'AlignWith' => 'EnforcedStyleAlignWith'] 246 | define_rule ['Lint/DefEndAlignment', 'AlignWith' => 'EnforcedStyleAlignWith'] 247 | define_rule ['Rails/UniqBeforePluck', 'EnforcedMode' => 'EnforcedStyle'] 248 | define_rule ['Style/MethodCallParentheses' => 'Style/MethodCallWithoutArgsParentheses'] 249 | end 250 | 251 | class Rewriter_0_46_0 < YAMLRewriter::Rewriter 252 | define_rule ['Performance/SortWithBlock' => 'Performance/CompareWithBlock'] 253 | end 254 | 255 | class Rewriter_0_45_0 < YAMLRewriter::Rewriter 256 | # 0.45.0 release does not have renaming. 257 | end 258 | 259 | class Rewriter_0_44_0 < YAMLRewriter::Rewriter 260 | # 0.44.0 release does not have renaming. 261 | end 262 | 263 | class Rewriter_0_43_0 < YAMLRewriter::Rewriter 264 | define_rule ['Lint/UselessArraySplat' => 'Lint/UnneededSplatExpansion'] 265 | end 266 | 267 | class Rewriter_0_42_0 < YAMLRewriter::Rewriter 268 | # 0.42.0 release does not have renaming. 269 | end 270 | 271 | class Rewriter_0_41_0 < YAMLRewriter::Rewriter 272 | define_rule ['Style/DeprecatedHashMethods' => 'Style/PreferredHashMethods'] 273 | end 274 | 275 | class Rewriter_0 < YAMLRewriter::Rewriter 276 | define_rule ['Style/SingleSpaceBeforeFirstArg' => 'Style/SpaceBeforeFirstArg'] 277 | define_rule ['Lint/SpaceBeforeFirstArg' => 'Style/SpaceBeforeFirstArg'] 278 | define_rule ['Style/SpaceAfterControlKeyword' => 'Style/SpaceAroundKeyword'] 279 | define_rule ['Style/SpaceBeforeModifierKeyword' => 'Style/SpaceAroundKeyword'] 280 | define_rule ['Style/SpaceAroundOperators', 'MultiSpaceAllowedForOperators' => 'AllowForAlignment'] 281 | end 282 | 283 | Rewriters = self.constants.grep(/^Rewriter_\d/).map do |name| 284 | version = Gem::Version.new(name[/Rewriter_(.+)$/, 1].gsub('_', '.')) 285 | klass = const_get(name) 286 | [version, klass] 287 | end.sort.reverse.to_h 288 | 289 | def self.rewriters(target) 290 | return [(Rewriters.values + [Rewriter_Master]).reverse, []] if target == :master 291 | 292 | Rewriters 293 | .partition{|key, _value| target >= key} 294 | .map{|rewriters| rewriters.map{|k, v| v}.reverse} 295 | end 296 | end 297 | end 298 | --------------------------------------------------------------------------------