diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a3eb678f..3e2a0ac93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### New features * [#4](https://github.com/rubocop-hq/rubocop-ast/issues/4): Add `interpolation?` for `RegexpNode`. ([@tejasbubane][]) +* [#20](https://github.com/rubocop-hq/rubocop-ast/pull/20): Add option predicates for `RegexpNode`. ([@owst][]) ## 0.0.3 (2020-05-15) @@ -28,3 +29,4 @@ * Gem extracted from RuboCop. ([@marcandre][]) [@marcandre]: https://github.com/marcandre +[@owst]: https://github.com/owst diff --git a/lib/rubocop/ast/node/regexp_node.rb b/lib/rubocop/ast/node/regexp_node.rb index dfa04c136..783c8c698 100644 --- a/lib/rubocop/ast/node/regexp_node.rb +++ b/lib/rubocop/ast/node/regexp_node.rb @@ -36,6 +36,37 @@ def content def interpolation? children.any?(&:begin_type?) end + + # @return [Bool] if regexp uses the multiline regopt + def multiline? + regopt_include?(:m) + end + + # @return [Bool] if regexp uses the extended regopt + def extended? + regopt_include?(:x) + end + + # @return [Bool] if regexp uses the ignore-case regopt + def ignore_case? + regopt_include?(:i) + end + + # @return [Bool] if regexp uses the single-interpolation regopt + def single_interpolation? + regopt_include?(:o) + end + + # @return [Bool] if regexp uses the no-encoding regopt + def no_encoding? + regopt_include?(:n) + end + + private + + def regopt_include?(option) + regopt.children.include?(option) + end end end end diff --git a/spec/rubocop/ast/regexp_node_spec.rb b/spec/rubocop/ast/regexp_node_spec.rb index e2d605eb0..f0b319bb8 100644 --- a/spec/rubocop/ast/regexp_node_spec.rb +++ b/spec/rubocop/ast/regexp_node_spec.rb @@ -160,4 +160,134 @@ it { expect(regexp_node.interpolation?).to eq(false) } end end + + describe '#multiline?' do + context 'with no options' do + let(:source) { '/x/' } + + it { expect(regexp_node.multiline?).to be(false) } + end + + context 'with other options' do + let(:source) { '/x/ix' } + + it { expect(regexp_node.multiline?).to be(false) } + end + + context 'with only m option' do + let(:source) { '/x/m' } + + it { expect(regexp_node.multiline?).to be(true) } + end + + context 'with m and other options' do + let(:source) { '/x/imx' } + + it { expect(regexp_node.multiline?).to be(true) } + end + end + + describe '#extended?' do + context 'with no options' do + let(:source) { '/x/' } + + it { expect(regexp_node.extended?).to be(false) } + end + + context 'with other options' do + let(:source) { '/x/im' } + + it { expect(regexp_node.extended?).to be(false) } + end + + context 'with only x option' do + let(:source) { '/x/x' } + + it { expect(regexp_node.extended?).to be(true) } + end + + context 'with x and other options' do + let(:source) { '/x/ixm' } + + it { expect(regexp_node.extended?).to be(true) } + end + end + + describe '#ignore_case?' do + context 'with no options' do + let(:source) { '/x/' } + + it { expect(regexp_node.ignore_case?).to be(false) } + end + + context 'with other options' do + let(:source) { '/x/xm' } + + it { expect(regexp_node.ignore_case?).to be(false) } + end + + context 'with only i option' do + let(:source) { '/x/i' } + + it { expect(regexp_node.ignore_case?).to be(true) } + end + + context 'with i and other options' do + let(:source) { '/x/xim' } + + it { expect(regexp_node.ignore_case?).to be(true) } + end + end + + describe '#no_encoding?' do + context 'with no options' do + let(:source) { '/x/' } + + it { expect(regexp_node.no_encoding?).to be(false) } + end + + context 'with other options' do + let(:source) { '/x/xm' } + + it { expect(regexp_node.no_encoding?).to be(false) } + end + + context 'with only n option' do + let(:source) { '/x/n' } + + it { expect(regexp_node.no_encoding?).to be(true) } + end + + context 'with n and other options' do + let(:source) { '/x/xnm' } + + it { expect(regexp_node.no_encoding?).to be(true) } + end + end + + describe '#single_interpolation?' do + context 'with no options' do + let(:source) { '/x/' } + + it { expect(regexp_node.single_interpolation?).to be(false) } + end + + context 'with other options' do + let(:source) { '/x/xm' } + + it { expect(regexp_node.single_interpolation?).to be(false) } + end + + context 'with only o option' do + let(:source) { '/x/o' } + + it { expect(regexp_node.single_interpolation?).to be(true) } + end + + context 'with o and other options' do + let(:source) { '/x/xom' } + + it { expect(regexp_node.single_interpolation?).to be(true) } + end + end end