Skip to content

SyntaxEditor could be more efficient when just operating on changes that do not involve lambda callbacks #28378

Closed as not planned
@CyrusNajmabadi

Description

@CyrusNajmabadi

SyntaxEditor has a very cool design surface where it allows one to describe a set of changes to a tree as a series of edits (as opposed to a bottom-up tree rewrite). Those edits can be of two forms. A node->node change (i.e. editor.ReplaceNode(oldNode, newNode)) or a node->callback change (i.e. editor.ReplaceNode(oldNode, currentNode => ...)). The benefit of the latter is it lets you see what your oldNode now looks like after previous edits have been applied. This is important in case you are making changes to nodes that contain other nodes that are being changed.

However, this functionality also comes at a cost. Because of the node->callback form, the editor has to apply changes one-at-a-time, so that it will have the proper currentNodes to pass to callbacks. This is because the currentNode will not be free-floating. Instead, it is stitched into its own tree. Allowing the callback to see things like the real parent at that point in the edits. When making many changes to a tree, this can end up becoming quite expensive as each change involves an entire tree rewrite. While the rewrite itself is still pretty efficient (usually only involving a logarithmic walk), that still makes the entire op O(n log n). And, even at n log n, then constants involves are fairly high given lots of overhead in the all the subcomponents involved.

We can do a far better job here in the fairly-common case of all the edits just being simple node->node changes. In that case, there is no need to be changing the tree serially, as there is no need to know the right currentNode to pass to a callback. Instead, we can just to a single bottom-up rewrite that processes all the changed nodes in one pass.

--

Doing this doesn't seem like it would be very complex. We would simply need to walk the 'Change's that SyntaxEditor was storing up. If all of them were non-callback 'Replace' changes, then we could simply make a call to root.ReplaceNodes which will do the bottom up rewrite for us, with all the provided nodes.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions