Fix wrong misspelling reports of fully capitalized words

Two flavors of words would be wrongly reported as misspelled
by the android spell checker when they are written in all
upper case letters:
- Words containing a quote or a dash or any other non-letter
- Words that need the first letter to be capitalized

Bug: 7659216
Change-Id: Ibc5d261945ffcbb8a858d4c73b7c62cef6671abf
main
Jean Chalard 2012-12-04 16:11:18 +09:00
parent 8918cb46f6
commit 95bfb8ac47
2 changed files with 48 additions and 15 deletions

View File

@ -438,15 +438,23 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
if (!Character.isUpperCase(text.codePointAt(0))) return CAPITALIZE_NONE;
final int len = text.length();
int capsCount = 1;
int letterCount = 1;
for (int i = 1; i < len; i = text.offsetByCodePoints(i, 1)) {
if (1 != capsCount && i != capsCount) break;
if (Character.isUpperCase(text.codePointAt(i))) ++capsCount;
if (1 != capsCount && letterCount != capsCount) break;
final int codePoint = text.codePointAt(i);
if (Character.isUpperCase(codePoint)) {
++capsCount;
++letterCount;
} else if (Character.isLetter(codePoint)) {
// We need to discount non-letters since they may not be upper-case, but may
// still be part of a word (e.g. single quote or dash, as in "IT'S" or "FULL-TIME")
++letterCount;
}
}
// We know the first char is upper case. So we want to test if either everything
// else is lower case, or if everything else is upper case. If the string is
// exactly one char long, then we will arrive here with capsCount 1, and this is
// correct, too.
// We know the first char is upper case. So we want to test if either every letter other
// than the first is lower case, or if they are all upper case. If the string is exactly
// one char long, then we will arrive here with letterCount 1, and this is correct, too.
if (1 == capsCount) return CAPITALIZE_FIRST;
return (len == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE);
return (letterCount == capsCount ? CAPITALIZE_ALL : CAPITALIZE_NONE);
}
}

View File

@ -28,9 +28,11 @@ import android.view.textservice.TextInfo;
import com.android.inputmethod.compat.SuggestionsInfoCompatUtils;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.LocaleUtils;
import com.android.inputmethod.latin.WordComposer;
import com.android.inputmethod.latin.StringUtils;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.WordComposer;
import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService.SuggestionsGatherer;
import java.util.ArrayList;
@ -188,6 +190,35 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
return (letterCount * 4 < length * 3);
}
/**
* Helper method to test valid capitalizations of a word.
*
* If the "text" is lower-case, we test only the exact string.
* If the "Text" is capitalized, we test the exact string "Text" and the lower-cased
* version of it "text".
* If the "TEXT" is fully upper case, we test the exact string "TEXT", the lower-cased
* version of it "text" and the capitalized version of it "Text".
*/
private boolean isInDictForAnyCapitalization(final Dictionary dict, final String text,
final int capitalizeType) {
// If the word is in there as is, then it's in the dictionary. If not, we'll test lower
// case versions, but only if the word is not already all-lower case or mixed case.
if (dict.isValidWord(text)) return true;
if (AndroidSpellCheckerService.CAPITALIZE_NONE == capitalizeType) return false;
// If we come here, we have a capitalized word (either First- or All-).
// Downcase the word and look it up again. If the word is only capitalized, we
// tested all possibilities, so if it's still negative we can return false.
final String lowerCaseText = text.toLowerCase(mLocale);
if (dict.isValidWord(lowerCaseText)) return true;
if (AndroidSpellCheckerService.CAPITALIZE_FIRST == capitalizeType) return false;
// If the lower case version is not in the dictionary, it's still possible
// that we have an all-caps version of a word that needs to be capitalized
// according to the dictionary. E.g. "GERMANS" only exists in the dictionary as "Germans".
return dict.isValidWord(StringUtils.toTitleCase(lowerCaseText, mLocale));
}
// Note : this must be reentrant
/**
* Gets a list of suggestions for a specific string. This returns a list of possible
@ -272,13 +303,7 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session {
suggestionsGatherer.addWord(suggestionStr.toCharArray(), null, 0,
suggestionStr.length(), suggestion.mScore);
}
isInDict = dictInfo.mDictionary.isValidWord(text);
if (!isInDict && AndroidSpellCheckerService.CAPITALIZE_NONE != capitalizeType) {
// We want to test the word again if it's all caps or first caps only.
// If it's fully down, we already tested it, if it's mixed case, we don't
// want to test a lowercase version of it.
isInDict = dictInfo.mDictionary.isValidWord(text.toLowerCase(mLocale));
}
isInDict = isInDictForAnyCapitalization(dictInfo.mDictionary, text, capitalizeType);
} finally {
if (null != dictInfo) {
if (!mDictionaryPool.offer(dictInfo)) {