Skip to content

Refactor: ChangeType in TextChange #486

@JordanMartinez

Description

@JordanMartinez

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:

  1. Refactor the code to always create a TextChange that can get exactly what kind of change type it is
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions