From 5f41b705fc95b21c8edd6226bb50c0fa78a39261 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Fri, 7 Oct 2011 16:34:19 +0900 Subject: [PATCH] Fix a bug with the whitelist This bug would kill the case where the whitelist contains a word to be autocorrected to an uppercased version of itself, and the user would enter the uppercase version. In this case, this bug would cause the typed word to be killed off the list of candidates, and possibly autocorrected to the *next* candidate. When the whitelist checks whether this the typed word is a candidate for whitelisting, this change has it check whether the whitelisting results in the typed word before returning. Hence, it can keep the case-insensitive behavior of the whitelist. Coincidentally, this change renames the method used to do this, because it does not comply with the general contract of Dictionary. This happens to be in the way of another upcoming change. Bug: 5420371 Change-Id: Ifb305271acc5f171adf9b18c762ae7975b14be0a --- .../inputmethod/latin/AutoCorrection.java | 16 +++++++++------- .../com/android/inputmethod/latin/LatinIME.java | 13 +++++++++---- .../inputmethod/latin/WhitelistDictionary.java | 16 ++++++++++++++++ .../android/inputmethod/latin/SuggestHelper.java | 2 +- 4 files changed, 35 insertions(+), 12 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/AutoCorrection.java b/java/src/com/android/inputmethod/latin/AutoCorrection.java index fc9771065..485ec511f 100644 --- a/java/src/com/android/inputmethod/latin/AutoCorrection.java +++ b/java/src/com/android/inputmethod/latin/AutoCorrection.java @@ -82,14 +82,16 @@ public class AutoCorrection { return false; } - public static boolean isValidWordForAutoCorrection( + public static boolean allowsToBeAutoCorrected( Map dictionaries, CharSequence word, boolean ignoreCase) { - final Dictionary whiteList = dictionaries.get(Suggest.DICT_KEY_WHITELIST); + final WhitelistDictionary whitelistDictionary = + (WhitelistDictionary)dictionaries.get(Suggest.DICT_KEY_WHITELIST); // If "word" is in the whitelist dictionary, it should not be auto corrected. - if (whiteList != null && whiteList.isValidWord(word)) { - return false; + if (whitelistDictionary != null + && whitelistDictionary.shouldForciblyAutoCorrectFrom(word)) { + return true; } - return isValidWord(dictionaries, word, ignoreCase); + return !isValidWord(dictionaries, word, ignoreCase); } private static boolean hasAutoCorrectionForWhitelistedWord(CharSequence whiteListedWord) { @@ -100,8 +102,8 @@ public class AutoCorrection { WordComposer wordComposer, ArrayList suggestions, CharSequence typedWord, int correctionMode) { if (TextUtils.isEmpty(typedWord)) return false; - boolean isValidWord = isValidWordForAutoCorrection(dictionaries, typedWord, false); - return wordComposer.size() > 1 && suggestions.size() > 0 && isValidWord + boolean allowsAutoCorrect = allowsToBeAutoCorrected(dictionaries, typedWord, false); + return wordComposer.size() > 1 && suggestions.size() > 0 && !allowsAutoCorrect && (correctionMode == Suggest.CORRECTION_FULL || correctionMode == Suggest.CORRECTION_FULL_BIGRAM); } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 36e97af11..d15aea3ff 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1634,11 +1634,16 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar boolean autoCorrectionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection(); final CharSequence typedWord = wordComposer.getTypedWord(); // Here, we want to promote a whitelisted word if exists. - final boolean typedWordValid = AutoCorrection.isValidWordForAutoCorrection( + // TODO: Change this scheme - a boolean is not enough. A whitelisted word may be "valid" + // but still autocorrected from - in the case the whitelist only capitalizes the word. + // The whitelist should be case-insensitive, so it's not possible to be consistent with + // a boolean flag. Right now this is handled with a slight hack in + // WhitelistDictionary#shouldForciblyAutoCorrectFrom. + final boolean allowsToBeAutoCorrected = AutoCorrection.allowsToBeAutoCorrected( mSuggest.getUnigramDictionaries(), typedWord, preferCapitalization()); if (mCorrectionMode == Suggest.CORRECTION_FULL || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM) { - autoCorrectionAvailable |= typedWordValid; + autoCorrectionAvailable |= (!allowsToBeAutoCorrected); } // Don't auto-correct words with multiple capital letter autoCorrectionAvailable &= !wordComposer.isMostlyCaps(); @@ -1651,9 +1656,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // need to clear the previous state when the user starts typing a word (i.e. typed word's // length == 1). if (typedWord != null) { - if (builder.size() > 1 || typedWord.length() == 1 || typedWordValid + if (builder.size() > 1 || typedWord.length() == 1 || (!allowsToBeAutoCorrected) || mSuggestionsView.isShowingAddToDictionaryHint()) { - builder.setTypedWordValid(typedWordValid).setHasMinimalSuggestion( + builder.setTypedWordValid(!allowsToBeAutoCorrected).setHasMinimalSuggestion( autoCorrectionAvailable); } else { SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions(); diff --git a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java index 93474b654..96241a340 100644 --- a/java/src/com/android/inputmethod/latin/WhitelistDictionary.java +++ b/java/src/com/android/inputmethod/latin/WhitelistDictionary.java @@ -93,4 +93,20 @@ public class WhitelistDictionary extends Dictionary { if (TextUtils.isEmpty(word)) return false; return !TextUtils.isEmpty(getWhiteListedWord(word.toString())); } + + // See LatinIME#updateSuggestions. This breaks in the (queer) case that the whitelist + // lists that word a should autocorrect to word b, and word c would autocorrect to + // an upper-cased version of a. In this case, the way this return value is used would + // remove the first candidate when the user typed the upper-cased version of A. + // Example : abc -> def and xyz -> Abc + // A user typing Abc would experience it being autocorrected to something else (not + // necessarily def). + // There is no such combination in the whitelist at the time and there probably won't + // ever be - it doesn't make sense. But still. + public boolean shouldForciblyAutoCorrectFrom(CharSequence word) { + if (TextUtils.isEmpty(word)) return false; + final String correction = getWhiteListedWord(word.toString()); + if (TextUtils.isEmpty(correction)) return false; + return !correction.equals(word); + } } diff --git a/tests/src/com/android/inputmethod/latin/SuggestHelper.java b/tests/src/com/android/inputmethod/latin/SuggestHelper.java index a08933539..464930f4c 100644 --- a/tests/src/com/android/inputmethod/latin/SuggestHelper.java +++ b/tests/src/com/android/inputmethod/latin/SuggestHelper.java @@ -89,7 +89,7 @@ public class SuggestHelper { } public boolean isValidWord(CharSequence typed) { - return AutoCorrection.isValidWordForAutoCorrection(mSuggest.getUnigramDictionaries(), + return AutoCorrection.isValidWord(mSuggest.getUnigramDictionaries(), typed, false); }