Skip to content

Upgrade RuboCop cops to v1 API #3512

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Jun 10, 2025
5 changes: 5 additions & 0 deletions .changeset/neat-taxis-remain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@primer/view-components": patch
---

Upgrade RuboCop cops to v1 API
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ module RuboCop
module Cop
module Migrations
# Lint and autocorrect deprecated IconButton
class IconButtonComponent < RuboCop::Cop::Cop
class IconButtonComponent < RuboCop::Cop::Base
extend AutoCorrector
INVALID_MESSAGE = <<~STR
`Primer::IconButton` is deprecated. Please use `Primer::Beta::IconButton` instead.
STR
Expand All @@ -20,13 +21,9 @@ class IconButtonComponent < RuboCop::Cop::Cop
def on_send(node)
return unless icon_button(node)

add_offense(node, message: INVALID_MESSAGE)
end

def autocorrect(node)
return if hash_with_box_value?(node.arguments.first)
add_offense(node, message: INVALID_MESSAGE) do |corrector|
next if hash_with_box_value?(node.arguments.first)

lambda do |corrector|
corrector.replace(icon_button(node), "Primer::Beta::IconButton")
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ module RuboCop
module Cop
module Migrations
# Lint & autocorrect Truncate components
class TruncateComponent < RuboCop::Cop::Cop
class TruncateComponent < RuboCop::Cop::Base
extend AutoCorrector
INVALID_MESSAGE = <<~STR
`Primer::Truncate` is deprecated. Please use `Primer::Beta::Truncate` instead!
STR
Expand All @@ -24,13 +25,9 @@ class TruncateComponent < RuboCop::Cop::Cop
def on_send(node)
return unless truncate_component(node)

add_offense(node, message: INVALID_MESSAGE)
end

def autocorrect(node)
return if hash_with_inline_value?(node.arguments.first)
add_offense(node, message: INVALID_MESSAGE) do |corrector|
next if hash_with_inline_value?(node.arguments.first)

lambda do |corrector|
if node.arguments.first.nil? == false
corrector.replace(node.children.first, "Primer::Beta::Truncate")
corrector.insert_after(node.arguments.first, ", tag: :div") unless truncate_with_tag?(node.arguments.first)
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/primer/base_cop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module RuboCop
module Cop
module Primer
# :nodoc:
class BaseCop < RuboCop::Cop::Cop
class BaseCop < RuboCop::Cop::Base
# We only verify SystemArguments if it's a `.new` call on a component or
# a ViewHeleper call.
def valid_node?(node)
Expand Down
15 changes: 7 additions & 8 deletions lib/rubocop/cop/primer/component_name_migration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,19 @@ module Primer
# good
# Primer::Beta::ComponentName.new()
class ComponentNameMigration < BaseCop
extend AutoCorrector

def on_send(node)
return unless node.method_name == :new && !node.receiver.nil? && ::Primer::Deprecations.deprecated?(node.receiver.const_name)

message = ::Primer::Deprecations.deprecation_message(node.receiver.const_name)
add_offense(node.receiver, message: message)
end

def autocorrect(node)
lambda do |corrector|
component_name = node.const_name
return unless ::Primer::Deprecations.correctable?(component_name)

add_offense(node.receiver, message: message) do |corrector|
component_name = node.receiver.const_name
next unless ::Primer::Deprecations.correctable?(component_name)

replacement = ::Primer::Deprecations.replacement(component_name)
corrector.replace(node, replacement) if replacement.present?
corrector.replace(node.receiver, replacement) if replacement.present?
end
end
end
Expand Down
15 changes: 7 additions & 8 deletions lib/rubocop/cop/primer/deprecated_arguments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module Primer
# good
# Component.new(foo: :bar)
class DeprecatedArguments < BaseCop
extend AutoCorrector
INVALID_MESSAGE = <<~STR
Avoid using deprecated arguments: https://primer.style/view-components/deprecated.
STR
Expand Down Expand Up @@ -283,17 +284,15 @@ def on_send(node)
key, value = extract_kv_from(pair)
next unless DEPRECATED.key?(key) && DEPRECATED[key].key?(value)

add_offense(pair, message: INVALID_MESSAGE)
add_offense(pair, message: INVALID_MESSAGE) do |corrector|
key, value = extract_kv_from(pair)
replacement = DEPRECATED[key][value]
corrector.replace(pair, replacement) if replacement.present?
end
end
end

def autocorrect(node)
lambda do |corrector|
key, value = extract_kv_from(node)
replacement = DEPRECATED[key][value]
corrector.replace(node, replacement) if replacement.present?
end
end


def extract_kv_from(pair)
key = pair.key.value
Expand Down
11 changes: 5 additions & 6 deletions lib/rubocop/cop/primer/deprecated_button_arguments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module Primer
# good
# ButtonComponent.new(size: :small)
class DeprecatedButtonArguments < BaseCop
extend AutoCorrector
INVALID_MESSAGE = <<~STR
`variant` is deprecated. Use `size` instead.
STR
Expand All @@ -37,14 +38,12 @@ def on_send(node)

return if pair.nil?

add_offense(pair.key, message: INVALID_MESSAGE)
end

def autocorrect(node)
lambda do |corrector|
corrector.replace(node, DEPRECATIONS[node.value])
add_offense(pair.key, message: INVALID_MESSAGE) do |corrector|
corrector.replace(pair.key, DEPRECATIONS[pair.key.value])
end
end


