Merge "Don't assume that correctable words are invalid"

main
Dan Zivkovic 2015-02-26 03:44:20 +00:00 committed by Android (Google) Code Review
commit e4619f029e
5 changed files with 72 additions and 25 deletions

View File

@ -674,7 +674,8 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
long proximityInfoHandle = keyboard.getProximityInfo().getNativeProximityInfo(); long proximityInfoHandle = keyboard.getProximityInfo().getNativeProximityInfo();
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups; final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
final SuggestionResults suggestionResults = new SuggestionResults( final SuggestionResults suggestionResults = new SuggestionResults(
SuggestedWords.MAX_SUGGESTIONS, ngramContext.isBeginningOfSentenceContext()); SuggestedWords.MAX_SUGGESTIONS, ngramContext.isBeginningOfSentenceContext(),
false /* firstSuggestionExceedsConfidenceThreshold */);
final float[] weightOfLangModelVsSpatialModel = final float[] weightOfLangModelVsSpatialModel =
new float[] { Dictionary.NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL }; new float[] { Dictionary.NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL };
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {

View File

@ -210,7 +210,8 @@ public final class Suggest {
} }
} }
SuggestedWordInfo.removeDups(typedWordString, suggestionsContainer); final int firstOcurrenceOfTypedWordInSuggestions =
SuggestedWordInfo.removeDups(typedWordString, suggestionsContainer);
final SuggestedWordInfo whitelistedWordInfo = final SuggestedWordInfo whitelistedWordInfo =
getWhitelistedWordInfoOrNull(suggestionsContainer); getWhitelistedWordInfoOrNull(suggestionsContainer);
@ -273,7 +274,8 @@ public final class Suggest {
hasAutoCorrection = false; hasAutoCorrection = false;
} else { } else {
final SuggestedWordInfo firstSuggestion = suggestionResults.first(); final SuggestedWordInfo firstSuggestion = suggestionResults.first();
if (suggestionResults.mAutocorrectRecommendation) { if (suggestionResults.mFirstSuggestionExceedsConfidenceThreshold
&& firstOcurrenceOfTypedWordInSuggestions != 0) {
hasAutoCorrection = true; hasAutoCorrection = true;
} else if (!AutoCorrectionUtils.suggestionExceedsThreshold( } else if (!AutoCorrectionUtils.suggestionExceedsThreshold(
firstSuggestion, consideredWord, mAutoCorrectionThreshold)) { firstSuggestion, consideredWord, mAutoCorrectionThreshold)) {
@ -314,12 +316,12 @@ public final class Suggest {
} else { } else {
inputStyle = inputStyleIfNotPrediction; inputStyle = inputStyleIfNotPrediction;
} }
final boolean isTypedWordValid = firstOcurrenceOfTypedWordInSuggestions > -1
|| (!resultsArePredictions && !allowsToBeAutoCorrected);
callback.onGetSuggestedWords(new SuggestedWords(suggestionsList, callback.onGetSuggestedWords(new SuggestedWords(suggestionsList,
suggestionResults.mRawSuggestions, typedWordInfo, suggestionResults.mRawSuggestions, typedWordInfo,
// TODO: this first argument is lying. If this is a whitelisted word which is an isTypedWordValid,
// actual word, it says typedWordValid = false, which looks wrong. We should either
// rename the attribute or change the value.
!resultsArePredictions && !allowsToBeAutoCorrected /* typedWordValid */,
hasAutoCorrection /* willAutoCorrect */, hasAutoCorrection /* willAutoCorrect */,
false /* isObsoleteSuggestions */, inputStyle, sequenceNumber)); false /* isObsoleteSuggestions */, inputStyle, sequenceNumber));
} }

View File

@ -17,6 +17,7 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CompletionInfo;
import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.annotations.UsedForTesting;
@ -375,31 +376,45 @@ public class SuggestedWords {
return mWord + " (" + mDebugString + ")"; return mWord + " (" + mDebugString + ")";
} }
// This will always remove the higher index if a duplicate is found. /**
public static void removeDups(@Nullable final String typedWord, * This will always remove the higher index if a duplicate is found.
@Nonnull ArrayList<SuggestedWordInfo> candidates) { *
* @return position of typed word in the candidate list
*/
public static int removeDups(
@Nullable final String typedWord,
@Nonnull final ArrayList<SuggestedWordInfo> candidates) {
if (candidates.isEmpty()) { if (candidates.isEmpty()) {
return; return -1;
} }
int firstOccurrenceOfWord = -1;
if (!TextUtils.isEmpty(typedWord)) { if (!TextUtils.isEmpty(typedWord)) {
removeSuggestedWordInfoFromList(typedWord, candidates, -1 /* startIndexExclusive */); firstOccurrenceOfWord = removeSuggestedWordInfoFromList(
typedWord, candidates, -1 /* startIndexExclusive */);
} }
for (int i = 0; i < candidates.size(); ++i) { for (int i = 0; i < candidates.size(); ++i) {
removeSuggestedWordInfoFromList(candidates.get(i).mWord, candidates, removeSuggestedWordInfoFromList(
i /* startIndexExclusive */); candidates.get(i).mWord, candidates, i /* startIndexExclusive */);
} }
return firstOccurrenceOfWord;
} }
private static void removeSuggestedWordInfoFromList( private static int removeSuggestedWordInfoFromList(
@Nonnull final String word, @Nonnull final ArrayList<SuggestedWordInfo> candidates, @Nonnull final String word,
@Nonnull final ArrayList<SuggestedWordInfo> candidates,
final int startIndexExclusive) { final int startIndexExclusive) {
int firstOccurrenceOfWord = -1;
for (int i = startIndexExclusive + 1; i < candidates.size(); ++i) { for (int i = startIndexExclusive + 1; i < candidates.size(); ++i) {
final SuggestedWordInfo previous = candidates.get(i); final SuggestedWordInfo previous = candidates.get(i);
if (word.equals(previous.mWord)) { if (word.equals(previous.mWord)) {
if (firstOccurrenceOfWord == -1) {
firstOccurrenceOfWord = i;
}
candidates.remove(i); candidates.remove(i);
--i; --i;
} }
} }
return firstOccurrenceOfWord;
} }
} }

