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; 2328e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyarimport android.databinding.tool.util.L; 244df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyarimport android.databinding.tool.util.Preconditions; 25fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.writer.AnnotationJavaFileWriter; 264df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyarimport android.databinding.tool.writer.BRWriter; 27fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mountimport android.databinding.tool.writer.JavaFileWriter; 28a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 29a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport java.util.Arrays; 30a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport java.util.List; 31a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport java.util.Set; 32a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 33a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport javax.annotation.processing.AbstractProcessor; 34a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport javax.annotation.processing.ProcessingEnvironment; 35a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport javax.annotation.processing.RoundEnvironment; 36a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport javax.annotation.processing.SupportedAnnotationTypes; 37a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport javax.lang.model.SourceVersion; 38a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyarimport javax.lang.model.element.TypeElement; 3928e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyarimport javax.xml.bind.JAXBException; 40a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 41a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar@SupportedAnnotationTypes({ 42fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount "android.databinding.BindingAdapter", 43fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount "android.databinding.Untaggable", 44fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount "android.databinding.BindingMethods", 45fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount "android.databinding.BindingConversion", 46fead9ca09b117136b35bc5bf137340a754f9edddGeorge Mount "android.databinding.BindingBuildInfo"} 47a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar) 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) { 6528e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar try { 6628e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar done = step.runStep(roundEnv, processingEnv, buildInfo) && done; 6728e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar } catch (JAXBException e) { 6828e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar L.e(e, "Exception while handling step %s", step); 6928e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar } 70a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 71a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar if (roundEnv.processingOver()) { 72a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar for (ProcessingStep step : mProcessingSteps) { 73a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar step.onProcessingOver(roundEnv, processingEnv, buildInfo); 74a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 75a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 76731b74f7f44e67312a1fc4161c4e0aae221b2417Yigit Boyar Scope.assertNoError(); 77a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return done; 78a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 79a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 809784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar @Override 819784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar public SourceVersion getSupportedSourceVersion() { 829784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar return SourceVersion.latest(); 839784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar } 849784c9aaedeb863018f5fcaa0a598e8e2f8ed2f3Yigit Boyar 85a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private void initProcessingSteps() { 864df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar final ProcessBindable processBindable = new ProcessBindable(); 87a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar mProcessingSteps = Arrays.asList( 88a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar new ProcessMethodAdapters(), 894df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar new ProcessExpressions(), 9061630faa88ee4817834d47294a0e17f19d8e1c51George Mount processBindable 91a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar ); 924df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar Callback dataBinderWriterCallback = new Callback() { 934df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar CompilerChef mChef; 944df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar BRWriter mBRWriter; 954df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar boolean mLibraryProject; 964df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar int mMinSdk; 974df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar 984df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar @Override 994df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar public void onChefReady(CompilerChef chef, boolean libraryProject, int minSdk) { 1004df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar Preconditions.checkNull(mChef, "Cannot set compiler chef twice"); 1014df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar chef.addBRVariables(processBindable); 1024df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar mChef = chef; 1034df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar mLibraryProject = libraryProject; 1044df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar mMinSdk = minSdk; 1054df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar considerWritingMapper(); 10699d74030fe5856572bd4b569bc04d2a11258f202George Mount mChef.writeDynamicUtil(); 1074df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar } 1084df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar 1094df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar private void considerWritingMapper() { 1104df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar if (mLibraryProject || mChef == null || mBRWriter == null) { 1114df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar return; 1124df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar } 1134df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar mChef.writeDataBinderMapper(mMinSdk, mBRWriter); 1144df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar } 1154df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar 1164df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar @Override 1174df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar public void onBrWriterReady(BRWriter brWriter) { 1184df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar Preconditions.checkNull(mBRWriter, "Cannot set br writer twice"); 1194df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar mBRWriter = brWriter; 1204df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar considerWritingMapper(); 1214df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar } 1224df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar }; 123a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar AnnotationJavaFileWriter javaFileWriter = new AnnotationJavaFileWriter(processingEnv); 124a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar for (ProcessingStep step : mProcessingSteps) { 125a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar step.mJavaFileWriter = javaFileWriter; 1264df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar step.mCallback = dataBinderWriterCallback; 127a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 128a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 129a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 130a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar @Override 131a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar public synchronized void init(ProcessingEnvironment processingEnv) { 132a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar super.init(processingEnv); 133a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar ModelAnalyzer.setProcessingEnvironment(processingEnv); 134a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 135a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 136a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar /** 137a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * To ensure execution order and binding build information, we use processing steps. 138a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar */ 139a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar public abstract static class ProcessingStep { 140a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private boolean mDone; 141a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private JavaFileWriter mJavaFileWriter; 1424df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar protected Callback mCallback; 143a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 144a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar protected JavaFileWriter getWriter() { 145a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return mJavaFileWriter; 146a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 147a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 148a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar private boolean runStep(RoundEnvironment roundEnvironment, 149a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar ProcessingEnvironment processingEnvironment, 15028e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar BindingBuildInfo buildInfo) throws JAXBException { 151a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar if (mDone) { 152a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return true; 153a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 154a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar mDone = onHandleStep(roundEnvironment, processingEnvironment, buildInfo); 155a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar return mDone; 156a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 157a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 158a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar /** 159a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * Invoked in each annotation processing step. 160a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * 161a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * @return True if it is done and should never be invoked again. 162a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar */ 163a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar abstract public boolean onHandleStep(RoundEnvironment roundEnvironment, 164a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar ProcessingEnvironment processingEnvironment, 16528e7064d455e2ef9da31c817dfc05ec7405c60dfYigit Boyar BindingBuildInfo buildInfo) throws JAXBException; 166a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar 167a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar /** 168a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * Invoked when processing is done. A good place to generate the output if the 169a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar * processor requires multiple steps. 170a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar */ 171a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar abstract public void onProcessingOver(RoundEnvironment roundEnvironment, 172a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar ProcessingEnvironment processingEnvironment, 173a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar BindingBuildInfo buildInfo); 174a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar } 1754df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar 1764df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar interface Callback { 1774df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar void onChefReady(CompilerChef chef, boolean libraryProject, int minSdk); 1784df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar void onBrWriterReady(BRWriter brWriter); 1794df4ba38a62b791bbbc25e923efe8d9c2f9a52e9Yigit Boyar } 180a6e4583962e19e8e93b4ca3f9fe3d34560b6d96cYigit Boyar} 181