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

Commit 4350a93a authored by Ken Wakasa's avatar Ken Wakasa Committed by Android (Google) Code Review
Browse files

Merge "Fix the offdevice regression test build"

parents 5fa96540 f56b82f8
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);
        }
    }
}