Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f2343de authored by Qi Wang's avatar Qi Wang
Browse files

Fix a bug in SpellCheckSpan update logic.

The the text is changed, we need to remove all affected SpellCheckSpan.
However, the previous check logic can not work correctly, and may
leave some out-of-date SpellCheckSpan, which causes problem when the
SpellChecker tries to apply suggestions on those spans later.

Also fixed the bug that the offset is not calculated correctly when we
validate spell checker suggestions.

Fix: 188107864
Change-Id: I8dc806d96b6a75255277d6de013305557835cb6d
Test: atest CtsInputMethodTestCases:SpellCheckerTest
Test: atest android.widget.cts.TextViewTest
parent 1d2868c4
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -375,6 +375,13 @@ public class SpellChecker implements SpellCheckerSessionListener {
        final int sequenceNumber = suggestionsInfo.getSequence();
        for (int k = 0; k < mLength; ++k) {
            if (sequenceNumber == mIds[k]) {
                final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[k];
                final int spellCheckSpanStart = editable.getSpanStart(spellCheckSpan);
                if (spellCheckSpanStart < 0) {
                    // Skips the suggestion if the matched span has been removed.
                    return null;
                }

                final int attributes = suggestionsInfo.getSuggestionsAttributes();
                final boolean isInDictionary =
                        ((attributes & SuggestionsInfo.RESULT_ATTR_IN_THE_DICTIONARY) > 0);
@@ -383,7 +390,11 @@ public class SpellChecker implements SpellCheckerSessionListener {
                final boolean looksLikeGrammarError =
                        ((attributes & SuggestionsInfo.RESULT_ATTR_LOOKS_LIKE_GRAMMAR_ERROR) > 0);

                final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[k];
                // Validates the suggestions range in case the SpellCheckSpan is out-of-date but not
                // removed as expected.
                if (spellCheckSpanStart + offset + length > editable.length()) {
                    return spellCheckSpan;
                }
                //TODO: we need to change that rule for results from a sentence-level spell
                // checker that will probably be in dictionary.
                if (!isInDictionary && (looksLikeTypo || looksLikeGrammarError)) {
@@ -393,7 +404,6 @@ public class SpellChecker implements SpellCheckerSessionListener {
                    // Valid word -- isInDictionary || !looksLikeTypo
                    // Allow the spell checker to remove existing misspelled span by
                    // overwriting the span over the same place
                    final int spellCheckSpanStart = editable.getSpanStart(spellCheckSpan);
                    final int spellCheckSpanEnd = editable.getSpanEnd(spellCheckSpan);
                    final int start;
                    final int end;
@@ -461,7 +471,6 @@ public class SpellChecker implements SpellCheckerSessionListener {
    @Override
    public void onGetSentenceSuggestions(SentenceSuggestionsInfo[] results) {
        final Editable editable = (Editable) mTextView.getText();
        final int sentenceLength = editable.length();
        for (int i = 0; i < results.length; ++i) {
            final SentenceSuggestionsInfo ssi = results[i];
            if (ssi == null) {
@@ -475,9 +484,6 @@ public class SpellChecker implements SpellCheckerSessionListener {
                }
                final int offset = ssi.getOffsetAt(j);
                final int length = ssi.getLengthAt(j);
                if (offset < 0 || offset + length > sentenceLength) {
                    continue;
                }
                final SpellCheckSpan scs = onGetSuggestionsInternal(
                        suggestionsInfo, offset, length);
                if (spellCheckSpan == null && scs != null) {
+9 −6
Original line number Diff line number Diff line
@@ -10746,12 +10746,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        Editable text = (Editable) mText;
        T[] spans = text.getSpans(start, end, type);
        final int length = spans.length;
        for (int i = 0; i < length; i++) {
            final int spanStart = text.getSpanStart(spans[i]);
            final int spanEnd = text.getSpanEnd(spans[i]);
            if (spanEnd == start || spanStart == end) break;
            text.removeSpan(spans[i]);
        ArrayList<T> spansToRemove = new ArrayList<>();
        for (T span : spans) {
            final int spanStart = text.getSpanStart(span);
            final int spanEnd = text.getSpanEnd(span);
            if (spanEnd == start || spanStart == end) continue;
            spansToRemove.add(span);
        }
        for (T span : spansToRemove) {
            text.removeSpan(span);
        }
    }