To address #322, I reimplemented the solution in #402 by using more readable code via ChangeType, which was through lazy evaluation initially. This caused regressions, as discovered in #472, and was later evaluated immediately in #470 to help find these regressions. Besides simplifying the logic, I used ChangeType because I thought developers would be able to use it in their code to quickly determine what kind of change the change was. By doing this, I realize now that I was solving the first problem and indirectly trying to solve another problem (adding convenience methods to TextChange that allows one to quickly determine what kind of change it was).
And that is the issue: my solution to the second problem was not fully thought out because it was not the issue I was trying to solve. I didn't realize it then (but do realize it now because of the regressions, both known and yet unknown, that have appeared since 0.7-M3) that a RichTextChange can be a number of different changes (insertion, deletion, replacement, text style change, or a paragraph style change)--change tyes which ChangeType does not cover.
So I see two options for addressing this bug:
- Refactor the code to always create a
TextChange that can get exactly what kind of change type it is
- Change the way the code knows that a
TextChange is an insertion or deletion type of change and thus whether to merge it with another TextChange.
I'm against the former because it will be more invasive to the current API and using a TextChange does not always require knowing what kind of change it is. For example, sometimes one just needs to know how much to adjust the caret based on how much content was removed and inserted.
I think the latter is best because it will immediately address all possible (known and currently unknown) regressions related to #458.
To still maintain code readability, I don't think we should just implement methods like TextChange#isInsertion and TextChange#isDeletion. Rather, I think ChangeType (which I think needs to be better named since it doesn't address all the changes a TextChange could be and since it pollutes the namespace that developers might want to use later in their own code) should be as follows:
// Enum needs a better name!
public class ChangeType {
INSERTION,
DELETION,
NEITHER // indicates it is neither an insertion/deletion
And then the TextChange#mergeWith code would still read:
// this is either a insertion/deletion
if (this.getType() != ChangeType.NEITHER
// the two types match: both are insertion or both are deletion
&& this.getType() == that.getType()) {
// merge code
}
Unfortunately, I can't think of a better name to address the namespace pollution issue I raised above. Does anyone else have a better name?
However, #472 did show that sometimes RTFX is inefficient because it tries to make an empty replacement. I wonder if there are others areas that could be further optimized so that replace always replaces something and ignores calls that ultimately do nothing. For example, ignoring "style change" calls that don't actually restyle the content because that content already has that style.
To address #322, I reimplemented the solution in #402 by using more readable code via
ChangeType, which was through lazy evaluation initially. This caused regressions, as discovered in #472, and was later evaluated immediately in #470 to help find these regressions. Besides simplifying the logic, I usedChangeTypebecause I thought developers would be able to use it in their code to quickly determine what kind of change the change was. By doing this, I realize now that I was solving the first problem and indirectly trying to solve another problem (adding convenience methods toTextChangethat allows one to quickly determine what kind of change it was).And that is the issue: my solution to the second problem was not fully thought out because it was not the issue I was trying to solve. I didn't realize it then (but do realize it now because of the regressions, both known and yet unknown, that have appeared since
0.7-M3) that aRichTextChangecan be a number of different changes (insertion, deletion, replacement, text style change, or a paragraph style change)--change tyes whichChangeTypedoes not cover.So I see two options for addressing this bug:
TextChangethat can get exactly what kind of change type it isTextChangeis an insertion or deletion type of change and thus whether to merge it with anotherTextChange.I'm against the former because it will be more invasive to the current API and using a
TextChangedoes not always require knowing what kind of change it is. For example, sometimes one just needs to know how much to adjust the caret based on how much content was removed and inserted.I think the latter is best because it will immediately address all possible (known and currently unknown) regressions related to #458.
To still maintain code readability, I don't think we should just implement methods like
TextChange#isInsertionandTextChange#isDeletion. Rather, I thinkChangeType(which I think needs to be better named since it doesn't address all the changes aTextChangecould be and since it pollutes the namespace that developers might want to use later in their own code) should be as follows:And then the
TextChange#mergeWithcode would still read:Unfortunately, I can't think of a better name to address the namespace pollution issue I raised above. Does anyone else have a better name?
However, #472 did show that sometimes RTFX is inefficient because it tries to make an empty replacement. I wonder if there are others areas that could be further optimized so that
replacealways replaces something and ignores calls that ultimately do nothing. For example, ignoring "style change" calls that don't actually restyle the content because that content already has that style.