Skip to content

Commit

Permalink
Improve parent_module_name (#177)
Browse files Browse the repository at this point in the history
* Fix unexpected non-local exits on Rubocop::AST::Node#parent_module_name

With this PR, when Rubocop::AST::Node#parent_module_name_part is executed, it will no longer do non-local exits when a block is evaluated, and evaluating singleton_class or block in Rubocop::AST::Node#parent_module_name will behave as expected.
With this change, this PR aims to resolve the following issue.

rubocop/rubocop#5022

Co-authored-by: masatoshi_moritsuka <yakiyaki_ikayaki@yahoo.co.jp>
  • Loading branch information
marcandre and sanfrecce-osaka committed May 26, 2021
1 parent 2c85e6a commit e303401
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 7 deletions.
@@ -0,0 +1 @@
* [#176](https://github.com/rubocop-hq/rubocop-ast/pull/176): Fix unexpected non-local exits on Rubocop::AST::Node#parent_module_name. ([@sanfrecce-osaka][])
8 changes: 3 additions & 5 deletions lib/rubocop/ast/node.rb
Expand Up @@ -612,19 +612,17 @@ def while_until_value_used?
def parent_module_name_part(node)
case node.type
when :class, :module, :casgn
# TODO: if constant name has cbase (leading ::), then we don't need
# to keep traversing up through nested classes/modules
# TODO: if constant name has cbase (leading ::), then we must not
# keep traversing up through nested classes/modules
node.defined_module_name
when :sclass
yield parent_module_name_for_sclass(node)
parent_module_name_for_sclass(node)
else # block
parent_module_name_for_block(node) { yield nil }
end
end

def parent_module_name_for_sclass(sclass_node)
# TODO: look for constant definition and see if it is nested
# inside a class or module
subject = sclass_node.children[0]

if subject.const_type?
Expand Down
1 change: 0 additions & 1 deletion spec/rubocop/ast/node_pattern_spec.rb
Expand Up @@ -10,7 +10,6 @@ def parse(code)
builder = RuboCop::AST::Builder.new
Parser::CurrentRuby.new(builder).parse(buffer)
end

let(:root_node) { parse(ruby) }
let(:node) { root_node }
let(:params) { [] }
Expand Down
69 changes: 68 additions & 1 deletion 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
Expand Down Expand Up @@ -659,4 +659,71 @@ 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::#<Class: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::#<Class: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
end
end

0 comments on commit e303401

Please sign in to comment.