kapusta 0.4.1 → 0.7.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.
@@ -0,0 +1,354 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'open3'
5
+ require 'rbconfig'
6
+
7
+ ERRORS_DIR = File.expand_path('../examples-errors', __dir__)
8
+ KAPUSTA_BIN = File.expand_path('../exe/kapusta', __dir__)
9
+ KAPFMT_BIN = File.expand_path('../exe/kapfmt', __dir__)
10
+
11
+ def run_error_example(name)
12
+ k_out, k_err, k_status = Open3.capture3(RbConfig.ruby, KAPUSTA_BIN, name, chdir: ERRORS_DIR)
13
+ f_out, f_err, f_status = Open3.capture3(RbConfig.ruby, KAPFMT_BIN, name, chdir: ERRORS_DIR)
14
+
15
+ raise "kapusta unexpectedly succeeded for #{name}" if k_status.success?
16
+ raise "kapfmt unexpectedly succeeded for #{name}" if f_status.success?
17
+ raise "kapusta wrote to stdout for #{name}: #{k_out.inspect}" unless k_out.empty?
18
+ raise "kapfmt wrote to stdout for #{name}: #{f_out.inspect}" unless f_out.empty?
19
+ raise "kapusta and kapfmt disagree for #{name}:\n kapusta: #{k_err} kapfmt: #{f_err}" unless k_err == f_err
20
+
21
+ k_err
22
+ end
23
+
24
+ RSpec.describe 'examples-errors' do
25
+ it 'accumulate-missing-iterator.kap' do
26
+ expect(run_error_example('accumulate-missing-iterator.kap'))
27
+ .to eq("accumulate-missing-iterator.kap:5:3: expected initial value and iterator binding table\n")
28
+ end
29
+
30
+ it 'auto-gensym-outside-quasiquote.kap' do
31
+ expect(run_error_example('auto-gensym-outside-quasiquote.kap'))
32
+ .to eq("auto-gensym-outside-quasiquote.kap: auto-gensym x# outside quasiquote\n")
33
+ end
34
+
35
+ it 'bad-multisym.kap' do
36
+ expect(run_error_example('bad-multisym.kap'))
37
+ .to eq("bad-multisym.kap:1:8: bad multisym: unbound.foo\n")
38
+ end
39
+
40
+ it 'bad-set-target.kap' do
41
+ expect(run_error_example('bad-set-target.kap'))
42
+ .to eq("bad-set-target.kap:2:1: bad set target: 1\n")
43
+ end
44
+
45
+ it 'bad-shorthand.kap' do
46
+ expect(run_error_example('bad-shorthand.kap'))
47
+ .to eq("bad-shorthand.kap:2:14: bad shorthand\n")
48
+ end
49
+
50
+ it 'call-empty-form.kap' do
51
+ expect(run_error_example('call-empty-form.kap'))
52
+ .to eq("call-empty-form.kap:7:8: expected a function, macro, or special to call\n")
53
+ end
54
+
55
+ it 'call-literal-number.kap' do
56
+ expect(run_error_example('call-literal-number.kap'))
57
+ .to eq("call-literal-number.kap:6:14: cannot call literal value 1\n")
58
+ end
59
+
60
+ it 'cannot-set-method-binding.kap' do
61
+ expect(run_error_example('cannot-set-method-binding.kap'))
62
+ .to eq("cannot-set-method-binding.kap:2:1: cannot set method binding: foo\n")
63
+ end
64
+
65
+ it 'case-no-patterns.kap' do
66
+ expect(run_error_example('case-no-patterns.kap'))
67
+ .to eq("case-no-patterns.kap:3:5: expected at least one pattern/body pair\n")
68
+ end
69
+
70
+ it 'case-no-subject.kap' do
71
+ expect(run_error_example('case-no-subject.kap'))
72
+ .to eq("case-no-subject.kap:1:1: missing subject\n")
73
+ end
74
+
75
+ it 'case-odd-pattern-body.kap' do
76
+ expect(run_error_example('case-odd-pattern-body.kap'))
77
+ .to eq("case-odd-pattern-body.kap:2:3: expected even number of pattern/body pairs\n")
78
+ end
79
+
80
+ it 'case-unsupported.kap' do
81
+ expect(run_error_example('case-unsupported.kap'))
82
+ .to eq("case-unsupported.kap:1:1: case/match clauses use patterns this compiler cannot translate\n")
83
+ end
84
+
85
+ it 'destructure-literal-number.kap' do
86
+ expect(run_error_example('destructure-literal-number.kap'))
87
+ .to eq("destructure-literal-number.kap:5:3: could not destructure literal\n")
88
+ end
89
+
90
+ it 'destructure-literal-table.kap' do
91
+ expect(run_error_example('destructure-literal-table.kap'))
92
+ .to eq("destructure-literal-table.kap:4:1: could not destructure literal\n")
93
+ end
94
+
95
+ it 'destructure-rest-as-table.kap' do
96
+ expect(run_error_example('destructure-rest-as-table.kap'))
97
+ .to eq("destructure-rest-as-table.kap:6:3: unable to bind table ...\n")
98
+ end
99
+
100
+ it 'dot-without-table.kap' do
101
+ expect(run_error_example('dot-without-table.kap'))
102
+ .to eq("dot-without-table.kap:5:15: expected table argument\n")
103
+ end
104
+
105
+ it 'each-not-binding-table.kap' do
106
+ expect(run_error_example('each-not-binding-table.kap'))
107
+ .to eq("each-not-binding-table.kap:6:3: expected binding table\n")
108
+ end
109
+
110
+ it 'faccumulate-missing-iterator.kap' do
111
+ expect(run_error_example('faccumulate-missing-iterator.kap'))
112
+ .to eq("faccumulate-missing-iterator.kap:7:3: expected initial value and iterator binding table\n")
113
+ end
114
+
115
+ it 'fcollect-missing-range.kap' do
116
+ expect(run_error_example('fcollect-missing-range.kap'))
117
+ .to eq("fcollect-missing-range.kap:6:3: expected range to include start and stop\n")
118
+ end
119
+
120
+ it 'fn-non-symbol-param.kap' do
121
+ expect(run_error_example('fn-non-symbol-param.kap'))
122
+ .to eq("fn-non-symbol-param.kap:4:1: destructure pattern this compiler cannot translate: [1 2]\n")
123
+ end
124
+
125
+ it 'fn-without-params.kap' do
126
+ expect(run_error_example('fn-without-params.kap'))
127
+ .to eq("fn-without-params.kap:4:11: expected parameters table\n")
128
+ end
129
+
130
+ it 'for-missing-stop.kap' do
131
+ expect(run_error_example('for-missing-stop.kap'))
132
+ .to eq("for-missing-stop.kap:6:3: expected range to include start and stop\n")
133
+ end
134
+
135
+ it 'global-non-symbol-name.kap' do
136
+ expect(run_error_example('global-non-symbol-name.kap'))
137
+ .to eq("global-non-symbol-name.kap:6:1: unable to bind integer 1\n")
138
+ end
139
+
140
+ it 'global-without-value.kap' do
141
+ expect(run_error_example('global-without-value.kap'))
142
+ .to eq("global-without-value.kap:6:1: expected name and value\n")
143
+ end
144
+
145
+ it 'icollect-missing-iterator.kap' do
146
+ expect(run_error_example('icollect-missing-iterator.kap'))
147
+ .to eq("icollect-missing-iterator.kap:6:3: expected iterator binding table\n")
148
+ end
149
+
150
+ it 'if-no-body.kap' do
151
+ expect(run_error_example('if-no-body.kap'))
152
+ .to eq("if-no-body.kap:8:5: expected condition and body\n")
153
+ end
154
+
155
+ it 'import-macros-missing-module.kap' do
156
+ expect(run_error_example('import-macros-missing-module.kap'))
157
+ .to eq("import-macros-missing-module.kap:4:1: import-macros is not yet supported\n")
158
+ end
159
+
160
+ it 'invalid-class-name.kap' do
161
+ expect(run_error_example('invalid-class-name.kap'))
162
+ .to eq("invalid-class-name.kap: invalid class name: lowercase\n")
163
+ end
164
+
165
+ it 'invalid-module-name.kap' do
166
+ expect(run_error_example('invalid-module-name.kap'))
167
+ .to eq("invalid-module-name.kap: invalid module name: lowercase\n")
168
+ end
169
+
170
+ it 'let-odd-bindings.kap' do
171
+ expect(run_error_example('let-odd-bindings.kap'))
172
+ .to eq("let-odd-bindings.kap:2:3: expected even number of name/value bindings\n")
173
+ end
174
+
175
+ it 'let-without-body-form.kap' do
176
+ expect(run_error_example('let-without-body-form.kap'))
177
+ .to eq("let-without-body-form.kap:4:5: expected body expression\n")
178
+ end
179
+
180
+ it 'local-with-extra-args.kap' do
181
+ expect(run_error_example('local-with-extra-args.kap'))
182
+ .to eq("local-with-extra-args.kap:6:3: local: expected name and value\n")
183
+ end
184
+
185
+ it 'local-without-value.kap' do
186
+ expect(run_error_example('local-without-value.kap'))
187
+ .to eq("local-without-value.kap:6:3: local: expected name and value\n")
188
+ end
189
+
190
+ it 'macro-name-must-be-symbol.kap' do
191
+ expect(run_error_example('macro-name-must-be-symbol.kap'))
192
+ .to eq("macro-name-must-be-symbol.kap: macro name must be a symbol\n")
193
+ end
194
+
195
+ it 'macro-params-must-be-vector.kap' do
196
+ expect(run_error_example('macro-params-must-be-vector.kap'))
197
+ .to eq("macro-params-must-be-vector.kap:1:12: macro params must be a vector\n")
198
+ end
199
+
200
+ it 'macro-unsafe-bind.kap' do
201
+ expect(run_error_example('macro-unsafe-bind.kap'))
202
+ .to eq("macro-unsafe-bind.kap:13:8: macro tried to bind unsafe without gensym\n")
203
+ end
204
+
205
+ it 'macro-vararg-with-operator.kap' do
206
+ expect(run_error_example('macro-vararg-with-operator.kap'))
207
+ .to eq("macro-vararg-with-operator.kap:5:3: tried to use vararg with operator\n")
208
+ end
209
+
210
+ it 'macros-entry-must-be-fn.kap' do
211
+ expect(run_error_example('macros-entry-must-be-fn.kap'))
212
+ .to eq("macros-entry-must-be-fn.kap: macros entry value must be a fn form, got 1\n")
213
+ end
214
+
215
+ it 'macros-entry-params-must-be-vector.kap' do
216
+ expect(run_error_example('macros-entry-params-must-be-vector.kap'))
217
+ .to eq("macros-entry-params-must-be-vector.kap:1:19: macros entry params must be a vector\n")
218
+ end
219
+
220
+ it 'macros-expects-hash.kap' do
221
+ expect(run_error_example('macros-expects-hash.kap'))
222
+ .to eq("macros-expects-hash.kap: macros expects a hash literal\n")
223
+ end
224
+
225
+ it 'match-no-patterns.kap' do
226
+ expect(run_error_example('match-no-patterns.kap'))
227
+ .to eq("match-no-patterns.kap:3:5: expected at least one pattern/body pair\n")
228
+ end
229
+
230
+ it 'match-no-subject.kap' do
231
+ expect(run_error_example('match-no-subject.kap'))
232
+ .to eq("match-no-subject.kap:1:1: missing subject\n")
233
+ end
234
+
235
+ it 'mismatched-brackets.kap' do
236
+ expect(run_error_example('mismatched-brackets.kap'))
237
+ .to eq("mismatched-brackets.kap:4:19: unexpected closing delimiter ')'\n")
238
+ end
239
+
240
+ it 'nested-quasiquote.kap' do
241
+ expect(run_error_example('nested-quasiquote.kap'))
242
+ .to eq("nested-quasiquote.kap: nested quasiquote is not supported\n")
243
+ end
244
+
245
+ it 'odd-forms-in-hash.kap' do
246
+ expect(run_error_example('odd-forms-in-hash.kap'))
247
+ .to eq("odd-forms-in-hash.kap:1:9: odd number of forms in hash\n")
248
+ end
249
+
250
+ it 'only-rest-param.kap' do
251
+ expect(run_error_example('only-rest-param.kap'))
252
+ .to eq("only-rest-param.kap:4:1: expected rest argument before last parameter\n")
253
+ end
254
+
255
+ it 'quote-runtime.kap' do
256
+ expect(run_error_example('quote-runtime.kap'))
257
+ .to eq("quote-runtime.kap:6:1: cannot emit form: `hello\n")
258
+ end
259
+
260
+ it 'rest-not-last.kap' do
261
+ expect(run_error_example('rest-not-last.kap'))
262
+ .to eq("rest-not-last.kap:6:3: expected rest argument before last parameter\n")
263
+ end
264
+
265
+ it 'set-immutable-let.kap' do
266
+ expect(run_error_example('set-immutable-let.kap'))
267
+ .to eq("set-immutable-let.kap:2:3: expected var counter\n")
268
+ end
269
+
270
+ it 'set-immutable-local.kap' do
271
+ expect(run_error_example('set-immutable-local.kap'))
272
+ .to eq("set-immutable-local.kap:8:3: expected var counter\n")
273
+ end
274
+
275
+ it 'shadow-special-fn.kap' do
276
+ expect(run_error_example('shadow-special-fn.kap'))
277
+ .to eq("shadow-special-fn.kap:6:3: local fn was overshadowed by a special form or macro\n")
278
+ end
279
+
280
+ it 'shadow-special-if.kap' do
281
+ expect(run_error_example('shadow-special-if.kap'))
282
+ .to eq("shadow-special-if.kap:4:1: local if was overshadowed by a special form or macro\n")
283
+ end
284
+
285
+ it 'symbol-starting-with-digit.kap' do
286
+ expect(run_error_example('symbol-starting-with-digit.kap'))
287
+ .to eq("symbol-starting-with-digit.kap:6:10: could not read number \"5var\"\n")
288
+ end
289
+
290
+ it 'tset-missing-value.kap' do
291
+ expect(run_error_example('tset-missing-value.kap'))
292
+ .to eq("tset-missing-value.kap:5:5: tset: expected table, key, and value arguments\n")
293
+ end
294
+
295
+ it 'unbalanced-parens.kap' do
296
+ expect(run_error_example('unbalanced-parens.kap'))
297
+ .to eq("unbalanced-parens.kap:4:1: unclosed opening delimiter '('\n")
298
+ end
299
+
300
+ it 'unclosed-table.kap' do
301
+ expect(run_error_example('unclosed-table.kap'))
302
+ .to eq("unclosed-table.kap:4:21: unexpected closing delimiter ']'\n")
303
+ end
304
+
305
+ it 'undefined-symbol.kap' do
306
+ expect(run_error_example('undefined-symbol.kap'))
307
+ .to eq("undefined-symbol.kap:1:8: undefined symbol: missing-symbol\n")
308
+ end
309
+
310
+ it 'unexpected-eof.kap' do
311
+ expect(run_error_example('unexpected-eof.kap'))
312
+ .to eq("unexpected-eof.kap:1:2: unexpected eof\n")
313
+ end
314
+
315
+ it 'unexpected-vararg.kap' do
316
+ expect(run_error_example('unexpected-vararg.kap'))
317
+ .to eq("unexpected-vararg.kap:2:10: unexpected vararg\n")
318
+ end
319
+
320
+ it 'unknown-special-form.kap' do
321
+ expect(run_error_example('unknown-special-form.kap'))
322
+ .to eq("unknown-special-form.kap:1:1: unknown special form: catch\n")
323
+ end
324
+
325
+ it 'unquote-outside-quote.kap' do
326
+ expect(run_error_example('unquote-outside-quote.kap'))
327
+ .to eq("unquote-outside-quote.kap:5:10: cannot emit form: ,x\n")
328
+ end
329
+
330
+ it 'unquote-splice-outside-list.kap' do
331
+ expect(run_error_example('unquote-splice-outside-list.kap'))
332
+ .to eq("unquote-splice-outside-list.kap: unquote-splice must appear inside a quoted list/vec\n")
333
+ end
334
+
335
+ it 'unterminated-string.kap' do
336
+ expect(run_error_example('unterminated-string.kap'))
337
+ .to eq("unterminated-string.kap:1:8: unterminated string\n")
338
+ end
339
+
340
+ it 'vararg-not-last.kap' do
341
+ expect(run_error_example('vararg-not-last.kap'))
342
+ .to eq("vararg-not-last.kap:1:1: expected vararg as last parameter\n")
343
+ end
344
+
345
+ it 'var-without-value.kap' do
346
+ expect(run_error_example('var-without-value.kap'))
347
+ .to eq("var-without-value.kap:6:3: var: expected name and value\n")
348
+ end
349
+
350
+ it 'when-no-body.kap' do
351
+ expect(run_error_example('when-no-body.kap'))
352
+ .to eq("when-no-body.kap:4:3: when: expected body\n")
353
+ end
354
+ end
@@ -43,7 +43,7 @@ RSpec.describe Kapusta::Formatter do
43
43
  Dir.mktmpdir do |dir|
44
44
  path = File.join(dir, 'sample.kap')
45
45
  File.write(path, <<~KAP)
46
- (let [uri (URI.join (ivar base-uri) (.. "/posts/" id)) body (Net.HTTP.get uri) post (JSON.parse body {:symbolize-names true}) {: title : author} post] (values title author))
46
+ (fn fetch-post [id] (let [uri (URI.join (ivar base-uri) (.. "/posts/" id)) body (Net.HTTP.get uri) post (JSON.parse body {:symbolize-names true}) {: title : author} post] (values title author)))
47
47
  KAP
48
48
 
49
49
  previous_path = ENV.fetch('PATH', nil)
@@ -54,11 +54,12 @@ RSpec.describe Kapusta::Formatter do
54
54
  end
55
55
 
56
56
  expect(output).to eq(<<~KAP)
57
- (let [uri (URI.join (ivar base-uri) (.. "/posts/" id))
58
- body (Net.HTTP.get uri)
59
- post (JSON.parse body {:symbolize-names true})
60
- {: title : author} post]
61
- (values title author))
57
+ (fn fetch-post [id]
58
+ (let [uri (URI.join (ivar base-uri) (.. "/posts/" id))
59
+ body (Net.HTTP.get uri)
60
+ post (JSON.parse body {:symbolize-names true})
61
+ {: title : author} post]
62
+ (values title author)))
62
63
  KAP
