Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f56b82f8 authored by Ken Wakasa's avatar Ken Wakasa
Browse files

Fix the offdevice regression test build

Followup to If4e44eca3cdc5bb02cf2e0c8c44ecd4bf27fae57

bug: 10622489
Change-Id: If98b2c75725f8692f0c2b41c33e448086404479b
parent 399422f4
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.latin.settings.SettingsValues;
import com.android.inputmethod.latin.utils.CapsModeUtils;
import com.android.inputmethod.latin.utils.DebugLogUtils;
import com.android.inputmethod.latin.utils.SpannableStringUtils;
import com.android.inputmethod.latin.utils.StringUtils;
import com.android.inputmethod.latin.utils.TextRange;
import com.android.inputmethod.research.ResearchLogger;
@@ -610,7 +611,8 @@ public final class RichInputConnection {
        // We don't use TextUtils#concat because it copies all spans without respect to their
        // nature. If the text includes a PARAGRAPH span and it has been split, then
        // TextUtils#concat will crash when it tries to concat both sides of it.
        return new TextRange(StringUtils.concatWithNonParagraphSuggestionSpansOnly(before, after),
        return new TextRange(
                SpannableStringUtils.concatWithNonParagraphSuggestionSpansOnly(before, after),
                        startIndexInBefore, before.length() + endIndexInAfter, before.length());
    }

+110 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 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.
 */

package com.android.inputmethod.latin.utils;

import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.SpannedString;
import android.text.TextUtils;
import android.text.style.SuggestionSpan;

public final class SpannableStringUtils {
    /**
     * Copies the spans from the region <code>start...end</code> in
     * <code>source</code> to the region
     * <code>destoff...destoff+end-start</code> in <code>dest</code>.
     * Spans in <code>source</code> that begin before <code>start</code>
     * or end after <code>end</code> but overlap this range are trimmed
     * as if they began at <code>start</code> or ended at <code>end</code>.
     * Only SuggestionSpans that don't have the SPAN_PARAGRAPH span are copied.
     *
     * This code is almost entirely taken from {@link TextUtils#copySpansFrom}, except for the
     * kind of span that is copied.
     *
     * @throws IndexOutOfBoundsException if any of the copied spans
     * are out of range in <code>dest</code>.
     */
    public static void copyNonParagraphSuggestionSpansFrom(Spanned source, int start, int end,
                                     Spannable dest, int destoff) {
        Object[] spans = source.getSpans(start, end, SuggestionSpan.class);

        for (int i = 0; i < spans.length; i++) {
            int fl = source.getSpanFlags(spans[i]);
            if (0 != (fl & Spannable.SPAN_PARAGRAPH)) continue;

            int st = source.getSpanStart(spans[i]);
            int en = source.getSpanEnd(spans[i]);

            if (st < start)
                st = start;
            if (en > end)
                en = end;

            dest.setSpan(spans[i], st - start + destoff, en - start + destoff,
                         fl);
        }
    }

    /**
     * Returns a CharSequence concatenating the specified CharSequences, retaining their
     * SuggestionSpans that don't have the PARAGRAPH flag, but not other spans.
     *
     * This code is almost entirely taken from {@link TextUtils#concat(CharSequence...)}, except
     * it calls copyNonParagraphSuggestionSpansFrom instead of {@link TextUtils#copySpansFrom}.
     */
    public static CharSequence concatWithNonParagraphSuggestionSpansOnly(CharSequence... text) {
        if (text.length == 0) {
            return "";
        }

        if (text.length == 1) {
            return text[0];
        }

        boolean spanned = false;
        for (int i = 0; i < text.length; i++) {
            if (text[i] instanceof Spanned) {
                spanned = true;
                break;
            }
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < text.length; i++) {
            sb.append(text[i]);
        }

        if (!spanned) {
            return sb.toString();
        }

        SpannableString ss = new SpannableString(sb);
        int off = 0;
        for (int i = 0; i < text.length; i++) {
            int len = text[i].length();

            if (text[i] instanceof Spanned) {
                copyNonParagraphSuggestionSpansFrom((Spanned) text[i], 0, len, ss, off);
            }

            off += len;
        }

        return new SpannedString(ss);
    }
}
+0 −89
Original line number Diff line number Diff line
@@ -20,12 +20,7 @@ import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.settings.SettingsValues;

import android.text.Spannable;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.SpannedString;
import android.text.TextUtils;
import android.text.style.SuggestionSpan;
import android.util.JsonReader;
import android.util.JsonWriter;
import android.util.Log;
@@ -467,88 +462,4 @@ public final class StringUtils {
        }
        return "";
    }

    /**
     * Copies the spans from the region <code>start...end</code> in
     * <code>source</code> to the region
     * <code>destoff...destoff+end-start</code> in <code>dest</code>.
     * Spans in <code>source</code> that begin before <code>start</code>
     * or end after <code>end</code> but overlap this range are trimmed
     * as if they began at <code>start</code> or ended at <code>end</code>.
     * Only SuggestionSpans that don't have the SPAN_PARAGRAPH span are copied.
     *
     * This code is almost entirely taken from {@link TextUtils#copySpansFrom}, except for the
     * kind of span that is copied.
     *
     * @throws IndexOutOfBoundsException if any of the copied spans
     * are out of range in <code>dest</code>.
     */
    public static void copyNonParagraphSuggestionSpansFrom(Spanned source, int start, int end,
                                     Spannable dest, int destoff) {
        Object[] spans = source.getSpans(start, end, SuggestionSpan.class);

        for (int i = 0; i < spans.length; i++) {
            int fl = source.getSpanFlags(spans[i]);
            if (0 != (fl & Spannable.SPAN_PARAGRAPH)) continue;

            int st = source.getSpanStart(spans[i]);
            int en = source.getSpanEnd(spans[i]);

            if (st < start)
                st = start;
            if (en > end)
                en = end;

            dest.setSpan(spans[i], st - start + destoff, en - start + destoff,
                         fl);
        }
    }

    /**
     * Returns a CharSequence concatenating the specified CharSequences, retaining their
     * SuggestionSpans that don't have the PARAGRAPH flag, but not other spans.
     *
     * This code is almost entirely taken from {@link TextUtils#concat(CharSequence...)}, except
     * it calls copyNonParagraphSuggestionSpansFrom instead of {@link TextUtils#copySpansFrom}.
     */
    public static CharSequence concatWithNonParagraphSuggestionSpansOnly(CharSequence... text) {
        if (text.length == 0) {
            return "";
        }

        if (text.length == 1) {
            return text[0];
        }

        boolean spanned = false;
        for (int i = 0; i < text.length; i++) {
            if (text[i] instanceof Spanned) {
                spanned = true;
                break;
            }
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < text.length; i++) {
            sb.append(text[i]);
        }

        if (!spanned) {
            return sb.toString();
        }

        SpannableString ss = new SpannableString(sb);
        int off = 0;
        for (int i = 0; i < text.length; i++) {
            int len = text[i].length();

            if (text[i] instanceof Spanned) {
                copyNonParagraphSuggestionSpansFrom((Spanned) text[i], 0, len, ss, off);
            }

            off += len;
        }

        return new SpannedString(ss);
    }
}
+58 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 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.
 */