end
end
end
Expand Down
13 changes: 6 additions & 7 deletions lib/rubocop/cop/primer/deprecated_label_schemes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ module Primer
# good
# Primer::Beta::Label.new(scheme: :accent)
class DeprecatedLabelSchemes < BaseCop
extend AutoCorrector
INVALID_MESSAGE = <<~STR
Avoid using deprecated schemes: https://primer.style/view-components/deprecated#labelcomponent.
STR
Expand Down Expand Up @@ -44,16 +45,14 @@ def on_send(node)

next unless DEPRECATIONS.key?(value)

add_offense(pair.value, message: INVALID_MESSAGE)
add_offense(pair.value, message: INVALID_MESSAGE) do |corrector|
replacement = DEPRECATIONS[pair.value.value.to_sym]
corrector.replace(pair.value, replacement)
end
end
end

def autocorrect(node)
lambda do |corrector|
replacement = DEPRECATIONS[node.value.to_sym]
corrector.replace(node, replacement)
end
end


private

Expand Down
21 changes: 7 additions & 14 deletions lib/rubocop/cop/primer/deprecated_label_variants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module Primer
# good
# Primer::Beta::Label.new(inline: true)
class DeprecatedLabelVariants < BaseCop
extend AutoCorrector
def on_send(node)
return unless label_node?(node)
return unless node.arguments?
Expand All @@ -37,26 +38,18 @@ def on_send(node)

case pair.value.value
when :large, "large"
add_offense(pair, message: "Avoid using `variant: :large` with `LabelComponent`. Use `size: :large` instead.")
add_offense(pair, message: "Avoid using `variant: :large` with `LabelComponent`. Use `size: :large` instead.") do |corrector|
corrector.replace(pair, "size: :large")
end
when :inline, "inline"
add_offense(pair, message: "Avoid using `variant: :inline` with `LabelComponent`. Use `inline: true` instead.")
add_offense(pair, message: "Avoid using `variant: :inline` with `LabelComponent`. Use `inline: true` instead.") do |corrector|
corrector.replace(pair, "inline: true")
end
end
end
end

def autocorrect(node)
lambda do |corrector|
replacement =
case node.value.value
when :large, "large"
"size: :large"
when :inline, "inline"
"inline: true"
end

corrector.replace(node, replacement)
end
end

private

Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/primer/no_tag_memoize.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module Primer
#
# good
# @system_arguments[:tag] = :h2
class NoTagMemoize < RuboCop::Cop::Cop
class NoTagMemoize < RuboCop::Cop::Base
INVALID_MESSAGE = <<~STR
Avoid `[:tag] ||=`. Instead, try one of the following:
- Don't allow consumers to update the tag by having a fixed tag (e.g. `system_arguments[:tag] = :div`)
Expand Down
11 changes: 5 additions & 6 deletions lib/rubocop/cop/primer/primer_octicon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ module Primer
# primer_octicon(:"icon-with-daashes")
# primer_octicon(@ivar)
# primer_octicon(condition > "icon" : "other-icon")
class PrimerOcticon < RuboCop::Cop::Cop
class PrimerOcticon < RuboCop::Cop::Base
extend AutoCorrector
INVALID_MESSAGE = <<~STR
Replace the octicon helper with primer_octicon. See https://primer.style/view-components/components/octicon for details.
STR
Expand Down Expand Up @@ -65,11 +66,7 @@ def on_send(node)
return if invalid_classes.present?
end

add_offense(node, message: INVALID_MESSAGE)
end

def autocorrect(node)
lambda do |corrector|
add_offense(node, message: INVALID_MESSAGE) do |corrector|
kwargs = kwargs(node)

# Converting arguments for the component
Expand All @@ -86,6 +83,8 @@ def autocorrect(node)
end
end



private

def transform_sizes(kwargs)
Expand Down
7 changes: 6 additions & 1 deletion test/lib/cop_test_case.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ def setup
def investigate(cop, src, filename = nil)
processed_source = processed_source(src, filename)
commissioner = RuboCop::Cop::Commissioner.new([cop], [], raise_error: true)
commissioner.investigate(processed_source)
result = commissioner.investigate(processed_source)
# Store offenses in the cop for backward compatibility with existing tests
def cop.offenses
@offenses ||= []
end
cop.instance_variable_set(:@offenses, result.offenses)
Comment on lines +23 to +28
Copy link
Preview

Copilot AI Jun 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The investigate method returns nil in RuboCop v1, so result.offenses will raise a NoMethodError. Instead, call commissioner.investigate(processed_source) without assignment and extract offenses from the cop instance (e.g., use cop.instance_variable_get(:@offenses) directly).

Suggested change
result = commissioner.investigate(processed_source)
# Store offenses in the cop for backward compatibility with existing tests
def cop.offenses
@offenses ||= []
end
cop.instance_variable_set(:@offenses, result.offenses)
commissioner.investigate(processed_source)
# Store offenses in the cop for backward compatibility with existing tests
def cop.offenses
@offenses ||= []
end
cop.instance_variable_set(:@offenses, cop.instance_variable_get(:@offenses))

Copilot uses AI. Check for mistakes.

commissioner
end

Expand Down
Loading