From 66a8a443e8b1cc26246dbd2b61f1c4dcdb0390cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?fn=20=E2=8C=83=20=E2=8C=A5?= <70830482+FnControlOption@users.noreply.github.com> Date: Sun, 5 Jan 2025 11:29:41 -0800 Subject: [PATCH] Add Rule::Base.autocorrect_incompatible_with --- spec/ameba/runner_spec.cr | 8 ++++++++ src/ameba/rule/base.cr | 5 +++++ src/ameba/rule/performance/minmax_after_map.cr | 4 ++++ src/ameba/rule/style/verbose_block.cr | 4 ++++ src/ameba/runner.cr | 5 +++++ 5 files changed, 26 insertions(+) diff --git a/spec/ameba/runner_spec.cr b/spec/ameba/runner_spec.cr index 17aa97c8c..357d1dcb8 100644 --- a/spec/ameba/runner_spec.cr +++ b/spec/ameba/runner_spec.cr @@ -135,6 +135,14 @@ module Ameba source.issues.first.rule.name.should eq Rule::Lint::UnneededDisableDirective.rule_name end end + + it "handles rules with incompatible autocorrect" do + rules = [Rule::Performance::MinMaxAfterMap.new, Rule::Style::VerboseBlock.new] + source = Source.new "list.map { |i| i.size }.max\n", File.tempfile("source", ".cr").path + + Runner.new(rules, [source], formatter, default_severity, autocorrect: true).run + source.code.should eq "list.max_of(&.size)\n" + end end describe "#explain" do diff --git a/src/ameba/rule/base.cr b/src/ameba/rule/base.cr index 242c86f0b..bd976a594 100644 --- a/src/ameba/rule/base.cr +++ b/src/ameba/rule/base.cr @@ -29,6 +29,11 @@ module Ameba::Rule abstract class Base include Config::RuleConfig + def self.autocorrect_incompatible_with + # TODO: can't use Class as generic type argument yet + [] of Base + end + # This method is designed to test the source passed in. If source has issues # that are tested by this rule, it should add an issue. # diff --git a/src/ameba/rule/performance/minmax_after_map.cr b/src/ameba/rule/performance/minmax_after_map.cr index 614fc7f36..4d158269f 100644 --- a/src/ameba/rule/performance/minmax_after_map.cr +++ b/src/ameba/rule/performance/minmax_after_map.cr @@ -36,6 +36,10 @@ module Ameba::Rule::Performance MSG = "Use `%s {...}` instead of `map {...}.%s`." CALL_NAMES = %w[min min? max max? minmax minmax?] + def self.autocorrect_incompatible_with + [Style::VerboseBlock] + end + def test(source) AST::NodeVisitor.new self, source, skip: :macro end diff --git a/src/ameba/rule/style/verbose_block.cr b/src/ameba/rule/style/verbose_block.cr index df81d5532..c7226ad02 100644 --- a/src/ameba/rule/style/verbose_block.cr +++ b/src/ameba/rule/style/verbose_block.cr @@ -47,6 +47,10 @@ module Ameba::Rule::Style MSG = "Use short block notation instead: `%s`" CALL_PATTERN = "%s(%s&.%s)" + def self.autocorrect_incompatible_with + [Performance::MinMaxAfterMap] + end + protected def same_location_lines?(a, b) return unless a_location = name_location(a) return unless b_location = b.location diff --git a/src/ameba/runner.cr b/src/ameba/runner.cr index d2189b394..7871306ea 100644 --- a/src/ameba/runner.cr +++ b/src/ameba/runner.cr @@ -141,9 +141,14 @@ module Ameba @syntax_rule.test(source) break unless source.valid? + rules_with_issues = [] of Rule::Base @rules.each do |rule| + next if autocorrect? && rules_with_issues.any?(&.class.in?(rule.class.autocorrect_incompatible_with)) next if rule.excluded?(source) + size_before = source.issues.size rule.test(source) + size_after = source.issues.size + rules_with_issues << rule if size_before != size_after end check_unneeded_directives(source) break unless autocorrect? && source.correct?