Browse Source

Correctly indent multiline variable blocks in let

This patch fixes a bug where multiline variable blocks in let would not
intent correctly, fixes #97.
pull/116/head
Fredrik Ekre 1 year ago
parent
commit
83204b8fcc
No known key found for this signature in database
GPG Key ID: DE82E6D5E364C0A2
  1. 14
      CHANGELOG.md
  2. 40
      src/runestone.jl
  3. 6
      test/runtests.jl

14
CHANGELOG.md

@ -9,6 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 @@ -9,6 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed
- Fix a bug that caused "single space after keyword" to not apply after the `function`
keyword in non-standard function definitions. ([#113])
- Fix a bug that caused multiline variable blocks in `let` to not indent correctly ([#97],
[#116]). This bug is classified as a [spec-bug] and the fix will result in diffs like the
following:
```diff
let a = 1,
- b = 2
+ b = 2
a + b
end
```
## [v1.0.1] - 2024-11-28
### Fixed
@ -17,11 +27,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 @@ -17,11 +27,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [v1.0.0] - 2024-11-06
First stable release of Runic.jl. See [README.md](README.md) for details and documentation.
[spec-bug]: https://github.com/fredrikekre/Runic.jl?tab=readme-ov-file#version-policy
<!-- Links generated by Changelog.jl -->
[v1.0.0]: https://github.com/fredrikekre/Runic.jl/releases/tag/v1.0.0
[v1.0.1]: https://github.com/fredrikekre/Runic.jl/releases/tag/v1.0.1
[#97]: https://github.com/fredrikekre/Runic.jl/issues/97
[#109]: https://github.com/fredrikekre/Runic.jl/issues/109
[#110]: https://github.com/fredrikekre/Runic.jl/issues/110
[#113]: https://github.com/fredrikekre/Runic.jl/issues/113
[#116]: https://github.com/fredrikekre/Runic.jl/issues/116

40
src/runestone.jl

@ -1640,6 +1640,33 @@ function indent_function_or_macro(ctx::Context, node::Node) @@ -1640,6 +1640,33 @@ function indent_function_or_macro(ctx::Context, node::Node)
return any_kid_changed ? make_node(node, kids) : nothing
end
# Soft-indentation between the variables
function indent_let_varblock(ctx::Context, node::Node)
@assert kind(node) === K"block" && !is_leaf(node)
kids = verified_kids(node)
changed = false
if length(kids) == 0
@assert span(node) == 0
# Empty block, but where are spaces and comments?
return nothing
end
# First node *must* be a space (?)
i = 1
kid = kids[i]
@assert kind(kid) === K"Whitespace"
i = findnext(x -> !JuliaSyntax.is_whitespace(x), kids, i + 1)
i === nothing && return nothing
@assert kind(kids[i]) in KSet"Identifier = $ macrocall" # This is a bit unnecessary
while (i = findnext(x -> kind(x) === K"NewlineWs", kids, i + 1); i !== nothing)
@assert kind(kids[i]) === K"NewlineWs"
if !has_tag(kids[i], TAG_LINE_CONT)
kids[i] = add_tag(kids[i], TAG_LINE_CONT)
changed = true
end
end
return changed ? make_node(node, kids) : nothing
end
function indent_let(ctx::Context, node::Node)
kids = verified_kids(node)
any_kid_changed = false
@ -1651,13 +1678,24 @@ function indent_let(ctx::Context, node::Node) @@ -1651,13 +1678,24 @@ function indent_let(ctx::Context, node::Node)
kids[let_idx] = add_tag(let_node, TAG_INDENT)
any_kid_changed = true
end
# Second node is the variables block (will be soft-indented by the assignments pass)
# Second node is the variables block
vars_idx = 2
vars_node = kids[vars_idx]
@assert !is_leaf(vars_node) && kind(vars_node) === K"block"
if span(vars_node) > 0 && length(verified_kids(vars_node)) > 0
@assert kind(last_leaf(vars_node)) !== "NewlineWs"
end
let p = position(ctx.fmt_io)
for i in 1:(vars_idx - 1)
accept_node!(ctx, kids[i])
end
vars_node′ = indent_let_varblock(ctx, vars_node)
if vars_node′ !== nothing
kids[vars_idx] = vars_node′
any_kid_changed = true
end
seek(ctx.fmt_io, p)
end
# # Third node is the NewlineWs before the block
# ln_idx = 3
# ln_node = kids[ln_idx]

6
test/runtests.jl

@ -912,6 +912,12 @@ end @@ -912,6 +912,12 @@ end
# K"cartesian_iterator"
@test format_string("for i in I,\n$(sp)j in J\n# body\nend") ==
"for i in I,\n j in J\n # body\nend"
# K"let"
for a in ("x = 1", "x", "@inline foo() = 1", "\$x"),
b in ("y = 1", "y", "@inline bar() = 1", "\$y")
@test format_string("let $(a),\n$(sp)$(b)\n nothing\nend") ==
"let $(a),\n $(b)\n nothing\nend"
end
end
end

Loading…
Cancel
Save