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