Merge "Use CharSequence for spell checker to keep spans preserved" into lmp-dev

This commit is contained in:
Yohei Yukawa 2014-07-20 02:45:20 +00:00 committed by Android (Google) Code Review
commit 91e7daaddf
5 changed files with 43 additions and 32 deletions

View file

@ -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;
}
}

View file

@ -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) {

View file

@ -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,9 +197,11 @@ 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();
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;
@ -205,9 +210,9 @@ public final class AndroidSpellCheckerSession extends AndroidWordLevelSpellCheck
}
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 {

View file

@ -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);

View file

@ -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;