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

Commit 81536a4d authored by George Mount's avatar George Mount
Browse files

Move expression parsing to Annotation Processing stage.

Change-Id: Ibf1e9c02856212c20300f10e4c63b96ec33b7a13
parent 2af44f84
Loading
Loading
Loading
Loading
+16 −22
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
@@ -41,8 +42,7 @@ import javax.tools.StandardLocation;
@SupportedAnnotationTypes({"android.binding.Bindable"})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class ProcessBindable extends AbstractProcessor {

    private boolean mFileGenerated;
    Intermediate mProperties = new IntermediateV1();

    public ProcessBindable() {
    }
@@ -55,24 +55,25 @@ public class ProcessBindable extends AbstractProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (mFileGenerated) {
            return false;
        }
        Intermediate properties = readIntermediateFile();
        for (Element element : roundEnv.getElementsAnnotatedWith(Bindable.class)) {
            TypeElement enclosing = (TypeElement) element.getEnclosingElement();
            properties.cleanProperties(enclosing.getQualifiedName().toString());
            Element enclosingElement = element.getEnclosingElement();
            ElementKind kind = enclosingElement.getKind();
            if (kind != ElementKind.CLASS && kind != ElementKind.INTERFACE) {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
                        "Bindable must be on a member field or method. The enclosing type is " +
                            enclosingElement.getKind(), element);
                continue;
            }
        for (Element element : roundEnv.getElementsAnnotatedWith(Bindable.class)) {
            TypeElement enclosing = (TypeElement) element.getEnclosingElement();
            TypeElement enclosing = (TypeElement) enclosingElement;
            String name = getPropertyName(element);
            if (name != null) {
                properties.addProperty(enclosing.getQualifiedName().toString(), name);
                mProperties.addProperty(enclosing.getQualifiedName().toString(), name);
            }
        }
        if (roundEnv.processingOver()) {
            writeIntermediateFile(mProperties);
            generateBR(mProperties);
        }
        writeIntermediateFile(properties);
        generateBR(properties);
        mFileGenerated = true;
        return true;
    }

@@ -294,8 +295,6 @@ public class ProcessBindable extends AbstractProcessor {
    private interface Intermediate {
        void captureProperties(Set<String> properties);

        void cleanProperties(String className);

        void addProperty(String className, String propertyName);
    }

@@ -311,11 +310,6 @@ public class ProcessBindable extends AbstractProcessor {
            }
        }

        @Override
        public void cleanProperties(String className) {
            mProperties.remove(className);
        }

        @Override
        public void addProperty(String className, String propertyName) {
            HashSet<String> properties = mProperties.get(className);
+56 −31
Original line number Diff line number Diff line
package com.android.databinding.annotationprocessor;

import com.android.databinding.CompilerChef;
import com.android.databinding.store.ResourceBundle;
import com.android.databinding.writer.AnnotationJavaFileWriter;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;

import android.binding.BinderBundle;
import android.binding.BindingAppInfo;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
@@ -21,60 +27,79 @@ import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

@SupportedAnnotationTypes({"android.binding.BinderBundle"})
@SupportedAnnotationTypes({"android.binding.BinderBundle", "android.binding.BindingAppInfo"})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class ProcessExpressions extends AbstractProcessor {
    private boolean mGenerationComplete;

    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (mGenerationComplete) {
            return false;
        }
        ResourceBundle resourceBundle = null;

        String binderBundle64 = null;
        for (Element element : roundEnv.getElementsAnnotatedWith(BinderBundle.class)) {
        for (Element element : roundEnv.getElementsAnnotatedWith(BindingAppInfo.class)) {
            if (element.getKind() != ElementKind.CLASS) {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
                        "BinderBundle associated with wrong type. Should be a class.", element);
                        "BindingAppInfo associated with wrong type. Should be a class.", element);
                continue;
            }
            TypeElement binderBundleClass = (TypeElement) element;
            if (!"BinderInfo".equals(binderBundleClass.getQualifiedName().toString())) {
            BindingAppInfo appInfo = element.getAnnotation(BindingAppInfo.class);
            if (resourceBundle == null) {
                resourceBundle = new ResourceBundle(appInfo.applicationPackage());
                processLayouts(resourceBundle, roundEnv);
            } else {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
                        "Only a generated class may use @BinderBundle attribute.", element);
                continue;
                        "BindingAppInfo must be applied to only one class.", element);
            }
        }
            BinderBundle binderBundle = binderBundleClass.getAnnotation(BinderBundle.class);
            binderBundle64 = binderBundle.value();

        return true;
    }

        if (binderBundle64 != null) {
    private void processLayouts(ResourceBundle resourceBundle, RoundEnvironment roundEnv) {
        Unmarshaller unmarshaller = null;
        for (Element element : roundEnv.getElementsAnnotatedWith(BinderBundle.class)) {
            if (element.getKind() != ElementKind.CLASS) {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
                        "BinderBundle associated with wrong type. Should be a class.", element);
                continue;
            }
            ByteArrayInputStream in = null;
            try {
                if (unmarshaller == null) {
                    JAXBContext context =
                            JAXBContext.newInstance(ResourceBundle.LayoutFileBundle.class);
                    unmarshaller = context.createUnmarshaller();
                }
                BinderBundle binderBundle = element.getAnnotation(BinderBundle.class);
                String binderBundle64 = binderBundle.value();
                byte[] buf = Base64.decodeBase64(binderBundle64);
                in = new ByteArrayInputStream(buf);
                AnnotationJavaFileWriter annotationJavaFileWriter =
                        new AnnotationJavaFileWriter(processingEnv);
                CompilerChef compilerChef = CompilerChef.createChef(in, annotationJavaFileWriter);
                if (compilerChef.hasAnythingToGenerate()) {
                    compilerChef.writeViewBinders();
                    compilerChef.writeDbrFile();
                }
            } catch (IOException e) {
                Reader reader = new InputStreamReader(in);
                ResourceBundle.LayoutFileBundle layoutFileBundle
                        = (ResourceBundle.LayoutFileBundle)
                        unmarshaller.unmarshal(reader);
                resourceBundle
                        .addLayoutBundle(layoutFileBundle, layoutFileBundle.getLayoutId());
            } catch (Exception e) {
                StringWriter stringWriter = new StringWriter();
                e.printStackTrace(new PrintWriter(stringWriter));
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
                        "Could not generate Binders from binder data store. " +
                                e.getLocalizedMessage());
            } catch (ClassNotFoundException e) {
                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
                        "Error generating Binders from binder data store. " +
                                e.getLocalizedMessage());
                        "Could not generate Binders from binder data store: " +
                                stringWriter.getBuffer().toString(), element);
            } finally {
                if (in != null) {
                    IOUtils.closeQuietly(in);
                }
            }

        }
        mGenerationComplete = true;
        return true;

        CompilerChef compilerChef = CompilerChef.createChef(resourceBundle,
                new AnnotationJavaFileWriter(processingEnv));
        compilerChef.writeDbrFile();
        compilerChef.writeViewBinderInterfaces();
        compilerChef.writeViewBinders();
    }
}
+0 −1
Original line number Diff line number Diff line
@@ -21,6 +21,5 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Bindable {
}
+28 −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 android.binding;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
public @interface BindingAppInfo {
    String buildId();
    String applicationPackage();
}
+1 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ dependencies {
    compile 'org.apache.commons:commons-io:1.3.2'
    compile 'com.google.guava:guava:18.0'
    compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
    compile 'commons-codec:commons-codec:1.10'
    compile project(":baseLibrary")
    compile project(":grammarBuilder")
    compile project(":xmlGrammar")
Loading