diff options
author | Yigit Boyar <yboyar@google.com> | 2018-01-24 17:33:32 -0800 |
---|---|---|
committer | Yigit Boyar <yboyar@google.com> | 2018-01-25 09:51:43 -0800 |
commit | c769d69b744d69f6de0a0a952add174f6e98a9b1 (patch) | |
tree | 6942b8153f2d88e543795b6937193def4fc058a1 /compiler/src/main/java/android/databinding | |
parent | 8b97b676dbb5d496f25ba247458f24cd78740c3e (diff) | |
download | data-binding-c769d69b744d69f6de0a0a952add174f6e98a9b1.tar.gz |
Hacky solution to clear singletons from data binding.
Bug: 68339615
Test: existing tests pass
Change-Id: I8a9004bc7b2e7c9cfe3b0ad914c721d77069d46e
Diffstat (limited to 'compiler/src/main/java/android/databinding')
20 files changed, 218 insertions, 118 deletions
diff --git a/compiler/src/main/java/android/databinding/annotationprocessor/ProcessBindable.java b/compiler/src/main/java/android/databinding/annotationprocessor/ProcessBindable.java index 6f22e0d4..15197eb7 100644 --- a/compiler/src/main/java/android/databinding/annotationprocessor/ProcessBindable.java +++ b/compiler/src/main/java/android/databinding/annotationprocessor/ProcessBindable.java @@ -88,7 +88,7 @@ public class ProcessBindable extends ProcessDataBinding.ProcessingStep implement // We'll get them later when we do the messages } } - GenerationalClassUtil.writeIntermediateFile(mProperties.getPackage(), + GenerationalClassUtil.get().writeIntermediateFile(mProperties.getPackage(), createIntermediateFileName(mProperties.getPackage()), mProperties); generateBRClasses(args, mProperties.getPackage()); } @@ -248,7 +248,7 @@ public class ProcessBindable extends ProcessDataBinding.ProcessingStep implement @SuppressWarnings("CodeBlock2Expr") private Collection<Intermediate> loadPreviousBRFiles(String... excludePackages) { - List<Intermediate> brFiles = GenerationalClassUtil + List<Intermediate> brFiles = GenerationalClassUtil.get() .loadObjects(GenerationalClassUtil.ExtensionFilter.BR); Set<String> excludeMap = Sets.newHashSet(excludePackages); // dedupe diff --git a/compiler/src/main/java/android/databinding/annotationprocessor/ProcessDataBinding.java b/compiler/src/main/java/android/databinding/annotationprocessor/ProcessDataBinding.java index d0dd5433..0a9863e2 100644 --- a/compiler/src/main/java/android/databinding/annotationprocessor/ProcessDataBinding.java +++ b/compiler/src/main/java/android/databinding/annotationprocessor/ProcessDataBinding.java @@ -17,6 +17,7 @@ package android.databinding.annotationprocessor; import android.databinding.tool.CompilerChef; +import android.databinding.tool.Context; import android.databinding.tool.DataBindingCompilerArgs; import android.databinding.tool.processing.Scope; import android.databinding.tool.processing.ScopedException; @@ -60,6 +61,16 @@ public class ProcessDataBinding extends AbstractProcessor { private DataBindingCompilerArgs mCompilerArgs; @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { + try { + return doProcess(roundEnv); + } finally { + if (roundEnv.processingOver()) { + Context.fullClear(processingEnv); + } + } + } + + private boolean doProcess(RoundEnvironment roundEnv) { if (mProcessingSteps == null) { readArguments(); initProcessingSteps(); @@ -73,6 +84,7 @@ public class ProcessDataBinding extends AbstractProcessor { return false; } boolean done = true; + Context.init(processingEnv, mCompilerArgs); for (ProcessingStep step : mProcessingSteps) { try { done = step.runStep(roundEnv, processingEnv, mCompilerArgs) && done; @@ -86,7 +98,6 @@ public class ProcessDataBinding extends AbstractProcessor { } } if (roundEnv.processingOver()) { - L.flushMessages(); Scope.assertNoError(); } return done; @@ -155,7 +166,7 @@ public class ProcessDataBinding extends AbstractProcessor { * use this instead of init method so that we won't become a problem when data binding happens * to be in annotation processor classpath by chance */ - public synchronized void readArguments() { + private synchronized void readArguments() { try { mCompilerArgs = DataBindingCompilerArgs .readFromOptions(processingEnv.getOptions()); @@ -168,8 +179,6 @@ public class ProcessDataBinding extends AbstractProcessor { throw new RuntimeException("Failed to parse data binding compiler options. Params:\n" + allParam, t); } - GenerationalClassUtil.init(mCompilerArgs); - ModelAnalyzer.setProcessingEnvironment(processingEnv); } @Override diff --git a/compiler/src/main/java/android/databinding/annotationprocessor/ProcessExpressions.java b/compiler/src/main/java/android/databinding/annotationprocessor/ProcessExpressions.java index 90a440ab..6ff47705 100644 --- a/compiler/src/main/java/android/databinding/annotationprocessor/ProcessExpressions.java +++ b/compiler/src/main/java/android/databinding/annotationprocessor/ProcessExpressions.java @@ -68,7 +68,6 @@ public class ProcessExpressions extends ProcessDataBinding.ProcessingStep { throws JAXBException { try { ResourceBundle resourceBundle; - SdkUtil.initialize(args.getMinApi(), new File(args.getSdkDir())); resourceBundle = new ResourceBundle(args.getModulePackage()); final List<IntermediateV2> intermediateList; if (args.isEnableV2()) { @@ -120,7 +119,7 @@ public class ProcessExpressions extends ProcessDataBinding.ProcessingStep { } private List<IntermediateV2> loadDependencyIntermediates() { - final List<Intermediate> original = GenerationalClassUtil.loadObjects( + final List<Intermediate> original = GenerationalClassUtil.get().loadObjects( GenerationalClassUtil.ExtensionFilter.LAYOUT); final List<IntermediateV2> upgraded = new ArrayList<IntermediateV2>(original.size()); for (Intermediate intermediate : original) { @@ -136,7 +135,7 @@ public class ProcessExpressions extends ProcessDataBinding.ProcessingStep { private void saveIntermediate(ProcessingEnvironment processingEnvironment, DataBindingCompilerArgs args, IntermediateV2 intermediate) { - GenerationalClassUtil.writeIntermediateFile(args.getModulePackage(), + GenerationalClassUtil.get().writeIntermediateFile(args.getModulePackage(), args.getModulePackage() + GenerationalClassUtil.ExtensionFilter.LAYOUT.getExtension(), intermediate); diff --git a/compiler/src/main/java/android/databinding/annotationprocessor/ProcessMethodAdapters.java b/compiler/src/main/java/android/databinding/annotationprocessor/ProcessMethodAdapters.java index 2968e35c..4fcfca34 100644 --- a/compiler/src/main/java/android/databinding/annotationprocessor/ProcessMethodAdapters.java +++ b/compiler/src/main/java/android/databinding/annotationprocessor/ProcessMethodAdapters.java @@ -64,7 +64,7 @@ public class ProcessMethodAdapters extends ProcessDataBinding.ProcessingStep { final ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance(); Preconditions.checkNotNull(modelAnalyzer, "Model analyzer should be" + " initialized first"); - SetterStore store = SetterStore.get(modelAnalyzer); + SetterStore store = SetterStore.get(); clearIncrementalClasses(roundEnv, store); addBindingAdapters(roundEnv, processingEnvironment, store); diff --git a/compiler/src/main/java/android/databinding/tool/Binding.java b/compiler/src/main/java/android/databinding/tool/Binding.java index 467a4cad..fe222fdb 100644 --- a/compiler/src/main/java/android/databinding/tool/Binding.java +++ b/compiler/src/main/java/android/databinding/tool/Binding.java @@ -128,7 +128,7 @@ public class Binding implements LocationScopeProvider { ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance(); ModelClass viewStubProxy = modelAnalyzer. findClass("android.databinding.ViewStubProxy", null); - mSetterCall = SetterStore.get(modelAnalyzer).getSetterCall(mName, + mSetterCall = SetterStore.get().getSetterCall(mName, viewStubProxy, mExpr.getResolvedType(), mExpr.getModel().getImports()); } else if (isViewStubAttribute(mName)) { mSetterCall = new ViewStubDirectCall(mName, viewType, mExpr.getResolvedType(), @@ -141,7 +141,7 @@ public class Binding implements LocationScopeProvider { if (mExpr.getResolvedType().getObservableGetterName() != null) { // If it is an ObservableField, try with the contents of it first. Expr expr = mExpr.unwrapObservableField(); - mSetterCall = SetterStore.get(modelAnalyzer).getSetterCall(mName, + mSetterCall = SetterStore.get().getSetterCall(mName, viewType, expr.getResolvedType(), mExpr.getModel().getImports()); if (mSetterCall != null) { mExpr = expr; @@ -149,7 +149,7 @@ public class Binding implements LocationScopeProvider { } if (mSetterCall == null) { // Now try with the value object directly - mSetterCall = SetterStore.get(modelAnalyzer).getSetterCall(mName, + mSetterCall = SetterStore.get().getSetterCall(mName, viewType, mExpr.getResolvedType(), mExpr.getModel().getImports()); } } @@ -164,12 +164,12 @@ public class Binding implements LocationScopeProvider { SetterCall setterCall; ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance(); ModelClass objectParameter = modelAnalyzer.findClass(Object.class); - SetterStore setterStore = SetterStore.get(modelAnalyzer); + SetterStore setterStore = SetterStore.get(); if (viewType != null && viewType.extendsViewStub()) { if (isListenerAttribute(name)) { ModelClass viewStubProxy = modelAnalyzer. findClass("android.databinding.ViewStubProxy", null); - setterCall = SetterStore.get(modelAnalyzer).getSetterCall(name, + setterCall = SetterStore.get().getSetterCall(name, viewStubProxy, objectParameter, model.getImports()); } else if (isViewStubAttribute(name)) { setterCall = null; // view stub attrs are not callbacks @@ -317,7 +317,7 @@ public class Binding implements LocationScopeProvider { public ViewStubDirectCall(String name, ModelClass viewType, ModelClass resolvedType, Map<String, String> imports) { - mWrappedCall = SetterStore.get(ModelAnalyzer.getInstance()).getSetterCall(name, + mWrappedCall = SetterStore.get().getSetterCall(name, viewType, resolvedType, imports); if (mWrappedCall == null) { L.e("Cannot find the setter for attribute '%s' on %s with parameter type %s.", diff --git a/compiler/src/main/java/android/databinding/tool/BindingTarget.java b/compiler/src/main/java/android/databinding/tool/BindingTarget.java index 83c28b08..38dd7e84 100644 --- a/compiler/src/main/java/android/databinding/tool/BindingTarget.java +++ b/compiler/src/main/java/android/databinding/tool/BindingTarget.java @@ -55,7 +55,7 @@ public class BindingTarget implements LocationScopeProvider { } public void addBinding(String name, Expr expr) { - if (SetterStore.get(ModelAnalyzer.getInstance()).isTwoWayEventAttribute(name)) { + if (SetterStore.get().isTwoWayEventAttribute(name)) { L.e(ErrorMessages.TWO_WAY_EVENT_ATTRIBUTE, name); } mBindings.add(new Binding(this, name, expr)); @@ -122,7 +122,7 @@ public class BindingTarget implements LocationScopeProvider { } public boolean supportsTag() { - return !SetterStore.get(ModelAnalyzer.getInstance()) + return !SetterStore.get() .isUntaggable(mBundle.getFullClassName()); } @@ -194,7 +194,7 @@ public class BindingTarget implements LocationScopeProvider { */ public void resolveMultiSetters() { L.d("resolving multi setters for %s", getId()); - final SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance()); + final SetterStore setterStore = SetterStore.get(); String[] attributes = new String[mBindings.size()]; ModelClass[] types = new ModelClass[mBindings.size()]; boolean hasObservableFields = false; diff --git a/compiler/src/main/java/android/databinding/tool/Context.kt b/compiler/src/main/java/android/databinding/tool/Context.kt new file mode 100644 index 00000000..23d9f2a4 --- /dev/null +++ b/compiler/src/main/java/android/databinding/tool/Context.kt @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2018 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.databinding.tool + +import android.databinding.tool.reflection.ModelAnalyzer +import android.databinding.tool.reflection.SdkUtil +import android.databinding.tool.reflection.TypeUtil +import android.databinding.tool.reflection.annotation.AnnotationAnalyzer +import android.databinding.tool.reflection.annotation.AnnotationLogger +import android.databinding.tool.store.SetterStore +import android.databinding.tool.util.GenerationalClassUtil +import android.databinding.tool.util.L +import java.io.File +import javax.annotation.processing.ProcessingEnvironment + +/** + * Simple class to hold all singletons so that it is relatively easier to clean them. + * We cannot easily get rid of singletons w/o a bigger change so this is a middle ground where + * we can start clearing them from a central location. + * + * Singletons are expected to use this to keep their instances. + */ +object Context { + private val logger : AnnotationLogger = AnnotationLogger() + @JvmStatic + fun init(processingEnvironment: ProcessingEnvironment, + args : DataBindingCompilerArgs) { + generationalClassUtil = GenerationalClassUtil.create(args) + modelAnalyzer = AnnotationAnalyzer(processingEnvironment) + typeUtil = modelAnalyzer!!.createTypeUtil() + setterStore = SetterStore.create(modelAnalyzer, generationalClassUtil) + sdkUtil = SdkUtil.create(File(args.sdkDir), args.minApi) + L.setClient(logger) + } + + @JvmStatic + fun initForTests(modelAnayzer: ModelAnalyzer, sdkUtil: SdkUtil) { + this.modelAnalyzer = modelAnayzer + this.sdkUtil = sdkUtil + typeUtil = modelAnalyzer!!.createTypeUtil() + } + + @JvmStatic + var modelAnalyzer : ModelAnalyzer? = null + private set + + @JvmStatic + var setterStore : SetterStore? = null + private set + + @JvmStatic + var generationalClassUtil : GenerationalClassUtil? = null + private set + + @JvmStatic + var typeUtil : TypeUtil? = null + private set + + @JvmStatic + var sdkUtil : SdkUtil? = null + private set + + @JvmStatic + fun fullClear(processingEnvironment: ProcessingEnvironment) { + logger.flushMessages(processingEnvironment) + modelAnalyzer = null + setterStore = null + generationalClassUtil = null + typeUtil = null + sdkUtil = null + L.setClient(null) + } +} diff --git a/compiler/src/main/java/android/databinding/tool/InverseBinding.java b/compiler/src/main/java/android/databinding/tool/InverseBinding.java index a2960c71..86564886 100644 --- a/compiler/src/main/java/android/databinding/tool/InverseBinding.java +++ b/compiler/src/main/java/android/databinding/tool/InverseBinding.java @@ -105,7 +105,7 @@ public class InverseBinding implements LocationScopeProvider { Scope.enter(mTarget); Scope.enter(this); ModelClass viewType = mTarget.getResolvedType(); - final SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance()); + final SetterStore setterStore = SetterStore.get(); final ModelClass resolvedType = expr == null ? null : expr.getResolvedType(); mGetterCall = setterStore.getGetterCall(mName, viewType, resolvedType, expr.getModel().getImports()); diff --git a/compiler/src/main/java/android/databinding/tool/expr/FieldAccessExpr.java b/compiler/src/main/java/android/databinding/tool/expr/FieldAccessExpr.java index d51df2f3..7a41d30f 100644 --- a/compiler/src/main/java/android/databinding/tool/expr/FieldAccessExpr.java +++ b/compiler/src/main/java/android/databinding/tool/expr/FieldAccessExpr.java @@ -16,7 +16,6 @@ package android.databinding.tool.expr; -import android.databinding.Bindable; import android.databinding.tool.Binding; import android.databinding.tool.BindingTarget; import android.databinding.tool.InverseBinding; @@ -27,7 +26,6 @@ import android.databinding.tool.reflection.Callable; import android.databinding.tool.reflection.Callable.Type; import android.databinding.tool.reflection.ModelAnalyzer; import android.databinding.tool.reflection.ModelClass; -import android.databinding.tool.reflection.ModelField; import android.databinding.tool.store.SetterStore; import android.databinding.tool.store.SetterStore.BindingGetterCall; import android.databinding.tool.util.BrNameUtil; @@ -35,14 +33,11 @@ import android.databinding.tool.util.L; import android.databinding.tool.util.Preconditions; import android.databinding.tool.util.StringUtils; import android.databinding.tool.writer.KCode; - import com.google.common.collect.Lists; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; public class FieldAccessExpr extends MethodBaseExpr { // notification name for the field. Important when we map this to a method w/ different name @@ -343,7 +338,7 @@ public class FieldAccessExpr extends MethodBaseExpr { // There was no binding expression to bind to. This should be a two-way binding. // This is a synthesized two-way binding because we must capture the events from // the View and change the value when the target View's attribute changes. - final SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance()); + final SetterStore setterStore = SetterStore.get(); final ModelClass targetClass = expr.getResolvedType(); BindingGetterCall getter = setterStore.getGetterCall(mName, targetClass, null, null); if (getter == null) { diff --git a/compiler/src/main/java/android/databinding/tool/expr/MethodCallExpr.java b/compiler/src/main/java/android/databinding/tool/expr/MethodCallExpr.java index 371925c2..0029e9e9 100644 --- a/compiler/src/main/java/android/databinding/tool/expr/MethodCallExpr.java +++ b/compiler/src/main/java/android/databinding/tool/expr/MethodCallExpr.java @@ -36,7 +36,6 @@ import java.util.List; import static android.databinding.tool.reflection.Callable.DYNAMIC; import static android.databinding.tool.reflection.Callable.STATIC; - public class MethodCallExpr extends Expr { final String mName; Callable mGetter; @@ -267,7 +266,7 @@ public class MethodCallExpr extends Expr { @Override public String getInvertibleError() { - final SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance()); + final SetterStore setterStore = SetterStore.get(); getResolvedType(); // ensure mMethod has been set if (mMethod == null) { return "Could not find the method " + mName + " to inverse for two-way binding"; @@ -299,7 +298,7 @@ public class MethodCallExpr extends Expr { inverse.setUnwrapObservableFields(false); return inverse; } - SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance()); + SetterStore setterStore = SetterStore.get(); String methodName = setterStore.getInverseMethod(mMethod); List<Expr> theseArgs = getArgs(); List<Expr> args = new ArrayList<>(); diff --git a/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.java b/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.java index a6ecc5b7..e8be90db 100644 --- a/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.java +++ b/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.java @@ -15,6 +15,7 @@ */ package android.databinding.tool.reflection; +import android.databinding.tool.Context; import android.databinding.tool.reflection.annotation.AnnotationAnalyzer; import android.databinding.tool.util.L; import android.databinding.tool.util.Preconditions; @@ -94,14 +95,9 @@ public abstract class ModelAnalyzer { */ private Boolean mHasGeneratedAnnotation; - private static ModelAnalyzer sAnalyzer; private final Map<String, InjectedClass> mInjectedClasses = new HashMap<String, InjectedClass>(); - protected void setInstance(ModelAnalyzer analyzer) { - sAnalyzer = analyzer; - } - public ModelClass findCommonParentOf(ModelClass modelClass1, ModelClass modelClass2) { return findCommonParentOf(modelClass1, modelClass2, true); } @@ -136,16 +132,7 @@ public abstract class ModelAnalyzer { public abstract ModelClass loadPrimitive(String className); public static ModelAnalyzer getInstance() { - return sAnalyzer; - } - - public static void setProcessingEnvironment(ProcessingEnvironment processingEnvironment) { - if (sAnalyzer != null) { - throw new IllegalStateException("processing env is already created, you cannot " - + "change class loader after that"); - } - L.d("setting processing env to %s", processingEnvironment); - sAnalyzer = new AnnotationAnalyzer(processingEnvironment); + return Context.getModelAnalyzer(); } /** diff --git a/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.java b/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.java index d4a022af..b7920936 100644 --- a/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.java +++ b/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.java @@ -451,7 +451,7 @@ public abstract class ModelClass { * return 1. */ public int getMinApi() { - return SdkUtil.getMinApi(this); + return SdkUtil.get().getMinApi(this); } /** diff --git a/compiler/src/main/java/android/databinding/tool/reflection/SdkUtil.java b/compiler/src/main/java/android/databinding/tool/reflection/SdkUtil.java index 350dda51..d9a82d66 100644 --- a/compiler/src/main/java/android/databinding/tool/reflection/SdkUtil.java +++ b/compiler/src/main/java/android/databinding/tool/reflection/SdkUtil.java @@ -19,9 +19,12 @@ import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import android.databinding.tool.Context; import android.databinding.tool.util.L; import android.databinding.tool.util.Preconditions; +import com.android.annotations.VisibleForTesting; + import java.io.File; import java.io.InputStream; import java.util.HashMap; @@ -40,29 +43,37 @@ import javax.xml.xpath.XPathFactory; */ public class SdkUtil { - static ApiChecker sApiChecker; + private ApiChecker mApiChecker; + + private final int mMinSdk; + + public SdkUtil(ApiChecker mApiChecker, int mMinSdk) { + this.mApiChecker = mApiChecker; + this.mMinSdk = mMinSdk; + } - static int sMinSdk; + public static SdkUtil create(File sdkPath, int minSdk) { + ApiChecker checker = new ApiChecker(new File(sdkPath.getAbsolutePath() + + "/platform-tools/api/api-versions.xml")); + return new SdkUtil(checker, minSdk); + } - public static void initialize(int minSdk, File sdkPath) { - sMinSdk = minSdk; - sApiChecker = new ApiChecker(new File(sdkPath.getAbsolutePath() - + "/platform-tools/api/api-versions.xml")); - L.d("SdkUtil init, minSdk: %s", minSdk); + public static SdkUtil get() { + return Context.getSdkUtil(); } - public static int getMinApi(ModelClass modelClass) { - return sApiChecker.getMinApi(modelClass.getJniDescription(), null); + public int getMinApi(ModelClass modelClass) { + return mApiChecker.getMinApi(modelClass.getJniDescription(), null); } - public static int getMinApi(ModelMethod modelMethod) { + public int getMinApi(ModelMethod modelMethod) { ModelClass declaringClass = modelMethod.getDeclaringClass(); - Preconditions.checkNotNull(sApiChecker, "should've initialized api checker"); + Preconditions.checkNotNull(mApiChecker, "should've initialized api checker"); int minApi = Integer.MAX_VALUE; String methodDesc = modelMethod.getJniDescription(); while (declaringClass != null) { String classDesc = declaringClass.getJniDescription(); - int result = sApiChecker.getMinApi(classDesc, methodDesc); + int result = mApiChecker.getMinApi(classDesc, methodDesc); L.d("checking method api for %s, class:%s method:%s. result: %d", modelMethod.getName(), classDesc, methodDesc, result); if (result > 0) { @@ -76,7 +87,20 @@ public class SdkUtil { return minApi; } - static class ApiChecker { + public ApiChecker getApiChecker() { + return mApiChecker; + } + + public int getMinSdk() { + return mMinSdk; + } + + @VisibleForTesting + public void swapApiChecker(ApiChecker apiChecker) { + mApiChecker = apiChecker; + } + + public static class ApiChecker { private Map<String, Integer> mFullLookup; diff --git a/compiler/src/main/java/android/databinding/tool/reflection/TypeUtil.java b/compiler/src/main/java/android/databinding/tool/reflection/TypeUtil.java index 2fd1735d..1dcb435c 100644 --- a/compiler/src/main/java/android/databinding/tool/reflection/TypeUtil.java +++ b/compiler/src/main/java/android/databinding/tool/reflection/TypeUtil.java @@ -16,6 +16,8 @@ package android.databinding.tool.reflection; +import android.databinding.tool.Context; + public abstract class TypeUtil { public static final String BYTE = "B"; @@ -42,8 +44,6 @@ public abstract class TypeUtil { public static final String CLASS_SUFFIX = ";"; - private static TypeUtil sInstance; - abstract public String getDescription(ModelClass modelClass); abstract public String getDescription(ModelMethod modelMethod); @@ -83,9 +83,6 @@ public abstract class TypeUtil { } public static TypeUtil getInstance() { - if (sInstance == null) { - sInstance = ModelAnalyzer.getInstance().createTypeUtil(); - } - return sInstance; + return Context.getTypeUtil(); } } diff --git a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationAnalyzer.java b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationAnalyzer.java index 6357e9b9..115fb442 100644 --- a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationAnalyzer.java +++ b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationAnalyzer.java @@ -52,8 +52,6 @@ public class AnnotationAnalyzer extends ModelAnalyzer { public AnnotationAnalyzer(ProcessingEnvironment processingEnvironment) { mProcessingEnv = processingEnvironment; - setInstance(this); - L.setClient(new AnnotationLogger(processingEnvironment)); } public static AnnotationAnalyzer get() { diff --git a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationLogger.java b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationLogger.java index 4501e519..df054c01 100644 --- a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationLogger.java +++ b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationLogger.java @@ -35,17 +35,12 @@ import javax.tools.Diagnostic; * Messager and then writes them all out when flushMessages() is called. Elements * are kept in a round-independent format so that the messages can be logged * independently from the annotation processing round in which they were created. - * {@link #flushMessages()} should be called when all rounds are over so that + * {@link #flushMessages(ProcessingEnvironment)} should be called when all rounds are over so that * superfluous errors aren't generated. */ -class AnnotationLogger implements L.Client { - private final ProcessingEnvironment mProcessingEnvironment; +public class AnnotationLogger implements L.Client { private final ArrayList<Message> mMessages = new ArrayList<>(); - AnnotationLogger(ProcessingEnvironment processingEnvironment) { - mProcessingEnvironment = processingEnvironment; - } - @Override public void printMessage(Diagnostic.Kind kind, String message, Element element) { ElementPath elementPath = null; @@ -59,13 +54,12 @@ class AnnotationLogger implements L.Client { } } - @Override - public void flushMessages() { - Messager messager = mProcessingEnvironment.getMessager(); + public void flushMessages(ProcessingEnvironment processingEnvironment) { + Messager messager = processingEnvironment.getMessager(); synchronized (mMessages) { for (Message message : mMessages) { if (message.element != null) { - Element element = message.element.toElement(mProcessingEnvironment); + Element element = message.element.toElement(processingEnvironment); messager.printMessage(message.kind, message.message, element); } else { messager.printMessage(message.kind, message.message); diff --git a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationMethod.java b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationMethod.java index e9f59d82..dfff98bb 100644 --- a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationMethod.java +++ b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationMethod.java @@ -159,7 +159,7 @@ class AnnotationMethod extends ModelMethod { @Override public int getMinApi() { if (mApiLevel == -1) { - mApiLevel = SdkUtil.getMinApi(this); + mApiLevel = SdkUtil.get().getMinApi(this); } return mApiLevel; } diff --git a/compiler/src/main/java/android/databinding/tool/store/SetterStore.java b/compiler/src/main/java/android/databinding/tool/store/SetterStore.java index c73c424f..d427a698 100644 --- a/compiler/src/main/java/android/databinding/tool/store/SetterStore.java +++ b/compiler/src/main/java/android/databinding/tool/store/SetterStore.java @@ -16,6 +16,7 @@ package android.databinding.tool.store; import android.databinding.InverseBindingListener; +import android.databinding.tool.Context; import android.databinding.tool.processing.ErrorMessages; import android.databinding.tool.reflection.ModelAnalyzer; import android.databinding.tool.reflection.ModelClass; @@ -58,7 +59,6 @@ import javax.lang.model.util.Types; public class SetterStore { private static final int ASSIGNABLE_CONVERSION = 1; - private static SetterStore sStore; private final IntermediateV3 mStore; private final ModelAnalyzer mClassAnalyzer; @@ -170,16 +170,19 @@ public class SetterStore { } } - public static SetterStore get(ModelAnalyzer modelAnalyzer) { - if (sStore == null) { - sStore = load(modelAnalyzer); - } - return sStore; + public static SetterStore get() { + return Context.getSetterStore(); + } + + public static SetterStore create(ModelAnalyzer modelAnalyzer, + GenerationalClassUtil generationalClassUtil) { + return load(modelAnalyzer, generationalClassUtil); } - private static SetterStore load(ModelAnalyzer modelAnalyzer) { + private static SetterStore load(ModelAnalyzer modelAnalyzer, + GenerationalClassUtil generationalClassUtil) { IntermediateV3 store = new IntermediateV3(); - List<Intermediate> previousStores = GenerationalClassUtil + List<Intermediate> previousStores = GenerationalClassUtil.get() .loadObjects(GenerationalClassUtil.ExtensionFilter.SETTER_STORE); for (Intermediate intermediate : previousStores) { merge(store, intermediate); @@ -485,7 +488,7 @@ public class SetterStore { public void write(String projectPackage, ProcessingEnvironment processingEnvironment) throws IOException { - GenerationalClassUtil.writeIntermediateFile(projectPackage, projectPackage + + GenerationalClassUtil.get().writeIntermediateFile(projectPackage, projectPackage + GenerationalClassUtil.ExtensionFilter.SETTER_STORE.getExtension(), mStore); } @@ -1187,7 +1190,7 @@ public class SetterStore { if (adapter.isStatic) { sb.append(adapter.type); } else { - final SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance()); + final SetterStore setterStore = SetterStore.get(); final String binderCall = setterStore.getBindingAdapterCall(adapter.type); sb.append(componentExpression).append('.').append(binderCall); } diff --git a/compiler/src/main/java/android/databinding/tool/util/GenerationalClassUtil.java b/compiler/src/main/java/android/databinding/tool/util/GenerationalClassUtil.java index b6e97c56..6a1319f2 100644 --- a/compiler/src/main/java/android/databinding/tool/util/GenerationalClassUtil.java +++ b/compiler/src/main/java/android/databinding/tool/util/GenerationalClassUtil.java @@ -17,6 +17,7 @@ package android.databinding.tool.util; import android.databinding.annotationprocessor.ProcessExpressions; +import android.databinding.tool.Context; import android.databinding.tool.DataBindingBuilder; import android.databinding.tool.DataBindingCompilerArgs; @@ -43,53 +44,61 @@ import java.util.List; * and their extraction later on. */ public class GenerationalClassUtil { - private static List[] sCache = null; + private List[] mCache = null; @Nullable - private static List<File> sInputDirs = new ArrayList<>(); + private List<File> mInputDirs; @Nullable - private static File sIncrementalOutDir; + private File mIncrementalOutDir; - private static ExtensionFilter[] sEnabledExtensions; + private ExtensionFilter[] mEnabledExtensions; - public static void init(DataBindingCompilerArgs args) { + public static GenerationalClassUtil create(DataBindingCompilerArgs args) { + return new GenerationalClassUtil(args); + } + + private GenerationalClassUtil(DataBindingCompilerArgs args) { if (args.isEnableV2()) { - sEnabledExtensions = new ExtensionFilter[]{ExtensionFilter.BR, + mEnabledExtensions = new ExtensionFilter[]{ExtensionFilter.BR, ExtensionFilter.SETTER_STORE}; } else { - sEnabledExtensions = new ExtensionFilter[]{ExtensionFilter.BR, ExtensionFilter.LAYOUT, + mEnabledExtensions = new ExtensionFilter[]{ExtensionFilter.BR, ExtensionFilter.LAYOUT, ExtensionFilter.SETTER_STORE}; } if (StringUtils.isNotBlank(args.getAarOutFolder())) { - sIncrementalOutDir = new File(args.getAarOutFolder(), + mIncrementalOutDir = new File(args.getAarOutFolder(), DataBindingBuilder.INCREMENTAL_BIN_AAR_DIR); } else { - sIncrementalOutDir = null; + mIncrementalOutDir = null; } - sInputDirs = new ArrayList<>(); + mInputDirs = new ArrayList<>(); if (StringUtils.isNotBlank(args.getBuildFolder())) { - sInputDirs.add(new File(args.getBuildFolder(), + mInputDirs.add(new File(args.getBuildFolder(), DataBindingBuilder.ARTIFACT_FILES_DIR_FROM_LIBS)); } } - public static <T extends Serializable> List<T> loadObjects(ExtensionFilter filter) { - if (sCache == null) { + public static GenerationalClassUtil get() { + return Context.getGenerationalClassUtil(); + } + + public <T extends Serializable> List<T> loadObjects(ExtensionFilter filter) { + if (mCache == null) { buildCache(); } - List result = sCache[filter.ordinal()]; + List result = mCache[filter.ordinal()]; Preconditions.checkNotNull(result, "Invalid filter " + filter); //noinspection unchecked return result; } - private static void buildCache() { + private void buildCache() { L.d("building generational class cache"); - sCache = new List[ExtensionFilter.values().length]; - for (ExtensionFilter filter : sEnabledExtensions) { - sCache[filter.ordinal()] = new ArrayList(); + mCache = new List[ExtensionFilter.values().length]; + for (ExtensionFilter filter : mEnabledExtensions) { + mCache[filter.ordinal()] = new ArrayList(); } loadFromBuildInfo(); } @@ -105,17 +114,17 @@ public class GenerationalClassUtil { * This is a backward compatibility measure and should eventually be phased out after we move * to an aar based information retrieval model. */ - private static void loadFromBuildInfo() { - sInputDirs.forEach(GenerationalClassUtil::loadFromDirectory); + private void loadFromBuildInfo() { + mInputDirs.forEach(this::loadFromDirectory); } - private static void loadFromDirectory(File directory) { + private void loadFromDirectory(File directory) { if (directory == null || !directory.canRead() || !directory.isDirectory()) { return; } for (File file : FileUtils.listFiles(directory, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE)) { - for (ExtensionFilter filter : sEnabledExtensions) { + for (ExtensionFilter filter : mEnabledExtensions) { if (filter.accept(file.getName())) { InputStream inputStream = null; try { @@ -123,7 +132,7 @@ public class GenerationalClassUtil { Serializable item = fromInputStream(inputStream); if (item != null) { //noinspection unchecked - sCache[filter.ordinal()].add(item); + mCache[filter.ordinal()].add(item); L.d("loaded item %s from file", item); } } catch (IOException e) { @@ -139,24 +148,24 @@ public class GenerationalClassUtil { } } - private static Serializable fromInputStream(InputStream inputStream) + private Serializable fromInputStream(InputStream inputStream) throws IOException, ClassNotFoundException { ObjectInputStream in = new IgnoreSerialIdObjectInputStream(inputStream); return (Serializable) in.readObject(); } - public static void writeIntermediateFile(String packageName, String fileName, + public void writeIntermediateFile(String packageName, String fileName, Serializable object) { ObjectOutputStream oos = null; OutputStream ios = null; try { try { - Preconditions.checkNotNull(sIncrementalOutDir, "incremental out directory should be" + Preconditions.checkNotNull(mIncrementalOutDir, "incremental out directory should be" + " set to aar output directory."); //noinspection ResultOfMethodCallIgnored - sIncrementalOutDir.mkdirs(); - File out = new File(sIncrementalOutDir, packageName + "-" + fileName); + mIncrementalOutDir.mkdirs(); + File out = new File(mIncrementalOutDir, packageName + "-" + fileName); ios = new FileOutputStream(out); oos = new ObjectOutputStream(ios); oos.writeObject(object); diff --git a/compiler/src/main/java/android/databinding/tool/writer/ComponentWriter.java b/compiler/src/main/java/android/databinding/tool/writer/ComponentWriter.java index e7af414e..f2a647f1 100644 --- a/compiler/src/main/java/android/databinding/tool/writer/ComponentWriter.java +++ b/compiler/src/main/java/android/databinding/tool/writer/ComponentWriter.java @@ -15,7 +15,6 @@ */ package android.databinding.tool.writer; -import android.databinding.tool.reflection.ModelAnalyzer; import android.databinding.tool.store.SetterStore; import java.util.List; @@ -34,7 +33,7 @@ public class ComponentWriter { final StringBuilder builder = new StringBuilder(); builder.append("package android.databinding;\n\n"); builder.append("public interface DataBindingComponent {\n"); - final SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance()); + final SetterStore setterStore = SetterStore.get(); Map<String, List<String>> bindingAdapters = setterStore.getComponentBindingAdapters(); for (final String simpleName : bindingAdapters.keySet()) { final List<String> classes = bindingAdapters.get(simpleName); |