Skip to content

Commit

Permalink
[Fix #10221] Update Naming::FileName to recognize Structs as clas…
Browse files Browse the repository at this point in the history
…ses that satisfy the `ExpectMatchingDefinition` requirement.
  • Loading branch information
dvandersluis authored and bbatsov committed Nov 12, 2021
1 parent 031c580 commit 1707630
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 1 deletion.
1 change: 1 addition & 0 deletions changelog/change_update_namingfilename_to_recognize.md
@@ -0,0 +1 @@
* [#10221](https://github.com/rubocop/rubocop/issues/10221): Update `Naming::FileName` to recognize `Struct`s as classes that satisfy the `ExpectMatchingDefinition` requirement. ([@dvandersluis][])
1 change: 1 addition & 0 deletions config/default.yml
Expand Up @@ -2506,6 +2506,7 @@ Naming/FileName:
StyleGuide: '#snake-case-files'
Enabled: true
VersionAdded: '0.50'
VersionChanged: '<<next>>'
# Camel case file names listed in `AllCops:Include` and all file names listed
# in `AllCops:Exclude` are excluded by default. Add extra excludes here.
Exclude: []
Expand Down
19 changes: 18 additions & 1 deletion lib/rubocop/cop/naming/file_name.rb
Expand Up @@ -33,6 +33,14 @@ class FileName < Base

SNAKE_CASE = /^[\d[[:lower:]]_.?!]+$/.freeze

# @!method struct_definition(node)
def_node_matcher :struct_definition, <<~PATTERN
{
(casgn $_ $_ (send (const {nil? cbase} :Struct) :new ...))
(casgn $_ $_ (block (send (const {nil? cbase} :Struct) :new ...) ...))
}
PATTERN

def on_new_investigation
file_path = processed_source.file_path
return if config.file_to_exclude?(file_path) || config.allowed_camel_case_file?(file_path)
Expand Down Expand Up @@ -126,7 +134,7 @@ def find_class_or_module(node, namespace)
name = namespace.pop

on_node(%i[class module casgn], node) do |child|
next unless (const = child.defined_module)
next unless (const = find_definition(child))

const_namespace, const_name = *const
next if name != const_name && !match_acronym?(name, const_name)
Expand All @@ -138,6 +146,15 @@ def find_class_or_module(node, namespace)
nil
end

def find_definition(node)
node.defined_module || defined_struct(node)
end

def defined_struct(node)
namespace, name = *struct_definition(node)
s(:const, namespace, name) if name
end

def match_namespace(node, namespace, expected)
match_partial = partial_matcher!(expected)

Expand Down
58 changes: 58 additions & 0 deletions spec/rubocop/cop/naming/file_name_spec.rb
Expand Up @@ -251,6 +251,23 @@ class B
end
RUBY
end

context 'on a file which defines a Struct without a block' do
include_examples 'matching module or class', <<~RUBY
module A
B = Struct.new(:foo, :bar)
end
RUBY
end

context 'on a file which defines a Struct with a block' do
include_examples 'matching module or class', <<~RUBY
module A
B = Struct.new(:foo, :bar) do
end
end
RUBY
end
end

context 'when CheckDefinitionPathHierarchy is false' do
Expand Down Expand Up @@ -285,6 +302,23 @@ class PictureCollection
end
end

context 'on a file with a matching struct' do
it 'does not register an offense' do
expect_no_offenses(<<~RUBY, '/lib/image_collection.rb')
ImageCollection = Struct.new
RUBY
end
end

context 'on a file with a non-matching struct' do
it 'registers an offense' do
expect_offense(<<~RUBY, '/lib/image_collection.rb')
PictureCollection = Struct.new
^ `image_collection.rb` should define a class or module called `ImageCollection`.
RUBY
end
end

context 'on an empty file' do
it 'registers an offense' do
expect_offense(<<~RUBY, '/lib/rubocop/foo.rb')
Expand Down Expand Up @@ -329,6 +363,30 @@ class NonMatching
RUBY
end
end

context 'with a non-matching module containing a matching struct' do
it 'does not register an offense' do
expect_no_offenses(<<~RUBY, 'lib/foo.rb')
begin
module NonMatching
Foo = Struct.new
end
end
RUBY
end
end

context 'with a matching module containing a non-matching struct' do
it 'does not register an offense' do
expect_no_offenses(<<~RUBY, 'lib/foo.rb')
begin
module Foo
NonMatching = Struct.new
end
end
RUBY
end
end
end

context 'when Regex is set' do
Expand Down

0 comments on commit 1707630

Please sign in to comment.