Skip to content

Commit a5fc3d6

Browse files
committed
Added limited HEREDOC tokenization
A TkHEREDOC is only generated when the heredoc identifier is followed by a line end. When followed by a method call, comma, etc. a TkSTRING is returned instead so the source output in the HTML view is correct. Fixes #162 Conflicts: History.rdoc lib/rdoc/store.rb
1 parent 78ef23e commit a5fc3d6

File tree

4 files changed

+75
-10
lines changed

4 files changed

+75
-10
lines changed

History.rdoc

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
* Fixed tokenization of % when it is not followed by a $-string type
99
* Fixed display of __END__ in documentation examples in HTML output
1010
* Fixed tokenization of reserved words used as new-style hash keys
11-
11+
* Fixed HEREDOC output for the limited case of a heredoc followed by a line
12+
end. When a HEREDOC is not followed by a line end RDoc is not currently
13+
smart enough to restore the source correctly. Bug #162 by Zachary Scott.
1214

1315
=== 3.12.1 / 2013-02-05
1416

lib/rdoc/ruby_lex.rb

+20-4
Original file line numberDiff line numberDiff line change
@@ -982,12 +982,13 @@ def identify_here_document
982982
indent = true
983983
end
984984
if /['"`]/ =~ ch
985-
lt = ch
985+
user_quote = lt = ch
986986
quoted = ""
987987
while (c = getc) && c != lt
988988
quoted.concat c
989989
end
990990
else
991+
user_quote = nil
991992
lt = '"'
992993
quoted = ch.dup
993994
while (c = getc) && c =~ /\w/
@@ -1007,26 +1008,41 @@ def identify_here_document
10071008
end
10081009
end
10091010

1011+
output_heredoc = reserve.join =~ /\A\r?\n\z/
1012+
1013+
if output_heredoc then
1014+
doc = '<<'
1015+
doc << '-' if indent
1016+
doc << "#{user_quote}#{quoted}#{user_quote}\n"
1017+
else
1018+
doc = '"'
1019+
end
1020+
10101021
@here_header = false
1011-
doc = '"'
10121022
while l = gets
10131023
l = l.sub(/(:?\r)?\n\z/, "\n")
10141024
if (indent ? l.strip : l.chomp) == quoted
10151025
break
10161026
end
10171027
doc << l
10181028
end
1019-
doc << '"'
1029+
1030+
if output_heredoc then
1031+
doc << l.chomp
1032+
else
1033+
doc << '"'
1034+
end
10201035

10211036
@here_header = true
10221037
@here_readed.concat reserve
10231038
while ch = reserve.pop
10241039
ungetc ch
10251040
end
10261041

1042+
token_class = output_heredoc ? RDoc::RubyLex::TkHEREDOC : Ltype2Token[lt]
10271043
@ltype = ltback
10281044
@lex_state = EXPR_END
1029-
Token(Ltype2Token[lt], doc)
1045+
Token(token_class, doc)
10301046
end
10311047

10321048
def identify_quotation

lib/rdoc/ruby_token.rb

+1
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ def Token(token, value = nil)
331331
[:TkINTEGER, TkVal],
332332
[:TkFLOAT, TkVal],
333333
[:TkSTRING, TkVal],
334+
[:TkHEREDOC, TkVal],
334335
[:TkXSTRING, TkVal],
335336
[:TkREGEXP, TkVal],
336337
[:TkSYMBOL, TkVal],

test/test_rdoc_ruby_lex.rb

+51-5
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ def x
7070
@TK::TkIDENTIFIER.new( 4, 1, 4, 'x'),
7171
@TK::TkNL .new( 5, 1, 5, "\n"),
7272
@TK::TkSPACE .new( 6, 2, 0, ' '),
73-
@TK::TkSTRING .new( 8, 2, 2, %Q{"Line 1\nLine 2\n"}),
73+
@TK::TkHEREDOC .new( 8, 2, 2,
74+
%Q{<<E\nLine 1\nLine 2\nE}),
7475
@TK::TkNL .new(27, 5, 28, "\n"),
7576
@TK::TkEND .new(28, 6, 0, 'end'),
7677
@TK::TkNL .new(31, 6, 28, "\n"),
@@ -96,21 +97,66 @@ def test_class_tokenize_hash_symbol
9697
assert_equal expected, tokens
9798
end
9899

100+
def test_class_tokenize_heredoc_CR_NL
101+
tokens = RDoc::RubyLex.tokenize <<-RUBY, nil
102+
string = <<-STRING\r
103+
Line 1\r
104+
Line 2\r
105+
STRING\r
106+
RUBY
107+
108+
expected = [
109+
@TK::TkIDENTIFIER.new( 0, 1, 0, 'string'),
110+
@TK::TkSPACE .new( 6, 1, 6, ' '),
111+
@TK::TkASSIGN .new( 7, 1, 7, '='),
112+
@TK::TkSPACE .new( 8, 1, 8, ' '),
113+
@TK::TkHEREDOC .new( 9, 1, 9,
114+
%Q{<<-STRING\nLine 1\nLine 2\n STRING}),
115+
@TK::TkSPACE .new(44, 4, 45, "\r"),
116+
@TK::TkNL .new(45, 4, 46, "\n"),
117+
]
118+
119+
assert_equal expected, tokens
120+
end
121+
122+
def test_class_tokenize_heredoc_call
123+
tokens = RDoc::RubyLex.tokenize <<-'RUBY', nil
124+
string = <<-STRING.chomp
125+
Line 1
126+
Line 2
127+
STRING
128+
RUBY
129+
130+
expected = [
131+
@TK::TkIDENTIFIER.new( 0, 1, 0, 'string'),
132+
@TK::TkSPACE .new( 6, 1, 6, ' '),
133+
@TK::TkASSIGN .new( 7, 1, 7, '='),
134+
@TK::TkSPACE .new( 8, 1, 8, ' '),
135+
@TK::TkSTRING .new( 9, 1, 9, %Q{"Line 1\nLine 2\n"}),
136+
@TK::TkDOT .new(41, 4, 42, '.'),
137+
@TK::TkIDENTIFIER.new(42, 4, 43, 'chomp'),
138+
@TK::TkNL .new(47, 4, 48, "\n"),
139+
]
140+
141+
assert_equal expected, tokens
142+
end
143+
99144
def test_class_tokenize_heredoc_indent
100145
tokens = RDoc::RubyLex.tokenize <<-'RUBY', nil
101146
string = <<-STRING
102147
Line 1
103148
Line 2
104-
STRING
149+
STRING
105150
RUBY
106151

107152
expected = [
108153
@TK::TkIDENTIFIER.new( 0, 1, 0, 'string'),
109154
@TK::TkSPACE .new( 6, 1, 6, ' '),
110155
@TK::TkASSIGN .new( 7, 1, 7, '='),
111156
@TK::TkSPACE .new( 8, 1, 8, ' '),
112-
@TK::TkSTRING .new( 9, 1, 9, %Q{"Line 1\nLine 2\n"}),
113-
@TK::TkNL .new(39, 4, 40, "\n"),
157+
@TK::TkHEREDOC .new( 9, 1, 9,
158+
%Q{<<-STRING\nLine 1\nLine 2\n STRING}),
159+
@TK::TkNL .new(41, 4, 42, "\n"),
114160
]
115161

116162
assert_equal expected, tokens
@@ -128,7 +174,7 @@ def test_class_tokenize_heredoc_percent_N
128174
@TK::TkSPACE .new( 1, 1, 1, ' '),
129175
@TK::TkIDENTIFIER.new( 2, 1, 2, 'b'),
130176
@TK::TkSPACE .new( 3, 1, 3, ' '),
131-
@TK::TkSTRING .new( 4, 1, 4, %Q{"%N\n"}),
177+
@TK::TkHEREDOC .new( 4, 1, 4, %Q{<<-U\n%N\nU}),
132178
@TK::TkNL .new(13, 3, 14, "\n"),
133179
]
134180

0 commit comments

Comments
 (0)