fear 1.2.0 → 2.0.0

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.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +27 -0
  3. data/.github/workflows/rubocop.yml +2 -2
  4. data/.github/workflows/spec.yml +1 -1
  5. data/CHANGELOG.md +13 -0
  6. data/Gemfile.lock +53 -56
  7. data/README.md +54 -186
  8. data/Rakefile +0 -21
  9. data/examples/pattern_extracting.rb +4 -4
  10. data/fear.gemspec +2 -4
  11. data/lib/fear/either.rb +8 -4
  12. data/lib/fear/either_api.rb +2 -0
  13. data/lib/fear/either_pattern_match.rb +7 -8
  14. data/lib/fear/failure.rb +0 -9
  15. data/lib/fear/failure_pattern_match.rb +2 -0
  16. data/lib/fear/for_api.rb +2 -0
  17. data/lib/fear/future.rb +12 -20
  18. data/lib/fear/future_api.rb +13 -2
  19. data/lib/fear/left.rb +0 -9
  20. data/lib/fear/none.rb +7 -9
  21. data/lib/fear/option.rb +5 -1
  22. data/lib/fear/option_api.rb +2 -0
  23. data/lib/fear/option_pattern_match.rb +6 -4
  24. data/lib/fear/partial_function/empty.rb +2 -0
  25. data/lib/fear/partial_function/guard.rb +4 -4
  26. data/lib/fear/partial_function/or_else.rb +2 -0
  27. data/lib/fear/partial_function.rb +9 -8
  28. data/lib/fear/pattern_match.rb +0 -10
  29. data/lib/fear/pattern_matching_api.rb +3 -28
  30. data/lib/fear/promise.rb +3 -9
  31. data/lib/fear/right.rb +0 -10
  32. data/lib/fear/right_biased.rb +1 -1
  33. data/lib/fear/right_pattern_match.rb +2 -0
  34. data/lib/fear/some.rb +7 -10
  35. data/lib/fear/struct.rb +3 -14
  36. data/lib/fear/success.rb +0 -9
  37. data/lib/fear/success_pattern_match.rb +2 -0
  38. data/lib/fear/try.rb +6 -2
  39. data/lib/fear/try_api.rb +2 -0
  40. data/lib/fear/try_pattern_match.rb +7 -8
  41. data/lib/fear/utils.rb +0 -3
  42. data/lib/fear/version.rb +1 -1
  43. data/lib/fear.rb +8 -42
  44. data/spec/fear/awaitable_spec.rb +2 -0
  45. data/spec/fear/either_spec.rb +26 -0
  46. data/spec/fear/failure_spec.rb +8 -23
  47. data/spec/fear/for/mixin_spec.rb +15 -0
  48. data/spec/fear/future_spec.rb +17 -2
  49. data/spec/fear/guard_spec.rb +110 -0
  50. data/spec/fear/left_spec.rb +7 -22
  51. data/spec/fear/none_spec.rb +11 -17
  52. data/spec/fear/option_spec.rb +15 -1
  53. data/spec/fear/partial_function/any_spec.rb +25 -0
  54. data/spec/fear/partial_function_spec.rb +2 -24
  55. data/spec/fear/pattern_match_spec.rb +0 -34
  56. data/spec/fear/promise_spec.rb +4 -6
  57. data/spec/fear/right_spec.rb +0 -22
  58. data/spec/fear/some_spec.rb +10 -22
  59. data/spec/fear/success_spec.rb +0 -22
  60. data/spec/fear/try/mixin_spec.rb +14 -0
  61. data/spec/fear/try_api_spec.rb +23 -0
  62. data/spec/struct_spec.rb +1 -33
  63. metadata +18 -80
  64. data/examples/pattern_extracting_ruby2.7.rb +0 -15
  65. data/lib/fear/extractor/anonymous_array_splat_matcher.rb +0 -10
  66. data/lib/fear/extractor/any_matcher.rb +0 -17
  67. data/lib/fear/extractor/array_head_matcher.rb +0 -36
  68. data/lib/fear/extractor/array_matcher.rb +0 -40
  69. data/lib/fear/extractor/array_splat_matcher.rb +0 -16
  70. data/lib/fear/extractor/empty_list_matcher.rb +0 -20
  71. data/lib/fear/extractor/extractor_matcher.rb +0 -44
  72. data/lib/fear/extractor/grammar.rb +0 -203
  73. data/lib/fear/extractor/grammar.treetop +0 -129
  74. data/lib/fear/extractor/identifier_matcher.rb +0 -18
  75. data/lib/fear/extractor/matcher/and.rb +0 -38
  76. data/lib/fear/extractor/matcher.rb +0 -53
  77. data/lib/fear/extractor/named_array_splat_matcher.rb +0 -17
  78. data/lib/fear/extractor/pattern.rb +0 -58
  79. data/lib/fear/extractor/typed_identifier_matcher.rb +0 -26
  80. data/lib/fear/extractor/value_matcher.rb +0 -19
  81. data/lib/fear/extractor.rb +0 -112
  82. data/lib/fear/extractor_api.rb +0 -35
  83. data/spec/fear/extractor/array_matcher_spec.rb +0 -230
  84. data/spec/fear/extractor/extractor_matcher_spec.rb +0 -153
  85. data/spec/fear/extractor/grammar_array_spec.rb +0 -25
  86. data/spec/fear/extractor/identified_matcher_spec.rb +0 -49
  87. data/spec/fear/extractor/identifier_matcher_spec.rb +0 -68
  88. data/spec/fear/extractor/pattern_spec.rb +0 -34
  89. data/spec/fear/extractor/typed_identifier_matcher_spec.rb +0 -64
  90. data/spec/fear/extractor/value_matcher_number_spec.rb +0 -79
  91. data/spec/fear/extractor/value_matcher_string_spec.rb +0 -88
  92. data/spec/fear/extractor/value_matcher_symbol_spec.rb +0 -71
  93. data/spec/fear/extractor_api_spec.rb +0 -115
  94. data/spec/fear/extractor_spec.rb +0 -61
