1a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar/* 2a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * Copyright (C) 2015 The Android Open Source Project 3a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * 4a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 5a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * you may not use this file except in compliance with the License. 6a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * You may obtain a copy of the License at 7a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * 8a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 9a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * 10a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * Unless required by applicable law or agreed to in writing, software 11a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 12a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * See the License for the specific language governing permissions and 14a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * limitations under the License. 15a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar */ 16a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 17fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountpackage android.databinding.annotationprocessor; 18a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 19fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.BindingBuildInfo; 204df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyarimport android.databinding.tool.CompilerChef; 21731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyarimport android.databinding.tool.processing.Scope; 22fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.reflection.ModelAnalyzer; 234df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyarimport android.databinding.tool.util.Preconditions; 24fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.writer.AnnotationJavaFileWriter; 254df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyarimport android.databinding.tool.writer.BRWriter; 26fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.writer.JavaFileWriter; 27a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 28a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport java.util.Arrays; 29a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport java.util.List; 30a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport java.util.Set; 31a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 32a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport javax.annotation.processing.AbstractProcessor; 33a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport javax.annotation.processing.ProcessingEnvironment; 34a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport javax.annotation.processing.RoundEnvironment; 35a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport javax.annotation.processing.SupportedAnnotationTypes; 36a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport javax.annotation.processing.SupportedSourceVersion; 37a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport javax.lang.model.SourceVersion; 38a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport javax.lang.model.element.TypeElement; 39a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 40a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar@SupportedAnnotationTypes({ 41fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount "android.databinding.BindingAdapter", 42fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount "android.databinding.Untaggable", 43fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount "android.databinding.BindingMethods", 44fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount "android.databinding.BindingConversion", 45fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount "android.databinding.BindingBuildInfo"} 46a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar) 47a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar@SupportedSourceVersion(SourceVersion.RELEASE_7) 48a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar/** 49a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * Parent annotation processor that dispatches sub steps to ensure execution order. 50a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * Use initProcessingSteps to add a new step. 51a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar */ 52a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarpublic class ProcessDataBinding extends AbstractProcessor { 53a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private List<ProcessingStep> mProcessingSteps; 54a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar @Override 55a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 56a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar if (mProcessingSteps == null) { 57a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar initProcessingSteps(); 58a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 59a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar final BindingBuildInfo buildInfo = BuildInfoUtil.load(roundEnv); 60a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar if (buildInfo == null) { 61a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return false; 62a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 63a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar boolean done = true; 64a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar for (ProcessingStep step : mProcessingSteps) { 65a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar done = step.runStep(roundEnv, processingEnv, buildInfo) && done; 66a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 67a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar if (roundEnv.processingOver()) { 68a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar for (ProcessingStep step : mProcessingSteps) { 69a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar step.onProcessingOver(roundEnv, processingEnv, buildInfo); 70a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 71a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 72731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar Scope.assertNoError(); 73a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return done; 74a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 75a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 76a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private void initProcessingSteps() { 774df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar final ProcessBindable processBindable = new ProcessBindable(); 78a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar mProcessingSteps = Arrays.asList( 79a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar new ProcessMethodAdapters(), 804df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar new ProcessExpressions(), 8161630faa88ee4817834d47294a0e17f19d8e1c51George Mount processBindable 82a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar ); 834df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar Callback dataBinderWriterCallback = new Callback() { 844df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar CompilerChef mChef; 854df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar BRWriter mBRWriter; 864df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar boolean mLibraryProject; 874df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar int mMinSdk; 884df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar 894df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar @Override 904df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar public void onChefReady(CompilerChef chef, boolean libraryProject, int minSdk) { 914df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar Preconditions.checkNull(mChef, "Cannot set compiler chef twice"); 924df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar chef.addBRVariables(processBindable); 934df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar mChef = chef; 944df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar mLibraryProject = libraryProject; 954df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar mMinSdk = minSdk; 964df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar considerWritingMapper(); 974df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar } 984df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar 994df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar private void considerWritingMapper() { 1004df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar if (mLibraryProject || mChef == null || mBRWriter == null) { 1014df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar return; 1024df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar } 1034df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar mChef.writeDataBinderMapper(mMinSdk, mBRWriter); 1044df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar } 1054df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar 1064df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar @Override 1074df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar public void onBrWriterReady(BRWriter brWriter) { 1084df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar Preconditions.checkNull(mBRWriter, "Cannot set br writer twice"); 1094df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar mBRWriter = brWriter; 1104df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar considerWritingMapper(); 1114df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar } 1124df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar }; 113a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar AnnotationJavaFileWriter javaFileWriter = new AnnotationJavaFileWriter(processingEnv); 114a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar for (ProcessingStep step : mProcessingSteps) { 115a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar step.mJavaFileWriter = javaFileWriter; 1164df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar step.mCallback = dataBinderWriterCallback; 117a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 118a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 119a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 120a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar @Override 121a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar public synchronized void init(ProcessingEnvironment processingEnv) { 122a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar super.init(processingEnv); 123a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar ModelAnalyzer.setProcessingEnvironment(processingEnv); 124a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 125a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 126a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar /** 127a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * To ensure execution order and binding build information, we use processing steps. 128a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar */ 129a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar public abstract static class ProcessingStep { 130a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private boolean mDone; 131a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private JavaFileWriter mJavaFileWriter; 1324df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar protected Callback mCallback; 133a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 134a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar protected JavaFileWriter getWriter() { 135a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return mJavaFileWriter; 136a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 137a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 138a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private boolean runStep(RoundEnvironment roundEnvironment, 139a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar ProcessingEnvironment processingEnvironment, 140a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar BindingBuildInfo buildInfo) { 141a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar if (mDone) { 142a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return true; 143a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 144a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar mDone = onHandleStep(roundEnvironment, processingEnvironment, buildInfo); 145a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return mDone; 146a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 147a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 148a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar /** 149a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * Invoked in each annotation processing step. 150a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * 151a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * @return True if it is done and should never be invoked again. 152a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar */ 153a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar abstract public boolean onHandleStep(RoundEnvironment roundEnvironment, 154a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar ProcessingEnvironment processingEnvironment, 155a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar BindingBuildInfo buildInfo); 156a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 157a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar /** 158a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * Invoked when processing is done. A good place to generate the output if the 159a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * processor requires multiple steps. 160a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar */ 161a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar abstract public void onProcessingOver(RoundEnvironment roundEnvironment, 162a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar ProcessingEnvironment processingEnvironment, 163a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar BindingBuildInfo buildInfo); 164a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 1654df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar 1664df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar interface Callback { 1674df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar void onChefReady(CompilerChef chef, boolean libraryProject, int minSdk); 1684df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar void onBrWriterReady(BRWriter brWriter); 1694df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar } 170a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar} 171