63
64
  ensure
64
65
  ENV['PATH'] = previous_path
data/spec/lsp_spec.rb ADDED
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'kapusta/lsp'
5
+ require 'json'
6
+ require 'stringio'
7
+
8
+ RSpec.describe Kapusta::LSP do
9
+ def frame(payload)
10
+ body = JSON.generate(payload)
11
+ "Content-Length: #{body.bytesize}\r\n\r\n#{body}"
12
+ end
13
+
14
+ def parse_responses(stdout)
15
+ messages = []
16
+ rest = stdout.dup
17
+ while (m = rest.match(/\AContent-Length: (\d+)\r\n\r\n/))
18
+ len = Integer(m[1], 10)
19
+ messages << JSON.parse(rest[m[0].length, len])
20
+ rest = rest[(m[0].length + len)..]
21
+ end
22
+ messages
23
+ end
24
+
25
+ def run(*frames)
26
+ input = StringIO.new(frames.join)
27
+ output = StringIO.new
28
+ log = StringIO.new
29
+ described_class.new(input:, output:, log:).run
30
+ parse_responses(output.string)
31
+ end
32
+
33
+ it 'advertises diagnostics and formatting capabilities on initialize' do
34
+ responses = run(frame(jsonrpc: '2.0', id: 1, method: 'initialize', params: {}))
35
+ capabilities = responses.first.dig('result', 'capabilities')
36
+
37
+ expect(capabilities).to include('textDocumentSync', 'documentFormattingProvider')
38
+ end
39
+
40
+ it 'publishes diagnostics for invalid source' do
41
+ responses = run(
42
+ frame(jsonrpc: '2.0', id: 1, method: 'initialize', params: {}),
43
+ frame(jsonrpc: '2.0', method: 'textDocument/didOpen',
44
+ params: { textDocument: { uri: 'file:///x.kap', version: 1, text: '(let [x 1] (+ x ()))' } })
45
+ )
46
+ diagnostics = responses.last.dig('params', 'diagnostics')
47
+
48
+ expect(diagnostics).not_to be_empty
49
+ end
50
+
51
+ it 'publishes no diagnostics for valid source' do
52
+ responses = run(
53
+ frame(jsonrpc: '2.0', id: 1, method: 'initialize', params: {}),
54
+ frame(jsonrpc: '2.0', method: 'textDocument/didOpen',
55
+ params: { textDocument: { uri: 'file:///x.kap', version: 1, text: '(print "hi")' } })
56
+ )
57
+
58
+ expect(responses.last.dig('params', 'diagnostics')).to be_empty
59
+ end
60
+
61
+ it 'returns a TextEdit for formatting' do
62
+ responses = run(
63
+ frame(jsonrpc: '2.0', id: 1, method: 'initialize', params: {}),
64
+ frame(jsonrpc: '2.0', method: 'textDocument/didOpen',
65
+ params: { textDocument: { uri: 'file:///x.kap', version: 1, text: "(fn greet [x] (print x))\n" } }),
66
+ frame(jsonrpc: '2.0', id: 2, method: 'textDocument/formatting',
67
+ params: { textDocument: { uri: 'file:///x.kap' } })
68
+ )
69
+ edits = responses.find { |m| m['id'] == 2 }['result']
70
+
71
+ expect(edits).to be_an(Array).and(be_one)
72
+ expect(edits.first).to include('range', 'newText')
73
+ end
74
+
75
+ it 'rejects requests sent before initialize' do
76
+ responses = run(
77
+ frame(jsonrpc: '2.0', id: 1, method: 'textDocument/formatting',
78
+ params: { textDocument: { uri: 'file:///x.kap' } })
79
+ )
80
+
81
+ expect(responses.first.dig('error', 'code')).to eq(-32_002)
82
+ end
83
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kapusta
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evgenii Morozov
@@ -13,6 +13,7 @@ description: Kapusta is a Lisp for the Ruby runtime.
13
13
  executables:
