From e00b7427ebcc43f09c140432c09f00f3fe3b9cd5 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Tue, 20 Jul 2021 18:58:37 +0900 Subject: [PATCH] Support auto-correction for `Rails/Output` This PR supports auto-correction for `Rails/Output`. --- CHANGELOG.md | 4 ++ config/default.yml | 1 + docs/modules/ROOT/pages/cops_rails.adoc | 2 +- lib/rubocop/cop/rails/output.rb | 20 ++++++-- spec/rubocop/cop/rails/output_spec.rb | 66 +++++++++++++++++++++++-- 5 files changed, 85 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bacf0dd39d..2cc2e87cf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## master (unreleased) +### New features + +* [#521](https://github.com/rubocop/rubocop-rails/pull/521): Support auto-correction for `Rails/Output`. ([@koic][]) + ## 2.11.3 (2021-07-11) ### Bug fixes diff --git a/config/default.yml b/config/default.yml index 27e926b27d..fc98a63970 100644 --- a/config/default.yml +++ b/config/default.yml @@ -499,6 +499,7 @@ Rails/OrderById: Rails/Output: Description: 'Checks for calls to puts, print, etc.' Enabled: true + SafeAutoCorrect: false VersionAdded: '0.15' VersionChanged: '0.19' Include: diff --git a/docs/modules/ROOT/pages/cops_rails.adoc b/docs/modules/ROOT/pages/cops_rails.adoc index 699bc76e66..f4d7baab0d 100644 --- a/docs/modules/ROOT/pages/cops_rails.adoc +++ b/docs/modules/ROOT/pages/cops_rails.adoc @@ -2747,7 +2747,7 @@ scope :chronological, -> { order(created_at: :asc) } | Enabled | Yes -| No +| Yes (Unsafe) | 0.15 | 0.19 |=== diff --git a/lib/rubocop/cop/rails/output.rb b/lib/rubocop/cop/rails/output.rb index 2d2df29581..a06b98b8e4 100644 --- a/lib/rubocop/cop/rails/output.rb +++ b/lib/rubocop/cop/rails/output.rb @@ -14,6 +14,9 @@ module Rails # # good # Rails.logger.debug 'A debug message' class Output < Base + include RangeHelp + extend AutoCorrector + MSG = 'Do not write to stdout. ' \ "Use Rails's logger if you want to log." RESTRICT_ON_SEND = %i[ @@ -35,10 +38,13 @@ class Output < Base PATTERN def on_send(node) - return unless (output?(node) || io_output?(node)) && - node.arguments? + return unless (output?(node) || io_output?(node)) && node.arguments? + + range = offense_range(node) - add_offense(node.loc.selector) + add_offense(range) do |corrector| + corrector.replace(range, 'Rails.logger.debug') + end end private @@ -46,6 +52,14 @@ def on_send(node) def match_gvar?(sym) %i[$stdout $stderr].include?(sym) end + + def offense_range(node) + if node.receiver + range_between(node.loc.expression.begin_pos, node.loc.selector.end_pos) + else + node.loc.selector + end + end end end end diff --git a/spec/rubocop/cop/rails/output_spec.rb b/spec/rubocop/cop/rails/output_spec.rb index c27d59c741..4e3077df18 100644 --- a/spec/rubocop/cop/rails/output_spec.rb +++ b/spec/rubocop/cop/rails/output_spec.rb @@ -1,22 +1,80 @@ # frozen_string_literal: true RSpec.describe RuboCop::Cop::Rails::Output, :config do - it 'registers an offense for methods without a receiver' do + it 'registers and corrects an offense for using `p` method without a receiver' do expect_offense(<<~RUBY) p "edmond dantes" ^ Do not write to stdout. Use Rails's logger if you want to log. + RUBY + + expect_correction(<<~RUBY) + Rails.logger.debug "edmond dantes" + RUBY + end + + it 'registers and corrects an offense for using `puts` method without a receiver' do + expect_offense(<<~RUBY) puts "sinbad" ^^^^ Do not write to stdout. Use Rails's logger if you want to log. + RUBY + + expect_correction(<<~RUBY) + Rails.logger.debug "sinbad" + RUBY + end + + it 'registers and corrects an offense for using `print` method without a receiver' do + expect_offense(<<~RUBY) print "abbe busoni" ^^^^^ Do not write to stdout. Use Rails's logger if you want to log. + RUBY + + expect_correction(<<~RUBY) + Rails.logger.debug "abbe busoni" + RUBY + end + + it 'registers and corrects an offense for using `pp` method without a receiver' do + expect_offense(<<~RUBY) pp "monte cristo" ^^ Do not write to stdout. Use Rails's logger if you want to log. + RUBY + + expect_correction(<<~RUBY) + Rails.logger.debug "monte cristo" + RUBY + end + + it 'registers and corrects an offense for using `$stdout` method without a receiver' do + expect_offense(<<~RUBY) $stdout.write "lord wilmore" - ^^^^^ Do not write to stdout. Use Rails's logger if you want to log. + ^^^^^^^^^^^^^ Do not write to stdout. Use Rails's logger if you want to log. + RUBY + + expect_correction(<<~RUBY) + Rails.logger.debug "lord wilmore" + RUBY + end + + it 'registers and corrects an offense for using `syswrite` method without a receiver' do + expect_offense(<<~RUBY) $stderr.syswrite "faria" - ^^^^^^^^ Do not write to stdout. Use Rails's logger if you want to log. + ^^^^^^^^^^^^^^^^ Do not write to stdout. Use Rails's logger if you want to log. + RUBY + + expect_correction(<<~RUBY) + Rails.logger.debug "faria" + RUBY + end + + it 'registers and corrects an offense for using `write` method without a receiver' do + expect_offense(<<~RUBY) STDOUT.write "bertuccio" - ^^^^^ Do not write to stdout. Use Rails's logger if you want to log. + ^^^^^^^^^^^^ Do not write to stdout. Use Rails's logger if you want to log. + RUBY + + expect_correction(<<~RUBY) + Rails.logger.debug "bertuccio" RUBY end