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-pneeds 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.finishis set to the value offsharp-goto-beyond-final-line.fsharp-goto-beyond-final-lineclaims to go to the line after the end of "the current statement."[^1]fsharp-goto-beyond-final-lineuses a while loopand-ing onfsharp-continuation-line-p.fsharp-continuation-line-ponly 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 returnspointat that position.fsharp-statement-opens-block-pimmediately adjusts the value returned fromfsharp-continuation-line-pby subtracting1.
To summarize:
fsharp-statement-opens-block-pis 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-linedefinitely does no such thing. (Again, no tests.)fsharp-continuation-line-pis 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."