Skip to content

Commit 46f4c07

Browse files
committed
Use a real parser for RDoc::Markup::ToHtml#parseable? (Fixes #320)
This uses BEGIN {return true} when evaluating the text, which will do a syntax check, but not actually execute the code. Using a real ruby parser is a big improvement for two reasons. First, it highlights valid ruby syntax that was left unhighlighted by the previous parser. Second and more important, it doesn't highlight invalid ruby syntax, which makes it easier to catch errors in example code in the documentation. This even fixes some errors in the tests, where code like "class C end" was considered valid syntax. There is some fallout in the tests where code that wasn't highlighted before is now highlighted, this also fixes those cases so the tests pass.
1 parent c102881 commit 46f4c07

File tree

3 files changed

+47
-25
lines changed

3 files changed

+47
-25
lines changed

lib/rdoc/markup/to_html.rb

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,11 +379,12 @@ def list_end_for(list_type)
379379
end
380380

381381
##
382-
# Returns true if Ripper is available it can create a sexp from +text+
382+
# Returns true if text is valid ruby syntax
383383

384384
def parseable? text
385-
text =~ /\b(def|class|module|require) |=>|\{\s?\||do \|/ and
386-
text !~ /<%|%>/
385+
eval("BEGIN {return true}\n#{text}")
386+
rescue SyntaxError
387+
false
387388
end
388389

389390
##

test/test_rdoc_markup_to_html.rb

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ def accept_rule
292292
end
293293

294294
def accept_verbatim
295-
assert_equal "\n<pre>hi\n world</pre>\n", @to.res.join
295+
assert_equal "\n<pre class=\"ruby\"><span class=\"ruby-identifier\">hi</span>\n <span class=\"ruby-identifier\">world</span>\n</pre>\n", @to.res.join
296296
end
297297

298298
def end_accepting
@@ -444,8 +444,7 @@ def test_accept_verbatim_parseable_error
444444

445445
expected = <<-EXPECTED
446446
447-
<pre>#{inner}
448-
</pre>
447+
<pre>#{inner}</pre>
449448
EXPECTED
450449

451450
assert_equal expected, @to.res.join
@@ -604,8 +603,9 @@ def test_list_verbatim_2
604603
<ul><li>
605604
<p>one</p>
606605
607-
<pre>verb1
608-
verb2</pre>
606+
<pre class=\"ruby\"><span class=\"ruby-identifier\">verb1</span>
607+
<span class=\"ruby-identifier\">verb2</span>
608+
</pre>
609609
</li><li>
610610
<p>two</p>
611611
</li></ul>
@@ -615,16 +615,36 @@ def test_list_verbatim_2
615615
end
616616

617617
def test_parseable_eh
618-
assert @to.parseable?('def x() end'), 'def'
619-
assert @to.parseable?('class C end'), 'class'
620-
assert @to.parseable?('module M end'), 'module'
621-
assert @to.parseable?('a # => blah'), '=>'
622-
assert @to.parseable?('x { |y| ... }'), '{ |x|'
623-
assert @to.parseable?('x do |y| ... end'), 'do |x|'
624-
refute @to.parseable?('* 1'), '* 1'
625-
refute @to.parseable?('# only a comment'), '# only a comment'
626-
refute @to.parseable?('<% require "foo" %>'), 'ERB'
627-
refute @to.parseable?('class="foo"'), 'HTML class'
618+
valid_syntax = [
619+
'def x() end',
620+
'def x; end',
621+
'class C; end',
622+
"module M end",
623+
'a # => blah',
624+
'x { |y| nil }',
625+
'x do |y| nil end',
626+
'# only a comment',
627+
'require "foo"',
628+
'cls="foo"'
629+
]
630+
invalid_syntax = [
631+
'def x end',
632+
'class C end',
633+
'class C < end',
634+
'module M < C end',
635+
'a=># blah',
636+
'x { |y| ... }',
637+
'x do |y| ... end',
638+
'// only a comment',
639+
'<% require "foo" %>',
640+
'class="foo"'
641+
]
642+
valid_syntax.each do |t|
643+
assert @to.parseable?(t), "valid syntax considered invalid: #{t}"
644+
end
645+
invalid_syntax.each do |t|
646+
refute @to.parseable?(t), "invalid syntax considered valid: #{t}"
647+
end
628648
end
629649

630650
def test_to_html

test/test_rdoc_markup_to_html_snippet.rb

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ def accept_rule
309309
end
310310

311311
def accept_verbatim
312-
assert_equal "\n<pre>hi\n world</pre>\n", @to.res.join
312+
assert_equal "\n<pre class=\"ruby\"><span class=\"ruby-identifier\">hi</span>\n <span class=\"ruby-identifier\">world</span>\n</pre>\n", @to.res.join
313313
assert_equal 10, @to.characters
314314
end
315315

@@ -427,8 +427,7 @@ def test_accept_verbatim_ruby_error
427427

428428
expected = <<-EXPECTED
429429
430-
<pre>#{inner}
431-
</pre>
430+
<pre>#{inner}</pre>
432431
EXPECTED
433432

434433
assert_equal expected, @to.res.join
@@ -588,8 +587,9 @@ def test_convert_limit_verbatim_multiline
588587
expected = <<-EXPECTED
589588
<p>Look for directives in a normal comment block:
590589
591-
<pre># :stopdoc:
592-
#{inner}</pre>
590+
<pre class=\"ruby\"><span class=\"ruby-comment\"># :stopdoc:</span>
591+
<span class=\"ruby-comment\">#{inner}</span>
592+
</pre>
593593
EXPECTED
594594

595595
actual = @to.convert rdoc
@@ -665,8 +665,9 @@ def test_list_verbatim_2
665665
expected = <<-EXPECTED
666666
<p>one
667667
668-
<pre>verb1
669-
verb2</pre>
668+
<pre class=\"ruby\"><span class=\"ruby-identifier\">verb1</span>
669+
<span class=\"ruby-identifier\">verb2</span>
670+
</pre>
670671
<p>two
671672
672673
EXPECTED

0 commit comments

Comments
 (0)