14
14
  - kapfmt
15
15
  - kapusta
16
+ - kapusta-ls
16
17
  extensions: []
17
18
  extra_rdoc_files: []
18
19
  files:
@@ -37,6 +38,7 @@ files:
37
38
  - examples/block-sort.kap
38
39
  - examples/blocks-and-kwargs.kap
39
40
  - examples/calc.kap
41
+ - examples/classify-wallet.kap
40
42
  - examples/climbing-stairs.kap
41
43
  - examples/contains-duplicate.kap
42
44
  - examples/counter.kap
@@ -80,6 +82,7 @@ files:
80
82
  - examples/pivot-index.kap
81
83
  - examples/plus-one.kap
82
84
  - examples/points.kap
85
+ - examples/power-of-three.kap
83
86
  - examples/primes.kap
84
87
  - examples/raindrops.kap
85
88
  - examples/record.kap
@@ -109,6 +112,7 @@ files:
109
112
  - examples/zoo-animal-inheritance-2.kap
110
113
  - exe/kapfmt
111
114
  - exe/kapusta
115
+ - exe/kapusta-ls
112
116
  - kapusta.gemspec
113
117
  - lib/kapusta.rb
114
118
  - lib/kapusta/ast.rb
@@ -122,18 +126,22 @@ files:
122
126
  - lib/kapusta/compiler/emitter/interop.rb
