ProcessDataBinding.java revision b1356339eaa6c8e967e4fc1dc283b82909a1208d
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.databinding.annotationprocessor;
18
19import android.databinding.BindingBuildInfo;
20import android.databinding.tool.reflection.ModelAnalyzer;
21import android.databinding.tool.writer.AnnotationJavaFileWriter;
22import android.databinding.tool.writer.JavaFileWriter;
23
24import java.util.Arrays;
25import java.util.List;
26import java.util.Set;
27
28import javax.annotation.processing.AbstractProcessor;
29import javax.annotation.processing.ProcessingEnvironment;
30import javax.annotation.processing.RoundEnvironment;
31import javax.annotation.processing.SupportedAnnotationTypes;
32import javax.annotation.processing.SupportedSourceVersion;
33import javax.lang.model.SourceVersion;
34import javax.lang.model.element.TypeElement;
35
36@SupportedAnnotationTypes({
37        "android.databinding.BindingAdapter",
38        "android.databinding.Untaggable",
39        "android.databinding.BindingMethods",
40        "android.databinding.BindingConversion",
41        "android.databinding.BindingBuildInfo"}
42)
43@SupportedSourceVersion(SourceVersion.RELEASE_7)
44/**
45 * Parent annotation processor that dispatches sub steps to ensure execution order.
46 * Use initProcessingSteps to add a new step.
47 */
48public class ProcessDataBinding extends AbstractProcessor {
49    private List<ProcessingStep> mProcessingSteps;
50    @Override
51    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
52        if (mProcessingSteps == null) {
53            initProcessingSteps();
54        }
55        final BindingBuildInfo buildInfo = BuildInfoUtil.load(roundEnv);
56        if (buildInfo == null) {
57            return false;
58        }
59        boolean done = true;
60        for (ProcessingStep step : mProcessingSteps) {
61            done = step.runStep(roundEnv, processingEnv, buildInfo) && done;
62        }
63        if (roundEnv.processingOver()) {
64            for (ProcessingStep step : mProcessingSteps) {
65                step.onProcessingOver(roundEnv, processingEnv, buildInfo);
66            }
67        }
68        return done;
69    }
70
71    private void initProcessingSteps() {
72        ProcessBindable processBindable = new ProcessBindable();
73        mProcessingSteps = Arrays.asList(
74                new ProcessMethodAdapters(),
75                new ProcessExpressions(processBindable),
76                processBindable
77        );
78        AnnotationJavaFileWriter javaFileWriter = new AnnotationJavaFileWriter(processingEnv);
79        for (ProcessingStep step : mProcessingSteps) {
80            step.mJavaFileWriter = javaFileWriter;
81        }
82    }
83
84    @Override
85    public synchronized void init(ProcessingEnvironment processingEnv) {
86        super.init(processingEnv);
87        ModelAnalyzer.setProcessingEnvironment(processingEnv);
88    }
89
90    /**
91     * To ensure execution order and binding build information, we use processing steps.
92     */
93    public abstract static class ProcessingStep {
94        private boolean mDone;
95        private JavaFileWriter mJavaFileWriter;
96
97        protected JavaFileWriter getWriter() {
98            return mJavaFileWriter;
99        }
100
101        private boolean runStep(RoundEnvironment roundEnvironment,
102                ProcessingEnvironment processingEnvironment,
103                BindingBuildInfo buildInfo) {
104            if (mDone) {
105                return true;
106            }
107            mDone = onHandleStep(roundEnvironment, processingEnvironment, buildInfo);
108            return mDone;
109        }
110
111        /**
112         * Invoked in each annotation processing step.
113         *
114         * @return True if it is done and should never be invoked again.
115         */
116        abstract public boolean onHandleStep(RoundEnvironment roundEnvironment,
117                ProcessingEnvironment processingEnvironment,
118                BindingBuildInfo buildInfo);
119
120        /**
121         * Invoked when processing is done. A good place to generate the output if the
122         * processor requires multiple steps.
123         */
124        abstract public void onProcessingOver(RoundEnvironment roundEnvironment,
125                ProcessingEnvironment processingEnvironment,
126                BindingBuildInfo buildInfo);
127    }
128}
129