Once we enable whitespace fat-fingering, it will be possible for the 'source text' to actually _change_ after an autocorrect yet still be correctable. `.sourceText` does not reflect this adequately. What _does_ remain unchanged is the `.sourceRangeKey` property and its value - those provide a better source of stability and identification.
Build-bot: skip build:web
Test-bot: skip
This PR converts SearchQuotientSpur into an abstract base class with specialized forms for different cases. Two implementations are provided:
- SearchQuotientRoot - for the root node of the search
- LegacyQuotientSpur - for modeling existing behavior before swapping to our target design and model
Build-bot: skip build:web
Test-bot: skip
As an upcoming goal is to introduce a new SearchQuotientNode type that will assist with context-caching across multiple tokenizaitons, it is wise to generalize SearchQuotientSpur and functions utilizing it to accept any SearchQuotientNode-implementing type as its parent.
Build-bot: skip build:web
Test-bot: skip
That is, corrections that eliminate user keystrokes from consideration should have a flat cost regardless of the keystroke's original transform distribution. Neither deleteLeft nor insert effects should have any impact.
Fixes: #15325
Build-bot: skip build:web
Test-bot: skip
Upon investigation into the code being removed, this mostly triggered whenever an empty transform appeared in the input - during a context reset, at initialization, or when a deadkey is typed. (Deadkeys aren't sent to the pred-text engine.) This is generally not a common case within the engine, and there exists other filtering that helps prevent duplicating search results.
Suppose a token that begins tagged with an empty transform. When the search performs an 'insertion' to better lookup words down a lexical path, the 'insertion' is identical whether before or after an empty transform. Similarly, insertions after a deletion appear no different than substitutions (or the same insertion before the deletion, then the deletion itself).
The code likely didn't gain us much, as it likely carried some performance overhead - it built a large object that required memory and lookup time that involved constructing and processing strings for hashing.
Build-bot: skip build:web
Test-bot: skip
When we start supporting more than one "space" for correction-searches, we may need to know which "space" (tokenization) a suggestion arose from. This way, we have a path forward for applying tokenization-dependent behaviors that may be required.
Build-bot: skip build:web
Test-bot: skip
This new interface is being added in preparation for efficient multi-tokenization correction-search. SearchQuotientSpur has been modified to implement it, and a new type (SearchQuotientNodeImpl) will be added in the near future as an additional implementing type.
Build-bot: skip build:web
Test-bot: skip
This changes SearchQuotientSpur to construct new instances whenever the path is extended, treating SearchQuotientSpur as an immutable portion of the search graph that may be extended by new input, creating new instances of SearchQuotientSpur.
This, in turn, removes the need to clone SearchQuotientSpur instances when new input is received for an incoming token; the original instance's represention will remain unchanged and may also be reused by a new instance extending the graph for the newly-received input.
Relates-to: #14445
Build-bot: skip build:web
Test-bot: skip