EmojiMatcher.java revision f8ec169d022fbed42fd82091d24c45f3767cdfe7
182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir/* 282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Copyright (C) 2017 The Android Open Source Project 382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * 482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Licensed under the Apache License, Version 2.0 (the "License"); 582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * you may not use this file except in compliance with the License. 682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * You may obtain a copy of the License at 782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * 882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * http://www.apache.org/licenses/LICENSE-2.0 982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * 1082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Unless required by applicable law or agreed to in writing, software 1182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * distributed under the License is distributed on an "AS IS" BASIS, 1282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * See the License for the specific language governing permissions and 1482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * limitations under the License. 1582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir */ 1682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirpackage android.support.text.emoji.util; 1782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 18f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.mockito.Matchers.argThat; 19f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 2082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.support.text.emoji.EmojiSpan; 2182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.text.Spanned; 22f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport android.text.TextUtils; 2382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 24f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport org.hamcrest.BaseMatcher; 2582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.hamcrest.Description; 2682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.hamcrest.Matcher; 2782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.hamcrest.TypeSafeMatcher; 2882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 2982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir/** 3082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Utility class that includes matchers specific to emojis and EmojiSpans. 3182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir */ 3282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirpublic class EmojiMatcher { 3382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 3482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmojiAt(final int id, final int start, 3582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir final int end) { 3682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiResourceMatcher(id, start, end); 3782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 3882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 3982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmojiAt(final Emoji.EmojiMapping emojiMapping, 4082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir final int start, final int end) { 4182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiResourceMatcher(emojiMapping.id(), start, end); 4282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 4382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 4482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmojiAt(final int start, final int end) { 4582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiResourceMatcher(-1, start, end); 4682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 4782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 4882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmoji(final int id) { 4982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiResourceMatcher(id, -1, -1); 5082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 5182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 5282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmoji(final Emoji.EmojiMapping emojiMapping) { 5382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiResourceMatcher(emojiMapping.id(), -1, -1); 5482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 5582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 5682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmoji() { 5782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiSpanMatcher(); 5882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 5982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 6082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmojiCount(final int count) { 6182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiCountMatcher(count); 6282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 6382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 64f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir public static <T extends CharSequence> T sameCharSequence(final T expected) { 65f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir return argThat(new BaseMatcher<T>() { 66f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir @Override 67f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir public boolean matches(Object o) { 68f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir if (o instanceof CharSequence && expected.getClass() == o.getClass()) { 69f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir return TextUtils.equals(expected, (CharSequence) o); 70f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 71f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir return false; 72f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 73f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 74f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir @Override 75f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir public void describeTo(Description description) { 76f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir description.appendText("doesn't match " + expected); 77f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 78f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir }); 79f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 8082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 8182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static class EmojiSpanMatcher extends TypeSafeMatcher<CharSequence> { 8282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 8382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private EmojiSpan[] mSpans; 8482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 8582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir EmojiSpanMatcher() { 8682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 8782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 8882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 8982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public void describeTo(Description description) { 9082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir description.appendText("should have EmojiSpans"); 9182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 9282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 9382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 9482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir protected void describeMismatchSafely(final CharSequence charSequence, 9582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir Description mismatchDescription) { 9682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" has no EmojiSpans"); 9782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 9882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 9982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 10082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir protected boolean matchesSafely(final CharSequence charSequence) { 10182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (charSequence == null) return false; 10282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (!(charSequence instanceof Spanned)) return false; 10382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mSpans = ((Spanned) charSequence).getSpans(0, charSequence.length(), EmojiSpan.class); 10482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return mSpans.length != 0; 10582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 10682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 10782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 10882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static class EmojiCountMatcher extends TypeSafeMatcher<CharSequence> { 10982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 11082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private final int mCount; 11182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private EmojiSpan[] mSpans; 11282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 11382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir EmojiCountMatcher(final int count) { 11482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mCount = count; 11582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 11682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 11782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 11882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public void describeTo(Description description) { 11982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir description.appendText("should have ").appendValue(mCount).appendText(" EmojiSpans"); 12082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 12182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 12282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 12382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir protected void describeMismatchSafely(final CharSequence charSequence, 12482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir Description mismatchDescription) { 12582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" has "); 12682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mSpans == null) { 12782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendValue("no"); 12882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } else { 12982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendValue(mSpans.length); 13082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 13182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 13282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" EmojiSpans"); 13382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 13482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 13582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 13682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir protected boolean matchesSafely(final CharSequence charSequence) { 13782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (charSequence == null) return false; 13882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (!(charSequence instanceof Spanned)) return false; 13982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mSpans = ((Spanned) charSequence).getSpans(0, charSequence.length(), EmojiSpan.class); 14082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return mSpans.length == mCount; 14182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 14282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 14382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 14482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static class EmojiResourceMatcher extends TypeSafeMatcher<CharSequence> { 14582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static final int ERR_NONE = 0; 14682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static final int ERR_SPANNABLE_NULL = 1; 14782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static final int ERR_NO_SPANS = 2; 14882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static final int ERR_WRONG_INDEX = 3; 14982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private final int mResId; 15082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private final int mStart; 15182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private final int mEnd; 15282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private int mError = ERR_NONE; 15382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private int mActualStart = -1; 15482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private int mActualEnd = -1; 15582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 15682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir EmojiResourceMatcher(int resId, int start, int end) { 15782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mResId = resId; 15882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mStart = start; 15982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mEnd = end; 16082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 16182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 16282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 16382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public void describeTo(final Description description) { 16482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mResId == -1) { 16582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir description.appendText("should have EmojiSpan at ") 16682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir .appendValue("[" + mStart + "," + mEnd + "]"); 16782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } else if (mStart == -1 && mEnd == -1) { 16882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir description.appendText("should have EmojiSpan with resource id ") 16982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir .appendValue(Integer.toHexString(mResId)); 17082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } else { 17182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir description.appendText("should have EmojiSpan with resource id ") 17282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir .appendValue(Integer.toHexString(mResId)) 17382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir .appendText(" at ") 17482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir .appendValue("[" + mStart + "," + mEnd + "]"); 17582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 17682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 17782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 17882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 17982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir protected void describeMismatchSafely(final CharSequence charSequence, 18082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir Description mismatchDescription) { 18182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir int offset = 0; 18282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText("["); 18382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir while (offset < charSequence.length()) { 18482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir int codepoint = Character.codePointAt(charSequence, offset); 18582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(Integer.toHexString(codepoint)); 18682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir offset += Character.charCount(codepoint); 18782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (offset < charSequence.length()) { 18882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(","); 18982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 19082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 19182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText("]"); 19282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 19382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir switch (mError) { 19482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir case ERR_NO_SPANS: 19582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" had no spans"); 19682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir break; 19782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir case ERR_SPANNABLE_NULL: 19882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" was null"); 19982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir break; 20082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir case ERR_WRONG_INDEX: 20182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" had Emoji at ") 20282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir .appendValue("[" + mActualStart + "," + mActualEnd + "]"); 20382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir break; 20482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir default: 20582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" does not have an EmojiSpan with given " 20682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir + "resource id "); 20782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 20882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 20982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 21082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 21182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir protected boolean matchesSafely(final CharSequence charSequence) { 21282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (charSequence == null) { 21382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mError = ERR_SPANNABLE_NULL; 21482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return false; 21582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 21682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 21782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (!(charSequence instanceof Spanned)) { 21882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mError = ERR_NO_SPANS; 21982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return false; 22082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 22182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 22282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir Spanned spanned = (Spanned) charSequence; 22382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir final EmojiSpan[] spans = spanned.getSpans(0, charSequence.length(), EmojiSpan.class); 22482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 22582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (spans.length == 0) { 22682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mError = ERR_NO_SPANS; 22782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return false; 22882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 22982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 23082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mStart == -1 && mEnd == -1) { 23182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir for (int index = 0; index < spans.length; index++) { 23282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mResId == spans[index].getId()) { 23382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return true; 23482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 23582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 23682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return false; 23782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } else { 23882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir for (int index = 0; index < spans.length; index++) { 23982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mResId == -1 || mResId == spans[index].getId()) { 24082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mActualStart = spanned.getSpanStart(spans[index]); 24182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mActualEnd = spanned.getSpanEnd(spans[index]); 24282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mActualStart == mStart && mActualEnd == mEnd) { 24382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return true; 24482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 24582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 24682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 24782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 24882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mActualStart != -1 && mActualEnd != -1) { 24982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mError = ERR_WRONG_INDEX; 25082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 25182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 25282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return false; 25382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 25482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 25582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 25682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir} 257