rdoc-spellcheck 1.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,655 @@
1
+ # coding: UTF-8
2
+
3
+ require 'rubygems'
4
+ require 'minitest/autorun'
5
+ require 'stringio'
6
+ require 'tempfile'
7
+
8
+ gem 'rdoc', '~> 3.12'
9
+
10
+ require 'rdoc' # automatically requires rdoc/generator/spell_check
11
+ require 'rdoc/test_case'
12
+
13
+ class TestRDocGeneratorSpellcheck < RDoc::TestCase
14
+
15
+ def setup
16
+ super
17
+
18
+ @SC = RDoc::Generator::Spellcheck
19
+ @options = RDoc::Options.new
20
+ @options.spell_language = 'en_US'
21
+ @options.spell_minimum_word_length = 3
22
+
23
+ @sc = @SC.new @options
24
+
25
+ @text = 'Hello, this class has real gud spelling!'
26
+
27
+ @tempfile = Tempfile.new __name__
28
+ @tempfile.puts "# #{@text}"
29
+ @tempfile.puts
30
+ @tempfile.puts "# funkify thingus"
31
+ @tempfile.flush
32
+
33
+ @escaped_path = Regexp.escape @tempfile.path
34
+
35
+ @top_level = RDoc::TopLevel.new @tempfile.path
36
+ @top_level.comment = comment 'funkify_thingus'
37
+
38
+ method = RDoc::AnyMethod.new nil, 'funkify_thingus'
39
+ @top_level.add_method method
40
+ end
41
+
42
+ def teardown
43
+ @tempfile.close
44
+
45
+ super
46
+ end
47
+
48
+ def test_add_name
49
+ @sc.add_name 'funkify_thingus'
50
+
51
+ assert @sc.spell.check('funkify'), 'funkify not added to wordlist'
52
+ assert @sc.spell.check('thingus'), 'thingus not added to wordlist'
53
+ end
54
+
55
+ def test_class_setup_options_default
56
+ orig_lang = ENV['LANG']
57
+ ENV['LANG'] = 'en_US.UTF-8'
58
+
59
+ options = RDoc::Options.new
60
+
61
+ options.parse %w[--format spellcheck]
62
+
63
+ refute options.spell_add_words
64
+ refute options.spell_aggregate_all
65
+ assert_equal 4, options.spell_minimum_word_length
66
+ assert_equal 'en_US', options.spell_language
67
+ assert_equal Dir.pwd, options.spell_source_dir
68
+
69
+ assert options.quiet
70
+ ensure
71
+ ENV['LANG'] = orig_lang
72
+ end
73
+
74
+ def test_class_setup_options_spell_aggregate_all
75
+ options = RDoc::Options.new
76
+
77
+ options.parse %w[
78
+ --format spellcheck
79
+ --no-ignore-invalid
80
+ --spell-aggregate-all
81
+ ]
82
+
83
+ assert options.spell_aggregate_all
84
+ end
85
+
86
+ def test_class_setup_options_spell_add_words
87
+ $stdin = StringIO.new "foo bar\nbaz"
88
+
89
+ options = RDoc::Options.new
90
+
91
+ options.parse %w[
92
+ --format spellcheck
93
+ --no-ignore-invalid
94
+ --spell-add-words
95
+ ]
96
+
97
+ assert_equal %w[foo bar baz], options.spell_add_words
98
+ ensure
99
+ $stdin = STDIN
100
+ end
101
+
102
+ def test_class_setup_options_spell_add_words_list
103
+ options = RDoc::Options.new
104
+
105
+ options.parse %w[
106
+ --format spellcheck
107
+ --no-ignore-invalid
108
+ --spell-add-words foo,bar
109
+ ]
110
+
111
+ assert_equal %w[foo bar], options.spell_add_words
112
+ end
113
+
114
+ def test_class_setup_options_spell_add_words_file
115
+ Tempfile.open 'words.txt' do |io|
116
+ io.write "foo bar\nbaz"
117
+ io.rewind
118
+
119
+ options = RDoc::Options.new
120
+
121
+ options.parse %W[
122
+ --format spellcheck
123
+ --no-ignore-invalid
124
+ --spell-add-words #{io.path}
125
+ ]
126
+
127
+ assert_equal %w[foo bar baz], options.spell_add_words
128
+ end
129
+ end
130
+
131
+ def test_class_setup_options_spell_language
132
+ options = RDoc::Options.new
133
+
134
+ options.parse %w[
135
+ --format spellcheck
136
+ --no-ignore-invalid
137
+ --spell-language en_GB
138
+ ]
139
+
140
+ assert_equal 'en_GB', options.spell_language
141
+ end
142
+
143
+ def test_class_setup_options_spell_minimum_word_length
144
+ options = RDoc::Options.new
145
+
146
+ options.parse %w[
147
+ --format spellcheck
148
+ --no-ignore-invalid
149
+ --spell-minimum-word-length 5
150
+ ]
151
+
152
+ assert_equal 5, options.spell_minimum_word_length
153
+ end
154
+
155
+ def test_initialize_add_words
156
+ private_wordlist do
157
+ @options.spell_add_words = %w[funkify thingus]
158
+
159
+ sc = @SC.new @options
160
+
161
+ spell = Aspell.new 'en_US'
162
+
163
+ assert spell.check('funkify'), 'funkify not added to personal wordlist'
164
+ assert spell.check('thingus'), 'thingus not added to personal wordlist'
165
+ end
166
+ end
167
+
168
+ def test_add_name
169
+ @sc.add_name '<=>'
170
+
171
+ assert true # just for counting
172
+ end
173
+
174
+ def test_add_name_utf_8
175
+ @sc.add_name 'Володя'
176
+
177
+ assert true # just for counting
178
+ end
179
+
180
+ def test_find_misspelled
181
+ private_wordlist do
182
+ c = comment @text
183
+
184
+ report = @sc.find_misspelled c
185
+
186
+ word, offset = report.shift
187
+
188
+ assert_equal 'gud', word
189
+ assert_equal 28, offset
190
+ end
191
+ end
192
+
193
+ def test_find_misspelled_length
194
+ private_wordlist do
195
+ c = comment @text
196
+
197
+ @sc.minimum_word_length = 4
198
+ report = @sc.find_misspelled c
199
+
200
+ assert_empty report
201
+ end
202
+ end
203
+
204
+ def test_find_misspelled_quote
205
+ c = comment "doesn't"
206
+
207
+ report = @sc.find_misspelled c
208
+
209
+ assert_empty report
210
+
211
+ c = comment "'quoted'"
212
+
213
+ report = @sc.find_misspelled c
214
+
215
+ assert_empty report
216
+
217
+ c = comment "other's"
218
+
219
+ report = @sc.find_misspelled c
220
+
221
+ assert_empty report
222
+ end
223
+
224
+ def test_find_misspelled_underscore
225
+ private_wordlist do
226
+ c = comment 'gud_method'
227
+
228
+ report = @sc.find_misspelled c
229
+
230
+ word, offset = report.shift
231
+
232
+ assert_equal 'gud', word
233
+ assert_equal 0, offset
234
+ end
235
+ end
236
+
237
+ def test_find_misspelled_utf_8
238
+ private_wordlist do
239
+ c = comment 'Marvin Gülker'
240
+
241
+ report = @sc.find_misspelled c
242
+
243
+ word, offset = report.shift
244
+
245
+ assert_equal 'Gülker', word
246
+ assert_equal 8, offset
247
+ end
248
+ end
249
+
250
+ def test_generate_attribute
251
+ klass = @top_level.add_class RDoc::NormalClass, 'Object'
252
+
253
+ attribute = RDoc::Attr.new nil, 'attr', 'RW', comment(@text)
254
+ attribute.record_location @top_level
255
+
256
+ klass.add_attribute attribute
257
+
258
+ out, err = capture_io do
259
+ @sc.generate [@top_level]
260
+ end
261
+
262
+ assert_empty err
263
+
264
+ assert_match %r%^Object\.attr_accessor :attr in #{@escaped_path}:%, out
265
+ assert_match %r%^"gud"%, out
266
+ end
267
+
268
+ def test_generate_class
269
+ klass = @top_level.add_class RDoc::NormalClass, 'Object'
270
+
271
+ c = comment @text
272
+ klass.add_comment c, @top_level
273
+
274
+ out, err = capture_io do
275
+ @sc.generate [@top_level]
276
+ end
277
+
278
+ assert_empty err
279
+
280
+ assert_match %r%^class Object in #{@escaped_path}:%, out
281
+ assert_match %r%^"gud"%, out
282
+ end
283
+
284
+ def test_generate_constant
285
+ klass = @top_level.add_class RDoc::NormalClass, 'Object'
286
+
287
+ const = RDoc::Constant.new 'CONSTANT', nil, comment(@text)
288
+ const.record_location @top_level
289
+
290
+ klass.add_constant const
291
+
292
+ out, err = capture_io do
293
+ @sc.generate [@top_level]
294
+ end
295
+
296
+ assert_empty err
297
+
298
+ assert_match %r%^Object::CONSTANT in #{@escaped_path}:%, out
299
+ assert_match %r%^"gud"%, out
300
+ end
301
+
302
+ def test_generate_correct
303
+ klass = @top_level.add_class RDoc::NormalClass, 'Object'
304
+
305
+ c = comment 'This class has perfect spelling!'
306
+ klass.add_comment c, @top_level
307
+
308
+ out, err = capture_io do
309
+ @sc.generate [@top_level]
310
+ end
311
+
312
+ assert_empty err
313
+ assert_equal "No misspellings found\n", out
314
+ end
315
+
316
+ def test_generate_file
317
+ @top_level.comment = comment @text
318
+ @top_level.parser = RDoc::Parser::Text
319
+
320
+ out, err = capture_io do
321
+ @sc.generate [@top_level]
322
+ end
323
+
324
+ assert_empty err
325
+
326
+ assert_match %r%^In #{@escaped_path}:%, out
327
+ assert_match %r%^"gud"%, out
328
+ end
329
+
330
+ def test_generate_include
331
+ klass = @top_level.add_class RDoc::NormalClass, 'Object'
332
+
333
+ incl = RDoc::Include.new 'INCLUDE', comment(@text)
334
+ incl.record_location @top_level
335
+
336
+ klass.add_include incl
337
+
338
+ out, err = capture_io do
339
+ @sc.generate [@top_level]
340
+ end
341
+
342
+ assert_empty err
343
+
344
+ assert_match %r%^Object\.include INCLUDE in #{@escaped_path}:%, out
345
+ assert_match %r%^"gud"%, out
346
+ end
347
+
348
+ def test_generate_method
349
+ klass = @top_level.add_class RDoc::NormalClass, 'Object'
350
+
351
+ meth = RDoc::AnyMethod.new nil, 'method'
352
+ meth.record_location @top_level
353
+ meth.comment = comment @text, meth
354
+
355
+ klass.add_method meth
356
+
357
+ out, err = capture_io do
358
+ @sc.generate [@top_level]
359
+ end
360
+
361
+ assert_empty err
362
+
363
+ assert_match %r%^Object#method in #{@escaped_path}:%, out
364
+ assert_match %r%^"gud"%, out
365
+ end
366
+
367
+ def test_generate_multiple
368
+ klass = @top_level.add_class RDoc::NormalClass, 'Object'
369
+ c = comment @text
370
+ klass.add_comment c, @top_level
371
+
372
+ meth = RDoc::AnyMethod.new nil, 'method'
373
+ meth.record_location @top_level
374
+ meth.comment = comment @text, meth
375
+
376
+ klass.add_method meth
377
+
378
+ out, err = capture_io do
379
+ @sc.generate [@top_level]
380
+ end
381
+
382
+ assert_empty err
383
+
384
+ assert_match %r%^Object#method in #{@escaped_path}:%, out
385
+ assert_match %r%^"gud"%, out
386
+ assert_match %r%^2 gud%, out
387
+ end
388
+
389
+ def test_location_of
390
+ Tempfile.open 'location_of' do |io|
391
+ io.puts "##"
392
+ io.puts "# Here is some text with proper spelling"
393
+ io.puts "#"
394
+ io.puts "# #{@text}"
395
+ io.flush
396
+
397
+ tl = RDoc::TopLevel.new io.path
398
+ text = "Here is some text with proper spelling\n\n#{@text}"
399
+ offset = text.index "gud"
400
+
401
+ line, column = @sc.location_of text, offset, tl
402
+
403
+ assert_equal 3, line
404
+ assert_equal 30, column
405
+ end
406
+ end
407
+
408
+ def test_location_of_first_line
409
+ Tempfile.open 'location_of' do |io|
410
+ io.puts "# #{@text}"
411
+ io.flush
412
+
413
+ tl = RDoc::TopLevel.new io.path
414
+ offset = @text.index "gud"
415
+
416
+ line, column = @sc.location_of @text, offset, tl
417
+
418
+ assert_equal 0, line
419
+ assert_equal 30, column
420
+ end
421
+ end
422
+
423
+ def test_location_of_include
424
+ Tempfile.open 'location_of' do |io|
425
+ io.puts "##"
426
+ io.puts "# Here is some text with proper spelling"
427
+ io.puts "#"
428
+ io.puts "# :include: other.rdoc"
429
+ io.flush
430
+
431
+ tl = RDoc::TopLevel.new io.path
432
+ text = "Here is some text with proper spelling\n\n#{@text}"
433
+ offset = text.index "gud"
434
+
435
+ assert_nil @sc.location_of text, offset, tl
436
+ end
437
+ end
438
+
439
+ def test_misspellings_for
440
+ out = @sc.misspellings_for 'class Object', comment(@text), @top_level
441
+
442
+ out = out.join "\n"
443
+
444
+ location = Regexp.escape @top_level.absolute_name
445
+ assert_match %r%^class Object in #{location}%, out
446
+ assert_match %r%^#{location}:0:32%, out
447
+ assert_match %r%^"gud"%, out
448
+ end
449
+
450
+ def test_misspellings_for_empty
451
+ out = @sc.misspellings_for 'class Object', comment(''), @top_level
452
+
453
+ assert_empty out
454
+ end
455
+
456
+ def test_misspellings_for_include
457
+ Tempfile.open 'other' do |io|
458
+ io.write "# :include: original.txt"
459
+ io.flush
460
+
461
+ tl = RDoc::TopLevel.new io.path
462
+
463
+ out = @sc.misspellings_for 'class Object', comment(@text), tl
464
+
465
+ out = out.join "\n"
466
+
467
+ include_location = Regexp.escape tl.absolute_name
468
+ source_location = Regexp.escape @top_level.absolute_name
469
+
470
+ assert_match %r%^class Object in #{include_location}%, out
471
+ assert_match %r%^\(via include\)%, out
472
+ assert_match %r%^"gud"%, out
473
+ end
474
+ end
475
+
476
+ def test_setup_dictionary_attribute
477
+ klass = @top_level.add_class RDoc::NormalClass, 'Object'
478
+
479
+ attribute = RDoc::Attr.new nil, 'funkify_thingus', 'RW', comment(@text)
480
+ attribute.record_location @top_level
481
+
482
+ klass.add_attribute attribute
483
+
484
+ @sc.setup_dictionary
485
+
486
+ assert @sc.spell.check('FUNKIFY'), 'FUNKIFY not added to wordlist'
487
+ assert @sc.spell.check('THINGUS'), 'THINGUS not added to wordlist'
488
+ end
489
+
490
+ def test_setup_dictionary_class
491
+ klass = @top_level.add_class RDoc::NormalClass, 'FunkifyThingus'
492
+
493
+ c = comment @text
494
+ klass.add_comment c, @top_level
495
+
496
+ @sc.setup_dictionary
497
+
498
+ assert @sc.spell.check('FunkifyThingus'),
499
+ 'FunkifyThingus not added to wordlist'
500
+ end
501
+
502
+ def test_setup_dictionary_constant
503
+ klass = @top_level.add_class RDoc::NormalClass, 'Object'
504
+
505
+ const = RDoc::Constant.new 'FUNKIFY_THINGUS', nil, comment(@text)
506
+ const.record_location @top_level
507
+
508
+ klass.add_constant const
509
+
510
+ @sc.setup_dictionary
511
+
512
+ assert @sc.spell.check('FUNKIFY'), 'FUNKIFY not added to wordlist'
513
+ assert @sc.spell.check('THINGUS'), 'THINGUS not added to wordlist'
514
+ end
515
+
516
+ def test_setup_dictionary_defaults
517
+ @sc.setup_dictionary
518
+
519
+ word = RDoc::Generator::Spellcheck::DEFAULT_WORDS.first
520
+
521
+ assert @sc.spell.check(word), "#{word} not added to wordlist"
522
+ end
523
+
524
+ def test_setup_dictionary_file
525
+ RDoc::TopLevel.new 'funkify_thingus.rb'
526
+
527
+ @sc.setup_dictionary
528
+
529
+ assert @sc.spell.check('funkify'), 'funkify not added to wordlist'
530
+ assert @sc.spell.check('thingus'), 'thingus not added to wordlist'
531
+ end
532
+
533
+ def test_setup_dictionary_include
534
+ klass = @top_level.add_class RDoc::NormalClass, 'Object'
535
+
536
+ incl = RDoc::Include.new 'FUNKIFY_THINGUS', comment(@text)
537
+ incl.record_location @top_level
538
+
539
+ klass.add_include incl
540
+
541
+ @sc.setup_dictionary
542
+
543
+ assert @sc.spell.check('FUNKIFY'), 'FUNKIFY not added to wordlist'
544
+ assert @sc.spell.check('THINGUS'), 'THINGUS not added to wordlist'
545
+ end
546
+
547
+ def test_setup_dictionary_method
548
+ klass = @top_level.add_class RDoc::NormalClass, 'Object'
549
+
550
+ meth = RDoc::AnyMethod.new nil, 'bagas_methd'
551
+ meth.block_params = 'foo, bar'
552
+ meth.params = 'baz, hoge'
553
+ meth.record_location @top_level
554
+ meth.comment = comment @text, meth
555
+
556
+ klass.add_method meth
557
+
558
+ @sc.setup_dictionary
559
+
560
+ assert @sc.spell.check('bagas'), 'bagas not added to wordlist'
561
+ assert @sc.spell.check('methd'), 'methd not added to wordlist'
562
+
563
+ assert @sc.spell.check('foo'), 'foo not added to wordlist'
564
+ assert @sc.spell.check('bar'), 'bar not added to wordlist'
565
+ assert @sc.spell.check('baz'), 'baz not added to wordlist'
566
+ assert @sc.spell.check('hoge'), 'hoge not added to wordlist'
567
+ end
568
+
569
+ def test_suggestion_text
570
+ out = @sc.suggestion_text @text, 'gud', 28
571
+
572
+ suggestions = suggest('gud').join ', '
573
+
574
+ expected = <<-EXPECTED
575
+ "...has real \e[1;31mgud\e[m spelling!..."
576
+
577
+ "gud" suggestions:
578
+ \t#{suggestions}
579
+
580
+ EXPECTED
581
+
582
+ assert_equal expected, out
583
+ end
584
+
585
+ def test_suggestion_text_end
586
+ out = @sc.suggestion_text 'you did real gud', 'gud', 14
587
+
588
+ suggestions = suggest('gud').join ', '
589
+
590
+ expected = <<-EXPECTED
591
+ "...did real \e[1;31mgud\e[m"
592
+
593
+ "gud" suggestions:
594
+ \t#{suggestions}
595
+
596
+ EXPECTED
597
+
598
+ assert_equal expected, out
599
+ end
600
+
601
+ def test_suggestion_text_newline
602
+ text = "This text has a typo\non the secnd line"
603
+ out = @sc.suggestion_text text, 'secnd', 29
604
+
605
+ suggestions = suggest('secnd').join ', '
606
+
607
+ expected = <<-EXPECTED
608
+ "...o\non the \e[1;31msecnd\e[m line"
609
+
610
+ "secnd" suggestions:
611
+ \t#{suggestions}
612
+
613
+ EXPECTED
614
+
615
+ assert_equal expected, out
616
+ end
617
+
618
+ def test_suggestion_text_start
619
+ out = @sc.suggestion_text 'gud night world, see you tomorrow', 'gud', 0
620
+
621
+ suggestions = suggest('gud').join ', '
622
+
623
+ expected = <<-EXPECTED
624
+ "\e[1;31mgud\e[m night wor..."
625
+
626
+ "gud" suggestions:
627
+ \t#{suggestions}
628
+
629
+ EXPECTED
630
+
631
+ assert_equal expected, out
632
+ end
633
+
634
+ def private_wordlist
635
+ orig_aspell_conf = ENV['ASPELL_CONF']
636
+
637
+ Tempfile.open 'personal_wordlist' do |wordlist|
638
+ Tempfile.open 'personal_repl' do |repl|
639
+ ENV['ASPELL_CONF'] = "personal #{wordlist.path};repl #{repl.path}"
640
+
641
+ @sc = @SC.new @options
642
+
643
+ yield
644
+ end
645
+ end
646
+ ensure
647
+ ENV['ASPELL_CONF'] = orig_aspell_conf
648
+ end
649
+
650
+ def suggest word
651
+ Aspell.new('en_US').suggest(word).first 5
652
+ end
653
+
654
+ end
655
+