Skip to content

Commit

Permalink
Merge pull request #11332 from fatkodima/class_structure-private-cons…
Browse files Browse the repository at this point in the history
…tants

Ignore private constants in `Layout/ClassStructure` cop
  • Loading branch information
koic committed Dec 29, 2022
2 parents fa401dc + bf6c018 commit aaa4166
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#8366](https://github.com/rubocop/rubocop/issues/8366): Ignore private constants in `Layout/ClassStructure` cop. ([@fatkodima][])
3 changes: 0 additions & 3 deletions lib/rubocop/cop/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -329,11 +329,8 @@ def begin_investigation(processed_source)
@current_corrector = nil
end

# rubocop:disable Layout/ClassStructure
EMPTY_OFFENSES = [].freeze
private_constant :EMPTY_OFFENSES
# rubocop:enable Layout/ClassStructure

# Called to complete an investigation
def complete_investigation
InvestigationReport.new(
Expand Down
27 changes: 23 additions & 4 deletions lib/rubocop/cop/layout/class_structure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ def find_category(node)
def walk_over_nested_class_definition(class_node)
class_elements(class_node).each do |node|
classification = classify(node)
next if ignore?(classification)
next if ignore?(node, classification)

yield node, classification
end
Expand All @@ -234,17 +234,20 @@ def class_elements(class_node)
end
end

def ignore?(classification)
def ignore?(node, classification)
classification.nil? ||
classification.to_s.end_with?('=') ||
expected_order.index(classification).nil?
expected_order.index(classification).nil? ||
private_constant?(node)
end

def ignore_for_autocorrect?(node, sibling)
classification = classify(node)
sibling_class = classify(sibling)

ignore?(sibling_class) || classification == sibling_class || dynamic_constant?(node)
ignore?(sibling, sibling_class) ||
classification == sibling_class ||
dynamic_constant?(node)
end

def humanize_node(node)
Expand All @@ -264,6 +267,22 @@ def dynamic_constant?(node)
!(expression.method?(:freeze) && expression.receiver&.recursive_basic_literal?)
end

def private_constant?(node)
return false unless node.casgn_type? && node.namespace.nil?
return false unless (parent = node.parent)

parent.each_child_node(:send) do |child_node|
return true if marked_as_private_constant?(child_node, node.name)
end
false
end

def marked_as_private_constant?(node, name)
return false unless node.method?(:private_constant)

node.arguments.any? { |arg| (arg.sym_type? || arg.str_type?) && arg.value == name }
end

def source_range_with_comment(node)
begin_pos, end_pos =
if (node.def_type? && !node.method?(:initialize)) ||
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/cop/mixin/annotation_comment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def split_comment(comment)
match.captures
end

KEYWORDS_REGEX_CACHE = {} # rubocop:disable Layout/ClassStructure, Style/MutableConstant
KEYWORDS_REGEX_CACHE = {} # rubocop:disable Style/MutableConstant
private_constant :KEYWORDS_REGEX_CACHE

def regex
Expand Down
3 changes: 0 additions & 3 deletions lib/rubocop/cop/variable_force.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ def skip_children!
:skip_children
end

# rubocop:disable Layout/ClassStructure
NODE_HANDLER_METHOD_NAMES = [
[VARIABLE_ASSIGNMENT_TYPE, :process_variable_assignment],
[REGEXP_NAMED_CAPTURE_TYPE, :process_regexp_named_captures],
Expand All @@ -123,8 +122,6 @@ def skip_children!
*SCOPE_TYPES.product([:process_scope])
].to_h.freeze
private_constant :NODE_HANDLER_METHOD_NAMES
# rubocop:enable Layout/ClassStructure

def node_handler_method_name(node)
NODE_HANDLER_METHOD_NAMES[node.type]
end
Expand Down
3 changes: 0 additions & 3 deletions lib/rubocop/target_ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,6 @@ def self.supported_versions
KNOWN_RUBIES
end

# rubocop:disable Layout/ClassStructure
SOURCES = [
RuboCopConfig,
RubyVersionFile,
Expand All @@ -245,8 +244,6 @@ def self.supported_versions
].freeze

private_constant :SOURCES
# rubocop:enable Layout/ClassStructure

def initialize(config)
@config = config
end
Expand Down
25 changes: 25 additions & 0 deletions spec/rubocop/cop/layout/class_structure_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,31 @@ def name; end
RUBY
end

it 'ignores misplaced private constants' do
expect_offense(<<~RUBY)
class Foo
def name; end
PRIVATE_CONST1 = 1
PRIVATE_CONST2 = 2
private_constant :PRIVATE_CONST1, :PRIVATE_CONST2
PUBLIC_CONST = 'public'
^^^^^^^^^^^^^^^^^^^^^^^ `constants` is supposed to appear before `public_methods`.
end
RUBY

expect_correction(<<~RUBY)
class Foo
PUBLIC_CONST = 'public'
def name; end
PRIVATE_CONST1 = 1
PRIVATE_CONST2 = 2
private_constant :PRIVATE_CONST1, :PRIVATE_CONST2
end
RUBY
end

it 'registers an offense and corrects when str heredoc constant is defined after public method' do
expect_offense(<<~RUBY)
class Foo
Expand Down

0 comments on commit aaa4166

Please sign in to comment.