Merge "Use CharSequence for spell checker to keep spans preserved" into lmp-dev
This commit is contained in:
commit
91e7daaddf
5 changed files with 43 additions and 32 deletions
|
@ -16,10 +16,12 @@
|
|||
|
||||
package com.android.inputmethod.latin;
|
||||
|
||||
import java.util.Arrays;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.inputmethod.latin.utils.StringUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Class to represent information of previous words. This class is used to add n-gram entries
|
||||
* into binary dictionaries, to get predictions, and to get suggestions.
|
||||
|
@ -37,8 +39,8 @@ public class PrevWordsInfo {
|
|||
public static final WordInfo EMPTY_WORD_INFO = new WordInfo(null);
|
||||
public static final WordInfo BEGINNING_OF_SENTENCE = new WordInfo();
|
||||
|
||||
// This is an empty string when mIsBeginningOfSentence is true.
|
||||
public final String mWord;
|
||||
// This is an empty char sequence when mIsBeginningOfSentence is true.
|
||||
public final CharSequence mWord;
|
||||
// TODO: Have sentence separator.
|
||||
// Whether the current context is beginning of sentence or not. This is true when composing
|
||||
// at the beginning of an input field or composing a word after a sentence separator.
|
||||
|
@ -50,7 +52,7 @@ public class PrevWordsInfo {
|
|||
mIsBeginningOfSentence = true;
|
||||
}
|
||||
|
||||
public WordInfo(final String word) {
|
||||
public WordInfo(final CharSequence word) {
|
||||
mWord = word;
|
||||
mIsBeginningOfSentence = false;
|
||||
}
|
||||
|
@ -73,7 +75,7 @@ public class PrevWordsInfo {
|
|||
return mWord == wordInfo.mWord
|
||||
&& mIsBeginningOfSentence == wordInfo.mIsBeginningOfSentence;
|
||||
}
|
||||
return mWord.equals(wordInfo.mWord)
|
||||
return TextUtils.equals(mWord, wordInfo.mWord)
|
||||
&& mIsBeginningOfSentence == wordInfo.mIsBeginningOfSentence;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package com.android.inputmethod.latin.personalization;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.inputmethod.annotations.UsedForTesting;
|
||||
import com.android.inputmethod.latin.Constants;
|
||||
|
@ -60,7 +61,7 @@ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBas
|
|||
public static void addToDictionary(final ExpandableBinaryDictionary userHistoryDictionary,
|
||||
final PrevWordsInfo prevWordsInfo, final String word, final boolean isValid,
|
||||
final int timestamp, final DistracterFilter distracterFilter) {
|
||||
final String prevWord = prevWordsInfo.mPrevWordsInfo[0].mWord;
|
||||
final CharSequence prevWord = prevWordsInfo.mPrevWordsInfo[0].mWord;
|
||||
if (word.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH ||
|
||||
(prevWord != null && prevWord.length() >= Constants.DICTIONARY_MAX_WORD_LENGTH)) {
|
||||
return;
|
||||
|
@ -71,7 +72,7 @@ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBas
|
|||
null /* shortcutTarget */, 0 /* shortcutFreq */, false /* isNotAWord */,
|
||||
false /* isBlacklisted */, timestamp, distracterFilter);
|
||||
// Do not insert a word as a bigram of itself
|
||||
if (word.equals(prevWord)) {
|
||||
if (TextUtils.equals(word, prevWord)) {
|
||||
return;
|
||||
}
|
||||
if (null != prevWord) {
|
||||
|
|
|
@ -24,7 +24,9 @@ import android.view.textservice.SentenceSuggestionsInfo;
|
|||
import android.view.textservice.SuggestionsInfo;
|
||||
import android.view.textservice.TextInfo;
|
||||
|
||||
import com.android.inputmethod.compat.TextInfoCompatUtils;
|
||||
import com.android.inputmethod.latin.PrevWordsInfo;
|
||||
import com.android.inputmethod.latin.utils.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Locale;
|
||||
|
@ -42,15 +44,15 @@ public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheck
|
|||
|
||||
private SentenceSuggestionsInfo fixWronglyInvalidatedWordWithSingleQuote(TextInfo ti,
|
||||
SentenceSuggestionsInfo ssi) {
|
||||
final String typedText = ti.getText();
|
||||
if (!typedText.contains(AndroidSpellCheckerService.SINGLE_QUOTE)) {
|
||||
final CharSequence typedText = TextInfoCompatUtils.getCharSequenceOrString(ti);
|
||||
if (!typedText.toString().contains(AndroidSpellCheckerService.SINGLE_QUOTE)) {
|
||||
return null;
|
||||
}
|
||||
final int N = ssi.getSuggestionsCount();
|
||||
final ArrayList<Integer> additionalOffsets = new ArrayList<>();
|
||||
final ArrayList<Integer> additionalLengths = new ArrayList<>();
|
||||
final ArrayList<SuggestionsInfo> additionalSuggestionsInfos = new ArrayList<>();
|
||||
String currentWord = null;
|
||||
CharSequence currentWord = null;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
final SuggestionsInfo si = ssi.getSuggestionsInfoAt(i);
|
||||
final int flags = si.getSuggestionsAttributes();
|
||||
|
@ -59,32 +61,33 @@ public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheck
|
|||
}
|
||||
final int offset = ssi.getOffsetAt(i);
|
||||
final int length = ssi.getLengthAt(i);
|
||||
final String subText = typedText.substring(offset, offset + length);
|
||||
final CharSequence subText = typedText.subSequence(offset, offset + length);
|
||||
final PrevWordsInfo prevWordsInfo =
|
||||
new PrevWordsInfo(new PrevWordsInfo.WordInfo(currentWord));
|
||||
currentWord = subText;
|
||||
if (!subText.contains(AndroidSpellCheckerService.SINGLE_QUOTE)) {
|
||||
if (!subText.toString().contains(AndroidSpellCheckerService.SINGLE_QUOTE)) {
|
||||
continue;
|
||||
}
|
||||
final String[] splitTexts =
|
||||
subText.split(AndroidSpellCheckerService.SINGLE_QUOTE, -1);
|
||||
final CharSequence[] splitTexts = StringUtils.split(subText,
|
||||
AndroidSpellCheckerService.SINGLE_QUOTE,
|
||||
true /* preserveTrailingEmptySegments */ );
|
||||
if (splitTexts == null || splitTexts.length <= 1) {
|
||||
continue;
|
||||
}
|
||||
final int splitNum = splitTexts.length;
|
||||
for (int j = 0; j < splitNum; ++j) {
|
||||
final String splitText = splitTexts[j];
|
||||
final CharSequence splitText = splitTexts[j];
|
||||
if (TextUtils.isEmpty(splitText)) {
|
||||
continue;
|
||||
}
|
||||
if (mSuggestionsCache.getSuggestionsFromCache(splitText, prevWordsInfo) == null) {
|
||||
if (mSuggestionsCache.getSuggestionsFromCache(splitText.toString(), prevWordsInfo)
|
||||
== null) {
|
||||
continue;
|
||||
}
|
||||
final int newLength = splitText.length();
|
||||
// Neither RESULT_ATTR_IN_THE_DICTIONARY nor RESULT_ATTR_LOOKS_LIKE_TYPO
|
||||
final int newFlags = 0;
|
||||
final SuggestionsInfo newSi =
|
||||
new SuggestionsInfo(newFlags, EMPTY_STRING_ARRAY);
|
||||
final SuggestionsInfo newSi = new SuggestionsInfo(newFlags, EMPTY_STRING_ARRAY);
|
||||
newSi.setCookieAndSequence(si.getCookie(), si.getSequence());
|
||||
if (DBG) {
|
||||
Log.d(TAG, "Override and remove old span over: " + splitText + ", "
|
||||
|
@ -194,20 +197,22 @@ public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheck
|
|||
final int length = textInfos.length;
|
||||
final SuggestionsInfo[] retval = new SuggestionsInfo[length];
|
||||
for (int i = 0; i < length; ++i) {
|
||||
final String prevWord;
|
||||
final CharSequence prevWord;
|
||||
if (sequentialWords && i > 0) {
|
||||
final String prevWordCandidate = textInfos[i - 1].getText();
|
||||
// Note that an empty string would be used to indicate the initial word
|
||||
// in the future.
|
||||
prevWord = TextUtils.isEmpty(prevWordCandidate) ? null : prevWordCandidate;
|
||||
final TextInfo prevTextInfo = textInfos[i - 1];
|
||||
final CharSequence prevWordCandidate =
|
||||
TextInfoCompatUtils.getCharSequenceOrString(prevTextInfo);
|
||||
// Note that an empty string would be used to indicate the initial word
|
||||
// in the future.
|
||||
prevWord = TextUtils.isEmpty(prevWordCandidate) ? null : prevWordCandidate;
|
||||
} else {
|
||||
prevWord = null;
|
||||
}
|
||||
final PrevWordsInfo prevWordsInfo =
|
||||
new PrevWordsInfo(new PrevWordsInfo.WordInfo(prevWord));
|
||||
retval[i] = onGetSuggestionsInternal(textInfos[i], prevWordsInfo, suggestionsLimit);
|
||||
retval[i].setCookieAndSequence(textInfos[i].getCookie(),
|
||||
textInfos[i].getSequence());
|
||||
final TextInfo textInfo = textInfos[i];
|
||||
retval[i] = onGetSuggestionsInternal(textInfo, prevWordsInfo, suggestionsLimit);
|
||||
retval[i].setCookieAndSequence(textInfo.getCookie(), textInfo.getSequence());
|
||||
}
|
||||
return retval;
|
||||
} finally {
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.view.textservice.SentenceSuggestionsInfo;
|
|||
import android.view.textservice.SuggestionsInfo;
|
||||
import android.view.textservice.TextInfo;
|
||||
|
||||
import com.android.inputmethod.compat.TextInfoCompatUtils;
|
||||
import com.android.inputmethod.latin.Constants;
|
||||
import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
|
||||
import com.android.inputmethod.latin.utils.RunInLocale;
|
||||
|
@ -127,7 +128,8 @@ public class SentenceLevelAdapter {
|
|||
|
||||
public SentenceTextInfoParams getSplitWords(TextInfo originalTextInfo) {
|
||||
final WordIterator wordIterator = mWordIterator;
|
||||
final CharSequence originalText = originalTextInfo.getText();
|
||||
final CharSequence originalText =
|
||||
TextInfoCompatUtils.getCharSequenceOrString(originalTextInfo);
|
||||
final int cookie = originalTextInfo.getCookie();
|
||||
final int start = -1;
|
||||
final int end = originalText.length();
|
||||
|
@ -136,8 +138,9 @@ public class SentenceLevelAdapter {
|
|||
int wordEnd = wordIterator.getEndOfWord(originalText, wordStart);
|
||||
while (wordStart <= end && wordEnd != -1 && wordStart != -1) {
|
||||
if (wordEnd >= start && wordEnd > wordStart) {
|
||||
final String query = originalText.subSequence(wordStart, wordEnd).toString();
|
||||
final TextInfo ti = new TextInfo(query, cookie, query.hashCode());
|
||||
CharSequence subSequence = originalText.subSequence(wordStart, wordEnd).toString();
|
||||
final TextInfo ti = TextInfoCompatUtils.newInstance(subSequence, 0,
|
||||
subSequence.length(), cookie, subSequence.hashCode());
|
||||
wordItems.add(new SentenceWordItem(ti, wordStart, wordEnd));
|
||||
}
|
||||
wordStart = wordIterator.getBeginningOfNextWord(originalText, wordEnd);
|
||||
|
|
|
@ -43,7 +43,7 @@ public final class LanguageModelParam {
|
|||
private static final int BIGRAM_PROBABILITY_FOR_VALID_WORD = 10;
|
||||
private static final int BIGRAM_PROBABILITY_FOR_OOV_WORD = Dictionary.NOT_A_PROBABILITY;
|
||||
|
||||
public final String mTargetWord;
|
||||
public final CharSequence mTargetWord;
|
||||
public final int[] mWord0;
|
||||
public final int[] mWord1;
|
||||
// TODO: this needs to be a list of shortcuts
|
||||
|
@ -57,13 +57,13 @@ public final class LanguageModelParam {
|
|||
public final int mTimestamp;
|
||||
|
||||
// Constructor for unigram. TODO: support shortcuts
|
||||
public LanguageModelParam(final String word, final int unigramProbability,
|
||||
public LanguageModelParam(final CharSequence word, final int unigramProbability,
|
||||
final int timestamp) {
|
||||
this(null /* word0 */, word, unigramProbability, Dictionary.NOT_A_PROBABILITY, timestamp);
|
||||
}
|
||||
|
||||
// Constructor for unigram and bigram.
|
||||
public LanguageModelParam(final String word0, final String word1,
|
||||
public LanguageModelParam(final CharSequence word0, final CharSequence word1,
|
||||
final int unigramProbability, final int bigramProbability,
|
||||
final int timestamp) {
|
||||
mTargetWord = word1;
|
||||
|
|
Loading…
Reference in a new issue