From 0bfe359ee42af9c4487ce56acf42c74a2510980d Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Wed, 25 Jan 2012 18:11:26 +0900 Subject: [PATCH] Add a test for auto-correction. Fix two related subtle bugs: - Stop singling out fat-finger-only corrections for rejection when touch coordinates are not available. - Remove a racy check that would happen only in debug mode Change-Id: Ic904f9b27c091ca6b369052c4e65a630bff81257 --- .../latin/ComposingStateManager.java | 7 ++++ .../android/inputmethod/latin/LatinIME.java | 5 +-- .../spellcheck/SpellCheckerProximityInfo.java | 3 +- native/src/defines.h | 1 + native/src/proximity_info.cpp | 3 ++ .../inputmethod/latin/InputLogicTests.java | 40 ++++++++++++++++++- 6 files changed, 54 insertions(+), 5 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/ComposingStateManager.java b/java/src/com/android/inputmethod/latin/ComposingStateManager.java index 8811f2023..27f509a29 100644 --- a/java/src/com/android/inputmethod/latin/ComposingStateManager.java +++ b/java/src/com/android/inputmethod/latin/ComposingStateManager.java @@ -53,6 +53,13 @@ public class ComposingStateManager { } } + public synchronized boolean isComposing() { + // TODO: use the composing flag in WordComposer instead of maintaining it + // here separately. Even better, do away with this class and manage the auto + // correction indicator in the same place as the suggestions. + return mIsComposing; + } + public synchronized boolean isAutoCorrectionIndicatorOn() { return mAutoCorrectionIndicatorOn; } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 31cbc4ee3..d59497d6a 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1702,10 +1702,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar if (DEBUG) { Log.d(TAG, "Flip the indicator. " + oldAutoCorrectionIndicator + " -> " + newAutoCorrectionIndicator); - if (newAutoCorrectionIndicator + if (mComposingStateManager.isComposing() && newAutoCorrectionIndicator != mComposingStateManager.isAutoCorrectionIndicatorOn()) { - throw new RuntimeException("Couldn't flip the indicator! We are not " - + "composing a word right now."); + throw new RuntimeException("Couldn't flip the indicator!"); } } final CharSequence textWithUnderline = diff --git a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java index 2bc2cfdf6..db3544987 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/SpellCheckerProximityInfo.java @@ -22,7 +22,8 @@ import com.android.inputmethod.keyboard.ProximityInfo; import java.util.TreeMap; public class SpellCheckerProximityInfo { - final private static int NUL = KeyDetector.NOT_A_CODE; + /* public for test */ + final public static int NUL = KeyDetector.NOT_A_CODE; // This must be the same as MAX_PROXIMITY_CHARS_SIZE else it will not work inside // native code - this value is passed at creation of the binary object and reused diff --git a/native/src/defines.h b/native/src/defines.h index 119a7d779..096f1fbf6 100644 --- a/native/src/defines.h +++ b/native/src/defines.h @@ -169,6 +169,7 @@ static void prof_out(void) { #define NOT_VALID_WORD -99 #define NOT_A_CHARACTER -1 #define NOT_A_DISTANCE -1 +#define NOT_A_COORDINATE -1 #define EQUIVALENT_CHAR_WITHOUT_DISTANCE_INFO -2 #define PROXIMITY_CHAR_WITHOUT_DISTANCE_INFO -3 #define NOT_A_INDEX -1 diff --git a/native/src/proximity_info.cpp b/native/src/proximity_info.cpp index b91957c77..e0e938099 100644 --- a/native/src/proximity_info.cpp +++ b/native/src/proximity_info.cpp @@ -165,6 +165,9 @@ float ProximityInfo::calculateNormalizedSquaredDistance( if (!hasSweetSpotData(keyIndex)) { return NOT_A_DISTANCE_FLOAT; } + if (NOT_A_COORDINATE == mInputXCoordinates[inputIndex]) { + return NOT_A_DISTANCE_FLOAT; + } const float squaredDistance = calculateSquaredDistanceFromSweetSpotCenter(keyIndex, inputIndex); const float squaredRadius = square(mSweetSpotRadii[keyIndex]); return squaredDistance / squaredRadius; diff --git a/tests/src/com/android/inputmethod/latin/InputLogicTests.java b/tests/src/com/android/inputmethod/latin/InputLogicTests.java index 0d5e42b81..59ca22df4 100644 --- a/tests/src/com/android/inputmethod/latin/InputLogicTests.java +++ b/tests/src/com/android/inputmethod/latin/InputLogicTests.java @@ -34,6 +34,11 @@ import android.widget.TextView; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardActionListener; +import com.android.inputmethod.latin.spellcheck.AndroidSpellCheckerService; // for proximity info +import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo; + +import java.util.Arrays; +import java.util.HashMap; public class InputLogicTests extends ServiceTestCase { @@ -42,9 +47,29 @@ public class InputLogicTests extends ServiceTestCase { private LatinIME mLatinIME; private TextView mTextView; private InputConnection mInputConnection; + private HashMap mProximity; public InputLogicTests() { super(LatinIME.class); + mProximity = createProximity(); + } + + private static HashMap createProximity() { + final HashMap proximity = new HashMap(); + final int[] testProximity = SpellCheckerProximityInfo.getProximityForScript( + AndroidSpellCheckerService.SCRIPT_LATIN); + final int ROW_SIZE = SpellCheckerProximityInfo.ROW_SIZE; + final int NUL = SpellCheckerProximityInfo.NUL; + for (int row = 0; row * ROW_SIZE < testProximity.length; ++row) { + final int rowBase = row * ROW_SIZE; + int column; + for (column = 1; NUL != testProximity[rowBase + column]; ++column) { + // Do nothing, just search for a NUL element + } + proximity.put(testProximity[row * ROW_SIZE], + Arrays.copyOfRange(testProximity, rowBase, rowBase + column)); + } + return proximity; } // returns the previous setting value @@ -73,7 +98,9 @@ public class InputLogicTests extends ServiceTestCase { mLatinIME.onCreate(); setDebugMode(previousDebugSetting); final EditorInfo ei = new EditorInfo(); + ei.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT; final InputConnection ic = mTextView.onCreateInputConnection(ei); + ei.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_AUTO_CORRECT; final LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); final ViewGroup vg = new FrameLayout(getContext()); @@ -95,7 +122,11 @@ public class InputLogicTests extends ServiceTestCase { // to keep these tests as pinpoint as possible and avoid bringing it too many dependencies, // but keep them in mind if something breaks. Commenting them out as is should work. //mLatinIME.onPressKey(codePoint); - mLatinIME.onCodeInput(codePoint, new int[] { codePoint }, + int[] proximityKeys = mProximity.get(codePoint); + if (null == proximityKeys) { + proximityKeys = new int[] { codePoint }; + } + mLatinIME.onCodeInput(codePoint, proximityKeys, KeyboardActionListener.NOT_A_TOUCH_COORDINATE, KeyboardActionListener.NOT_A_TOUCH_COORDINATE); //mLatinIME.onReleaseKey(codePoint, false); @@ -139,4 +170,11 @@ public class InputLogicTests extends ServiceTestCase { type(Keyboard.CODE_DELETE); assertEquals("delete selection", EXPECTED_RESULT, mTextView.getText().toString()); } + + public void testAutoCorrect() { + final String STRING_TO_TYPE = "tgis "; + final String EXPECTED_RESULT = "this "; + type(STRING_TO_TYPE); + assertEquals("simple auto-correct", EXPECTED_RESULT, mTextView.getText().toString()); + } }