From 8d8cd2341468c9ae4779d02d8646743e7d87b00f Mon Sep 17 00:00:00 2001 From: Rylan Polster Date: Sun, 17 Dec 2023 16:46:48 -0500 Subject: [PATCH] Add rubocop to enforce `deprecate!` over `discontinued` --- .../Homebrew/rubocops/cask/discontinued.rb | 43 ++++++++++++ .../Homebrew/rubocops/cask/discontinued.rbi | 25 +++++++ Library/Homebrew/rubocops/rubocop-cask.rb | 1 + .../test/rubocops/cask/discontinued_spec.rb | 65 +++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 Library/Homebrew/rubocops/cask/discontinued.rb create mode 100644 Library/Homebrew/rubocops/cask/discontinued.rbi create mode 100644 Library/Homebrew/test/rubocops/cask/discontinued_spec.rb diff --git a/Library/Homebrew/rubocops/cask/discontinued.rb b/Library/Homebrew/rubocops/cask/discontinued.rb new file mode 100644 index 0000000000..7c871909cd --- /dev/null +++ b/Library/Homebrew/rubocops/cask/discontinued.rb @@ -0,0 +1,43 @@ +# typed: true +# frozen_string_literal: true + +# TODO: Remove this when we remove `caveats { discontinued }` (likely for Homebrew 4.5.0) +module RuboCop + module Cop + module Cask + # This cop corrects `caveats { discontinued }` to `deprecate!`. + class Discontinued < Base + include CaskHelp + extend AutoCorrector + + MESSAGE = "Use `deprecate!` instead of `caveats { discontinued }`." + + def on_cask_stanza_block(stanza_block) + stanza_block.stanzas.select(&:caveats?).each do |stanza| + find_discontinued_method_call(stanza.stanza_node) do |node| + if caveats_constains_only_discontinued?(node.parent) + add_offense(node.parent, message: MESSAGE) do |corrector| + corrector.replace(node.parent.source_range, + "deprecate! date: \"#{Date.today}\", because: :discontinued") + end + else + add_offense(node, message: MESSAGE) + end + end + end + end + + def_node_matcher :caveats_constains_only_discontinued?, <<~EOS + (block + (send nil? :caveats) + (args) + (send nil? :discontinued)) + EOS + + def_node_search :find_discontinued_method_call, <<~EOS + $(send nil? :discontinued) + EOS + end + end + end +end diff --git a/Library/Homebrew/rubocops/cask/discontinued.rbi b/Library/Homebrew/rubocops/cask/discontinued.rbi new file mode 100644 index 0000000000..de0c35e009 --- /dev/null +++ b/Library/Homebrew/rubocops/cask/discontinued.rbi @@ -0,0 +1,25 @@ +# typed: strict + +module RuboCop + module Cop + module Cask + class Discontinued < Base + sig { + params( + base_node: RuboCop::AST::BlockNode, + block: T.nilable(T.proc.params(node: RuboCop::AST::SendNode).void), + ).returns(T::Boolean) + } + def caveats_constains_only_discontinued?(base_node, &block); end + + sig { + params( + base_node: RuboCop::AST::BlockNode, + block: T.proc.params(node: RuboCop::AST::SendNode).void, + ).void + } + def find_discontinued_method_call(base_node, &block); end + end + end + end +end diff --git a/Library/Homebrew/rubocops/rubocop-cask.rb b/Library/Homebrew/rubocops/rubocop-cask.rb index a5ee744b8d..9f3cb11e6a 100644 --- a/Library/Homebrew/rubocops/rubocop-cask.rb +++ b/Library/Homebrew/rubocops/rubocop-cask.rb @@ -13,6 +13,7 @@ require_relative "cask/mixin/cask_help" require_relative "cask/mixin/on_homepage_stanza" require_relative "cask/mixin/on_url_stanza" require_relative "cask/desc" +require_relative "cask/discontinued" require_relative "cask/homepage_url_trailing_slash" require_relative "cask/no_overrides" require_relative "cask/on_system_conditionals" diff --git a/Library/Homebrew/test/rubocops/cask/discontinued_spec.rb b/Library/Homebrew/test/rubocops/cask/discontinued_spec.rb new file mode 100644 index 0000000000..e3264600aa --- /dev/null +++ b/Library/Homebrew/test/rubocops/cask/discontinued_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require "rubocops/rubocop-cask" + +describe RuboCop::Cop::Cask::Discontinued, :config do + it "reports no offenses when there is no `caveats` stanza" do + expect_no_offenses <<~CASK + cask "foo" do + url "https://example.com/download/foo-v1.2.0.dmg", + verified: "example.com/download/" + end + CASK + end + + it "reports no offenses when there is a `caveats` stanza without `discontinued`" do + expect_no_offenses <<~CASK + cask "foo" do + url "https://example.com/download/foo-v1.2.0.dmg", + verified: "example.com/download/" + + caveats do + files_in_usr_local + end + end + CASK + end + + it "reports an offense when there is a `caveats` stanza with `discontinued` and other caveats" do + expect_offense <<~CASK + cask "foo" do + url "https://example.com/download/foo-v1.2.0.dmg", + verified: "example.com/download/" + + caveats do + discontinued + ^^^^^^^^^^^^ Use `deprecate!` instead of `caveats { discontinued }`. + files_in_usr_local + end + end + CASK + end + + it "corrects `caveats { discontinued }` to `deprecate!`" do + expect_offense <<~CASK + cask "foo" do + url "https://example.com/download/foo-v1.2.0.dmg", + verified: "example.com/download/" + + caveats do + ^^^^^^^^^^ Use `deprecate!` instead of `caveats { discontinued }`. + discontinued + end + end + CASK + + expect_correction <<~CASK + cask "foo" do + url "https://example.com/download/foo-v1.2.0.dmg", + verified: "example.com/download/" + + deprecate! date: "#{Date.today}", because: :discontinued + end + CASK + end +end