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

Commit eed3f1fe authored by George Mount's avatar George Mount
Browse files

Support bracket expressions for SparseArray.

Also support single-quotes for XML attributes.
parent f9c62b6f
Loading
Loading
Loading
Loading
+78 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2015 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.databinding.testapp;

import com.android.databinding.testapp.generated.BracketTestBinder;

import android.test.UiThreadTest;
import android.util.LongSparseArray;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
import android.widget.LinearLayout;
import android.widget.TextView;

public class BracketTest extends BaseDataBinderTest<BracketTestBinder> {
    private String[] mArray = {
            "Hello World"
    };

    private SparseArray<String> mSparseArray = new SparseArray<>();
    private SparseIntArray mSparseIntArray = new SparseIntArray();
    private SparseBooleanArray mSparseBooleanArray = new SparseBooleanArray();
    private SparseLongArray mSparseLongArray = new SparseLongArray();
    private LongSparseArray<String> mLongSparseArray = new LongSparseArray<>();

    public BracketTest() {
        super(BracketTestBinder.class, R.layout.bracket_test);
        mSparseArray.put(0, "Hello");
        mLongSparseArray.put(0, "World");
        mSparseIntArray.put(0, 100);
        mSparseBooleanArray.put(0, true);
        mSparseLongArray.put(0, 5);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        try {
            runTestOnUiThread(new Runnable() {
                @Override
                public void run() {
                    mBinder.setArray(mArray);
                    mBinder.setSparseArray(mSparseArray);
                    mBinder.setSparseIntArray(mSparseIntArray);
                    mBinder.setSparseBooleanArray(mSparseBooleanArray);
                    mBinder.setSparseLongArray(mSparseLongArray);
                    mBinder.setLongSparseArray(mLongSparseArray);

                    mBinder.rebindDirty();
                }
            });
        } catch (Throwable throwable) {
            throw new Exception(throwable);
        }
    }

    @UiThreadTest
    public void testBrackets() {
        assertEquals("Hello World", mBinder.getArrayText().getText().toString());
        assertEquals("Hello", mBinder.getSparseArrayText().getText().toString());
        assertEquals("World", mBinder.getLongSparseArrayText().getText().toString());
        assertEquals("100", mBinder.getSparseIntArrayText().getText().toString());
        assertEquals("true", mBinder.getSparseBooleanArrayText().getText().toString());
        assertEquals("5", mBinder.getSparseLongArrayText().getText().toString());
    }
}
+44 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical"
        >
    <variable name="array" type="String[]"/>
    <variable name="sparseArray" type="android.util.SparseArray&lt;String>"/>
    <variable name="sparseBooleanArray" type="android.util.SparseBooleanArray"/>
    <variable name="sparseIntArray" type="android.util.SparseIntArray"/>
    <variable name="sparseLongArray" type="android.util.SparseLongArray"/>
    <variable name="longSparseArray" type="android.util.LongSparseArray&lt;String>"/>

    <TextView android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:id="@+id/arrayText"
              android:text="@{array[0]}"/>

    <TextView android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:id="@+id/sparseArrayText"
              android:text='@{sparseArray[0]}'/>

    <TextView android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:id="@+id/sparseBooleanArrayText"
              android:text='@{"" + sparseBooleanArray[0]}'/>

    <TextView android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:id="@+id/sparseIntArrayText"
              android:text='@{"" + sparseIntArray[0]}'/>

    <TextView android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:id="@+id/sparseLongArrayText"
              android:text='@{"" + sparseLongArray[0]}'/>

    <TextView android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:id="@+id/longSparseArrayText"
              android:text='@{longSparseArray[0]}'/>

</LinearLayout>
 No newline at end of file
+21 −6
Original line number Diff line number Diff line
@@ -45,7 +45,15 @@ import javax.tools.Diagnostic;

public class AnnotationAnalyzer extends ModelAnalyzer {

    public static final String LIST_CLASS_NAME = "java.util.List";
    public static final String[] LIST_CLASS_NAMES = {
            "java.util.List",
            "android.util.SparseArray",
            "android.util.SparseBooleanArray",
            "android.util.SparseIntArray",
            "android.util.SparseLongArray",
            "android.util.LongSparseArray",
            "android.support.v4.util.LongSparseArray",
    };

