diff --git a/changelog/fix_fix_184_fix_nodeparent_module_name_for.md b/changelog/fix_fix_184_fix_nodeparent_module_name_for.md new file mode 100644 index 000000000..4c7173e55 --- /dev/null +++ b/changelog/fix_fix_184_fix_nodeparent_module_name_for.md @@ -0,0 +1 @@ +* [#197](https://github.com/rubocop-hq/rubocop-ast/pull/197): [Fix #184] Fix `Node#parent_module_name` for `sclass` nodes. ([@dvandersluis][]) diff --git a/lib/rubocop/ast/node.rb b/lib/rubocop/ast/node.rb index 98fddd52d..89efc3c13 100644 --- a/lib/rubocop/ast/node.rb +++ b/lib/rubocop/ast/node.rb @@ -317,7 +317,11 @@ def parent_module_name # returns nil if answer cannot be determined ancestors = each_ancestor(:class, :module, :sclass, :casgn, :block) result = ancestors.map do |ancestor| - parent_module_name_part(ancestor) { |full_name| return full_name } + parent_module_name_part(ancestor) do |full_name| + return nil unless full_name + + full_name + end end.compact.reverse.join('::') result.empty? ? 'Object' : result end diff --git a/spec/rubocop/ast/node_spec.rb b/spec/rubocop/ast/node_spec.rb index d27828b80..eb87d2927 100644 --- a/spec/rubocop/ast/node_spec.rb +++ b/spec/rubocop/ast/node_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true RSpec.describe RuboCop::AST::Node do - let(:ast) { RuboCop::AST::ProcessedSource.new(src, ruby_version).ast } + let(:ast) { parse_source(src).node } let(:node) { ast } describe '#value_used?' do @@ -659,4 +659,86 @@ def variables; end end end end + + describe '#parent_module_name' do + subject(:parent_module_name) { node.parent_module_name } + + context 'when node on top level' do + let(:src) { 'def config; end' } + + it { is_expected.to eq 'Object' } + end + + context 'when node on module' do + let(:src) do + <<~RUBY + module Foo + >>attr_reader :config<< + end + RUBY + end + + it { is_expected.to eq 'Foo' } + end + + context 'when node on singleton class' do + let(:src) do + <<~RUBY + module Foo + class << self + >>attr_reader :config<< + end + end + RUBY + end + + it { is_expected.to eq 'Foo::#' } + end + + context 'when node on class in singleton class' do + let(:src) do + <<~RUBY + module Foo + class << self + class Bar + >>attr_reader :config<< + end + end + end + RUBY + end + + it { is_expected.to eq 'Foo::#::Bar' } + end + + context 'when node nested in an unknown block' do + let(:src) do + <<~RUBY + module Foo + foo do + class Bar + >>attr_reader :config<< + end + end + end + RUBY + end + + it { is_expected.to eq nil } + end + + context 'when node nested in a class << exp' do + let(:src) do + <<~RUBY + class A + class << expr + >>attr_reader :config<< + end + end + RUBY + end + + it { is_expected.to eq nil } + end + end end