From d2da4a43b51b72557917f60b879313107425c989 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Sun, 5 Mar 2023 01:36:06 +0900 Subject: [PATCH] Fix an error for `Style/Documentation` This PR fixes an error for `Style/Documentation` when namespace is a variable. ```ruby m = Module.new module n::N def method end end ``` ```console % rubocop documentation.rb --only Style/Documentation -d (snip) undefined method `namespace' for s(:lvar, :m):RuboCop::AST::Node /Users/koic/src/github.com/rubocop/rubocop/lib/rubocop/cop/style/documentation.rb:187:in `qualify_const' /Users/koic/src/github.com/rubocop/rubocop/lib/rubocop/cop/style/documentation.rb:187:in `qualify_const' /Users/koic/src/github.com/rubocop/rubocop/lib/rubocop/cop/style/documentation.rb:181:in `block in identifier' ``` It also complements missing cbase and namespaces in offense messages. e.g.: ```diff class ::MyClass -^^^^^^^^^^^^^^^ Missing top-level documentation comment for `class MyClass`. +^^^^^^^^^^^^^^^ Missing top-level documentation comment for `class ::MyClass`. ``` ```diff class self::MyClass -^^^^^^^^^^^^^^^^^^^ Missing top-level documentation comment for `class MyClass`. +^^^^^^^^^^^^^^^^^^^ Missing top-level documentation comment for `class self::MyClass`. ``` ```diff class my_method::MyClass -^^^^^^^^^^^^^^^^^^^^^^^^ Missing top-level documentation comment for `class MyClass`. +^^^^^^^^^^^^^^^^^^^^^^^^ Missing top-level documentation comment for `class my_method::MyClass`. ``` --- .../fix_an_error_for_style_documentation.md | 1 + lib/rubocop/cop/style/documentation.rb | 12 +++- spec/rubocop/cop/style/documentation_spec.rb | 69 ++++++++++++++++++- 3 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 changelog/fix_an_error_for_style_documentation.md diff --git a/changelog/fix_an_error_for_style_documentation.md b/changelog/fix_an_error_for_style_documentation.md new file mode 100644 index 000000000000..f11c04be381f --- /dev/null +++ b/changelog/fix_an_error_for_style_documentation.md @@ -0,0 +1 @@ +* [#11661](https://github.com/rubocop/rubocop/pull/11661): Fix an error for `Style/Documentation` when namespace is a variable. ([@koic][]) diff --git a/lib/rubocop/cop/style/documentation.rb b/lib/rubocop/cop/style/documentation.rb index 5329582e5d2c..bddc16cb9466 100644 --- a/lib/rubocop/cop/style/documentation.rb +++ b/lib/rubocop/cop/style/documentation.rb @@ -178,13 +178,19 @@ def allowed_constants def identifier(node) # Get the fully qualified identifier for a class/module nodes = [node, *node.each_ancestor(:class, :module)] - nodes.reverse_each.flat_map { |n| qualify_const(n.identifier) }.join('::') + identifier = nodes.reverse_each.flat_map { |n| qualify_const(n.identifier) }.join('::') + + identifier.sub('::::', '::') end def qualify_const(node) - return if node.nil? || node.cbase_type? || node.self_type? || node.send_type? + return if node.nil? - [qualify_const(node.namespace), node.short_name].compact + if node.cbase_type? || node.self_type? || node.call_type? || node.variable? + node.source + else + [qualify_const(node.namespace), node.short_name].compact + end end end end diff --git a/spec/rubocop/cop/style/documentation_spec.rb b/spec/rubocop/cop/style/documentation_spec.rb index ddf9c3606244..96768646017e 100644 --- a/spec/rubocop/cop/style/documentation_spec.rb +++ b/spec/rubocop/cop/style/documentation_spec.rb @@ -20,7 +20,7 @@ def method it 'registers an offense for non-empty cbase class' do expect_offense(<<~RUBY) class ::MyClass - ^^^^^^^^^^^^^^^ Missing top-level documentation comment for `class MyClass`. + ^^^^^^^^^^^^^^^ Missing top-level documentation comment for `class ::MyClass`. def method end end @@ -30,7 +30,7 @@ def method it 'registers an offense for non-empty class nested under self' do expect_offense(<<~RUBY) class self::MyClass - ^^^^^^^^^^^^^^^^^^^ Missing top-level documentation comment for `class MyClass`. + ^^^^^^^^^^^^^^^^^^^ Missing top-level documentation comment for `class self::MyClass`. def method end end @@ -40,7 +40,70 @@ def method it 'registers an offense for non-empty class nested under method call' do expect_offense(<<~RUBY) class my_method::MyClass - ^^^^^^^^^^^^^^^^^^^^^^^^ Missing top-level documentation comment for `class MyClass`. + ^^^^^^^^^^^^^^^^^^^^^^^^ Missing top-level documentation comment for `class my_method::MyClass`. + def method + end + end + RUBY + end + + it 'registers an offense for non-empty class nested under safe navigation method call' do + expect_offense(<<~RUBY) + class obj&.my_method::MyClass + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Missing top-level documentation comment for `class obj&.my_method::MyClass`. + def method + end + end + RUBY + end + + it 'registers an offense for non-empty class nested under local variable' do + expect_offense(<<~RUBY) + m = Module.new + module m::N + ^^^^^^^^^^^ Missing top-level documentation comment for `module m::N`. + def method + end + end + RUBY + end + + it 'registers an offense for non-empty class nested under instance variable' do + expect_offense(<<~RUBY) + module @m::N + ^^^^^^^^^^^^ Missing top-level documentation comment for `module @m::N`. + def method + end + end + RUBY + end + + it 'registers an offense for non-empty class nested under class variable' do + expect_offense(<<~RUBY) + module @@m::N + ^^^^^^^^^^^^^ Missing top-level documentation comment for `module @@m::N`. + def method + end + end + RUBY + end + + it 'registers an offense for non-empty class nested under global variable' do + expect_offense(<<~RUBY) + module $m::N + ^^^^^^^^^^^^ Missing top-level documentation comment for `module $m::N`. + def method + end + end + RUBY + end + + it 'registers an offense for non-empty class nested under local variables' do + expect_offense(<<~RUBY) + m = Module.new + n = Module.new + module m::n::M + ^^^^^^^^^^^^^^ Missing top-level documentation comment for `module m::n::M`. def method end end