Ok, I’ve updated my parinfer implementation to return modified lines instead of precise edits. This gets nearly all of the gain with much less incidental complexity, and makes the implementation more similar to mainline parinfer so it’s easier to keep in sync.
Basically I get the lines out of a CharSequence using subSequence(), so no char arrays are required to be allocated or copied around. I use those for the read part of the algorithm. I maintain a sorted map of line number -> StringBuilder, and when I come to modify a line I populate that lazily.
There are a couple of methods which require read access to a potentially updated line, for those I check the modified line map first, and if it’s not there I get the line from the original CharSequence.
The only thing I had to add back in was the caret output position tracking, which I didn’t need when using edits. That’s a little more complicated for me because I track multiple carets, but it wasn’t too bad.
Assuming there are no horrible problems I find (which I’m not expecting, the change is straightforward), I’m very happy with this solution and I’d recommend it over the edits one as the solution for https://github.com/shaunlebron/parinfer/issues/158