Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions spec/compiler/parser/to_s_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -490,4 +490,125 @@ describe "ASTNode#to_s" do
end
end
CRYSTAL

expect_to_s %({% {id: 10} %})
expect_to_s <<-'CR'
{%
data = {__nil: nil}
data["foo"] = {
id: 1,
active: true,
name: "foo".upcase,
pie: 3.14,
}
%}
CR

expect_to_s <<-'CR'
{%
data = {__nil: nil}
data["foo"] = {
id: 1, active: true,
name: "foo".upcase,
pie: 3.14,
}
%}
CR

expect_to_s <<-'CR'
{%
data = {__nil: nil}
data["foo"] = {
id: 1, active: true,
name: "foo".upcase,
pie: 3.14, biz: "baz", blah: false,
}
%}
CR

expect_to_s <<-'CR'
{%
{
id: 1,

blah: false,

pie: 3.14,
}
%}
CR

expect_to_s <<-'CR', <<-'CR'
{%
{
id: 1,

# Foo
pie: 3.14,
}
%}
CR
{%
{
id: 1,


pie: 3.14,
}
%}
CR

expect_to_s <<-'CR', <<-'CR'
macro finished
{% verbatim do %}
{%
nt = {
id: 1,

# Foo
pie: 3.14,
}
%}
{% end %}
end
CR
macro finished
{% verbatim do %}
{%
nt = {
id: 1,


pie: 3.14,
}
%}
{% end %}
end
CR

expect_to_s <<-'CR'
{%
{
id: 1,
blah: false,
pie: 3.14}
%}
CR

expect_to_s <<-'CR'
{%
{id: 1,
blah: false,
pie: 3.14}
%}
CR

expect_to_s <<-'CR'
{%
{id: 1,
blah: false,
pie: 3.14,
}
%}
CR
end
52 changes: 51 additions & 1 deletion src/compiler/crystal/syntax/to_s.cr
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,61 @@ module Crystal

def visit(node : NamedTupleLiteral)
@str << '{'
node.entries.join(@str, ", ") do |entry|

# short-circuit to handle empty named tuple context
if node.entries.empty?
@str << '}'
return false
end
Comment on lines +206 to +210
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's at least one case somewhere where an empty named tuple literal is to be stringified. Having this early return prevents having to use .first? and .last? and dealing with nil.


# A node starts multiline when its starting brace is on a different line than the staring line of it's first entry
start_multiline = (start_loc = node.location) && (first_entry_loc = node.entries.first?.try &.value.location) && first_entry_loc.line_number > start_loc.line_number

# and similarly ends multiline if its last entry's end location is on a different line than its ending brace
end_multiline = (last_entry_loc = node.entries.last?.try &.value.end_location) && (end_loc = node.end_location) && end_loc.line_number > last_entry_loc.line_number

last_entry = node.entries.first

if start_multiline
newline
@indent += 1
append_indent
end

node.entries.each_with_index do |entry, idx|
write_extra_newlines (last_entry.value || entry.value).end_location, entry.value.location

if (current_entry_loc = entry.value.location) && (last_entry_loc = last_entry.value.location) && current_entry_loc.line_number > last_entry_loc.line_number
newline

# If the node is not starting multiline, explicitly enable it once there is a line break to ensure additional values are indented properly
unless start_multiline
start_multiline = true
@indent += 1
end

append_indent
elsif !idx.zero?
@str << ' '
end

visit_named_arg_name(entry.key)
@str << ": "
entry.value.accept self

last_entry = entry

@str << ',' unless idx == node.entries.size - 1
end

@indent -= 1 if start_multiline

if end_multiline
@str << ','
newline
append_indent
end

@str << '}'
false
end
Expand Down