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 +4 -4
- data/lib/msfl_visitors/visitor.rb +18 -4
- data/msfl_visitors.gemspec +1 -1
- data/spec/msfl_visitors/visitor_spec.rb +16 -0
- data/spec/msfl_visitors/visitors/chewy_term_filter_spec.rb +50 -49
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e43425b31d0774b6b7bfef7b7a47dd8914195729
|
4
|
+
data.tar.gz: b3fdf922ea429c522a77258ca40e5955d53373f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
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
|
-
|
90
|
-
"#{node.left.accept(visitor)} #{BINARY_OPERATORS[node.class]}
|
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]}
|
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,
|
data/msfl_visitors.gemspec
CHANGED
@@ -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
|
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:
|
206
|
-
expect(result).to eq
|
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 =~
|
227
|
-
expect(result).to eq %(lhs =~
|
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 =~
|
247
|
-
expect(result).to eq %(lhs =~
|
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 =~
|
266
|
-
expect(result).to eq %(lhs =~
|
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.
|
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:
|
178
|
+
version: 1.3.1
|
179
179
|
requirements: []
|
180
180
|
rubyforge_project:
|
181
181
|
rubygems_version: 2.2.2
|