crystal-lang / crystal

The Crystal Programming Language
https://crystal-lang.org
Apache License 2.0
19.48k stars 1.62k forks source link

Strings should be limited to a single line by default #15031

Open nobodywasishere opened 1 month ago

nobodywasishere commented 1 month ago

Discussion

Single quote strings ("string") should be single-line by default. This allows for better error-handling (if one quote is missing, can just start again from next line), especially since 99% of the time, strings will only be single-line. This is especially apparent when editing, as a double-quote will invert quote highlighting for the rest of the document until it's fixed.

Recommending using heredocs could be a remedy, but those may be less clean depending on the situation. Alternatively, we could go with a letter/symbol in front of quotes to tell the lexer to allow multi-line, or use triple quotes.

a = "single line string"

b = "other string without end quote
# syntax error, potentially recoverable though

c = """
multi-line string?
"""

d = m"
multi-line string?
"

I realize this is a breaking change, and so could only fit behind an optional feature-flag (-Dsingle_line_strings) or something for Crystal 2.0. This is also something that's more focused on making writing language tooling easier / improves the developer experience, rather than something that concerns the language itself.

straight-shoota commented 1 month ago

I'm not quite following the motivation.

You mention this is primarily intended to make language tooling easier? What effect would this change have there?

This is especially apparent when editing, as a double-quote will invert quote highlighting for the rest of the document until it's fixed.

How much of a problem is that really? I don't recall having much issues with this. Every halfway-decent editor inserts an end delimiter automatically when I write a start delimiter (btw. this is not necessarily the case for heredocs, so that would hardly be a good alternative). So there'll only be a dangling delimiter if I mess something up.

nobodywasishere commented 1 month ago

This would allow a fault-tolerant lexer/parser to recover if there is an extra delimiter. Otherwise, there's no way to recover and it will invert the quotation of the rest of the document.

While editors do insert an additional quote after the cursor when you insert one, there are cases when it doesn't do this (like trying to insert another pair of quotes before a quote, it only inserts one quote as there's already one after it). A single dangling delimiter is the problem I'm trying to mitigate.

ysbaddaden commented 1 month ago

It might be possible without the change. The prism parser for Ruby might be useful to understand how they recover this exact issue.

I like the idea. I'm quite fond of """ though we already have heredocs, so šŸ¤·

straight-shoota commented 1 month ago

Note this would only have a positive effect if the string literal is the last thing on the line. If anything follows afterward, the missing delimiter would still cause issues. And that might even be harder to spot.

devnote-dev commented 1 month ago

Focusing on the language side of things, I'd agree that multi-line quote strings probably shouldn't be a thing. I can't say I've ever had as use case for it that heredocs didn't solve, and it has been the cause of issues such as #13526, #13537 and #13903. I'm not aware of any limitations of heredocs so as to warrant another way to define multi-line strings like the suggested """ (keep in mind we also have percent literals which reasonably accept multiple lines).

On the tooling side of things I don't see this being of much use even if it's behind a flag because it would still be limited to shards that choose to support it, so you'd still need to handle parsing multi-line quote strings.