diff --git a/lib/yard/parser/ruby/legacy/ruby_lex.rb b/lib/yard/parser/ruby/legacy/ruby_lex.rb index 0a843d0f5..40f805ff0 100644 --- a/lib/yard/parser/ruby/legacy/ruby_lex.rb +++ b/lib/yard/parser/ruby/legacy/ruby_lex.rb @@ -656,7 +656,7 @@ def lex_init() if @lex_state != EXPR_END && @lex_state != EXPR_CLASS && (@lex_state != EXPR_ARG || @space_seen) c = peek(0) - tk = identify_here_document if /[-\w\"\'\`]/ =~ c + tk = identify_here_document if /[-~\w\"\'\`]/ =~ c end if !tk @lex_state = EXPR_BEG @@ -1063,6 +1063,8 @@ def identify_here_document ch = getc if ch == "-" ch = getc + elsif ch == "~" + ch = getc indent = true end if /['"`]/ =~ ch # ' @@ -1096,9 +1098,12 @@ def identify_here_document str = String.new while (l = gets) l.chomp! - l.strip! if indent - break if l == quoted - str << l.chomp << "\n" + if l == quoted + str = dedent(str) if indent + break + else + str << l.chomp << "\n" + end end @reader.divert_read_from(reserve) @@ -1108,6 +1113,16 @@ def identify_here_document Token(Ltype2Token[lt], str).set_text(str.dump) end + def dedent(str) + lines = str.split("\n", -1) + dedent_amt = lines.map do |line| + line =~ /\S/ ? line.match(/^ */).offset(0)[1] : nil + end.compact.min || 0 + return str if dedent_amt.zero? + + lines.map { |line| line =~ /\S/ ? line.gsub(/^ {#{dedent_amt}}/, "") : line }.join("\n") + end + def identify_quotation(initial_char) ch = getc if lt = PERCENT_LTYPE[ch] diff --git a/spec/parser/ruby/legacy/statement_list_spec.rb b/spec/parser/ruby/legacy/statement_list_spec.rb index e6474a992..525b5bdc3 100644 --- a/spec/parser/ruby/legacy/statement_list_spec.rb +++ b/spec/parser/ruby/legacy/statement_list_spec.rb @@ -294,6 +294,12 @@ class B; end it "converts heredoc to string" do src = "<<-XML\n foo\n\nXML" s = stmt(src) - expect(s.source).to eq '"foo\n\n"' + expect(s.source).to eq '" foo\n\n"' + end + + it "converts squiggly heredoc to string" do + src = "<<~XML\n bar\n\nXML" + s = stmt(src) + expect(s.source).to eq '"bar\n\n"' end end