Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: incremental goal state requests select incomplete snapshot #6887

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

mhuisi
Copy link
Contributor

@mhuisi mhuisi commented Jan 31, 2025

This PR fixes a bug where the goal state selection would sometimes select incomplete incremental snapshots on whitespace, leading to an incorrect "no goals" response. Fixes #6594, a regression that was originally introduced in 4.11.0 by #4727.

The fundamental cause of #6594 was that the snapshot selection would always select the first snapshot with a range that contains the cursor position. For tactics, whitespace had to be included in this range. However, in the test case of #6594, this meant that the snapshot selection would also sometimes pick a snapshot before the cursor that still contains the cursor in its whitespace, but which also does not necessarily contain all the information needed to produce a correct goal state. Specifically, at the InfoTree-level, when the cursor is in whitespace, we distinguish competing goal states by their level of indentation. The snapshot selection did not have access to this information, so it necessarily had to do the wrong thing in some cases.

This PR fixes the issue by adjusting the snapshot selection for goals to explicitly account for whitespace and indentation, and refactoring the language processor architecture to thread enough information through to the snapshot selection so that it can decide which snapshots to use without having to force too many tasks, which would destroy incrementality in goal state requests.

Specifically, this PR makes the following adjustments:

  • Refactor SnapshotTask to contain both a Syntax and a Range. Before, SnapshotTasks had a single range that was used both for displaying file progress information and for selecting snapshots in server requests. For most snapshots, this range did not include whitespace, though for tactics it did. Now, the reportingRange field of SnapshotTask is intended exclusively for reporting file progress information, and the Syntax is used for selecting snapshots in server requests. Importantly, the Syntax contains the full range information of the snapshot, i.e. its regular range and its range including whitespace.
  • Adjust all call-sites of SnapshotTask to produce a reasonable Syntax.
  • Adjust the goal snapshot selection to account for whitespace and indentation, as the InfoTree goal selection does.
  • Fix a bug in the snapshot tree tracing that would cause it to render the Info of a snapshot at the wrong location when trace.Elab.info was also set.

This PR is based on #6329.

@mhuisi mhuisi requested review from Vtec234, Kha and kim-em as code owners January 31, 2025 16:26
inner? := some { range?, task := inner.result }
finished := { range?, task := finished.result }
next := #[{ range? := stxs.getRange?, task := next.result }]
inner? := some { stx? := tac, reportingRange? := range?, task := inner.result }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

range? should be unnecessary now, right? findInfoTreeAtPos/findGoalsAt? doesn't use it anymore

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed the range hack.

Comment on lines +289 to +290
stx? := mkNullNode altStxs
reportingRange? := none
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This special case seems worthy of a comment

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(We discussed this and came to the conclusion that it's not a special case)

Comment on lines +253 to +255
match cmdParsed.nextCmdSnap? with
| some next => next.task.bind (sync := true) go
| none => .pure none
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can return early if hoverPos is before cmdParsed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

Task (Option CommandParsedSnapshot) := Id.run do
/-- Finds the first `CommandParsedSnapshot` containing `hoverPos`, asynchronously. -/
partial def findCmdParsedSnap (doc : EditableDocument) (hoverPos : String.Pos)
(config : Language.SnapSelectionConfig) : Task (Option CommandParsedSnapshot) := Id.run do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is an example where we do not want to include stop/trailing in findCmdParsedSnap? Isn't this only relevant when we get to nesting, i.e. in the info tree?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've adjusted the command snapshot selection logic so that it doesn't need a config.

- Get rid of command snap selection config
- Remove tactic reporting range hack
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

No goals after finishing subgoal
2 participants