Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
RescueNode
. Add ResbodyNode#exceptions
and `ResbodyNode#branc…
…h_index`
- Loading branch information
Showing
7 changed files
with
254 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module AST | ||
# A node extension for `rescue` nodes. This will be used in place of a | ||
# plain node when the builder constructs the AST, making its methods | ||
# available to all `rescue` nodes within RuboCop. | ||
class RescueNode < Node | ||
# Returns the body of the rescue node. | ||
# | ||
# @return [Node, nil] The body of the rescue node. | ||
def body | ||
node_parts[0] | ||
end | ||
|
||
# Returns an array of all the rescue branches in the exception handling statement. | ||
# | ||
# @return [Array<ResbodyNode>] an array of `resbody` nodes | ||
def resbody_branches | ||
node_parts[1...-1] | ||
end | ||
|
||
# Returns an array of all the rescue branches in the exception handling statement. | ||
# | ||
# @return [Array<Node, nil>] an array of the bodies of the rescue branches | ||
# and the else (if any). Note that these bodies could be nil. | ||
def branches | ||
bodies = resbody_branches.map(&:body) | ||
bodies.push(else_branch) if else? | ||
bodies | ||
end | ||
|
||
# Returns the else branch of the exception handling statement, if any. | ||
# | ||
# @return [Node] the else branch node of the exception handling statement | ||
# @return [nil] if the exception handling statement does not have an else branch. | ||
def else_branch | ||
node_parts[-1] | ||
end | ||
|
||
# Checks whether this exception handling statement has an `else` branch. | ||
# | ||
# @return [Boolean] whether the exception handling statement has an `else` branch | ||
def else? | ||
loc.else | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe RuboCop::AST::RescueNode do | ||
let(:ast) { parse_source(source).ast } | ||
let(:rescue_node) { ast.children.first } | ||
|
||
describe '.new' do | ||
let(:source) { <<~RUBY } | ||
begin | ||
rescue => e | ||
end | ||
RUBY | ||
|
||
it { expect(rescue_node.is_a?(described_class)).to be(true) } | ||
end | ||
|
||
describe '#body' do | ||
let(:source) { <<~RUBY } | ||
begin | ||
foo | ||
rescue => e | ||
end | ||
RUBY | ||
|
||
it { expect(rescue_node.body.send_type?).to be(true) } | ||
end | ||
|
||
describe '#resbody_branches' do | ||
let(:source) { <<~RUBY } | ||
begin | ||
rescue FooError then foo | ||
rescue BarError, BazError then bar_and_baz | ||
end | ||
RUBY | ||
|
||
it { expect(rescue_node.resbody_branches.size).to eq(2) } | ||
it { expect(rescue_node.resbody_branches).to all(be_resbody_type) } | ||
end | ||
|
||
describe '#branches' do | ||
context 'when there is an else' do | ||
let(:source) { <<~RUBY } | ||
begin | ||
rescue FooError then foo | ||
rescue BarError then # do nothing | ||
else 'bar' | ||
end | ||
RUBY | ||
|
||
it 'returns all the bodies' do | ||
expect(rescue_node.branches).to match [be_send_type, nil, be_str_type] | ||
end | ||
|
||
context 'with an empty else' do | ||
let(:source) { <<~RUBY } | ||
begin | ||
rescue FooError then foo | ||
rescue BarError then # do nothing | ||
else # do nothing | ||
end | ||
RUBY | ||
|
||
it 'returns all the bodies' do | ||
expect(rescue_node.branches).to match [be_send_type, nil, nil] | ||
end | ||
end | ||
end | ||
|
||
context 'when there is no else keyword' do | ||
let(:source) { <<~RUBY } | ||
begin | ||
rescue FooError then foo | ||
rescue BarError then # do nothing | ||
end | ||
RUBY | ||
|
||
it 'returns only then rescue bodies' do | ||
expect(rescue_node.branches).to match [be_send_type, nil] | ||
end | ||
end | ||
end | ||
|
||
describe '#else_branch' do | ||
context 'without an else statement' do | ||
let(:source) { <<~RUBY } | ||
begin | ||
rescue FooError then foo | ||
end | ||
RUBY | ||
|
||
it { expect(rescue_node.else_branch.nil?).to be(true) } | ||
end | ||
|
||
context 'with an else statement' do | ||
let(:source) { <<~RUBY } | ||
begin | ||
rescue FooError then foo | ||
else bar | ||
end | ||
RUBY | ||
|
||
it { expect(rescue_node.else_branch.send_type?).to be(true) } | ||
end | ||
end | ||
|
||
describe '#else?' do | ||
context 'without an else statement' do | ||
let(:source) { <<~RUBY } | ||
begin | ||
rescue FooError then foo | ||
end | ||
RUBY | ||
|
||
it { expect(rescue_node.else?).to be_falsey } | ||
end | ||
|
||
context 'with an else statement' do | ||
let(:source) { <<~RUBY } | ||
begin | ||
rescue FooError then foo | ||
else bar | ||
end | ||
RUBY | ||
|
||
it { expect(rescue_node.else?).to be_truthy } | ||
end | ||
end | ||
end |