diff options
9 files changed, 363 insertions, 114 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/Key.java b/java/src/com/android/inputmethod/keyboard/Key.java index ebd61505d..6003d9723 100644 --- a/java/src/com/android/inputmethod/keyboard/Key.java +++ b/java/src/com/android/inputmethod/keyboard/Key.java @@ -101,7 +101,7 @@ public class Key { /** Text to output when pressed. This can be multiple characters, like ".com" */ public final CharSequence mOutputText; /** More keys */ - public final CharSequence[] mMoreKeys; + public final String[] mMoreKeys; /** More keys maximum column number */ public final int mMaxMoreKeysColumn; @@ -255,7 +255,7 @@ public class Key { // Update row to have current x coordinate. row.setXPos(keyXPos + keyWidth); - final CharSequence[] moreKeys = style.getTextArray(keyAttr, + final String[] moreKeys = style.getTextArray(keyAttr, R.styleable.Keyboard_Key_moreKeys); // In Arabic symbol layouts, we'd like to keep digits in more keys regardless of // config_digit_more_keys_enabled. diff --git a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java index 548b5ea85..974291373 100644 --- a/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java +++ b/java/src/com/android/inputmethod/keyboard/MiniKeyboard.java @@ -34,7 +34,7 @@ public class MiniKeyboard extends Keyboard { } public static class Builder extends Keyboard.Builder<Builder.MiniKeyboardParams> { - private final CharSequence[] mMoreKeys; + private final String[] mMoreKeys; public static class MiniKeyboardParams extends Keyboard.Params { /* package */int mTopRowAdjustment; @@ -230,16 +230,14 @@ public class MiniKeyboard extends Keyboard { parentKey.mX + (mParams.mDefaultKeyWidth - width) / 2, view.getMeasuredWidth()); } - private static int getMaxKeyWidth(KeyboardView view, CharSequence[] moreKeys, - int minKeyWidth) { + private static int getMaxKeyWidth(KeyboardView view, String[] moreKeys, int minKeyWidth) { final int padding = (int) view.getContext().getResources() .getDimension(R.dimen.mini_keyboard_key_horizontal_padding); Paint paint = null; int maxWidth = minKeyWidth; - for (CharSequence moreKeySpec : moreKeys) { - final CharSequence label = MoreKeySpecParser.getLabel(moreKeySpec.toString()); - // If the label is single letter, minKeyWidth is enough to hold - // the label. + for (String moreKeySpec : moreKeys) { + final String label = MoreKeySpecParser.getLabel(moreKeySpec); + // If the label is single letter, minKeyWidth is enough to hold the label. if (label != null && label.length() > 1) { if (paint == null) { paint = new Paint(); @@ -258,7 +256,7 @@ public class MiniKeyboard extends Keyboard { public MiniKeyboard build() { final MiniKeyboardParams params = mParams; for (int n = 0; n < mMoreKeys.length; n++) { - final String moreKeySpec = mMoreKeys[n].toString(); + final String moreKeySpec = mMoreKeys[n]; final int row = n / params.mNumColumns; final Key key = new Key(mResources, params, moreKeySpec, params.getX(n, row), params.getY(row), params.mDefaultKeyWidth, params.mDefaultRowHeight); diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java index 5dd8340fc..faea38941 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java +++ b/java/src/com/android/inputmethod/keyboard/internal/KeyStyles.java @@ -16,11 +16,13 @@ package com.android.inputmethod.keyboard.internal; +import android.content.res.Resources; import android.content.res.TypedArray; import android.util.Log; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.Utils; import com.android.inputmethod.latin.XmlParseUtils; import org.xmlpull.v1.XmlPullParser; @@ -30,7 +32,7 @@ import java.util.ArrayList; import java.util.HashMap; public class KeyStyles { - private static final String TAG = "KeyStyles"; + private static final String TAG = KeyStyles.class.getSimpleName(); private static final boolean DEBUG = false; private final HashMap<String, DeclaredKeyStyle> mStyles = @@ -38,19 +40,19 @@ public class KeyStyles { private static final KeyStyle EMPTY_KEY_STYLE = new EmptyKeyStyle(); public interface KeyStyle { - public CharSequence[] getTextArray(TypedArray a, int index); + public String[] getTextArray(TypedArray a, int index); public CharSequence getText(TypedArray a, int index); public int getInt(TypedArray a, int index, int defaultValue); public int getFlag(TypedArray a, int index, int defaultValue); } - /* package */ static class EmptyKeyStyle implements KeyStyle { + private static class EmptyKeyStyle implements KeyStyle { EmptyKeyStyle() { // Nothing to do. } @Override - public CharSequence[] getTextArray(TypedArray a, int index) { + public String[] getTextArray(TypedArray a, int index) { return parseTextArray(a, index); } @@ -69,64 +71,77 @@ public class KeyStyles { return a.getInt(index, defaultValue); } - protected static CharSequence[] parseTextArray(TypedArray a, int index) { + protected static String[] parseTextArray(TypedArray a, int index) { if (!a.hasValue(index)) return null; final CharSequence text = a.getText(index); - return parseCsvText(text); - } - - /* package */ static CharSequence[] parseCsvText(CharSequence text) { - final int size = text.length(); - if (size == 0) return null; - if (size == 1) return new CharSequence[] { text }; - final StringBuilder sb = new StringBuilder(); - ArrayList<CharSequence> list = null; - int start = 0; - for (int pos = 0; pos < size; pos++) { - final char c = text.charAt(pos); - if (c == ',') { - if (list == null) list = new ArrayList<CharSequence>(); - if (sb.length() == 0) { - list.add(text.subSequence(start, pos)); - } else { - list.add(sb.toString()); - sb.setLength(0); + return parseCsvText(text.toString(), a.getResources(), R.string.english_ime_name); + } + } + + /* package for test */ + static String[] parseCsvText(String rawText, Resources res, int packageNameResId) { + final String text = Utils.resolveStringResource(rawText, res, packageNameResId); + final int size = text.length(); + if (size == 0) { + return null; + } + if (size == 1) { + return new String[] { text }; + } + + final StringBuilder sb = new StringBuilder(); + ArrayList<String> list = null; + int start = 0; + for (int pos = 0; pos < size; pos++) { + final char c = text.charAt(pos); + if (c == ',') { + if (list == null) { + list = new ArrayList<String>(); + } + if (sb.length() == 0) { + list.add(text.substring(start, pos)); + } else { + list.add(sb.toString()); + sb.setLength(0); + } + start = pos + 1; + continue; + } else if (c == Utils.ESCAPE_CHAR) { + if (start == pos) { + // Skip escape character at the beginning of the value. + start++; + pos++; + } else { + if (start < pos && sb.length() == 0) { + sb.append(text.subSequence(start, pos)); } - start = pos + 1; - continue; - } else if (c == '\\') { - if (start == pos) { - // Skip escape character at the beginning of the value. - start++; - pos++; - } else { - if (start < pos && sb.length() == 0) - sb.append(text.subSequence(start, pos)); - pos++; - if (pos < size) - sb.append(text.charAt(pos)); + pos++; + if (pos < size) { + sb.append(text.charAt(pos)); } - } else if (sb.length() > 0) { - sb.append(c); } + } else if (sb.length() > 0) { + sb.append(c); } - if (list == null) { - return new CharSequence[] { sb.length() > 0 ? sb : text.subSequence(start, size) }; - } else { - list.add(sb.length() > 0 ? sb : text.subSequence(start, size)); - return list.toArray(new CharSequence[list.size()]); - } + } + if (list == null) { + return new String[] { + sb.length() > 0 ? sb.toString() : text.substring(start) + }; + } else { + list.add(sb.length() > 0 ? sb.toString() : text.substring(start)); + return list.toArray(new String[list.size()]); } } - /* package */ static class DeclaredKeyStyle extends EmptyKeyStyle { + private static class DeclaredKeyStyle extends EmptyKeyStyle { private final HashMap<Integer, Object> mAttributes = new HashMap<Integer, Object>(); @Override - public CharSequence[] getTextArray(TypedArray a, int index) { + public String[] getTextArray(TypedArray a, int index) { return a.hasValue(index) - ? super.getTextArray(a, index) : (CharSequence[])mAttributes.get(index); + ? super.getTextArray(a, index) : (String[])mAttributes.get(index); } @Override diff --git a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java index c7d226d6e..2facf8439 100644 --- a/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java +++ b/java/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParser.java @@ -22,6 +22,7 @@ import android.util.Log; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.R; +import com.android.inputmethod.latin.Utils; import java.util.ArrayList; @@ -40,11 +41,9 @@ import java.util.ArrayList; public class MoreKeySpecParser { private static final String TAG = MoreKeySpecParser.class.getSimpleName(); - private static final char ESCAPE = '\\'; - private static final String LABEL_END = "|"; - private static final String PREFIX_AT = "@"; - private static final String PREFIX_ICON = PREFIX_AT + "icon/"; - private static final String PREFIX_CODE = PREFIX_AT + "integer/"; + private static final char LABEL_END = '|'; + private static final String PREFIX_ICON = Utils.PREFIX_AT + "icon" + Utils.SUFFIX_SLASH; + private static final String PREFIX_CODE = Utils.PREFIX_AT + "integer" + Utils.SUFFIX_SLASH; private MoreKeySpecParser() { // Intentional empty constructor for utility class. @@ -71,14 +70,14 @@ public class MoreKeySpecParser { } private static String parseEscape(String text) { - if (text.indexOf(ESCAPE) < 0) { + if (text.indexOf(Utils.ESCAPE_CHAR) < 0) { return text; } final int length = text.length(); final StringBuilder sb = new StringBuilder(); for (int pos = 0; pos < length; pos++) { final char c = text.charAt(pos); - if (c == ESCAPE && pos + 1 < length) { + if (c == Utils.ESCAPE_CHAR && pos + 1 < length) { sb.append(text.charAt(++pos)); } else { sb.append(c); @@ -88,7 +87,7 @@ public class MoreKeySpecParser { } private static int indexOfLabelEnd(String moreKeySpec, int start) { - if (moreKeySpec.indexOf(ESCAPE, start) < 0) { + if (moreKeySpec.indexOf(Utils.ESCAPE_CHAR, start) < 0) { final int end = moreKeySpec.indexOf(LABEL_END, start); if (end == 0) { throw new MoreKeySpecParserError(LABEL_END + " at " + start + ": " + moreKeySpec); @@ -98,9 +97,9 @@ public class MoreKeySpecParser { final int length = moreKeySpec.length(); for (int pos = start; pos < length; pos++) { final char c = moreKeySpec.charAt(pos); - if (c == ESCAPE && pos + 1 < length) { + if (c == Utils.ESCAPE_CHAR && pos + 1 < length) { pos++; - } else if (moreKeySpec.startsWith(LABEL_END, pos)) { + } else if (c == LABEL_END) { return pos; } } @@ -130,7 +129,8 @@ public class MoreKeySpecParser { throw new MoreKeySpecParserError("Multiple " + LABEL_END + ": " + moreKeySpec); } - final String outputText = parseEscape(moreKeySpec.substring(end + LABEL_END.length())); + final String outputText = parseEscape( + moreKeySpec.substring(end + /* LABEL_END */1)); if (!TextUtils.isEmpty(outputText)) { return outputText; } @@ -150,8 +150,9 @@ public class MoreKeySpecParser { if (indexOfLabelEnd(moreKeySpec, end + 1) >= 0) { throw new MoreKeySpecParserError("Multiple " + LABEL_END + ": " + moreKeySpec); } - final int resId = getResourceId(res, - moreKeySpec.substring(end + LABEL_END.length() + PREFIX_AT.length())); + final int resId = Utils.getResourceId(res, + moreKeySpec.substring(end + /* LABEL_END */1 + /* PREFIX_AT */1), + R.string.english_ime_name); final int code = res.getInteger(resId); return code; } @@ -168,7 +169,7 @@ public class MoreKeySpecParser { public static int getIconId(String moreKeySpec) { if (hasIcon(moreKeySpec)) { - int end = moreKeySpec.indexOf(LABEL_END, PREFIX_ICON.length() + 1); + final int end = moreKeySpec.indexOf(LABEL_END, PREFIX_ICON.length() + 1); final String iconId = moreKeySpec.substring(PREFIX_ICON.length(), end); try { return Integer.valueOf(iconId); @@ -180,15 +181,6 @@ public class MoreKeySpecParser { return KeyboardIconsSet.ICON_UNDEFINED; } - private static int getResourceId(Resources res, String name) { - String packageName = res.getResourcePackageName(R.string.english_ime_name); - int resId = res.getIdentifier(name, null, packageName); - if (resId == 0) { - throw new MoreKeySpecParserError("Unknown resource: " + name); - } - return resId; - } - @SuppressWarnings("serial") public static class MoreKeySpecParserError extends RuntimeException { public MoreKeySpecParserError(String message) { @@ -207,21 +199,19 @@ public class MoreKeySpecParser { } }; - public static CharSequence[] filterOut(Resources res, CharSequence[] moreKeys, - CodeFilter filter) { + public static String[] filterOut(Resources res, String[] moreKeys, CodeFilter filter) { if (moreKeys == null || moreKeys.length < 1) { return null; } - if (moreKeys.length == 1 - && filter.shouldFilterOut(getCode(res, moreKeys[0].toString()))) { + if (moreKeys.length == 1 && filter.shouldFilterOut(getCode(res, moreKeys[0]))) { return null; } - ArrayList<CharSequence> filtered = null; + ArrayList<String> filtered = null; for (int i = 0; i < moreKeys.length; i++) { - final CharSequence moreKeySpec = moreKeys[i]; - if (filter.shouldFilterOut(getCode(res, moreKeySpec.toString()))) { + final String moreKeySpec = moreKeys[i]; + if (filter.shouldFilterOut(getCode(res, moreKeySpec))) { if (filtered == null) { - filtered = new ArrayList<CharSequence>(); + filtered = new ArrayList<String>(); for (int j = 0; j < i; j++) { filtered.add(moreKeys[j]); } @@ -236,6 +226,6 @@ public class MoreKeySpecParser { if (filtered.size() == 0) { return null; } - return filtered.toArray(new CharSequence[filtered.size()]); + return filtered.toArray(new String[filtered.size()]); } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index d36140de6..94c47bdc9 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -1881,6 +1881,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } return; } + // We need to log before we commit, because the word composer will store away the user + // typed word. + LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(), + suggestion.toString(), index, suggestions.mWords); mExpectingUpdateSelection = true; commitChosenWord(suggestion, WordComposer.COMMIT_TYPE_MANUAL_PICK); // Add the word to the auto dictionary if it's not a known word @@ -1890,10 +1894,6 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar } else { addToOnlyBigramDictionary(suggestion, 1); } - // TODO: the following is fishy, because it seems there may be cases where we are not - // composing a word at all. Maybe throw an exception if !mWordComposer.isComposingWord() ? - LatinImeLogger.logOnManualSuggestion(mWordComposer.getTypedWord().toString(), - suggestion.toString(), index, suggestions.mWords); // Follow it with a space if (mInputAttributes.mInsertSpaceOnPickSuggestionManually) { sendMagicSpace(); @@ -2129,12 +2129,12 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final String wordBeforeCursor = ic.getTextBeforeCursor(cancelLength + 1, 0).subSequence(0, cancelLength) .toString(); - if (!autoCorrectedTo.equals(wordBeforeCursor)) { + if (!TextUtils.equals(autoCorrectedTo, wordBeforeCursor)) { throw new RuntimeException("cancelAutoCorrect check failed: we thought we were " + "reverting \"" + autoCorrectedTo + "\", but before the cursor we found \"" + wordBeforeCursor + "\""); } - if (originallyTypedWord.equals(wordBeforeCursor)) { + if (TextUtils.equals(originallyTypedWord, wordBeforeCursor)) { throw new RuntimeException("cancelAutoCorrect check failed: we wanted to cancel " + "auto correction and revert to \"" + originallyTypedWord + "\" but we found this very string before the cursor"); @@ -2169,7 +2169,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar final String wordBeforeCursor = ic.getTextBeforeCursor(restartLength + 1, 0).subSequence(0, restartLength) .toString(); - if (!mWordComposer.getTypedWord().equals(wordBeforeCursor)) { + if (!TextUtils.equals(mWordComposer.getTypedWord(), wordBeforeCursor)) { throw new RuntimeException("restartSuggestionsOnManuallyPickedTypedWord " + "check failed: we thought we were reverting \"" + mWordComposer.getTypedWord() diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java index 8e0cfa122..bc8a1301c 100644 --- a/java/src/com/android/inputmethod/latin/Utils.java +++ b/java/src/com/android/inputmethod/latin/Utils.java @@ -16,14 +16,6 @@ package com.android.inputmethod.latin; -import com.android.inputmethod.compat.InputMethodInfoCompatWrapper; -import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; -import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; -import com.android.inputmethod.compat.InputTypeCompatUtils; -import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.KeyboardId; -import com.android.inputmethod.latin.define.JniLibName; - import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -41,6 +33,14 @@ import android.text.format.DateUtils; import android.util.Log; import android.view.inputmethod.EditorInfo; +import com.android.inputmethod.compat.InputMethodInfoCompatWrapper; +import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; +import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper; +import com.android.inputmethod.compat.InputTypeCompatUtils; +import com.android.inputmethod.keyboard.Keyboard; +import com.android.inputmethod.keyboard.KeyboardId; +import com.android.inputmethod.latin.define.JniLibName; + import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; @@ -62,6 +62,12 @@ public class Utils { private static boolean DBG = LatinImeLogger.sDBG; private static boolean DBG_EDIT_DISTANCE = false; + // Constants for resource name parsing. + public static final char ESCAPE_CHAR = '\\'; + public static final char PREFIX_AT = '@'; + public static final char SUFFIX_SLASH = '/'; + private static final String PREFIX_STRING = PREFIX_AT + "string"; + private Utils() { // Intentional empty constructor for utility class. } @@ -793,4 +799,62 @@ public class Utils { LatinImeLogger.logOnAutoCorrectionCancelled(); } } + + public static int getResourceId(Resources res, String name, int packageNameResId) { + String packageName = res.getResourcePackageName(packageNameResId); + int resId = res.getIdentifier(name, null, packageName); + if (resId == 0) { + throw new RuntimeException("Unknown resource: " + name); + } + return resId; + } + + public static String resolveStringResource(String text, Resources res, int packageNameResId) { + final int size = text.length(); + if (size < PREFIX_STRING.length()) { + return text; + } + + StringBuilder sb = null; + for (int pos = 0; pos < size; pos++) { + final char c = text.charAt(pos); + if (c == PREFIX_AT && text.startsWith(PREFIX_STRING, pos)) { + if (sb == null) { + sb = new StringBuilder(text.substring(0, pos)); + } + final int end = Utils.searchResourceNameEnd(text, pos + PREFIX_STRING.length()); + final String resName = text.substring(pos + 1, end); + final int resId = getResourceId(res, resName, packageNameResId); + sb.append(res.getString(resId)); + pos = end - 1; + } else if (c == ESCAPE_CHAR) { + pos++; + if (sb != null) { + sb.append(c); + if (pos < size) { + sb.append(text.charAt(pos)); + } + } + } else if (sb != null) { + sb.append(c); + } + } + return (sb == null) ? text : sb.toString(); + } + + private static int searchResourceNameEnd(String text, int start) { + final int size = text.length(); + if (start >= size || text.charAt(start) != SUFFIX_SLASH) { + throw new RuntimeException("Resource name not specified"); + } + for (int pos = start + 1; pos < size; pos++) { + final char c = text.charAt(pos); + // String resource name should be consisted of [a-z_0-9]. + if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')) { + continue; + } + return pos; + } + return size; + } } diff --git a/tests/res/values/strings.xml b/tests/res/values/strings.xml new file mode 100644 index 000000000..bfd1c1716 --- /dev/null +++ b/tests/res/values/strings.xml @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** +** Copyright 2012, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ +--> + +<resources> + <string name="empty_string">""</string> + <string name="single_char">"a"</string> + <string name="space">" "</string> + <string name="single_label">"abc"</string> + <string name="spaces">" "</string> + <string name="spaces_in_label">"a b c"</string> + <string name="spaces_at_beginning_of_label">" abc"</string> + <string name="spaces_at_end_of_label">"abc "</string> + <string name="label_surrounded_by_spaces">" abc "</string> + <string name="escaped_char">"\\a"</string> + <string name="escaped_comma">"\\,"</string> + <string name="escaped_escape">"\\\\"</string> + <string name="escaped_label">"a\\bc"</string> + <string name="escaped_label_at_beginning">"\\abc"</string> + <string name="escaped_label_with_comma">"a\\,c"</string> + <string name="escaped_label_with_comma_at_beginning">"\\,bc"</string> + <string name="escaped_label_with_successive">"\\,\\\\bc"</string> + <string name="escaped_label_with_escape">"a\\\\c"</string> + <string name="multiple_chars">"a,b,c"</string> + <string name="multiple_chars_surrounded_by_spaces">" a , b , c "</string> + <string name="multiple_labels">"abc,def,ghi"</string> + <string name="multiple_labels_surrounded_by_spaces">" abc , def , ghi "</string> + <string name="multiple_chars_with_comma">"a,\\,,c"</string> + <string name="multiple_chars_with_comma_surrounded_by_spaces">" a , \\, , c "</string> + <string name="multiple_labels_with_escape">"\\abc,d\\ef,gh\\i"</string> + <string name="multiple_labels_with_escape_surrounded_by_spaces">" \\abc , d\\ef , gh\\i "</string> + <string name="multiple_labels_with_comma_and_escape">"ab\\\\,d\\\\\\,,g\\,i"</string> + <string name="multiple_labels_with_comma_and_escape_surrounded_by_spaces">" ab\\\\ , d\\\\\\, , g\\,i "</string> +</resources> diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyStylesTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyStylesTests.java index 4050a7123..29881d91c 100644 --- a/tests/src/com/android/inputmethod/keyboard/internal/KeyStylesTests.java +++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyStylesTests.java @@ -16,30 +16,53 @@ package com.android.inputmethod.keyboard.internal; -import com.android.inputmethod.keyboard.internal.KeyStyles.EmptyKeyStyle; - +import android.content.res.Resources; import android.test.AndroidTestCase; import android.text.TextUtils; +import com.android.inputmethod.latin.tests.R; + +import java.util.Arrays; + public class KeyStylesTests extends AndroidTestCase { + private Resources mTestResources; + + @Override + protected void setUp() throws Exception { + super.setUp(); + + mTestResources = getTestContext().getResources(); + } + private static String format(String message, Object expected, Object actual) { return message + " expected:<" + expected + "> but was:<" + actual + ">"; } - private static void assertTextArray(String message, CharSequence value, - CharSequence ... expected) { - final CharSequence actual[] = EmptyKeyStyle.parseCsvText(value); + private void assertTextArray(String message, String value, String ... expected) { + final String actual[] = KeyStyles.parseCsvText(value, mTestResources, + R.string.empty_string); if (expected.length == 0) { assertNull(message, actual); return; } - assertSame(message + ": result length", expected.length, actual.length); + assertEquals(message + ": expected=" + Arrays.toString(expected) + + " actual=" + Arrays.toString(actual) + + ": result length", expected.length, actual.length); for (int i = 0; i < actual.length; i++) { final boolean equals = TextUtils.equals(expected[i], actual[i]); assertTrue(format(message + ": result at " + i + ":", expected[i], actual[i]), equals); } } + private void assertError(String message, String value, String ... expected) { + try { + assertTextArray(message, value, expected); + fail(message); + } catch (Exception pcpe) { + // success. + } + } + public void testParseCsvTextZero() { assertTextArray("Empty string", ""); } @@ -52,7 +75,10 @@ public class KeyStylesTests extends AndroidTestCase { assertTextArray("Spaces in label", "a b c", "a b c"); assertTextArray("Spaces at beginning of label", " abc", " abc"); assertTextArray("Spaces at end of label", "abc ", "abc "); - assertTextArray("label surrounded by spaces", " abc ", " abc "); + assertTextArray("Label surrounded by spaces", " abc ", " abc "); + + assertTextArray("Incomplete resource reference 1", "string", "string"); + assertTextArray("Incomplete resource reference 2", "@strin", "@strin"); } public void testParseCsvTextSingleEscaped() { @@ -60,11 +86,13 @@ public class KeyStylesTests extends AndroidTestCase { assertTextArray("Escaped comma", "\\,", ","); assertTextArray("Escaped escape", "\\\\", "\\"); assertTextArray("Escaped label", "a\\bc", "abc"); - assertTextArray("Escaped label at begininng", "\\abc", "abc"); + assertTextArray("Escaped label at beginning", "\\abc", "abc"); assertTextArray("Escaped label with comma", "a\\,c", "a,c"); assertTextArray("Escaped label with comma at beginning", "\\,bc", ",bc"); assertTextArray("Escaped label with successive", "\\,\\\\bc", ",\\bc"); assertTextArray("Escaped label with escape", "a\\\\c", "a\\c"); + + assertTextArray("Escaped @string", "\\@string/empty_string", "@string/empty_string"); } public void testParseCsvTextMulti() { @@ -86,5 +114,109 @@ public class KeyStylesTests extends AndroidTestCase { "ab\\\\,d\\\\\\,,g\\,i", "ab\\", "d\\,", "g,i"); assertTextArray("Multiple labels with comma and escape surrounded by spaces", " ab\\\\ , d\\\\\\, , g\\,i ", " ab\\ ", " d\\, ", " g,i "); + + assertTextArray("Multiple escaped @string", "\\@,\\@string/empty_string", + "@", "@string/empty_string"); + } + + public void testParseCsvResourceError() { + assertError("Incomplete resource name 1", "@string", "@string"); + assertError("Incomplete resource name 2", "@string/", "@string/"); + assertError("Non existing resource", "@string/non_existing"); + } + + public void testParseCsvResourceZero() { + assertTextArray("Empty string", + "@string/empty_string"); + } + + public void testParseCsvResourceSingle() { + assertTextArray("Single char", + "@string/single_char", "a"); + assertTextArray("Space", + "@string/space", " "); + assertTextArray("Single label", + "@string/single_label", "abc"); + assertTextArray("Spaces", + "@string/spaces", " "); + assertTextArray("Spaces in label", + "@string/spaces_in_label", "a b c"); + assertTextArray("Spaces at beginning of label", + "@string/spaces_at_beginning_of_label", " abc"); + assertTextArray("Spaces at end of label", + "@string/spaces_at_end_of_label", "abc "); + assertTextArray("label surrounded by spaces", + "@string/label_surrounded_by_spaces", " abc "); + } + + public void testParseCsvResourceSingleEscaped() { + assertTextArray("Escaped char", + "@string/escaped_char", "a"); + assertTextArray("Escaped comma", + "@string/escaped_comma", ","); + assertTextArray("Escaped escape", + "@string/escaped_escape", "\\"); + assertTextArray("Escaped label", + "@string/escaped_label", "abc"); + assertTextArray("Escaped label at beginning", + "@string/escaped_label_at_beginning", "abc"); + assertTextArray("Escaped label with comma", + "@string/escaped_label_with_comma", "a,c"); + assertTextArray("Escaped label with comma at beginning", + "@string/escaped_label_with_comma_at_beginning", ",bc"); + assertTextArray("Escaped label with successive", + "@string/escaped_label_with_successive", ",\\bc"); + assertTextArray("Escaped label with escape", + "@string/escaped_label_with_escape", "a\\c"); + } + + public void testParseCsvResourceMulti() { + assertTextArray("Multiple chars", + "@string/multiple_chars", "a", "b", "c"); + assertTextArray("Multiple chars surrounded by spaces", + "@string/multiple_chars_surrounded_by_spaces", + " a ", " b ", " c "); + assertTextArray("Multiple labels", + "@string/multiple_labels", "abc", "def", "ghi"); + assertTextArray("Multiple labels surrounded by spaces", + "@string/multiple_labels_surrounded_by_spaces", " abc ", " def ", " ghi "); + } + + public void testParseCsvResourcetMultiEscaped() { + assertTextArray("Multiple chars with comma", + "@string/multiple_chars_with_comma", + "a", ",", "c"); + assertTextArray("Multiple chars with comma surrounded by spaces", + "@string/multiple_chars_with_comma_surrounded_by_spaces", + " a ", " , ", " c "); + assertTextArray("Multiple labels with escape", + "@string/multiple_labels_with_escape", + "abc", "def", "ghi"); + assertTextArray("Multiple labels with escape surrounded by spaces", + "@string/multiple_labels_with_escape_surrounded_by_spaces", + " abc ", " def ", " ghi "); + assertTextArray("Multiple labels with comma and escape", + "@string/multiple_labels_with_comma_and_escape", + "ab\\", "d\\,", "g,i"); + assertTextArray("Multiple labels with comma and escape surrounded by spaces", + "@string/multiple_labels_with_comma_and_escape_surrounded_by_spaces", + " ab\\ ", " d\\, ", " g,i "); + } + + public void testParseMultipleResources() { + assertTextArray("Literals and resources", + "1,@string/multiple_chars,z", "1", "a", "b", "c", "z"); + assertTextArray("Multiple single resource chars and labels", + "@string/single_char,@string/single_label,@string/escaped_comma", + "a", "abc", ","); + assertTextArray("Multiple multiple resource chars and labels", + "@string/multiple_chars,@string/multiple_labels,@string/multiple_chars_with_comma", + "a", "b", "c", "abc", "def", "ghi", "a", ",", "c"); + assertTextArray("Concatenated resources", + "@string/multiple_chars@string/multiple_labels@string/multiple_chars_with_comma", + "a", "b", "cabc", "def", "ghia", ",", "c"); + assertTextArray("Concatenated resource and literal", + "abc@string/multiple_labels", + "abcabc", "def", "ghi"); } } diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParserTests.java b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParserTests.java index edccff33a..ea11ff73d 100644 --- a/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParserTests.java +++ b/tests/src/com/android/inputmethod/keyboard/internal/MoreKeySpecParserTests.java @@ -66,7 +66,7 @@ public class MoreKeySpecParserTests extends AndroidTestCase { assertParser(message, moreKeySpec, expectedLabel, expectedOutputText, expectedIcon, expectedCode); fail(message); - } catch (MoreKeySpecParser.MoreKeySpecParserError pcpe) { + } catch (Exception pcpe) { // success. } } |