radian-software / apheleia

🌷 Run code formatter on buffer contents without moving point, using RCS patches and dynamic programming.
MIT License
523 stars 74 forks source link

[#226] Use lexical variable for saved buffer hash #234

Closed raxod502 closed 9 months ago

raxod502 commented 9 months ago

Should help with https://github.com/radian-software/apheleia/issues/226 although there is a second problem related to performance also reported in that thread, which would not be helped with this.

Mostly indentation changes.

raxod502 commented 9 months ago

This uses the lexical variable approach suggested by @DinoChiesa, which I think is the best solution. There is a second thing mentioned in https://github.com/radian-software/apheleia/issues/226#issuecomment-1769166750, which is that we should perhaps only allow the results of the last (most recent) formatting operation to be applied, rather than whichever one happens to finish first. I think this implementation should actually achieve that as a side effect.

In the following cases the "earlier formatter" and "second formatter" are two instances of the same formatter. Chained formatters are configured to run in series, and that is not what is happening in #226.

Case 1: no changes to buffer between when the two format operations start. The formatter makes no changes to the buffer. In this case it doesn't matter which order the formatters finish in because neither will make any changes.

Case 2: no changes to buffer between when the two format operations start. The formatter wants to make some changes to the buffer. If the earlier formatter finishes first then its changes will invalidate the saved buffer hash from the second formatter so the second formatter's changes will not be applied. The same happens if the later formatter finishes first. Either way only one formatter runs, and since there were no changes to the buffer between when the two format operations start, the output should be the same in both cases.

Case 3: the buffer was modified between when the two format operations start. If the earlier formatter finishes first, it will abort because the buffer hash changed. The second formatter will be able to apply its changes (or it won't have any to apply) because the buffer hash has not changed since it started. If the later formatter finishes first, the same thing will happen. The earlier formatter will still abort as before... unless the buffer modification is actually reverted by the later formatter which finished first. In that case the earlier formatter will indeed get to run as well. However that should be fine because it will have the same effect as running the same formatter twice, no data will be lost.