diff --git a/CHANGELOG.md b/CHANGELOG.md index e4a8d5a72..1d54f8517 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### New features +* [#36](https://github.com/rubocop-hq/rubocop-ast/pull/36): Add `post_condition_loop?` and `loop_keyword?` for `Node`. ([@fatkodima][]) * [#38](https://github.com/rubocop-hq/rubocop-ast/pull/38): Add helpers allowing to check whether the method is a nonmutating operator method or a nonmutating method of several core classes. ([@fatkodima][]) * [#37](https://github.com/rubocop-hq/rubocop-ast/pull/37): Add `enumerable_method?` for `MethodIdentifierPredicates`. ([@fatkodima][]) * [#4](https://github.com/rubocop-hq/rubocop-ast/issues/4): Add `interpolation?` for `RegexpNode`. ([@tejasbubane][]) diff --git a/lib/rubocop/ast/node.rb b/lib/rubocop/ast/node.rb index e23b0b665..2efd2542c 100644 --- a/lib/rubocop/ast/node.rb +++ b/lib/rubocop/ast/node.rb @@ -44,6 +44,8 @@ class Node < Parser::AST::Node # rubocop:disable Metrics/ClassLength BASIC_CONDITIONALS = %i[if while until].freeze CONDITIONALS = [*BASIC_CONDITIONALS, :case].freeze + POST_CONDITION_LOOP_TYPES = %i[while_post until_post].freeze + LOOP_TYPES = (POST_CONDITION_LOOP_TYPES + %i[while until for]).freeze VARIABLES = %i[ivar gvar cvar lvar].freeze REFERENCES = %i[nth_ref back_ref].freeze KEYWORDS = %i[alias and break case class def defs defined? @@ -426,6 +428,14 @@ def conditional? CONDITIONALS.include?(type) end + def post_condition_loop? + POST_CONDITION_LOOP_TYPES.include?(type) + end + + def loop_keyword? + LOOP_TYPES.include?(type) + end + def keyword? return true if special_keyword? || send_type? && prefix_not? return false unless KEYWORDS.include?(type) diff --git a/spec/rubocop/ast/for_node_spec.rb b/spec/rubocop/ast/for_node_spec.rb index 94b84bb75..bb7e6e710 100644 --- a/spec/rubocop/ast/for_node_spec.rb +++ b/spec/rubocop/ast/for_node_spec.rb @@ -60,4 +60,16 @@ it { expect(for_node.body.sym_type?).to be(true) } end + + describe '#post_condition_loop?' do + let(:source) { 'for foo in bar; baz; end' } + + it { expect(for_node.post_condition_loop?).to be_falsey } + end + + describe '#loop_keyword?' do + let(:source) { 'for foo in bar; baz; end' } + + it { expect(for_node.loop_keyword?).to be_truthy } + end end diff --git a/spec/rubocop/ast/send_node_spec.rb b/spec/rubocop/ast/send_node_spec.rb index 4acd3d12a..5f93b4d12 100644 --- a/spec/rubocop/ast/send_node_spec.rb +++ b/spec/rubocop/ast/send_node_spec.rb @@ -1414,4 +1414,16 @@ module Foo it { expect(send_node.binary_operation?).to be(false) } end end + + describe '#post_condition_loop?' do + let(:source) { 'foo(bar)' } + + it { expect(send_node.post_condition_loop?).to be(false) } + end + + describe '#loop_keyword?' do + let(:source) { 'foo(bar)' } + + it { expect(send_node.loop_keyword?).to be(false) } + end end diff --git a/spec/rubocop/ast/until_node_spec.rb b/spec/rubocop/ast/until_node_spec.rb index e2d4679ad..549e99159 100644 --- a/spec/rubocop/ast/until_node_spec.rb +++ b/spec/rubocop/ast/until_node_spec.rb @@ -42,4 +42,32 @@ it { expect(until_node.do?).to be_falsey } end end + + describe '#post_condition_loop?' do + context 'with a statement until' do + let(:source) { 'until foo; bar; end' } + + it { expect(until_node.post_condition_loop?).to be_falsey } + end + + context 'with a modifier until' do + let(:source) { 'begin foo; end until bar' } + + it { expect(until_node.post_condition_loop?).to be_truthy } + end + end + + describe '#loop_keyword?' do + context 'with a statement until' do + let(:source) { 'until foo; bar; end' } + + it { expect(until_node.loop_keyword?).to be_truthy } + end + + context 'with a modifier until' do + let(:source) { 'begin foo; end until bar' } + + it { expect(until_node.loop_keyword?).to be_truthy } + end + end end diff --git a/spec/rubocop/ast/while_node_spec.rb b/spec/rubocop/ast/while_node_spec.rb index 4933203b8..74a14997a 100644 --- a/spec/rubocop/ast/while_node_spec.rb +++ b/spec/rubocop/ast/while_node_spec.rb @@ -42,4 +42,32 @@ it { expect(while_node.do?).to be_falsey } end end + + describe '#post_condition_loop?' do + context 'with a statement while' do + let(:source) { 'while foo; bar; end' } + + it { expect(while_node.post_condition_loop?).to be_falsey } + end + + context 'with a modifier while' do + let(:source) { 'begin foo; end while bar' } + + it { expect(while_node.post_condition_loop?).to be_truthy } + end + end + + describe '#loop_keyword?' do + context 'with a statement while' do + let(:source) { 'while foo; bar; end' } + + it { expect(while_node.loop_keyword?).to be_truthy } + end + + context 'with a modifier while' do + let(:source) { 'begin foo; end while bar' } + + it { expect(while_node.loop_keyword?).to be_truthy } + end + end end