123
127
  - lib/kapusta/compiler/emitter/patterns.rb
124
128
  - lib/kapusta/compiler/emitter/support.rb
129
+ - lib/kapusta/compiler/lua_compat.rb
125
130
  - lib/kapusta/compiler/macro_expander.rb
126
131
  - lib/kapusta/compiler/normalizer.rb
127
132
  - lib/kapusta/env.rb
128
133
  - lib/kapusta/error.rb
134
+ - lib/kapusta/errors.rb
129
135
  - lib/kapusta/formatter.rb
136
+ - lib/kapusta/lsp.rb
130
137
  - lib/kapusta/reader.rb
131
138
  - lib/kapusta/support.rb
132
139
  - lib/kapusta/version.rb
133
140
  - spec/cli_spec.rb
141
+ - spec/examples_errors_spec.rb
134
142
  - spec/examples_spec.rb
135
143
  - spec/formatter_spec.rb
136
- - spec/reader_spec.rb
144
+ - spec/lsp_spec.rb
137
145
  - spec/spec_helper.rb
138
146
  homepage: https://github.com/evmorov/kapusta
139
147
  licenses:
data/spec/reader_spec.rb DELETED
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
-
5
- RSpec.describe Kapusta::Reader do
6
- describe 'error messages' do
7
- it 'reports unexpected closing delimiters with their source position' do
8
- expect { Kapusta.eval('(print 1))') }
9
- .to raise_error(Kapusta::Reader::Error,
10
- /unexpected closing delimiter '\)' at line 1, column 10/)
11
- end
12
-
13
- it 'reports unclosed opening delimiters with their source position' do
14
- cases = {
15
- '(print 1' => /unclosed opening delimiter '\(' at line 1, column 1/,
16
- '[1 2' => /unclosed opening delimiter '\[' at line 1, column 1/,
17
- '{:name "A"' => /unclosed opening delimiter '\{' at line 1, column 1/
18
- }
19
-
20
- cases.each do |source, message|
21
- expect { Kapusta.eval(source) }
22
- .to raise_error(Kapusta::Reader::Error, message)
23
- end
24
- end
25
- end
26
- end