    public static final String MAP_CLASS_NAME = "java.util.Map";

@@ -83,7 +91,7 @@ public class AnnotationAnalyzer extends ModelAnalyzer {

    public final ProcessingEnvironment processingEnv;

    private AnnotationClass mListType;
    private AnnotationClass[] mListTypes;
    private AnnotationClass mMapType;
    private AnnotationClass mStringType;
    private AnnotationClass mObjectType;
@@ -98,11 +106,18 @@ public class AnnotationAnalyzer extends ModelAnalyzer {
        instance = this;
    }

    public AnnotationClass getListType() {
        if (mListType == null) {
            mListType = loadClassErasure(LIST_CLASS_NAME);
    public AnnotationClass[] getListTypes() {
        if (mListTypes == null) {
            Types typeUtil = getTypeUtils();
            mListTypes = new AnnotationClass[LIST_CLASS_NAMES.length];
            for (int i = 0; i < mListTypes.length; i++) {
                TypeElement typeElement = findType(LIST_CLASS_NAMES[i]);
                if (typeElement != null) {
                    mListTypes[i] = new AnnotationClass(typeUtil.erasure(typeElement.asType()));
                }
            }
        }
        return mListType;
        return mListTypes;
    }

    public AnnotationClass getMapType() {
+20 −9
Original line number Diff line number Diff line
@@ -57,15 +57,20 @@ public class AnnotationClass implements ModelClass {

    @Override
    public AnnotationClass getComponentType() {
        TypeMirror component;
        TypeMirror component = null;
        if (isArray()) {
            component = ((ArrayType) mTypeMirror).getComponentType();
        } else if (isList()) {
            DeclaredType listType = findInterface(getListType().mTypeMirror);
            if (listType == null) {
                return null;
            for (ModelMethod method : getMethods("get", 1)) {
                ModelClass parameter = method.getParameterTypes()[0];
                if (parameter.isInt() || parameter.isLong()) {
                    ArrayList<ModelClass> parameters = new ArrayList<>(1);
                    parameters.add(parameter);
                    return (AnnotationClass) method.getReturnType(parameters);
                }
            }
            component = listType.getTypeArguments().get(0);
            // no "get" call found!
            return null;
        } else {
            DeclaredType mapType = findInterface(getMapType().mTypeMirror);
            if (mapType == null) {
@@ -112,8 +117,14 @@ public class AnnotationClass implements ModelClass {

    @Override
    public boolean isList() {
        Types typeUtil = getTypeUtils();
        return typeUtil.isAssignable(typeUtil.erasure(mTypeMirror), getListType().mTypeMirror);
        for (AnnotationClass listType : getListTypes()) {
            if (listType != null) {
                if (listType.isAssignableFrom(this)) {
                    return true;
                }
            }
        }
        return false;
    }

    @Override
@@ -296,8 +307,8 @@ public class AnnotationClass implements ModelClass {
        return AnnotationAnalyzer.instance.processingEnv.getElementUtils();
    }

    private static AnnotationClass getListType() {
        return AnnotationAnalyzer.instance.getListType();
    private static AnnotationClass[] getListTypes() {
        return AnnotationAnalyzer.instance.getListTypes();
    }

    private static AnnotationClass getMapType() {
+2 −1
Original line number Diff line number Diff line
@@ -52,7 +52,8 @@ object XmlEditor {
            }
            val isTag = ctx.attrName.getText().equals("android:tag")
            if (isTag || ctx.attrName.getText().startsWith("bind:") ||
                    (ctx.attrValue.getText().startsWith("\"@{") && ctx.attrValue.getText().endsWith("}\""))) {
                    (ctx.attrValue.getText().startsWith("\"@{") && ctx.attrValue.getText().endsWith("}\"")) ||
                    (ctx.attrValue.getText().startsWith("'@{") && ctx.attrValue.getText().endsWith("}'"))) {
                return arrayListOf(LayoutXmlElements(ctx.getStart().toPosition(),
                    ctx.getStop().toEndPosition(), ctx.getStart().toPosition(), isTag, false, null))
            }