summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/BuildInfoUtil.java54
-rw-r--r--annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessBindable.java275
-rw-r--r--annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessDataBinding.java128
-rw-r--r--annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessExpressions.java219
-rw-r--r--annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessMethodAdapters.java79
-rw-r--r--annotationprocessor/src/main/resources/META-INF/services/javax.annotation.processing.Processor4
-rw-r--r--baseLibrary/build.gradle1
-rw-r--r--baseLibrary/src/main/java/android/binding/BindingBuildInfo.java (renamed from baseLibrary/src/main/java/android/binding/BindingAppInfo.java)14
-rw-r--r--build.gradle23
-rw-r--r--compiler/src/main/java/com/android/databinding/LayoutBinder.java8
-rw-r--r--compiler/src/main/java/com/android/databinding/LayoutXmlProcessor.java143
-rw-r--r--compiler/src/main/java/com/android/databinding/reflection/ModelAnalyzer.java2
-rw-r--r--compiler/src/main/java/com/android/databinding/reflection/annotation/AnnotationAnalyzer.java15
-rw-r--r--compiler/src/main/java/com/android/databinding/store/LayoutFileParser.java2
-rw-r--r--compiler/src/main/java/com/android/databinding/store/ResourceBundle.java67
-rw-r--r--compiler/src/main/java/com/android/databinding/store/SetterStore.java116
-rw-r--r--compiler/src/main/java/com/android/databinding/util/GenerationalClassUtil.java187
-rw-r--r--compiler/src/main/java/com/android/databinding/writer/AnnotationJavaFileWriter.java12
-rw-r--r--compiler/src/main/java/com/android/databinding/writer/JavaFileWriter.java21
-rw-r--r--compiler/src/main/kotlin/com/android/databinding/ext/ext.kt2
-rw-r--r--compiler/src/main/kotlin/com/android/databinding/util/XmlEditor.kt3
-rw-r--r--compiler/src/main/kotlin/com/android/databinding/writer/DataBinderWriter.kt6
-rw-r--r--compiler/src/main/kotlin/com/android/databinding/writer/LayoutBinderWriter.kt11
-rw-r--r--compiler/src/test/java/com/android/databinding/MockLayoutBinder.java2
-rw-r--r--compiler/src/test/java/com/android/databinding/reflection/java/JavaAnalyzer.java17
-rw-r--r--databinding.properties3
-rw-r--r--extensions/baseAdapters/build.gradle96
-rw-r--r--extensions/baseAdapters/src/main/AndroidManifest.xml19
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/AbsListViewBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/AbsListViewBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/AbsSeekBarBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/AbsSeekBarBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/AbsSpinnerBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/AbsSpinnerBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/AutoCompleteTextViewBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/AutoCompleteTextViewBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/CardViewBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/CardViewBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/CheckedTextViewBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/CheckedTextViewBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/CompoundButtonBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/CompoundButtonBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/Converters.java (renamed from library/src/main/java/android/binding/adapters/Converters.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/FrameLayoutBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/FrameLayoutBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/ImageViewBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/ImageViewBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/LinearLayoutBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/LinearLayoutBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/ProgressBarBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/ProgressBarBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/RadioGroupBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/RadioGroupBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/SpinnerBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/SpinnerBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/SwitchBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/SwitchBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/SwitchCompatBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/SwitchCompatBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/TabWidgetBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/TabWidgetBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/TableLayoutBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/TableLayoutBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/TextViewBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/TextViewBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/ViewBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/ViewBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/ViewGroupBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/ViewGroupBindingAdapter.java)0
-rw-r--r--extensions/baseAdapters/src/main/java/android/bindings/adapters/ViewStubBindingAdapter.java (renamed from library/src/main/java/android/binding/adapters/ViewStubBindingAdapter.java)0
-rw-r--r--extensions/build.gradle45
-rw-r--r--extensions/gradle/wrapper/gradle-wrapper.jarbin0 -> 49896 bytes
-rw-r--r--extensions/gradle/wrapper/gradle-wrapper.properties6
-rwxr-xr-xextensions/gradlew164
-rw-r--r--extensions/settings.gradle20
-rw-r--r--gradlePlugin/src/main/kotlin/DataBindingProcessLayoutsTask.kt5
-rw-r--r--gradlePlugin/src/main/kotlin/plugin.kt266
-rw-r--r--integration-tests/IndependentLibrary/app/.gitignore1
-rw-r--r--integration-tests/IndependentLibrary/app/build.gradle60
-rw-r--r--integration-tests/IndependentLibrary/app/proguard-rules.pro17
-rw-r--r--integration-tests/IndependentLibrary/app/src/androidTest/java/com/android/databinding/test/independentlibrary/ApplicationTest.java29
-rw-r--r--integration-tests/IndependentLibrary/app/src/androidTest/java/com/android/databinding/test/independentlibrary/LibraryActivityTest.java41
-rw-r--r--integration-tests/IndependentLibrary/app/src/main/AndroidManifest.xml24
-rw-r--r--integration-tests/IndependentLibrary/app/src/main/java/com/android/databinding/test/independentlibrary/LibraryActivity.java36
-rw-r--r--integration-tests/IndependentLibrary/app/src/main/java/com/android/databinding/test/independentlibrary/LibraryAdapter.java26
-rw-r--r--integration-tests/IndependentLibrary/app/src/main/java/com/android/databinding/test/independentlibrary/vo/MyBindableObject.java36
-rw-r--r--integration-tests/IndependentLibrary/app/src/main/res/layout/library_layout.xml25
-rw-r--r--integration-tests/IndependentLibrary/app/src/main/res/values/strings.xml18
-rw-r--r--integration-tests/IndependentLibrary/build.gradle44
-rw-r--r--integration-tests/IndependentLibrary/gradle.properties33
-rw-r--r--integration-tests/IndependentLibrary/gradle/wrapper/gradle-wrapper.jarbin0 -> 49896 bytes
-rw-r--r--integration-tests/IndependentLibrary/gradle/wrapper/gradle-wrapper.properties21
-rwxr-xr-xintegration-tests/IndependentLibrary/gradlew164
-rw-r--r--integration-tests/IndependentLibrary/gradlew.bat90
-rw-r--r--integration-tests/IndependentLibrary/settings.gradle16
-rw-r--r--integration-tests/MultiModuleTestApp/app/.gitignore1
-rw-r--r--integration-tests/MultiModuleTestApp/app/build.gradle52
-rw-r--r--integration-tests/MultiModuleTestApp/app/proguard-rules.pro17
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/androidTest/java/com/android/databinding/multimoduletestapp/ApplicationTest.java38
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/androidTest/java/com/android/databinding/multimoduletestapp/EventIdsTest.java132
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/AndroidManifest.xml37
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/java/com/android/databinding/multimoduletestapp/MainActivity.java61
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/java/com/android/databinding/multimoduletestapp/ObservableExtendingLib.java36
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/java/com/android/databinding/multimoduletestapp/ObservableInMainApp.java58
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/res/drawable-hdpi/ic_launcher.pngbin0 -> 9397 bytes
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/res/drawable-mdpi/ic_launcher.pngbin0 -> 5237 bytes
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/res/drawable-xhdpi/ic_launcher.pngbin0 -> 14383 bytes
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/res/drawable-xxhdpi/ic_launcher.pngbin0 -> 19388 bytes
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/res/layout/activity_main.xml27
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/res/layout/activity_test_library_main.xml27
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/res/menu/menu_main.xml21
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/res/values-v21/styles.xml21
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/res/values-w820dp/dimens.xml22
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/res/values/dimens.xml21
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/res/values/strings.xml24
-rw-r--r--integration-tests/MultiModuleTestApp/app/src/main/res/values/styles.xml24
-rw-r--r--integration-tests/MultiModuleTestApp/build.gradle44
-rw-r--r--integration-tests/MultiModuleTestApp/gradle.properties34
-rw-r--r--integration-tests/MultiModuleTestApp/gradle/wrapper/gradle-wrapper.jarbin0 -> 49896 bytes
-rw-r--r--integration-tests/MultiModuleTestApp/gradle/wrapper/gradle-wrapper.properties22
-rwxr-xr-xintegration-tests/MultiModuleTestApp/gradlew164
-rw-r--r--integration-tests/MultiModuleTestApp/gradlew.bat90
-rw-r--r--integration-tests/MultiModuleTestApp/settings.gradle17
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/.gitignore1
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/build.gradle48
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/proguard-rules.pro17
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/androidTest/java/com/android/databinding/testlibrary/ApplicationTest.java29
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/main/AndroidManifest.xml36
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/main/java/com/android/databinding/testlibrary/ObservableInLibrary.java61
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/main/java/com/android/databinding/testlibrary/TestLibObject.java (renamed from baseLibrary/src/main/java/android/binding/BinderBundle.java)23
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/main/java/com/android/databinding/testlibrary/TestLibraryMainActivity.java56
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-hdpi/ic_launcher.pngbin0 -> 9397 bytes
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-mdpi/ic_launcher.pngbin0 -> 5237 bytes
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-xhdpi/ic_launcher.pngbin0 -> 14383 bytes
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-xxhdpi/ic_launcher.pngbin0 -> 19388 bytes
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/main/res/layout/activity_test_library_main.xml29
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/main/res/menu/menu_test_library_main.xml21
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/main/res/values-w820dp/dimens.xml22
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/main/res/values/dimens.xml21
-rw-r--r--integration-tests/MultiModuleTestApp/testlibrary/src/main/res/values/strings.xml24
-rw-r--r--integration-tests/TestApp/app/build.gradle1
-rw-r--r--integration-tests/TestApp/app/src/androidTest/java/com/android/databinding/testapp/ProcessBindableTest.java4
-rw-r--r--integration-tests/TestApp/app/src/main/java/com/android/databinding/testapp/vo/PublicFinalWithObservableTestVo.java3
-rw-r--r--integration-tests/TestApp/app/src/main/java/com/android/databinding/testapp/vo/TextViewBindingObject.java3
-rw-r--r--integration-tests/TestApp/app/src/main/res/layout-land/multi_res_layout.xml3
-rw-r--r--library/build.gradle3
-rw-r--r--samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java10
-rw-r--r--samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/vo/User.java9
-rw-r--r--samples/BindingDemo/app/src/test/java/com/android/example/bindingdemo/vo/UnitTest.java3
-rw-r--r--settings.gradle2
130 files changed, 3477 insertions, 658 deletions
diff --git a/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/BuildInfoUtil.java b/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/BuildInfoUtil.java
new file mode 100644
index 00000000..bd242339
--- /dev/null
+++ b/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/BuildInfoUtil.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.annotationprocessor;
+
+import com.google.common.base.Preconditions;
+
+import android.binding.BindingBuildInfo;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.Element;
+
+public class BuildInfoUtil {
+ private static BindingBuildInfo sCached;
+ public static BindingBuildInfo load(RoundEnvironment roundEnvironment) {
+ if (sCached == null) {
+ sCached = extractNotNull(roundEnvironment, BindingBuildInfo.class);
+ }
+ return sCached;
+ }
+
+ private static <T extends Annotation> T extractNotNull(RoundEnvironment roundEnv,
+ Class<T> annotationClass) {
+ T result = null;
+ for (Element element : roundEnv.getElementsAnnotatedWith(annotationClass)) {
+ final T info = element.getAnnotation(annotationClass);
+ if (info == null) {
+ continue; // It gets confused between BindingAppInfo and BinderBundle
+ }
+ Preconditions.checkState(result == null, "Should have only one %s",
+ annotationClass.getCanonicalName());
+ result = info;
+ }
+ return result;
+
+ }
+}
diff --git a/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessBindable.java b/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessBindable.java
index ca554db7..099a0eaa 100644
--- a/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessBindable.java
+++ b/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessBindable.java
@@ -1,30 +1,39 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.annotationprocessor;
-import com.android.databinding.reflection.ModelAnalyzer;
+import com.google.common.base.Preconditions;
-import org.apache.commons.io.IOUtils;
+import com.android.databinding.util.GenerationalClassUtil;
+import com.android.databinding.util.L;
import android.binding.Bindable;
+import android.binding.BindingBuildInfo;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
import java.io.Serializable;
-import java.io.Writer;
-import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
-import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
-import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
@@ -34,91 +43,100 @@ import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
-import javax.tools.Diagnostic;
-import javax.tools.FileObject;
-import javax.tools.JavaFileObject;
-import javax.tools.StandardLocation;
-@SupportedAnnotationTypes({"android.binding.Bindable"})
+// binding app info and library info are necessary to trigger this.
@SupportedSourceVersion(SourceVersion.RELEASE_7)
-public class ProcessBindable extends AbstractProcessor {
- Intermediate mProperties = new IntermediateV1();
-
- public ProcessBindable() {
- }
-
- @Override
- public synchronized void init(ProcessingEnvironment processingEnv) {
- super.init(processingEnv);
- ModelAnalyzer.setProcessingEnvironment(processingEnv);
- }
+public class ProcessBindable extends ProcessDataBinding.ProcessingStep {
+ private static final String INTERMEDIATE_FILE_EXT = "-br.bin";
+ Intermediate mProperties;
@Override
- public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ public boolean onHandleStep(RoundEnvironment roundEnv, ProcessingEnvironment processingEnv,
+ BindingBuildInfo buildInfo) {
+ if (mProperties == null) {
+ mProperties = new IntermediateV1(buildInfo.modulePackage());
+ }
for (Element element : roundEnv.getElementsAnnotatedWith(Bindable.class)) {
Element enclosingElement = element.getEnclosingElement();
ElementKind kind = enclosingElement.getKind();
if (kind != ElementKind.CLASS && kind != ElementKind.INTERFACE) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "Bindable must be on a member field or method. The enclosing type is " +
- enclosingElement.getKind(), element);
- continue;
+ 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);
}
}
- if (roundEnv.processingOver()) {
- writeIntermediateFile(mProperties);
- generateBR(mProperties);
+ return false;
+ }
+
+ @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());
}
- return true;
}
- private void generateBR(Intermediate intermediate) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,
- "************* Generating BR file from Bindable attributes");
+ private String createIntermediateFileName(String appPkg) {
+ return appPkg + INTERMEDIATE_FILE_EXT;
+ }
+
+ private void generateBRClasses(boolean useFinalFields, String pkg) {
+ L.d("************* Generating BR file %s. use final: %s", pkg, useFinalFields);
HashSet<String> properties = new HashSet<>();
- intermediate.captureProperties(properties);
- mergeClassPathResources(properties);
- try {
- ArrayList<String> sortedProperties = new ArrayList<String>();
- sortedProperties.addAll(properties);
- Collections.sort(sortedProperties);
-
- JavaFileObject fileObject = processingEnv.getFiler()
- .createSourceFile("android.binding.BR");
- Writer writer = fileObject.openWriter();
- writer.write("package android.binding;\n\n" +
- "public final class BR {\n" +
- " public static final int _all = 0;\n"
- );
- int id = 0;
- for (String property : sortedProperties) {
- id++;
- writer.write(" public static final int " + property + " = " + id + ";\n");
- }
- writer.write(" public static int getId(String key) {\n");
- writer.write(" switch(key) {\n");
- id = 0;
- for (String property : sortedProperties) {
- id++;
- writer.write(" case \"" + property + "\": return " + id + ";\n");
+ mProperties.captureProperties(properties);
+ List<Intermediate> previousIntermediates = loadPreviousBRFiles();
+ for (Intermediate intermediate : previousIntermediates) {
+ intermediate.captureProperties(properties);
+ }
+ writeBRClass(useFinalFields, pkg, properties);
+ if (useFinalFields) {
+ // generate BR for all previous packages
+ for (Intermediate intermediate : previousIntermediates) {
+ writeBRClass(true, intermediate.getPackage(),
+ properties);
}
- writer.write(" }\n");
- writer.write(" return -1;\n");
- writer.write(" }");
- writer.write("}\n");
-
- writer.close();
- } catch (IOException e) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "Could not generate BR file " + e.getLocalizedMessage());
}
}
+ private void writeBRClass(boolean useFinalFields, String pkg, HashSet<String> properties) {
+ ArrayList<String> sortedProperties = new ArrayList<String>();
+ sortedProperties.addAll(properties);
+ Collections.sort(sortedProperties);
+ StringBuilder out = new StringBuilder();
+ String modifier = "public static " + (useFinalFields ? "final" : "") + " int ";
+ out.append("package " + pkg + ";\n\n" +
+ "public class BR {\n" +
+ " " + modifier + "_all = 0;\n"
+ );
+ int id = 0;
+ for (String property : sortedProperties) {
+ id++;
+ out.append(" " + modifier + property + " = " + id + ";\n");
+ }
+ out.append(" public static int getId(String key) {\n");
+ out.append(" switch(key) {\n");
+ id = 0;
+ for (String property : sortedProperties) {
+ id++;
+ out.append(" case \"" + property + "\": return " + id + ";\n");
+ }
+ out.append(" }\n");
+ out.append(" return -1;\n");
+ out.append(" }");
+ out.append("}\n");
+
+ getWriter().writeToFile(pkg + ".BR", out.toString() );
+ }
+
private String getPropertyName(Element element) {
switch (element.getKind()) {
case FIELD:
@@ -126,8 +144,7 @@ public class ProcessBindable extends AbstractProcessor {
case METHOD:
return stripPrefixFromMethod((ExecutableElement) element);
default:
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "@Bindable is not allowed on " + element.getKind(), element);
+ L.e("@Bindable is not allowed on %s", element.getKind());
return null;
}
}
@@ -159,8 +176,7 @@ public class ProcessBindable extends AbstractProcessor {
} else if (isBooleanGetter(element)) {
propertyName = name.subSequence(2, name.length());
} else {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "@Bindable associated with method must follow JavaBeans convention", element);
+ L.e("@Bindable associated with method must follow JavaBeans convention %s", element);
return null;
}
char firstChar = propertyName.charAt(0);
@@ -207,102 +223,32 @@ public class ProcessBindable extends AbstractProcessor {
element.getReturnType().getKind() == TypeKind.BOOLEAN;
}
- private Intermediate readIntermediateFile() {
- Intermediate properties = null;
- ObjectInputStream in = null;
- try {
- FileObject intermediate = processingEnv.getFiler()
- .getResource(StandardLocation.CLASS_OUTPUT,
- ProcessBindable.class.getPackage().getName(), "binding_properties.bin");
- if (new File(intermediate.getName()).exists()) {
- in = new ObjectInputStream(intermediate.openInputStream());
- properties = (Intermediate) in.readObject();
- }
- } catch (IOException e) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "Could not read Binding properties intermediate file: " +
- e.getLocalizedMessage());
- } catch (ClassNotFoundException e) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "Could not read Binding properties intermediate file: " +
- e.getLocalizedMessage());
- } finally {
- try {
- if (in != null) {
- in.close();
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (properties == null) {
- properties = new IntermediateV1();
- }
- return properties;
+ private List<Intermediate> loadPreviousBRFiles() {
+ return GenerationalClassUtil
+ .loadObjects(getClass().getClassLoader(),
+ new GenerationalClassUtil.ExtensionFilter(INTERMEDIATE_FILE_EXT));
}
- private void mergeClassPathResources(HashSet<String> intermediateProperties) {
- try {
- String resourcePath = ProcessBindable.class.getPackage().getName()
- .replace('.', '/') + "/binding_properties.bin";
- Enumeration<URL> resources = getClass().getClassLoader()
- .getResources(resourcePath);
- while (resources.hasMoreElements()) {
- URL url = resources.nextElement();
- processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,
- "Merging binding adapters from " + url);
- InputStream inputStream = null;
- try {
- inputStream = url.openStream();
- ObjectInputStream in = new ObjectInputStream(inputStream);
- Intermediate properties = (Intermediate) in.readObject();
- if (properties != null) {
- properties.captureProperties(intermediateProperties);
- }
- } catch (IOException e) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "Could not merge in Bindables from " + url + ": " +
- e.getLocalizedMessage());
- } catch (ClassNotFoundException e) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "Could not read Binding properties intermediate file: " +
- e.getLocalizedMessage());
- } finally {
- IOUtils.closeQuietly(inputStream);
- }
- }
- } catch (IOException e) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "Could not read Binding properties intermediate file: " +
- e.getLocalizedMessage());
- }
- }
+ private interface Intermediate extends Serializable {
- private void writeIntermediateFile(Intermediate properties) {
- try {
- FileObject intermediate = processingEnv.getFiler().createResource(
- StandardLocation.CLASS_OUTPUT, ProcessBindable.class.getPackage().getName(),
- "binding_properties.bin");
- ObjectOutputStream out = new ObjectOutputStream(intermediate.openOutputStream());
- out.writeObject(properties);
- out.close();
- } catch (IOException e) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "Could not write to intermediate file: " + e.getLocalizedMessage());
- }
- }
-
- private interface Intermediate {
void captureProperties(Set<String> properties);
void addProperty(String className, String propertyName);
+
+ String getPackage();
}
private static class IntermediateV1 implements Serializable, Intermediate {
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 2L;
+
+ private String mPackage;
private final HashMap<String, HashSet<String>> mProperties = new HashMap<>();
+ public IntermediateV1(String aPackage) {
+ mPackage = aPackage;
+ }
+
@Override
public void captureProperties(Set<String> properties) {
for (HashSet<String> propertySet : mProperties.values()) {
@@ -319,5 +265,10 @@ public class ProcessBindable extends AbstractProcessor {
}
properties.add(propertyName);
}
+
+ @Override
+ public String getPackage() {
+ return mPackage;
+ }
}
}
diff --git a/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessDataBinding.java b/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessDataBinding.java
new file mode 100644
index 00000000..dd648408
--- /dev/null
+++ b/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessDataBinding.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.annotationprocessor;
+
+import com.android.databinding.reflection.ModelAnalyzer;
+import com.android.databinding.writer.AnnotationJavaFileWriter;
+import com.android.databinding.writer.JavaFileWriter;
+
+import android.binding.BindingBuildInfo;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+
+@SupportedAnnotationTypes({
+ "android.binding.BindingAdapter",
+ "android.binding.Untaggable",
+ "android.binding.BindingMethods",
+ "android.binding.BindingConversion",
+ "android.binding.BindingBuildInfo"}
+)
+@SupportedSourceVersion(SourceVersion.RELEASE_7)
+/**
+ * Parent annotation processor that dispatches sub steps to ensure execution order.
+ * Use initProcessingSteps to add a new step.
+ */
+public class ProcessDataBinding extends AbstractProcessor {
+ private List<ProcessingStep> mProcessingSteps;
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (mProcessingSteps == null) {
+ initProcessingSteps();
+ }
+ final BindingBuildInfo buildInfo = BuildInfoUtil.load(roundEnv);
+ if (buildInfo == null) {
+ return false;
+ }
+ boolean done = true;
+ for (ProcessingStep step : mProcessingSteps) {
+ done = step.runStep(roundEnv, processingEnv, buildInfo) && done;
+ }
+ if (roundEnv.processingOver()) {
+ for (ProcessingStep step : mProcessingSteps) {
+ step.onProcessingOver(roundEnv, processingEnv, buildInfo);
+ }
+ }
+ return done;
+ }
+
+ private void initProcessingSteps() {
+ mProcessingSteps = Arrays.asList(
+ new ProcessMethodAdapters(),
+ new ProcessExpressions(),
+ new ProcessBindable()
+ );
+ AnnotationJavaFileWriter javaFileWriter = new AnnotationJavaFileWriter(processingEnv);
+ for (ProcessingStep step : mProcessingSteps) {
+ step.mJavaFileWriter = javaFileWriter;
+ }
+ }
+
+ @Override
+ public synchronized void init(ProcessingEnvironment processingEnv) {
+ super.init(processingEnv);
+ ModelAnalyzer.setProcessingEnvironment(processingEnv);
+ }
+
+ /**
+ * To ensure execution order and binding build information, we use processing steps.
+ */
+ public abstract static class ProcessingStep {
+ private boolean mDone;
+ private JavaFileWriter mJavaFileWriter;
+
+ protected JavaFileWriter getWriter() {
+ return mJavaFileWriter;
+ }
+
+ private boolean runStep(RoundEnvironment roundEnvironment,
+ ProcessingEnvironment processingEnvironment,
+ BindingBuildInfo buildInfo) {
+ if (mDone) {
+ return true;
+ }
+ mDone = onHandleStep(roundEnvironment, processingEnvironment, buildInfo);
+ return mDone;
+ }
+
+ /**
+ * Invoked in each annotation processing step.
+ *
+ * @return True if it is done and should never be invoked again.
+ */
+ abstract public boolean onHandleStep(RoundEnvironment roundEnvironment,
+ ProcessingEnvironment processingEnvironment,
+ BindingBuildInfo buildInfo);
+
+ /**
+ * Invoked when processing is done. A good place to generate the output if the
+ * processor requires multiple steps.
+ */
+ abstract public void onProcessingOver(RoundEnvironment roundEnvironment,
+ ProcessingEnvironment processingEnvironment,
+ BindingBuildInfo buildInfo);
+ }
+}
diff --git a/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessExpressions.java b/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessExpressions.java
index 2b047bb2..7f5ab94d 100644
--- a/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessExpressions.java
+++ b/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessExpressions.java
@@ -19,114 +19,171 @@ package com.android.databinding.annotationprocessor;
import com.android.databinding.CompilerChef;
import com.android.databinding.reflection.SdkUtil;
import com.android.databinding.store.ResourceBundle;
+import com.android.databinding.util.GenerationalClassUtil;
import com.android.databinding.util.L;
-import com.android.databinding.writer.AnnotationJavaFileWriter;
-import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
-import android.binding.BinderBundle;
-import android.binding.BindingAppInfo;
+import android.binding.BindingBuildInfo;
-import java.io.ByteArrayInputStream;
import java.io.File;
+import java.io.FilenameFilter;
import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.util.Set;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
-import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
-import javax.annotation.processing.SupportedAnnotationTypes;
-import javax.annotation.processing.SupportedSourceVersion;
-import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.TypeElement;
-import javax.tools.Diagnostic;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
-@SupportedAnnotationTypes({"android.binding.BinderBundle", "android.binding.BindingAppInfo"})
-@SupportedSourceVersion(SourceVersion.RELEASE_7)
-public class ProcessExpressions extends AbstractProcessor {
+public class ProcessExpressions extends ProcessDataBinding.ProcessingStep {
- public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
- ResourceBundle resourceBundle = null;
- for (Element element : roundEnv.getElementsAnnotatedWith(BindingAppInfo.class)) {
- final BindingAppInfo appInfo = element.getAnnotation(BindingAppInfo.class);
- if (appInfo == null) {
- continue; // It gets confused between BindingAppInfo and BinderBundle
+ private static final String LAYOUT_INFO_FILE_SUFFIX = "-layoutinfo.bin";
+
+ @Override
+ public boolean onHandleStep(RoundEnvironment roundEnvironment,
+ ProcessingEnvironment processingEnvironment, BindingBuildInfo buildInfo) {
+ ResourceBundle resourceBundle;
+ SdkUtil.initialize(buildInfo.minSdk(), new File(buildInfo.sdkRoot()));
+ resourceBundle = new ResourceBundle(buildInfo.modulePackage());
+ List<Intermediate> intermediateList =
+ GenerationalClassUtil.loadObjects(getClass().getClassLoader(),
+ new GenerationalClassUtil.ExtensionFilter(LAYOUT_INFO_FILE_SUFFIX));
+ IntermediateV1 mine = createIntermediateFromLayouts(buildInfo.layoutInfoDir());
+ if (mine != null) {
+ mine.removeOverridden(intermediateList);
+ intermediateList.add(mine);
+ saveIntermediate(processingEnvironment, buildInfo, mine);
+ }
+ // generate them here so that bindable parser can read
+ try {
+ generateBinders(resourceBundle, buildInfo, intermediateList);
+ } catch (Throwable t) {
+ L.e(t, "cannot generate view binders");
+ }
+ return true;
+ }
+
+ private void saveIntermediate(ProcessingEnvironment processingEnvironment,
+ BindingBuildInfo buildInfo, IntermediateV1 intermediate) {
+ GenerationalClassUtil.writeIntermediateFile(processingEnvironment,
+ buildInfo.modulePackage(), buildInfo.modulePackage() + LAYOUT_INFO_FILE_SUFFIX,
+ intermediate);
+ }
+
+ @Override
+ public void onProcessingOver(RoundEnvironment roundEnvironment,
+ ProcessingEnvironment processingEnvironment, BindingBuildInfo buildInfo) {
+
+ }
+
+ private void generateBinders(ResourceBundle resourceBundle, BindingBuildInfo buildInfo,
+ List<Intermediate> intermediates)
+ throws Throwable {
+ for (Intermediate intermediate : intermediates) {
+ intermediate.appendTo(resourceBundle);
+ }
+ writeResourceBundle(resourceBundle, buildInfo.isLibrary());
+ }
+
+ private IntermediateV1 createIntermediateFromLayouts(String layoutInfoFolderPath) {
+ final File layoutInfoFolder = new File(layoutInfoFolderPath);
+ if (!layoutInfoFolder.isDirectory()) {
+ L.d("layout info folder does not exist, skipping for %s", layoutInfoFolderPath);
+ return null;
+ }
+ IntermediateV1 result = new IntermediateV1();
+ for (File layoutFile : layoutInfoFolder.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.endsWith(".xml");
}
- SdkUtil.initialize(appInfo.minSdk(), new File(appInfo.sdkRoot()));
- if (element.getKind() != ElementKind.CLASS) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "BindingAppInfo associated with wrong type. Should be a class.", element);
- continue;
+ })) {
+ try {
+ result.addEntry(layoutFile.getName(), FileUtils.readFileToString(layoutFile));
+ } catch (IOException e) {
+ L.e(e, "cannot load layout file information. Try a clean build");
}
- if (resourceBundle == null) {
- resourceBundle = new ResourceBundle(appInfo.applicationPackage());
- processLayouts(resourceBundle, roundEnv);
- } else {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "BindingAppInfo must be applied to only one class.", element);
+ }
+ return result;
+ }
+
+ private void writeResourceBundle(ResourceBundle resourceBundle, boolean forLibraryModule)
+ throws JAXBException {
+ CompilerChef compilerChef = CompilerChef.createChef(resourceBundle, getWriter());
+ if (compilerChef.hasAnythingToGenerate()) {
+ compilerChef.writeViewBinderInterfaces();
+ if (!forLibraryModule) {
+ compilerChef.writeDbrFile();
+ compilerChef.writeViewBinders();
}
}
+ }
- return true;
+ public static interface Intermediate extends Serializable {
+
+ Intermediate upgrade();
+
+ public void appendTo(ResourceBundle resourceBundle) throws Throwable;
}
- private void processLayouts(ResourceBundle resourceBundle, RoundEnvironment roundEnv) {
- Unmarshaller unmarshaller = null;
- for (Element element : roundEnv.getElementsAnnotatedWith(BinderBundle.class)) {
- final BinderBundle binderBundle = element.getAnnotation(BinderBundle.class);
- if (binderBundle == null) {
- continue;
- }
- if (element.getKind() != ElementKind.CLASS) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "BinderBundle associated with wrong type. Should be a class.", element);
- continue;
+ public static class IntermediateV1 implements Intermediate {
+
+ transient Unmarshaller mUnmarshaller;
+
+ // name to xml content map
+ Map<String, String> mLayoutInfoMap = new HashMap<>();
+
+ @Override
+ public Intermediate upgrade() {
+ return this;
+ }
+
+ @Override
+ public void appendTo(ResourceBundle resourceBundle) throws JAXBException {
+ if (mUnmarshaller == null) {
+ JAXBContext context = JAXBContext
+ .newInstance(ResourceBundle.LayoutFileBundle.class);
+ mUnmarshaller = context.createUnmarshaller();
}
- ByteArrayInputStream in = null;
- try {
- if (unmarshaller == null) {
- JAXBContext context =
- JAXBContext.newInstance(ResourceBundle.LayoutFileBundle.class);
- unmarshaller = context.createUnmarshaller();
- }
- String binderBundle64 = binderBundle.value();
- byte[] buf = Base64.decodeBase64(binderBundle64);
- in = new ByteArrayInputStream(buf);
- Reader reader = new InputStreamReader(in);
- ResourceBundle.LayoutFileBundle layoutFileBundle
- = (ResourceBundle.LayoutFileBundle)
- unmarshaller.unmarshal(reader);
- resourceBundle
- .addLayoutBundle(layoutFileBundle, layoutFileBundle.getLayoutId());
- } catch (Exception e) {
- StringWriter stringWriter = new StringWriter();
- e.printStackTrace(new PrintWriter(stringWriter));
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "Could not generate Binders from binder data store: " +
- stringWriter.getBuffer().toString(), element);
- } finally {
- if (in != null) {
- IOUtils.closeQuietly(in);
+ for (String content : mLayoutInfoMap.values()) {
+ final InputStream is = IOUtils.toInputStream(content);
+ try {
+ final ResourceBundle.LayoutFileBundle bundle
+ = (ResourceBundle.LayoutFileBundle) mUnmarshaller.unmarshal(is);
+ resourceBundle.addLayoutBundle(bundle, bundle.getLayoutId());
+ L.d("loaded layout info file %s", bundle);
+ } finally {
+ IOUtils.closeQuietly(is);
}
}
+ }
+ public void addEntry(String name, String contents) {
+ mLayoutInfoMap.put(name, contents);
}
- CompilerChef compilerChef = CompilerChef.createChef(resourceBundle,
- new AnnotationJavaFileWriter(processingEnv));
- if (compilerChef.hasAnythingToGenerate()) {
- compilerChef.writeDbrFile();
- compilerChef.writeViewBinderInterfaces();
- compilerChef.writeViewBinders();
+ public void removeOverridden(List<Intermediate> existing) {
+ // this is the way we get rid of files that are copied from previous modules
+ // it is important to do this before saving the intermediate file
+ for (Intermediate old : existing) {
+ if (old instanceof IntermediateV1) {
+ IntermediateV1 other = (IntermediateV1) old;
+ for (String key : other.mLayoutInfoMap.keySet()) {
+ // TODO we should consider the original file as the key here
+ // but aapt probably cannot provide that information
+ if (mLayoutInfoMap.remove(key) != null) {
+ L.d("removing %s from bundle because it came from another module", key);
+ }
+ }
+ }
+ }
}
}
}
diff --git a/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessMethodAdapters.java b/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessMethodAdapters.java
index 6ed56323..a13e3a2a 100644
--- a/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessMethodAdapters.java
+++ b/annotationprocessor/src/main/java/com/android/databinding/annotationprocessor/ProcessMethodAdapters.java
@@ -15,24 +15,25 @@
*/
package com.android.databinding.annotationprocessor;
+import com.google.common.base.Preconditions;
+
import android.binding.BindingAdapter;
+import android.binding.BindingBuildInfo;
import android.binding.BindingConversion;
import android.binding.BindingMethod;
import android.binding.BindingMethods;
import android.binding.Untaggable;
+import com.android.databinding.reflection.ModelAnalyzer;
import com.android.databinding.store.SetterStore;
+import com.android.databinding.util.L;
import java.io.IOException;
import java.util.HashSet;
import java.util.List;
-import java.util.Set;
-import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
-import javax.annotation.processing.SupportedAnnotationTypes;
-import javax.annotation.processing.SupportedSourceVersion;
-import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
@@ -42,50 +43,46 @@ import javax.lang.model.element.VariableElement;
import javax.lang.model.type.TypeKind;
import javax.tools.Diagnostic;
-@SupportedAnnotationTypes({
- "android.binding.BindingAdapter",
- "android.binding.Untaggable",
- "android.binding.BindingMethods",
- "android.binding.BindingConversion"})
-@SupportedSourceVersion(SourceVersion.RELEASE_7)
-public class ProcessMethodAdapters extends AbstractProcessor {
- private boolean mProcessed;
-
+public class ProcessMethodAdapters extends ProcessDataBinding.ProcessingStep {
public ProcessMethodAdapters() {
}
@Override
- public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
- if (mProcessed) {
- return true;
- }
-
- SetterStore store = SetterStore.get(processingEnv);
+ public boolean onHandleStep(RoundEnvironment roundEnv,
+ ProcessingEnvironment processingEnvironment, BindingBuildInfo buildInfo) {
+ L.d("processing adapters");
+ final ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance();
+ Preconditions.checkNotNull(modelAnalyzer, "Model analyzer should be"
+ + " initialized first");
+ SetterStore store = SetterStore.get(modelAnalyzer);
clearIncrementalClasses(roundEnv, store);
- addBindingAdapters(roundEnv, store);
- addRenamed(roundEnv, store);
- addConversions(roundEnv, store);
- addUntaggable(roundEnv, store);
+ addBindingAdapters(roundEnv, processingEnvironment, store);
+ addRenamed(roundEnv, processingEnvironment, store);
+ addConversions(roundEnv, processingEnvironment, store);
+ addUntaggable(roundEnv, processingEnvironment, store);
try {
- store.write(processingEnv);
+ store.write(buildInfo.modulePackage(), processingEnvironment);
} catch (IOException e) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "Could not write BindingAdapter intermediate file: " + e.getLocalizedMessage());
- e.printStackTrace();
+ L.e(e, "Could not write BindingAdapter intermediate file.");
}
- mProcessed = true;
return true;
}
- private void addBindingAdapters(RoundEnvironment roundEnv, SetterStore store) {
+ @Override
+ public void onProcessingOver(RoundEnvironment roundEnvironment,
+ ProcessingEnvironment processingEnvironment, BindingBuildInfo buildInfo) {
+
+ }
+
+ private void addBindingAdapters(RoundEnvironment roundEnv, ProcessingEnvironment
+ processingEnv, SetterStore store) {
for (Element element : roundEnv.getElementsAnnotatedWith(BindingAdapter.class)) {
if (element.getKind() != ElementKind.METHOD ||
!element.getModifiers().contains(Modifier.STATIC) ||
!element.getModifiers().contains(Modifier.PUBLIC)) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "@BindingAdapter on invalid element: " + element);
+ L.e("@BindingAdapter on invalid element: %s", element);
continue;
}
BindingAdapter bindingAdapter = element.getAnnotation(BindingAdapter.class);
@@ -93,22 +90,20 @@ public class ProcessMethodAdapters extends AbstractProcessor {
ExecutableElement executableElement = (ExecutableElement) element;
List<? extends VariableElement> parameters = executableElement.getParameters();
if (parameters.size() != 2) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "@BindingAdapter does not take two parameters: " + element);
+ L.e("@BindingAdapter does not take two parameters: %s",element);
continue;
}
try {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,
- "------------------ @BindingAdapter for " + element);
+ L.d("------------------ @BindingAdapter for %s", element);
store.addBindingAdapter(bindingAdapter.value(), executableElement);
} catch (IllegalArgumentException e) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "@BindingAdapter for duplicate View and parameter type: " + element);
+ L.e(e, "@BindingAdapter for duplicate View and parameter type: %s", element);
}
}
}
- private void addRenamed(RoundEnvironment roundEnv, SetterStore store) {
+ private void addRenamed(RoundEnvironment roundEnv, ProcessingEnvironment processingEnv,
+ SetterStore store) {
for (Element element : roundEnv.getElementsAnnotatedWith(BindingMethods.class)) {
BindingMethods bindingMethods = element.getAnnotation(BindingMethods.class);
for (BindingMethod bindingMethod : bindingMethods.value()) {
@@ -118,7 +113,8 @@ public class ProcessMethodAdapters extends AbstractProcessor {
}
}
- private void addConversions(RoundEnvironment roundEnv, SetterStore store) {
+ private void addConversions(RoundEnvironment roundEnv,
+ ProcessingEnvironment processingEnv, SetterStore store) {
for (Element element : roundEnv.getElementsAnnotatedWith(BindingConversion.class)) {
if (element.getKind() != ElementKind.METHOD ||
!element.getModifiers().contains(Modifier.STATIC) ||
@@ -145,7 +141,8 @@ public class ProcessMethodAdapters extends AbstractProcessor {
}
}
- private void addUntaggable(RoundEnvironment roundEnv, SetterStore store) {
+ private void addUntaggable(RoundEnvironment roundEnv,
+ ProcessingEnvironment processingEnv, SetterStore store) {
for (Element element : roundEnv.getElementsAnnotatedWith(Untaggable.class)) {
Untaggable untaggable = element.getAnnotation(Untaggable.class);
store.addUntaggableTypes(untaggable.value(), (TypeElement) element);
diff --git a/annotationprocessor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/annotationprocessor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
index 7b825401..27f59e00 100644
--- a/annotationprocessor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
+++ b/annotationprocessor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -1,3 +1 @@
-com.android.databinding.annotationprocessor.ProcessBindable
-com.android.databinding.annotationprocessor.ProcessMethodAdapters
-com.android.databinding.annotationprocessor.ProcessExpressions
+com.android.databinding.annotationprocessor.ProcessDataBinding \ No newline at end of file
diff --git a/baseLibrary/build.gradle b/baseLibrary/build.gradle
index 66f61b38..ecb7205b 100644
--- a/baseLibrary/build.gradle
+++ b/baseLibrary/build.gradle
@@ -46,7 +46,6 @@ sourceSets {
}
dependencies {
- compile 'com.tunnelvisionlabs:antlr4:4.4'
testCompile 'junit:junit:4.11'
}
diff --git a/baseLibrary/src/main/java/android/binding/BindingAppInfo.java b/baseLibrary/src/main/java/android/binding/BindingBuildInfo.java
index a90f3328..62b6043f 100644
--- a/baseLibrary/src/main/java/android/binding/BindingAppInfo.java
+++ b/baseLibrary/src/main/java/android/binding/BindingBuildInfo.java
@@ -7,12 +7,12 @@
*
* 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,
+ * 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.binding;
import java.lang.annotation.ElementType;
@@ -22,9 +22,15 @@ import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.SOURCE)
-public @interface BindingAppInfo {
+public @interface BindingBuildInfo {
String buildId();
- String applicationPackage();
+ String modulePackage();
String sdkRoot();
int minSdk();
+
+ /**
+ * The folder that includes xml files which are exported by aapt or gradle plugin from layout files
+ */
+ String layoutInfoDir();
+ boolean isLibrary();
}
diff --git a/build.gradle b/build.gradle
index b86af2b1..c63b74b4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,13 +3,12 @@ databindingProperties.load(new FileInputStream("${projectDir}/databinding.proper
databindingProperties.mavenRepoDir = "${projectDir}/${databindingProperties.mavenRepoName}"
ext.config = databindingProperties
-
println "local maven repo is ${ext.config.mavenRepoDir}."
new File(ext.config.mavenRepoDir).mkdir()
subprojects {
apply plugin: 'maven'
- group = 'com.android.databinding'
+ group = config.group
version = config.snapshotVersion
repositories {
mavenCentral()
@@ -30,14 +29,22 @@ task deleteRepo(type: Delete) {
delete "${config.mavenRepoDir}"
}
+def buildExtensionsTask = project.tasks.create "buildExtensionsTask", Exec
+buildExtensionsTask.workingDir file('extensions').getAbsolutePath()
+//on linux
+buildExtensionsTask.commandLine './gradlew'
+buildExtensionsTask.args 'clean', 'uploadArchives', '--info', '--stacktrace'
+buildExtensionsTask.dependsOn subprojects.uploadArchives
+
file('integration-tests').listFiles().findAll { it.isDirectory() }.each {
- println("${it.getAbsolutePath()}")
+ println("Creating run test task for ${it.getAbsolutePath()}.")
def testTask = project.tasks.create "runTestsOf${it.getName().capitalize()}", Exec
- testTask.workingDir 'integration-tests/TestApp'
+ testTask.workingDir it.getAbsolutePath()
//on linux
testTask.commandLine './gradlew'
- testTask.args 'clean', 'connectedCheck', '--info'
+ testTask.args 'clean', 'connectedCheck', '--info', '--stacktrace'
testTask.dependsOn subprojects.uploadArchives
+ testTask.dependsOn buildExtensionsTask
}
task runIntegrationTests {
@@ -51,11 +58,17 @@ task runAllTests {
allprojects {
afterEvaluate { project ->
runAllTests.dependsOn project.tasks.findAll {task -> task.name.equals('test')}
+ runAllTests.dependsOn project.tasks.findAll {task -> task.name.equals('connectedCheck')}
}
}
+subprojects.uploadArchives.each { it.shouldRunAfter deleteRepo }
+buildExtensionsTask.shouldRunAfter deleteRepo
+tasks['runTestsOfMultiModuleTestApp'].shouldRunAfter tasks['runTestsOfIndependentLibrary']
+
task rebuildRepo() {
dependsOn deleteRepo
dependsOn subprojects.uploadArchives
+ dependsOn buildExtensionsTask
} \ No newline at end of file
diff --git a/compiler/src/main/java/com/android/databinding/LayoutBinder.java b/compiler/src/main/java/com/android/databinding/LayoutBinder.java
index a285e165..a2aa2485 100644
--- a/compiler/src/main/java/com/android/databinding/LayoutBinder.java
+++ b/compiler/src/main/java/com/android/databinding/LayoutBinder.java
@@ -43,6 +43,7 @@ public class LayoutBinder {
private final ExpressionParser mExpressionParser;
private final List<BindingTarget> mBindingTargets;
private String mPackage;
+ private String mModulePackage;
private String mProjectPackage;
private String mBaseClassName;
private final HashMap<String, String> mUserDefinedVariables = new HashMap<String, String>();
@@ -57,7 +58,8 @@ public class LayoutBinder {
mBindingTargets = new ArrayList<BindingTarget>();
mBundle = layoutBundle;
mProjectPackage = resourceBundle.getAppPackage();
- mPackage = mProjectPackage + ".generated";
+ mModulePackage = layoutBundle.getModulePackage();
+ mPackage = layoutBundle.getModulePackage() + ".generated";
mBaseClassName = ParserHelper.INSTANCE$.toClassName(layoutBundle.getFileName()) + "Binding";
// copy over data.
for (Map.Entry<String, String> variable : mBundle.getVariables().entrySet()) {
@@ -159,6 +161,10 @@ public class LayoutBinder {
return mPackage;
}
+ public String getModulePackage() {
+ return mModulePackage;
+ }
+
public void setPackage(String aPackage) {
mPackage = aPackage;
}
diff --git a/compiler/src/main/java/com/android/databinding/LayoutXmlProcessor.java b/compiler/src/main/java/com/android/databinding/LayoutXmlProcessor.java
index ed170bff..d0ce5068 100644
--- a/compiler/src/main/java/com/android/databinding/LayoutXmlProcessor.java
+++ b/compiler/src/main/java/com/android/databinding/LayoutXmlProcessor.java
@@ -20,15 +20,16 @@ import com.android.databinding.store.LayoutFileParser;
import com.android.databinding.store.ResourceBundle;
import com.android.databinding.writer.JavaFileWriter;
-import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringEscapeUtils;
import org.xml.sax.SAXException;
+import android.binding.BindingBuildInfo;
+
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.StringWriter;
-import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -44,24 +45,51 @@ import javax.xml.xpath.XPathExpressionException;
* processor to work with.
*/
public class LayoutXmlProcessor {
-
- public static final String RESOURCE_BUNDLE_PACKAGE = "com.android.databinding.layouts.";
- public static final String APPLICATION_INFO_CLASS = "ApplicationBindingInfo";
+ // hardcoded in baseAdapters
+ public static final String RESOURCE_BUNDLE_PACKAGE = "com.android.databinding.layouts";
+ public static final String CLASS_NAME = "DataBindingInfo";
private final JavaFileWriter mFileWriter;
private final ResourceBundle mResourceBundle;
private final int mMinSdk;
private boolean mProcessingComplete;
private boolean mWritten;
+ private final boolean mIsLibrary;
private final String mBuildId = UUID.randomUUID().toString();
- private final List<File> mResourceFolders;
+ // can be a list of xml files or folders that contain XML files
+ private final List<File> mResources;
- public LayoutXmlProcessor(String applicationPackage, List<File> resourceFolders,
- JavaFileWriter fileWriter, int minSdk) {
+ public LayoutXmlProcessor(String applicationPackage, List<File> resources,
+ JavaFileWriter fileWriter, int minSdk, boolean isLibrary) {
mFileWriter = fileWriter;
mResourceBundle = new ResourceBundle(applicationPackage);
- mResourceFolders = resourceFolders;
+ mResources = resources;
mMinSdk = minSdk;
+ mIsLibrary = isLibrary;
+ }
+
+ public static List<File> getLayoutFiles(List<File> resources) {
+ List<File> result = new ArrayList<File>();
+ for (File resource : Iterables.filter(resources, fileExists)) {
+ if (resource.isDirectory()) {
+ for (File layoutFolder : resource.listFiles(layoutFolderFilter)) {
+ for (File xmlFile : layoutFolder.listFiles(xmlFileFilter)) {
+ result.add(xmlFile);
+ }
+
+ }
+ } else if (xmlFileFilter.accept(resource.getParentFile(), resource.getName())) {
+ result.add(resource);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * used by the studio plugin
+ */
+ public ResourceBundle getResourceBundle() {
+ return mResourceBundle;
}
public boolean processResources()
@@ -72,92 +100,101 @@ public class LayoutXmlProcessor {
}
LayoutFileParser layoutFileParser = new LayoutFileParser();
int layoutId = 0;
- for (File resFolder : Iterables.filter(mResourceFolders, fileExists)) {
- for (File layoutFolder : resFolder.listFiles(layoutFolderFilter)) {
- for (File xmlFile : layoutFolder.listFiles(xmlFileFilter)) {
- final ResourceBundle.LayoutFileBundle bindingLayout = layoutFileParser
- .parseXml(xmlFile, mResourceBundle.getAppPackage(), layoutId);
- if (bindingLayout != null && !bindingLayout.isEmpty()) {
- mResourceBundle.addLayoutBundle(bindingLayout, layoutId);
- layoutId++;
- }
- }
+ for (File xmlFile : getLayoutFiles(mResources)) {
+ final ResourceBundle.LayoutFileBundle bindingLayout = layoutFileParser
+ .parseXml(xmlFile, mResourceBundle.getAppPackage(), layoutId);
+ if (bindingLayout != null && !bindingLayout.isEmpty()) {
+ mResourceBundle.addLayoutBundle(bindingLayout, layoutId);
+ layoutId++;
}
}
mProcessingComplete = true;
return true;
}
- public ResourceBundle getResourceBundle() {
- return mResourceBundle;
- }
-
- public void writeIntermediateFile(File sdkDir) throws JAXBException {
+ public void writeIntermediateFile(File sdkDir, File xmlOutDir) throws JAXBException {
if (mWritten) {
return;
}
JAXBContext context = JAXBContext.newInstance(ResourceBundle.LayoutFileBundle.class);
Marshaller marshaller = context.createMarshaller();
- writeAppInfo(marshaller, sdkDir);
+ writeInfoClass(marshaller, sdkDir, xmlOutDir);
for (List<ResourceBundle.LayoutFileBundle> layouts : mResourceBundle.getLayoutBundles()
.values()) {
for (ResourceBundle.LayoutFileBundle layout : layouts) {
- writeAnnotatedFile(layout, marshaller);
+ writeXmlFile(xmlOutDir, layout, marshaller);
}
}
mWritten = true;
}
- private void writeAnnotatedFile(ResourceBundle.LayoutFileBundle layout, Marshaller marshaller)
+ private void writeXmlFile(File xmlOutDir, ResourceBundle.LayoutFileBundle layout,
+ Marshaller marshaller) throws JAXBException {
+ String filename = generateExportFileName(layout) + ".xml";
+ String xml = toXML(layout, marshaller);
+ mFileWriter.writeToFile(new File(xmlOutDir, filename), xml);
+ }
+
+ public String getInfoClassFullName() {
+ return RESOURCE_BUNDLE_PACKAGE + "." + CLASS_NAME;
+ }
+
+ private String toXML(ResourceBundle.LayoutFileBundle layout, Marshaller marshaller)
throws JAXBException {
- StringBuilder className = new StringBuilder(layout.getFileName());
- className.append('-').append(layout.getDirectory());
- for (int i = className.length() - 1; i >= 0; i--) {
- char c = className.charAt(i);
+ StringWriter writer = new StringWriter();
+ marshaller.marshal(layout, writer);
+ return writer.getBuffer().toString();
+ }
+
+ /**
+ * Generates a string identifier that can uniquely identify the given layout bundle.
+ * This identifier can be used when we need to export data about this layout bundle.
+ */
+ private String generateExportFileName(ResourceBundle.LayoutFileBundle layout) {
+ StringBuilder name = new StringBuilder(layout.getFileName());
+ name.append('-').append(layout.getDirectory());
+ for (int i = name.length() - 1; i >= 0; i--) {
+ char c = name.charAt(i);
if (c == '-') {
- className.deleteCharAt(i);
- c = Character.toUpperCase(className.charAt(i));
- className.setCharAt(i, c);
+ name.deleteCharAt(i);
+ c = Character.toUpperCase(name.charAt(i));
+ name.setCharAt(i, c);
}
}
- className.setCharAt(0, Character.toUpperCase(className.charAt(0)));
- StringWriter writer = new StringWriter();
- marshaller.marshal(layout, writer);
- String xml = writer.getBuffer().toString();
- String classString = "import android.binding.BinderBundle;\n\n" +
- "@BinderBundle(\"" +
- Base64.encodeBase64String(xml.getBytes(StandardCharsets.UTF_8)) +
- "\")\n" +
- "public class " + className + " {}\n";
- mFileWriter.writeToFile(RESOURCE_BUNDLE_PACKAGE + className, classString);
+ return name.toString();
}
- private void writeAppInfo(Marshaller marshaller, File sdkDir) {
+ private void writeInfoClass(Marshaller marshaller, File sdkDir, File xmlOutDir) {
final String sdkPath = StringEscapeUtils.escapeJava(sdkDir.getAbsolutePath());
- String classString = "import android.binding.BindingAppInfo;\n\n" +
- "@BindingAppInfo(buildId=\"" + mBuildId + "\", " +
- "applicationPackage=\"" + mResourceBundle.getAppPackage() + "\", " +
+ final Class annotation = BindingBuildInfo.class;
+ final String layoutInfoPath = StringEscapeUtils.escapeJava(xmlOutDir.getAbsolutePath());
+ String classString = "package " + RESOURCE_BUNDLE_PACKAGE + ";\n\n" +
+ "import " + annotation.getCanonicalName() + ";\n\n" +
+ "@" + annotation.getSimpleName() + "(buildId=\"" + mBuildId + "\", " +
+ "modulePackage=\"" + mResourceBundle.getAppPackage() + "\", " +
"sdkRoot=\"" + sdkPath + "\", " +
+ "layoutInfoDir=\"" + layoutInfoPath + "\"," +
+ "isLibrary=" + mIsLibrary + "," +
"minSdk=" + mMinSdk + ")\n" +
- "public class " + APPLICATION_INFO_CLASS + " {}\n";
- mFileWriter.writeToFile(RESOURCE_BUNDLE_PACKAGE + APPLICATION_INFO_CLASS, classString);
+ "public class " + CLASS_NAME + " {}\n";
+ mFileWriter.writeToFile(mResourceBundle.getAppPackage() + "." + CLASS_NAME, classString);
}
- private final Predicate<File> fileExists = new Predicate<File>() {
+ private static final Predicate<File> fileExists = new Predicate<File>() {
@Override
public boolean apply(File input) {
return input.exists() && input.canRead();
}
};
- private final FilenameFilter layoutFolderFilter = new FilenameFilter() {
+ private static final FilenameFilter layoutFolderFilter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.startsWith("layout");
}
};
- private final FilenameFilter xmlFileFilter = new FilenameFilter() {
+ private static final FilenameFilter xmlFileFilter = new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".xml");
diff --git a/compiler/src/main/java/com/android/databinding/reflection/ModelAnalyzer.java b/compiler/src/main/java/com/android/databinding/reflection/ModelAnalyzer.java
index 63cbc38b..9a7ef2f4 100644
--- a/compiler/src/main/java/com/android/databinding/reflection/ModelAnalyzer.java
+++ b/compiler/src/main/java/com/android/databinding/reflection/ModelAnalyzer.java
@@ -209,8 +209,6 @@ public abstract class ModelAnalyzer {
public abstract ModelClass findClass(String className, Map<String, String> imports);
- public abstract List<URL> getResources(String name);
-
public abstract ModelClass findClass(Class classType);
public abstract TypeUtil createTypeUtil();
diff --git a/compiler/src/main/java/com/android/databinding/reflection/annotation/AnnotationAnalyzer.java b/compiler/src/main/java/com/android/databinding/reflection/annotation/AnnotationAnalyzer.java
index ca40f2e8..92c6aa8c 100644
--- a/compiler/src/main/java/com/android/databinding/reflection/annotation/AnnotationAnalyzer.java
+++ b/compiler/src/main/java/com/android/databinding/reflection/annotation/AnnotationAnalyzer.java
@@ -439,21 +439,6 @@ public class AnnotationAnalyzer extends ModelAnalyzer {
}
@Override
- public List<URL> getResources(String name) {
- ArrayList<URL> urls = new ArrayList<URL>();
- try {
- Enumeration<URL> resources = getClass().getClassLoader().getResources(name);
- while (resources.hasMoreElements()) {
- urls.add(resources.nextElement());
- }
- } catch (IOException e) {
- L.e(e, "IOException while getting resources:");
- }
-
- return urls;
- }
-
- @Override
public ModelClass findClass(Class classType) {
return findClass(classType.getCanonicalName(), null);
}
diff --git a/compiler/src/main/java/com/android/databinding/store/LayoutFileParser.java b/compiler/src/main/java/com/android/databinding/store/LayoutFileParser.java
index 752562ba..99efe6ba 100644
--- a/compiler/src/main/java/com/android/databinding/store/LayoutFileParser.java
+++ b/compiler/src/main/java/com/android/databinding/store/LayoutFileParser.java
@@ -67,7 +67,7 @@ public class LayoutFileParser {
ResourceBundle.LayoutFileBundle bundle = new ResourceBundle.LayoutFileBundle(
ParserHelper.INSTANCE$.stripExtension(xml.getName()), layoutId,
- xml.getParentFile().getName());
+ xml.getParentFile().getName(), pkg);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
diff --git a/compiler/src/main/java/com/android/databinding/store/ResourceBundle.java b/compiler/src/main/java/com/android/databinding/store/ResourceBundle.java
index 767cc34e..a781417b 100644
--- a/compiler/src/main/java/com/android/databinding/store/ResourceBundle.java
+++ b/compiler/src/main/java/com/android/databinding/store/ResourceBundle.java
@@ -57,7 +57,15 @@ public class ResourceBundle implements Serializable {
mLayoutBundles.put(bundle.mFileName, new ArrayList<LayoutFileBundle>());
}
bundle.mLayoutId = layoutId;
- mLayoutBundles.get(bundle.mFileName).add(bundle);
+ final List<LayoutFileBundle> bundles = mLayoutBundles.get(bundle.mFileName);
+ for (LayoutFileBundle existing : bundles) {
+ if (existing.equals(bundle)) {
+ L.d("skipping layout bundle %s because it already exists.", bundle);
+ return;
+ }
+ }
+ L.d("adding bundle %s", bundle);
+ bundles.add(bundle);
}
public HashMap<String, List<LayoutFileBundle>> getLayoutBundles() {
@@ -200,6 +208,8 @@ public class ResourceBundle implements Serializable {
public int mLayoutId;
@XmlAttribute(name="layout", required = true)
public String mFileName;
+ @XmlAttribute(name="modulePackage", required = true)
+ public String mModulePackage;
private String mConfigName;
@XmlAttribute(name="directory", required = true)
@@ -222,10 +232,12 @@ public class ResourceBundle implements Serializable {
public LayoutFileBundle() {
}
- public LayoutFileBundle(String fileName, int layoutId, String directory) {
+ public LayoutFileBundle(String fileName, int layoutId, String directory,
+ String modulePackage) {
mFileName = fileName;
mLayoutId = layoutId;
mDirectory = directory;
+ mModulePackage = modulePackage;
}
public void addVariable(String name, String type) {
@@ -288,6 +300,57 @@ public class ResourceBundle implements Serializable {
public List<BindingTargetBundle> getBindingTargetBundles() {
return mBindingTargetBundles;
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ LayoutFileBundle bundle = (LayoutFileBundle) o;
+
+ if (mConfigName != null ? !mConfigName.equals(bundle.mConfigName)
+ : bundle.mConfigName != null) {
+ return false;
+ }
+ if (mDirectory != null ? !mDirectory.equals(bundle.mDirectory)
+ : bundle.mDirectory != null) {
+ return false;
+ }
+ if (mFileName != null ? !mFileName.equals(bundle.mFileName)
+ : bundle.mFileName != null) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mFileName != null ? mFileName.hashCode() : 0;
+ result = 31 * result + (mConfigName != null ? mConfigName.hashCode() : 0);
+ result = 31 * result + (mDirectory != null ? mDirectory.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "LayoutFileBundle{" +
+ "mHasVariations=" + mHasVariations +
+ ", mDirectory='" + mDirectory + '\'' +
+ ", mConfigName='" + mConfigName + '\'' +
+ ", mModulePackage='" + mModulePackage + '\'' +
+ ", mFileName='" + mFileName + '\'' +
+ ", mLayoutId=" + mLayoutId +
+ '}';
+ }
+
+ public String getModulePackage() {
+ return mModulePackage;
+ }
}
@XmlAccessorType(XmlAccessType.NONE)
diff --git a/compiler/src/main/java/com/android/databinding/store/SetterStore.java b/compiler/src/main/java/com/android/databinding/store/SetterStore.java
index fe14b7e5..a34c8c58 100644
--- a/compiler/src/main/java/com/android/databinding/store/SetterStore.java
+++ b/compiler/src/main/java/com/android/databinding/store/SetterStore.java
@@ -18,6 +18,7 @@ package com.android.databinding.store;
import com.android.databinding.reflection.ModelAnalyzer;
import com.android.databinding.reflection.ModelClass;
import com.android.databinding.reflection.ModelMethod;
+import com.android.databinding.util.GenerationalClassUtil;
import com.android.databinding.util.L;
import org.apache.commons.lang3.StringUtils;
@@ -30,6 +31,7 @@ import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -50,7 +52,7 @@ import javax.tools.StandardLocation;
public class SetterStore {
- public static final String SETTER_STORE_FILE_NAME = "setter_store.bin";
+ public static final String SETTER_STORE_FILE_EXT = "-setter_store.bin";
private static SetterStore sStore;
@@ -62,70 +64,24 @@ public class SetterStore {
mStore = store;
}
- public static SetterStore get(ProcessingEnvironment processingEnvironment) {
- if (sStore == null) {
- InputStream in = null;
- try {
- Filer filer = processingEnvironment.getFiler();
- FileObject resource = filer.getResource(StandardLocation.CLASS_OUTPUT,
- SetterStore.class.getPackage().getName(), SETTER_STORE_FILE_NAME);
- if (resource != null && new File(resource.getName()).exists()) {
- in = resource.openInputStream();
- if (in != null) {
- sStore = load(in);
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- if (sStore == null) {
- sStore = new SetterStore(null, new IntermediateV1());
- }
- }
- return sStore;
- }
-
public static SetterStore get(ModelAnalyzer modelAnalyzer) {
if (sStore == null) {
- sStore = load(modelAnalyzer);
+ sStore = load(modelAnalyzer, SetterStore.class.getClassLoader());
}
return sStore;
}
- private static SetterStore load(ModelAnalyzer modelAnalyzer) {
+ private static SetterStore load(ModelAnalyzer modelAnalyzer, ClassLoader classLoader) {
IntermediateV1 store = new IntermediateV1();
- String resourceName = SetterStore.class.getPackage().getName().replace('.', '/') +
- '/' + SETTER_STORE_FILE_NAME;
- try {
- for (URL resource : modelAnalyzer.getResources(resourceName)) {
- merge(store, resource);
- }
- return new SetterStore(modelAnalyzer, store);
- } catch (IOException e) {
- L.e(e, "Could not read SetterStore intermediate file");
- } catch (ClassNotFoundException e) {
- L.e(e, "Could not read SetterStore intermediate file");
+ List<Intermediate> previousStores = GenerationalClassUtil
+ .loadObjects(classLoader,
+ new GenerationalClassUtil.ExtensionFilter(SETTER_STORE_FILE_EXT));
+ for (Intermediate intermediate : previousStores) {
+ merge(store, intermediate);
}
return new SetterStore(modelAnalyzer, store);
}
- private static SetterStore load(InputStream inputStream)
- throws IOException, ClassNotFoundException {
- ObjectInputStream in = new ObjectInputStream(inputStream);
- Intermediate intermediate = (Intermediate) in.readObject();
- return new SetterStore(null, (IntermediateV1) intermediate.upgrade());
- }
-
public void addRenamedMethod(String attribute, String declaringClass, String method,
TypeElement declaredOn) {
HashMap<String, MethodDescription> renamed = mStore.renamedMethods.get(attribute);
@@ -135,10 +91,12 @@ public class SetterStore {
}
MethodDescription methodDescription =
new MethodDescription(declaredOn.getQualifiedName().toString(), method);
+ L.d("STORE addmethod desc %s", methodDescription);
renamed.put(declaringClass, methodDescription);
}
public void addBindingAdapter(String attribute, ExecutableElement bindingMethod) {
+ L.d("STORE addBindingAdapter %s %s", attribute, bindingMethod);
HashMap<AccessorKey, MethodDescription> adapters = mStore.adapterMethods.get(attribute);
if (adapters == null) {
@@ -158,6 +116,7 @@ public class SetterStore {
}
public void addUntaggableTypes(String[] typeNames, TypeElement declaredOn) {
+ L.d("STORE addUntaggableTypes %s %s", Arrays.toString(typeNames), declaredOn);
String declaredType = declaredOn.getQualifiedName().toString();
for (String type : typeNames) {
mStore.untaggableTypes.put(type, declaredType);
@@ -187,6 +146,7 @@ public class SetterStore {
}
public void addConversionMethod(ExecutableElement conversionMethod) {
+ L.d("STORE addConversionMethod %s", conversionMethod);
List<? extends VariableElement> parameters = conversionMethod.getParameters();
String fromType = getQualifiedName(parameters.get(0).asType());
String toType = getQualifiedName(conversionMethod.getReturnType());
@@ -248,21 +208,10 @@ public class SetterStore {
keys.clear();
}
- public void write(ProcessingEnvironment processingEnvironment) throws IOException {
- Filer filer = processingEnvironment.getFiler();
- FileObject resource = filer.createResource(StandardLocation.CLASS_OUTPUT,
- SetterStore.class.getPackage().getName(), "setter_store.bin");
- L.d("============= Writing intermediate file: %s", resource.getName());
- ObjectOutputStream out = null;
- try {
- out = new ObjectOutputStream(resource.openOutputStream());
-
- out.writeObject(mStore);
- } finally {
- if (out != null) {
- out.close();
- }
- }
+ public void write(String projectPackage, ProcessingEnvironment processingEnvironment)
+ throws IOException {
+ GenerationalClassUtil.writeIntermediateFile(processingEnvironment,
+ projectPackage, projectPackage + SETTER_STORE_FILE_EXT, mStore);
}
public SetterCall getSetterCall(String attribute, ModelClass viewType,
@@ -503,27 +452,12 @@ public class SetterStore {
}
}
- private static void merge(IntermediateV1 store,
- URL nextUrl) throws IOException, ClassNotFoundException {
- InputStream inputStream = null;
- JarFile jarFile = null;
- try {
- inputStream = nextUrl.openStream();
- ObjectInputStream in = new ObjectInputStream(inputStream);
- Intermediate intermediate = (Intermediate) in.readObject();
- IntermediateV1 intermediateV1 = (IntermediateV1) intermediate.upgrade();
- merge(store.adapterMethods, intermediateV1.adapterMethods);
- merge(store.renamedMethods, intermediateV1.renamedMethods);
- merge(store.conversionMethods, intermediateV1.conversionMethods);
- store.untaggableTypes.putAll(intermediateV1.untaggableTypes);
- } finally {
- if (inputStream != null) {
- inputStream.close();
- }
- if (jarFile != null) {
- jarFile.close();
- }
- }
+ private static void merge(IntermediateV1 store, Intermediate dumpStore) {
+ IntermediateV1 intermediateV1 = (IntermediateV1) dumpStore.upgrade();
+ merge(store.adapterMethods, intermediateV1.adapterMethods);
+ merge(store.renamedMethods, intermediateV1.renamedMethods);
+ merge(store.conversionMethods, intermediateV1.conversionMethods);
+ store.untaggableTypes.putAll(intermediateV1.untaggableTypes);
}
private static <K, V> void merge(HashMap<K, HashMap<V, MethodDescription>> first,
@@ -619,7 +553,7 @@ public class SetterStore {
}
}
- private interface Intermediate {
+ private interface Intermediate extends Serializable {
Intermediate upgrade();
}
diff --git a/compiler/src/main/java/com/android/databinding/util/GenerationalClassUtil.java b/compiler/src/main/java/com/android/databinding/util/GenerationalClassUtil.java
new file mode 100644
index 00000000..c970ad53
--- /dev/null
+++ b/compiler/src/main/java/com/android/databinding/util/GenerationalClassUtil.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.util;
+
+import com.android.databinding.util.L;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.filefilter.IOFileFilter;
+import org.apache.commons.io.filefilter.TrueFileFilter;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+
+/**
+ * A utility class that helps adding build specific objects to the jar file
+ * and their extraction later on.
+ */
+public class GenerationalClassUtil {
+ public static <T extends Serializable> List<T> loadObjects(ClassLoader classLoader, Filter filter) {
+ final List<T> result = new ArrayList<T>();
+ if (!(classLoader instanceof URLClassLoader)) {
+ L.d("class loader is not url class loader (%s). skipping.", classLoader.getClass());
+ return result;
+ }
+ final URLClassLoader urlClassLoader = (URLClassLoader) classLoader;
+ for (URL url : urlClassLoader.getURLs()) {
+ L.d("checking url %s for intermediate data", url);
+ try {
+ final File file = new File(url.toURI());
+ if (!file.exists()) {
+ L.d("cannot load file for %s", url);
+ continue;
+ }
+ if (file.isDirectory()) {
+ // probably exported classes dir.
+ loadFromDirectory(filter, result, file);
+ } else {
+ // assume it is a zip file
+ loadFomZipFile(filter, result, file);
+ }
+ } catch (IOException e) {
+ L.d("cannot open zip file from %s", url);
+ } catch (URISyntaxException e) {
+ L.d("cannot open zip file from %s", url);
+ }
+ }
+ return result;
+ }
+
+ private static <T extends Serializable> void loadFromDirectory(final Filter filter, List<T> result,
+ File directory) {
+ //noinspection unchecked
+ Collection<File> files = FileUtils.listFiles(directory, new IOFileFilter() {
+ @Override
+ public boolean accept(File file) {
+ return filter.accept(file.getName());
+ }
+
+ @Override
+ public boolean accept(File dir, String name) {
+ return filter.accept(name);
+ }
+ }, TrueFileFilter.INSTANCE);
+ for (File file : files) {
+ InputStream inputStream = null;
+ try {
+ inputStream = FileUtils.openInputStream(file);
+ T item = fromInputStream(result, inputStream);
+ L.d("loaded item %s from file", item);
+ if (item != null) {
+ result.add(item);
+ }
+ } catch (IOException e) {
+ L.e(e, "Could not merge in Bindables from %s", file.getAbsolutePath());
+ } catch (ClassNotFoundException e) {
+ L.e(e, "Could not read Binding properties intermediate file. %s", file.getAbsolutePath());
+ } finally {
+ IOUtils.closeQuietly(inputStream);
+ }
+ }
+ }
+
+ private static <T extends Serializable> void loadFomZipFile(Filter filter,
+ List<T> result, File file) throws IOException {
+ ZipFile zipFile = new ZipFile(file);
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ if (!filter.accept(entry.getName())) {
+ continue;
+ }
+ L.d("loading data from file %s", entry.getName());
+ InputStream inputStream = null;
+ try {
+ inputStream = zipFile.getInputStream(entry);
+ T item = fromInputStream(result, inputStream);
+ L.d("loaded item %s from zip file", item);
+ if (item != null) {
+ result.add(item);
+ }
+ } catch (IOException e) {
+ L.e(e, "Could not merge in Bindables from %s", file.getAbsolutePath());
+ } catch (ClassNotFoundException e) {
+ L.e(e, "Could not read Binding properties intermediate file. %s", file.getAbsolutePath());
+ } finally {
+ IOUtils.closeQuietly(inputStream);
+ }
+ }
+ }
+
+ private static <T extends Serializable> T fromInputStream(List<T> result,
+ InputStream inputStream) throws IOException, ClassNotFoundException {
+ ObjectInputStream in = new ObjectInputStream(inputStream);
+ return (T) in.readObject();
+
+ }
+
+ public static void writeIntermediateFile(ProcessingEnvironment processingEnv,
+ String packageName, String fileName, Serializable object) {
+ ObjectOutputStream oos = null;
+ try {
+ FileObject intermediate = processingEnv.getFiler().createResource(
+ StandardLocation.CLASS_OUTPUT, packageName,
+ fileName);
+ OutputStream ios = intermediate.openOutputStream();
+ oos = new ObjectOutputStream(ios);
+ oos.writeObject(object);
+ oos.close();
+ L.d("wrote intermediate bindable file %s %s", packageName, fileName);
+ } catch (IOException e) {
+ L.e(e, "Could not write to intermediate file: %s", fileName);
+ } finally {
+ IOUtils.closeQuietly(oos);
+ }
+ }
+
+
+ public static interface Filter {
+ public boolean accept(String entryName);
+ }
+
+ public static class ExtensionFilter implements Filter {
+ private final String mExtension;
+ public ExtensionFilter(String extension) {
+ mExtension = extension;
+ }
+
+ @Override
+ public boolean accept(String entryName) {
+ return entryName.endsWith(mExtension);
+ }
+ }
+}
diff --git a/compiler/src/main/java/com/android/databinding/writer/AnnotationJavaFileWriter.java b/compiler/src/main/java/com/android/databinding/writer/AnnotationJavaFileWriter.java
index 67d274ed..d24ac04a 100644
--- a/compiler/src/main/java/com/android/databinding/writer/AnnotationJavaFileWriter.java
+++ b/compiler/src/main/java/com/android/databinding/writer/AnnotationJavaFileWriter.java
@@ -15,8 +15,14 @@
*/
package com.android.databinding.writer;
+import com.google.common.base.Preconditions;
+
+import com.android.databinding.util.L;
+
+import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
+import java.io.File;
import java.io.IOException;
import java.io.Writer;
@@ -24,7 +30,7 @@ import javax.annotation.processing.ProcessingEnvironment;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
-public class AnnotationJavaFileWriter implements JavaFileWriter {
+public class AnnotationJavaFileWriter extends JavaFileWriter {
private final ProcessingEnvironment mProcessingEnvironment;
public AnnotationJavaFileWriter(ProcessingEnvironment processingEnvironment) {
@@ -35,13 +41,13 @@ public class AnnotationJavaFileWriter implements JavaFileWriter {
public void writeToFile(String canonicalName, String contents) {
Writer writer = null;
try {
+ L.d("writing file %s", canonicalName);
JavaFileObject javaFileObject =
mProcessingEnvironment.getFiler().createSourceFile(canonicalName);
writer = javaFileObject.openWriter();
writer.write(contents);
} catch (IOException e) {
- mProcessingEnvironment.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "Could not write to " + canonicalName + ": " + e.getLocalizedMessage());
+ L.e(e, "Could not write to %s", canonicalName);
} finally {
if (writer != null) {
IOUtils.closeQuietly(writer);
diff --git a/compiler/src/main/java/com/android/databinding/writer/JavaFileWriter.java b/compiler/src/main/java/com/android/databinding/writer/JavaFileWriter.java
index f7b3c9ce..9fa93477 100644
--- a/compiler/src/main/java/com/android/databinding/writer/JavaFileWriter.java
+++ b/compiler/src/main/java/com/android/databinding/writer/JavaFileWriter.java
@@ -13,6 +13,23 @@
package com.android.databinding.writer;
-public interface JavaFileWriter {
- public void writeToFile(String canonicalName, String contents);
+import com.android.databinding.util.L;
+
+import org.apache.commons.io.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+
+public abstract class JavaFileWriter {
+ public abstract void writeToFile(String canonicalName, String contents);
+ public void writeToFile(File exactPath, String contents) {
+ File parent = exactPath.getParentFile();
+ parent.mkdirs();
+ try {
+ L.d("writing file %s", exactPath.getAbsoluteFile());
+ FileUtils.writeStringToFile(exactPath, contents);
+ } catch (IOException e) {
+ L.e(e, "Could not write to %s", exactPath);
+ }
+ }
}
diff --git a/compiler/src/main/kotlin/com/android/databinding/ext/ext.kt b/compiler/src/main/kotlin/com/android/databinding/ext/ext.kt
index b7abeb7e..11804ff9 100644
--- a/compiler/src/main/kotlin/com/android/databinding/ext/ext.kt
+++ b/compiler/src/main/kotlin/com/android/databinding/ext/ext.kt
@@ -77,4 +77,4 @@ public fun String.toCamelCaseAsVar() : String {
}
public fun String.br() : String =
- "android.binding.BR.${if (this == "") "_all" else this}"
+ "BR.${if (this == "") "_all" else this}"
diff --git a/compiler/src/main/kotlin/com/android/databinding/util/XmlEditor.kt b/compiler/src/main/kotlin/com/android/databinding/util/XmlEditor.kt
index b1531fc4..ad79405f 100644
--- a/compiler/src/main/kotlin/com/android/databinding/util/XmlEditor.kt
+++ b/compiler/src/main/kotlin/com/android/databinding/util/XmlEditor.kt
@@ -131,7 +131,8 @@ object XmlEditor {
Preconditions.checkNotNull(rootNodeContext, "Cannot find root node for ${f.getName()}")
Preconditions.checkState(rootNodeHasTag == false, """You cannot set a tag in the layout
root if you are using binding. Invalid file: ${f}""")
- val rootNodeBounds = Pair(rootNodeContext!!.getStart().toPosition(), rootNodeContext!!.getStop().toEndPosition())
+ val rootNodeBounds = Pair(rootNodeContext!!.getStart().toPosition(),
+ rootNodeContext!!.getStop().toEndPosition())
log { "root node bounds: ${rootNodeBounds}" }
val out = StringBuilder()
diff --git a/compiler/src/main/kotlin/com/android/databinding/writer/DataBinderWriter.kt b/compiler/src/main/kotlin/com/android/databinding/writer/DataBinderWriter.kt
index d52a6122..7b3638e3 100644
--- a/compiler/src/main/kotlin/com/android/databinding/writer/DataBinderWriter.kt
+++ b/compiler/src/main/kotlin/com/android/databinding/writer/DataBinderWriter.kt
@@ -19,13 +19,13 @@ class DataBinderWriter(val pkg: String, val projectPackage: String, val classNam
fun write() =
kcode("") {
nl("package $pkg;")
- nl("import $projectPackage.R;")
+ nl("import $projectPackage.BR;")
nl("public class $className implements com.android.databinding.library.DataBinderMapper {") {
tab("@Override")
tab("public com.android.databinding.library.ViewDataBinding getDataBinder(android.view.View view, int layoutId) {") {
tab("switch(layoutId) {") {
layoutBinders.groupBy{it.getLayoutname()}.forEach {
- tab("case R.layout.${it.value.first!!.getLayoutname()}:") {
+ tab("case ${it.value.first!!.getModulePackage()}.R.layout.${it.value.first!!.getLayoutname()}:") {
if (it.value.size() == 1) {
tab("return new ${it.value.first!!.getPackage()}.${it.value.first!!.getClassName()}(view);")
} else {
@@ -51,7 +51,7 @@ class DataBinderWriter(val pkg: String, val projectPackage: String, val classNam
tab("}")
tab("public int getId(String key) {") {
- tab("return android.binding.BR.getId(key);")
+ tab("return BR.getId(key);")
} tab("}")
}
nl("}")
diff --git a/compiler/src/main/kotlin/com/android/databinding/writer/LayoutBinderWriter.kt b/compiler/src/main/kotlin/com/android/databinding/writer/LayoutBinderWriter.kt
index fec3b460..e82de91d 100644
--- a/compiler/src/main/kotlin/com/android/databinding/writer/LayoutBinderWriter.kt
+++ b/compiler/src/main/kotlin/com/android/databinding/writer/LayoutBinderWriter.kt
@@ -331,7 +331,8 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder) {
public fun write() : String {
layoutBinder.resolveWhichExpressionsAreUsed()
return kcode("package ${layoutBinder.getPackage()};") {
- nl("import ${layoutBinder.getProjectPackage()}.R;")
+ nl("import ${layoutBinder.getModulePackage()}.R;")
+ nl("import ${layoutBinder.getModulePackage()}.BR;")
nl("import android.view.View;")
nl("public class ${className} extends ${baseClassName} {") {
tab(declareIncludeViews())
@@ -401,7 +402,7 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder) {
if (originalTag != null) {
tagValue = "\"${originalTag}\""
if (originalTag.startsWith("@")) {
- var packageName = layoutBinder.getProjectPackage()
+ var packageName = layoutBinder.getModulePackage()
if (originalTag.startsWith("@android:")) {
packageName = "android"
}
@@ -749,15 +750,15 @@ class LayoutBinderWriter(val layoutBinder : LayoutBinder) {
}
nl("")
tab("public static ${baseClassName} inflate(android.view.ViewGroup root) {") {
- tab("return DataBindingUtil.<${baseClassName}>inflate(root.getContext(), ${layoutBinder.getProjectPackage()}.R.layout.${layoutBinder.getLayoutname()}, root, true);")
+ tab("return DataBindingUtil.<${baseClassName}>inflate(root.getContext(), ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, root, true);")
}
tab("}")
tab("public static ${baseClassName} inflate(android.content.Context context) {") {
- tab("return DataBindingUtil.<${baseClassName}>inflate(context, ${layoutBinder.getProjectPackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false);")
+ tab("return DataBindingUtil.<${baseClassName}>inflate(context, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()}, null, false);")
}
tab("}")
tab("public static ${baseClassName} bind(android.view.View view) {") {
- tab("return (${baseClassName})DataBindingUtil.bindTo(view, ${layoutBinder.getProjectPackage()}.R.layout.${layoutBinder.getLayoutname()});")
+ tab("return (${baseClassName})DataBindingUtil.bindTo(view, ${layoutBinder.getModulePackage()}.R.layout.${layoutBinder.getLayoutname()});")
}
tab("}")
nl("}")
diff --git a/compiler/src/test/java/com/android/databinding/MockLayoutBinder.java b/compiler/src/test/java/com/android/databinding/MockLayoutBinder.java
index 6ef97d23..dc57437a 100644
--- a/compiler/src/test/java/com/android/databinding/MockLayoutBinder.java
+++ b/compiler/src/test/java/com/android/databinding/MockLayoutBinder.java
@@ -19,6 +19,6 @@ public class MockLayoutBinder extends LayoutBinder {
public MockLayoutBinder() {
super(new ResourceBundle("com.test"),
- new ResourceBundle.LayoutFileBundle("blah.xml", 1, "."));
+ new ResourceBundle.LayoutFileBundle("blah.xml", 1, ".", "com.test.submodule"));
}
} \ No newline at end of file
diff --git a/compiler/src/test/java/com/android/databinding/reflection/java/JavaAnalyzer.java b/compiler/src/test/java/com/android/databinding/reflection/java/JavaAnalyzer.java
index c6c7cf17..1e88f84f 100644
--- a/compiler/src/test/java/com/android/databinding/reflection/java/JavaAnalyzer.java
+++ b/compiler/src/test/java/com/android/databinding/reflection/java/JavaAnalyzer.java
@@ -314,23 +314,6 @@ public class JavaAnalyzer extends ModelAnalyzer {
}
}
- @Override
- public List<URL> getResources(String name) {
- List<URL> urlList = new ArrayList<URL>();
- Enumeration<URL> urls = null;
- try {
- urls = mClassLoader.getResources(name);
- if (urls != null) {
- while (urls.hasMoreElements()) {
- urlList.add(urls.nextElement());
- }
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- return urlList;
- }
-
public static void initForTests() {
Map<String, String> env = System.getenv();
for (Map.Entry<String, String> entry : env.entrySet()) {
diff --git a/databinding.properties b/databinding.properties
index 7974fa99..d0c3576c 100644
--- a/databinding.properties
+++ b/databinding.properties
@@ -6,3 +6,6 @@ androidPluginVersion = 1.0.1
javaTargetCompatibility = 1.6
javaSourceCompatibility = 1.6
mavenRepoName=maven-repo
+group=com.android.databinding
+testGroup=com.android.databinding.test
+
diff --git a/extensions/baseAdapters/build.gradle b/extensions/baseAdapters/build.gradle
new file mode 100644
index 00000000..74e90365
--- /dev/null
+++ b/extensions/baseAdapters/build.gradle
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+
+apply plugin: 'maven'
+apply plugin: 'com.android.library'
+apply plugin: 'com.android.databinding'
+
+android {
+ compileSdkVersion 21
+ buildToolsVersion "21.1.2"
+
+ defaultConfig {
+ minSdkVersion 7
+ targetSdkVersion 21
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ packagingOptions {
+ exclude 'META-INF/services/javax.annotation.processing.Processor'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/NOTICE.txt'
+ }
+}
+
+dependencies {
+ compile "com.android.databinding:baseLibrary:${config.snapshotVersion}"
+ provided "com.android.databinding:annotationprocessor:${config.snapshotVersion}"
+ compile 'com.android.support:support-v4:+'
+ compile 'com.android.support:cardview-v7:+'
+ compile 'com.android.support:appcompat-v7:+'
+}
+
+configurations {
+ jarArchives
+}
+
+
+//create jar tasks
+android.libraryVariants.all { variant ->
+ def name = variant.buildType.name
+
+ if (name.equals(com.android.builder.core.BuilderConstants.DEBUG)) {
+ return; // Skip debug builds.
+ }
+ // @Jar version is needed to run compiler tests
+ def task = project.tasks.create "jar${name.capitalize()}", Jar
+ task.dependsOn variant.javaCompile
+ task.from variant.javaCompile.destinationDir
+ def packageName = "com.android.databinding.library.baseAdapters"
+ def appPkgAsClass = packageName.replace('.', '/')
+ task.exclude("com/android/databinding/layouts/*.*")
+ task.exclude("$appPkgAsClass/generated/*")
+ task.exclude("$appPkgAsClass/BR.*")
+ artifacts.add('jarArchives', task);
+}
+
+uploadArchives {
+}
+
+uploadJarArchives {
+ repositories {
+ mavenDeployer {
+ repository(url: "file://${config.mavenRepoDir}")
+ pom.artifactId = "adapters"
+ pom.whenConfigured {
+ println("configured pom, $it")
+ it.dependencies.find {dep -> dep.groupId == 'com.android.support' && dep.artifactId == 'support-v4' }.optional = true
+ it.dependencies.find {dep -> dep.groupId == 'com.android.support' && dep.artifactId == 'cardview-v7' }.optional = true
+ it.dependencies.find {dep -> dep.groupId == 'com.android.support' && dep.artifactId == 'appcompat-v7' }.optional = true
+ }
+ }
+ }
+}
+
+uploadArchives.dependsOn uploadJarArchives
diff --git a/extensions/baseAdapters/src/main/AndroidManifest.xml b/extensions/baseAdapters/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..38cf7790
--- /dev/null
+++ b/extensions/baseAdapters/src/main/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.databinding.library.baseAdapters">
+</manifest>
diff --git a/library/src/main/java/android/binding/adapters/AbsListViewBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/AbsListViewBindingAdapter.java
index c8b481d4..c8b481d4 100644
--- a/library/src/main/java/android/binding/adapters/AbsListViewBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/AbsListViewBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/AbsSeekBarBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/AbsSeekBarBindingAdapter.java
index f02be48c..f02be48c 100644
--- a/library/src/main/java/android/binding/adapters/AbsSeekBarBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/AbsSeekBarBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/AbsSpinnerBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/AbsSpinnerBindingAdapter.java
index b02ff074..b02ff074 100644
--- a/library/src/main/java/android/binding/adapters/AbsSpinnerBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/AbsSpinnerBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/AutoCompleteTextViewBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/AutoCompleteTextViewBindingAdapter.java
index 79c06a8a..79c06a8a 100644
--- a/library/src/main/java/android/binding/adapters/AutoCompleteTextViewBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/AutoCompleteTextViewBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/CardViewBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/CardViewBindingAdapter.java
index ba5246dd..ba5246dd 100644
--- a/library/src/main/java/android/binding/adapters/CardViewBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/CardViewBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/CheckedTextViewBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/CheckedTextViewBindingAdapter.java
index 3b16d080..3b16d080 100644
--- a/library/src/main/java/android/binding/adapters/CheckedTextViewBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/CheckedTextViewBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/CompoundButtonBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/CompoundButtonBindingAdapter.java
index 7115bc5c..7115bc5c 100644
--- a/library/src/main/java/android/binding/adapters/CompoundButtonBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/CompoundButtonBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/Converters.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/Converters.java
index 5982dc12..5982dc12 100644
--- a/library/src/main/java/android/binding/adapters/Converters.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/Converters.java
diff --git a/library/src/main/java/android/binding/adapters/FrameLayoutBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/FrameLayoutBindingAdapter.java
index 49aa6a5b..49aa6a5b 100644
--- a/library/src/main/java/android/binding/adapters/FrameLayoutBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/FrameLayoutBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/ImageViewBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/ImageViewBindingAdapter.java
index e2d09293..e2d09293 100644
--- a/library/src/main/java/android/binding/adapters/ImageViewBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/ImageViewBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/LinearLayoutBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/LinearLayoutBindingAdapter.java
index b0a4cc43..b0a4cc43 100644
--- a/library/src/main/java/android/binding/adapters/LinearLayoutBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/LinearLayoutBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/ProgressBarBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/ProgressBarBindingAdapter.java
index b0d6249e..b0d6249e 100644
--- a/library/src/main/java/android/binding/adapters/ProgressBarBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/ProgressBarBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/RadioGroupBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/RadioGroupBindingAdapter.java
index 8d21b7af..8d21b7af 100644
--- a/library/src/main/java/android/binding/adapters/RadioGroupBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/RadioGroupBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/SpinnerBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/SpinnerBindingAdapter.java
index 34a62c7e..34a62c7e 100644
--- a/library/src/main/java/android/binding/adapters/SpinnerBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/SpinnerBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/SwitchBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/SwitchBindingAdapter.java
index 3645118a..3645118a 100644
--- a/library/src/main/java/android/binding/adapters/SwitchBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/SwitchBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/SwitchCompatBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/SwitchCompatBindingAdapter.java
index 4c3c996a..4c3c996a 100644
--- a/library/src/main/java/android/binding/adapters/SwitchCompatBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/SwitchCompatBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/TabWidgetBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/TabWidgetBindingAdapter.java
index 8c58e915..8c58e915 100644
--- a/library/src/main/java/android/binding/adapters/TabWidgetBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/TabWidgetBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/TableLayoutBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/TableLayoutBindingAdapter.java
index 1973799e..1973799e 100644
--- a/library/src/main/java/android/binding/adapters/TableLayoutBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/TableLayoutBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/TextViewBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/TextViewBindingAdapter.java
index 1cd5ef4f..1cd5ef4f 100644
--- a/library/src/main/java/android/binding/adapters/TextViewBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/TextViewBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/ViewBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/ViewBindingAdapter.java
index 1e361cf2..1e361cf2 100644
--- a/library/src/main/java/android/binding/adapters/ViewBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/ViewBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/ViewGroupBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/ViewGroupBindingAdapter.java
index 4448a30d..4448a30d 100644
--- a/library/src/main/java/android/binding/adapters/ViewGroupBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/ViewGroupBindingAdapter.java
diff --git a/library/src/main/java/android/binding/adapters/ViewStubBindingAdapter.java b/extensions/baseAdapters/src/main/java/android/bindings/adapters/ViewStubBindingAdapter.java
index f24ab03b..f24ab03b 100644
--- a/library/src/main/java/android/binding/adapters/ViewStubBindingAdapter.java
+++ b/extensions/baseAdapters/src/main/java/android/bindings/adapters/ViewStubBindingAdapter.java
diff --git a/extensions/build.gradle b/extensions/build.gradle
new file mode 100644
index 00000000..cfa26978
--- /dev/null
+++ b/extensions/build.gradle
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+
+buildscript {
+ def Properties dataBindingProperties = new Properties()
+ dataBindingProperties.load(new FileInputStream("${projectDir}/../databinding.properties"))
+ dataBindingProperties.mavenRepoDir = "${projectDir}/../${dataBindingProperties.mavenRepoName}"
+ ext.config = dataBindingProperties
+ repositories {
+ jcenter()
+ maven {
+ url config.mavenRepoDir
+ }
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.1.3'
+ classpath "com.android.databinding:dataBinder:${config.snapshotVersion}"
+ }
+}
+
+subprojects {
+ apply plugin: 'maven'
+ group = config.group
+ version = config.snapshotVersion
+ repositories {
+ mavenCentral()
+ maven {
+ url config.mavenRepoDir
+ }
+ }
+} \ No newline at end of file
diff --git a/extensions/gradle/wrapper/gradle-wrapper.jar b/extensions/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..8c0fb64a
--- /dev/null
+++ b/extensions/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/extensions/gradle/wrapper/gradle-wrapper.properties b/extensions/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..e5fd8793
--- /dev/null
+++ b/extensions/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Mar 12 15:27:48 PDT 2015
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
diff --git a/extensions/gradlew b/extensions/gradlew
new file mode 100755
index 00000000..91a7e269
--- /dev/null
+++ b/extensions/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/extensions/settings.gradle b/extensions/settings.gradle
new file mode 100644
index 00000000..80ebcc8c
--- /dev/null
+++ b/extensions/settings.gradle
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+/**
+ * These are projects that requires a compiled version of data binding.
+ */
+include ':baseAdapters'
diff --git a/gradlePlugin/src/main/kotlin/DataBindingProcessLayoutsTask.kt b/gradlePlugin/src/main/kotlin/DataBindingProcessLayoutsTask.kt
index 7732f96f..d89552cd 100644
--- a/gradlePlugin/src/main/kotlin/DataBindingProcessLayoutsTask.kt
+++ b/gradlePlugin/src/main/kotlin/DataBindingProcessLayoutsTask.kt
@@ -32,6 +32,9 @@ open class DataBindingProcessLayoutsTask : DefaultTask() {
public fun doIt() {
Log.d {"running process layouts task"}
xmlProcessor.processResources()
- xmlProcessor.writeIntermediateFile(sdkDir)
+ }
+
+ public fun writeFiles(xmlOutFolder : File) {
+ xmlProcessor.writeIntermediateFile(sdkDir, xmlOutFolder)
}
} \ No newline at end of file
diff --git a/gradlePlugin/src/main/kotlin/plugin.kt b/gradlePlugin/src/main/kotlin/plugin.kt
index 3741ba95..b991ed60 100644
--- a/gradlePlugin/src/main/kotlin/plugin.kt
+++ b/gradlePlugin/src/main/kotlin/plugin.kt
@@ -54,10 +54,22 @@ import org.apache.commons.codec.binary.Base64
import com.android.builder.model.ApiVersion
import com.android.databinding.util.Log
import org.gradle.api.Action
+import com.android.build.gradle.BaseExtension
+import com.android.build.gradle.LibraryExtension
+import com.android.build.gradle.api.LibraryVariant
+import com.android.build.gradle.api.ApplicationVariant
+import com.android.build.gradle.api.BaseVariant
+import com.android.build.gradle.internal.variant.BaseVariantData
+import com.android.build.gradle.internal.variant.ApkVariantData
+import com.android.build.gradle.internal.variant.LibraryVariantData
+import com.android.build.gradle.internal.api.LibraryVariantImpl
+import com.android.build.gradle.api.TestVariant
+import com.android.build.gradle.internal.variant.TestVariantData
+import com.android.build.gradle.internal.api.TestVariantImpl
class DataBinderPlugin : Plugin<Project> {
- inner class GradleFileWriter(var outputBase: String) : JavaFileWriter {
+ inner class GradleFileWriter(var outputBase: String) : JavaFileWriter() {
override fun writeToFile(canonicalName: String, contents: String) {
val f = File("$outputBase/${canonicalName.replaceAll("\\.", "/")}.java")
log("Asked to write to ${canonicalName}. outputting to:${f.getAbsolutePath()}")
@@ -66,158 +78,148 @@ class DataBinderPlugin : Plugin<Project> {
}
}
- var xmlProcessor: LayoutXmlProcessor by Delegates.notNull()
- var project: Project by Delegates.notNull()
-
- var generatedBinderSrc: File by Delegates.notNull()
-
- var generatedBinderOut: File by Delegates.notNull()
-
- var androidJar: File by Delegates.notNull()
-
- var variantData: ApplicationVariantData by Delegates.notNull()
-
- var codeGenTargetFolder: File by Delegates.notNull()
-
- var viewBinderSource: File by Delegates.notNull()
-
- var sdkDir: File by Delegates.notNull()
-
- val viewBinderSourceRoot by Delegates.lazy {
- File(project.getBuildDir(), "databinder")
- }
-
-
- var fileWriter: GradleFileWriter by Delegates.notNull()
-
- val viewBinderCompileOutput by Delegates.lazy { File(viewBinderSourceRoot, "out") }
-
override fun apply(project: Project?) {
if (project == null) return
- val generateIntermediateFile = MethodClosure(this, "generateIntermediateFile")
- val preprocessLayoutFiles = MethodClosure(this, "preprocessLayoutFiles")
- this.project = project
project.afterEvaluate {
- // TODO read from app
- val variants = arrayListOf("Debug")
- xmlProcessor = createXmlProcessor(project)
- log("after eval")
- //processDebugResources
- variants.forEach { variant ->
- val processResTasks = it.getTasksByName("process${variant}Resources", true)
- processResTasks.forEach {
- Log.d { "${it} depends on ${it.getDependsOn()}" }
- }
- project.getTasks().create("processDataBinding${variant}Resources",
- javaClass<DataBindingProcessLayoutsTask>(),
- object : Action<DataBindingProcessLayoutsTask> {
- override fun execute(task: DataBindingProcessLayoutsTask) {
- task.xmlProcessor = xmlProcessor
- task.sdkDir = sdkDir
- processResTasks.forEach {
- // until we add these as a new source folder,
- // do it the old way
-
- // TODO uncomment this and comment below
- // it.dependsOn(task)
- it.doFirst(preprocessLayoutFiles)
- it.doLast(generateIntermediateFile)
- }
- processResTasks.forEach {
- it.getDependsOn().filterNot { it == task }.forEach {
- Log.d { "adding dependency on ${it} for ${task}" }
- task.dependsOn(it)
- }
- }
- }
- });
- }
+ createXmlProcessor(project)
}
}
fun log(s: String) {
- System.out.println("PLOG: $s")
+ System.out.println("[qwqw data binding]: $s")
}
- fun createXmlProcessor(p: Project): LayoutXmlProcessor {
- val ss = p.getExtensions().getByName("android") as AppExtension
- sdkDir = ss.getSdkDirectory()
- val minSdkVersion = ss.getDefaultConfig().getMinSdkVersion()
- androidJar = File(ss.getSdkDirectory().getAbsolutePath()
- + "/platforms/${ss.getCompileSdkVersion()}/android.jar")
- log("creating parser!")
+ fun createXmlProcessor(p: Project) {
+ val androidExt = p.getExtensions().getByName("android")
+ if (androidExt !is BaseExtension) {
+ return
+ }
log("project build dir:${p.getBuildDir()}")
+ // TODO this will differ per flavor
+
+ if (androidExt is AppExtension) {
+ createXmlProcessorForApp(p, androidExt)
+ } else if (androidExt is LibraryExtension) {
+ createXmlProcessorForLibrary(p, androidExt)
+ } else {
+ throw RuntimeException("cannot understand android extension. What is it? ${androidExt}")
+ }
+ }
+
+ fun createXmlProcessorForLibrary(project : Project, lib : LibraryExtension) {
+ val sdkDir = lib.getSdkDirectory()
+ lib.getTestVariants().forEach { variant ->
+ log("test variant $variant. dir name ${variant.getDirName()}")
+ val variantData = getVariantData(variant)
+ attachXmlProcessor(project, variantData, sdkDir, false)//tests extend apk variant
+ }
+ lib.getLibraryVariants().forEach { variant ->
+ log("lib variant $variant . dir name ${variant.getDirName()}")
+ val variantData = getVariantData(variant)
+ attachXmlProcessor(project, variantData, sdkDir, true)
+ }
+ }
+
+ fun getVariantData(appVariant : LibraryVariant) : LibraryVariantData {
+ val clazz = javaClass<LibraryVariantImpl>()
+ val field = clazz.getDeclaredField("variantData")
+ field.setAccessible(true)
+ return field.get(appVariant) as LibraryVariantData
+ }
+
+ fun getVariantData(testVariant : TestVariant) : TestVariantData {
+ val clazz = javaClass<TestVariantImpl>()
+ val field = clazz.getDeclaredField("variantData")
+ field.setAccessible(true)
+ return field.get(testVariant) as TestVariantData
+ }
+
+ fun getVariantData(appVariant : ApplicationVariant) : ApplicationVariantData {
val clazz = javaClass<ApplicationVariantImpl>()
val field = clazz.getDeclaredField("variantData")
field.setAccessible(true)
- var appVariant = ss.getApplicationVariants().first { it is ApplicationVariantImpl }
- variantData = field.get(appVariant) as ApplicationVariantData
+ return field.get(appVariant) as ApplicationVariantData
+ }
+ fun createXmlProcessorForApp(project : Project, appExt: AppExtension) {
+ val sdkDir = appExt.getSdkDirectory()
+ appExt.getTestVariants().forEach { testVariant ->
+ val variantData = getVariantData(testVariant)
+ attachXmlProcessor(project, variantData, sdkDir, false)
+ }
+ appExt.getApplicationVariants().forEach { appVariant ->
+ val variantData = getVariantData(appVariant)
+ attachXmlProcessor(project, variantData, sdkDir, false)
+ }
+ }
- val packageName = variantData.generateRClassTask.getPackageForR()
+ fun attachXmlProcessor(project : Project, variantData : BaseVariantData<*>, sdkDir : File,
+ isLibrary : Boolean) {
+ val configuration = variantData.getVariantConfiguration()
+ val minSdkVersion = configuration.getMinSdkVersion()
+ val generateRTask = variantData.generateRClassTask
+ val packageName = generateRTask.getPackageForR()
+ log("r task name $generateRTask . text symbols output dir: ${generateRTask.getTextSymbolOutputDir()}")
+ val fullName = configuration.getFullName()
val sources = variantData.getJavaSources()
sources.forEach({
- log("source: ${it}");
+ if (it is FileCollection) {
+ it.forEach {
+ log("sources for ${variantData} ${it}}")
+ }
+ } else {
+ log("sources for ${variantData}: ${it}");
+ }
})
val resourceFolders = arrayListOf(variantData.mergeResourcesTask.getOutputDir())
log("MERGE RES OUTPUT ${variantData.mergeResourcesTask.getOutputDir()}")
- //TODO
- codeGenTargetFolder = variantData.generateRClassTask.getSourceOutputDir()
- val resGenTargetFolder = variantData.generateRClassTask.getResDir()
- variantData.addJavaSourceFoldersToModel(codeGenTargetFolder)
- variantData.addJavaSourceFoldersToModel(viewBinderSourceRoot)
-
- val jCompileTask = variantData.javaCompileTask
- val dexTask = variantData.dexTask
- val options = jCompileTask.getOptions()
- log("compile options: ${options.optionMap()}")
- viewBinderSource = File(viewBinderSourceRoot.getAbsolutePath() + "/src")
- viewBinderSource.mkdirs()
- variantData.registerJavaGeneratingTask(project.task("dataBinderDummySourceGenTask",
- MethodClosure(this, "dummySourceGenTask")),
- File(viewBinderSourceRoot.getAbsolutePath() + "/src/"))
- viewBinderCompileOutput.mkdirs()
- log("view binder source will be ${viewBinderSource}")
- log("adding out dir to input files ${viewBinderCompileOutput}")
- var inputFiles = dexTask.getInputFiles()
- var inputDir = dexTask.getInputDir()
- log("current input files for dex are ${inputFiles} or dir ${inputDir}")
- if (inputDir != null && inputFiles == null) {
- inputFiles = arrayListOf(inputDir)
- dexTask.setInputDir(null)
- }
- inputFiles.add(viewBinderCompileOutput)
- dexTask.setInputFiles(inputFiles)
+ val codeGenTargetFolder = generateRTask.getSourceOutputDir()
+ // TODO unnecessary?
- dexTask.doFirst(MethodClosure(this, "preDexAnalysis"))
- val writerOutBase = codeGenTargetFolder.getAbsolutePath();
- fileWriter = GradleFileWriter(writerOutBase)
- return LayoutXmlProcessor(packageName, resourceFolders, fileWriter,
- minSdkVersion.getApiLevel())
- }
-
-
- fun dummySourceGenTask(o: Any?) {
- System.out.println("running dummySourceGenTask")
- }
-
- fun preDexAnalysis(o: Any?) {
- val jCompileTask = variantData.javaCompileTask
- val dexTask = variantData.dexTask
- log("dex task files: ${dexTask.getInputFiles()} ${dexTask.getInputFiles().javaClass}")
- log("compile CP: ${jCompileTask.getClasspath().getAsPath()}")
- val jarUrl = androidJar.toURI().toURL()
- val androidClassLoader = URLClassLoader(array(jarUrl))
- val cpFiles = arrayListOf<File>()
- cpFiles.addAll(dexTask.getInputFiles())
- cpFiles.addAll(jCompileTask.getClasspath().getFiles())
- }
+ // TODO attach to test module as well!
- fun preprocessLayoutFiles(o: Any?) {
- xmlProcessor.processResources()
- }
-
- fun generateIntermediateFile(o: Any?) {
- xmlProcessor.writeIntermediateFile(sdkDir)
+ variantData.addJavaSourceFoldersToModel(codeGenTargetFolder)
+ val writerOutBase = codeGenTargetFolder.getAbsolutePath();
+ val fileWriter = GradleFileWriter(writerOutBase)
+ val xmlProcessor = LayoutXmlProcessor(packageName, resourceFolders, fileWriter,
+ minSdkVersion.getApiLevel(), isLibrary)
+ val processResTask = generateRTask
+
+ val xmlOutDir = "${project.getBuildDir()}/layout-info/${configuration.getDirName()}";
+ log("xml output for ${variantData} is ${xmlOutDir}")
+ val dataBindingTaskName = "dataBinding${processResTask.getName().capitalize()}"
+ log("created task $dataBindingTaskName")
+ project.getTasks().create(dataBindingTaskName,
+ javaClass<DataBindingProcessLayoutsTask>(),
+ object : Action<DataBindingProcessLayoutsTask> {
+ override fun execute(task: DataBindingProcessLayoutsTask) {
+ task.xmlProcessor = xmlProcessor
+ task.sdkDir = sdkDir
+ Log.d { "TASK adding dependency on ${task} for ${processResTask}" }
+ processResTask.dependsOn(task)
+ processResTask.getDependsOn().filterNot { it == task }.forEach {
+ Log.d { "adding dependency on ${it} for ${task}" }
+ task.dependsOn(it)
+ }
+ processResTask.doLast {
+ task.writeFiles(File(xmlOutDir))
+ }
+ }
+ });
+
+ if (isLibrary) {
+ val packageJarTaskName = "package${fullName.capitalize()}Jar"
+ val packageTask = project.getTasks().findByName(packageJarTaskName)
+ if (packageTask !is org.gradle.api.tasks.bundling.Jar) {
+ throw RuntimeException("cannot find package task in $project $variantData project $packageJarTaskName")
+ }
+ val excludePattern = "com/android/databinding/layouts/*.*"
+ val appPkgAsClass = packageName.replace('.', '/')
+ packageTask.exclude(excludePattern)
+ packageTask.exclude("$appPkgAsClass/generated/*")
+ packageTask.exclude("$appPkgAsClass/BR.*")
+ packageTask.exclude(xmlProcessor.getInfoClassFullName().replace('.', '/') + ".class")
+ log("excludes ${packageTask.getExcludes()}")
+ }
}
}
diff --git a/integration-tests/IndependentLibrary/app/.gitignore b/integration-tests/IndependentLibrary/app/.gitignore
new file mode 100644
index 00000000..796b96d1
--- /dev/null
+++ b/integration-tests/IndependentLibrary/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/integration-tests/IndependentLibrary/app/build.gradle b/integration-tests/IndependentLibrary/app/build.gradle
new file mode 100644
index 00000000..552e1a52
--- /dev/null
+++ b/integration-tests/IndependentLibrary/app/build.gradle
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+apply plugin: 'maven'
+apply plugin: 'com.android.library'
+apply plugin: 'com.android.databinding'
+
+android {
+ compileSdkVersion 21
+ buildToolsVersion "21.1.2"
+
+ defaultConfig {
+ minSdkVersion 7
+ targetSdkVersion 21
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ packagingOptions {
+ exclude 'META-INF/services/javax.annotation.processing.Processor'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/NOTICE.txt'
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile "com.android.databinding:library:${config.snapshotVersion}"
+ provided "com.android.databinding:annotationprocessor:${config.snapshotVersion}"
+}
+
+uploadArchives {
+ repositories {
+ mavenDeployer {
+ repository(url: "file://${config.mavenRepoDir}")
+ pom.artifactId = 'independent-library'
+ pom.version = config.snapshotVersion
+ pom.groupId = config.testGroup
+ }
+ }
+}
+
+connectedCheck.dependsOn uploadArchives \ No newline at end of file
diff --git a/integration-tests/IndependentLibrary/app/proguard-rules.pro b/integration-tests/IndependentLibrary/app/proguard-rules.pro
new file mode 100644
index 00000000..b7210d1d
--- /dev/null
+++ b/integration-tests/IndependentLibrary/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/yboyar/android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/integration-tests/IndependentLibrary/app/src/androidTest/java/com/android/databinding/test/independentlibrary/ApplicationTest.java b/integration-tests/IndependentLibrary/app/src/androidTest/java/com/android/databinding/test/independentlibrary/ApplicationTest.java
new file mode 100644
index 00000000..0b267a3a
--- /dev/null
+++ b/integration-tests/IndependentLibrary/app/src/androidTest/java/com/android/databinding/test/independentlibrary/ApplicationTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.test.independentlibrary;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
+ */
+public class ApplicationTest extends ApplicationTestCase<Application> {
+
+ public ApplicationTest() {
+ super(Application.class);
+ }
+} \ No newline at end of file
diff --git a/integration-tests/IndependentLibrary/app/src/androidTest/java/com/android/databinding/test/independentlibrary/LibraryActivityTest.java b/integration-tests/IndependentLibrary/app/src/androidTest/java/com/android/databinding/test/independentlibrary/LibraryActivityTest.java
new file mode 100644
index 00000000..939d1bae
--- /dev/null
+++ b/integration-tests/IndependentLibrary/app/src/androidTest/java/com/android/databinding/test/independentlibrary/LibraryActivityTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.test.independentlibrary;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.View;
+import android.widget.TextView;
+
+public class LibraryActivityTest extends ActivityInstrumentationTestCase2<LibraryActivity> {
+ public LibraryActivityTest() {
+ super(LibraryActivity.class);
+ }
+
+ public void testTextViewContents() throws Throwable {
+ final LibraryActivity activity = getActivity();
+ assertNotNull("test sanity", activity);
+ runTestOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ TextView textView = (TextView) activity.findViewById(R.id.fooTextView);
+ final String expected = LibraryActivity.FIELD_VALUE + " " +
+ LibraryActivity.FIELD_VALUE;
+ assertEquals(expected, textView.getText().toString());
+ }
+ });
+ }
+}
diff --git a/integration-tests/IndependentLibrary/app/src/main/AndroidManifest.xml b/integration-tests/IndependentLibrary/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..ff2388c2
--- /dev/null
+++ b/integration-tests/IndependentLibrary/app/src/main/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.databinding.test.independentlibrary">
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name">
+ <activity android:name=".LibraryActivity"/>
+ </application>
+
+</manifest>
diff --git a/integration-tests/IndependentLibrary/app/src/main/java/com/android/databinding/test/independentlibrary/LibraryActivity.java b/integration-tests/IndependentLibrary/app/src/main/java/com/android/databinding/test/independentlibrary/LibraryActivity.java
new file mode 100644
index 00000000..2d2e0240
--- /dev/null
+++ b/integration-tests/IndependentLibrary/app/src/main/java/com/android/databinding/test/independentlibrary/LibraryActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.test.independentlibrary;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.databinding.test.independentlibrary.vo.MyBindableObject;
+import com.android.databinding.test.independentlibrary.generated.LibraryLayoutBinding;
+public class LibraryActivity extends Activity {
+ public static final String FIELD_VALUE = "BAR";
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ LibraryLayoutBinding binding = LibraryLayoutBinding.inflate(this);
+ setContentView(binding.getRoot());
+ MyBindableObject object = new MyBindableObject();
+ object.setField(FIELD_VALUE);
+ binding.setFoo(object);
+ binding.executePendingBindings();
+ }
+}
diff --git a/integration-tests/IndependentLibrary/app/src/main/java/com/android/databinding/test/independentlibrary/LibraryAdapter.java b/integration-tests/IndependentLibrary/app/src/main/java/com/android/databinding/test/independentlibrary/LibraryAdapter.java
new file mode 100644
index 00000000..e7a2ea65
--- /dev/null
+++ b/integration-tests/IndependentLibrary/app/src/main/java/com/android/databinding/test/independentlibrary/LibraryAdapter.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.test.independentlibrary;
+
+import android.binding.BindingAdapter;
+import android.view.View;
+
+public class LibraryAdapter {
+ @BindingAdapter("myTagAttr")
+ public static void set(View view, String someTag) {
+ view.setTag(someTag);
+ }
+}
diff --git a/integration-tests/IndependentLibrary/app/src/main/java/com/android/databinding/test/independentlibrary/vo/MyBindableObject.java b/integration-tests/IndependentLibrary/app/src/main/java/com/android/databinding/test/independentlibrary/vo/MyBindableObject.java
new file mode 100644
index 00000000..c4c5cc8b
--- /dev/null
+++ b/integration-tests/IndependentLibrary/app/src/main/java/com/android/databinding/test/independentlibrary/vo/MyBindableObject.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.test.independentlibrary.vo;
+
+import com.android.databinding.library.BaseObservable;
+import com.android.databinding.test.independentlibrary.BR;
+
+import android.binding.Bindable;
+
+public class MyBindableObject extends BaseObservable {
+ @Bindable
+ private String mField;
+
+ public String getField() {
+ return mField;
+ }
+
+ public void setField(String field) {
+ mField = field;
+ notifyPropertyChanged(BR.field);
+ }
+}
diff --git a/integration-tests/IndependentLibrary/app/src/main/res/layout/library_layout.xml b/integration-tests/IndependentLibrary/app/src/main/res/layout/library_layout.xml
new file mode 100644
index 00000000..a7ba2857
--- /dev/null
+++ b/integration-tests/IndependentLibrary/app/src/main/res/layout/library_layout.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <variable name="foo" type="com.android.databinding.test.independentlibrary.vo.MyBindableObject"/>
+ <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
+ android:id="@+id/fooTextView"
+ android:text='@{foo.field + " " + foo.field}'/>
+</LinearLayout> \ No newline at end of file
diff --git a/integration-tests/IndependentLibrary/app/src/main/res/values/strings.xml b/integration-tests/IndependentLibrary/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000..8e6caf7b
--- /dev/null
+++ b/integration-tests/IndependentLibrary/app/src/main/res/values/strings.xml
@@ -0,0 +1,18 @@
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<resources>
+ <string name="app_name">IndependentLibrary</string>
+</resources>
diff --git a/integration-tests/IndependentLibrary/build.gradle b/integration-tests/IndependentLibrary/build.gradle
new file mode 100644
index 00000000..d74b7e69
--- /dev/null
+++ b/integration-tests/IndependentLibrary/build.gradle
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+buildscript {
+ def Properties dataBindingProperties = new Properties()
+ dataBindingProperties.load(new FileInputStream("${projectDir}/../../databinding.properties"))
+ dataBindingProperties.mavenRepoDir = "${projectDir}/../../${dataBindingProperties.mavenRepoName}"
+ ext.config = dataBindingProperties
+ println "loaded config"
+
+ repositories {
+ jcenter()
+ maven {
+ url config.mavenRepoDir
+ }
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.1.3'
+ classpath "com.android.databinding:dataBinder:${config.snapshotVersion}"
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ maven {
+ url config.mavenRepoDir
+ }
+ }
+}
diff --git a/integration-tests/IndependentLibrary/gradle.properties b/integration-tests/IndependentLibrary/gradle.properties
new file mode 100644
index 00000000..efd23622
--- /dev/null
+++ b/integration-tests/IndependentLibrary/gradle.properties
@@ -0,0 +1,33 @@
+#
+# Copyright (C) 2015 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.
+#
+
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true \ No newline at end of file
diff --git a/integration-tests/IndependentLibrary/gradle/wrapper/gradle-wrapper.jar b/integration-tests/IndependentLibrary/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..8c0fb64a
--- /dev/null
+++ b/integration-tests/IndependentLibrary/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/integration-tests/IndependentLibrary/gradle/wrapper/gradle-wrapper.properties b/integration-tests/IndependentLibrary/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..de86a571
--- /dev/null
+++ b/integration-tests/IndependentLibrary/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,21 @@
+#
+# Copyright (C) 2015 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.
+#
+
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
diff --git a/integration-tests/IndependentLibrary/gradlew b/integration-tests/IndependentLibrary/gradlew
new file mode 100755
index 00000000..91a7e269
--- /dev/null
+++ b/integration-tests/IndependentLibrary/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/integration-tests/IndependentLibrary/gradlew.bat b/integration-tests/IndependentLibrary/gradlew.bat
new file mode 100644
index 00000000..aec99730
--- /dev/null
+++ b/integration-tests/IndependentLibrary/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/integration-tests/IndependentLibrary/settings.gradle b/integration-tests/IndependentLibrary/settings.gradle
new file mode 100644
index 00000000..e2afad2a
--- /dev/null
+++ b/integration-tests/IndependentLibrary/settings.gradle
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+include ':app'
diff --git a/integration-tests/MultiModuleTestApp/app/.gitignore b/integration-tests/MultiModuleTestApp/app/.gitignore
new file mode 100644
index 00000000..796b96d1
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/integration-tests/MultiModuleTestApp/app/build.gradle b/integration-tests/MultiModuleTestApp/app/build.gradle
new file mode 100644
index 00000000..8079ff5d
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/build.gradle
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+apply plugin: 'com.android.application'
+apply plugin: 'com.android.databinding'
+
+android {
+ compileSdkVersion 21
+ buildToolsVersion "22"
+
+ defaultConfig {
+ applicationId "com.android.databinding.multimoduletestapp"
+ minSdkVersion 7
+ targetSdkVersion 21
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ packagingOptions {
+ exclude 'META-INF/services/javax.annotation.processing.Processor'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/NOTICE.txt'
+ }
+}
+
+println "combined ${config.testGroup}.independent-library:${config.snapshotVersion}"
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile project(':testlibrary')
+ compile "com.android.support:support-v4:+"
+ provided "com.android.databinding:annotationprocessor:${config.snapshotVersion}"
+ compile "${config.testGroup}:independent-library:${config.snapshotVersion}"
+}
diff --git a/integration-tests/MultiModuleTestApp/app/proguard-rules.pro b/integration-tests/MultiModuleTestApp/app/proguard-rules.pro
new file mode 100644
index 00000000..b7210d1d
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/yboyar/android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/integration-tests/MultiModuleTestApp/app/src/androidTest/java/com/android/databinding/multimoduletestapp/ApplicationTest.java b/integration-tests/MultiModuleTestApp/app/src/androidTest/java/com/android/databinding/multimoduletestapp/ApplicationTest.java
new file mode 100644
index 00000000..f1797487
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/androidTest/java/com/android/databinding/multimoduletestapp/ApplicationTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.multimoduletestapp;
+
+import com.android.databinding.testlibrary.ObservableInLibrary;
+
+import android.app.Application;
+import android.binding.Observable;
+import android.binding.OnPropertyChangedListener;
+import android.test.ApplicationTestCase;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
+ */
+public class ApplicationTest extends ApplicationTestCase<Application> {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+} \ No newline at end of file
diff --git a/integration-tests/MultiModuleTestApp/app/src/androidTest/java/com/android/databinding/multimoduletestapp/EventIdsTest.java b/integration-tests/MultiModuleTestApp/app/src/androidTest/java/com/android/databinding/multimoduletestapp/EventIdsTest.java
new file mode 100644
index 00000000..32dbffe8
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/androidTest/java/com/android/databinding/multimoduletestapp/EventIdsTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.multimoduletestapp;
+
+import com.android.databinding.testlibrary.ObservableInLibrary;
+
+import android.binding.Observable;
+import android.binding.OnPropertyChangedListener;
+import android.os.Debug;
+import android.test.AndroidTestCase;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.android.databinding.multimoduletestapp.BR;
+
+public class EventIdsTest extends AndroidTestCase {
+ public void testLibraryObservable() {
+ ObservableInLibrary observableInLibrary = new ObservableInLibrary();
+ EventCounter ec = new EventCounter();
+ observableInLibrary.addOnPropertyChangedListener(ec);
+ ec.assertProperty(BR.libField1, 0);
+ ec.assertProperty(BR.libField2, 0);
+ ec.assertProperty(BR.sharedField, 0);
+
+ observableInLibrary.setLibField1("a");
+ ec.assertProperty(BR.libField1, 1);
+ ec.assertProperty(BR.libField2, 0);
+ ec.assertProperty(BR.sharedField, 0);
+
+ observableInLibrary.setLibField2("b");
+ ec.assertProperty(BR.libField1, 1);
+ ec.assertProperty(BR.libField2, 1);
+ ec.assertProperty(BR.sharedField, 0);
+
+ observableInLibrary.setSharedField(3);
+ ec.assertProperty(BR.libField1, 1);
+ ec.assertProperty(BR.libField2, 1);
+ ec.assertProperty(BR.sharedField, 1);
+ }
+
+ public void testAppObservable() {
+ ObservableInMainApp observableInMainApp = new ObservableInMainApp();
+ EventCounter ec = new EventCounter();
+ observableInMainApp.addOnPropertyChangedListener(ec);
+ ec.assertProperty(BR.appField1, 0);
+ ec.assertProperty(BR.appField2, 0);
+ ec.assertProperty(BR.sharedField, 0);
+
+ observableInMainApp.setAppField2(3);
+ ec.assertProperty(BR.appField1, 0);
+ ec.assertProperty(BR.appField2, 1);
+ ec.assertProperty(BR.sharedField, 0);
+
+ observableInMainApp.setAppField1("b");
+ ec.assertProperty(BR.appField1, 1);
+ ec.assertProperty(BR.appField2, 1);
+ ec.assertProperty(BR.sharedField, 0);
+
+ observableInMainApp.setSharedField(5);
+ ec.assertProperty(BR.appField1, 1);
+ ec.assertProperty(BR.appField2, 1);
+ ec.assertProperty(BR.sharedField, 1);
+ }
+
+ public void testExtendingObservable() {
+ ObservableExtendingLib observable = new ObservableExtendingLib();
+ EventCounter ec = new EventCounter();
+ observable.addOnPropertyChangedListener(ec);
+
+ ec.assertProperty(BR.childClassField, 0);
+ ec.assertProperty(BR.libField1, 0);
+ ec.assertProperty(BR.libField2, 0);
+ ec.assertProperty(BR.sharedField, 0);
+
+ observable.setChildClassField("a");
+ ec.assertProperty(BR.childClassField, 1);
+ ec.assertProperty(BR.libField1, 0);
+ ec.assertProperty(BR.libField2, 0);
+ ec.assertProperty(BR.sharedField, 0);
+
+ observable.setLibField1("b");
+ ec.assertProperty(BR.childClassField, 1);
+ ec.assertProperty(BR.libField1, 1);
+ ec.assertProperty(BR.libField2, 0);
+ ec.assertProperty(BR.sharedField, 0);
+
+ observable.setLibField2("c");
+ ec.assertProperty(BR.childClassField, 1);
+ ec.assertProperty(BR.libField1, 1);
+ ec.assertProperty(BR.libField2, 1);
+ ec.assertProperty(BR.sharedField, 0);
+
+ observable.setSharedField(2);
+ ec.assertProperty(BR.childClassField, 1);
+ ec.assertProperty(BR.libField1, 1);
+ ec.assertProperty(BR.libField2, 1);
+ ec.assertProperty(BR.sharedField, 1);
+ }
+
+ private static class EventCounter implements OnPropertyChangedListener {
+ Map<Integer, Integer> mCounter = new HashMap<>();
+
+ @Override
+ public void onPropertyChanged(Observable observable, int propertyId) {
+ mCounter.put(propertyId, get(propertyId) + 1);
+ }
+
+ public int get(int propertyId) {
+ Integer val = mCounter.get(propertyId);
+ return val == null ? 0 : val;
+ }
+
+ private void assertProperty(int propertyId, int value) {
+ assertEquals(get(propertyId), value);
+ }
+ }
+}
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/AndroidManifest.xml b/integration-tests/MultiModuleTestApp/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..aaa07198
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.databinding.multimoduletestapp" >
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/java/com/android/databinding/multimoduletestapp/MainActivity.java b/integration-tests/MultiModuleTestApp/app/src/main/java/com/android/databinding/multimoduletestapp/MainActivity.java
new file mode 100644
index 00000000..f8a012a0
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/java/com/android/databinding/multimoduletestapp/MainActivity.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.multimoduletestapp;
+
+import com.android.databinding.multimoduletestapp.generated.ActivityMainBinding;
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.ViewGroup;
+
+public class MainActivity extends Activity {
+ ActivityMainBinding mBinder;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mBinder = ActivityMainBinding.inflate(this);
+ setContentView(mBinder.getRoot());
+ }
+
+ public ActivityMainBinding getBinder() {
+ return mBinder;
+ }
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.menu_main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+
+ //noinspection SimplifiableIfStatement
+ if (id == R.id.action_settings) {
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/java/com/android/databinding/multimoduletestapp/ObservableExtendingLib.java b/integration-tests/MultiModuleTestApp/app/src/main/java/com/android/databinding/multimoduletestapp/ObservableExtendingLib.java
new file mode 100644
index 00000000..b558790d
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/java/com/android/databinding/multimoduletestapp/ObservableExtendingLib.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.multimoduletestapp;
+
+import com.android.databinding.testlibrary.ObservableInLibrary;
+
+import android.binding.Bindable;
+import com.android.databinding.multimoduletestapp.BR;
+
+public class ObservableExtendingLib extends ObservableInLibrary {
+ @Bindable
+ private String mChildClassField;
+
+ public String getChildClassField() {
+ return mChildClassField;
+ }
+
+ public void setChildClassField(String childClassField) {
+ mChildClassField = childClassField;
+ notifyPropertyChanged(BR.childClassField);
+ }
+}
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/java/com/android/databinding/multimoduletestapp/ObservableInMainApp.java b/integration-tests/MultiModuleTestApp/app/src/main/java/com/android/databinding/multimoduletestapp/ObservableInMainApp.java
new file mode 100644
index 00000000..c870fd44
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/java/com/android/databinding/multimoduletestapp/ObservableInMainApp.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.multimoduletestapp;
+
+import android.binding.Bindable;
+
+import com.android.databinding.library.BaseObservable;
+import com.android.databinding.multimoduletestapp.BR;
+
+public class ObservableInMainApp extends BaseObservable {
+ @Bindable
+ private String mAppField1;
+ @Bindable
+ private int mAppField2;
+ @Bindable
+ private int mSharedField;
+
+ public String getAppField1() {
+ return mAppField1;
+ }
+
+ public void setAppField1(String appField1) {
+ mAppField1 = appField1;
+ notifyPropertyChanged(BR.appField1);
+ }
+
+ public int getAppField2() {
+ return mAppField2;
+ }
+
+ public void setAppField2(int appField2) {
+ mAppField2 = appField2;
+ notifyPropertyChanged(BR.appField2);
+ }
+
+ public int getSharedField() {
+ return mSharedField;
+ }
+
+ public void setSharedField(int sharedField) {
+ mSharedField = sharedField;
+ notifyPropertyChanged(BR.sharedField);
+ }
+}
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/res/drawable-hdpi/ic_launcher.png b/integration-tests/MultiModuleTestApp/app/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..96a442e5
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/res/drawable-mdpi/ic_launcher.png b/integration-tests/MultiModuleTestApp/app/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..359047df
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/res/drawable-xhdpi/ic_launcher.png b/integration-tests/MultiModuleTestApp/app/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..71c6d760
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/integration-tests/MultiModuleTestApp/app/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..4df18946
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/res/layout/activity_main.xml b/integration-tests/MultiModuleTestApp/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..4549e817
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,27 @@
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
+ android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
+ <variable name="foo" type="String"/>
+ <TextView android:text='@{foo + " " + foo}' android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</RelativeLayout>
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/res/layout/activity_test_library_main.xml b/integration-tests/MultiModuleTestApp/app/src/main/res/layout/activity_test_library_main.xml
new file mode 100644
index 00000000..5a340493
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/res/layout/activity_test_library_main.xml
@@ -0,0 +1,27 @@
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
+ android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ >
+ <TextView android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</RelativeLayout>
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/res/menu/menu_main.xml b/integration-tests/MultiModuleTestApp/app/src/main/res/menu/menu_main.xml
new file mode 100644
index 00000000..4674d4d1
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/res/menu/menu_main.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity">
+ <item android:id="@+id/action_settings" android:title="@string/action_settings"
+ android:orderInCategory="100" android:showAsAction="never" />
+</menu>
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/res/values-v21/styles.xml b/integration-tests/MultiModuleTestApp/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 00000000..9b24d4f7
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<resources>
+ <style name="AppTheme" parent="android:Theme.Material.Light">
+ </style>
+</resources>
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/res/values-w820dp/dimens.xml b/integration-tests/MultiModuleTestApp/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 00000000..4719591c
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,22 @@
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<resources>
+ <!-- Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+</resources>
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/res/values/dimens.xml b/integration-tests/MultiModuleTestApp/app/src/main/res/values/dimens.xml
new file mode 100644
index 00000000..c06ae3f9
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/res/values/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<resources>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/res/values/strings.xml b/integration-tests/MultiModuleTestApp/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000..20d68aa2
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<resources>
+
+ <string name="app_name">Multi Module Test App</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+
+</resources>
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/res/values/styles.xml b/integration-tests/MultiModuleTestApp/app/src/main/res/values/styles.xml
new file mode 100644
index 00000000..7dc23c83
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/app/src/main/res/values/styles.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ </style>
+
+</resources>
diff --git a/integration-tests/MultiModuleTestApp/build.gradle b/integration-tests/MultiModuleTestApp/build.gradle
new file mode 100644
index 00000000..b9340e59
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/build.gradle
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+buildscript {
+ def Properties dataBindingProperties = new Properties()
+ dataBindingProperties.load(new FileInputStream("${projectDir}/../../databinding.properties"))
+ dataBindingProperties.mavenRepoDir = "${projectDir}/../../${dataBindingProperties.mavenRepoName}"
+ ext.config = dataBindingProperties
+ println "loaded config"
+
+ repositories {
+ jcenter()
+ maven {
+ url config.mavenRepoDir
+ }
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.1.3'
+ classpath "com.android.databinding:dataBinder:${config.snapshotVersion}"
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ maven {
+ url config.mavenRepoDir
+ }
+ }
+}
diff --git a/integration-tests/MultiModuleTestApp/gradle.properties b/integration-tests/MultiModuleTestApp/gradle.properties
new file mode 100644
index 00000000..5b24ba3e
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/gradle.properties
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2015 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.
+#
+
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true \ No newline at end of file
diff --git a/integration-tests/MultiModuleTestApp/gradle/wrapper/gradle-wrapper.jar b/integration-tests/MultiModuleTestApp/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..8c0fb64a
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/integration-tests/MultiModuleTestApp/gradle/wrapper/gradle-wrapper.properties b/integration-tests/MultiModuleTestApp/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..992e276a
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,22 @@
+#
+# Copyright (C) 2015 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.
+#
+
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
diff --git a/integration-tests/MultiModuleTestApp/gradlew b/integration-tests/MultiModuleTestApp/gradlew
new file mode 100755
index 00000000..91a7e269
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/integration-tests/MultiModuleTestApp/gradlew.bat b/integration-tests/MultiModuleTestApp/gradlew.bat
new file mode 100644
index 00000000..aec99730
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/integration-tests/MultiModuleTestApp/settings.gradle b/integration-tests/MultiModuleTestApp/settings.gradle
new file mode 100644
index 00000000..c79cb3da
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/settings.gradle
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+include ':app', ':testlibrary'
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/.gitignore b/integration-tests/MultiModuleTestApp/testlibrary/.gitignore
new file mode 100644
index 00000000..796b96d1
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/build.gradle b/integration-tests/MultiModuleTestApp/testlibrary/build.gradle
new file mode 100644
index 00000000..4b2c87c6
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/build.gradle
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+apply plugin: 'com.android.library'
+apply plugin: 'com.android.databinding'
+
+android {
+ compileSdkVersion 21
+ buildToolsVersion "21.1.2"
+
+ defaultConfig {
+ minSdkVersion 7
+ targetSdkVersion 21
+ versionCode 1
+ versionName "1.0"
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ packagingOptions {
+ exclude 'META-INF/services/javax.annotation.processing.Processor'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/NOTICE.txt'
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ compile "com.android.databinding:library:${config.snapshotVersion}"
+ provided "com.android.databinding:annotationprocessor:${config.snapshotVersion}"
+}
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/proguard-rules.pro b/integration-tests/MultiModuleTestApp/testlibrary/proguard-rules.pro
new file mode 100644
index 00000000..b7210d1d
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/yboyar/android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/androidTest/java/com/android/databinding/testlibrary/ApplicationTest.java b/integration-tests/MultiModuleTestApp/testlibrary/src/androidTest/java/com/android/databinding/testlibrary/ApplicationTest.java
new file mode 100644
index 00000000..9efa645c
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/androidTest/java/com/android/databinding/testlibrary/ApplicationTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.testlibrary;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
+ */
+public class ApplicationTest extends ApplicationTestCase<Application> {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+} \ No newline at end of file
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/AndroidManifest.xml b/integration-tests/MultiModuleTestApp/testlibrary/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..263d6632
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/AndroidManifest.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.databinding.testlibrary" >
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name" >
+ <activity
+ android:name=".TestLibraryMainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/java/com/android/databinding/testlibrary/ObservableInLibrary.java b/integration-tests/MultiModuleTestApp/testlibrary/src/main/java/com/android/databinding/testlibrary/ObservableInLibrary.java
new file mode 100644
index 00000000..f5470f10
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/java/com/android/databinding/testlibrary/ObservableInLibrary.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.testlibrary;
+
+import android.binding.Bindable;
+
+import com.android.databinding.library.BaseObservable;
+import com.android.databinding.testlibrary.BR;
+
+public class ObservableInLibrary extends BaseObservable {
+
+ @Bindable
+ private String mLibField1;
+
+ @Bindable
+ private String mLibField2;
+
+ @Bindable
+ private int mSharedField;
+
+ public String getLibField1() {
+ return mLibField1;
+ }
+
+ public void setLibField1(String libField1) {
+ mLibField1 = libField1;
+ notifyPropertyChanged(BR.libField1);
+ }
+
+ public String getLibField2() {
+ return mLibField2;
+ }
+
+ public void setLibField2(String libField2) {
+ mLibField2 = libField2;
+ notifyPropertyChanged(BR.libField2);
+ }
+
+ public int getSharedField() {
+ return mSharedField;
+ }
+
+ public void setSharedField(int sharedField) {
+ mSharedField = sharedField;
+ notifyPropertyChanged(BR.sharedField);
+ }
+}
diff --git a/baseLibrary/src/main/java/android/binding/BinderBundle.java b/integration-tests/MultiModuleTestApp/testlibrary/src/main/java/com/android/databinding/testlibrary/TestLibObject.java
index 1a59bd5a..330b870a 100644
--- a/baseLibrary/src/main/java/android/binding/BinderBundle.java
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/java/com/android/databinding/testlibrary/TestLibObject.java
@@ -13,15 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package android.binding;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
+package com.android.databinding.testlibrary;
-@Target({ElementType.TYPE})
-@Retention(RetentionPolicy.SOURCE)
-public @interface BinderBundle {
- String value();
+import android.binding.Bindable;
+
+public class TestLibObject {
+ @Bindable
+ private String mField;
+
+ public String getField() {
+ return mField;
+ }
+
+ public void setField(String field) {
+ this.mField = field;
+ }
}
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/java/com/android/databinding/testlibrary/TestLibraryMainActivity.java b/integration-tests/MultiModuleTestApp/testlibrary/src/main/java/com/android/databinding/testlibrary/TestLibraryMainActivity.java
new file mode 100644
index 00000000..812b222b
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/java/com/android/databinding/testlibrary/TestLibraryMainActivity.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 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 com.android.databinding.testlibrary;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import com.android.databinding.testlibrary.R;
+import com.android.databinding.testlibrary.generated.ActivityTestLibraryMainBinding;
+public class TestLibraryMainActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ActivityTestLibraryMainBinding binder = ActivityTestLibraryMainBinding.inflate(this);
+ setContentView(binder.getRoot());
+
+ }
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.menu_test_library_main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+
+ //noinspection SimplifiableIfStatement
+ if (id == R.id.action_settings) {
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-hdpi/ic_launcher.png b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..96a442e5
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-mdpi/ic_launcher.png b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..359047df
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-xhdpi/ic_launcher.png b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..71c6d760
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-xxhdpi/ic_launcher.png b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..4df18946
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/layout/activity_test_library_main.xml b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/layout/activity_test_library_main.xml
new file mode 100644
index 00000000..b731cc03
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/layout/activity_test_library_main.xml
@@ -0,0 +1,29 @@
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
+ android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ tools:context=".TestLibraryMainActivity">
+ <variable name="obj1" type="com.android.databinding.testlibrary.TestLibObject"/>
+
+ <TextView android:text="@{obj1.field}" android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</RelativeLayout>
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/menu/menu_test_library_main.xml b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/menu/menu_test_library_main.xml
new file mode 100644
index 00000000..68d936d4
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/menu/menu_test_library_main.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools" tools:context=".TestLibraryMainActivity">
+ <item android:id="@+id/action_settings" android:title="@string/action_settings"
+ android:orderInCategory="100" android:showAsAction="never" />
+</menu>
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/values-w820dp/dimens.xml b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 00000000..4719591c
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,22 @@
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<resources>
+ <!-- Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+</resources>
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/values/dimens.xml b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/values/dimens.xml
new file mode 100644
index 00000000..c06ae3f9
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/values/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<resources>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/values/strings.xml b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/values/strings.xml
new file mode 100644
index 00000000..d930ddb6
--- /dev/null
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/values/strings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 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.
+ -->
+
+<resources>
+
+ <string name="app_name">Test Library</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+
+</resources>
diff --git a/integration-tests/TestApp/app/build.gradle b/integration-tests/TestApp/app/build.gradle
index 2fe5cf44..11f17571 100644
--- a/integration-tests/TestApp/app/build.gradle
+++ b/integration-tests/TestApp/app/build.gradle
@@ -27,6 +27,7 @@ android {
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile "com.android.databinding:library:${config.snapshotVersion}"
+ compile "com.android.databinding:adapters:${config.snapshotVersion}"
compile "com.android.support:support-v4:+"
provided "com.android.databinding:annotationprocessor:${config.snapshotVersion}"
}
diff --git a/integration-tests/TestApp/app/src/androidTest/java/com/android/databinding/testapp/ProcessBindableTest.java b/integration-tests/TestApp/app/src/androidTest/java/com/android/databinding/testapp/ProcessBindableTest.java
index a092d0de..0b579276 100644
--- a/integration-tests/TestApp/app/src/androidTest/java/com/android/databinding/testapp/ProcessBindableTest.java
+++ b/integration-tests/TestApp/app/src/androidTest/java/com/android/databinding/testapp/ProcessBindableTest.java
@@ -22,7 +22,7 @@ import android.util.ArrayMap;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashSet;
-
+import com.android.databinding.testapp.BR;
public class ProcessBindableTest extends BaseDataBinderTest<BasicBindingBinding> {
private static String[] EXPECTED_BINDING_NAMES = {
"bindableField1",
@@ -40,7 +40,7 @@ public class ProcessBindableTest extends BaseDataBinderTest<BasicBindingBinding>
}
public void testFieldsGenerated() throws IllegalAccessException {
- Field[] fields = android.binding.BR.class.getFields();
+ Field[] fields = BR.class.getFields();
ArrayMap<String, Integer> fieldValues = new ArrayMap<>();
int modifiers = Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL;
diff --git a/integration-tests/TestApp/app/src/main/java/com/android/databinding/testapp/vo/PublicFinalWithObservableTestVo.java b/integration-tests/TestApp/app/src/main/java/com/android/databinding/testapp/vo/PublicFinalWithObservableTestVo.java
index dd415ded..2c9695b8 100644
--- a/integration-tests/TestApp/app/src/main/java/com/android/databinding/testapp/vo/PublicFinalWithObservableTestVo.java
+++ b/integration-tests/TestApp/app/src/main/java/com/android/databinding/testapp/vo/PublicFinalWithObservableTestVo.java
@@ -17,6 +17,7 @@ import com.android.databinding.library.BaseObservable;
import com.android.databinding.testapp.R;
import android.binding.Bindable;
+import com.android.databinding.testapp.BR;
public class PublicFinalWithObservableTestVo {
public final int myField;
@@ -36,7 +37,7 @@ public class PublicFinalWithObservableTestVo {
public void setVal(int val) {
this.val = val;
- notifyPropertyChanged(android.binding.BR.val);
+ notifyPropertyChanged(BR.val);
}
}
}
diff --git a/integration-tests/TestApp/app/src/main/java/com/android/databinding/testapp/vo/TextViewBindingObject.java b/integration-tests/TestApp/app/src/main/java/com/android/databinding/testapp/vo/TextViewBindingObject.java
index b98ded26..482be18d 100644
--- a/integration-tests/TestApp/app/src/main/java/com/android/databinding/testapp/vo/TextViewBindingObject.java
+++ b/integration-tests/TestApp/app/src/main/java/com/android/databinding/testapp/vo/TextViewBindingObject.java
@@ -25,6 +25,7 @@ import android.text.util.Linkify;
import android.view.KeyEvent;
import android.view.View;
import android.widget.TextView;
+import com.android.databinding.testapp.BR;
public class TextViewBindingObject extends BindingAdapterBindingObject {
@@ -236,7 +237,7 @@ public class TextViewBindingObject extends BindingAdapterBindingObject {
public void setCapitalize(TextKeyListener.Capitalize capitalize) {
mCapitalize = capitalize;
- notifyPropertyChanged(android.binding.BR.capitalize);
+ notifyPropertyChanged(BR.capitalize);
}
public boolean isPhoneNumber() {
diff --git a/integration-tests/TestApp/app/src/main/res/layout-land/multi_res_layout.xml b/integration-tests/TestApp/app/src/main/res/layout-land/multi_res_layout.xml
index caf0389e..5906fd16 100644
--- a/integration-tests/TestApp/app/src/main/res/layout-land/multi_res_layout.xml
+++ b/integration-tests/TestApp/app/src/main/res/layout-land/multi_res_layout.xml
@@ -30,8 +30,7 @@
<include layout="@layout/included_layout" android:id="@+id/includedLayoutConflict"
bind:innerObject="@{objectInLand}"
- bind:innerValue="@{`modified ` + objectInLand.intValue}"
- />
+ bind:innerValue='@{"modified " + objectInLand.intValue}' />
<include layout="@layout/basic_binding" android:id="@+id/includedLayoutShared"
bind:a="@{objectInDefault.stringValue}"
/>
diff --git a/library/build.gradle b/library/build.gradle
index c91e1172..bb078f7a 100644
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -59,9 +59,6 @@ dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile project(":baseLibrary")
compile 'com.android.support:support-v4:+'
- provided project(":annotationprocessor")
- provided 'com.android.support:cardview-v7:+'
- provided 'com.android.support:appcompat-v7:+'
}
configurations {
diff --git a/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java b/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java
index 6785b5fd..aa7661ac 100644
--- a/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java
+++ b/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/MainActivity.java
@@ -13,8 +13,6 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.binding.BR;
-
import com.android.databinding.library.DataBindingUtil;
import com.android.databinding.library.PropertyChangeRegistry;
import com.android.example.bindingdemo.generated.ListItemBinding;
@@ -26,7 +24,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-
+import com.android.example.bindingdemo.BR;
public class MainActivity extends ActionBarActivity implements Observable {
@Bindable
UserAdapter tkAdapter;
@@ -78,7 +76,7 @@ public class MainActivity extends ActionBarActivity implements Observable {
return;
}
this.selected = selected;
- mListeners.notifyChange(this, android.binding.BR.selected);
+ mListeners.notifyChange(this, BR.selected);
}
@Bindable
@@ -190,7 +188,7 @@ public class MainActivity extends ActionBarActivity implements Observable {
}
userList.add(user);
notifyItemInserted(userList.size() - 1);
- mListeners.notifyChange(this, android.binding.BR.itemCount);
+ mListeners.notifyChange(this, BR.itemCount);
}
public void remove(User user) {
@@ -200,7 +198,7 @@ public class MainActivity extends ActionBarActivity implements Observable {
}
userList.remove(i);
notifyItemRemoved(i);
- mListeners.notifyChange(this, android.binding.BR.itemCount);
+ mListeners.notifyChange(this, BR.itemCount);
}
@Override
diff --git a/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/vo/User.java b/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/vo/User.java
index 929d6956..92523216 100644
--- a/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/vo/User.java
+++ b/samples/BindingDemo/app/src/main/java/com/android/example/bindingdemo/vo/User.java
@@ -4,6 +4,7 @@ import android.binding.Bindable;
import android.graphics.Color;
import com.android.databinding.library.BaseObservable;
+import com.android.example.bindingdemo.BR;
import java.util.Objects;
@@ -33,7 +34,7 @@ public class User extends BaseObservable {
return;
}
this.group = group;
- notifyPropertyChanged(android.binding.BR.group);
+ notifyPropertyChanged(BR.group);
}
public int getGroup() {
@@ -49,7 +50,7 @@ public class User extends BaseObservable {
return;
}
this.name = name;
- notifyPropertyChanged(android.binding.BR.name);
+ notifyPropertyChanged(BR.name);
}
public String getLastName() {
@@ -61,7 +62,7 @@ public class User extends BaseObservable {
return;
}
this.lastName = lastName;
- notifyPropertyChanged(android.binding.BR.lastName);
+ notifyPropertyChanged(BR.lastName);
}
public int getPhotoResource() {
@@ -73,7 +74,7 @@ public class User extends BaseObservable {
return;
}
this.photoResource = photoResource;
- notifyPropertyChanged(android.binding.BR.photoResource);
+ notifyPropertyChanged(BR.photoResource);
}
public int getFavoriteColor() {
diff --git a/samples/BindingDemo/app/src/test/java/com/android/example/bindingdemo/vo/UnitTest.java b/samples/BindingDemo/app/src/test/java/com/android/example/bindingdemo/vo/UnitTest.java
index 3bda1434..7f0ba3af 100644
--- a/samples/BindingDemo/app/src/test/java/com/android/example/bindingdemo/vo/UnitTest.java
+++ b/samples/BindingDemo/app/src/test/java/com/android/example/bindingdemo/vo/UnitTest.java
@@ -12,6 +12,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import com.android.example.bindingdemo.BR;
public class UnitTest {
private User testUser;
@@ -33,7 +34,7 @@ public class UnitTest {
OnPropertyChangedListener mockListener = mock(OnPropertyChangedListener.class);
testUser.addOnPropertyChangedListener(mockListener);
testUser.setName("Tom");
- verify(mockListener).onPropertyChanged(testUser, android.binding.BR.name);
+ verify(mockListener).onPropertyChanged(testUser, BR.name);
verifyNoMoreInteractions(mockListener);
}
} \ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index c7906238..21905180 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,4 +1,4 @@
-include ':baseLibrary'
+include ':baseLibrary', ':app'
include ':library'
include ':compiler'
include ':gradlePlugin'