From 109ac2767234b5b1a87472a8ab33b64e656b7a7e Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Wed, 30 Sep 2020 19:25:09 +0900 Subject: [PATCH] Fix an error for `Metrics/ClassLength` Follow #8122. This PR fixes the following error for `Metrics/ClassLength` when using or assignment (`||=`). ```console % cat example.rb Constant ||= Struct.new {} % bundle exec rubocop --only Layout/ClassLength -d example.rb (snip) Inspecting 1 file Scanning /Users/koic/src/github.com/koic/rubocop-issues/8122/example.rb An error occurred while Metrics/ClassLength cop was inspecting /Users/koic/src/github.com/koic/rubocop-issues/8122/example.rb:1:0. undefined method `class_definition?' for nil:NilClass /Users/koic/src/github.com/rubocop-hq/rubocop/lib/rubocop/cop/metrics/class_length.rb:43:in `on_casgn' /Users/koic/src/github.com/rubocop-hq/rubocop/lib/rubocop/cop/commissioner.rb:99:in `block (2 levels) in trigger_responding_cops' /Users/koic/src/github.com/rubocop-hq/rubocop/lib/rubocop/cop/commissioner.rb:152:in `with_cop_error_handling' /Users/koic/src/github.com/rubocop-hq/rubocop/lib/rubocop/cop/commissioner.rb:98:in `block in trigger_responding_cops' /Users/koic/src/github.com/rubocop-hq/rubocop/lib/rubocop/cop/commissioner.rb:97:in `each' /Users/koic/src/github.com/rubocop-hq/rubocop/lib/rubocop/cop/commissioner.rb:97:in `trigger_responding_cops' /Users/koic/src/github.com/rubocop-hq/rubocop/lib/rubocop/cop/commissioner.rb:70:in `on_casgn' /Users/koic/src/github.com/rubocop-hq/rubocop-ast/lib/rubocop/ast/traversal.rb:60:in `block in on_or_asgn' /Users/koic/src/github.com/rubocop-hq/rubocop-ast/lib/rubocop/ast/traversal.rb:60:in `each' /Users/koic/src/github.com/rubocop-hq/rubocop-ast/lib/rubocop/ast/traversal.rb:60:in `on_or_asgn' /Users/koic/src/github.com/rubocop-hq/rubocop/lib/rubocop/cop/commissioner.rb:72:in `on_or_asgn' /Users/koic/src/github.com/rubocop-hq/rubocop-ast/lib/rubocop/ast/traversal.rb:14:in `walk' /Users/koic/src/github.com/rubocop-hq/rubocop/lib/rubocop/cop/commissioner.rb:85:in `investigate' ``` This PR have also tweaked the highlight area of offense to more eligible location for count the class block length. Before: ```ruby Foo = Class.new do ^^^ Class has too many lines. [6/5] ``` After: ```ruby Foo = Class.new do ^^^^^^^^^^^^ Class has too many lines. [6/5] ``` I haven't added the fixing to the changelog because #8122 hasn't been released yet. --- lib/rubocop/cop/metrics/class_length.rb | 9 +++++++-- spec/rubocop/cop/metrics/class_length_spec.rb | 20 ++++++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/lib/rubocop/cop/metrics/class_length.rb b/lib/rubocop/cop/metrics/class_length.rb index 1f0f7d5d243..22634b4f36a 100644 --- a/lib/rubocop/cop/metrics/class_length.rb +++ b/lib/rubocop/cop/metrics/class_length.rb @@ -39,8 +39,13 @@ def on_class(node) end def on_casgn(node) - _scope, _name, block_node = *node - check_code_length(node) if block_node.class_definition? + if node.parent&.assignment? + block_node = node.parent.children[1] + else + _scope, _name, block_node = *node + end + + check_code_length(block_node) if block_node.class_definition? end private diff --git a/spec/rubocop/cop/metrics/class_length_spec.rb b/spec/rubocop/cop/metrics/class_length_spec.rb index 85f1a741bb5..9ae48f3f5e2 100644 --- a/spec/rubocop/cop/metrics/class_length_spec.rb +++ b/spec/rubocop/cop/metrics/class_length_spec.rb @@ -174,7 +174,7 @@ class Test it 'registers an offense' do expect_offense(<<~RUBY) Foo = Class.new do - ^^^ Class has too many lines. [6/5] + ^^^^^^^^^^^^ Class has too many lines. [6/5] a = 1 a = 2 a = 3 @@ -190,7 +190,7 @@ class Test it 'registers an offense' do expect_offense(<<~RUBY) Foo = ::Class.new do - ^^^ Class has too many lines. [6/5] + ^^^^^^^^^^^^^^ Class has too many lines. [6/5] a = 1 a = 2 a = 3 @@ -206,7 +206,21 @@ class Test it 'registers an offense' do expect_offense(<<~RUBY) Foo = Struct.new(:foo, :bar) do - ^^^ Class has too many lines. [6/5] + ^^^^^^^^^^^^^^^^^^^^^^^^^ Class has too many lines. [6/5] + a = 1 + a = 2 + a = 3 + a = 4 + a = 5 + a = 6 + end + RUBY + end + + it 'registers an offense when inspecting or equals (`||=`) for consntant' do + expect_offense(<<~RUBY) + Foo ||= Struct.new(:foo, :bar) do + ^^^^^^^^^^^^^^^^^^^^^^^^^ Class has too many lines. [6/5] a = 1 a = 2 a = 3