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

Enable the Code Editor, with new apply-text-edits algo. #9055

Merged
merged 44 commits into from
Feb 19, 2024

Conversation

kazcw
Copy link
Contributor

@kazcw kazcw commented Feb 14, 2024

Pull Request Description

  • Fix the UI problems with our CodeMirror integration (Fixed view stability; Fixed a focus bug; Fixed errors caused by diagnostics range exceptions; Fixed linter invalidation--see https://discuss.codemirror.net/t/problem-trying-to-force-linting/5823; Implemented edit-coalescing for performance).
  • Introduce an algorithm for applying text edits to an AST. Compared to the GUI1 approach, the new algorithm supports deeper identity-stability for expressions (which is important for subexpression metadata and Y.Js sync), as well as reordered-subtree identification.
  • Enable the code editor.

Important Notes

Checklist

Please ensure that the following checklist has been satisfied before submitting the PR:

  • The documentation has been updated, if necessary.
  • Screenshots/screencasts have been attached, if there are any visual changes. For interactive or animated visual changes, a screencast is preferred.
  • All code follows the
    Scala,
    Java,
    and
    Rust
    style guides. In case you are using a language not listed above, follow the Rust style guide.
  • All code has been tested:
    • Unit tests have been written where possible.
    • If GUI codebase was changed, the GUI was tested when built using ./run ide build.

@kazcw kazcw added the -gui label Feb 14, 2024
@kazcw kazcw self-assigned this Feb 14, 2024
@kazcw kazcw added the CI: No changelog needed Do not require a changelog entry for this PR. label Feb 14, 2024
@kazcw kazcw linked an issue Feb 14, 2024 that may be closed by this pull request
@kazcw kazcw mentioned this pull request Feb 15, 2024
5 tasks
Copy link
Collaborator

@somebody1234 somebody1234 left a comment

Choose a reason for hiding this comment

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

approving the single-line change to dashboard code.

Copy link
Contributor

@Frizi Frizi left a comment

Choose a reason for hiding this comment

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

Lots of small nitpicks, nothing serious enough to block merging this. The comments can be addressed either immediately, or as a separate PR.

app/gui2/shared/ast/mutableModule.ts Outdated Show resolved Hide resolved
app/gui2/shared/ast/mutableModule.ts Outdated Show resolved Hide resolved
app/gui2/shared/ast/parse.ts Show resolved Hide resolved
app/gui2/src/util/ast/index.ts Outdated Show resolved Hide resolved
app/gui2/shared/ast/parse.ts Outdated Show resolved Hide resolved
Comment on lines 86 to 105
while (starts[0] !== undefined) {
if (starts[0] < range[0]) {
startMap.set(starts[0], starts[0] + offset)
} else if (starts[0] <= range[1]) {
startMap.set(starts[0], range[0] + offset + insert.length)
} else {
break
}
starts.shift()
}
while (ends[0] !== undefined) {
if (ends[0] <= range[0]) {
endMap.set(ends[0], ends[0] + offset)
} else if (ends[0] <= range[1]) {
endMap.set(ends[0], range[0] + offset)
} else {
break
}
ends.shift()
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Shifting arrays in a loop is unnecessarily expensive. Better to replace those with index accesses, and maintain two incrementing "read head" indices throuhgout the function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hm. The typechecker doesn't seem to know that while (ends[endsIndex] !== undefined) implies that ends[endsIndex] !== undefined at the start of the loop body, so I'll use iterators.

app/gui2/shared/util/data/text.ts Outdated Show resolved Hide resolved
(ready) => {
if (ready) graphStore.moduleSource.observe(observeSourceChange)
},
{ immediate: true },
Copy link
Contributor

Choose a reason for hiding this comment

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

If viewInitialized is always set asynchronously, then this immediate has no real effect, since ready will always be false on the first execution.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually in practice projectStore.module is already non-null when the top-level watchEffect above runs, so this needs immediate to work.

function* fieldDataEntries<Fields>(map: FixedMapView<Fields>) {
for (const entry of map.entries()) {
// All fields that are not from `AstFields` are `FieldData`.
if (!astFieldKeys.includes(entry[0] as any)) yield entry as [string, FieldData]
Copy link
Contributor

Choose a reason for hiding this comment

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

Since the key type is checked here, the return type can be narrowed.

Suggested change
if (!astFieldKeys.includes(entry[0] as any)) yield entry as [string, FieldData]
if (!astFieldKeys.includes(entry[0] as any)) yield entry as [keyof RawAstFields, FieldData]

This should help further reduce casts down the line.

Also to contain those remaining (trivial in-context) type casts, a separate isAstFieldKey type asserting function could be created. Same for FieldData validation, though this one may be a bit harder to balance safety and runtime verification overhead. But given that this effectively deals with arbitrary network received data, we shouldn't just blindly trust it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This return the fields that are not from AstFields, so I don't see a good way to narrow it.

Runtime AST field validation would need to occur when applying updates to the module, and seems orthogonal to this new functionality--on develop we already trust the received AST fields not to cause TypeErrors.

app/gui2/shared/ast/tree.ts Outdated Show resolved Hide resolved
@kazcw kazcw added the CI: Ready to merge This PR is eligible for automatic merge label Feb 19, 2024
@mergify mergify bot merged commit c811a5a into develop Feb 19, 2024
25 of 27 checks passed
@mergify mergify bot deleted the wip/kw/text-edits-4-new-algo branch February 19, 2024 23:57
farmaazon added a commit that referenced this pull request Feb 20, 2024
mergify bot pushed a commit that referenced this pull request Feb 21, 2024
Add a test for some functionality introduced in #9055.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
-gui CI: No changelog needed Do not require a changelog entry for this PR. CI: Ready to merge This PR is eligible for automatic merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

AST-diffing for text edits
3 participants