msfl_visitors 1.2.0 → 1.2.1.dev0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b4fcb0f385bb41b619dad3d25724604bf43796e7
4
- data.tar.gz: 3c51e3af9013e32a0b423da17f0b9926108dd9c6
3
+ metadata.gz: e43425b31d0774b6b7bfef7b7a47dd8914195729
4
+ data.tar.gz: b3fdf922ea429c522a77258ca40e5955d53373f3
5
5
  SHA512:
6
- metadata.gz: b6626c6471bfeab9c8d1056fd2d23cbb6ccb2bf14409ef0589b7e0b4687c5fa3a0455f7596f223687a0bd8995449c548a5ee93617351b392491704878c3060be
7
- data.tar.gz: 33d2578796d206d74757c9d587a34d1d46a148c777ac005599cebd51d8d28727ff231176000a4eedee15f47e20ab0f559842f92a0f5f2866511bcf62c44bd45d
6
+ metadata.gz: cc796e4b08f79201048cf37715f50cba54abc9026ebbb96669a5c8f4b3e8ef93505a65e2f5e1790494d3775521a65bfdcb30092ba1c7d1fffec329855684a8e7
7
+ data.tar.gz: 142acb13b5679b278a9c2487ecace20e8917d3673a715b9ecbfa91ee1ea5ab71f131a49a2237851cdb50855e28b1ee8aa1468a831b548736eeb0700b02ffaa09
@@ -49,6 +49,13 @@ module MSFLVisitors
49
49
  [{clause: root.accept(self)}].concat(clauses).reject { |c| c[:clause] == "" }
50
50
  end
51
51
 
52
+ # Note that the ES documentation also indicates that # is a special character that requires
53
+ # escaping and that this behavior is not part of the PERL regex; however Ruby automatically escapes
54
+ # literal hashes when constructing regices
55
+ def escape_es_special_regex_chars(str)
56
+ str.gsub(/([@&<>~])/) { |m| "\\#{m}" }
57
+ end
58
+
52
59
  private
53
60
 
54
61
  attr_reader :mode
@@ -68,12 +75,19 @@ module MSFLVisitors
68
75
  Nodes::Match => '=~',
69
76
  }
70
77
 
