mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Merge "Don't assume that correctable words are invalid"
This commit is contained in:
commit
e4619f029e
@ -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) {
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user