View File

@ -33,21 +33,18 @@ public final class SuggestionResults extends TreeSet<SuggestedWordInfo> {
// TODO: Instead of a boolean , we may want to include the context of this suggestion results, // TODO: Instead of a boolean , we may want to include the context of this suggestion results,
// such as {@link NgramContext}. // such as {@link NgramContext}.
public final boolean mIsBeginningOfSentence; public final boolean mIsBeginningOfSentence;
public final boolean mAutocorrectRecommendation; public final boolean mFirstSuggestionExceedsConfidenceThreshold;
private final int mCapacity; private final int mCapacity;
public SuggestionResults(final int capacity, final boolean isBeginningOfSentence) {
this(sSuggestedWordInfoComparator, capacity, isBeginningOfSentence, false);
}
public SuggestionResults(final int capacity, final boolean isBeginningOfSentence, public SuggestionResults(final int capacity, final boolean isBeginningOfSentence,
final boolean autocorrectRecommendation) { final boolean firstSuggestionExceedsConfidenceThreshold) {
this(sSuggestedWordInfoComparator, capacity, isBeginningOfSentence, this(sSuggestedWordInfoComparator, capacity, isBeginningOfSentence,
autocorrectRecommendation); firstSuggestionExceedsConfidenceThreshold);
} }
private SuggestionResults(final Comparator<SuggestedWordInfo> comparator, final int capacity, private SuggestionResults(final Comparator<SuggestedWordInfo> comparator, final int capacity,
final boolean isBeginningOfSentence, final boolean autocorrectRecommendation) { final boolean isBeginningOfSentence,
final boolean firstSuggestionExceedsConfidenceThreshold) {
super(comparator); super(comparator);
mCapacity = capacity; mCapacity = capacity;
if (ProductionFlags.INCLUDE_RAW_SUGGESTIONS) { if (ProductionFlags.INCLUDE_RAW_SUGGESTIONS) {
@ -56,7 +53,7 @@ public final class SuggestionResults extends TreeSet<SuggestedWordInfo> {
mRawSuggestions = null; mRawSuggestions = null;
} }
mIsBeginningOfSentence = isBeginningOfSentence; mIsBeginningOfSentence = isBeginningOfSentence;
mAutocorrectRecommendation = autocorrectRecommendation; mFirstSuggestionExceedsConfidenceThreshold = firstSuggestionExceedsConfidenceThreshold;
} }
@Override @Override

View File

@ -59,6 +59,14 @@ public class SuggestedWordsTests extends AndroidTestCase {
SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */); SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */);
} }
private static ArrayList<SuggestedWordInfo> createCorrectionWordInfos(final String... words) {
final ArrayList<SuggestedWordInfo> infos = new ArrayList<>();
for (final String word : words) {
infos.add(createCorrectionWordInfo(word));
}
return infos;
}
// Helper for testGetTransformedWordInfo // Helper for testGetTransformedWordInfo
private static SuggestedWordInfo transformWordInfo(final String info, private static SuggestedWordInfo transformWordInfo(final String info,
final int trailingSingleQuotesCount) { final int trailingSingleQuotesCount) {
@ -72,6 +80,30 @@ public class SuggestedWordsTests extends AndroidTestCase {
return returnedWordInfo; return returnedWordInfo;
} }
public void testRemoveDupesNoDupes() {
final ArrayList<SuggestedWordInfo> infos = createCorrectionWordInfos("a", "c");
assertEquals(-1, SuggestedWordInfo.removeDups("b", infos));
assertEquals(2, infos.size());
}
public void testRemoveDupesTypedWordNotDupe() {
final ArrayList<SuggestedWordInfo> infos = createCorrectionWordInfos("a", "a", "c");
assertEquals(-1, SuggestedWordInfo.removeDups("b", infos));
assertEquals(2, infos.size());
}
public void testRemoveDupesTypedWordOnlyDupe() {
final ArrayList<SuggestedWordInfo> infos = createCorrectionWordInfos("a", "b", "c");
assertEquals(1, SuggestedWordInfo.removeDups("b", infos));
assertEquals(2, infos.size());
}
public void testRemoveDupesTypedWordNotOnlyDupe() {
final ArrayList<SuggestedWordInfo> infos = createCorrectionWordInfos("a", "b", "b", "c");
assertEquals(1, SuggestedWordInfo.removeDups("b", infos));
assertEquals(2, infos.size());
}
public void testGetTransformedSuggestedWordInfo() { public void testGetTransformedSuggestedWordInfo() {
SuggestedWordInfo result = transformWordInfo("word", 0); SuggestedWordInfo result = transformWordInfo("word", 0);
assertEquals(result.mWord, "word"); assertEquals(result.mWord, "word");