package com.android.inputmethod.latin.utils;

import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.style.SuggestionSpan;
import android.text.style.URLSpan;
import android.text.SpannableStringBuilder;
import android.text.Spannable;
import android.text.Spanned;

@SmallTest
public class SpannableStringUtilsTests extends AndroidTestCase {
    public void testConcatWithSuggestionSpansOnly() {
        SpannableStringBuilder s = new SpannableStringBuilder("test string\ntest string\n"
                + "test string\ntest string\ntest string\ntest string\ntest string\ntest string\n"
                + "test string\ntest string\n");
        final int N = 10;
        for (int i = 0; i < N; ++i) {
            // Put a PARAGRAPH-flagged span that should not be found in the result.
            s.setSpan(new SuggestionSpan(getContext(),
                    new String[] {"" + i}, Spannable.SPAN_PARAGRAPH),
                    i * 12, i * 12 + 12, Spannable.SPAN_PARAGRAPH);
            // Put a normal suggestion span that should be found in the result.
            s.setSpan(new SuggestionSpan(getContext(), new String[] {"" + i}, 0), i, i * 2, 0);
            // Put a URL span than should not be found in the result.
            s.setSpan(new URLSpan("http://a"), i, i * 2, 0);
        }

        final CharSequence a = s.subSequence(0, 15);
        final CharSequence b = s.subSequence(15, s.length());
        final Spanned result =
                (Spanned)SpannableStringUtils.concatWithNonParagraphSuggestionSpansOnly(a, b);

        Object[] spans = result.getSpans(0, result.length(), SuggestionSpan.class);
        for (int i = 0; i < spans.length; i++) {
            final int flags = result.getSpanFlags(spans[i]);
            assertEquals("Should not find a span with PARAGRAPH flag",
                    flags & Spannable.SPAN_PARAGRAPH, 0);
            assertTrue("Should be a SuggestionSpan", spans[i] instanceof SuggestionSpan);
        }
    }
}
+0 −35
Original line number Diff line number Diff line
@@ -20,11 +20,6 @@ import com.android.inputmethod.latin.settings.SettingsValues;

import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.style.SuggestionSpan;
import android.text.style.URLSpan;
import android.text.SpannableStringBuilder;
import android.text.Spannable;
import android.text.Spanned;

import java.util.Arrays;
import java.util.List;
@@ -285,34 +280,4 @@ public class StringUtilsTests extends AndroidTestCase {
            assertEquals(objs[i], newObjArray.get(i));
        }
    }

    public void testConcatWithSuggestionSpansOnly() {
        SpannableStringBuilder s = new SpannableStringBuilder("test string\ntest string\n"
                + "test string\ntest string\ntest string\ntest string\ntest string\ntest string\n"
                + "test string\ntest string\n");
        final int N = 10;
        for (int i = 0; i < N; ++i) {
            // Put a PARAGRAPH-flagged span that should not be found in the result.
            s.setSpan(new SuggestionSpan(getContext(),
                    new String[] {"" + i}, Spannable.SPAN_PARAGRAPH),
                    i * 12, i * 12 + 12, Spannable.SPAN_PARAGRAPH);
            // Put a normal suggestion span that should be found in the result.
            s.setSpan(new SuggestionSpan(getContext(), new String[] {"" + i}, 0), i, i * 2, 0);
            // Put a URL span than should not be found in the result.
            s.setSpan(new URLSpan("http://a"), i, i * 2, 0);
        }

        final CharSequence a = s.subSequence(0, 15);
        final CharSequence b = s.subSequence(15, s.length());
        final Spanned result =
                (Spanned)StringUtils.concatWithNonParagraphSuggestionSpansOnly(a, b);

        Object[] spans = result.getSpans(0, result.length(), SuggestionSpan.class);
        for (int i = 0; i < spans.length; i++) {
            final int flags = result.getSpanFlags(spans[i]);
            assertEquals("Should not find a span with PARAGRAPH flag",
                    flags & Spannable.SPAN_PARAGRAPH, 0);
            assertTrue("Should be a SuggestionSpan", spans[i] instanceof SuggestionSpan);
        }
    }
}