fsharp / fsharp/emacs-fsharp-mode

Problems in Block Detection and Expression Traversal

Open
#224 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Emacs Lisp
Stars
215
Forks
65
PR merge metrics
No merged PRs in 30d

Description

### 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:

1. `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 of `point`, and an endpoint called `finish`. `finish` is set to the value of `fsharp-goto-beyond-final-line`.
2. `fsharp-goto-beyond-final-line` claims to go to the line after the end of "the current statement."[^1]
3. `fsharp-goto-beyond-final-line` uses a while loop `and`-ing on `fsharp-continuation-line-p`.
4. `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 returns `point` at that position.
5. `fsharp-statement-opens-block-p` _immediately_ adjusts the value returned from `fsharp-continuation-line-p` by subtracting `1`.

To summarize:
1. `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.
2. `fsharp-goto-beyond-final-line` definitely does no such thing. (Again, no tests.)
3. `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."

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by tracing fsharp-statement-opens-block-p, fsharp-goto-beyond-final-line, fsharp-continuation-line-p, and fsharp-compute-indentation to understand their current motion and fallback behavior. Add focused tests for expression block detection, end-of-expression navigation, and ongoing-block detection; done means the predicates are documented, consistently named, and their behavior is covered by tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
emacs-lisp
Domain
tooling
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.