summaryrefslogtreecommitdiff
path: root/compiler/src/main/java/android/databinding
diff options
context:
space:
mode:
authorYigit Boyar <yboyar@google.com>2017-11-21 15:09:38 -0800
committerYigit Boyar <yboyar@google.com>2017-12-01 11:21:43 -0800
commit88d7ed6b87dd1165935e134fa1e9b4dd7f7be9f5 (patch)
tree65b1848a4d6e25442db60ad6d07215e115afee36 /compiler/src/main/java/android/databinding
parent13fb2f2e748e4726486b874b785b9d2f8ddbb423 (diff)
downloaddata-binding-88d7ed6b87dd1165935e134fa1e9b4dd7f7be9f5.tar.gz
Keep generated binding codes in libraries
This CL changes data binding to not strip binding code that is generated for libraries. This will allow data binding to be more incremental and only generate binding code for the current app/module. Generated DataBindingMapper and BR classes are still stripped as they require final R class and/or final list of BR classes. Bug: 68392907 Test: existing tests pass Change-Id: I39c8c25b90ec58a8b452e34310b57acc4b77c1d1
Diffstat (limited to 'compiler/src/main/java/android/databinding')
-rw-r--r--compiler/src/main/java/android/databinding/annotationprocessor/ProcessBindable.java5
-rw-r--r--compiler/src/main/java/android/databinding/annotationprocessor/ProcessExpressions.java50
-rw-r--r--compiler/src/main/java/android/databinding/tool/CallbackWrapper.java11
-rw-r--r--compiler/src/main/java/android/databinding/tool/CompilerChef.java48
-rw-r--r--compiler/src/main/java/android/databinding/tool/DataBinder.java44
-rw-r--r--compiler/src/main/java/android/databinding/tool/LayoutBinder.java9
-rw-r--r--compiler/src/main/java/android/databinding/tool/expr/CallbackExprModel.java1
-rw-r--r--compiler/src/main/java/android/databinding/tool/expr/ExprModel.java10
-rw-r--r--compiler/src/main/java/android/databinding/tool/util/GenerationalClassUtil.java17
9 files changed, 146 insertions, 49 deletions
diff --git a/compiler/src/main/java/android/databinding/annotationprocessor/ProcessBindable.java b/compiler/src/main/java/android/databinding/annotationprocessor/ProcessBindable.java
index 96a8c765..4814b2f1 100644
--- a/compiler/src/main/java/android/databinding/annotationprocessor/ProcessBindable.java
+++ b/compiler/src/main/java/android/databinding/annotationprocessor/ProcessBindable.java
@@ -127,10 +127,7 @@ public class ProcessBindable extends ProcessDataBinding.ProcessingStep implement
// bazel has duplicate package names so we need to avoid overwriting BR files.
writer.writeToFile(pkg + ".BR", brWriter.write(pkg));
written.add(pkg);
- // Generate BR files for dependencies unless we are compiling a test variant of an app
- // and it is not enabled for tests.
- if (!(compilerArgs.isApp() && compilerArgs.isTestVariant()
- && !compilerArgs.isEnabledForTests())) {
+ if (!compilerArgs.isTestVariant() || compilerArgs.isLibrary()) {
// Generate BR for all previous packages.
for (Intermediate intermediate : previousIntermediates) {
if (written.add(intermediate.getPackage())) {
diff --git a/compiler/src/main/java/android/databinding/annotationprocessor/ProcessExpressions.java b/compiler/src/main/java/android/databinding/annotationprocessor/ProcessExpressions.java
index b874db55..90a440ab 100644
--- a/compiler/src/main/java/android/databinding/annotationprocessor/ProcessExpressions.java
+++ b/compiler/src/main/java/android/databinding/annotationprocessor/ProcessExpressions.java
@@ -17,10 +17,12 @@
package android.databinding.annotationprocessor;
import android.databinding.tool.CompilerChef;
-import android.databinding.tool.DataBindingBuilder;
import android.databinding.tool.DataBindingCompilerArgs;
import android.databinding.tool.LayoutXmlProcessor;
+import android.databinding.tool.processing.Scope;
+import android.databinding.tool.processing.ScopedException;
import android.databinding.tool.reflection.SdkUtil;
+import android.databinding.tool.store.GenClassInfoLog;
import android.databinding.tool.store.ResourceBundle;
import android.databinding.tool.util.GenerationalClassUtil;
import android.databinding.tool.util.L;
@@ -40,6 +42,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
@@ -67,25 +70,41 @@ public class ProcessExpressions extends ProcessDataBinding.ProcessingStep {
ResourceBundle resourceBundle;
SdkUtil.initialize(args.getMinApi(), new File(args.getSdkDir()));
resourceBundle = new ResourceBundle(args.getModulePackage());
- List<IntermediateV2> intermediateList = loadDependencyIntermediates();
- for (Intermediate intermediate : intermediateList) {
+ final List<IntermediateV2> intermediateList;
+ if (args.isEnableV2()) {
+ GenClassInfoLog infoLog;
try {
+ infoLog = ResourceBundle.loadClassInfoFromFolder(
+ new File(args.getClassLogDir()));
+ } catch (IOException e) {
+ infoLog = new GenClassInfoLog();
+ Scope.defer(new ScopedException("cannot load the info log from %s",
+ args.getClassLogDir()));
+ }
+ resourceBundle.addDependencyLayouts(infoLog);
+ intermediateList = Collections.emptyList();
+ } else {
+ intermediateList = loadDependencyIntermediates();
+ for (Intermediate intermediate : intermediateList) {
try {
- intermediate.appendTo(resourceBundle, false);
- } catch (Throwable throwable) {
- L.e(throwable, "unable to prepare resource bundle");
+ try {
+ intermediate.appendTo(resourceBundle, false);
+ } catch (Throwable throwable) {
+ L.e(throwable, "unable to prepare resource bundle");
+ }
+ } catch (LoggedErrorException e) {
+ // This will be logged later
}
- } catch (LoggedErrorException e) {
- // This will be logged later
}
}
-
IntermediateV2 mine = createIntermediateFromLayouts(args.getXmlOutDir(),
intermediateList);
if (mine != null) {
- mine.updateOverridden(resourceBundle);
- intermediateList.add(mine);
- saveIntermediate(processingEnvironment, args, mine);
+ if (!args.isEnableV2()) {
+ mine.updateOverridden(resourceBundle);
+ intermediateList.add(mine);
+ saveIntermediate(processingEnvironment, args, mine);
+ }
mine.appendTo(resourceBundle, true);
}
// generate them here so that bindable parser can read
@@ -203,8 +222,9 @@ public class ProcessExpressions extends ProcessDataBinding.ProcessingStep {
compilerChef.writeViewBinderInterfaces(compilerArgs.isLibrary()
&& !compilerArgs.isTestVariant());
}
- if (compilerArgs.isApp() != compilerArgs.isTestVariant() ||
- compilerArgs.isEnabledForTests()) {
+ if (compilerArgs.isApp() != compilerArgs.isTestVariant()
+ || (compilerArgs.isEnabledForTests() && !compilerArgs.isLibrary())
+ || compilerArgs.isEnableV2()) {
compilerChef.writeViewBinders(compilerArgs.getMinApi());
}
}
@@ -213,7 +233,7 @@ public class ProcessExpressions extends ProcessDataBinding.ProcessingStep {
L.e("When compiling a library module, build info must include exportClassListTo path");
}
if (compilerArgs.isLibrary() && !compilerArgs.isTestVariant()) {
- Set<String> classNames = compilerChef.getWrittenClassNames();
+ Set<String> classNames = compilerChef.getClassesToBeStripped();
String out = Joiner.on(StringUtils.LINE_SEPARATOR).join(classNames);
L.d("Writing list of classes to %s . \nList:%s",
compilerArgs.getExportClassListTo(), out);
diff --git a/compiler/src/main/java/android/databinding/tool/CallbackWrapper.java b/compiler/src/main/java/android/databinding/tool/CallbackWrapper.java
index d8ec24f3..28f4f7de 100644
--- a/compiler/src/main/java/android/databinding/tool/CallbackWrapper.java
+++ b/compiler/src/main/java/android/databinding/tool/CallbackWrapper.java
@@ -34,15 +34,20 @@ public class CallbackWrapper {
public final ModelClass klass;
public final ModelMethod method;
public final String key;
- private static final String PACKAGE = "android.databinding.generated.callback";
+ // in v1, we always used 1 global app package
+ private static final String V1_PACKAGE = "android.databinding.generated.callback";
+ private static final String CALLBACK_PACKAGE_SUFFIX = ".generated.callback";
private static final String LISTENER_NAME = "Listener";
private String mClassName;
private String mListenerMethodName;
private boolean mInitialized;
+ private final String mPackage;
- public CallbackWrapper(ModelClass klass, ModelMethod method) {
+ public CallbackWrapper(ModelClass klass, ModelMethod method, String modulePackage,
+ boolean enableV2) {
this.klass = klass;
this.method = method;
+ this.mPackage = enableV2 ? modulePackage + CALLBACK_PACKAGE_SUFFIX : V1_PACKAGE;
this.key = uniqueKey(klass, method);
}
@@ -56,7 +61,7 @@ public class CallbackWrapper {
}
public String getPackage() {
- return PACKAGE;
+ return mPackage;
}
public String getClassName() {
diff --git a/compiler/src/main/java/android/databinding/tool/CompilerChef.java b/compiler/src/main/java/android/databinding/tool/CompilerChef.java
index 73fe07f1..79cce64b 100644
--- a/compiler/src/main/java/android/databinding/tool/CompilerChef.java
+++ b/compiler/src/main/java/android/databinding/tool/CompilerChef.java
@@ -14,18 +14,27 @@
package android.databinding.tool;
import android.databinding.tool.expr.ExprModel;
+import android.databinding.tool.processing.Scope;
+import android.databinding.tool.processing.ScopedException;
import android.databinding.tool.reflection.InjectedClass;
import android.databinding.tool.reflection.InjectedMethod;
import android.databinding.tool.reflection.ModelAnalyzer;
import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.store.GenClassInfoLog;
import android.databinding.tool.store.ResourceBundle;
import android.databinding.tool.util.L;
import android.databinding.tool.util.Preconditions;
import android.databinding.tool.writer.BRWriter;
import android.databinding.tool.writer.BindingMapperWriter;
+import android.databinding.tool.writer.BindingMapperWriterV2;
import android.databinding.tool.writer.DynamicUtilWriter;
import android.databinding.tool.writer.JavaFileWriter;
+import com.squareup.javapoet.JavaFile;
+import com.squareup.javapoet.TypeSpec;
+
+import java.io.File;
+import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -147,7 +156,9 @@ public class CompilerChef {
// inject implementation
if (mEnableV2 || bundles.size() > 1) {
// Add the implementation class
- final String implName = className + layoutFileBundle.getConfigName() + "Impl";
+ final String implName =
+ layoutFileBundle.getBindingClassPackage() + "."
+ + layoutFileBundle.createImplClassNameWithConfig();
analyzer.injectClass(new InjectedClass(implName, className));
}
}
@@ -169,11 +180,34 @@ public class CompilerChef {
}
public void writeDataBinderMapper(DataBindingCompilerArgs compilerArgs, BRWriter brWriter) {
- ensureDataBinder();
final String pkg = "android.databinding";
- BindingMapperWriter dbr = new BindingMapperWriter(pkg, "DataBinderMapper",
- mDataBinder.getLayoutBinders(), compilerArgs);
- mFileWriter.writeToFile(pkg + "." + dbr.getClassName(), dbr.write(brWriter));
+ final String mapperName = "DataBinderMapper";
+ if (compilerArgs.isEnableV2()) {
+ GenClassInfoLog infoLog;
+ try {
+ infoLog = ResourceBundle.loadClassInfoFromFolder(
+ new File(compilerArgs.getClassLogDir()));
+ } catch (IOException e) {
+ Scope.defer(new ScopedException("Cannot read class info log"));
+ infoLog = new GenClassInfoLog();
+ }
+ BindingMapperWriterV2 v2 = new BindingMapperWriterV2(pkg,
+ mapperName, infoLog, compilerArgs);
+ TypeSpec spec = v2.write(brWriter);
+ StringBuilder sb = new StringBuilder();
+ try {
+ JavaFile.builder(pkg, spec)
+ .build().writeTo(sb);
+ mFileWriter.writeToFile(pkg + "." + v2.getClassName(), sb.toString());
+ } catch (IOException e) {
+ Scope.defer(new ScopedException("cannot generate mapper class", e));
+ }
+ } else {
+ ensureDataBinder();
+ BindingMapperWriter dbr = new BindingMapperWriter(pkg, mapperName,
+ mDataBinder.getLayoutBinders(), compilerArgs);
+ mFileWriter.writeToFile(pkg + "." + dbr.getClassName(), dbr.write(brWriter));
+ }
}
public void writeDynamicUtil() {
@@ -225,9 +259,9 @@ public class CompilerChef {
mDataBinder.writeComponent();
}
- public Set<String> getWrittenClassNames() {
+ public Set<String> getClassesToBeStripped() {
ensureDataBinder();
- return mDataBinder.getWrittenClassNames();
+ return mDataBinder.getClassesToBeStripped();
}
public interface BindableHolder {
diff --git a/compiler/src/main/java/android/databinding/tool/DataBinder.java b/compiler/src/main/java/android/databinding/tool/DataBinder.java
index 54fa5922..fa2f256c 100644
--- a/compiler/src/main/java/android/databinding/tool/DataBinder.java
+++ b/compiler/src/main/java/android/databinding/tool/DataBinder.java
@@ -20,6 +20,7 @@ import android.databinding.tool.processing.Scope;
import android.databinding.tool.processing.ScopedException;
import android.databinding.tool.store.ResourceBundle;
import android.databinding.tool.util.L;
+import android.databinding.tool.util.Preconditions;
import android.databinding.tool.util.StringUtils;
import android.databinding.tool.writer.CallbackWrapperWriter;
import android.databinding.tool.writer.ComponentWriter;
@@ -41,19 +42,32 @@ public class DataBinder {
private JavaFileWriter mFileWriter;
- Set<String> mWrittenClasses = new HashSet<String>();
+ Set<String> mClassesToBeStripped = new HashSet<String>();
+ private final boolean mEnableV2;
public DataBinder(ResourceBundle resourceBundle, boolean enableV2) {
L.d("reading resource bundle into data binder");
- for (Map.Entry<String, List<ResourceBundle.LayoutFileBundle>> entry :
- resourceBundle.getLayoutBundles().entrySet()) {
- for (ResourceBundle.LayoutFileBundle bundle : entry.getValue()) {
+ mEnableV2 = enableV2;
+ if (mEnableV2) {
+ for(ResourceBundle.LayoutFileBundle bundle :
+ resourceBundle.getLayoutFileBundlesInSource()) {
try {
- mLayoutBinders.add(new LayoutBinder(bundle, enableV2));
+ mLayoutBinders.add(new LayoutBinder(bundle, true));
} catch (ScopedException ex) {
Scope.defer(ex);
}
}
+ } else {
+ for (Map.Entry<String, List<ResourceBundle.LayoutFileBundle>> entry :
+ resourceBundle.getLayoutBundles().entrySet()) {
+ for (ResourceBundle.LayoutFileBundle bundle : entry.getValue()) {
+ try {
+ mLayoutBinders.add(new LayoutBinder(bundle, false));
+ } catch (ScopedException ex) {
+ Scope.defer(ex);
+ }
+ }
+ }
}
}
public List<LayoutBinder> getLayoutBinders() {
@@ -67,13 +81,14 @@ public class DataBinder {
}
public void writerBaseClasses(boolean isLibrary) {
+ Preconditions.check(!mEnableV2, "Should not call write base classes in v2");
for (LayoutBinder layoutBinder : mLayoutBinders) {
try {
Scope.enter(layoutBinder);
if (isLibrary || layoutBinder.hasVariations()) {
String className = layoutBinder.getClassName();
String canonicalName = layoutBinder.getPackage() + "." + className;
- if (mWrittenClasses.contains(canonicalName)) {
+ if (mClassesToBeStripped.contains(canonicalName)) {
continue;
}
@@ -82,7 +97,7 @@ public class DataBinder {
L.d("writing data binder base %s", canonicalName);
mFileWriter.writeToFile(canonicalName,
layoutBinder.writeViewBinderBaseClass(isLibrary, variations));
- mWrittenClasses.add(canonicalName);
+ mClassesToBeStripped.add(canonicalName);
}
} catch (ScopedException ex){
Scope.defer(ex);
@@ -112,7 +127,10 @@ public class DataBinder {
String className = layoutBinder.getImplementationName();
String canonicalName = layoutBinder.getPackage() + "." + className;
L.d("writing data binder %s", canonicalName);
- mWrittenClasses.add(canonicalName);
+ if (!mEnableV2) {
+ // if v2 is enable, do not record it as we don't want it to be stripped
+ mClassesToBeStripped.add(canonicalName);
+ }
mFileWriter.writeToFile(canonicalName, layoutBinder.writeViewBinder(minSdk));
} catch (ScopedException ex) {
Scope.defer(ex);
@@ -154,7 +172,9 @@ public class DataBinder {
String canonicalName = wrapper.getPackage() + "." + className;
mFileWriter.writeToFile(canonicalName, code);
// these will be deleted for library projects.
- mWrittenClasses.add(canonicalName);
+ if (!mEnableV2) {
+ mClassesToBeStripped.add(canonicalName);
+ }
}
}
@@ -172,12 +192,12 @@ public class DataBinder {
public void writeComponent() {
ComponentWriter componentWriter = new ComponentWriter();
- mWrittenClasses.add(COMPONENT_CLASS);
+ mClassesToBeStripped.add(COMPONENT_CLASS);
mFileWriter.writeToFile(COMPONENT_CLASS, componentWriter.createComponent());
}
- public Set<String> getWrittenClassNames() {
- return mWrittenClasses;
+ public Set<String> getClassesToBeStripped() {
+ return mClassesToBeStripped;
}
public void setFileWriter(JavaFileWriter fileWriter) {
diff --git a/compiler/src/main/java/android/databinding/tool/LayoutBinder.java b/compiler/src/main/java/android/databinding/tool/LayoutBinder.java
index b5b94fea..98d9f918 100644
--- a/compiler/src/main/java/android/databinding/tool/LayoutBinder.java
+++ b/compiler/src/main/java/android/databinding/tool/LayoutBinder.java
@@ -174,11 +174,12 @@ public class LayoutBinder implements FileScopeProvider {
mEnableV2 = enableV2;
try {
Scope.enter(this);
- mExprModel = new ExprModel();
+ mModulePackage = layoutBundle.getModulePackage();
+ mExprModel = new ExprModel(mModulePackage, enableV2);
mExpressionParser = new ExpressionParser(mExprModel);
mBindingTargets = new ArrayList<BindingTarget>();
mBundle = layoutBundle;
- mModulePackage = layoutBundle.getModulePackage();
+
HashSet<String> names = new HashSet<String>();
// copy over data.
for (ResourceBundle.VariableDeclaration variable : mBundle.getVariables()) {
@@ -376,7 +377,7 @@ public class LayoutBinder implements FileScopeProvider {
public String getImplementationName() {
if (mEnableV2 || hasVariations()) {
- return mBundle.getBindingClassName() + mBundle.getConfigName() + "Impl";
+ return mBundle.createImplClassNameWithConfig();
} else {
return mBundle.getBindingClassName();
}
@@ -391,7 +392,7 @@ public class LayoutBinder implements FileScopeProvider {
}
public String getTag() {
- return mBundle.getDirectory() + "/" + mBundle.getFileName();
+ return mBundle.createTag();
}
public boolean hasVariations() {
diff --git a/compiler/src/main/java/android/databinding/tool/expr/CallbackExprModel.java b/compiler/src/main/java/android/databinding/tool/expr/CallbackExprModel.java
index d5c361f9..af49ee1d 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/CallbackExprModel.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/CallbackExprModel.java
@@ -37,6 +37,7 @@ public class CallbackExprModel extends ExprModel {
final ExprModel mOriginal;
final List<CallbackArgExpr> mArguments = new ArrayList<CallbackArgExpr>();
public CallbackExprModel(ExprModel original) {
+ super(original.modulePackage, original.enableV2);
mOriginal = original;
}
diff --git a/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java b/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java
index b32422f4..0464aa91 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java
@@ -93,6 +93,14 @@ public class ExprModel {
private ExprModelExt mExt = new ExprModelExt();
+ public final String modulePackage;
+ public final boolean enableV2;
+
+ public ExprModel(String modulePackage, boolean enableV2) {
+ this.modulePackage = modulePackage;
+ this.enableV2 = enableV2;
+ }
+
/**
* Adds the expression to the list of expressions and returns it.
* If it already exists, returns existing one.
@@ -765,7 +773,7 @@ public class ExprModel {
final String key = CallbackWrapper.uniqueKey(klass, method);
CallbackWrapper wrapper = mCallbackWrappers.get(key);
if (wrapper == null) {
- wrapper = new CallbackWrapper(klass, method);
+ wrapper = new CallbackWrapper(klass, method, modulePackage, enableV2);
mCallbackWrappers.put(key, wrapper);
}
return wrapper;
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 46d0e63a..c4872e40 100644
--- a/compiler/src/main/java/android/databinding/tool/util/GenerationalClassUtil.java
+++ b/compiler/src/main/java/android/databinding/tool/util/GenerationalClassUtil.java
@@ -49,7 +49,16 @@ public class GenerationalClassUtil {
@Nullable
private static File sIncrementalOutDir;
+ private static ExtensionFilter[] sEnabledExtensions;
+
public static void init(DataBindingCompilerArgs args) {
+ if (args.isEnableV2()) {
+ sEnabledExtensions = new ExtensionFilter[]{ExtensionFilter.BR,
+ ExtensionFilter.SETTER_STORE};
+ } else {
+ sEnabledExtensions = new ExtensionFilter[]{ExtensionFilter.BR, ExtensionFilter.LAYOUT,
+ ExtensionFilter.SETTER_STORE};
+ }
if (StringUtils.isNotBlank(args.getAarOutFolder())) {
sIncrementalOutDir = new File(args.getAarOutFolder(),
DataBindingBuilder.INCREMENTAL_BIN_AAR_DIR);
@@ -67,15 +76,17 @@ public class GenerationalClassUtil {
if (sCache == null) {
buildCache();
}
+ List result = sCache[filter.ordinal()];
+ Preconditions.checkNotNull(result, "Invalid filter " + filter);
//noinspection unchecked
- return sCache[filter.ordinal()];
+ return result;
}
private static void buildCache() {
L.d("building generational class cache");
sCache = new List[ExtensionFilter.values().length];
- for (ExtensionFilter filter : ExtensionFilter.values()) {
+ for (ExtensionFilter filter : sEnabledExtensions) {
sCache[filter.ordinal()] = new ArrayList();
}
loadFromBuildInfo();
@@ -102,7 +113,7 @@ public class GenerationalClassUtil {
}
for (File file : FileUtils.listFiles(directory, TrueFileFilter.INSTANCE,
TrueFileFilter.INSTANCE)) {
- for (ExtensionFilter filter : ExtensionFilter.values()) {
+ for (ExtensionFilter filter : sEnabledExtensions) {
if (filter.accept(file.getName())) {
InputStream inputStream = null;
try {