@@ -1,35 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Fear
4
- module ExtractorApi
5
- # Allows to pattern match and extract matcher variables
6
- #
7
- # @param pattern [String]
8
- # @return [Extractor::Pattern]
9
- # @note it is not intended to be used by itself, rather then with partial functions
10
- def [](pattern)
11
- Extractor::Pattern.new(pattern)
12
- end
13
-
14
- # Register extractor for given class
15
- # @!method register_extractor(*names, extractor)
16
- # @param names [<Class, String>, Class, String] name of a class. You can also pass alias for the name
17
- # @param extractor [Proc<any => Fear::Option>] proc taking any argument and returned Option
18
- # of extracted value('s)
19
- #
20
- # @example
21
- # register_extractor(Fear::Some, Fear.case(Fear::Some) { |some| some.get }.lift)
22
- #
23
- # register_extractor(User, Fear.case(User) { |user|} [user.id, user.email] , )
24
- #
25
- # @example registering an alias. Alias should be CamelCased string
26
- # register_extractor(Fear::Some, 'Some', Fear.case(Fear::Some) { |some| some.get }.lift)
27
- #
28
- # # no you can extract Fear::Some's using Some alias
29
- # m.case(Fear['Some(value : Integer)']) { |value:| value * 2 }
30
- #
31
- def register_extractor(*args)
32
- Extractor.register_extractor(*args)
33
- end
34
- end
35
- end
@@ -1,230 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Fear::Extractor::ArrayMatcher do
4
- let(:parser) { Fear::Extractor::GrammarParser.new }
5
- let(:matcher) { parser.parse(pattern).to_matcher }
6
-
7
- describe "#defined_at?" do
8
- subject { matcher }
9
-
10
- context "empty array" do
11
- let(:pattern) { "[]" }
12
-
13
- it { is_expected.to be_defined_at([]) }
14
- it { is_expected.not_to be_defined_at([1]) }
15
- end
16
-
17
- context "empty array with splat" do
18
- let(:pattern) { "[*]" }
19
-
20
- it { is_expected.to be_defined_at([]) }
21
- it { is_expected.to be_defined_at([1]) }
22
- it { is_expected.to be_defined_at([1, 2]) }
23
- end
24
-
25
- context "empty array with named splat" do
26
- let(:pattern) { "[*var]" }
27
-
28
- it { is_expected.to be_defined_at([]) }
29
- it { is_expected.to be_defined_at([1]) }
30
- it { is_expected.to be_defined_at([1, 2]) }
31
- end
32
-
33
- context "one element array" do
34
- let(:pattern) { "[1]" }
35
-
36
- it { is_expected.not_to be_defined_at([]) }
37
- it { is_expected.to be_defined_at([1]) }
38
- it { is_expected.not_to be_defined_at([1, 2]) }
39
- it { is_expected.not_to be_defined_at([2, 1]) }
40
-
41
- context "identifier" do
42
- let(:pattern) { "[var]" }
43
-
44
- it { is_expected.not_to be_defined_at([]) }
45
- it { is_expected.to be_defined_at([1]) }
46
- it { is_expected.to be_defined_at([[1]]) }
47
- end
48
- end
49
-
50
- context "two elements array with nested matcher" do
51
- let(:pattern) { "[[1, *], 1]" }
52
-
53
- it { is_expected.not_to be_defined_at([]) }
54
- it { is_expected.to be_defined_at([[1], 1]) }
55
- it { is_expected.to be_defined_at([[1, 2], 1]) }
56
- it { is_expected.not_to be_defined_at([[1, 2], 2]) }
57
- it { is_expected.not_to be_defined_at([2, 1]) }
58
- end
59
-
60
- context "one element array with splat" do
61
- let(:pattern) { "[1, *]" }
62
-
63
- it { is_expected.not_to be_defined_at([]) }
64
- it { is_expected.to be_defined_at([1]) }
65
- it { is_expected.to be_defined_at([1, 2]) }
66
- it { is_expected.to be_defined_at([1, 2, 3]) }
67
- it { is_expected.not_to be_defined_at([2, 1]) }
68
- end
69
-
70
- context "one element array with named splat" do
71
- let(:pattern) { "[1, *var]" }
72
-
73
- it { is_expected.not_to be_defined_at([]) }
74
- it { is_expected.to be_defined_at([1]) }
75
- it { is_expected.to be_defined_at([1, 2]) }
76
- it { is_expected.to be_defined_at([1, 2, 3]) }
77
- it { is_expected.not_to be_defined_at([2, 1]) }
78
- end
79
-
80
- context "three elements array" do
81
- context "with identifier in the middle" do
82
- let(:pattern) { "[1, var, 2]" }
83
-
84
- it { is_expected.not_to be_defined_at([]) }
85
- it { is_expected.to be_defined_at([1, 3, 2]) }
86
- it { is_expected.not_to be_defined_at([1, 2, 3]) }
87
- it { is_expected.not_to be_defined_at([1, 2, 3, 4]) }
88
- it { is_expected.not_to be_defined_at([1]) }
89
- it { is_expected.not_to be_defined_at([2]) }
90
- end
91
-
92
- context "head and tail" do
93
- let(:pattern) { "[head, *tail]" }
94
-
95
- it { is_expected.not_to be_defined_at([]) }
96
- it { is_expected.to be_defined_at([1, 3, 2]) }
97
- end
98
- end
99
-
100
- context "two element array" do
101
- let(:pattern) { "[ 1, 2 ]" }
102
-
103
- it { is_expected.not_to be_defined_at([]) }
104
- it { is_expected.to be_defined_at([1, 2]) }
105
- it { is_expected.not_to be_defined_at([1]) }
106
- it { is_expected.not_to be_defined_at([2]) }
107
- it { is_expected.not_to be_defined_at([1, 3]) }
108
- it { is_expected.not_to be_defined_at([2, 2]) }
109
- it { is_expected.not_to be_defined_at([1, 2, 3]) }
110
-
111
- context "with identifier at the beginning" do
112
- let(:pattern) { "[var, 2]" }
113
-
114
- it { is_expected.not_to be_defined_at([]) }
115
- it { is_expected.to be_defined_at([1, 2]) }
116
- it { is_expected.not_to be_defined_at([1, 3]) }
117
- it { is_expected.not_to be_defined_at([1]) }
118
- it { is_expected.not_to be_defined_at([2]) }
119
- it { is_expected.not_to be_defined_at([1, 2, 3]) }
120
- end
121
- end
122
- end
123
-
124
- describe "#call" do
125
- subject { matcher.(other) }
126
-
127
- context "on the same array" do
128
- let(:other) { [1] }
129
- let(:pattern) { "[1]" }
130
-
131
- it { is_expected.to eq({}) }
132
- end
133
-
134
- context "with splat on another array" do
135
- let(:other) { [2, 1] }
136
- let(:pattern) { "[2, *]" }
137
-
138
- it { is_expected.to eq({}) }
139
- end
140
-
141
- context "with identifier at the middle of an array" do
142
- let(:other) { [2, 1, 3] }
143
- let(:pattern) { "[2, var, 3]" }
144
-
145
- it { is_expected.to eq(var: 1) }
146
- end
147
-
148
- context "with identifier at the end of an array" do
149
- let(:other) { [2, 1, 3] }
150
- let(:pattern) { "[2, 1, var]" }
151
-
152
- it { is_expected.to eq(var: 3) }
153
- end
154
-
155
- context "with named splat matching all the array" do
156
- let(:other) { [2, 1, 3, 4] }
157
- let(:pattern) { "[*var]" }
158
-
159
- it { is_expected.to eq(var: [2, 1, 3, 4]) }
160
- end
161
-
162
- context "with named splat matching tail of an array" do
163
- let(:other) { [2, 1, 3, 4] }
164
- let(:pattern) { "[2, 1, *var]" }
165
-
166
- it { is_expected.to eq(var: [3, 4]) }
167
- end
168
-
169
- context "with named splat at the end of an array" do
170
- let(:other) { [2, 1] }
171
- let(:pattern) { "[2, 1, *var]" }
172
-
173
- it { is_expected.to eq(var: []) }
174
- end
175
-
176
- context "with several identifiers in an array" do
177
- let(:other) { [2, 1, 3] }
178
- let(:pattern) { "[a, 1, b]" }
179
-
180
- it { is_expected.to eq(a: 2, b: 3) }
181
- end
182
-
183
- context "head and tail" do
184
- let(:other) { [2, 1, 3] }
185
- let(:pattern) { "[head, *tail]" }
186
-
187
- it { is_expected.to eq(head: 2, tail: [1, 3]) }
188
- end
189
-
190
- context "ignore head, capture tail" do
191
- let(:other) { [2, 1, 3] }
192
- let(:pattern) { "[_, *tail]" }
193
-
194
- it { is_expected.to eq(tail: [1, 3]) }
195
- end
196
- end
197
-
198
- describe "#failure_reason" do
199
- subject { matcher.failure_reason(other) }
200
-
201
- context "on the same array" do
202
- let(:other) { [1] }
203
- let(:pattern) { "[1]" }
204
-
205
- it { is_expected.to eq(Fear.none) }
206
- end
207
-
208
- context "on another array" do
209
- let(:other) { [2, 1] }
210
- let(:pattern) { "[2, 2]" }
211
-
212
- it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
213
- Expected `1` to match:
214
- [2, 2]
215
- ~~~~^
216
- ERROR
217
- end
218
-
219
- context "element type mismatch" do
220
- let(:other) { [2, 1] }
221
- let(:pattern) { "[[2], 1]" }
222
-
223
- it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
224
- Expected `2` to match:
225
- [[2], 1]
226
- ~~^
227
- ERROR
228
- end
229
- end
230
- end
@@ -1,153 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Fear::Extractor::ExtractorMatcher do
4
- let(:parser) { Fear::Extractor::GrammarParser.new }
5
- let(:matcher) { parser.parse(pattern).to_matcher }
6
-
7
- describe "#defined_at?" do
8
- subject { matcher }
9
-
10
- context "boolean extractor" do
11
- let(:pattern) { "IsEven()" }
12
-
13
- it { is_expected.to be_defined_at(42) }
14
- it { is_expected.not_to be_defined_at(43) }
15
- it { is_expected.not_to be_defined_at("foo") }
16
- end
17
-
18
- context "single argument extractor" do
19
- let(:pattern) { "Fear::Some(a : Integer)" }
20
-
21
- it { is_expected.to be_defined_at(Fear.some(42)) }
22
- it { is_expected.not_to be_defined_at("foo") }
23
- it { is_expected.not_to be_defined_at(Fear.some("foo")) }
24
- end
25
-
26
- context "single argument extractor with array as an argument" do
27
- let(:pattern) { "Fear::Some([1, 2])" }
28
-
29
- it { is_expected.to be_defined_at(Fear.some([1, 2])) }
30
- it { is_expected.not_to be_defined_at(Fear.some([1, 1])) }
31
- it { is_expected.not_to be_defined_at(Fear.some("foo")) }
32
- end
33
-
34
- context "multiple arguments extractor" do
35
- let(:pattern) { "Date(2017, month, _)" }
36
-
37
- it { is_expected.to be_defined_at(Date.parse("2017-02-15")) }
38
- it { is_expected.not_to be_defined_at(Date.parse("2018-02-15")) }
39
- it { is_expected.not_to be_defined_at("foo") }
40
- end
41
-
42
- context "Struct" do
43
- StructDate = ::Struct.new(:year, :month, :day)
44
-
45
- let(:pattern) { "StructDate(2017, month, _)" }
46
-
47
- it { is_expected.to be_defined_at(StructDate.new(2017, 2, 15)) }
48
- it { is_expected.not_to be_defined_at(StructDate.new(2018, 2, 15)) }
49
- end
50
- end
51
-
52
- describe "#call" do
53
- subject { matcher.(other) }
54
-
55
- context "single argument extractor" do
56
- let(:pattern) { "Fear::Some(a : Integer)" }
57
- let(:other) { Fear.some(42) }
58
-
59
- it { is_expected.to eq(a: 42) }
60
- end
61
-
62
- context "multiple arguments extractor" do
63
- let(:pattern) { "Date(2017, month, day)" }
64
- let(:other) { Date.parse("2017-02-15") }
65
-
66
- it { is_expected.to eq(month: 2, day: 15) }
67
- end
68
- end
69
-
70
- describe "#failure_reason" do
71
- subject { matcher.failure_reason(other) }
72
-
73
- context "no argument extractor" do
74
- let(:pattern) { "IsEven()" }
75
-
76
- context "defined" do
77
- let(:other) { 42 }
78
-
79
- it { is_expected.to eq(Fear.none) }
80
- end
81
-
82
- context "not defined" do
83
- let(:other) { 43 }
84
-
85
- it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
86
- Expected `43` to match:
87
- IsEven()
88
- ^
89
- MSG
90
- end
91
- end
92
-
93
- context "single argument extractor" do
94
- let(:pattern) { "Fear::Some(a : Integer)" }
95
-
96
- context "defined" do
97
- let(:other) { Fear.some(42) }
98
-
99
- it { is_expected.to eq(Fear.none) }
100
- end
101
-
102
- context "not defined" do
103
- let(:other) { Fear.some("42") }
104
-
105
- it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
106
- Expected `"42"` to match:
107
- Fear::Some(a : Integer)
108
- ~~~~~~~~~~~~~~~^
109
- MSG
110
- end
111
- end
112
-
113
- context "single argument extractor, array argument" do
114
- let(:pattern) { "Fear::Some([1, 2])" }
115
-
116
- context "defined" do
117
- let(:other) { Fear.some([1, 2]) }
118
-
119
- it { is_expected.to eq(Fear.none) }
120
- end
121
-
122
- context "not defined" do
123
- let(:other) { Fear.some([1, 1]) }
124
-
125
- it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
126
- Expected `1` to match:
127
- Fear::Some([1, 2])
128
- ~~~~~~~~~~~~~~~^
129
- MSG
130
- end
131
- end
132
-
133
- context "multiple arguments extractor" do
134
- let(:pattern) { "Date(year, 02, day)" }
135
-
136
- context "defined" do
137
- let(:other) { Date.parse("2017-02-15") }
138
-
139
- it { is_expected.to eq(Fear.none) }
140
- end
141
-
142
- context "not defined" do
143
- let(:other) { Date.parse("2017-04-15") }
144
-
145
- it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
146
- Expected `4` to match:
147
- Date(year, 02, day)
148
- ~~~~~~~~~~~^
149
- MSG
150
- end
151
- end
152
- end
153
- end
@@ -1,25 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Fear::Extractor::Grammar, "Array" do
4
- let(:parser) { Fear::Extractor::GrammarParser.new }
5
- let(:matcher) { parser.parse(pattern).to_matcher }
6
-
7
- context "non empty array" do
8
- let(:pattern) { "[1, 2, 3, 4]" }
9
-
10
- it do
11
- first = matcher.head
12
- rest_after_first = matcher.tail
13
-
14
- expect(first).to be_kind_of(Fear::Extractor::ArrayHeadMatcher)
15
- expect(first.matcher.value).to eq(1)
16
- expect(rest_after_first).to be_kind_of(Fear::Extractor::ArrayMatcher)
17
-
18
- second = rest_after_first.head
19
- rest_after_second = rest_after_first.tail
20
- expect(second).to be_kind_of(Fear::Extractor::ArrayHeadMatcher)
21
- expect(second.matcher.value).to eq(2)
22
- expect(rest_after_second).to be_kind_of(Fear::Extractor::ArrayMatcher)
23
- end
24
- end
25
- end
@@ -1,49 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe "Fear::Extractor::IdentifiedMatcher" do
4
- let(:parser) { Fear::Extractor::GrammarParser.new }
5
- let(:matcher) { parser.parse(pattern).to_matcher }
6
-
7
- describe "#defined_at?" do
8
- subject { matcher }
9
-
10
- let(:pattern) { "array @ [1, *tail]" }
11
-
12
- it { is_expected.to be_defined_at([1, 2]) }
13
- it { is_expected.not_to be_defined_at("foo") }
14
- it { is_expected.not_to be_defined_at([2, 1]) }
15
- end
16
-
17
- describe "#call" do
18
- subject { matcher.(other) }
19
-
20
- context "defined" do
21
- let(:other) { [1, 2] }
22
- let(:pattern) { "array @ [1, *tail]" }
23
-
24
- it { is_expected.to eq(array: [1, 2], tail: [2]) }
25
- end
26
- end
27
-
28
- describe "#failure_reason" do
29
- subject { matcher.failure_reason(other) }
30
-
31
- let(:pattern) { "array @ [1, *tail]" }
32
-
33
- context "match integer" do
34
- let(:other) { [1, 2] }
35
-
36
- it { is_expected.to eq(Fear.none) }
37
- end
38
-
39
- context "does not match float" do
40
- let(:other) { [2, 2] }
41
-
42
- it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
43
- Expected `2` to match:
44
- array @ [1, *tail]
45
- ~~~~~~~~~^
46
- ERROR
47
- end
48
- end
49
- end
@@ -1,68 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Fear::Extractor::IdentifierMatcher do
4
- let(:parser) { Fear::Extractor::GrammarParser.new }
5
- let(:matcher) { parser.parse(pattern).to_matcher }
6
-
7
- describe "#defined_at?" do
8
- subject { matcher }
9
-
10
- let(:pattern) { "number" }
11
-
12
- it { is_expected.to be_defined_at(1) }
13
- it { is_expected.to be_defined_at("foo") }
14
- it { is_expected.to be_defined_at(1.2) }
15
- it { is_expected.to be_defined_at([1, "2"]) }
16
-
17
- context "within array" do
18
- let(:pattern) { "[1, n, 2]" }
19
-
20
- it { is_expected.to be_defined_at([1, 2, 2]) }
21
- it { is_expected.to be_defined_at([1, "foo", 2]) }
22
- it { is_expected.not_to be_defined_at([1, "foo"]) }
23
- end
24
- end
25
-
26
- describe "#call" do
27
- subject { matcher.(other) }
28
-
29
- let(:pattern) { "1.0" }
30
-
31
- context "defined" do
32
- let(:other) { 1 }
33
-
34
- it { is_expected.to eq({}) }
35
- end
36
- end
37
-
38
- describe "#failure_reason" do
39
- subject { matcher.failure_reason(other) }
40
-
41
- let(:pattern) { "1.0" }
42
-
43
- context "match integer" do
44
- let(:other) { 1 }
45
- let(:pattern) { "1" }
46
-
47
- it { is_expected.to eq(Fear.none) }
48
- end
49
-
50
- context "match float" do
51
- let(:other) { 1.0 }
52
- let(:pattern) { "1" }
53
-
54
- it { is_expected.to eq(Fear.none) }
55
- end
56
-
57
- context "does not match another integer" do
58
- let(:other) { 2 }
59
- let(:pattern) { "1" }
60
-
61
- it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
62
- Expected `2` to match:
63
- 1
64
- ^
65
- ERROR
66
- end
67
- end
68
- end
@@ -1,34 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Fear::Extractor::Pattern do
4
- describe ".new" do
5
- context "invalid syntax" do
6
- subject { -> { described_class.new("[1, 2, 3") } }
7
-
8
- it "shows where the error happens" do
9
- is_expected.to raise_error(Fear::PatternSyntaxError) { |error|
10
- lines = error.message.split("\n")
11
- expect(lines[0]).to start_with("Expected one of")
12
- .and(end_with("at line 1, column 9 (byte 9):"))
13
-
14
- expect(lines[1]).to eq("[1, 2, 3")
15
- expect(lines[2]).to eq("~~~~~~~~^")
16
- }
17
- end
18
- end
19
- end
20
-
21
- describe "#failure_reason" do
22
- let(:pattern) { described_class.new("Some([:err, 444])") }
23
-
24
- context "not defined" do
25
- subject { pattern.failure_reason(Fear.some([:err, 445])) }
26
-
27
- it { is_expected.to eq(<<~MSG.strip) }
28
- Expected `445` to match:
29
- Some([:err, 444])
30
- ~~~~~~~~~~~~^
31
- MSG
32
- end
33
- end
34
- end
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe Fear::Extractor::TypedIdentifierMatcher do
4
- let(:parser) { Fear::Extractor::GrammarParser.new }
5
- let(:matcher) { parser.parse(pattern).to_matcher }
6
-
7
- describe "#defined_at?" do
8
- subject { matcher }
9
-
10
- let(:pattern) { "var : Integer" }
11
-
12
- it { is_expected.to be_defined_at(1) }
13
- it { is_expected.not_to be_defined_at("foo") }
14
- it { is_expected.not_to be_defined_at(1.2) }
15
-
16
- context "within array" do
17
- let(:pattern) { "[1, n : String, 2]" }
18
-
19
- it { is_expected.to be_defined_at([1, "foo", 2]) }
20
- it { is_expected.not_to be_defined_at([1, 2, 2]) }
21
- it { is_expected.not_to be_defined_at([1, "foo"]) }
22
- end
23
- end
24
-
25
- describe "#call" do
26
- subject { matcher.(other) }
27
-
28
- context "defined" do
29
- let(:other) { 1 }
30
- let(:pattern) { "var : Integer" }
31
-
32
- it { is_expected.to eq(var: 1) }
33
- end
34
-
35
- context "defined within array" do
36
- let(:other) { [4, 2, 1, 6] }
37
- let(:pattern) { "[head : Integer, *tail]" }
38
-
39
- it { is_expected.to eq(head: 4, tail: [2, 1, 6]) }
40
- end
41
- end
42
-
43
- describe "#" do
44
- subject { matcher.failure_reason(other) }
45
-
46
- let(:pattern) { "var : Integer" }
47
-
48
- context "match integer" do
49
- let(:other) { 1 }
50
-
51
- it { is_expected.to eq(Fear.none) }
52
- end
53
-
54
- context "does not match float" do
55
- let(:other) { 1.0 }
56
-
57
- it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
58
- Expected `1.0` to match:
59
- var : Integer
60
- ~~~~~~^
61
- ERROR
62
- end
63
- end
64
- end