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 */ 16ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.emoji.util; 1782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 18f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport static org.mockito.Matchers.argThat; 19f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 2082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.text.Spanned; 21f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinirimport android.text.TextUtils; 2282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 2338746a682208c764867ffe4415d0b62fb22b5b9aAurimas Liutikasimport androidx.emoji.text.EmojiSpan; 2438746a682208c764867ffe4415d0b62fb22b5b9aAurimas Liutikas 2582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.hamcrest.Description; 2682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.hamcrest.Matcher; 2782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.hamcrest.TypeSafeMatcher; 28963facb8fce35022f296c38fadafd9a959ab1655Aurimas Liutikasimport org.mockito.ArgumentMatcher; 2982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 3082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir/** 3182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Utility class that includes matchers specific to emojis and EmojiSpans. 3282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir */ 3382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirpublic class EmojiMatcher { 3482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 3582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmojiAt(final int id, final int start, 3682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir final int end) { 3782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiResourceMatcher(id, start, end); 3882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 3982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 4082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmojiAt(final Emoji.EmojiMapping emojiMapping, 4182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir final int start, final int end) { 4282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiResourceMatcher(emojiMapping.id(), start, end); 4382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 4482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 4582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmojiAt(final int start, final int end) { 4682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiResourceMatcher(-1, start, end); 4782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 4882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 4982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmoji(final int id) { 5082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiResourceMatcher(id, -1, -1); 5182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 5282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 5382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmoji(final Emoji.EmojiMapping emojiMapping) { 5482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiResourceMatcher(emojiMapping.id(), -1, -1); 5582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 5682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 5782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmoji() { 5882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiSpanMatcher(); 5982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 6082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 6182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public static Matcher<CharSequence> hasEmojiCount(final int count) { 6282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return new EmojiCountMatcher(count); 6382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 6482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 65f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir public static <T extends CharSequence> T sameCharSequence(final T expected) { 66963facb8fce35022f296c38fadafd9a959ab1655Aurimas Liutikas return argThat(new ArgumentMatcher<T>() { 67f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir @Override 68963facb8fce35022f296c38fadafd9a959ab1655Aurimas Liutikas public boolean matches(T o) { 69410ea048366f492ff9908c1dbe91160da87792fcSiyamed Sinir if (o instanceof CharSequence) { 70410ea048366f492ff9908c1dbe91160da87792fcSiyamed Sinir return TextUtils.equals(expected, o); 71f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 72f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir return false; 73f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 74f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir 75f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir @Override 76963facb8fce35022f296c38fadafd9a959ab1655Aurimas Liutikas public String toString() { 77963facb8fce35022f296c38fadafd9a959ab1655Aurimas Liutikas return "doesn't match " + expected; 78f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 79f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir }); 80f8ec169d022fbed42fd82091d24c45f3767cdfe7Siyamed Sinir } 8182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 8282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static class EmojiSpanMatcher extends TypeSafeMatcher<CharSequence> { 8382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 8482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private EmojiSpan[] mSpans; 8582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 8682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir EmojiSpanMatcher() { 8782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 8882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 8982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 9082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public void describeTo(Description description) { 9182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir description.appendText("should have EmojiSpans"); 9282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 9382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 9482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 9582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir protected void describeMismatchSafely(final CharSequence charSequence, 9682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir Description mismatchDescription) { 9782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" has no EmojiSpans"); 9882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 9982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 10082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 10182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir protected boolean matchesSafely(final CharSequence charSequence) { 10282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (charSequence == null) return false; 10382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (!(charSequence instanceof Spanned)) return false; 10482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mSpans = ((Spanned) charSequence).getSpans(0, charSequence.length(), EmojiSpan.class); 10582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return mSpans.length != 0; 10682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 10782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 10882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 10982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static class EmojiCountMatcher extends TypeSafeMatcher<CharSequence> { 11082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 11182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private final int mCount; 11282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private EmojiSpan[] mSpans; 11382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 11482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir EmojiCountMatcher(final int count) { 11582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mCount = count; 11682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 11782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 11882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 11982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public void describeTo(Description description) { 12082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir description.appendText("should have ").appendValue(mCount).appendText(" EmojiSpans"); 12182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 12282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 12382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 12482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir protected void describeMismatchSafely(final CharSequence charSequence, 12582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir Description mismatchDescription) { 12682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" has "); 12782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mSpans == null) { 12882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendValue("no"); 12982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } else { 13082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendValue(mSpans.length); 13182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 13282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 13382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" EmojiSpans"); 13482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 13582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 13682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 13782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir protected boolean matchesSafely(final CharSequence charSequence) { 13882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (charSequence == null) return false; 13982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (!(charSequence instanceof Spanned)) return false; 14082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mSpans = ((Spanned) charSequence).getSpans(0, charSequence.length(), EmojiSpan.class); 14182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return mSpans.length == mCount; 14282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 14382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 14482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 14582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static class EmojiResourceMatcher extends TypeSafeMatcher<CharSequence> { 14682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static final int ERR_NONE = 0; 14782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static final int ERR_SPANNABLE_NULL = 1; 14882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static final int ERR_NO_SPANS = 2; 14982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private static final int ERR_WRONG_INDEX = 3; 15082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private final int mResId; 15182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private final int mStart; 15282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private final int mEnd; 15382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private int mError = ERR_NONE; 15482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private int mActualStart = -1; 15582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir private int mActualEnd = -1; 15682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 15782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir EmojiResourceMatcher(int resId, int start, int end) { 15882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mResId = resId; 15982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mStart = start; 16082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mEnd = end; 16182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 16282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 16382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 16482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir public void describeTo(final Description description) { 16582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mResId == -1) { 16682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir description.appendText("should have EmojiSpan at ") 16782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir .appendValue("[" + mStart + "," + mEnd + "]"); 16882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } else if (mStart == -1 && mEnd == -1) { 16982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir description.appendText("should have EmojiSpan with resource id ") 17082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir .appendValue(Integer.toHexString(mResId)); 17182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } else { 17282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir description.appendText("should have EmojiSpan with resource id ") 17382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir .appendValue(Integer.toHexString(mResId)) 17482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir .appendText(" at ") 17582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir .appendValue("[" + mStart + "," + mEnd + "]"); 17682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 17782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 17882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 17982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 18082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir protected void describeMismatchSafely(final CharSequence charSequence, 18182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir Description mismatchDescription) { 18282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir int offset = 0; 18382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText("["); 18482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir while (offset < charSequence.length()) { 18582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir int codepoint = Character.codePointAt(charSequence, offset); 18682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(Integer.toHexString(codepoint)); 18782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir offset += Character.charCount(codepoint); 18882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (offset < charSequence.length()) { 18982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(","); 19082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 19182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 19282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText("]"); 19382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 19482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir switch (mError) { 19582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir case ERR_NO_SPANS: 19682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" had no spans"); 19782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir break; 19882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir case ERR_SPANNABLE_NULL: 19982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" was null"); 20082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir break; 20182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir case ERR_WRONG_INDEX: 20282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" had Emoji at ") 20382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir .appendValue("[" + mActualStart + "," + mActualEnd + "]"); 20482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir break; 20582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir default: 20682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mismatchDescription.appendText(" does not have an EmojiSpan with given " 20782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir + "resource id "); 20882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 20982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 21082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 21182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir @Override 21282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir protected boolean matchesSafely(final CharSequence charSequence) { 21382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (charSequence == null) { 21482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mError = ERR_SPANNABLE_NULL; 21582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return false; 21682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 21782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 21882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (!(charSequence instanceof Spanned)) { 21982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mError = ERR_NO_SPANS; 22082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return false; 22182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 22282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 22382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir Spanned spanned = (Spanned) charSequence; 22482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir final EmojiSpan[] spans = spanned.getSpans(0, charSequence.length(), EmojiSpan.class); 22582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 22682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (spans.length == 0) { 22782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mError = ERR_NO_SPANS; 22882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return false; 22982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 23082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 23182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mStart == -1 && mEnd == -1) { 23282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir for (int index = 0; index < spans.length; index++) { 23382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mResId == spans[index].getId()) { 23482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return true; 23582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 23682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 23782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return false; 23882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } else { 23982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir for (int index = 0; index < spans.length; index++) { 24082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mResId == -1 || mResId == spans[index].getId()) { 24182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mActualStart = spanned.getSpanStart(spans[index]); 24282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mActualEnd = spanned.getSpanEnd(spans[index]); 24382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mActualStart == mStart && mActualEnd == mEnd) { 24482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return true; 24582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 24682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 24782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 24882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 24982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir if (mActualStart != -1 && mActualEnd != -1) { 25082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir mError = ERR_WRONG_INDEX; 25182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 25282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir 25382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir return false; 25482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 25582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 25682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir } 25782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir} 258