emacs-fsharp-mode
emacs-fsharp-mode copied to clipboard
Problems in Block Detection and Expression Traversal
Description
As part of #218, I've been digging in to the code fsharp-mode
uses to compute indentation. This is a fairly complicated topic, including regexen for keyword detection, predicate functions, and motion functions. In particular, I've found a set of problems with fsharp-statement-opens-block-p
and fsharp-goto-beyond-final-line
. This goes like so:
-
fsharp-statement-opens-block-p
needs to compute whether or not the current statement creates a new block or not. To do this, it searches between the current value ofpoint
, and an endpoint calledfinish
.finish
is set to the value offsharp-goto-beyond-final-line
. -
fsharp-goto-beyond-final-line
claims to go to the line after the end of "the current statement."[^1] -
fsharp-goto-beyond-final-line
uses a while loopand
-ing onfsharp-continuation-line-p
. -
fsharp-continuation-line-p
only considers a line a "continuation line" if it either 1) ends in a dangling arithmetic operator or 2) point is inside a block delimited by a pair (i.e. point is inside[]
or{}
). This means the function almost always goes one line forward, then returnspoint
at that position. -
fsharp-statement-opens-block-p
immediately adjusts the value returned fromfsharp-continuation-line-p
by subtracting1
.
To summarize:
-
fsharp-statement-opens-block-p
is taking an incredibly convoluted approach to searching until end of same line. This might be correct, but there are no previously existing tests. -
fsharp-goto-beyond-final-line
definitely does no such thing. (Again, no tests.) -
fsharp-continuation-line-p
is being used when we likely want a slightly different function.
For example, let x = 5 +
is a "continuation line", but type Shape =
is not.
(As a final, frustrating note, F# does not, in fact, have statements, at all.)
Proposed Solutions
fsharp-statement-opens-block-p
needs to reliably return whether or not the statement (which is to say, expression) opens a block. It is used all over the place, so should be well documented, and under test. (Also, the name should be changed to use "expression" over "statement".)
fsharp-goto-beyond-final-line
should do so, and be under test. I assert we need a function similar to, but distinct from, fsharp-continuation-line-p
. Something like fsharp-in-block-p
-- "tell me if this line could be considered part of an ongoing block." Right now, there is no code to detect this -- it's handled in fsharp-compute-indentation
as the final default "fall-through" case, so lacks a proper predicate. We should probably have one!
Footnotes
[^1] Note that if #223 has been merged, this will say "the current expression."