Require only one pass to make BR.java file.

Bug 19985005

Because the generation of Binding files created @Bindable
annotations, the BR file generation had to wait until a
second annotation pass. This caused errors to be generated
that were later cleared, causing confusion. I moved the
BR file generation to the same annotation processing stage
that generates the Binding files to clear up the error
generation.

TODO: merge the annotation processing stages so that there
is less cross-talk between annotation processors.
This commit is contained in:
George Mount
2015-03-30 12:20:20 -07:00
parent a428ab93ec
commit 75aa9bf96f
5 changed files with 78 additions and 24 deletions

View File

@@ -20,6 +20,7 @@ import com.google.common.base.Preconditions;
import android.databinding.Bindable;
import android.databinding.BindingBuildInfo;
import android.databinding.tool.CompilerChef.BindableHolder;
import android.databinding.tool.util.GenerationalClassUtil;
import android.databinding.tool.util.L;
@@ -45,43 +46,58 @@ import javax.lang.model.type.TypeKind;
// binding app info and library info are necessary to trigger this.
@SupportedSourceVersion(SourceVersion.RELEASE_7)
public class ProcessBindable extends ProcessDataBinding.ProcessingStep {
public class ProcessBindable extends ProcessDataBinding.ProcessingStep implements BindableHolder {
private static final String INTERMEDIATE_FILE_EXT = "-br.bin";
Intermediate mProperties;
HashMap<String, HashSet<String>> mLayoutVariables = new HashMap<>();
@Override
public boolean onHandleStep(RoundEnvironment roundEnv, ProcessingEnvironment processingEnv,
BindingBuildInfo buildInfo) {
if (mProperties == null) {
mProperties = new IntermediateV1(buildInfo.modulePackage());
}
for (Element element : AnnotationUtil.getElementsAnnotatedWith(roundEnv, Bindable.class)) {
Element enclosingElement = element.getEnclosingElement();
ElementKind kind = enclosingElement.getKind();
if (kind != ElementKind.CLASS && kind != ElementKind.INTERFACE) {
L.e("Bindable must be on a member field or method. The enclosing type is %s",
enclosingElement.getKind());
mergeLayoutVariables();
mLayoutVariables.clear();
for (Element element : AnnotationUtil
.getElementsAnnotatedWith(roundEnv, Bindable.class)) {
Element enclosingElement = element.getEnclosingElement();
ElementKind kind = enclosingElement.getKind();
if (kind != ElementKind.CLASS && kind != ElementKind.INTERFACE) {
L.e("Bindable must be on a member field or method. The enclosing type is %s",
enclosingElement.getKind());
}
TypeElement enclosing = (TypeElement) enclosingElement;
String name = getPropertyName(element);
if (name != null) {
Preconditions
.checkNotNull(mProperties, "Must receive app / library info before "
+ "Bindable fields.");
mProperties.addProperty(enclosing.getQualifiedName().toString(), name);
}
}
TypeElement enclosing = (TypeElement) enclosingElement;
String name = getPropertyName(element);
if (name != null) {
Preconditions.checkNotNull(mProperties, "Must receive app / library info before "
+ "Bindable fields.");
mProperties.addProperty(enclosing.getQualifiedName().toString(), name);
if (mProperties.hasValues()) {
GenerationalClassUtil.writeIntermediateFile(processingEnv,
mProperties.getPackage(),
createIntermediateFileName(mProperties.getPackage()), mProperties);
generateBRClasses(!buildInfo.isLibrary(), mProperties.getPackage());
}
}
return false;
}
@Override
public void addVariable(String variableName, String containingClassName) {
HashSet<String> variableNames = mLayoutVariables.get(containingClassName);
if (variableNames == null) {
variableNames = new HashSet<>();
mLayoutVariables.put(containingClassName, variableNames);
}
variableNames.add(variableName);
}
@Override
public void onProcessingOver(RoundEnvironment roundEnvironment,
ProcessingEnvironment processingEnvironment, BindingBuildInfo buildInfo) {
if (mProperties != null) {
GenerationalClassUtil.writeIntermediateFile(processingEnvironment,
mProperties.getPackage(),
createIntermediateFileName(mProperties.getPackage()), mProperties);
generateBRClasses(!buildInfo.isLibrary(), mProperties.getPackage());
}
}
private String createIntermediateFileName(String appPkg) {
@@ -183,6 +199,14 @@ public class ProcessBindable extends ProcessDataBinding.ProcessingStep {
propertyName.subSequence(1, propertyName.length());
}
private void mergeLayoutVariables() {
for (String containingClass : mLayoutVariables.keySet()) {
for (String variable : mLayoutVariables.get(containingClass)) {
mProperties.addProperty(containingClass, variable);
}
}
}
private static boolean prefixes(CharSequence sequence, String prefix) {
boolean prefixes = false;
if (sequence.length() > prefix.length()) {
@@ -234,6 +258,8 @@ public class ProcessBindable extends ProcessDataBinding.ProcessingStep {
void addProperty(String className, String propertyName);
boolean hasValues();
String getPackage();
}
@@ -265,6 +291,11 @@ public class ProcessBindable extends ProcessDataBinding.ProcessingStep {
properties.add(propertyName);
}
@Override
public boolean hasValues() {
return !mProperties.isEmpty();
}
@Override
public String getPackage() {
return mPackage;

View File

@@ -69,10 +69,11 @@ public class ProcessDataBinding extends AbstractProcessor {
}
private void initProcessingSteps() {
ProcessBindable processBindable = new ProcessBindable();
mProcessingSteps = Arrays.asList(
new ProcessMethodAdapters(),
new ProcessExpressions(),
new ProcessBindable()
new ProcessExpressions(processBindable),
processBindable
);
AnnotationJavaFileWriter javaFileWriter = new AnnotationJavaFileWriter(processingEnv);
for (ProcessingStep step : mProcessingSteps) {

View File

@@ -45,6 +45,13 @@ public class ProcessExpressions extends ProcessDataBinding.ProcessingStep {
private static final String LAYOUT_INFO_FILE_SUFFIX = "-layoutinfo.bin";
private final ProcessBindable mProcessBindable;
public ProcessExpressions(ProcessBindable processBindable) {
mProcessBindable = processBindable;
}
@Override
public boolean onHandleStep(RoundEnvironment roundEnvironment,
ProcessingEnvironment processingEnvironment, BindingBuildInfo buildInfo) {
@@ -79,7 +86,6 @@ public class ProcessExpressions extends ProcessDataBinding.ProcessingStep {
@Override
public void onProcessingOver(RoundEnvironment roundEnvironment,
ProcessingEnvironment processingEnvironment, BindingBuildInfo buildInfo) {
}
private void generateBinders(ResourceBundle resourceBundle, BindingBuildInfo buildInfo,
@@ -117,6 +123,7 @@ public class ProcessExpressions extends ProcessDataBinding.ProcessingStep {
throws JAXBException {
CompilerChef compilerChef = CompilerChef.createChef(resourceBundle, getWriter());
if (compilerChef.hasAnythingToGenerate()) {
compilerChef.addBRVariables(mProcessBindable);
compilerChef.writeViewBinderInterfaces();
if (!forLibraryModule) {
compilerChef.writeDbrFile();

View File

@@ -66,6 +66,18 @@ public class CompilerChef {
mFileWriter.writeToFile(pkg + "." + dbr.getClassName(), dbr.write());
}
}
/**
* Adds variables to list of Bindables.
*/
public void addBRVariables(BindableHolder bindables) {
ensureDataBinder();
for (LayoutBinder layoutBinder : mDataBinder.mLayoutBinders) {
for (String variableName : layoutBinder.getUserDefinedVariables().keySet()) {
bindables.addVariable(variableName, layoutBinder.getInterfaceName());
}
}
}
public void writeViewBinderInterfaces() {
ensureDataBinder();
@@ -76,4 +88,8 @@ public class CompilerChef {
ensureDataBinder();
mDataBinder.writeBinders();
}
public interface BindableHolder {
void addVariable(String variableName, String containingClassName);
}
}

View File

@@ -810,7 +810,6 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder) {
nl("")
variables.forEach {
if (it.getUserDefinedType() != null) {
tab("@Bindable")
//it.getExpandedUserDefinedType(ModelAnalyzer.getInstance());
val type = ModelAnalyzer.getInstance().applyImports(it.getUserDefinedType(), model.getImports())
tab("public abstract void ${it.setterName}(${type} ${it.readableUniqueName});")