78
+ def escaped_regex_helper(escaped_str)
79
+ exp = visitor.escape_es_special_regex_chars "#{escaped_str}"
80
+ # why you must use #inspect, not #to_s. @link http://ruby-doc.org/core-1.9.3/Regexp.html#method-i-3D-7E
81
+ %r[.*#{exp}.*]
82
+ end
83
+
71
84
  def visit(node)
72
85
  case node
73
86
  when Nodes::Field
74
87
  node.value.to_s
75
88
  when Nodes::Regex
76
- %(Regexp.new( '.*' + Regexp.escape( "#{node.value.to_s}" ) + '.*' ))
89
+ esc = Regexp.escape("#{node.value.to_s}")
90
+ escaped_regex_helper esc
77
91
  when Nodes::Word
78
92
  "\"#{node.value}\""
79
93
  when Nodes::Date, Nodes::Time
@@ -86,10 +100,10 @@ module MSFLVisitors
86
100
 
87
101
  when Nodes::Match
88
102
  if node.right.is_a? Nodes::Set
89
- regex = node.right.contents.map { |right_child| MSFLVisitors::Nodes::Regex.new(right_child.value.to_s).accept(visitor)[15..-6] }.join('|')
90
- "#{node.left.accept(visitor)} #{BINARY_OPERATORS[node.class]} Regexp.new( '.*' + #{regex[4..-5]} + '.*' )"
103
+ escaped_str = node.right.contents.map { |right_child| MSFLVisitors::Nodes::Regex.new(right_child.value.to_s).accept(visitor).inspect[3..-4] }.join('|')
104
+ "#{node.left.accept(visitor)} #{BINARY_OPERATORS[node.class]} " + escaped_regex_helper(escaped_str).inspect
91
105
  else
92
- "#{node.left.accept(visitor)} #{BINARY_OPERATORS[node.class]} #{MSFLVisitors::Nodes::Regex.new(node.right.value.to_s).accept(visitor)}"
106
+ "#{node.left.accept(visitor)} #{BINARY_OPERATORS[node.class]} " + MSFLVisitors::Nodes::Regex.new(node.right.value.to_s).accept(visitor).inspect
93
107
  end
94
108
  when Nodes::Containment,
95
109
  Nodes::GreaterThan,
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'msfl_visitors'
3
- s.version = '1.2.0'
3
+ s.version = '1.2.1.dev0'
4
4
  s.date = '2015-06-19'
5
5
  s.summary = "Convert MSFL to other forms"
6
6
  s.description = "Visitor pattern approach to converting MSFL to other forms."
@@ -11,4 +11,20 @@ describe MSFLVisitors::Visitor do
11
11
  expect(subject.send(:mode)).to eq :term
12
12
  end
13
13
  end
14
+
15
+ describe "#escape_es_special_regex_chars" do
16
+
17
+ {
18
+ 'ab@cd' => 'ab\@cd',
19
+ 'ab&cd' => 'ab\&cd',
20
+ 'ab<cd' => 'ab\<cd',
21
+ 'ab>cd' => 'ab\>cd',
22
+ 'ab~cd' => 'ab\~cd',
23
+ }.each do |str, expected|
24
+
25
+ it "escapes '#{str}' as '#{expected}'" do
26
+ expect(MSFLVisitors::Visitor.new.escape_es_special_regex_chars str).to eq expected
27
+ end
28
+ end
29
+ end
14
30
  end
@@ -198,12 +198,23 @@ describe MSFLVisitors::Visitor do
198
198
 
199
199
  describe "a Regex node" do
200
200
 
201
- let(:node) { MSFLVisitors::Nodes::Regex.new "foobar" }
201
+ let(:node) { MSFLVisitors::Nodes::Regex.new regex }
202
+
203
+ let(:regex) { "foobar" }
202
204
 
203
205
  context "when using the TermFilter visitor" do
204
206
 
205
- it "results in: 'Regexp.new( '.*' + Regexp.escape( \"foobar\" ) + '.*' )'" do
206
- expect(result).to eq %(Regexp.new( '.*' + Regexp.escape( "foobar" ) + '.*' ))
207
+ it "results in: /.*foobar.*/" do
208
+ expect(result).to eq /.*foobar.*/
209
+ end
210
+
211
+ context "when the node requires escaping" do
212
+
213
+ let(:node) { MSFLVisitors::Nodes::Regex.new "foo*bar" }
214
+
215
+ it "results in: #{/.*foo\*bar.*/.inspect}" do
216
+ expect(result).to eq /.*foo\*bar.*/
217
+ end
207
218
  end
208
219
  end
209
220
 
@@ -215,6 +226,36 @@ describe MSFLVisitors::Visitor do
215
226
  expect(result).to eq "foobar"
216
227
  end
217
228
  end
229
+
230
+ context "when the expression contains `#`, `@`, `&`, `<`, `>`, or `~`" do
231
+
232
+ let(:regex) { "a #sentence@ contain&ing <lucene> cha~rs" }
233
+
234
+ it "escapes lucene specific special characters" do
235
+ expected = /.*a\ \#sentence\@\ contain\&ing\ \<lucene\>\ cha\~rs.*/
236
+ expect(result).to eq expected
237
+ end
238
+ end
239
+
240
+ context "when the regex contains characters that require escaping" do
241
+
242
+ let(:regex) { 'this / needs to % {be,escaped} *. ^[or] | \else' }
243
+
244
+ let(:node) { MSFLVisitors::Nodes::Regex.new regex }
245
+
246
+ it "returns: #{/.*this\ \/\ needs\ to\ %\ \{be,escaped\}\ \*\.\ \^\[or\]\ \|\ \\else.*/.inspect}" do
247
+ expect(result).to eq /.*this\ \/\ needs\ to\ %\ \{be,escaped\}\ \*\.\ \^\[or\]\ \|\ \\else.*/
248
+ end
249
+
250
+ context "when using the Aggregations visitor" do
251
+
252
+ before { visitor.mode = :aggregations }
253
+
254
+ it "returns: 'this\\ /\\ needs\\ to\\ %\\ \\{be,escaped\\}\\ \\*\\.\\ \\^\\[or\\]\\ \\|\\ \\\\else'" do
255
+ expect(result).to eq "this\\ /\\ needs\\ to\\ %\\ \\{be,escaped\\}\\ \\*\\.\\ \\^\\[or\\]\\ \\|\\ \\\\else"
256
+ end
257
+ end
258
+ end
218
259
  end
219
260
 
220
261
  describe "a Match node" do
@@ -223,8 +264,8 @@ describe MSFLVisitors::Visitor do
223
264
 
224
265
  context "when using the TermFilter visitor" do
225
266
 
226
- it "results in: 'left =~ Regexp.new( '.*' + Regexp.parse( \"rhs\" ) + '.*' )'" do
227
- expect(result).to eq %(lhs =~ Regexp.new( '.*' + Regexp.escape( "rhs" ) + '.*' ))
267
+ it "results in: 'left =~ /.*rhs.*/'" do
268
+ expect(result).to eq %(lhs =~ /.*rhs.*/)
228
269
  end
229
270
  end
230
271
 
@@ -243,8 +284,8 @@ describe MSFLVisitors::Visitor do
243
284
 
244
285
  context "when using the TermFilter visitor" do
245
286
 
246
- it "results in: 'left =~ Regexp.new( '.*' + Regexp.escape( \"this (needs) to be* escaped\" ) + '.*' )'" do
247
- expect(result).to eq %(lhs =~ Regexp.new( '.*' + Regexp.escape( "this (needs) to be* escaped" ) + '.*' ))
287
+ it "results in: 'left =~ /.*this\ \(needs\)\ to\ be\*\ escaped.*/'" do
288
+ expect(result).to eq %(lhs =~ ) + /.*this\ \(needs\)\ to\ be\*\ escaped.*/.inspect
248
289
  end
249
290
  end
250
291
 
@@ -262,8 +303,8 @@ describe MSFLVisitors::Visitor do
262
303
 
263
304
  context "when using the TermFilter visitor" do
264
305
 
265
- it "results in: 'left =~ Regexp.new( '.*' + Regexp.escape( \"foo\" ) + '|' + Regexp.escape( \"bar\" ) + '|' + Regexp.escape( \"baz\" ) + '.*' )'" do
266
- expect(result).to eq %(lhs =~ Regexp.new( '.*' + Regexp.escape( "foo" ) + '|' + Regexp.escape( "bar" ) + '|' + Regexp.escape( "baz" ) + '.*' ))
306
+ it "results in: 'left =~ /.*foo|bar|baz.*/'" do
307
+ expect(result).to eq %(lhs =~ ) + /.*foo|bar|baz.*/.inspect
267
308
  end
268
309
  end
269
310
 
@@ -719,46 +760,6 @@ describe MSFLVisitors::Visitor do
719
760
  end
720
761
  end
721
762
  end
722
-
723
- describe "a Regex node" do
724
-
725
- let(:regex) { "content" }
726
-
727
- let(:node) { MSFLVisitors::Nodes::Regex.new regex }
728
-
729
- it "returns: 'Regexp.new( '.*' + Regexp.escape( \"content\" ) + '.*' )'" do
730
- expect(result).to eq %(Regexp.new( '.*' + Regexp.escape( "#{regex}" ) + '.*' ))
731
- end
732
-
733
- context "when using the Aggregations visitor" do
734
-
735
- before { visitor.mode = :aggregations }
736
-
737
- it "returns: the elasticsearch regular expression formatted string \"content\"" do
738
- expect(result).to eq "#{regex}"
739
- end
740
- end
741
-
742
- context "when the regex contains characters that require escaping" do
743
-
744
- let(:regex) { 'this / needs to % {be,escaped} *. ^[or] | \else' }
745
-
746
- let(:node) { MSFLVisitors::Nodes::Regex.new regex }
747
-
748
- it "returns: 'Regexp.new( '.*' + Regexp.escape( \"this / needs to % {be,escaped} *. ^[or] | \\else\" ) + '.*' )'" do
749
- expect(result).to eq %(Regexp.new( '.*' + Regexp.escape( "this / needs to % {be,escaped} *. ^[or] | \\else" ) + '.*' ))
750
- end
751
-
752
- context "when using the Aggregations visitor" do
753
-
754
- before { visitor.mode = :aggregations }
755
-
756
- it "returns: 'this\\ /\\ needs\\ to\\ %\\ \\{be,escaped\\}\\ \\*\\.\\ \\^\\[or\\]\\ \\|\\ \\\\else'" do
757
- expect(result).to eq "this\\ /\\ needs\\ to\\ %\\ \\{be,escaped\\}\\ \\*\\.\\ \\^\\[or\\]\\ \\|\\ \\\\else"
758
- end
759
- end
760
- end
761
- end
762
763
  end
763
764
 
764
765
  describe "range value nodes" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: msfl_visitors
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.1.dev0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Courtland Caldwell
@@ -173,9 +173,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
173
173
  version: '0'
174
174
  required_rubygems_version: !ruby/object:Gem::Requirement
175
175
  requirements:
176
- - - ">="
176
+ - - ">"
177
177
  - !ruby/object:Gem::Version
178
- version: '0'
178
+ version: 1.3.1
179
179
  requirements: []
180
180
  rubyforge_project:
181
181
  rubygems_version: 2.2.2