Don't create prebuilts for files that don't exist am: 134eecccdc am: e1c9fe64b1
am: 15281a01df

Change-Id: I7104bd839c6c81328a40e375e2f6648022748351
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index 96cc43e..0103dd1 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -18,5 +18,15 @@
         <processorPath useClasspath="true" />
       </profile>
     </annotationProcessing>
+    <bytecodeTargetLevel>
+      <module name="baseLibrary_main" target="1.6" />
+      <module name="baseLibrary_test" target="1.6" />
+      <module name="compilationTests_main" target="1.6" />
+      <module name="compilationTests_test" target="1.6" />
+      <module name="compiler_main" target="1.8" />
+      <module name="compiler_test" target="1.8" />
+      <module name="compilerCommon_main" target="1.8" />
+      <module name="compilerCommon_test" target="1.8" />
+    </bytecodeTargetLevel>
   </component>
 </project>
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index c9e59e1..0dce863 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -5,7 +5,7 @@
       <GradleProjectSettings>
         <option name="distributionType" value="DEFAULT_WRAPPED" />
         <option name="externalProjectPath" value="$PROJECT_DIR$" />
-        <option name="gradleJvm" value="1.6" />
+        <option name="gradleJvm" value="1.8" />
         <option name="modules">
           <set>
             <option value="$PROJECT_DIR$" />
@@ -17,16 +17,6 @@
           </set>
         </option>
         <option name="useAutoImport" value="true" />
-        <option name="myModules">
-          <set>
-            <option value="$PROJECT_DIR$" />
-            <option value="$PROJECT_DIR$/baseLibrary" />
-            <option value="$PROJECT_DIR$/compilationTests" />
-            <option value="$PROJECT_DIR$/compiler" />
-            <option value="$PROJECT_DIR$/compilerCommon" />
-            <option value="$PROJECT_DIR$/dataBinding" />
-          </set>
-        </option>
       </GradleProjectSettings>
     </option>
   </component>
diff --git a/.idea/misc.xml b/.idea/misc.xml
index caac652..e48072e 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,7 +1,41 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
-  <component name="EntryPointsManager">
-    <entry_points version="2.0" />
+  <component name="ProjectInspectionProfilesVisibleTreeState">
+    <entry key="Project Default">
+      <profile-state>
+        <expanded-state>
+          <State>
+            <id />
+          </State>
+          <State>
+            <id>Class structureJava</id>
+          </State>
+          <State>
+            <id>Code maturity issuesJava</id>
+          </State>
+          <State>
+            <id>Java</id>
+          </State>
+          <State>
+            <id>Java language level migration aidsJava</id>
+          </State>
+          <State>
+            <id>Javadoc issuesJava</id>
+          </State>
+          <State>
+            <id>Performance issuesJava</id>
+          </State>
+          <State>
+            <id>Threading issuesJava</id>
+          </State>
+        </expanded-state>
+        <selected-state>
+          <State>
+            <id>BashSupport</id>
+          </State>
+        </selected-state>
+      </profile-state>
+    </entry>
   </component>
   <component name="ProjectLevelVcsManager" settingsEditedManually="false">
     <OptionsSetting value="true" id="Add" />
@@ -13,7 +47,7 @@
     <ConfirmationsSetting value="0" id="Add" />
     <ConfirmationsSetting value="0" id="Remove" />
   </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
-    <output url="file://$PROJECT_DIR$/classes" />
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+    <output url="file://$PROJECT_DIR$/build/classes" />
   </component>
 </project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 7eefe60..a3acbc5 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -2,12 +2,20 @@
 <project version="4">
   <component name="ProjectModuleManager">
     <modules>
-      <module fileurl="file://$PROJECT_DIR$/baseLibrary/baseLibrary.iml" filepath="$PROJECT_DIR$/baseLibrary/baseLibrary.iml" />
-      <module fileurl="file://$PROJECT_DIR$/compilationTests/compilationTests.iml" filepath="$PROJECT_DIR$/compilationTests/compilationTests.iml" />
-      <module fileurl="file://$PROJECT_DIR$/compiler/compiler.iml" filepath="$PROJECT_DIR$/compiler/compiler.iml" />
-      <module fileurl="file://$PROJECT_DIR$/compilerCommon/compilerCommon.iml" filepath="$PROJECT_DIR$/compilerCommon/compilerCommon.iml" />
-      <module fileurl="file://$PROJECT_DIR$/data-binding.iml" filepath="$PROJECT_DIR$/data-binding.iml" />
-      <module fileurl="file://$PROJECT_DIR$/dataBinding/dataBinding.iml" filepath="$PROJECT_DIR$/dataBinding/dataBinding.iml" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/baseLibrary/baseLibrary.iml" filepath="$PROJECT_DIR$/.idea/modules/baseLibrary/baseLibrary.iml" group="dataBinding/baseLibrary" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/baseLibrary/baseLibrary_main.iml" filepath="$PROJECT_DIR$/.idea/modules/baseLibrary/baseLibrary_main.iml" group="dataBinding/baseLibrary" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/baseLibrary/baseLibrary_test.iml" filepath="$PROJECT_DIR$/.idea/modules/baseLibrary/baseLibrary_test.iml" group="dataBinding/baseLibrary" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/compilationTests/compilationTests.iml" filepath="$PROJECT_DIR$/.idea/modules/compilationTests/compilationTests.iml" group="dataBinding/compilationTests" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/compilationTests/compilationTests_main.iml" filepath="$PROJECT_DIR$/.idea/modules/compilationTests/compilationTests_main.iml" group="dataBinding/compilationTests" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/compilationTests/compilationTests_test.iml" filepath="$PROJECT_DIR$/.idea/modules/compilationTests/compilationTests_test.iml" group="dataBinding/compilationTests" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/compiler/compiler.iml" filepath="$PROJECT_DIR$/.idea/modules/compiler/compiler.iml" group="dataBinding/compiler" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/compilerCommon/compilerCommon.iml" filepath="$PROJECT_DIR$/.idea/modules/compilerCommon/compilerCommon.iml" group="dataBinding/compilerCommon" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/compilerCommon/compilerCommon_main.iml" filepath="$PROJECT_DIR$/.idea/modules/compilerCommon/compilerCommon_main.iml" group="dataBinding/compilerCommon" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/compilerCommon/compilerCommon_test.iml" filepath="$PROJECT_DIR$/.idea/modules/compilerCommon/compilerCommon_test.iml" group="dataBinding/compilerCommon" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/compiler/compiler_main.iml" filepath="$PROJECT_DIR$/.idea/modules/compiler/compiler_main.iml" group="dataBinding/compiler" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/compiler/compiler_test.iml" filepath="$PROJECT_DIR$/.idea/modules/compiler/compiler_test.iml" group="dataBinding/compiler" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/data-binding.iml" filepath="$PROJECT_DIR$/.idea/modules/data-binding.iml" />
+      <module fileurl="file://$PROJECT_DIR$/.idea/modules/dataBinding/dataBinding.iml" filepath="$PROJECT_DIR$/.idea/modules/dataBinding/dataBinding.iml" group="dataBinding" />
     </modules>
   </component>
 </project>
\ No newline at end of file
diff --git a/.idea/modules/baseLibrary/baseLibrary.iml b/.idea/modules/baseLibrary/baseLibrary.iml
new file mode 100644
index 0000000..019a989
--- /dev/null
+++ b/.idea/modules/baseLibrary/baseLibrary.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":dataBinding:baseLibrary" external.linked.project.path="$MODULE_DIR$/../../../baseLibrary" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.version="2.2.0-dev" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../baseLibrary">
+      <excludeFolder url="file://$MODULE_DIR$/../../../baseLibrary/.gradle" />
+      <excludeFolder url="file://$MODULE_DIR$/../../../baseLibrary/build" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/modules/baseLibrary/baseLibrary_main.iml b/.idea/modules/baseLibrary/baseLibrary_main.iml
new file mode 100644
index 0000000..4d93153
--- /dev/null
+++ b/.idea/modules/baseLibrary/baseLibrary_main.iml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":dataBinding:baseLibrary:main" external.linked.project.path="$MODULE_DIR$/../../../baseLibrary" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.type="sourceSet" external.system.module.version="2.2.0-dev" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
+    <output url="file://$MODULE_DIR$/../../../baseLibrary/build/classes/main" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../baseLibrary/src/main">
+      <sourceFolder url="file://$MODULE_DIR$/../../../baseLibrary/src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/../../../baseLibrary/src/main/resources" type="java-resource" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/modules/baseLibrary/baseLibrary_test.iml b/.idea/modules/baseLibrary/baseLibrary_test.iml
new file mode 100644
index 0000000..bc70242
--- /dev/null
+++ b/.idea/modules/baseLibrary/baseLibrary_test.iml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":dataBinding:baseLibrary:test" external.linked.project.path="$MODULE_DIR$/../../../baseLibrary" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.type="sourceSet" external.system.module.version="2.2.0-dev" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
+    <output-test url="file://$MODULE_DIR$/../../../baseLibrary/build/classes/test" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../baseLibrary/src/test">
+      <sourceFolder url="file://$MODULE_DIR$/../../../baseLibrary/src/test/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/../../../baseLibrary/src/test/resources" type="java-test-resource" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="baseLibrary_main" />
+    <orderEntry type="library" name="Gradle: junit:junit:4.12" level="project" />
+    <orderEntry type="library" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" />
+  </component>
+  <component name="TestModuleProperties" production-module="baseLibrary_main" />
+</module>
\ No newline at end of file
diff --git a/.idea/modules/compilationTests/compilationTests.iml b/.idea/modules/compilationTests/compilationTests.iml
new file mode 100644
index 0000000..bedf7d9
--- /dev/null
+++ b/.idea/modules/compilationTests/compilationTests.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":dataBinding:compilationTests" external.linked.project.path="$MODULE_DIR$/../../../compilationTests" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="data-binding.dataBinding" external.system.module.version="1.0" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../compilationTests">
+      <excludeFolder url="file://$MODULE_DIR$/../../../compilationTests/.gradle" />
+      <excludeFolder url="file://$MODULE_DIR$/../../../compilationTests/build" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/modules/compilationTests/compilationTests_main.iml b/.idea/modules/compilationTests/compilationTests_main.iml
new file mode 100644
index 0000000..def742c
--- /dev/null
+++ b/.idea/modules/compilationTests/compilationTests_main.iml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":dataBinding:compilationTests:main" external.linked.project.path="$MODULE_DIR$/../../../compilationTests" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="data-binding.dataBinding" external.system.module.type="sourceSet" external.system.module.version="1.0" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
+    <output url="file://$MODULE_DIR$/../../../compilationTests/build/classes/main" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../compilationTests/src/main">
+      <sourceFolder url="file://$MODULE_DIR$/../../../compilationTests/src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/../../../compilationTests/src/main/resources" type="java-resource" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/modules/compilationTests/compilationTests_test.iml b/.idea/modules/compilationTests/compilationTests_test.iml
new file mode 100644
index 0000000..5241cc7
--- /dev/null
+++ b/.idea/modules/compilationTests/compilationTests_test.iml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":dataBinding:compilationTests:test" external.linked.project.path="$MODULE_DIR$/../../../compilationTests" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="data-binding.dataBinding" external.system.module.type="sourceSet" external.system.module.version="1.0" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
+    <output-test url="file://$MODULE_DIR$/../../../compilationTests/build/classes/test" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../compilationTests/src/test">
+      <sourceFolder url="file://$MODULE_DIR$/../../../compilationTests/src/test/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/../../../compilationTests/src/test/resources" type="java-test-resource" />
+    </content>
+    <content url="file://$MODULE_DIR$/../../../compiler/src/test/java/android">
+      <sourceFolder url="file://$MODULE_DIR$/../../../compiler/src/test/java/android/databinding/tool/reflection/java" isTestSource="true" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="compilationTests_main" />
+    <orderEntry type="module" module-name="baseLibrary_main" />
+    <orderEntry type="library" name="Gradle: junit:junit:4.12" level="project" />
+    <orderEntry type="library" name="Gradle: org.apache.commons:commons-lang3:3.3.2" level="project" />
+    <orderEntry type="library" name="Gradle: commons-io:commons-io:2.4" level="project" />
+    <orderEntry type="library" name="Gradle: commons-codec:commons-codec:1.10" level="project" />
+    <orderEntry type="module" module-name="compilerCommon_main" />
+    <orderEntry type="module" module-name="compiler_main" />
+    <orderEntry type="library" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" />
+    <orderEntry type="library" name="Gradle: org.antlr:antlr4:4.5.3" level="project" />
+    <orderEntry type="library" name="Gradle: com.googlecode.juniversalchardet:juniversalchardet:1.0.3" level="project" />
+    <orderEntry type="library" name="Gradle: com.google.guava:guava:17.0" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.tools:annotations:24.5.0" level="project" />
+    <orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.0.0" level="project" />
+    <orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-runtime:1.0.0" level="project" />
+  </component>
+  <component name="TestModuleProperties" production-module="compilationTests_main" />
+</module>
\ No newline at end of file
diff --git a/.idea/modules/compiler/compiler.iml b/.idea/modules/compiler/compiler.iml
new file mode 100644
index 0000000..50b5884
--- /dev/null
+++ b/.idea/modules/compiler/compiler.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":dataBinding:compiler" external.linked.project.path="$MODULE_DIR$/../../../compiler" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.version="2.2.0-dev" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../compiler">
+      <excludeFolder url="file://$MODULE_DIR$/../../../compiler/.gradle" />
+      <excludeFolder url="file://$MODULE_DIR$/../../../compiler/build" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/modules/compiler/compiler_main.iml b/.idea/modules/compiler/compiler_main.iml
new file mode 100644
index 0000000..abf8411
--- /dev/null
+++ b/.idea/modules/compiler/compiler_main.iml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":dataBinding:compiler:main" external.linked.project.path="$MODULE_DIR$/../../../compiler" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.type="sourceSet" external.system.module.version="2.2.0-dev" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="false">
+    <output url="file://$MODULE_DIR$/../../../compiler/build/classes/main" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../compiler/src/main">
+      <sourceFolder url="file://$MODULE_DIR$/../../../compiler/src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/../../../compiler/src/main/kotlin" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/../../../compiler/src/main/resources" type="java-resource" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="compilerCommon_main" />
+    <orderEntry type="module" module-name="baseLibrary_main" />
+    <orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.0.0" level="project" />
+    <orderEntry type="library" name="Gradle: commons-io:commons-io:2.4" level="project" />
+    <orderEntry type="library" name="Gradle: commons-codec:commons-codec:1.10" level="project" />
+    <orderEntry type="library" name="Gradle: org.antlr:antlr4:4.5.3" level="project" />
+    <orderEntry type="library" name="Gradle: com.googlecode.juniversalchardet:juniversalchardet:1.0.3" level="project" />
+    <orderEntry type="library" name="Gradle: com.google.guava:guava:17.0" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.tools:annotations:24.5.0" level="project" />
+    <orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-runtime:1.0.0" level="project" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/modules/compiler/compiler_test.iml b/.idea/modules/compiler/compiler_test.iml
new file mode 100644
index 0000000..433185e
--- /dev/null
+++ b/.idea/modules/compiler/compiler_test.iml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":dataBinding:compiler:test" external.linked.project.path="$MODULE_DIR$/../../../compiler" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.type="sourceSet" external.system.module.version="2.2.0-dev" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="false">
+    <output-test url="file://$MODULE_DIR$/../../../compiler/build/classes/test" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../compiler/src/test/java">
+      <sourceFolder url="file://$MODULE_DIR$/../../../compiler/src/test/java" isTestSource="true" />
+    </content>
+    <content url="file://$MODULE_DIR$/../../../compiler/src/test/kotlin">
+      <sourceFolder url="file://$MODULE_DIR$/../../../compiler/src/test/kotlin" isTestSource="true" />
+    </content>
+    <content url="file://$MODULE_DIR$/../../../compiler/src/test/resources">
+      <sourceFolder url="file://$MODULE_DIR$/../../../compiler/src/test/resources" type="java-test-resource" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="compiler_main" />
+    <orderEntry type="module" module-name="compilerCommon_main" />
+    <orderEntry type="module" module-name="baseLibrary_main" />
+    <orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.0.0" level="project" />
+    <orderEntry type="library" name="Gradle: commons-io:commons-io:2.4" level="project" />
+    <orderEntry type="library" name="Gradle: commons-codec:commons-codec:1.10" level="project" />
+    <orderEntry type="library" name="Gradle: org.antlr:antlr4:4.5.3" level="project" />
+    <orderEntry type="library" name="Gradle: com.googlecode.juniversalchardet:juniversalchardet:1.0.3" level="project" />
+    <orderEntry type="library" name="Gradle: junit:junit:4.12" level="project" />
+    <orderEntry type="library" name="Gradle: com.google.guava:guava:17.0" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.tools:annotations:24.5.0" level="project" />
+    <orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-runtime:1.0.0" level="project" />
+    <orderEntry type="library" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" />
+  </component>
+  <component name="TestModuleProperties" production-module="compiler_main" />
+</module>
\ No newline at end of file
diff --git a/.idea/modules/compilerCommon/compilerCommon.iml b/.idea/modules/compilerCommon/compilerCommon.iml
new file mode 100644
index 0000000..27fdbd4
--- /dev/null
+++ b/.idea/modules/compilerCommon/compilerCommon.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":dataBinding:compilerCommon" external.linked.project.path="$MODULE_DIR$/../../../compilerCommon" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.version="2.2.0-dev" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../compilerCommon">
+      <excludeFolder url="file://$MODULE_DIR$/../../../compilerCommon/.gradle" />
+      <excludeFolder url="file://$MODULE_DIR$/../../../compilerCommon/build" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/modules/compilerCommon/compilerCommon_main.iml b/.idea/modules/compilerCommon/compilerCommon_main.iml
new file mode 100644
index 0000000..4978e29
--- /dev/null
+++ b/.idea/modules/compilerCommon/compilerCommon_main.iml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":dataBinding:compilerCommon:main" external.linked.project.path="$MODULE_DIR$/../../../compilerCommon" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.type="sourceSet" external.system.module.version="2.2.0-dev" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="false">
+    <output url="file://$MODULE_DIR$/../../../compilerCommon/build/classes/main" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../compilerCommon/src/main">
+      <sourceFolder url="file://$MODULE_DIR$/../../../compilerCommon/src/main/grammar-gen" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/../../../compilerCommon/src/main/java" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/../../../compilerCommon/src/main/xml-gen" isTestSource="false" />
+      <sourceFolder url="file://$MODULE_DIR$/../../../compilerCommon/src/main/resources" type="java-resource" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="baseLibrary_main" />
+    <orderEntry type="library" name="Gradle: org.antlr:antlr4:4.5.3" level="project" />
+    <orderEntry type="library" name="Gradle: commons-io:commons-io:2.4" level="project" />
+    <orderEntry type="library" name="Gradle: com.googlecode.juniversalchardet:juniversalchardet:1.0.3" level="project" />
+    <orderEntry type="library" name="Gradle: com.google.guava:guava:17.0" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.tools:annotations:24.5.0" level="project" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/modules/compilerCommon/compilerCommon_test.iml b/.idea/modules/compilerCommon/compilerCommon_test.iml
new file mode 100644
index 0000000..26e89c6
--- /dev/null
+++ b/.idea/modules/compilerCommon/compilerCommon_test.iml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":dataBinding:compilerCommon:test" external.linked.project.path="$MODULE_DIR$/../../../compilerCommon" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.type="sourceSet" external.system.module.version="2.2.0-dev" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="false">
+    <output-test url="file://$MODULE_DIR$/../../../compilerCommon/build/classes/test" />
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../compilerCommon/src/test">
+      <sourceFolder url="file://$MODULE_DIR$/../../../compilerCommon/src/test/java" isTestSource="true" />
+      <sourceFolder url="file://$MODULE_DIR$/../../../compilerCommon/src/test/resources" type="java-test-resource" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+    <orderEntry type="module" module-name="compilerCommon_main" />
+    <orderEntry type="module" module-name="baseLibrary_main" />
+    <orderEntry type="library" name="Gradle: org.antlr:antlr4:4.5.3" level="project" />
+    <orderEntry type="library" name="Gradle: commons-io:commons-io:2.4" level="project" />
+    <orderEntry type="library" name="Gradle: com.googlecode.juniversalchardet:juniversalchardet:1.0.3" level="project" />
+    <orderEntry type="library" name="Gradle: com.google.guava:guava:17.0" level="project" />
+    <orderEntry type="library" name="Gradle: com.android.tools:annotations:24.5.0" level="project" />
+    <orderEntry type="library" name="Gradle: junit:junit:4.12" level="project" />
+    <orderEntry type="library" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" />
+  </component>
+  <component name="TestModuleProperties" production-module="compilerCommon_main" />
+</module>
\ No newline at end of file
diff --git a/.idea/modules/data-binding.iml b/.idea/modules/data-binding.iml
new file mode 100644
index 0000000..2bbad64
--- /dev/null
+++ b/.idea/modules/data-binding.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id="data-binding" external.linked.project.path="$MODULE_DIR$/../.." external.root.project.path="$MODULE_DIR$/../.." external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../..">
+      <excludeFolder url="file://$MODULE_DIR$/../../.gradle" />
+      <excludeFolder url="file://$MODULE_DIR$/../../build" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/modules/dataBinding/dataBinding.iml b/.idea/modules/dataBinding/dataBinding.iml
new file mode 100644
index 0000000..d0099f2
--- /dev/null
+++ b/.idea/modules/dataBinding/dataBinding.iml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module external.linked.project.id=":dataBinding" external.linked.project.path="$MODULE_DIR$/../../../dataBinding" external.root.project.path="$MODULE_DIR$/../../.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.version="2.2.0-dev" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$/../../../dataBinding">
+      <excludeFolder url="file://$MODULE_DIR$/../../../dataBinding/.gradle" />
+      <excludeFolder url="file://$MODULE_DIR$/../../../dataBinding/build" />
+    </content>
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/baseLibrary/baseLibrary.iml b/baseLibrary/baseLibrary.iml
deleted file mode 100644
index c6163c1..0000000
--- a/baseLibrary/baseLibrary.iml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module external.linked.project.id=":dataBinding:baseLibrary" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.version="1.1" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="false">
-    <output url="file://$MODULE_DIR$/build/classes/main" />
-    <output-test url="file://$MODULE_DIR$/build/classes/test" />
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
-      <excludeFolder url="file://$MODULE_DIR$/.gradle" />
-      <excludeFolder url="file://$MODULE_DIR$/build" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/baseLibrary/build.gradle b/baseLibrary/build.gradle
index 7489e0d..8cbfd6d 100644
--- a/baseLibrary/build.gradle
+++ b/baseLibrary/build.gradle
@@ -62,6 +62,10 @@
     }
 }
 
+javadoc {
+   options.addStringOption('Xdoclint:none', '-quiet')
+}
+
 project.ext.pomName = 'Data Binding Base Library'
 project.ext.pomDesc = 'Shared library between Data Binding runtime lib and compiler'
-enablePublishing(this, true)
\ No newline at end of file
+enablePublishing(this, true)
diff --git a/baseLibrary/db-baseLibrary.iml b/baseLibrary/db-baseLibrary.iml
index 7cf9983..1804bc9 100644
--- a/baseLibrary/db-baseLibrary.iml
+++ b/baseLibrary/db-baseLibrary.iml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <module relativePaths="true" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="true">
     <exclude-output />
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
diff --git a/baseLibrary/src/main/java/android/databinding/CallbackRegistry.java b/baseLibrary/src/main/java/android/databinding/CallbackRegistry.java
index 0cd7b43..322b279 100644
--- a/baseLibrary/src/main/java/android/databinding/CallbackRegistry.java
+++ b/baseLibrary/src/main/java/android/databinding/CallbackRegistry.java
@@ -210,6 +210,9 @@
      * @param callback The callback to add.
      */
     public synchronized void add(C callback) {
+        if (callback == null) {
+            throw new IllegalArgumentException("callback cannot be null");
+        }
         int index = mCallbacks.lastIndexOf(callback);
         if (index < 0 || isRemoved(index)) {
             mCallbacks.add(callback);
diff --git a/build.gradle b/build.gradle
index c33a72c..2aa4ea4 100644
--- a/build.gradle
+++ b/build.gradle
@@ -169,8 +169,7 @@
     if (localizeTask != null) {
         localizeTask.dependsOn project.tasks.findByName('buildLicenseNotice')
     }
-
-    if (!dataBindingConfig.runProguard || !dataBindingConfig.inReleaseBuild) {
+    if (!dataBindingConfig.inReleaseBuild) {
         return
     }
     def jarName = project.uploadArchives.repositories.mavenDeployer.pom.artifactId
@@ -178,6 +177,7 @@
     def fatJar = "${workingDir}/${jarName}-fat.jar"
     def proguardJar = "${workingDir}/${jarName}-proguard.jar"
     def jarJar = project.jar.archivePath
+    def runProguard = dataBindingConfig.runProguard
 
     project.configurations {
         jarJarArchives
@@ -208,6 +208,9 @@
         destinationDir = new File(workingDir)
         with project.jar
     }
+    /**
+     * not used unless jarJarFile is changed to use proguarded version instead.
+     */
     project.tasks.create(name: 'proguard', type: proguard.gradle.ProGuardTask) {
         dependsOn 'fatJar'
 
@@ -218,16 +221,16 @@
     }
 
     project.tasks.create(name: 'jarJarFile') {
-        dependsOn 'proguard'
+        dependsOn runProguard ? 'proguard' : 'fatJar'
         dependsOn project.jar
-        def inputLibrary = proguardJar
+        def inputLibrary = runProguard ? proguardJar : fatJar
         def outputLibrary = jarJar
         inputs.file(inputLibrary)
         outputs.file(outputLibrary)
 
         doLast {
             def jarJarLibrary = new File(dataBindingConfig.externalPrebuiltsBase,
-                    'tools/common/m2/repository/com/googlecode/jarjar/jarjar/1.3/jarjar-1.3.jar').
+                    'tools/common/m2/repository/com/googlecode/jarjar/jarjar/1.4/jarjar-1.4.jar').
                     getCanonicalPath()
             // in Ant
             ant.taskdef(name: "jarjarIt",
@@ -238,8 +241,7 @@
                 // input is our inputLibrary
                 zipfileset(src: inputLibrary)
                 // rule to repackage antlr to new package
-                rule pattern: 'org.antlr.**', result: 'com.google.repacked.antlr.@1'
-                rule pattern: 'com.tunnelvisionlabs.**', result: 'com.google.repacked.tunnelvision.@1'
+                rule pattern: 'org.antlr.**', result: 'com.google.repacked.org.antlr.@1'
                 rule pattern: 'org.abego.treelayout.**', result: 'com.google.repacked.treelayout.@1'
                 // rule to repackage commons
                 rule pattern: 'org.apache.**', result: 'com.google.repacked.apache.@1'
@@ -248,25 +250,33 @@
         }
     }
 
-    project.uploadArchives {
-        dependsOn 'jarJarFile'
-        repositories {
-            mavenDeployer {
-                pom.whenConfigured { pom ->
-                    pom.dependencies.removeAll { dep ->
-                        def isBaseLibrary = dep.groupId == 'com.android.databinding' &&
-                                dep.artifactId == 'baseLibrary'
-                        def isGradle = dep.groupId == 'com.android.tools.build' &&
-                                dep.artifactId == 'gradle'
-                        def isChardet = dep.groupId == 'com.googlecode.juniversalchardet' &&
-                                dep.artifactId == 'juniversalchardet'
-                        return !isBaseLibrary && !isGradle && !isChardet
+    def setupUpload = { uploadTask ->
+        uploadTask.dependsOn 'jarJarFile'
+        uploadTask.repositories {
+                mavenDeployer {
+                    pom.whenConfigured { pom ->
+                        pom.dependencies.removeAll { dep ->
+                            def isBaseLibrary = dep.groupId == 'com.android.databinding' &&
+                                    dep.artifactId == 'baseLibrary'
+                            def isGradle = dep.groupId == 'com.android.tools.build' &&
+                                    dep.artifactId == 'gradle'
+                            def isChardet = dep.groupId == 'com.googlecode.juniversalchardet' &&
+                                    dep.artifactId == 'juniversalchardet'
+                            return !isBaseLibrary && !isGradle && !isChardet
+                        }
                     }
                 }
             }
-        }
-        outputs.upToDateWhen { false } // force it to re-run all the time.
+        uploadTask.outputs.upToDateWhen { false } // force it to re-run all the time.
     }
+
+    if (project.publishLocal != null) {
+        setupUpload(project.publishLocal)
+    }
+    if (project.uploadArchives != null) {
+        setupUpload(project.uploadArchives)
+    }
+
     project.bintrayUpload.dependsOn 'jarJarFile'
     project.publishing.publications.mavenJava(MavenPublication) {
             pom.withXml {
diff --git a/compilationTests/build.gradle b/compilationTests/build.gradle
index 0ca1877..be30dc2 100644
--- a/compilationTests/build.gradle
+++ b/compilationTests/build.gradle
@@ -9,9 +9,18 @@
     testCompile 'commons-io:commons-io:2.4'
     testCompile 'commons-codec:commons-codec:1.10'
     testCompile project(':dataBinding:compilerCommon')
+    testCompile project(':dataBinding:compiler')
 }
 
 afterEvaluate {
     tasks['test'].systemProperties['useReleaseVersion'] = dataBindingConfig.inReleaseBuild ? 'true' : 'false'
     tasks['test'].systemProperties['addRemoteRepos'] = dataBindingConfig.addRemoteRepos ? 'true' : 'false'
-}
\ No newline at end of file
+}
+
+sourceSets {
+    test {
+        java {
+            srcDirs += "${project.rootProject.getProjectDir().getAbsolutePath()}/compiler/src/test/java/android/databinding/tool/reflection/java"
+        }
+    }
+}
diff --git a/compilationTests/compilationTests.iml b/compilationTests/compilationTests.iml
deleted file mode 100644
index 751bf1e..0000000
--- a/compilationTests/compilationTests.iml
+++ /dev/null
@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module external.linked.project.id=":dataBinding:compilationTests" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="data-binding.dataBinding" external.system.module.version="1.0" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="false">
-    <output url="file://$MODULE_DIR$/build/classes/main" />
-    <output-test url="file://$MODULE_DIR$/build/classes/test" />
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
-      <excludeFolder url="file://$MODULE_DIR$/.gradle" />
-      <excludeFolder url="file://$MODULE_DIR$/build" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="module" module-name="compilerCommon" scope="TEST" />
-    <orderEntry type="module" module-name="baseLibrary" scope="TEST" />
-    <orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: org.apache.commons:commons-lang3:3.3.2" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: commons-io:commons-io:2.4" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: commons-codec:commons-codec:1.10" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: com.tunnelvisionlabs:antlr4:4.5" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: com.googlecode.juniversalchardet:juniversalchardet:1.0.3" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: com.tunnelvisionlabs:antlr4-runtime:4.5" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: com.tunnelvisionlabs:antlr4-annotations:4.5" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: org.antlr:antlr-runtime:3.5.2" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: org.antlr:ST4:4.0.8" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: org.abego.treelayout:org.abego.treelayout.core:1.0.1" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: com.google.guava:guava:17.0" level="project" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/compilationTests/src/test/java/android/databinding/compilationTest/CompilationResult.java b/compilationTests/src/test/java/android/databinding/compilationTest/CompilationResult.java
index f6d1f5e..90fd122 100644
--- a/compilationTests/src/test/java/android/databinding/compilationTest/CompilationResult.java
+++ b/compilationTests/src/test/java/android/databinding/compilationTest/CompilationResult.java
@@ -18,7 +18,9 @@
 
 import android.databinding.tool.processing.ScopedErrorReport;
 import android.databinding.tool.processing.ScopedException;
+import android.databinding.tool.util.StringUtils;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import static org.junit.Assert.assertEquals;
@@ -51,6 +53,16 @@
         return errors.get(0);
     }
 
+    public List<String> getBindingWarnings() {
+        List<String> warnings = new ArrayList<String>();
+        for (String line : error.split(StringUtils.LINE_SEPARATOR)) {
+            if (line.startsWith("warning:")) {
+                warnings.add(line.substring("warning:".length()));
+            }
+        }
+        return warnings;
+    }
+
     public List<ScopedException> getBindingExceptions() {
         return ScopedException.extractErrors(error);
     }
diff --git a/compilationTests/src/test/java/android/databinding/compilationTest/MultiLayoutVerificationTest.java b/compilationTests/src/test/java/android/databinding/compilationTest/MultiLayoutVerificationTest.java
index bbf86e7..2c13868 100644
--- a/compilationTests/src/test/java/android/databinding/compilationTest/MultiLayoutVerificationTest.java
+++ b/compilationTests/src/test/java/android/databinding/compilationTest/MultiLayoutVerificationTest.java
@@ -208,13 +208,15 @@
         CompilationResult result = runGradle("assembleDebug");
         assertNotEquals(result.output, 0, result.resultCode);
         List<ScopedException> exceptions = result.getBindingExceptions();
-        assertEquals(result.error, 2, exceptions.size());
 
         boolean foundNormal = false;
         boolean foundLandscape = false;
         for (ScopedException exception : exceptions) {
             ScopedErrorReport report = exception.getScopedErrorReport();
             assertNotNull(report);
+            if (exception.getMessage().startsWith("Cannot find the setter")) {
+                continue;
+            }
             File file = new File(report.getFilePath());
             assertTrue(file.exists());
             assertEquals(result.error, 1, report.getLocations().size());
diff --git a/compilationTests/src/test/java/android/databinding/compilationTest/SimpleCompilationTest.java b/compilationTests/src/test/java/android/databinding/compilationTest/SimpleCompilationTest.java
index 229323f..ee5467e 100644
--- a/compilationTests/src/test/java/android/databinding/compilationTest/SimpleCompilationTest.java
+++ b/compilationTests/src/test/java/android/databinding/compilationTest/SimpleCompilationTest.java
@@ -16,23 +16,41 @@
 
 package android.databinding.compilationTest;
 
+import android.databinding.tool.CompilerChef;
+import android.databinding.tool.processing.ErrorMessages;
+import android.databinding.tool.processing.ScopedErrorReport;
+import android.databinding.tool.processing.ScopedException;
+import android.databinding.tool.reflection.InjectedClass;
+import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.reflection.ModelMethod;
+import android.databinding.tool.reflection.java.JavaAnalyzer;
+import android.databinding.tool.store.Location;
+
+import com.google.common.base.Joiner;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.filefilter.PrefixFileFilter;
 import org.apache.commons.io.filefilter.SuffixFileFilter;
 import org.apache.commons.lang3.StringUtils;
 import org.junit.Test;
 
-import android.databinding.tool.processing.ErrorMessages;
-import android.databinding.tool.processing.ScopedErrorReport;
-import android.databinding.tool.processing.ScopedException;
-import android.databinding.tool.store.Location;
-
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
@@ -118,6 +136,21 @@
         return scopedException;
     }
 
+    private void singleFileWarningTest(String resource, String targetFile,
+            String expectedMessage)
+            throws IOException, URISyntaxException, InterruptedException {
+        prepareProject();
+        copyResourceTo(resource, targetFile);
+        CompilationResult result = runGradle("assembleDebug");
+        assertEquals(0, result.resultCode);
+        final List<String> warnings = result.getBindingWarnings();
+        boolean found = false;
+        for (String warning : warnings) {
+            found |= warning.contains(expectedMessage);
+        }
+        assertTrue(Joiner.on("\n").join(warnings),found);
+    }
+
     @Test
     public void testMultipleExceptionsInDifferentFiles()
             throws IOException, URISyntaxException, InterruptedException {
@@ -142,7 +175,7 @@
                 expectedErrorFile = "/app/src/main/res/layout/broken.xml";
             } else if (errorFile.getCanonicalPath().equals(invalidSetter.getCanonicalPath())) {
                 message = String.format(ErrorMessages.CANNOT_FIND_SETTER_CALL, "android:textx",
-                        String.class.getCanonicalName());
+                        String.class.getCanonicalName(), "android.widget.TextView");
                 expectedErrorFile = "/app/src/main/res/layout/invalid_setter.xml";
             } else {
                 fail("unexpected exception " + exception.getBareMessage());
@@ -161,9 +194,9 @@
                 "/app/src/main/res/layout/broken.xml",
                 "myVar.length())",
                 String.format(ErrorMessages.SYNTAX_ERROR,
-                        "extraneous input ')' expecting {<EOF>, ',', '.', '[', '+', '-', '*', '/', "
-                                + "'%', '<<', '>>>', '>>', '<=', '>=', '>', '<', 'instanceof', "
-                                + "'==', '!=', '&', '^', '|', '&&', '||', '?', '??'}"));
+                        "extraneous input ')' expecting {<EOF>, ',', '.', '::', '[', '+', '-', " +
+                                "'*', '/', '%', '<<', '>>>', '>>', '<=', '>=', '>', '<', " +
+                                "'instanceof', '==', '!=', '&', '^', '|', '&&', '||', '?', '??'}"));
     }
 
     @Test
@@ -172,9 +205,9 @@
                 "/app/src/main/res/layout/broken.xml",
                 "new String()",
                 String.format(ErrorMessages.SYNTAX_ERROR,
-                        "mismatched input 'String' expecting {<EOF>, ',', '.', '[', '+', '-', '*', "
-                                + "'/', '%', '<<', '>>>', '>>', '<=', '>=', '>', '<', 'instanceof',"
-                                + " '==', '!=', '&', '^', '|', '&&', '||', '?', '??'}"));
+                        "mismatched input 'String' expecting {<EOF>, ',', '.', '::', '[', '+', " +
+                                "'-', '*', '/', '%', '<<', '>>>', '>>', '<=', '>=', '>', '<', " +
+                                "'instanceof', '==', '!=', '&', '^', '|', '&&', '||', '?', '??'}"));
     }
 
     @Test
@@ -192,7 +225,35 @@
         ScopedException ex = singleFileErrorTest("/layout/invalid_setter_binding.xml",
                 "/app/src/main/res/layout/invalid_setter.xml", "myVariable",
                 String.format(ErrorMessages.CANNOT_FIND_SETTER_CALL, "android:textx",
-                        String.class.getCanonicalName()));
+                        String.class.getCanonicalName(), "android.widget.TextView"));
+    }
+
+    @Test
+    public void testCallbackArgumentCountMismatch() throws Throwable {
+        singleFileErrorTest("/layout/layout_with_missing_callback_args.xml",
+                "/app/src/main/res/layout/broken.xml",
+                "(seekBar, progress) -> obj.length()",
+                String.format(ErrorMessages.CALLBACK_ARGUMENT_COUNT_MISMATCH,
+                        "android.databinding.adapters.SeekBarBindingAdapter.OnProgressChanged",
+                        "onProgressChanged", 3, 2));
+    }
+
+    @Test
+    public void testDuplicateCallbackArgument() throws Throwable {
+        singleFileErrorTest("/layout/layout_with_duplicate_callback_identifier.xml",
+                "/app/src/main/res/layout/broken.xml",
+                "(seekBar, progress, progress) -> obj.length()",
+                String.format(ErrorMessages.DUPLICATE_CALLBACK_ARGUMENT,
+                        "progress"));
+    }
+
+    @Test
+    public void testConflictWithVariableName() throws Throwable {
+        singleFileWarningTest("/layout/layout_with_same_name_for_var_and_callback.xml",
+                "/app/src/main/res/layout/broken.xml",
+                String.format(ErrorMessages.CALLBACK_VARIABLE_NAME_CLASH,
+                        "myVar", "myVar", "String"));
+
     }
 
     @Test
@@ -213,7 +274,7 @@
         prepareProject();
         ScopedException ex = singleFileErrorTest("/layout/invalid_variable_type.xml",
                 "/app/src/main/res/layout/invalid_variable.xml", "myVariable",
-                String.format(ErrorMessages.CANNOT_RESOLVE_TYPE, "myVariable~"));
+                String.format(ErrorMessages.CANNOT_RESOLVE_TYPE, "myVariable"));
     }
 
     @Test
@@ -281,4 +342,61 @@
         assertEquals("Merge shouldn't support includes as root. Error message was '" + result.error,
                 ErrorMessages.INCLUDE_INSIDE_MERGE, ex.getBareMessage());
     }
+
+    @Test
+    public void testAssignTwoWayEvent() throws Throwable {
+        prepareProject();
+        copyResourceTo("/layout/layout_with_two_way_event_attribute.xml",
+                "/app/src/main/res/layout/layout_with_two_way_event_attribute.xml");
+        CompilationResult result = runGradle("assembleDebug");
+        assertNotEquals(0, result.resultCode);
+        List<ScopedException> errors = ScopedException.extractErrors(result.error);
+        assertEquals(result.error, 1, errors.size());
+        final ScopedException ex = errors.get(0);
+        final ScopedErrorReport report = ex.getScopedErrorReport();
+        final File errorFile = new File(report.getFilePath());
+        assertTrue(errorFile.exists());
+        assertEquals(new File(testFolder,
+                "/app/src/main/res/layout/layout_with_two_way_event_attribute.xml")
+                        .getCanonicalFile(),
+                errorFile.getCanonicalFile());
+        assertEquals("The attribute android:textAttrChanged is a two-way binding event attribute " +
+                "and cannot be assigned.", ex.getBareMessage());
+    }
+
+    @SuppressWarnings("deprecated")
+    @Test
+    public void testDynamicUtilMembers() throws Throwable {
+        prepareProject();
+        CompilationResult result = runGradle("assembleDebug");
+        assertEquals(result.error, 0, result.resultCode);
+        assertTrue("there should not be any errors " + result.error,
+                StringUtils.isEmpty(result.error));
+        assertTrue("Test sanity, should compile fine",
+                result.resultContainsText("BUILD SUCCESSFUL"));
+        File classFile = new File(testFolder,
+                "app/build/intermediates/classes/debug/android/databinding/DynamicUtil.class");
+        assertTrue(classFile.exists());
+
+        File root = new File(testFolder, "app/build/intermediates/classes/debug/");
+        URL[] urls = new URL[] {root.toURL()};
+        JavaAnalyzer.initForTests();
+        JavaAnalyzer analyzer = (JavaAnalyzer) JavaAnalyzer.getInstance();
+        ClassLoader classLoader = new URLClassLoader(urls, analyzer.getClassLoader());
+        Class dynamicUtilClass = classLoader.loadClass("android.databinding.DynamicUtil");
+
+        InjectedClass injectedClass = CompilerChef.pushDynamicUtilToAnalyzer();
+
+        // test methods
+        for (Method method : dynamicUtilClass.getMethods()) {
+            // look for the method in the injected class
+            ArrayList<ModelClass> args = new ArrayList<ModelClass>();
+            for (Class<?> param : method.getParameterTypes()) {
+                args.add(analyzer.findClass(param));
+            }
+            ModelMethod modelMethod = injectedClass.getMethod(
+                    method.getName(), args, Modifier.isStatic(method.getModifiers()), false);
+            assertNotNull("Method " + method + " not found", modelMethod);
+        }
+    }
 }
diff --git a/compilationTests/src/test/resources/layout/layout_with_duplicate_callback_identifier.xml b/compilationTests/src/test/resources/layout/layout_with_duplicate_callback_identifier.xml
new file mode 100644
index 0000000..3ba571e
--- /dev/null
+++ b/compilationTests/src/test/resources/layout/layout_with_duplicate_callback_identifier.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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.
+  -->
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:bind="http://schemas.android.com/apk/res-auto">
+    <data>
+        <variable name="myVar" type="String"/>
+    </data>
+    <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+        <!-- undefined variable -->
+        <View android:layout_width="wrap_content" android:layout_height="wrap_content"
+                  android:onProgressChanged="@{(seekBar, progress, progress) -> obj.length()}"/>
+    </LinearLayout>
+</layout>
\ No newline at end of file
diff --git a/compilationTests/src/test/resources/layout/layout_with_missing_callback_args.xml b/compilationTests/src/test/resources/layout/layout_with_missing_callback_args.xml
new file mode 100644
index 0000000..7882cb6
--- /dev/null
+++ b/compilationTests/src/test/resources/layout/layout_with_missing_callback_args.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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.
+  -->
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:bind="http://schemas.android.com/apk/res-auto">
+    <data>
+        <variable name="myVar" type="String"/>
+    </data>
+    <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+        <!-- undefined variable -->
+        <SeekBar android:layout_width="wrap_content" android:layout_height="wrap_content"
+                  android:onProgressChanged="@{(seekBar, progress) -> obj.length()}"/>
+    </LinearLayout>
+</layout>
\ No newline at end of file
diff --git a/compilationTests/src/test/resources/layout/layout_with_same_name_for_var_and_callback.xml b/compilationTests/src/test/resources/layout/layout_with_same_name_for_var_and_callback.xml
new file mode 100644
index 0000000..379ae6e
--- /dev/null
+++ b/compilationTests/src/test/resources/layout/layout_with_same_name_for_var_and_callback.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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.
+  -->
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:bind="http://schemas.android.com/apk/res-auto">
+    <data>
+        <variable name="myVar" type="String"/>
+    </data>
+    <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+        <!-- undefined variable -->
+        <SeekBar android:layout_width="wrap_content" android:layout_height="wrap_content"
+                  android:onClick="@{(myVar) -> myVar.setVisibility(1)}"/>
+    </LinearLayout>
+</layout>
\ No newline at end of file
diff --git a/compilationTests/src/test/resources/layout/layout_with_two_way_event_attribute.xml b/compilationTests/src/test/resources/layout/layout_with_two_way_event_attribute.xml
new file mode 100644
index 0000000..16536e3
--- /dev/null
+++ b/compilationTests/src/test/resources/layout/layout_with_two_way_event_attribute.xml
@@ -0,0 +1,35 @@
+<?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.
+  -->
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+>
+    <data>
+        <variable name="myVariable" type="String"/>
+        <variable name="myEventListener" type="android.databinding.InverseBindingListener"/>
+    </data>
+    <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+        <!-- undefined variable -->
+        <TextView android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:id="@+id/textView"
+                  android:text="@{myVariable}"
+                  android:textAttrChanged="@{myEventListener}"/>
+    </LinearLayout>
+</layout>
\ No newline at end of file
diff --git a/compiler/build.gradle b/compiler/build.gradle
index 8a9e991..cd4eac2 100644
--- a/compiler/build.gradle
+++ b/compiler/build.gradle
@@ -16,8 +16,8 @@
 apply plugin: 'java'
 apply plugin: 'kotlin'
 
-sourceCompatibility = dataBindingConfig.javaTargetCompatibility
-targetCompatibility = dataBindingConfig.javaSourceCompatibility
+sourceCompatibility = dataBindingConfig.compilerJavaTargetCompatibility
+targetCompatibility = dataBindingConfig.compilerJavaSourceCompatibility
 
 sourceSets {
     main.java.srcDirs += 'src/main/kotlin'
@@ -38,7 +38,7 @@
     compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
     compile 'commons-io:commons-io:2.4'
     compile 'commons-codec:commons-codec:1.10'
-    compile 'com.tunnelvisionlabs:antlr4:4.5'
+    compile 'org.antlr:antlr4:4.5.3'
     compile 'com.googlecode.juniversalchardet:juniversalchardet:1.0.3'
     testCompile 'junit:junit:4.12'
 }
@@ -60,7 +60,9 @@
     }
 }
 
-
+javadoc {
+   options.addStringOption('Xdoclint:none', '-quiet')
+}
 
 project.ext.pomName = 'Data Binding Annotation Processor'
 project.ext.pomDesc = 'The annotation processor for Data Binding. Generates binding classes for runtime.'
diff --git a/compiler/compiler.iml b/compiler/compiler.iml
deleted file mode 100644
index b0d4edf..0000000
--- a/compiler/compiler.iml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module external.linked.project.id=":dataBinding:compiler" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.version="1.1" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="false">
-    <output url="file://$MODULE_DIR$/build/classes/main" />
-    <output-test url="file://$MODULE_DIR$/build/classes/test" />
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/main/kotlin" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/kotlin" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
-      <excludeFolder url="file://$MODULE_DIR$/.gradle" />
-      <excludeFolder url="file://$MODULE_DIR$/build" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="module" module-name="compilerCommon" />
-    <orderEntry type="module" module-name="baseLibrary" />
-    <orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-stdlib:1.0.0-beta-4584" level="project" />
-    <orderEntry type="library" name="Gradle: commons-io:commons-io:2.4" level="project" />
-    <orderEntry type="library" name="Gradle: commons-codec:commons-codec:1.10" level="project" />
-    <orderEntry type="library" name="Gradle: com.tunnelvisionlabs:antlr4:4.5" level="project" />
-    <orderEntry type="library" name="Gradle: com.googlecode.juniversalchardet:juniversalchardet:1.0.3" level="project" />
-    <orderEntry type="library" name="Gradle: org.jetbrains.kotlin:kotlin-runtime:1.0.0-beta-4584" level="project" />
-    <orderEntry type="library" name="Gradle: com.tunnelvisionlabs:antlr4-runtime:4.5" level="project" />
-    <orderEntry type="library" name="Gradle: com.tunnelvisionlabs:antlr4-annotations:4.5" level="project" />
-    <orderEntry type="library" name="Gradle: org.antlr:antlr-runtime:3.5.2" level="project" />
-    <orderEntry type="library" name="Gradle: org.antlr:ST4:4.0.8" level="project" />
-    <orderEntry type="library" name="Gradle: org.abego.treelayout:org.abego.treelayout.core:1.0.1" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" />
-    <orderEntry type="library" name="Gradle: com.google.guava:guava:17.0" level="project" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/compiler/db-compiler.iml b/compiler/db-compiler.iml
index 2f3a0d2..d47a582 100644
--- a/compiler/db-compiler.iml
+++ b/compiler/db-compiler.iml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <module relativePaths="true" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
     <exclude-output />
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
diff --git a/compiler/src/main/java/android/databinding/tool/Binding.java b/compiler/src/main/java/android/databinding/tool/Binding.java
index aba6b3e..59e8614 100644
--- a/compiler/src/main/java/android/databinding/tool/Binding.java
+++ b/compiler/src/main/java/android/databinding/tool/Binding.java
@@ -17,19 +17,24 @@
 package android.databinding.tool;
 
 import android.databinding.tool.expr.Expr;
+import android.databinding.tool.expr.ExprModel;
+import android.databinding.tool.expr.LambdaExpr;
 import android.databinding.tool.processing.ErrorMessages;
 import android.databinding.tool.processing.Scope;
 import android.databinding.tool.processing.scopes.LocationScopeProvider;
 import android.databinding.tool.reflection.ModelAnalyzer;
 import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.reflection.ModelMethod;
 import android.databinding.tool.store.Location;
 import android.databinding.tool.store.SetterStore;
 import android.databinding.tool.store.SetterStore.BindingSetterCall;
 import android.databinding.tool.store.SetterStore.SetterCall;
 import android.databinding.tool.util.L;
+import android.databinding.tool.util.Preconditions;
 import android.databinding.tool.writer.LayoutBinderWriterKt;
 
 import java.util.List;
+import java.util.Map;
 
 public class Binding implements LocationScopeProvider {
 
@@ -55,7 +60,7 @@
     }
 
     public void resolveListeners() {
-        final ModelClass listenerParameter = getListenerParameter(mTarget, mName, mExpr);
+        final ModelClass listenerParameter = getListenerParameter(mTarget, mName, mExpr.getModel());
         Expr listenerExpr = mExpr.resolveListeners(listenerParameter, null);
         if (listenerExpr != mExpr) {
             listenerExpr.setBindingExpression(true);
@@ -63,6 +68,30 @@
         }
     }
 
+    public void resolveCallbackParams() {
+        if (!(mExpr instanceof LambdaExpr)) {
+            return;
+        }
+        LambdaExpr lambdaExpr = (LambdaExpr) mExpr;
+        final ModelClass listener = getListenerParameter(mTarget, mName, mExpr.getModel());
+        Preconditions.checkNotNull(listener, ErrorMessages.CANNOT_FIND_SETTER_CALL, mName,
+                "lambda", getTarget().getInterfaceType());
+        //noinspection ConstantConditions
+        List<ModelMethod> abstractMethods = listener.getAbstractMethods();
+        int numberOfAbstractMethods = abstractMethods.size();
+        if (numberOfAbstractMethods != 1) {
+            L.e(ErrorMessages.CANNOT_FIND_ABSTRACT_METHOD, mName, listener.getCanonicalName(),
+                    numberOfAbstractMethods, 1);
+        }
+        final ModelMethod method = abstractMethods.get(0);
+        final int argCount = lambdaExpr.getCallbackExprModel().getArgCount();
+        if (argCount != 0 && argCount != method.getParameterTypes().length) {
+            L.e(ErrorMessages.CALLBACK_ARGUMENT_COUNT_MISMATCH, listener.getCanonicalName(),
+                    method.getName(), method.getParameterTypes().length, argCount);
+        }
+        lambdaExpr.setup(listener, method, mExpr.getModel().obtainCallbackId());
+    }
+
     public void resolveTwoWayExpressions() {
         Expr expr = mExpr.resolveTwoWayExpressions(null);
         if (expr != mExpr) {
@@ -77,7 +106,8 @@
                 Scope.enter(this);
                 resolveSetterCall();
                 if (mSetterCall == null) {
-                    L.e(ErrorMessages.CANNOT_FIND_SETTER_CALL, mName, mExpr.getResolvedType());
+                    L.e(ErrorMessages.CANNOT_FIND_SETTER_CALL, mName, mExpr.getResolvedType(),
+                            getTarget().getInterfaceType());
                 }
             } finally {
                 Scope.exit();
@@ -97,7 +127,8 @@
                 mSetterCall = SetterStore.get(modelAnalyzer).getSetterCall(mName,
                         viewStubProxy, mExpr.getResolvedType(), mExpr.getModel().getImports());
             } else if (isViewStubAttribute(mName)) {
-                mSetterCall = new ViewStubDirectCall(mName, viewType, mExpr);
+                mSetterCall = new ViewStubDirectCall(mName, viewType, mExpr.getResolvedType(),
+                        mExpr.getModel().getImports());
             } else {
                 mSetterCall = new ViewStubSetterCall(mName);
             }
@@ -111,7 +142,8 @@
     /**
      * Similar to getSetterCall, but assumes an Object parameter to find the best matching listener.
      */
-    private static ModelClass getListenerParameter(BindingTarget target, String name, Expr expr) {
+    private static ModelClass getListenerParameter(BindingTarget target, String name,
+            ExprModel model) {
         ModelClass viewType = target.getResolvedType();
         SetterCall setterCall;
         ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance();
@@ -122,15 +154,15 @@
                 ModelClass viewStubProxy = modelAnalyzer.
                         findClass("android.databinding.ViewStubProxy", null);
                 setterCall = SetterStore.get(modelAnalyzer).getSetterCall(name,
-                        viewStubProxy, objectParameter, expr.getModel().getImports());
+                        viewStubProxy, objectParameter, model.getImports());
             } else if (isViewStubAttribute(name)) {
-                setterCall = new ViewStubDirectCall(name, viewType, expr);
+                setterCall = null; // view stub attrs are not callbacks
             } else {
                 setterCall = new ViewStubSetterCall(name);
             }
         } else {
             setterCall = setterStore.getSetterCall(name, viewType, objectParameter,
-                    expr.getModel().getImports());
+                    model.getImports());
         }
         if (setterCall != null) {
             return setterCall.getParameterTypes()[0];
@@ -244,12 +276,13 @@
     private static class ViewStubDirectCall extends SetterCall {
         private final SetterCall mWrappedCall;
 
-        public ViewStubDirectCall(String name, ModelClass viewType, Expr expr) {
+        public ViewStubDirectCall(String name, ModelClass viewType, ModelClass resolvedType,
+                Map<String, String> imports) {
             mWrappedCall = SetterStore.get(ModelAnalyzer.getInstance()).getSetterCall(name,
-                    viewType, expr.getResolvedType(), expr.getModel().getImports());
+                    viewType, resolvedType, imports);
             if (mWrappedCall == null) {
                 L.e("Cannot find the setter for attribute '%s' on %s with parameter type %s.",
-                        name, viewType, expr.getResolvedType());
+                        name, viewType, resolvedType);
             }
         }
 
diff --git a/compiler/src/main/java/android/databinding/tool/BindingTarget.java b/compiler/src/main/java/android/databinding/tool/BindingTarget.java
index d8db559..8c59ca7 100644
--- a/compiler/src/main/java/android/databinding/tool/BindingTarget.java
+++ b/compiler/src/main/java/android/databinding/tool/BindingTarget.java
@@ -58,28 +58,24 @@
             L.e(ErrorMessages.TWO_WAY_EVENT_ATTRIBUTE, name);
         }
         mBindings.add(new Binding(this, name, expr));
-        if (expr.isTwoWay()) {
-            try {
-                Scope.enter(expr);
-                expr.assertIsInvertible();
-                final InverseBinding inverseBinding = new InverseBinding(this, name, expr);
-                mInverseBindings.add(inverseBinding);
-                mBindings.add(new Binding(this, inverseBinding.getEventAttribute(),
-                        mModel.twoWayListenerExpr(inverseBinding),
-                        inverseBinding.getEventSetter()));
-            } finally {
-                Scope.exit();
-            }
-        }
     }
 
     public String getInterfaceType() {
         return mBundle.getInterfaceType() == null ? mBundle.getFullClassName() : mBundle.getInterfaceType();
     }
 
+    public InverseBinding addInverseBinding(String name, Expr expr, String bindingClass) {
+        expr.assertIsInvertible();
+        final InverseBinding inverseBinding = new InverseBinding(this, name, expr, bindingClass);
+        mInverseBindings.add(inverseBinding);
+        mBindings.add(new Binding(this, inverseBinding.getEventAttribute(),
+                mModel.twoWayListenerExpr(inverseBinding),
+                inverseBinding.getEventSetter()));
+        return inverseBinding;
+    }
+
     public InverseBinding addInverseBinding(String name, BindingGetterCall call) {
-        final InverseBinding inverseBinding = new InverseBinding(this, name, null);
-        inverseBinding.setGetterCall(call);
+        final InverseBinding inverseBinding = new InverseBinding(this, name, call);
         mInverseBindings.add(inverseBinding);
         mBindings.add(new Binding(this, inverseBinding.getEventAttribute(),
                 mModel.twoWayListenerExpr(inverseBinding)));
@@ -111,7 +107,7 @@
         if (mResolvedClass == null) {
             if (mBundle.isBinder()) {
                 mResolvedClass = ModelAnalyzer.getInstance().
-                        findClass(ModelAnalyzer.VIEW_DATA_BINDING, mModel.getImports());
+                        findClass(mBundle.getInterfaceType(), mModel.getImports());
             } else {
                 mResolvedClass = ModelAnalyzer.getInstance().findClass(mBundle.getFullClassName(),
                         mModel.getImports());
@@ -151,13 +147,34 @@
 
     public void resolveListeners() {
         for (Binding binding : mBindings) {
-            binding.resolveListeners();
+            try {
+                Scope.enter(binding);
+                binding.resolveListeners();
+            } finally {
+                Scope.exit();
+            }
+        }
+    }
+
+    public void resolveCallbackParams() {
+        for (Binding binding : mBindings) {
+            try {
+                Scope.enter(binding);
+                binding.resolveCallbackParams();
+            } finally {
+                Scope.exit();
+            }
         }
     }
 
     public void resolveTwoWayExpressions() {
         for (Binding binding : mBindings) {
-            binding.resolveTwoWayExpressions();
+            try {
+                Scope.enter(binding);
+                binding.resolveTwoWayExpressions();
+            } finally {
+                Scope.exit();
+            }
         }
     }
 
diff --git a/compiler/src/main/java/android/databinding/tool/CallbackWrapper.java b/compiler/src/main/java/android/databinding/tool/CallbackWrapper.java
new file mode 100644
index 0000000..d8ec24f
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/CallbackWrapper.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.tool;
+
+import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.reflection.ModelMethod;
+import android.databinding.tool.util.L;
+import android.databinding.tool.util.Preconditions;
+
+/**
+ * As data-binding finds lambda expressions, it creates classes that can wrap those callbacks
+ * into methods that can be called into the ViewDataBinding classes.
+ * <p>
+ * The model keeps track of these wrappers and at the end data-binding generates all of them.
+ * These are stripped from library projects and re-generated.
+ */
+public class CallbackWrapper {
+    public static String SOURCE_ID = "sourceId";
+    public static String ARG_PREFIX = "callbackArg_";
+    public final ModelClass klass;
+    public final ModelMethod method;
+    public final String key;
+    private static final String PACKAGE = "android.databinding.generated.callback";
+    private static final String LISTENER_NAME = "Listener";
+    private String mClassName;
+    private String mListenerMethodName;
+    private boolean mInitialized;
+
+    public CallbackWrapper(ModelClass klass, ModelMethod method) {
+        this.klass = klass;
+        this.method = method;
+        this.key = uniqueKey(klass, method);
+    }
+
+    public void prepare(String className, String listenerMethodName) {
+        if (mInitialized) {
+            L.e("trying to initialize listener wrapper twice.");
+        }
+        mInitialized = true;
+        mClassName = className;
+        mListenerMethodName = listenerMethodName;
+    }
+
+    public String getPackage() {
+        return PACKAGE;
+    }
+
+    public String getClassName() {
+        Preconditions.check(mInitialized, "Listener wrapper is not initialized yet.");
+        return mClassName;
+    }
+
+    public String getListenerInterfaceName() {
+        return LISTENER_NAME;
+    }
+
+    public String getListenerMethodName() {
+        Preconditions.check(mInitialized, "Listener wrapper is not initialized yet.");
+        return mListenerMethodName;
+    }
+
+    public static String uniqueKey(ModelClass klass, ModelMethod method) {
+        String base = klass.getCanonicalName() + "#" + method.getName();
+        for (ModelClass param : method.getParameterTypes()) {
+            base += param + ",";
+        }
+        return base;
+    }
+
+    public String getCannonicalName() {
+        return getPackage() + "." + getClassName();
+    }
+
+    public String getCannonicalListenerName() {
+        return getPackage() + "." + getClassName() + "." + getListenerInterfaceName();
+    }
+
+    public String constructForIdentifier(int listenerId) {
+        return "new " + getCannonicalName() + "(this, " + listenerId + ")";
+    }
+
+    public int getMinApi() {
+        return Math.min(method.getMinApi(), klass.getMinApi());
+    }
+}
diff --git a/compiler/src/main/java/android/databinding/tool/CompilerChef.java b/compiler/src/main/java/android/databinding/tool/CompilerChef.java
index b7456da..c167207 100644
--- a/compiler/src/main/java/android/databinding/tool/CompilerChef.java
+++ b/compiler/src/main/java/android/databinding/tool/CompilerChef.java
@@ -13,6 +13,8 @@
 
 package android.databinding.tool;
 
+import android.databinding.tool.reflection.InjectedClass;
+import android.databinding.tool.reflection.InjectedMethod;
 import android.databinding.tool.reflection.ModelAnalyzer;
 import android.databinding.tool.reflection.ModelClass;
 import android.databinding.tool.store.ResourceBundle;
@@ -23,6 +25,7 @@
 import android.databinding.tool.writer.DynamicUtilWriter;
 import android.databinding.tool.writer.JavaFileWriter;
 
+import java.util.HashMap;
 import java.util.Set;
 
 /**
@@ -69,6 +72,8 @@
         chef.mResourceBundle = bundle;
         chef.mFileWriter = fileWriter;
         chef.mResourceBundle.validateMultiResLayouts();
+        chef.pushClassesToAnalyzer();
+        chef.pushDynamicUtilToAnalyzer();
         return chef;
     }
 
@@ -89,6 +94,71 @@
         return mResourceBundle != null && mResourceBundle.getLayoutBundles().size() > 0;
     }
 
+    /**
+     * Injects ViewDataBinding subclasses to the ModelAnalyzer so that they can be
+     * analyzed prior to creation. This is useful for resolving variable setters and
+     * View fields during compilation.
+     */
+    private void pushClassesToAnalyzer() {
+        ModelAnalyzer analyzer = ModelAnalyzer.getInstance();
+        for (String layoutName : mResourceBundle.getLayoutBundles().keySet()) {
+            ResourceBundle.LayoutFileBundle layoutFileBundle =
+                    mResourceBundle.getLayoutBundles().get(layoutName).get(0);
+            final HashMap<String, String> imports = new HashMap<String, String>();
+            for (ResourceBundle.NameTypeLocation imp : layoutFileBundle.getImports()) {
+                imports.put(imp.name, imp.type);
+            }
+            final HashMap<String, String> variables = new HashMap<String, String>();
+            for (ResourceBundle.VariableDeclaration variable : layoutFileBundle.getVariables()) {
+                final String variableName = variable.name;
+                String type = variable.type;
+                if (imports.containsKey(type)) {
+                    type = imports.get(type);
+                }
+                variables.put(variableName, type);
+            }
+            final HashMap<String, String> fields = new HashMap<String, String>();
+            for (ResourceBundle.BindingTargetBundle bindingTargetBundle :
+                    layoutFileBundle.getBindingTargetBundles()) {
+                if (bindingTargetBundle.getId() != null) {
+                    fields.put(bindingTargetBundle.getId(), bindingTargetBundle.getInterfaceType());
+                }
+            }
+            final String className = layoutFileBundle.getBindingClassPackage() + "." +
+                    layoutFileBundle.getBindingClassName();
+            analyzer.injectViewDataBinding(className, variables, fields);
+        }
+    }
+
+    public static InjectedClass pushDynamicUtilToAnalyzer() {
+        InjectedClass injectedClass = new InjectedClass("android.databinding.DynamicUtil",
+                "java.lang.Object");
+        injectedClass.addMethod(new InjectedMethod(injectedClass, true, "getColorFromResource",
+                "int", "android.view.View", "int"));
+        injectedClass.addMethod(new InjectedMethod(injectedClass, true,
+                "getColorStateListFromResource", "android.content.res.ColorStateList",
+                "android.view.View", "int"));
+        injectedClass.addMethod(new InjectedMethod(injectedClass, true, "getDrawableFromResource",
+                "android.graphics.drawable.Drawable", "android.view.View", "int"));
+        injectedClass.addMethod(new InjectedMethod(injectedClass, true, "parse",
+                "boolean", "java.lang.String", "boolean"));
+        injectedClass.addMethod(new InjectedMethod(injectedClass, true, "parse",
+                "short", "java.lang.String", "short"));
+        injectedClass.addMethod(new InjectedMethod(injectedClass, true, "parse",
+                "int", "java.lang.String", "int"));
+        injectedClass.addMethod(new InjectedMethod(injectedClass, true, "parse",
+                "long", "java.lang.String", "long"));
+        injectedClass.addMethod(new InjectedMethod(injectedClass, true, "parse",
+                "float", "java.lang.String", "float"));
+        injectedClass.addMethod(new InjectedMethod(injectedClass, true, "parse",
+                "double", "java.lang.String", "double"));
+        injectedClass.addMethod(new InjectedMethod(injectedClass, true, "parse",
+                "char", "java.lang.String", "char"));
+        ModelAnalyzer analyzer = ModelAnalyzer.getInstance();
+        analyzer.injectClass(injectedClass);
+        return injectedClass;
+    }
+
     public void writeDataBinderMapper(int minSdk, BRWriter brWriter) {
         ensureDataBinder();
         final String pkg = "android.databinding";
diff --git a/compiler/src/main/java/android/databinding/tool/DataBinder.java b/compiler/src/main/java/android/databinding/tool/DataBinder.java
index 0280bd4..0942282 100644
--- a/compiler/src/main/java/android/databinding/tool/DataBinder.java
+++ b/compiler/src/main/java/android/databinding/tool/DataBinder.java
@@ -20,10 +20,13 @@
 import android.databinding.tool.processing.ScopedException;
 import android.databinding.tool.store.ResourceBundle;
 import android.databinding.tool.util.L;
+import android.databinding.tool.util.StringUtils;
+import android.databinding.tool.writer.CallbackWrapperWriter;
 import android.databinding.tool.writer.ComponentWriter;
 import android.databinding.tool.writer.JavaFileWriter;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -38,7 +41,7 @@
 
     private JavaFileWriter mFileWriter;
 
-    Set<String> writtenClasses = new HashSet<String>();
+    Set<String> mWrittenClasses = new HashSet<String>();
 
     public DataBinder(ResourceBundle resourceBundle) {
         L.d("reading resource bundle into data binder");
@@ -70,13 +73,13 @@
                 if (isLibrary || layoutBinder.hasVariations()) {
                     String className = layoutBinder.getClassName();
                     String canonicalName = layoutBinder.getPackage() + "." + className;
-                    if (writtenClasses.contains(canonicalName)) {
+                    if (mWrittenClasses.contains(canonicalName)) {
                         continue;
                     }
                     L.d("writing data binder base %s", canonicalName);
                     mFileWriter.writeToFile(canonicalName,
                             layoutBinder.writeViewBinderBaseClass(isLibrary));
-                    writtenClasses.add(canonicalName);
+                    mWrittenClasses.add(canonicalName);
                 }
             } catch (ScopedException ex){
                 Scope.defer(ex);
@@ -87,13 +90,14 @@
     }
 
     public void writeBinders(int minSdk) {
+        writeCallbackWrappers(minSdk);
         for (LayoutBinder layoutBinder : mLayoutBinders) {
             try {
                 Scope.enter(layoutBinder);
                 String className = layoutBinder.getImplementationName();
                 String canonicalName = layoutBinder.getPackage() + "." + className;
                 L.d("writing data binder %s", canonicalName);
-                writtenClasses.add(canonicalName);
+                mWrittenClasses.add(canonicalName);
                 mFileWriter.writeToFile(canonicalName, layoutBinder.writeViewBinder(minSdk));
             } catch (ScopedException ex) {
                 Scope.defer(ex);
@@ -103,15 +107,62 @@
         }
     }
 
+    private void writeCallbackWrappers(int minSdk) {
+        Map<String, CallbackWrapper> uniqueWrappers = new HashMap<String, CallbackWrapper>();
+        Set<String> classNames = new HashSet<String>();
+        int callbackCounter = 0;
+        for (LayoutBinder binder : mLayoutBinders) {
+            for (Map.Entry<String, CallbackWrapper> entry : binder.getModel().getCallbackWrappers()
+                    .entrySet()) {
+                final CallbackWrapper existing = uniqueWrappers.get(entry.getKey());
+                if (existing == null) {
+                    // first time seeing this. register
+                    final CallbackWrapper wrapper = entry.getValue();
+                    uniqueWrappers.put(entry.getKey(), wrapper);
+                    String listenerName = makeUnique(classNames, wrapper.klass.getSimpleName());
+                    String methodName = makeUnique(classNames,
+                            "_internalCallback" + StringUtils.capitalize(wrapper.method.getName()));
+                    wrapper.prepare(listenerName, methodName);
+                } else {
+                    // fill from previous
+                    entry.getValue()
+                            .prepare(existing.getClassName(), existing.getListenerMethodName());
+                }
+
+            }
+        }
+
+        // now write the original wrappers
+        for (CallbackWrapper wrapper : uniqueWrappers.values()) {
+            final String code = new CallbackWrapperWriter(wrapper).write();
+            String className = wrapper.getClassName();
+            String canonicalName = wrapper.getPackage() + "." + className;
+            mFileWriter.writeToFile(canonicalName, code);
+            // these will be deleted for library projects.
+            mWrittenClasses.add(canonicalName);
+        }
+
+    }
+
+    private String makeUnique(Set<String> existing, String wanted) {
+        int cnt = 1;
+        while (existing.contains(wanted)) {
+            wanted = wanted + cnt;
+            cnt++;
+        }
+        existing.add(wanted);
+        return wanted;
+    }
+
     public void writeComponent() {
         ComponentWriter componentWriter = new ComponentWriter();
 
-        writtenClasses.add(COMPONENT_CLASS);
+        mWrittenClasses.add(COMPONENT_CLASS);
         mFileWriter.writeToFile(COMPONENT_CLASS, componentWriter.createComponent());
     }
 
     public Set<String> getWrittenClassNames() {
-        return writtenClasses;
+        return mWrittenClasses;
     }
 
     public void setFileWriter(JavaFileWriter fileWriter) {
diff --git a/compiler/src/main/java/android/databinding/tool/ExpressionParser.java b/compiler/src/main/java/android/databinding/tool/ExpressionParser.java
index 5468c93..18fb839 100644
--- a/compiler/src/main/java/android/databinding/tool/ExpressionParser.java
+++ b/compiler/src/main/java/android/databinding/tool/ExpressionParser.java
@@ -23,7 +23,6 @@
 import org.antlr.v4.runtime.RecognitionException;
 import org.antlr.v4.runtime.Recognizer;
 import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.misc.Nullable;
 import org.antlr.v4.runtime.tree.ErrorNode;
 import org.antlr.v4.runtime.tree.ParseTreeListener;
 import org.antlr.v4.runtime.tree.TerminalNode;
@@ -37,6 +36,8 @@
 import android.databinding.tool.util.L;
 import android.databinding.tool.util.Preconditions;
 
+import com.android.annotations.Nullable;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -49,16 +50,16 @@
         visitor = new ExpressionVisitor(mModel);
     }
 
-    public Expr parse(String input, @Nullable Location locationInFile) {
+    public Expr parse(String input, @Nullable Location locationInFile, BindingTarget target) {
         ANTLRInputStream inputStream = new ANTLRInputStream(input);
         BindingExpressionLexer lexer = new BindingExpressionLexer(inputStream);
         CommonTokenStream tokenStream = new CommonTokenStream(lexer);
         final BindingExpressionParser parser = new BindingExpressionParser(tokenStream);
+        visitor.setBindingTarget(target);
         parser.addErrorListener(new BaseErrorListener() {
             @Override
-            public <T extends Token> void syntaxError(Recognizer<T, ?> recognizer,
-                    @Nullable T offendingSymbol, int line, int charPositionInLine, String msg,
-                    @Nullable RecognitionException e) {
+            public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line,
+                    int charPositionInLine, String msg, RecognitionException e) {
                 L.e(ErrorMessages.SYNTAX_ERROR, msg);
             }
         });
diff --git a/compiler/src/main/java/android/databinding/tool/ExpressionVisitor.java b/compiler/src/main/java/android/databinding/tool/ExpressionVisitor.java
index 08e6744..d273f38 100644
--- a/compiler/src/main/java/android/databinding/tool/ExpressionVisitor.java
+++ b/compiler/src/main/java/android/databinding/tool/ExpressionVisitor.java
@@ -16,14 +16,6 @@
 
 package android.databinding.tool;
 
-import com.google.common.base.Objects;
-
-import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.misc.NotNull;
-import org.antlr.v4.runtime.tree.ParseTree;
-import org.antlr.v4.runtime.tree.ParseTreeListener;
-import org.antlr.v4.runtime.tree.TerminalNode;
-
 import android.databinding.parser.BindingExpressionBaseVisitor;
 import android.databinding.parser.BindingExpressionParser;
 import android.databinding.parser.BindingExpressionParser.AndOrOpContext;
@@ -31,6 +23,7 @@
 import android.databinding.parser.BindingExpressionParser.BitShiftOpContext;
 import android.databinding.parser.BindingExpressionParser.InstanceOfOpContext;
 import android.databinding.parser.BindingExpressionParser.UnaryOpContext;
+import android.databinding.tool.expr.CallbackExprModel;
 import android.databinding.tool.expr.Expr;
 import android.databinding.tool.expr.ExprModel;
 import android.databinding.tool.expr.StaticIdentifierExpr;
@@ -38,21 +31,36 @@
 import android.databinding.tool.reflection.ModelClass;
 import android.databinding.tool.util.Preconditions;
 
+import com.android.annotations.NonNull;
+import com.google.common.base.Objects;
+
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.antlr.v4.runtime.tree.ParseTreeListener;
+import org.antlr.v4.runtime.tree.TerminalNode;
+
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.List;
 
-public class ExpressionVisitor extends BindingExpressionBaseVisitor<Expr> {
-    private final ExprModel mModel;
+class ExpressionVisitor extends BindingExpressionBaseVisitor<Expr> {
+    private ExprModel mModel;
     private ParseTreeListener mParseTreeListener;
+    private ArrayDeque<ExprModel> mModelStack = new ArrayDeque<ExprModel>();
+    private BindingTarget mTarget;
 
-    public ExpressionVisitor(ExprModel model) {
+    ExpressionVisitor(ExprModel model) {
         mModel = model;
     }
 
-    public void setParseTreeListener(ParseTreeListener parseTreeListener) {
+    void setParseTreeListener(ParseTreeListener parseTreeListener) {
         mParseTreeListener = parseTreeListener;
     }
 
+    public void setBindingTarget(BindingTarget bindingTarget) {
+        mTarget = bindingTarget;
+    }
+
     private void onEnter(ParserRuleContext context) {
         if (mParseTreeListener != null) {
             mParseTreeListener.enterEveryRule(context);
@@ -65,8 +73,75 @@
         }
     }
 
+    private void pushModel(ExprModel model) {
+        Preconditions.checkNotNull(mModel, "Cannot put empty model to stack");
+        Preconditions.checkNotNull(model, "Cannot set null model");
+        mModelStack.push(mModel);
+        mModel = model;
+    }
+
+    private void popModel() {
+        Preconditions.checkNotNull(mModel, "Cannot have empty mdoel stack");
+        Preconditions.check(mModelStack.size() > 0, "Cannot have empty model stack");
+        mModel = mModelStack.pop();
+    }
+
     @Override
-    public Expr visitStringLiteral(@NotNull BindingExpressionParser.StringLiteralContext ctx) {
+    public Expr visitRootLambda(@NonNull BindingExpressionParser.RootLambdaContext ctx) {
+        try {
+            onEnter(ctx);
+            CallbackExprModel callbackModel = new CallbackExprModel(mModel);
+            ExprModel prev = mModel;
+            pushModel(callbackModel);
+            final BindingExpressionParser.LambdaExpressionContext lambdaCtx = ctx
+                    .lambdaExpression();
+            lambdaCtx.args.accept(this);
+            return prev.lambdaExpr(lambdaCtx.expression().accept(this), callbackModel);
+        } finally {
+            popModel();
+            onExit(ctx);
+        }
+    }
+
+    @Override
+    public Expr visitSingleLambdaParameter(
+            @NonNull BindingExpressionParser.SingleLambdaParameterContext ctx) {
+        try {
+            onEnter(ctx);
+            Preconditions.check(mModel instanceof CallbackExprModel, "Lambdas can only be used in"
+                    + " callbacks.");
+            // just add it to the callback model as identifier
+            ((CallbackExprModel) mModel).callbackArg(ctx.getText());
+            return null;
+        } finally {
+            onExit(ctx);
+        }
+    }
+
+    @Override
+    public Expr visitLambdaParameterList(
+            @NonNull BindingExpressionParser.LambdaParameterListContext ctx) {
+        try {
+            onEnter(ctx);
+            Preconditions.check(mModel instanceof CallbackExprModel, "Lambdas can only be used in"
+                    + " callbacks.");
+            if (ctx.params != null) {
+                for (ParseTree item : ctx.params.children) {
+                    if (Objects.equal(item.getText(), ",")) {
+                        continue;
+                    }
+                    // just add them to the callback model as identifiers
+                    ((CallbackExprModel) mModel).callbackArg(item.getText());
+                }
+            }
+            return null;
+        } finally {
+            onExit(ctx);
+        }
+    }
+
+    @Override
+    public Expr visitStringLiteral(@NonNull BindingExpressionParser.StringLiteralContext ctx) {
         try {
             onEnter(ctx);
             final String javaString;
@@ -85,19 +160,7 @@
     }
 
     @Override
-    public Expr visitGrouping(@NotNull BindingExpressionParser.GroupingContext ctx) {
-        try {
-            onEnter(ctx);
-            Preconditions.check(ctx.children.size() == 3, "Grouping expression should have"
-                    + " 3 children. # of children: %d", ctx.children.size());
-            return mModel.group(ctx.children.get(1).accept(this));
-        } finally {
-            onExit(ctx);
-        }
-    }
-
-    @Override
-    public Expr visitBindingSyntax(@NotNull BindingExpressionParser.BindingSyntaxContext ctx) {
+    public Expr visitRootExpr(@NonNull BindingExpressionParser.RootExprContext ctx) {
         try {
             onEnter(ctx);
             // TODO handle defaults
@@ -112,7 +175,19 @@
     }
 
     @Override
-    public Expr visitDotOp(@NotNull BindingExpressionParser.DotOpContext ctx) {
+    public Expr visitGrouping(@NonNull BindingExpressionParser.GroupingContext ctx) {
+        try {
+            onEnter(ctx);
+            Preconditions.check(ctx.children.size() == 3, "Grouping expression should have"
+                    + " 3 children. # of children: %d", ctx.children.size());
+            return ctx.children.get(1).accept(this);
+        } finally {
+            onExit(ctx);
+        }
+    }
+
+    @Override
+    public Expr visitDotOp(@NonNull BindingExpressionParser.DotOpContext ctx) {
         try {
             onEnter(ctx);
             ModelAnalyzer analyzer = ModelAnalyzer.getInstance();
@@ -132,7 +207,19 @@
     }
 
     @Override
-    public Expr visitQuestionQuestionOp(@NotNull BindingExpressionParser.QuestionQuestionOpContext ctx) {
+    public Expr visitFunctionRef(@NonNull BindingExpressionParser.FunctionRefContext ctx) {
+        try {
+            onEnter(ctx);
+            return mModel.methodReference(ctx.expression().accept(this),
+                    ctx.Identifier().getSymbol().getText());
+        } finally {
+            onExit(ctx);
+        }
+    }
+
+    @Override
+    public Expr visitQuestionQuestionOp(
+            @NonNull BindingExpressionParser.QuestionQuestionOpContext ctx) {
         try {
             onEnter(ctx);
             final Expr left = ctx.left.accept(this);
@@ -144,9 +231,9 @@
     }
 
     @Override
-    public Expr visitTerminal(@NotNull TerminalNode node) {
+    public Expr visitTerminal(@NonNull TerminalNode node) {
         try {
-            onEnter((ParserRuleContext) node.getParent().getRuleContext());
+            onEnter((ParserRuleContext) node.getParent());
             final int type = node.getSymbol().getType();
             Class classType;
             switch (type) {
@@ -169,18 +256,21 @@
                 case BindingExpressionParser.NullLiteral:
                     classType = Object.class;
                     break;
+                case BindingExpressionParser.VoidLiteral:
+                    classType = void.class;
+                    break;
                 default:
                     throw new RuntimeException("cannot create expression from terminal node " +
                             node.toString());
             }
             return mModel.symbol(node.getText(), classType);
         } finally {
-            onExit((ParserRuleContext) node.getParent().getRuleContext());
+            onExit((ParserRuleContext) node.getParent());
         }
     }
 
     @Override
-    public Expr visitComparisonOp(@NotNull BindingExpressionParser.ComparisonOpContext ctx) {
+    public Expr visitComparisonOp(@NonNull BindingExpressionParser.ComparisonOpContext ctx) {
         try {
             onEnter(ctx);
             return mModel.comparison(ctx.op.getText(), ctx.left.accept(this), ctx.right.accept(this));
@@ -190,7 +280,7 @@
     }
 
     @Override
-    public Expr visitIdentifier(@NotNull BindingExpressionParser.IdentifierContext ctx) {
+    public Expr visitIdentifier(@NonNull BindingExpressionParser.IdentifierContext ctx) {
         try {
             onEnter(ctx);
             return mModel.identifier(ctx.getText());
@@ -200,7 +290,7 @@
     }
 
     @Override
-    public Expr visitTernaryOp(@NotNull BindingExpressionParser.TernaryOpContext ctx) {
+    public Expr visitTernaryOp(@NonNull BindingExpressionParser.TernaryOpContext ctx) {
         try {
             onEnter(ctx);
             return mModel.ternary(ctx.left.accept(this), ctx.iftrue.accept(this),
@@ -213,7 +303,7 @@
 
     @Override
     public Expr visitMethodInvocation(
-            @NotNull BindingExpressionParser.MethodInvocationContext ctx) {
+            @NonNull BindingExpressionParser.MethodInvocationContext ctx) {
         try {
             onEnter(ctx);
             List<Expr> args = new ArrayList<Expr>();
@@ -233,7 +323,7 @@
     }
 
     @Override
-    public Expr visitMathOp(@NotNull BindingExpressionParser.MathOpContext ctx) {
+    public Expr visitMathOp(@NonNull BindingExpressionParser.MathOpContext ctx) {
         try {
             onEnter(ctx);
             return mModel.math(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
@@ -243,7 +333,7 @@
     }
 
     @Override
-    public Expr visitAndOrOp(@NotNull AndOrOpContext ctx) {
+    public Expr visitAndOrOp(@NonNull AndOrOpContext ctx) {
         try {
             onEnter(ctx);
             return mModel.logical(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
@@ -253,7 +343,7 @@
     }
 
     @Override
-    public Expr visitBinaryOp(@NotNull BinaryOpContext ctx) {
+    public Expr visitBinaryOp(@NonNull BinaryOpContext ctx) {
         try {
             onEnter(ctx);
             return mModel.math(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
@@ -263,7 +353,7 @@
     }
 
     @Override
-    public Expr visitBitShiftOp(@NotNull BitShiftOpContext ctx) {
+    public Expr visitBitShiftOp(@NonNull BitShiftOpContext ctx) {
         try {
             onEnter(ctx);
             return mModel.bitshift(ctx.left.accept(this), ctx.op.getText(), ctx.right.accept(this));
@@ -273,7 +363,7 @@
     }
 
     @Override
-    public Expr visitInstanceOfOp(@NotNull InstanceOfOpContext ctx) {
+    public Expr visitInstanceOfOp(@NonNull InstanceOfOpContext ctx) {
         try {
             onEnter(ctx);
             return mModel.instanceOfOp(ctx.expression().accept(this), ctx.type().getText());
@@ -283,7 +373,7 @@
     }
 
     @Override
-    public Expr visitUnaryOp(@NotNull UnaryOpContext ctx) {
+    public Expr visitUnaryOp(@NonNull UnaryOpContext ctx) {
         try {
             onEnter(ctx);
             return mModel.unary(ctx.op.getText(), ctx.expression().accept(this));
@@ -293,7 +383,7 @@
     }
 
     @Override
-    public Expr visitResources(@NotNull BindingExpressionParser.ResourcesContext ctx) {
+    public Expr visitResources(@NonNull BindingExpressionParser.ResourcesContext ctx) {
         try {
             onEnter(ctx);
             final List<Expr> args = new ArrayList<Expr>();
@@ -313,14 +403,14 @@
             final int startIndex = Math.max(1, colonIndex + 1);
             final String resourceType = resourceReference.substring(startIndex, slashIndex).trim();
             final String resourceName = resourceReference.substring(slashIndex + 1).trim();
-            return mModel.resourceExpr(packageName, resourceType, resourceName, args);
+            return mModel.resourceExpr(mTarget, packageName, resourceType, resourceName, args);
         } finally {
             onExit(ctx);
         }
     }
 
     @Override
-    public Expr visitBracketOp(@NotNull BindingExpressionParser.BracketOpContext ctx) {
+    public Expr visitBracketOp(@NonNull BindingExpressionParser.BracketOpContext ctx) {
         try {
             onEnter(ctx);
             return mModel.bracketExpr(visit(ctx.expression(0)), visit(ctx.expression(1)));
@@ -330,7 +420,7 @@
     }
 
     @Override
-    public Expr visitCastOp(@NotNull BindingExpressionParser.CastOpContext ctx) {
+    public Expr visitCastOp(@NonNull BindingExpressionParser.CastOpContext ctx) {
         try {
             onEnter(ctx);
             return mModel.castExpr(ctx.type().getText(), visit(ctx.expression()));
diff --git a/compiler/src/main/java/android/databinding/tool/InverseBinding.java b/compiler/src/main/java/android/databinding/tool/InverseBinding.java
index e04be28..13dd887 100644
--- a/compiler/src/main/java/android/databinding/tool/InverseBinding.java
+++ b/compiler/src/main/java/android/databinding/tool/InverseBinding.java
@@ -16,25 +16,23 @@
 
 package android.databinding.tool;
 
+import android.databinding.tool.expr.CallbackArgExpr;
+import android.databinding.tool.expr.CallbackExprModel;
 import android.databinding.tool.expr.Expr;
 import android.databinding.tool.expr.ExprModel;
 import android.databinding.tool.expr.FieldAccessExpr;
+import android.databinding.tool.expr.IdentifierExpr;
 import android.databinding.tool.processing.ErrorMessages;
 import android.databinding.tool.processing.Scope;
 import android.databinding.tool.processing.scopes.LocationScopeProvider;
 import android.databinding.tool.reflection.ModelAnalyzer;
 import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.solver.ExecutionPath;
 import android.databinding.tool.store.Location;
 import android.databinding.tool.store.SetterStore;
 import android.databinding.tool.store.SetterStore.BindingGetterCall;
 import android.databinding.tool.store.SetterStore.BindingSetterCall;
 import android.databinding.tool.util.L;
-import android.databinding.tool.util.Preconditions;
-import android.databinding.tool.writer.FlagSet;
-import android.databinding.tool.writer.KCode;
-import android.databinding.tool.writer.LayoutBinderWriterKt;
-
-import kotlin.jvm.functions.Function2;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -46,11 +44,38 @@
     private final BindingTarget mTarget;
     private BindingGetterCall mGetterCall;
     private final ArrayList<FieldAccessExpr> mChainedExpressions = new ArrayList<FieldAccessExpr>();
+    private final CallbackExprModel mCallbackExprModel;
+    private final Expr mInverseExpr;
+    private final CallbackArgExpr mVariableExpr;
+    private final ExecutionPath mExecutionPath;
 
-    public InverseBinding(BindingTarget target, String name, Expr expr) {
+    public InverseBinding(BindingTarget target, String name, Expr expr, String bindingClassName) {
         mTarget = target;
         mName = name;
-        mExpr = expr;
+        mCallbackExprModel = new CallbackExprModel(expr.getModel());
+        mExpr = expr.cloneToModel(mCallbackExprModel);
+        setGetterCall(mExpr);
+        mVariableExpr = mCallbackExprModel.callbackArg("callbackArg_0");
+        ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance();
+        ModelClass type = modelAnalyzer.findClass(getGetterCall().getGetterType(), null);
+        mVariableExpr.setClassFromCallback(type);
+        mVariableExpr.setUserDefinedType(getGetterCall().getGetterType());
+        mInverseExpr =
+                mExpr.generateInverse(mCallbackExprModel, mVariableExpr, bindingClassName);
+        mExecutionPath = ExecutionPath.createRoot();
+        mInverseExpr.toExecutionPath(mExecutionPath);
+        mCallbackExprModel.seal();
+    }
+
+    public InverseBinding(BindingTarget target, String name, BindingGetterCall getterCall) {
+        mTarget = target;
+        mName = name;
+        mExpr = null;
+        mCallbackExprModel = null;
+        mInverseExpr = null;
+        mVariableExpr = null;
+        mExecutionPath = null;
+        setGetterCall(getterCall);
     }
 
     @Override
@@ -62,7 +87,7 @@
         }
     }
 
-    void setGetterCall(BindingGetterCall getterCall) {
+    private void setGetterCall(BindingGetterCall getterCall) {
         mGetterCall = getterCall;
     }
 
@@ -74,74 +99,56 @@
         return mTarget.getResolvedType().isViewDataBinding();
     }
 
-    private SetterStore.BindingGetterCall getGetterCall() {
-        if (mGetterCall == null) {
-            if (mExpr != null) {
-                mExpr.getResolvedType(); // force resolve of ObservableFields
+    private void setGetterCall(Expr expr) {
+        try {
+            Scope.enter(mTarget);
+            Scope.enter(this);
+            ModelClass viewType = mTarget.getResolvedType();
+            final SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance());
+            final ModelClass resolvedType = expr == null ? null : expr.getResolvedType();
+            mGetterCall = setterStore.getGetterCall(mName, viewType, resolvedType,
+                    expr.getModel().getImports());
+            if (mGetterCall == null) {
+                L.e(ErrorMessages.CANNOT_FIND_GETTER_CALL, mName,
+                        expr == null ? "Unknown" : mExpr.getResolvedType(),
+                        mTarget.getResolvedType());
             }
-            try {
-                Scope.enter(mTarget);
-                Scope.enter(this);
-                resolveGetterCall();
-                if (mGetterCall == null) {
-                    L.e(ErrorMessages.CANNOT_FIND_GETTER_CALL, mName,
-                            mExpr == null ? "Unknown" : mExpr.getResolvedType(),
-                            mTarget.getResolvedType());
-                }
-            } finally {
-                Scope.exit();
-                Scope.exit();
-            }
+        } finally {
+            Scope.exit();
+            Scope.exit();
         }
-        return mGetterCall;
     }
 
-    private void resolveGetterCall() {
-        ModelClass viewType = mTarget.getResolvedType();
-        final SetterStore setterStore = SetterStore.get(ModelAnalyzer.getInstance());
-        final ModelClass resolvedType = mExpr == null ? null : mExpr.getResolvedType();
-        mGetterCall = setterStore.getGetterCall(mName, viewType, resolvedType,
-                getModel().getImports());
+    public SetterStore.BindingGetterCall getGetterCall() {
+        return mGetterCall;
     }
 
     public BindingTarget getTarget() {
         return mTarget;
     }
 
-    public KCode toJavaCode(String bindingComponent, final FlagSet flagField) {
-        final String targetViewName = LayoutBinderWriterKt.getFieldName(getTarget());
-        KCode code = new KCode();
-        // A chained expression will have substituted its chained value for the expression
-        // unless the attribute has no expression. Therefore, chaining and expressions are
-        // mutually exclusive.
-        Preconditions.check((mExpr == null) != mChainedExpressions.isEmpty(),
-                "Chained expressions are only against unbound attributes.");
-        if (mExpr != null) {
-            code.app("", mExpr.toInverseCode(new KCode(getGetterCall().toJava(bindingComponent,
-                    targetViewName))));
-        } else { // !mChainedExpressions.isEmpty())
-            final String fieldName = flagField.getLocalName();
-            FlagSet flagSet = new FlagSet();
-            for (FieldAccessExpr expr : mChainedExpressions) {
-                flagSet = flagSet.or(new FlagSet(expr.getId()));
-            }
-            final FlagSet allFlags = flagSet;
-            code.nl(new KCode("synchronized(this) {"));
-            code.tab(LayoutBinderWriterKt
-                    .mapOr(flagField, flagSet, new Function2<String, Integer, KCode>() {
-                        @Override
-                        public KCode invoke(String suffix, Integer index) {
-                            return new KCode(fieldName)
-                                    .app(suffix)
-                                    .app(" |= ")
-                                    .app(LayoutBinderWriterKt.binaryCode(allFlags, index))
-                                    .app(";");
-                        }
-                    }));
-            code.nl(new KCode("}"));
-            code.nl(new KCode("requestRebind()"));
-        }
-        return code;
+    public Expr getExpr() {
+        return mExpr;
+    }
+
+    public Expr getInverseExpr() {
+        return mInverseExpr;
+    }
+
+    public IdentifierExpr getVariableExpr() {
+        return mVariableExpr;
+    }
+
+    public ExecutionPath getExecutionPath() {
+        return mExecutionPath;
+    }
+
+    public CallbackExprModel getCallbackExprModel() {
+        return mCallbackExprModel;
+    }
+
+    public List<FieldAccessExpr> getChainedExpressions() {
+        return mChainedExpressions;
     }
 
     public String getBindingAdapterInstanceClass() {
diff --git a/compiler/src/main/java/android/databinding/tool/LayoutBinder.java b/compiler/src/main/java/android/databinding/tool/LayoutBinder.java
index 7ed944a..bcbafda 100644
--- a/compiler/src/main/java/android/databinding/tool/LayoutBinder.java
+++ b/compiler/src/main/java/android/databinding/tool/LayoutBinder.java
@@ -30,7 +30,7 @@
 import android.databinding.tool.writer.LayoutBinderWriter;
 import android.databinding.tool.writer.LayoutBinderWriterKt;
 
-import org.antlr.v4.runtime.misc.Nullable;
+import com.android.annotations.Nullable;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -216,17 +216,25 @@
             for (BindingTarget bindingTarget : mBindingTargets) {
                 try {
                     Scope.enter(bindingTarget.mBundle);
+                    final String className = getPackage() + "." + getClassName();
                     for (BindingTargetBundle.BindingBundle bindingBundle : bindingTarget.mBundle
                             .getBindingBundleList()) {
                         try {
                             Scope.enter(bindingBundle.getValueLocation());
-                            bindingTarget.addBinding(bindingBundle.getName(),
-                                    parse(bindingBundle.getExpr(), bindingBundle.isTwoWay(),
-                                            bindingBundle.getValueLocation()));
+                            Expr expr = parse(bindingBundle.getExpr(),
+                                    bindingBundle.getValueLocation(),
+                                    bindingTarget);
+                            bindingTarget.addBinding(bindingBundle.getName(), expr);
+                            if (bindingBundle.isTwoWay()) {
+                                bindingTarget.addInverseBinding(bindingBundle.getName(), expr,
+                                        className);
+                            }
                         } finally {
                             Scope.exit();
                         }
                     }
+                    // resolve callbacks first because they introduce local variables.
+                    bindingTarget.resolveCallbackParams();
                     bindingTarget.resolveTwoWayExpressions();
                     bindingTarget.resolveMultiSetters();
                     bindingTarget.resolveListeners();
@@ -245,7 +253,7 @@
         List<Expr> used = new ArrayList<Expr>();
         for (BindingTarget target : mBindingTargets) {
             for (Binding binding : target.getBindings()) {
-                binding.getExpr().setIsUsed(true);
+                binding.getExpr().markAsUsed();
                 used.add(binding.getExpr());
             }
         }
@@ -254,7 +262,7 @@
             for (Dependency dep : e.getDependencies()) {
                 if (!dep.getOther().isUsed()) {
                     used.add(dep.getOther());
-                    dep.getOther().setIsUsed(true);
+                    dep.getOther().markAsUsed();
                 }
             }
         }
@@ -288,10 +296,9 @@
         return target;
     }
 
-    public Expr parse(String input, boolean isTwoWay, @Nullable Location locationInFile) {
-        final Expr parsed = mExpressionParser.parse(input, locationInFile);
+    public Expr parse(String input, @Nullable Location locationInFile, BindingTarget target) {
+        final Expr parsed = mExpressionParser.parse(input, locationInFile, target);
         parsed.setBindingExpression(true);
-        parsed.setTwoWay(isTwoWay);
         return parsed;
     }
 
diff --git a/compiler/src/main/java/android/databinding/tool/expr/ArgListExpr.java b/compiler/src/main/java/android/databinding/tool/expr/ArgListExpr.java
index c8f6e2c..cdb0d14 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/ArgListExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/ArgListExpr.java
@@ -42,12 +42,17 @@
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
+    protected KCode generateCode() {
         throw new IllegalStateException("should never try to convert an argument expressions"
                 + " into code");
     }
 
     @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.argListExpr(cloneToModel(model, getChildren()));
+    }
+
+    @Override
     protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
         return modelAnalyzer.findClass(Void.class);
     }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/BitShiftExpr.java b/compiler/src/main/java/android/databinding/tool/expr/BitShiftExpr.java
index cbc895b..f4da3ec 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/BitShiftExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/BitShiftExpr.java
@@ -57,15 +57,25 @@
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
+    protected KCode generateCode() {
         return new KCode()
-                .app("", getLeft().toCode(expand))
+                .app("", getLeft().toCode())
                 .app(getOp())
-                .app("", getRight().toCode(expand));
+                .app("", getRight().toCode());
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.bitshift(getLeft().cloneToModel(model), mOp, getRight().cloneToModel(model));
     }
 
     @Override
     public String getInvertibleError() {
         return "Bit shift operators cannot be inverted in two-way binding";
     }
+
+    @Override
+    public String toString() {
+        return getLeft().toString() + ' ' + mOp + ' ' + getRight().toString();
+    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/BracketExpr.java b/compiler/src/main/java/android/databinding/tool/expr/BracketExpr.java
index 392512c..a9a6155 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/BracketExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/BracketExpr.java
@@ -18,8 +18,12 @@
 
 import android.databinding.tool.reflection.ModelAnalyzer;
 import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.solver.ExecutionPath;
 import android.databinding.tool.writer.KCode;
 
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
 import java.util.List;
 
 public class BracketExpr extends Expr {
@@ -54,6 +58,28 @@
     }
 
     @Override
+    public List<ExecutionPath> toExecutionPath(List<ExecutionPath> paths) {
+        final List<ExecutionPath> targetPaths = getTarget().toExecutionPath(paths);
+        // after this, we need a null check.
+        List<ExecutionPath> result = new ArrayList<ExecutionPath>();
+        if (getTarget() instanceof StaticIdentifierExpr) {
+            result.addAll(toExecutionPathInOrder(paths, getTarget()));
+        } else {
+            for (ExecutionPath path : targetPaths) {
+                Expr cmp = getModel().comparison("!=", getTarget(),
+                        getModel().symbol("null", Object.class));
+                path.addPath(cmp);
+                final ExecutionPath subPath = path.addBranch(cmp, true);
+                if (subPath != null) {
+                    final List<ExecutionPath> argPath = getArg().toExecutionPath(subPath);
+                    result.addAll(addJustMeToExecutionPath(argPath));
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
     protected List<Dependency> constructDependencies() {
         final List<Dependency> dependencies = constructDynamicChildrenDependencies();
         for (Dependency dependency : dependencies) {
@@ -66,7 +92,7 @@
 
     protected String computeUniqueKey() {
         final String targetKey = getTarget().computeUniqueKey();
-        return addTwoWay(join(targetKey, "$", getArg().computeUniqueKey(), "$"));
+        return join(targetKey, "$", getArg().computeUniqueKey(), "$");
     }
 
     @Override
@@ -91,7 +117,7 @@
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
+    protected KCode generateCode() {
         String cast = argCastsInteger() ? "(Integer) " : "";
         switch (getAccessor()) {
             case ARRAY: {
@@ -128,12 +154,33 @@
     }
 
     @Override
-    public KCode toInverseCode(KCode value) {
-        String cast = argCastsInteger() ? "(Integer) " : "";
-        return new KCode().
-                app("setTo(", getTarget().toCode(true)).
-                app(", ").
-                app(cast, getArg().toCode(true)).
-                app(", ", value).app(");");
+    public Expr generateInverse(ExprModel model, Expr value, String bindingClassName) {
+        Expr arg = getArg().cloneToModel(model);
+        arg = argCastsInteger()
+                ? model.castExpr("int", model.castExpr("Integer", arg))
+                : arg;
+        StaticIdentifierExpr viewDataBinding =
+                model.staticIdentifier(ModelAnalyzer.VIEW_DATA_BINDING);
+        viewDataBinding.setUserDefinedType(ModelAnalyzer.VIEW_DATA_BINDING);
+        ModelClass targetType = getTarget().getResolvedType();
+        if ((targetType.isList() || targetType.isMap()) &&
+                value.getResolvedType().isPrimitive()) {
+            ModelClass boxed = value.getResolvedType().box();
+            value = model.castExpr(boxed.toJavaCode(), value);
+        }
+        List<Expr> args = Lists.newArrayList(getTarget().cloneToModel(model), arg, value);
+        MethodCallExpr setter = model.methodCall(viewDataBinding, "setTo", args);
+        setter.setAllowProtected();
+        return setter;
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.bracketExpr(getTarget().cloneToModel(model), getArg().cloneToModel(model));
+    }
+
+    @Override
+    public String toString() {
+        return getTarget().toString() + '[' + getArg() + ']';
     }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/BuiltInVariableExpr.java b/compiler/src/main/java/android/databinding/tool/expr/BuiltInVariableExpr.java
index d2fdea1..ff1d1ad 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/BuiltInVariableExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/BuiltInVariableExpr.java
@@ -49,7 +49,7 @@
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
+    protected KCode generateCode() {
         if (mAccessCode == null) {
             return new KCode().app(mName);
         } else {
@@ -65,4 +65,9 @@
     public String getInvertibleError() {
         return "Built-in variables may not be the target of two-way binding";
     }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.builtInVariable(mName, mUserDefinedType, mAccessCode);
+    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/CallbackArgExpr.java b/compiler/src/main/java/android/databinding/tool/expr/CallbackArgExpr.java
new file mode 100644
index 0000000..34841c9
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/expr/CallbackArgExpr.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.databinding.tool.expr;
+
+import android.databinding.tool.CallbackWrapper;
+import android.databinding.tool.processing.ErrorMessages;
+import android.databinding.tool.reflection.ModelAnalyzer;
+import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.util.Preconditions;
+import android.databinding.tool.writer.KCode;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * This expressions that are used to reference arguments in callbacks.
+ * <p
+ * While the callback is being parsed, they get whatever the variable user defined in the lambda.
+ * When the code is being generated, they get simple enumarated names so that multiple callbacks
+ * can be handled in the same method.
+ */
+public class CallbackArgExpr extends IdentifierExpr {
+
+    private int mArgIndex;
+
+    private String mName;
+
+    private ModelClass mClassFromCallback;
+
+    public CallbackArgExpr(int argIndex, String name) {
+        super(name);
+        mArgIndex = argIndex;
+        mName = name;
+    }
+
+    @Override
+    public boolean isDynamic() {
+        return false;
+    }
+
+    public void setClassFromCallback(ModelClass modelClass) {
+        mClassFromCallback = modelClass;
+    }
+
+    @Override
+    protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
+        Preconditions
+                .checkNotNull(mClassFromCallback, ErrorMessages.UNDEFINED_CALLBACK_ARGUMENT, mName);
+        return mClassFromCallback;
+    }
+
+    @Override
+    protected List<Dependency> constructDependencies() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    protected KCode generateCode() {
+        return new KCode(CallbackWrapper.ARG_PREFIX + mArgIndex);
+    }
+
+    @Override
+    protected String computeUniqueKey() {
+        return CallbackWrapper.ARG_PREFIX + mArgIndex;
+    }
+
+    @Override
+    public String getInvertibleError() {
+        return "Callback arguments cannot be inverted";
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return new CallbackArgExpr(mArgIndex, mName);
+    }
+}
diff --git a/compiler/src/main/java/android/databinding/tool/expr/CallbackExprModel.java b/compiler/src/main/java/android/databinding/tool/expr/CallbackExprModel.java
new file mode 100644
index 0000000..501125c
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/expr/CallbackExprModel.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.tool.expr;
+
+import android.databinding.tool.processing.ErrorMessages;
+import android.databinding.tool.processing.Scope;
+import android.databinding.tool.store.Location;
+import android.databinding.tool.util.L;
+import android.databinding.tool.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Callbacks are evaluated when event happens, not when execute pending is run. To separate their
+ * expressions, we provide a separate model for them that extends the main model. This allows them
+ * to introduce their own variables etc. without mixing them with other expressions.
+ */
+public class CallbackExprModel extends ExprModel {
+    // used for imports and other stuff.
+    final ExprModel mOriginal;
+    final List<CallbackArgExpr> mArguments = new ArrayList<CallbackArgExpr>();
+    public CallbackExprModel(ExprModel original) {
+        mOriginal = original;
+    }
+
+    @Override
+    public Map<String, String> getImports() {
+        return mOriginal.getImports();
+    }
+
+    @Override
+    public StaticIdentifierExpr addImport(String alias, String type, Location location) {
+        return mOriginal.addImport(alias, type, location);
+    }
+
+    @Override
+    public <T extends Expr> T register(T expr) {
+        // locations are only synced to main model so we need to sync overselves here.
+        setCurrentLocationInFile(mOriginal.getCurrentLocationInFile());
+        setCurrentParserContext(mOriginal.getCurrentParserContext());
+        return super.register(expr);
+    }
+
+    @Override
+    public void seal() {
+        // ensure all types are calculated
+        for (Expr expr : mExprMap.values()) {
+            expr.getResolvedType();
+            expr.markAsUsedInCallback();
+        }
+        markSealed();
+        // we do not resolve dependencies for these expression because they are resolved via
+        // ExecutionPath and should not interfere with the main expr model's dependency graph.
+    }
+
+    @Override
+    public IdentifierExpr identifier(String name) {
+        CallbackArgExpr arg = findArgByName(name);
+        if (arg != null) {
+            return arg;
+        }
+        IdentifierExpr id = new IdentifierExpr(name);
+        final Expr existing = mExprMap.get(id.getUniqueKey());
+        if (existing == null) {
+             // this is not a method variable reference. register it in the main model
+            final IdentifierExpr identifier = mOriginal.identifier(name);
+            mExprMap.put(identifier.getUniqueKey(), identifier);
+            identifier.markAsUsedInCallback();
+            return identifier;
+        }
+        return (IdentifierExpr) existing;
+    }
+
+    private CallbackArgExpr findArgByName(String name) {
+        for (CallbackArgExpr arg : mArguments) {
+            if (name.equals(arg.getName())) {
+                return arg;
+            }
+        }
+        return null;
+    }
+
+    public CallbackArgExpr callbackArg(String name) {
+        Preconditions.checkNull(findArgByName(name),
+                ErrorMessages.DUPLICATE_CALLBACK_ARGUMENT, name);
+        final CallbackArgExpr id = new CallbackArgExpr(mArguments.size(), name);
+        final CallbackArgExpr added = register(id);
+        mArguments.add(added);
+
+        try {
+            Scope.enter(added);
+            IdentifierExpr identifierWithSameName = mOriginal.findIdentifier(name);
+            if (identifierWithSameName != null) {
+                L.w(ErrorMessages.CALLBACK_VARIABLE_NAME_CLASH, name, name,
+                        identifierWithSameName.getUserDefinedType());
+            }
+        } finally {
+            Scope.exit();
+        }
+        return added;
+    }
+
+    public int getArgCount() {
+        return mArguments.size();
+    }
+
+    public List<CallbackArgExpr> getArguments() {
+        return mArguments;
+    }
+}
diff --git a/compiler/src/main/java/android/databinding/tool/expr/CastExpr.java b/compiler/src/main/java/android/databinding/tool/expr/CastExpr.java
index 9a4a36a..9a66cd9 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/CastExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/CastExpr.java
@@ -46,7 +46,7 @@
     }
 
     protected String computeUniqueKey() {
-        return addTwoWay(join(mType, getCastExpr().computeUniqueKey()));
+        return join(mType, getCastExpr().computeUniqueKey());
     }
 
     public Expr getCastExpr() {
@@ -58,11 +58,12 @@
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
+    protected KCode generateCode() {
         return new KCode()
                 .app("(")
                 .app(getCastType())
-                .app(") ", getCastExpr().toCode(expand));
+                .app(") (", getCastExpr().toCode())
+                .app(")");
     }
 
     @Override
@@ -71,8 +72,20 @@
     }
 
     @Override
-    public KCode toInverseCode(KCode value) {
-        // assume no need to cast in reverse
-        return getCastExpr().toInverseCode(value);
+    public Expr generateInverse(ExprModel model, Expr value, String bindingClassName) {
+        Expr castExpr = getCastExpr();
+        ModelClass exprType = castExpr.getResolvedType();
+        Expr castValue = model.castExpr(exprType.toJavaCode(), value);
+        return castExpr.generateInverse(model, castValue, bindingClassName);
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.castExpr(mType, getCastExpr().cloneToModel(model));
+    }
+
+    @Override
+    public String toString() {
+        return "(" + mType + ") " + getCastExpr();
     }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/ComparisonExpr.java b/compiler/src/main/java/android/databinding/tool/expr/ComparisonExpr.java
index 172ea21..6b36bca 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/ComparisonExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/ComparisonExpr.java
@@ -62,14 +62,27 @@
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
-        return new KCode().app("", getLeft().toCode(expand))
-        .app(" ").app(getOp()).app(" ")
-        .app("", getRight().toCode(expand));
+    protected KCode generateCode() {
+        return new KCode()
+                .app("(", getLeft().toCode())
+                .app(") ")
+                .app(getOp())
+                .app(" (", getRight().toCode())
+                .app(")");
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.comparison(mOp, getLeft().cloneToModel(model), getRight().cloneToModel(model));
     }
 
     @Override
     public String getInvertibleError() {
         return "Comparison operators are not valid as targets of two-way binding";
     }
+
+    @Override
+    public String toString() {
+        return getLeft().toString() + ' ' + mOp + ' ' + getRight();
+    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/Expr.java b/compiler/src/main/java/android/databinding/tool/expr/Expr.java
index 193501c..42d98a1 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/Expr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/Expr.java
@@ -16,19 +16,21 @@
 
 package android.databinding.tool.expr;
 
-import org.antlr.v4.runtime.misc.Nullable;
-
 import android.databinding.tool.processing.ErrorMessages;
 import android.databinding.tool.processing.Scope;
 import android.databinding.tool.processing.scopes.LocationScopeProvider;
 import android.databinding.tool.reflection.ModelAnalyzer;
 import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.solver.ExecutionPath;
 import android.databinding.tool.store.Location;
 import android.databinding.tool.util.L;
 import android.databinding.tool.util.Preconditions;
 import android.databinding.tool.writer.KCode;
 import android.databinding.tool.writer.LayoutBinderWriterKt;
 
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
 import java.util.ArrayList;
 import java.util.BitSet;
 import java.util.Collections;
@@ -36,7 +38,6 @@
 import java.util.Map;
 
 abstract public class Expr implements VersionProvider, LocationScopeProvider {
-
     public static final int NO_ID = -1;
     protected List<Expr> mChildren = new ArrayList<Expr>();
 
@@ -98,7 +99,7 @@
      */
     private boolean mRead;
     private boolean mIsUsed = false;
-    private boolean mIsTwoWay = false;
+    private boolean mIsUsedInCallback = false;
 
     Expr(Iterable<Expr> children) {
         for (Expr expr : children) {
@@ -163,7 +164,7 @@
     }
 
     public boolean canBeEvaluatedToAVariable() {
-        return true; // anything except arg expr can be evaluated to a variable
+        return true; // anything except arg/return expr can be evaluated to a variable
     }
 
     public boolean isObservable() {
@@ -210,22 +211,6 @@
         mModel = model;
     }
 
-    public void setTwoWay(boolean isTwoWay) {
-        mIsTwoWay = isTwoWay;
-    }
-
-    public boolean isTwoWay() {
-        return mIsTwoWay;
-    }
-
-    protected String addTwoWay(String uniqueKey) {
-        if (mIsTwoWay) {
-            return "twoWay(" + uniqueKey + ")";
-        } else {
-            return "oneWay(" + uniqueKey + ")";
-        }
-    }
-
     private BitSet resolveShouldReadWithConditionals() {
         // ensure we have invalid flags
         BitSet bitSet = new BitSet();
@@ -341,6 +326,58 @@
         return mResolvedType;
     }
 
+    public final List<ExecutionPath> toExecutionPath(ExecutionPath path) {
+        List<ExecutionPath> paths = new ArrayList<ExecutionPath>();
+        paths.add(path);
+        return toExecutionPath(paths);
+    }
+
+    public List<ExecutionPath> toExecutionPath(List<ExecutionPath> paths) {
+        if (getChildren().isEmpty()) {
+            return addJustMeToExecutionPath(paths);
+        } else {
+            return toExecutionPathInOrder(paths, getChildren());
+        }
+
+    }
+
+    @NotNull
+    protected final List<ExecutionPath> addJustMeToExecutionPath(List<ExecutionPath> paths) {
+        List<ExecutionPath> result = new ArrayList<ExecutionPath>();
+        for (ExecutionPath path : paths) {
+            result.add(path.addPath(this));
+        }
+        return result;
+    }
+
+    @SuppressWarnings("Duplicates")
+    protected final List<ExecutionPath> toExecutionPathInOrder(List<ExecutionPath> paths,
+            Expr... order) {
+        List<ExecutionPath> executionPaths = paths;
+        for (Expr anOrder : order) {
+            executionPaths = anOrder.toExecutionPath(executionPaths);
+        }
+        List<ExecutionPath> result = new ArrayList<ExecutionPath>(paths.size());
+        for (ExecutionPath path : executionPaths) {
+            result.add(path.addPath(this));
+        }
+        return result;
+    }
+
+    @SuppressWarnings("Duplicates")
+    protected final List<ExecutionPath> toExecutionPathInOrder(List<ExecutionPath> paths,
+            List<Expr> order) {
+        List<ExecutionPath> executionPaths = paths;
+        for (Expr expr : order) {
+            executionPaths = expr.toExecutionPath(executionPaths);
+        }
+        List<ExecutionPath> result = new ArrayList<ExecutionPath>(paths.size());
+        for (ExecutionPath path : executionPaths) {
+            result.add(path.addPath(this));
+        }
+        return result;
+    }
+
     abstract protected ModelClass resolveType(ModelAnalyzer modelAnalyzer);
 
     abstract protected List<Dependency> constructDependencies();
@@ -516,7 +553,8 @@
                     allCovered = false;
                     break;
                 }
-                final BitSet readForConditional = (BitSet) expr.findConditionalFlags().clone();
+                final BitSet readForConditional = (BitSet) expr
+                        .getShouldReadFlagsWithConditionals().clone();
 
                 // FIXME: this does not do full traversal so misses some cases
                 // to calculate that conditional, i should've read /readForConditional/ flags
@@ -630,13 +668,24 @@
         return false;
     }
 
-    public void setIsUsed(boolean isUsed) {
-        mIsUsed = isUsed;
+    public void markAsUsed() {
+        mIsUsed = true;
         for (Expr child : getChildren()) {
-            child.setIsUsed(isUsed);
+            child.markAsUsed();
         }
     }
 
+    public void markAsUsedInCallback() {
+        mIsUsedInCallback = true;
+        for (Expr child : getChildren()) {
+            child.markAsUsedInCallback();
+        }
+    }
+
+    public boolean isIsUsedInCallback() {
+        return mIsUsedInCallback;
+    }
+
     public boolean isUsed() {
         return mIsUsed;
     }
@@ -686,26 +735,32 @@
     }
 
     public KCode toCode() {
-        return toCode(false);
-    }
-
-    protected KCode toCode(boolean expand) {
-        if (!expand && isDynamic()) {
-            return new KCode(LayoutBinderWriterKt.getExecutePendingLocalName(this));
+        if (isDynamic()) {
+            return new KCode(LayoutBinderWriterKt.scopedName(this));
         }
-        return generateCode(expand);
+        return generateCode();
     }
 
     public KCode toFullCode() {
-        return generateCode(false);
+        return generateCode();
     }
 
-    protected abstract KCode generateCode(boolean expand);
+    protected abstract KCode generateCode();
 
-    public KCode toInverseCode(KCode value) {
+    public Expr generateInverse(ExprModel model, Expr value, String bindingClassName) {
         throw new IllegalStateException("expression does not support two-way binding");
     }
 
+    public abstract Expr cloneToModel(ExprModel model);
+
+    protected static List<Expr> cloneToModel(ExprModel model, List<Expr> exprs) {
+        ArrayList<Expr> clones = new ArrayList<Expr>();
+        for (Expr expr : exprs) {
+            clones.add(expr.cloneToModel(model));
+        }
+        return clones;
+    }
+
     public void assertIsInvertible() {
         final String errorMessage = getInvertibleError();
         if (errorMessage != null) {
diff --git a/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java b/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java
index 058427e..34b2569 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/ExprModel.java
@@ -17,6 +17,7 @@
 package android.databinding.tool.expr;
 
 import android.databinding.tool.BindingTarget;
+import android.databinding.tool.CallbackWrapper;
 import android.databinding.tool.InverseBinding;
 import android.databinding.tool.reflection.ModelAnalyzer;
 import android.databinding.tool.reflection.ModelClass;
@@ -24,9 +25,11 @@
 import android.databinding.tool.store.Location;
 import android.databinding.tool.util.L;
 import android.databinding.tool.util.Preconditions;
+import android.databinding.tool.writer.ExprModelExt;
 import android.databinding.tool.writer.FlagSet;
 
 import org.antlr.v4.runtime.ParserRuleContext;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -34,6 +37,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
 
 public class ExprModel {
 
@@ -67,9 +71,6 @@
      */
     private String[] mFlagMapping;
 
-    private BitSet mInvalidateableFlags;
-    private BitSet mConditionalFlags;
-
     private int mFlagBucketCount;// how many buckets we use to identify flags
 
     private List<Expr> mObservables;
@@ -80,6 +81,13 @@
 
     private ParserRuleContext mCurrentParserContext;
     private Location mCurrentLocationInFile;
+
+    private Map<String, CallbackWrapper> mCallbackWrappers = new HashMap<String, CallbackWrapper>();
+
+    private AtomicInteger mCallbackIdCounter = new AtomicInteger();
+
+    private ExprModelExt mExt = new ExprModelExt();
+
     /**
      * Adds the expression to the list of expressions and returns it.
      * If it already exists, returns existing one.
@@ -94,6 +102,7 @@
             location = new Location(mCurrentParserContext);
             location.setParentLocation(mCurrentLocationInFile);
         }
+        //noinspection unchecked
         T existing = (T) mExprMap.get(expr.getUniqueKey());
         if (existing != null) {
             Preconditions.check(expr.getParents().isEmpty(),
@@ -116,10 +125,30 @@
         return expr;
     }
 
+    protected void markSealed() {
+        mSealed = true;
+    }
+
+    public ExprModelExt getExt() {
+        return mExt;
+    }
+
+    public int obtainCallbackId() {
+        return mCallbackIdCounter.incrementAndGet();
+    }
+
     public void setCurrentParserContext(ParserRuleContext currentParserContext) {
         mCurrentParserContext = currentParserContext;
     }
 
+    public ParserRuleContext getCurrentParserContext() {
+        return mCurrentParserContext;
+    }
+
+    public Location getCurrentLocationInFile() {
+        return mCurrentLocationInFile;
+    }
+
     public Map<String, Expr> getExprMap() {
         return mExprMap;
     }
@@ -141,7 +170,11 @@
     }
 
     public FieldAccessExpr observableField(Expr parent, String name) {
-        return register(new FieldAccessExpr(parent, name, true));
+        return register(new ObservableFieldExpr(parent, name));
+    }
+
+    public MethodReferenceExpr methodReference(Expr parent, String name) {
+        return register(new MethodReferenceExpr(parent, name));
     }
 
     public SymbolExpr symbol(String text, Class type) {
@@ -174,13 +207,9 @@
     public StaticIdentifierExpr staticIdentifierFor(final ModelClass modelClass) {
         final String type = modelClass.getCanonicalName();
         // check for existing
-        for (Expr expr : mExprMap.values()) {
-            if (expr instanceof StaticIdentifierExpr) {
-                StaticIdentifierExpr id = (StaticIdentifierExpr) expr;
-                if (id.getUserDefinedType().equals(type)) {
-                    return id;
-                }
-            }
+        StaticIdentifierExpr id = findStaticIdentifierExpr(type);
+        if (id != null) {
+            return id;
         }
 
         // does not exist. Find a name for it.
@@ -203,6 +232,19 @@
         }
     }
 
+    @Nullable
+    private StaticIdentifierExpr findStaticIdentifierExpr(String type) {
+        for (Expr expr : mExprMap.values()) {
+            if (expr instanceof StaticIdentifierExpr) {
+                StaticIdentifierExpr id = (StaticIdentifierExpr) expr;
+                if (id.getUserDefinedType().equals(type)) {
+                    return id;
+                }
+            }
+        }
+        return null;
+    }
+
     public MethodCallExpr methodCall(Expr target, String name, List<Expr> args) {
         return register(new MethodCallExpr(target, name, args));
     }
@@ -231,13 +273,9 @@
         return register(new UnaryExpr(op, expr));
     }
 
-    public Expr group(Expr grouped) {
-        return register(new GroupExpr(grouped));
-    }
-
-    public Expr resourceExpr(String packageName, String resourceType, String resourceName,
-            List<Expr> args) {
-        return register(new ResourceExpr(packageName, resourceType, resourceName, args));
+    public Expr resourceExpr(BindingTarget target, String packageName, String resourceType,
+            String resourceName, List<Expr> args) {
+        return register(new ResourceExpr(target, packageName, resourceType, resourceName, args));
     }
 
     public Expr bracketExpr(Expr variableExpr, Expr argExpr) {
@@ -256,8 +294,19 @@
     }
 
     public StaticIdentifierExpr addImport(String alias, String type, Location location) {
-        Preconditions.check(!mImports.containsKey(alias),
-                "%s has already been defined as %s", alias, type);
+        String existing = mImports.get(alias);
+        if (existing != null) {
+            if (existing.equals(type)) {
+                final StaticIdentifierExpr id = findStaticIdentifierExpr(type);
+                Preconditions.checkNotNull(id, "Missing import expression although it is"
+                        + " registered");
+                return id;
+            } else {
+                L.e("%s has already been defined as %s but trying to re-define as %s", alias,
+                        existing, type);
+            }
+        }
+
         final StaticIdentifierExpr id = staticIdentifier(alias);
         L.d("adding import %s as %s klass: %s", type, alias, id.getClass().getSimpleName());
         id.setUserDefinedType(type);
@@ -289,7 +338,7 @@
     public void removeExpr(Expr expr) {
         Preconditions.check(!mSealed, "Can't modify the expression list after sealing the model.");
         mBindingExpressions.remove(expr);
-        mExprMap.remove(expr.computeUniqueKey());
+        mExprMap.remove(expr.getUniqueKey());
     }
 
     public List<Expr> getObservables() {
@@ -338,7 +387,9 @@
                 if (parent instanceof FieldAccessExpr) {
                     FieldAccessExpr fae = (FieldAccessExpr) parent;
                     L.d("checking field access expr %s. getter: %s", fae,fae.getGetter());
-                    if (fae.isDynamic() && fae.getGetter().canBeInvalidated()) {
+                    // FAE#getter might be null if it is used only in a callback.
+                    if (fae.getGetter() != null && fae.isDynamic()
+                            && fae.getGetter().canBeInvalidated()) {
                         flagMapping.add(parent.getUniqueKey());
                         parent.setId(counter++);
                         notifiableExpressions.add(parent);
@@ -355,7 +406,7 @@
         for (Expr expr : mExprMap.values()) {
             if (expr instanceof FieldAccessExpr) {
                 FieldAccessExpr fieldAccessExpr = (FieldAccessExpr) expr;
-                if (fieldAccessExpr.getChild() instanceof ViewFieldExpr) {
+                if (fieldAccessExpr.getTarget() instanceof ViewFieldExpr) {
                     flagMapping.add(fieldAccessExpr.getUniqueKey());
                     fieldAccessExpr.setId(counter++);
                 }
@@ -381,9 +432,9 @@
         mInvalidateAnyFlagIndex = counter ++;
         flagMapping.add("INVALIDATE ANY");
         mInvalidateableFieldLimit = counter;
-        mInvalidateableFlags = new BitSet();
+        BitSet invalidateableFlags = new BitSet();
         for (int i = 0; i < mInvalidateableFieldLimit; i++) {
-            mInvalidateableFlags.set(i, true);
+            invalidateableFlags.set(i, true);
         }
 
         // make sure all dependencies are resolved to avoid future race conditions
@@ -396,9 +447,9 @@
                 counter += 2;
             }
         }
-        mConditionalFlags = new BitSet();
+        BitSet conditionalFlags = new BitSet();
         for (int i = mInvalidateableFieldLimit; i < counter; i++) {
-            mConditionalFlags.set(i, true);
+            conditionalFlags.set(i, true);
         }
         mRequirementIdCount = (counter - mInvalidateableFieldLimit) / 2;
 
@@ -538,15 +589,17 @@
                 }
             }
         }
-        for (Expr partialRead : markedSomeFlagsAsRead) {
-            // even if all paths are not satisfied, we can elevate certain conditional dependencies
-            // if all of their paths are satisfied.
-            for (Dependency dependency : partialRead.getDependants()) {
-                Expr dependant = dependency.getDependant();
-                if (dependant.isConditional() && dependant.getAllCalculationPaths()
-                        .areAllPathsSatisfied(partialRead.mReadSoFar)) {
-                    if (dependant.considerElevatingConditionals(partialRead)) {
-                        elevated = true;
+        if (!elevated) {
+            for (Expr partialRead : markedSomeFlagsAsRead) {
+                // even if all paths are not satisfied, we can elevate certain conditional
+                // dependencies if all of their paths are satisfied.
+                for (Dependency dependency : partialRead.getDependants()) {
+                    Expr dependant = dependency.getDependant();
+                    if (dependant.isConditional() && dependant.getAllCalculationPaths()
+                            .areAllPathsSatisfied(partialRead.mReadSoFar)) {
+                        if (dependant.considerElevatingConditionals(partialRead)) {
+                            elevated = true;
+                        }
                     }
                 }
             }
@@ -572,8 +625,8 @@
         return false;
     }
 
-    public static List<Expr> filterShouldRead(Iterable<Expr> exprs) {
-        List<Expr> result = new ArrayList<Expr>();
+    public static ArrayList<Expr> filterShouldRead(Iterable<Expr> exprs) {
+        ArrayList<Expr> result = new ArrayList<Expr>();
         for (Expr expr : exprs) {
             if (!expr.getShouldReadFlags().isEmpty() &&
                     !hasConditionalOrNestedCannotReadDependency(expr)) {
@@ -634,4 +687,35 @@
             ModelMethod listenerMethod) {
         return register(new ListenerExpr(expression, name, listenerType, listenerMethod));
     }
+
+    public FieldAssignmentExpr assignment(Expr target, String name, Expr value) {
+        return register(new FieldAssignmentExpr(target, name, value));
+    }
+
+    public Map<String, CallbackWrapper> getCallbackWrappers() {
+        return mCallbackWrappers;
+    }
+
+    public CallbackWrapper callbackWrapper(ModelClass klass, ModelMethod method) {
+        final String key = CallbackWrapper.uniqueKey(klass, method);
+        CallbackWrapper wrapper = mCallbackWrappers.get(key);
+        if (wrapper == null) {
+            wrapper = new CallbackWrapper(klass, method);
+            mCallbackWrappers.put(key, wrapper);
+        }
+        return wrapper;
+    }
+
+    public LambdaExpr lambdaExpr(Expr expr, CallbackExprModel callbackExprModel) {
+        return register(new LambdaExpr(expr, callbackExprModel));
+    }
+
+    public IdentifierExpr findIdentifier(String name) {
+        for (Expr expr : mExprMap.values()) {
+            if (expr instanceof IdentifierExpr && name.equals(((IdentifierExpr) expr).getName())) {
+                return (IdentifierExpr) expr;
+            }
+        }
+        return null;
+    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/FieldAccessExpr.java b/compiler/src/main/java/android/databinding/tool/expr/FieldAccessExpr.java
index ff55a00..d897f0a 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/FieldAccessExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/FieldAccessExpr.java
@@ -16,48 +16,37 @@
 
 package android.databinding.tool.expr;
 
-import android.databinding.tool.ext.ExtKt;
 import android.databinding.tool.Binding;
 import android.databinding.tool.BindingTarget;
 import android.databinding.tool.InverseBinding;
+import android.databinding.tool.ext.ExtKt;
+import android.databinding.tool.processing.ErrorMessages;
 import android.databinding.tool.processing.Scope;
 import android.databinding.tool.reflection.Callable;
 import android.databinding.tool.reflection.Callable.Type;
 import android.databinding.tool.reflection.ModelAnalyzer;
 import android.databinding.tool.reflection.ModelClass;
-import android.databinding.tool.reflection.ModelMethod;
-import android.databinding.tool.util.BrNameUtil;
 import android.databinding.tool.store.SetterStore;
 import android.databinding.tool.store.SetterStore.BindingGetterCall;
+import android.databinding.tool.util.BrNameUtil;
 import android.databinding.tool.util.L;
 import android.databinding.tool.util.Preconditions;
 import android.databinding.tool.writer.KCode;
 
+import com.google.common.collect.Lists;
+
 import java.util.List;
 
-public class FieldAccessExpr extends Expr {
-    String mName;
+public class FieldAccessExpr extends MethodBaseExpr {
     // notification name for the field. Important when we map this to a method w/ different name
     String mBrName;
     Callable mGetter;
-    final boolean mIsObservableField;
     boolean mIsListener;
     boolean mIsViewAttributeAccess;
 
     FieldAccessExpr(Expr parent, String name) {
-        super(parent);
+        super(parent, name);
         mName = name;
-        mIsObservableField = false;
-    }
-
-    FieldAccessExpr(Expr parent, String name, boolean isObservableField) {
-        super(parent);
-        mName = name;
-        mIsObservableField = isObservableField;
-    }
-
-    public Expr getChild() {
-        return getChildren().get(0);
     }
 
     public Callable getGetter() {
@@ -69,7 +58,10 @@
 
     @Override
     public String getInvertibleError() {
-        if (getGetter().setterName == null) {
+        if (getGetter() == null) {
+            return "Listeners do not support two-way binding";
+        }
+        if (mGetter.setterName == null) {
             return "Two-way binding cannot resolve a setter for " + getResolvedType().toJavaCode() +
                     " property '" + mName + "'";
         }
@@ -81,7 +73,7 @@
     }
 
     public int getMinApi() {
-        return mGetter.getMinApi();
+        return mGetter == null ? 0 : mGetter.getMinApi();
     }
 
     @Override
@@ -93,7 +85,7 @@
             return true;
         }
         // if it is static final, gone
-        if (getChild().isDynamic()) {
+        if (getTarget().isDynamic()) {
             // if owner is dynamic, then we can be dynamic unless we are static final
             return !mGetter.isStatic() || mGetter.isDynamic();
         }
@@ -107,111 +99,33 @@
     }
 
     public boolean hasBindableAnnotations() {
-        return mGetter.canBeInvalidated();
+        return mGetter != null && mGetter.canBeInvalidated();
     }
 
     @Override
     public Expr resolveListeners(ModelClass listener, Expr parent) {
-        if (mName == null || mName.isEmpty()) {
-            return this; // ObservableFields aren't listeners
+        final ModelClass targetType = getTarget().getResolvedType();
+        if (getGetter() == null && (listener == null || !mIsListener)) {
+            L.e("Could not resolve %s.%s as an accessor or listener on the attribute.",
+                    targetType.getCanonicalName(), mName);
+            return this;
         }
-        final ModelClass childType = getChild().getResolvedType();
-        if (getGetter() == null) {
-            if (listener == null || !mIsListener) {
-                L.e("Could not resolve %s.%s as an accessor or listener on the attribute.",
-                        childType.getCanonicalName(), mName);
-                return this;
-            }
-            getChild().getParents().remove(this);
-        } else if (listener == null) {
-            return this; // Not a listener, but we have a getter.
-        }
-        List<ModelMethod> abstractMethods = listener.getAbstractMethods();
-        int numberOfAbstractMethods = abstractMethods == null ? 0 : abstractMethods.size();
-        if (numberOfAbstractMethods != 1) {
-            if (mGetter == null) {
-                L.e("Could not find accessor %s.%s and %s has %d abstract methods, so is" +
-                                " not resolved as a listener",
-                        childType.getCanonicalName(), mName,
-                        listener.getCanonicalName(), numberOfAbstractMethods);
+        try {
+            Expr listenerExpr = resolveListenersAsMethodReference(listener, parent);
+            L.w("Method references using '.' is deprecated. Instead of '%s', use '%s::%s'",
+                    toString(), getTarget(), getName());
+            return listenerExpr;
+        } catch (IllegalStateException e) {
+            if (getGetter() == null) {
+                L.e("%s", e.getMessage());
             }
             return this;
         }
-
-        // Look for a signature matching the abstract method
-        final ModelMethod listenerMethod = abstractMethods.get(0);
-        final ModelClass[] listenerParameters = listenerMethod.getParameterTypes();
-        boolean isStatic = getChild() instanceof StaticIdentifierExpr;
-        List<ModelMethod> methods = childType.findMethods(mName, isStatic);
-        if (methods == null) {
-            return this;
-        }
-        for (ModelMethod method : methods) {
-            if (acceptsParameters(method, listenerParameters) &&
-                    method.getReturnType(null).equals(listenerMethod.getReturnType(null))) {
-                resetResolvedType();
-                // replace this with ListenerExpr in parent
-                Expr listenerExpr = getModel().listenerExpr(getChild(), mName, listener,
-                        listenerMethod);
-                if (parent != null) {
-                    int index;
-                    while ((index = parent.getChildren().indexOf(this)) != -1) {
-                        parent.getChildren().set(index, listenerExpr);
-                    }
-                }
-                if (getModel().mBindingExpressions.contains(this)) {
-                    getModel().bindingExpr(listenerExpr);
-                }
-                getParents().remove(parent);
-                if (getParents().isEmpty()) {
-                    getModel().removeExpr(this);
-                }
-                return listenerExpr;
-            }
-        }
-
-        if (mGetter == null) {
-            L.e("Listener class %s with method %s did not match signature of any method %s.%s",
-                    listener.getCanonicalName(), listenerMethod.getName(),
-                    childType.getCanonicalName(), mName);
-        }
-        return this;
-    }
-
-    private boolean acceptsParameters(ModelMethod method, ModelClass[] listenerParameters) {
-        ModelClass[] parameters = method.getParameterTypes();
-        if (parameters.length != listenerParameters.length) {
-            return false;
-        }
-        for (int i = 0; i < parameters.length; i++) {
-            if (!parameters[i].isAssignableFrom(listenerParameters[i])) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    @Override
-    protected List<Dependency> constructDependencies() {
-        final List<Dependency> dependencies = constructDynamicChildrenDependencies();
-        for (Dependency dependency : dependencies) {
-            if (dependency.getOther() == getChild()) {
-                dependency.setMandatory(true);
-            }
-        }
-        return dependencies;
     }
 
     @Override
     protected String computeUniqueKey() {
-        if (mIsObservableField) {
-            return addTwoWay(join(mName, "..", super.computeUniqueKey()));
-        }
-        return addTwoWay(join(mName, ".", super.computeUniqueKey()));
-    }
-
-    public String getName() {
-        return mName;
+        return join(mName, ".", getTarget().getUniqueKey());
     }
 
     public String getBrName() {
@@ -228,32 +142,21 @@
     }
 
     @Override
-    public void updateExpr(ModelAnalyzer modelAnalyzer) {
-        try {
-            Scope.enter(this);
-            resolveType(modelAnalyzer);
-            super.updateExpr(modelAnalyzer);
-        } finally {
-            Scope.exit();
-        }
-    }
-
-    @Override
     protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
         if (mIsListener) {
             return modelAnalyzer.findClass(Object.class);
         }
         if (mGetter == null) {
-            Expr child = getChild();
-            child.getResolvedType();
-            boolean isStatic = child instanceof StaticIdentifierExpr;
-            ModelClass resolvedType = child.getResolvedType();
+            Expr target = getTarget();
+            target.getResolvedType();
+            boolean isStatic = target instanceof StaticIdentifierExpr;
+            ModelClass resolvedType = target.getResolvedType();
             L.d("resolving %s. Resolved class type: %s", this, resolvedType);
 
             mGetter = resolvedType.findGetterOrField(mName, isStatic);
 
             if (mGetter == null) {
-                mIsListener = resolvedType.findMethods(mName, isStatic) != null;
+                mIsListener = !resolvedType.findMethods(mName, isStatic).isEmpty();
                 if (!mIsListener) {
                     L.e("Could not find accessor %s.%s", resolvedType.getCanonicalName(), mName);
                 }
@@ -262,22 +165,16 @@
 
             if (mGetter.isStatic() && !isStatic) {
                 // found a static method on an instance. register a new one
-                child.getParents().remove(this);
-                getChildren().remove(child);
-                StaticIdentifierExpr staticId = getModel().staticIdentifierFor(resolvedType);
-                getChildren().add(staticId);
-                staticId.getParents().add(this);
-                child = getChild(); // replace the child for the next if stmt
+                replaceStaticIdentifier(resolvedType);
+                target = getTarget();
             }
 
             if (mGetter.resolvedType.isObservableField()) {
                 // Make this the ".get()" and add an extra field access for the observable field
-                child.getParents().remove(this);
-                getChildren().remove(child);
+                target.getParents().remove(this);
+                getChildren().remove(target);
 
-                FieldAccessExpr observableField = getModel().observableField(child, mName);
-                observableField.mGetter = mGetter;
-
+                FieldAccessExpr observableField = getModel().observableField(target, mName);
                 getChildren().add(observableField);
                 observableField.getParents().add(this);
                 mGetter = mGetter.resolvedType.findGetterOrField("", false);
@@ -290,9 +187,17 @@
         return mGetter.resolvedType;
     }
 
+    protected void replaceStaticIdentifier(ModelClass staticIdentifierType) {
+        getTarget().getParents().remove(this);
+        getChildren().remove(getTarget());
+        StaticIdentifierExpr staticId = getModel().staticIdentifierFor(staticIdentifierType);
+        getChildren().add(staticId);
+        staticId.getParents().add(this);
+    }
+
     @Override
     public Expr resolveTwoWayExpressions(Expr parent) {
-        final Expr child = getChild();
+        final Expr child = getTarget();
         if (!(child instanceof ViewFieldExpr)) {
             return this;
         }
@@ -365,22 +270,17 @@
 
     @Override
     protected String asPackage() {
-        String parentPackage = getChild().asPackage();
+        String parentPackage = getTarget().asPackage();
         return parentPackage == null ? null : parentPackage + "." + mName;
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
-        KCode code = new KCode();
-        if (expand) {
-            String defaultValue = ModelAnalyzer.getInstance().getDefaultValue(
-                    getResolvedType().toJavaCode());
-            code.app("(", getChild().toCode(true))
-                    .app(" == null) ? ")
-                    .app(defaultValue)
-                    .app(" : ");
-        }
-        code.app("", getChild().toCode(expand)).app(".");
+    protected KCode generateCode() {
+        // once we can deprecate using Field.access for callbacks, we can get rid of this since
+        // it will be detected when resolve type is run.
+        Preconditions.checkNotNull(getGetter(), ErrorMessages.CANNOT_RESOLVE_TYPE, this);
+        KCode code = new KCode()
+                .app("", getTarget().toCode()).app(".");
         if (getGetter().type == Callable.Type.FIELD) {
             return code.app(getGetter().name);
         } else {
@@ -389,25 +289,27 @@
     }
 
     @Override
-    public KCode toInverseCode(KCode value) {
-        if (mGetter.setterName == null) {
-            throw new IllegalStateException("There is no inverse for " + toCode().generate());
-        }
-        KCode castValue = new KCode("(").app(getResolvedType().toJavaCode() + ")(", value).app(")");
-        String type = getChild().getResolvedType().toJavaCode();
-        KCode code = new KCode("targetObj_.");
+    public Expr generateInverse(ExprModel model, Expr value, String bindingClassName) {
+        Expr castExpr = model.castExpr(getResolvedType().toJavaCode(), value);
+        Expr target = getTarget().cloneToModel(model);
+        Expr result;
         if (getGetter().type == Callable.Type.FIELD) {
-            code.app(getGetter().setterName).app(" = ", castValue).app(";");
+            result = model.assignment(target, mName, castExpr);
         } else {
-            code.app(getGetter().setterName).app("(", castValue).app(")").app(";");
+            result = model.methodCall(target, mGetter.setterName, Lists.newArrayList(castExpr));
         }
-        return new KCode()
-                .app("final ")
-                .app(type)
-                .app(" targetObj_ = ", getChild().toCode(true))
-                .app(";")
-                .nl(new KCode("if (targetObj_ != null) {"))
-                .tab(code)
-                .nl(new KCode("}"));
+        return result;
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        final Expr clonedTarget = getTarget().cloneToModel(model);
+        return model.field(clonedTarget, mName);
+    }
+
+    @Override
+    public String toString() {
+        String name = mName.isEmpty() ? "get()" : mName;
+        return getTarget().toString() + '.' + name;
     }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/FieldAssignmentExpr.java b/compiler/src/main/java/android/databinding/tool/expr/FieldAssignmentExpr.java
new file mode 100644
index 0000000..a99df62
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/expr/FieldAssignmentExpr.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.tool.expr;
+
+import android.databinding.tool.reflection.ModelAnalyzer;
+import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.solver.ExecutionPath;
+import android.databinding.tool.writer.KCode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This is used by inverse field access expressions to assign back to the field.
+ * For example, <code>&commat;={a.b}</code> is inverted to @{code a.b = value;}
+ */
+public class FieldAssignmentExpr extends Expr {
+    final String mName;
+
+    public FieldAssignmentExpr(Expr target, String name, Expr value) {
+        super(target, value);
+        mName = name;
+    }
+
+    @Override
+    protected String computeUniqueKey() {
+        return join(getTarget().getUniqueKey(), mName, "=", getValueExpr().getUniqueKey());
+    }
+
+    public Expr getTarget() {
+        return (FieldAccessExpr) getChildren().get(0);
+    }
+
+    public Expr getValueExpr() {
+        return getChildren().get(1);
+    }
+
+    @Override
+    protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
+        return modelAnalyzer.findClass(void.class);
+    }
+
+    @Override
+    protected List<Dependency> constructDependencies() {
+        return constructDynamicChildrenDependencies();
+    }
+
+    @Override
+    protected KCode generateCode() {
+        return new KCode()
+                .app("", getTarget().toCode())
+                .app("." + mName + " = ", getValueExpr().toCode());
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.assignment(getTarget().cloneToModel(model), mName, getValueExpr());
+    }
+
+    @Override
+    protected String getInvertibleError() {
+        return "Assignment expressions are inverses of field access expressions.";
+    }
+
+    @Override
+    public List<ExecutionPath> toExecutionPath(List<ExecutionPath> paths) {
+        Expr child = getTarget();
+        List<ExecutionPath> targetPaths = child.toExecutionPath(paths);
+
+        // after this, we need a null check.
+        List<ExecutionPath> result = new ArrayList<ExecutionPath>();
+        if (child instanceof StaticIdentifierExpr) {
+            result.addAll(toExecutionPathInOrder(paths, child));
+        } else {
+            for (ExecutionPath path : targetPaths) {
+                final ComparisonExpr cmp = getModel()
+                        .comparison("!=", child, getModel().symbol("null", Object.class));
+                path.addPath(cmp);
+                final ExecutionPath subPath = path.addBranch(cmp, true);
+                if (subPath != null) {
+                    subPath.addPath(this);
+                    result.add(subPath);
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return getTarget().toString() + '.' + mName + " = " + getValueExpr();
+    }
+}
diff --git a/compiler/src/main/java/android/databinding/tool/expr/GroupExpr.java b/compiler/src/main/java/android/databinding/tool/expr/GroupExpr.java
deleted file mode 100644
index 4a76688..0000000
--- a/compiler/src/main/java/android/databinding/tool/expr/GroupExpr.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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 android.databinding.tool.expr;
-
-import android.databinding.tool.reflection.ModelAnalyzer;
-import android.databinding.tool.reflection.ModelClass;
-import android.databinding.tool.writer.KCode;
-
-import java.util.List;
-
-public class GroupExpr extends Expr {
-    public GroupExpr(Expr wrapped) {
-        super(wrapped);
-    }
-
-    @Override
-    protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
-        return getWrapped().getResolvedType();
-    }
-
-    @Override
-    protected List<Dependency> constructDependencies() {
-        return getWrapped().constructDependencies();
-    }
-
-    @Override
-    protected KCode generateCode(boolean expand) {
-        return new KCode().app("(", getWrapped().toCode(expand)).app(")");
-    }
-
-    public Expr getWrapped() {
-        return getChildren().get(0);
-    }
-
-    @Override
-    public KCode toInverseCode(KCode value) {
-        // Nothing to do here. Other expressions should automatically take care of grouping.
-        return getWrapped().toInverseCode(value);
-    }
-
-    @Override
-    public String getInvertibleError() {
-        return getWrapped().getInvertibleError();
-    }
-}
diff --git a/compiler/src/main/java/android/databinding/tool/expr/IdentifierExpr.java b/compiler/src/main/java/android/databinding/tool/expr/IdentifierExpr.java
index efe4fb1..b866218 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/IdentifierExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/IdentifierExpr.java
@@ -23,6 +23,8 @@
 import android.databinding.tool.writer.KCode;
 import android.databinding.tool.writer.LayoutBinderWriterKt;
 
+import com.google.common.collect.Lists;
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -78,12 +80,8 @@
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
-        if (expand) {
-            return new KCode(LayoutBinderWriterKt.getFieldName(this));
-        } else {
-            return new KCode(LayoutBinderWriterKt.getExecutePendingLocalName(this));
-        }
+    protected KCode generateCode() {
+        return new KCode(LayoutBinderWriterKt.scopedName(this));
     }
 
     public void setDeclared() {
@@ -100,7 +98,20 @@
     }
 
     @Override
-    public KCode toInverseCode(KCode value) {
-        return new KCode().app(LayoutBinderWriterKt.getSetterName(this)).app("(", value).app(");");
+    public Expr generateInverse(ExprModel model, Expr value, String bindingClassName) {
+        String thisType = bindingClassName + ".this";
+        Expr target = model.builtInVariable(thisType, bindingClassName, thisType);
+        return model.methodCall(target, LayoutBinderWriterKt.getSetterName(this),
+                Lists.newArrayList(value));
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.identifier(mName);
+    }
+
+    @Override
+    public String toString() {
+        return mName;
     }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/InstanceOfExpr.java b/compiler/src/main/java/android/databinding/tool/expr/InstanceOfExpr.java
index 980d635..8783d0e 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/InstanceOfExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/InstanceOfExpr.java
@@ -37,14 +37,19 @@
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
+    protected KCode generateCode() {
         return new KCode()
-                .app("", getExpr().toCode(expand))
+                .app("", getExpr().toCode())
                 .app(" instanceof ")
                 .app(getType().toJavaCode());
     }
 
     @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.instanceOfOp(getExpr().cloneToModel(model), mTypeStr);
+    }
+
+    @Override
     protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
         mType = modelAnalyzer.findClass(mTypeStr, getModel().getImports());
         return modelAnalyzer.loadPrimitive("boolean");
@@ -67,4 +72,9 @@
     public String getInvertibleError() {
         return "two-way binding can't target a value with the 'instanceof' operator";
     }
+
+    @Override
+    public String toString() {
+        return getExpr().toString() + " instanceof " + mTypeStr;
+    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/LambdaExpr.java b/compiler/src/main/java/android/databinding/tool/expr/LambdaExpr.java
new file mode 100644
index 0000000..13c6cb7
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/expr/LambdaExpr.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.tool.expr;
+
+import android.databinding.tool.CallbackWrapper;
+import android.databinding.tool.reflection.ModelAnalyzer;
+import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.reflection.ModelMethod;
+import android.databinding.tool.solver.ExecutionPath;
+import android.databinding.tool.util.Preconditions;
+import android.databinding.tool.writer.KCode;
+import android.databinding.tool.writer.LayoutBinderWriterKt;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class LambdaExpr extends Expr {
+    private static AtomicInteger sIdCounter = new AtomicInteger();
+    private final int mId = sIdCounter.incrementAndGet();
+    private CallbackWrapper mCallbackWrapper;
+    // set when Binding resolves the receiver
+    private final CallbackExprModel mCallbackExprModel;
+    private int mCallbackId;
+    private ExecutionPath mExecutionPath;
+
+    public LambdaExpr(Expr expr, CallbackExprModel callbackExprModel) {
+        super(expr);
+        mCallbackExprModel = callbackExprModel;
+    }
+
+    public Expr getExpr() {
+        return getChildren().get(0);
+    }
+
+    public CallbackExprModel getCallbackExprModel() {
+        return mCallbackExprModel;
+    }
+
+    @Override
+    protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
+        Preconditions.checkNotNull(mCallbackWrapper, "Lambda expression must be resolved to its"
+                + " setter first to get the type.");
+        return mCallbackWrapper.klass;
+    }
+
+    @Override
+    protected List<Dependency> constructDependencies() {
+        return Collections.emptyList();
+    }
+
+    public CallbackWrapper getCallbackWrapper() {
+        return mCallbackWrapper;
+    }
+
+    @Override
+    public Expr resolveListeners(ModelClass valueType, Expr parent) {
+        return this;
+    }
+
+    @Override
+    protected String computeUniqueKey() {
+        return "callback" + mId;
+    }
+
+    @Override
+    public boolean isDynamic() {
+        return false;
+    }
+
+    @Override
+    protected KCode generateCode() {
+        Preconditions
+                .checkNotNull(mCallbackWrapper, "Cannot find the callback method for %s", this);
+        KCode code = new KCode("");
+        final int minApi = mCallbackWrapper.getMinApi();
+        final String fieldName = LayoutBinderWriterKt.getFieldName(this);
+        if (minApi > 1) {
+            code.app("(getBuildSdkInt() < " + minApi + " ? null : ").app(fieldName).app(")");
+        } else {
+            code.app(fieldName);
+        }
+        return code;
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.lambdaExpr(getExpr().cloneToModel(model), (CallbackExprModel) model);
+    }
+
+    public String generateConstructor() {
+        return getCallbackWrapper().constructForIdentifier(mCallbackId);
+    }
+
+    @Override
+    public void markAsUsed() {
+        super.markAsUsed();
+    }
+
+    @Override
+    protected String getInvertibleError() {
+        return "Lambda expressions cannot be inverted";
+    }
+
+    @Override
+    public List<ExecutionPath> toExecutionPath(List<ExecutionPath> paths) {
+        // i'm not involved.
+        throw new UnsupportedOperationException("should not call toExecutionPath on a lambda"
+                + " expression");
+    }
+
+    public final ExecutionPath getExecutionPath() {
+        return mExecutionPath;
+    }
+
+    public int getCallbackId() {
+        return mCallbackId;
+    }
+
+    public void setup(ModelClass klass, ModelMethod method, int callbackId) {
+        mCallbackId = callbackId;
+        mCallbackWrapper = getModel().callbackWrapper(klass, method);
+        // now register the arguments as variables.
+        final ModelClass[] parameterTypes = method.getParameterTypes();
+        final List<CallbackArgExpr> args = mCallbackExprModel.getArguments();
+        if (parameterTypes.length == args.size()) {
+            for (int i = 0; i < parameterTypes.length; i++) {
+                args.get(i).setClassFromCallback(parameterTypes[i]);
+            }
+        }
+        // first convert to execution path because we may add additional expressions
+        mExecutionPath = ExecutionPath.createRoot();
+        getExpr().toExecutionPath(mExecutionPath);
+        mCallbackExprModel.seal();
+    }
+}
diff --git a/compiler/src/main/java/android/databinding/tool/expr/ListenerExpr.java b/compiler/src/main/java/android/databinding/tool/expr/ListenerExpr.java
index 6adf997..d8d07ff 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/ListenerExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/ListenerExpr.java
@@ -54,7 +54,7 @@
         return mMethod;
     }
 
-    public Expr getChild() {
+    public Expr getTarget() {
         return getChildren().get(0);
     }
 
@@ -64,24 +64,24 @@
 
     @Override
     public boolean isDynamic() {
-        return getChild().isDynamic();
+        return getTarget().isDynamic();
     }
 
     @Override
     protected List<Dependency> constructDependencies() {
         final List<Dependency> dependencies = new ArrayList<Dependency>();
-        Dependency dependency = new Dependency(this, getChild());
+        Dependency dependency = new Dependency(this, getTarget());
         dependency.setMandatory(true);
         dependencies.add(dependency);
         return dependencies;
     }
 
     protected String computeUniqueKey() {
-        return join(getResolvedType().getCanonicalName(), getChild().computeUniqueKey(), mName);
+        return join(getResolvedType().getCanonicalName(), getTarget().computeUniqueKey(), mName);
     }
 
     @Override
-    public KCode generateCode(boolean expand) {
+    public KCode generateCode() {
         KCode code = new KCode("(");
         final int minApi = Math.max(mListenerType.getMinApi(), mMethod.getMinApi());
         if (minApi > 1) {
@@ -89,7 +89,7 @@
         }
         final String fieldName = LayoutBinderWriterKt.getFieldName(this);
         final String listenerClassName = LayoutBinderWriterKt.getListenerClassName(this);
-        final KCode value = getChild().toCode();
+        final KCode value = getTarget().toCode();
             code.app("((")
                     .app(fieldName)
                     .app(" == null) ? (")
@@ -99,7 +99,7 @@
                     .app("()) : ")
                     .app(fieldName)
                     .app(")");
-        if (getChild().isDynamic()) {
+        if (getTarget().isDynamic()) {
             code.app(".setValue(", value)
                     .app(")");
         }
@@ -108,7 +108,17 @@
     }
 
     @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.listenerExpr(getTarget().cloneToModel(model), mName, mListenerType, mMethod);
+    }
+
+    @Override
     public String getInvertibleError() {
         return "Listeners cannot be the target of a two-way binding";
     }
+
+    @Override
+    public String toString() {
+        return getTarget().toString() + "::" + mName;
+    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/MathExpr.java b/compiler/src/main/java/android/databinding/tool/expr/MathExpr.java
index a302659..14b82c4 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/MathExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/MathExpr.java
@@ -18,12 +18,17 @@
 
 import android.databinding.tool.reflection.ModelAnalyzer;
 import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.util.Preconditions;
 import android.databinding.tool.writer.KCode;
 
+import com.google.common.collect.Lists;
+
 import java.util.List;
 
 public class MathExpr extends Expr {
+    static final String DYNAMIC_UTIL = "android.databinding.DynamicUtil";
     final String mOp;
+
     MathExpr(Expr left, String op, Expr right) {
         super(left, right);
         mOp = op;
@@ -31,7 +36,7 @@
 
     @Override
     protected String computeUniqueKey() {
-        return addTwoWay(join(getLeft().getUniqueKey(), mOp, getRight().getUniqueKey()));
+        return join(getLeft().getUniqueKey(), mOp, getRight().getUniqueKey());
     }
 
     @Override
@@ -52,10 +57,6 @@
         return constructDynamicChildrenDependencies();
     }
 
-    public String getOp() {
-        return mOp;
-    }
-
     public Expr getLeft() {
         return getChildren().get(0);
     }
@@ -65,81 +66,99 @@
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
-        return new KCode().app("", getLeft().toCode(expand)).app(mOp, getRight().toCode(expand));
+    protected KCode generateCode() {
+        return new KCode().app("(", getLeft().toCode())
+                .app(") ")
+                .app(mOp)
+                .app(" (", getRight().toCode())
+                .app(")");
     }
 
     @Override
     public String getInvertibleError() {
         if (mOp.equals("%")) {
             return "The modulus operator (%) is not supported in two-way binding.";
-        } else if (getResolvedType().isString()) {
-            return "String concatenation operator (+) is not supported in two-way binding.";
         }
-        if (!getLeft().isDynamic()) {
-            return getRight().getInvertibleError();
-        } else if (!getRight().isDynamic()) {
-            return getLeft().getInvertibleError();
-        } else {
-            return "Arithmetic operator " + mOp + " is not supported with two dynamic expressions.";
-        }
-    }
 
-    private String inverseCast() {
-        if (!getLeft().isDynamic()) {
-            return inverseCast(getRight());
-        } else {
-            return inverseCast(getLeft());
+        final Expr left = getLeft();
+        final Expr right = getRight();
+        if (left.isDynamic() == right.isDynamic()) {
+            return "Two way binding with operator " + mOp +
+                    " supports only a single dynamic expressions.";
         }
-    }
+        Expr dyn = left.isDynamic() ? left : right;
+        if (getResolvedType().isString()) {
+            Expr constExpr = left.isDynamic() ? right : left;
 
-    private String inverseCast(Expr expr) {
-        if (!expr.getResolvedType().isAssignableFrom(getResolvedType())) {
-            return "(" + getResolvedType() + ")";
+            if (!(constExpr instanceof SymbolExpr) ||
+                    !"\"\"".equals(((SymbolExpr) constExpr).getText())) {
+                return "Two-way binding with string concatenation operator (+) only supports the" +
+                        " empty string constant (`` or \"\")";
+            }
+            if (!dyn.getResolvedType().unbox().isPrimitive()) {
+                return "Two-way binding with string concatenation operator (+) only supports " +
+                        "primitives";
+            }
         }
-        return null;
+        return dyn.getInvertibleError();
     }
 
     @Override
-    public KCode toInverseCode(KCode value) {
-        if (!isDynamic()) {
-            return toCode();
-        }
+    public Expr generateInverse(ExprModel model, Expr value, String bindingClassName) {
         final Expr left = getLeft();
         final Expr right = getRight();
-        final Expr constExpr = left.isDynamic() ? right : left;
+        Preconditions.check(left.isDynamic() ^ right.isDynamic(), "Two-way binding of a math " +
+                "operations requires A single dynamic expression. Neither or both sides are " +
+                "dynamic: (%s) %s (%s)", left, mOp, right);
+        final Expr constExpr = (left.isDynamic() ? right : left).cloneToModel(model);
         final Expr varExpr = left.isDynamic() ? left : right;
-        final String cast = inverseCast();
-        if (cast != null) {
-            value = new KCode(cast).app("(", value).app(")");
-        }
+        final Expr newValue;
         switch (mOp.charAt(0)) {
             case '+': // const + x = value  => x = value - const
-                return varExpr.toInverseCode(value.app(" - (", constExpr.toCode()).app(")"));
-            case '*': // const * x = value => x = value / const
-                return varExpr.toInverseCode(value.app(" / (", constExpr.toCode()).app(")"));
-            case '-':
-                if (!left.isDynamic()) { // const - x = value => x = const - value)
-                    return varExpr.toInverseCode(new KCode()
-                            .app("(", constExpr.toCode())
-                            .app(") - (", value)
-                            .app(")"));
-                } else { // x - const = value => x = value + const)
-                    return varExpr.toInverseCode(value.app(" + ", constExpr.toCode()));
+                if (getResolvedType().isString()) {
+                    // just convert back to the primitive type
+                    newValue = parseInverse(model, value, varExpr);
+                } else {
+                    newValue = model.math(value, "-", constExpr);
                 }
+                break;
+            case '*': // const * x = value => x = value / const
+                newValue = model.math(value, "/", constExpr);
+                break;
+            case '-':
+                if (!left.isDynamic()) { // const - x = value => x = const - (value)
+                    newValue = model.math(constExpr, "-", value);
+                } else { // x - const = value => x = value + const)
+                    newValue = model.math(value, "+", constExpr);
+                }
+                break;
             case '/':
                 if (!left.isDynamic()) { // const / x = value => x = const / value
-                    return varExpr.toInverseCode(new KCode("(")
-                            .app("", constExpr.toCode())
-                            .app(") / (", value)
-                            .app(")"));
+                    newValue = model.math(constExpr, "/", value);
                 } else { // x / const = value => x = value * const
-                    return varExpr.toInverseCode(new KCode("(")
-                            .app("", value)
-                            .app(") * (", constExpr.toCode())
-                            .app(")"));
+                    newValue = model.math(value, "*", constExpr);
                 }
+                break;
+            default:
+                throw new IllegalStateException("Invalid math operation is not invertible: " + mOp);
         }
-        throw new IllegalStateException("Invalid math operation is not invertible: " + mOp);
+        return varExpr.generateInverse(model, newValue, bindingClassName);
+    }
+
+    private Expr parseInverse(ExprModel model, Expr value, Expr prev) {
+        IdentifierExpr dynamicUtil = model.staticIdentifier(DYNAMIC_UTIL);
+        dynamicUtil.setUserDefinedType(DYNAMIC_UTIL);
+
+        return model.methodCall(dynamicUtil, "parse", Lists.newArrayList(value, prev));
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.math(getLeft().cloneToModel(model), mOp, getRight().cloneToModel(model));
+    }
+
+    @Override
+    public String toString() {
+        return "(" + getLeft() + ") " + mOp + " (" + getRight() + ")";
     }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/MethodBaseExpr.java b/compiler/src/main/java/android/databinding/tool/expr/MethodBaseExpr.java
new file mode 100644
index 0000000..3b5bd87
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/expr/MethodBaseExpr.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.tool.expr;
+
+import android.databinding.tool.processing.Scope;
+import android.databinding.tool.reflection.ModelAnalyzer;
+import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.reflection.ModelMethod;
+import android.databinding.tool.solver.ExecutionPath;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class MethodBaseExpr extends Expr {
+    String mName;
+
+    MethodBaseExpr(Expr parent, String name) {
+        super(parent);
+        mName = name;
+    }
+
+    public Expr getTarget() {
+        return getChildren().get(0);
+    }
+
+    @Override
+    public List<ExecutionPath> toExecutionPath(List<ExecutionPath> paths) {
+        final List<ExecutionPath> targetPaths = getTarget().toExecutionPath(paths);
+        // after this, we need a null check.
+        List<ExecutionPath> result = new ArrayList<ExecutionPath>();
+        if (getTarget() instanceof StaticIdentifierExpr) {
+            result.addAll(toExecutionPathInOrder(paths, getTarget()));
+        } else {
+            for (ExecutionPath path : targetPaths) {
+                final ComparisonExpr cmp = getModel()
+                        .comparison("!=", getTarget(), getModel().symbol("null", Object.class));
+                path.addPath(cmp);
+                final ExecutionPath subPath = path.addBranch(cmp, true);
+                if (subPath != null) {
+                    subPath.addPath(this);
+                    result.add(subPath);
+                }
+            }
+        }
+        return result;
+    }
+
+    protected Expr resolveListenersAsMethodReference(ModelClass listener, Expr parent) {
+        final Expr target = getTarget();
+        final ModelClass childType = target.getResolvedType();
+        if (listener == null) {
+            throw new IllegalStateException(
+                    String.format("Could not resolve %s as a listener.", this));
+        }
+
+        List<ModelMethod> abstractMethods = listener.getAbstractMethods();
+        int numberOfAbstractMethods = abstractMethods == null ? 0 : abstractMethods.size();
+        if (numberOfAbstractMethods != 1) {
+            throw new IllegalStateException(String.format(
+                    "Could not find accessor %s.%s and %s has %d abstract methods, so is" +
+                            " not resolved as a listener",
+                    childType.getCanonicalName(), mName,
+                    listener.getCanonicalName(), numberOfAbstractMethods));
+        }
+
+        // Look for a signature matching the abstract method
+        final ModelMethod listenerMethod = abstractMethods.get(0);
+        final ModelClass[] listenerParameters = listenerMethod.getParameterTypes();
+        boolean isStatic = getTarget() instanceof StaticIdentifierExpr;
+        List<ModelMethod> methods = childType.findMethods(mName, isStatic);
+        for (ModelMethod method : methods) {
+            if (acceptsParameters(method, listenerParameters) &&
+                    method.getReturnType(null).equals(listenerMethod.getReturnType(null))) {
+                target.getParents().remove(this);
+                resetResolvedType();
+                // replace this with ListenerExpr in parent
+                Expr listenerExpr = getModel().listenerExpr(getTarget(), mName, listener,
+                        listenerMethod);
+                if (parent != null) {
+                    int index;
+                    while ((index = parent.getChildren().indexOf(this)) != -1) {
+                        parent.getChildren().set(index, listenerExpr);
+                    }
+                }
+                if (getModel().mBindingExpressions.contains(this)) {
+                    getModel().bindingExpr(listenerExpr);
+                }
+                getParents().remove(parent);
+                if (getParents().isEmpty()) {
+                    getModel().removeExpr(this);
+                }
+                return listenerExpr;
+            }
+        }
+
+        throw new IllegalStateException(String.format(
+                "Listener class %s with method %s did not match signature of any method %s",
+                listener.getCanonicalName(), listenerMethod.getName(), this));
+    }
+
+    private boolean acceptsParameters(ModelMethod method, ModelClass[] listenerParameters) {
+        ModelClass[] parameters = method.getParameterTypes();
+        if (parameters.length != listenerParameters.length) {
+            return false;
+        }
+        for (int i = 0; i < parameters.length; i++) {
+            if (!parameters[i].isAssignableFrom(listenerParameters[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    protected List<Dependency> constructDependencies() {
+        final List<Dependency> dependencies = constructDynamicChildrenDependencies();
+        for (Dependency dependency : dependencies) {
+            if (dependency.getOther() == getTarget()) {
+                dependency.setMandatory(true);
+            }
+        }
+        return dependencies;
+    }
+
+    public String getName() {
+        return mName;
+    }
+
+    @Override
+    public void updateExpr(ModelAnalyzer modelAnalyzer) {
+        try {
+            Scope.enter(this);
+            resolveType(modelAnalyzer);
+            super.updateExpr(modelAnalyzer);
+        } finally {
+            Scope.exit();
+        }
+    }
+}
diff --git a/compiler/src/main/java/android/databinding/tool/expr/MethodCallExpr.java b/compiler/src/main/java/android/databinding/tool/expr/MethodCallExpr.java
index 4990981..6acbfa2 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/MethodCallExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/MethodCallExpr.java
@@ -16,26 +16,29 @@
 
 package android.databinding.tool.expr;
 
-import static android.databinding.tool.reflection.Callable.DYNAMIC;
-import static android.databinding.tool.reflection.Callable.STATIC;
-
 import android.databinding.tool.processing.Scope;
 import android.databinding.tool.reflection.Callable;
 import android.databinding.tool.reflection.Callable.Type;
 import android.databinding.tool.reflection.ModelAnalyzer;
 import android.databinding.tool.reflection.ModelClass;
 import android.databinding.tool.reflection.ModelMethod;
+import android.databinding.tool.solver.ExecutionPath;
 import android.databinding.tool.util.L;
 import android.databinding.tool.writer.KCode;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
+import static android.databinding.tool.reflection.Callable.DYNAMIC;
+import static android.databinding.tool.reflection.Callable.STATIC;
+
 
 public class MethodCallExpr extends Expr {
     final String mName;
-
     Callable mGetter;
+    // Allow protected calls -- only used for ViewDataBinding methods.
+    private boolean mAllowProtected;
 
     static List<Expr> concat(Expr e, List<Expr> list) {
         List<Expr> merged = new ArrayList<Expr>();
@@ -49,6 +52,7 @@
         mName = name;
     }
 
+    @SuppressWarnings("Duplicates")
     @Override
     public void updateExpr(ModelAnalyzer modelAnalyzer) {
         try {
@@ -61,12 +65,24 @@
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
+    protected KCode generateCode() {
         KCode code = new KCode()
-        .app("", getTarget().toCode(expand))
-        .app(".")
-        .app(getGetter().name)
-        .app("(");
+                .app("", getTarget().toCode())
+                .app(".")
+                .app(getGetter().name)
+                .app("(");
+        appendArgs(code);
+        code.app(")");
+        return code;
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.methodCall(getTarget().cloneToModel(model), mName,
+                cloneToModel(model, getArgs()));
+    }
+
+    private void appendArgs(KCode code) {
         boolean first = true;
         for (Expr arg : getArgs()) {
             if (first) {
@@ -74,10 +90,33 @@
             } else {
                 code.app(", ");
             }
-            code.app("", arg.toCode(expand));
+            code.app("", arg.toCode());
         }
-        code.app(")");
-        return code;
+    }
+
+    @Override
+    public List<ExecutionPath> toExecutionPath(List<ExecutionPath> paths) {
+        final List<ExecutionPath> targetPaths = getTarget().toExecutionPath(paths);
+        // after this, we need a null check.
+        List<ExecutionPath> result = new ArrayList<ExecutionPath>();
+        if (getTarget() instanceof StaticIdentifierExpr) {
+            result.addAll(toExecutionPathInOrder(paths, getArgs()));
+        } else {
+            for (ExecutionPath path : targetPaths) {
+                Expr cmp = getModel()
+                        .comparison("!=", getTarget(), getModel().symbol("null", Object.class));
+                path.addPath(cmp);
+                final ExecutionPath subPath = path.addBranch(cmp, true);
+                if (subPath != null) {
+                    result.addAll(toExecutionPathInOrder(subPath, getArgs()));
+                }
+            }
+        }
+        return result;
+    }
+
+    private List<ExecutionPath> toExecutionPathInOrder(ExecutionPath path, List<Expr> args) {
+        return toExecutionPathInOrder(Arrays.asList(path), args);
     }
 
     @Override
@@ -90,12 +129,20 @@
 
             Expr target = getTarget();
             boolean isStatic = target instanceof StaticIdentifierExpr;
-            ModelMethod method = target.getResolvedType().getMethod(mName, args, isStatic);
+            ModelMethod method = target.getResolvedType().getMethod(mName, args, isStatic,
+                    mAllowProtected);
             if (method == null) {
-                String message = "cannot find method '" + mName + "' in class " +
+                StringBuilder argTypes = new StringBuilder();
+                for (ModelClass arg : args) {
+                    if (argTypes.length() != 0) {
+                        argTypes.append(", ");
+                    }
+                    argTypes.append(arg.toJavaCode());
+                }
+                String message = "cannot find method '" + mName + "(" + argTypes + ")' in class " +
                         target.getResolvedType().toJavaCode();
                 IllegalArgumentException e = new IllegalArgumentException(message);
-                L.e(e, "cannot find method %s in class %s", mName,
+                L.e(e, "cannot find method %s(%s) in class %s", mName, argTypes,
                         target.getResolvedType().toJavaCode());
                 throw e;
             }
@@ -115,7 +162,7 @@
                 flags |= STATIC;
             }
             mGetter = new Callable(Type.METHOD, method.getName(), null, method.getReturnType(args),
-                    method.getParameterTypes().length, flags);
+                    method.getParameterTypes().length, flags, method);
         }
         return mGetter.resolvedType;
     }
@@ -153,8 +200,31 @@
         return mGetter;
     }
 
+    public void setAllowProtected() {
+        mAllowProtected = true;
+    }
+
     @Override
     public String getInvertibleError() {
         return "Method calls may not be used in two-way expressions";
     }
+
+    @Override
+    public String toString() {
+        StringBuilder buf = new StringBuilder();
+        buf.append(getTarget())
+                .append('.')
+                .append(mName)
+                .append('(');
+        final List<Expr> args = getArgs();
+        for (int i = 0; i < args.size(); i++) {
+            Expr arg = args.get(i);
+            if (i != 0) {
+                buf.append(", ");
+            }
+            buf.append(arg);
+        }
+        buf.append(')');
+        return buf.toString();
+    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/MethodReferenceExpr.java b/compiler/src/main/java/android/databinding/tool/expr/MethodReferenceExpr.java
new file mode 100644
index 0000000..9b717e8
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/expr/MethodReferenceExpr.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.tool.expr;
+
+import android.databinding.tool.reflection.ModelAnalyzer;
+import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.util.L;
+import android.databinding.tool.util.Preconditions;
+import android.databinding.tool.writer.KCode;
+
+public class MethodReferenceExpr extends MethodBaseExpr {
+
+    MethodReferenceExpr(Expr parent, String name) {
+        super(parent, name);
+    }
+
+    @Override
+    protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
+        return modelAnalyzer.findClass(Object.class);
+    }
+
+    @Override
+    protected String computeUniqueKey() {
+        return join(mName, "::", getTarget().getUniqueKey());
+    }
+
+    @Override
+    public String getInvertibleError() {
+        return "Listeners do not support two-way binding";
+    }
+
+    @Override
+    public boolean isDynamic() {
+        return true;
+    }
+
+    @Override
+    public Expr resolveListeners(ModelClass listener, Expr parent) {
+        try {
+            return resolveListenersAsMethodReference(listener, parent);
+        } catch (IllegalStateException e) {
+            L.e("%s", e.getMessage());
+            return this;
+        }
+    }
+
+    @Override
+    protected KCode generateCode() {
+        // once we can deprecate using Field.access for callbacks, we can get rid of this since
+        // it will be detected when resolve type is run.
+        Preconditions.check(false, "Cannot generate code for unresolved method reference %s", this);
+        return null;
+    }
+
+    @Override
+    public Expr generateInverse(ExprModel model, Expr value, String bindingClassName) {
+        Preconditions.check(false, "Method references do not have an inverse");
+        return this;
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        final Expr clonedTarget = getTarget().cloneToModel(model);
+        return model.methodReference(clonedTarget, mName);
+    }
+
+    @Override
+    public String toString() {
+        return getTarget().toString() + "::" + mName;
+    }
+}
diff --git a/compiler/src/main/java/android/databinding/tool/expr/ObservableFieldExpr.java b/compiler/src/main/java/android/databinding/tool/expr/ObservableFieldExpr.java
new file mode 100644
index 0000000..22d8145
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/expr/ObservableFieldExpr.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.tool.expr;
+
+import android.databinding.tool.ext.ExtKt;
+import android.databinding.tool.reflection.ModelAnalyzer;
+import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.util.BrNameUtil;
+import android.databinding.tool.util.L;
+
+public class ObservableFieldExpr extends FieldAccessExpr {
+
+    ObservableFieldExpr(Expr parent, String name) {
+        super(parent, name);
+    }
+
+    @Override
+    public Expr resolveListeners(ModelClass listener, Expr parent) {
+        return this;  // ObservableFields aren't listeners
+    }
+
+    @Override
+    protected String computeUniqueKey() {
+        return join(mName, "..", getTarget().getUniqueKey());
+    }
+
+    @Override
+    protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
+        if (mGetter == null) {
+            Expr target = getTarget();
+            target.getResolvedType();
+            boolean isStatic = target instanceof StaticIdentifierExpr;
+            ModelClass resolvedType = target.getResolvedType();
+            L.d("resolving %s. Resolved class type: %s", this, resolvedType);
+
+            mGetter = resolvedType.findGetterOrField(mName, isStatic);
+
+            if (mGetter == null) {
+                L.e("Could not find accessor %s.%s", resolvedType.getCanonicalName(), mName);
+                return null;
+            }
+
+            if (mGetter.isStatic() && !isStatic) {
+                // found a static method on an instance. register a new one
+                replaceStaticIdentifier(resolvedType);
+            }
+            if (hasBindableAnnotations()) {
+                mBrName = ExtKt.br(BrNameUtil.brKey(getGetter()));
+            } else {
+                mBrName = ExtKt.br(mName);
+            }
+        }
+        return mGetter.resolvedType;
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        final Expr clonedTarget = getTarget().cloneToModel(model);
+        return model.observableField(clonedTarget, mName);
+    }
+
+    @Override
+    public String toString() {
+        return getTarget().toString() + '.' + mName;
+    }
+}
diff --git a/compiler/src/main/java/android/databinding/tool/expr/ResourceExpr.java b/compiler/src/main/java/android/databinding/tool/expr/ResourceExpr.java
index 752cb9f..df36cf6 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/ResourceExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/ResourceExpr.java
@@ -15,9 +15,11 @@
  */
 package android.databinding.tool.expr;
 
+import android.databinding.tool.BindingTarget;
 import android.databinding.tool.reflection.ModelAnalyzer;
 import android.databinding.tool.reflection.ModelClass;
 import android.databinding.tool.writer.KCode;
+import android.databinding.tool.writer.LayoutBinderWriterKt;
 
 import java.util.HashMap;
 import java.util.List;
@@ -45,9 +47,12 @@
 
     protected final String mResourceId;
 
-    public ResourceExpr(String packageName, String resourceType, String resourceName,
-            List<Expr> args) {
+    protected final BindingTarget mTarget;
+
+    public ResourceExpr(BindingTarget target, String packageName, String resourceType,
+            String resourceName, List<Expr> args) {
         super(args);
+        mTarget = target;
         if ("android".equals(packageName)) {
             mPackage = "android.";
         } else {
@@ -120,20 +125,26 @@
 
     @Override
     protected String computeUniqueKey() {
-        String base;
-        if (mPackage == null) {
-            base = "@" + mResourceType + "/" + mResourceId;
-        } else {
-            base = "@" + "android:" + mResourceType + "/" + mResourceId;
+        String base = toString();
+        String view = "";
+        if (requiresView()) {
+            view = LayoutBinderWriterKt.getFieldName(mTarget);
         }
-        return join(base, computeChildrenKey());
+        return join(base, view, computeChildrenKey());
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
+    protected KCode generateCode() {
         return new KCode(toJava());
     }
 
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        String pkg = mPackage.isEmpty() ? "" : "android";
+        return model.resourceExpr(mTarget, pkg, mResourceType, mResourceId,
+                cloneToModel(model, getChildren()));
+    }
+
     public String getResourceId() {
         return mPackage + "R." + getResourceObject() + "." + mResourceId;
     }
@@ -144,19 +155,31 @@
                 computeUniqueKey();
     }
 
+    private boolean requiresView() {
+        return !mTarget.isBinder() && !("anim".equals(mResourceType) ||
+                "animator".equals(mResourceType) ||
+                "id".equals(mResourceType) ||
+                "interpolator".equals(mResourceType) ||
+                "layout".equals(mResourceType) ||
+                "stateListAnimator".equals(mResourceType) ||
+                "transition".equals(mResourceType));
+    }
+
     public String toJava() {
         final String context = "getRoot().getContext()";
-        final String resources = "getRoot().getResources()";
+        final String viewName = requiresView() ? LayoutBinderWriterKt.getFieldName(mTarget) :
+                "getRoot()";
+        final String resources = viewName + ".getResources()";
         final String resourceName = mPackage + "R." + getResourceObject() + "." + mResourceId;
         if ("anim".equals(mResourceType)) return "android.view.animation.AnimationUtils.loadAnimation(" + context + ", " + resourceName + ")";
         if ("animator".equals(mResourceType)) return "android.animation.AnimatorInflater.loadAnimator(" + context + ", " + resourceName + ")";
         if ("bool".equals(mResourceType)) return resources + ".getBoolean(" + resourceName + ")";
-        if ("color".equals(mResourceType)) return "android.databinding.DynamicUtil.getColorFromResource(getRoot(), " + resourceName + ")";
-        if ("colorStateList".equals(mResourceType)) return "getColorStateListFromResource(" + resourceName + ")";
+        if ("color".equals(mResourceType)) return "android.databinding.DynamicUtil.getColorFromResource(" + viewName + ", " + resourceName + ")";
+        if ("colorStateList".equals(mResourceType)) return "android.databinding.DynamicUtil.getColorStateListFromResource(" + viewName + ", " + resourceName + ")";
         if ("dimen".equals(mResourceType)) return resources + ".getDimension(" + resourceName + ")";
         if ("dimenOffset".equals(mResourceType)) return resources + ".getDimensionPixelOffset(" + resourceName + ")";
         if ("dimenSize".equals(mResourceType)) return resources + ".getDimensionPixelSize(" + resourceName + ")";
-        if ("drawable".equals(mResourceType)) return "getDrawableFromResource(" + resourceName + ")";
+        if ("drawable".equals(mResourceType)) return "android.databinding.DynamicUtil.getDrawableFromResource(" + viewName + ", " + resourceName + ")";
         if ("fraction".equals(mResourceType)) {
             String base = getChildCode(0, "1");
             String pbase = getChildCode(1, "1");
@@ -172,11 +195,11 @@
             if (getChildren().isEmpty()) {
                 return resourceName;
             } else {
-                return makeParameterCall(resourceName, "getQuantityString");
+                return makeParameterCall(resources, resourceName, "getQuantityString");
             }
         }
         if ("stateListAnimator".equals(mResourceType)) return "android.animation.AnimatorInflater.loadStateListAnimator(" + context + ", " + resourceName + ")";
-        if ("string".equals(mResourceType)) return makeParameterCall(resourceName, "getString");
+        if ("string".equals(mResourceType)) return makeParameterCall(resources, resourceName, "getString");
         if ("stringArray".equals(mResourceType)) return resources + ".getStringArray(" + resourceName + ")";
         if ("transition".equals(mResourceType)) return "android.transition.TransitionInflater.from(" + context + ").inflateTransition(" + resourceName + ")";
         if ("typedArray".equals(mResourceType)) return resources + ".obtainTypedArray(" + resourceName + ")";
@@ -194,9 +217,9 @@
         }
     }
 
-    private String makeParameterCall(String resourceName, String methodCall) {
-        StringBuilder sb = new StringBuilder("getRoot().getResources().");
-        sb.append(methodCall).append("(").append(resourceName);
+    private String makeParameterCall(String resources, String resourceName, String methodCall) {
+        StringBuilder sb = new StringBuilder(resources);
+        sb.append('.').append(methodCall).append("(").append(resourceName);
         for (Expr expr : getChildren()) {
             sb.append(", ").append(expr.toCode().generate());
         }
@@ -211,4 +234,13 @@
         }
         return rFileObject;
     }
+
+    @Override
+    public String toString() {
+        if (mPackage == null) {
+            return "@" + mResourceType + "/" + mResourceId;
+        } else {
+            return "@" + "android:" + mResourceType + "/" + mResourceId;
+        }
+    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/StaticIdentifierExpr.java b/compiler/src/main/java/android/databinding/tool/expr/StaticIdentifierExpr.java
index 7618e94..0d36f2a 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/StaticIdentifierExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/StaticIdentifierExpr.java
@@ -41,11 +41,17 @@
     }
 
     @Override
-    public KCode toInverseCode(KCode value) {
+    public Expr generateInverse(ExprModel model, Expr value, String bindingClassName) {
         throw new IllegalStateException("StaticIdentifierExpr is not invertible.");
     }
+
     @Override
-    protected KCode generateCode(boolean expand) {
+    protected KCode generateCode() {
         return new KCode(getResolvedType().toJavaCode());
     }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.staticIdentifier(mName);
+    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/SymbolExpr.java b/compiler/src/main/java/android/databinding/tool/expr/SymbolExpr.java
index 38708c0..388d224 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/SymbolExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/SymbolExpr.java
@@ -18,6 +18,7 @@
 
 import android.databinding.tool.reflection.ModelAnalyzer;
 import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.solver.ExecutionPath;
 import android.databinding.tool.writer.KCode;
 
 import java.util.ArrayList;
@@ -53,12 +54,35 @@
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
+    protected KCode generateCode() {
         return new KCode(getText());
     }
 
     @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.symbol(mText, mType);
+    }
+
+    @Override
     protected List<Dependency> constructDependencies() {
         return new ArrayList<Dependency>();
     }
+
+    @Override
+    public boolean canBeEvaluatedToAVariable() {
+        return !void.class.equals(mType);
+    }
+
+    @Override
+    public List<ExecutionPath> toExecutionPath(List<ExecutionPath> paths) {
+        if (void.class.equals(mType)) {
+            return paths;
+        }
+        return super.toExecutionPath(paths);
+    }
+
+    @Override
+    public String toString() {
+        return mText;
+    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/TernaryExpr.java b/compiler/src/main/java/android/databinding/tool/expr/TernaryExpr.java
index d4a3727..856cab0 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/TernaryExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/TernaryExpr.java
@@ -18,6 +18,7 @@
 
 import android.databinding.tool.reflection.ModelAnalyzer;
 import android.databinding.tool.reflection.ModelClass;
+import android.databinding.tool.solver.ExecutionPath;
 import android.databinding.tool.writer.KCode;
 
 import java.util.ArrayList;
@@ -25,6 +26,7 @@
 import java.util.List;
 
 public class TernaryExpr extends Expr {
+
     TernaryExpr(Expr pred, Expr ifTrue, Expr ifFalse) {
         super(pred, ifTrue, ifFalse);
     }
@@ -76,7 +78,7 @@
     private static boolean isNullLiteral(Expr expr) {
         final ModelClass type = expr.getResolvedType();
         return (type.isObject() && (expr instanceof SymbolExpr) &&
-                "null".equals(((SymbolExpr)expr).getText()));
+                "null".equals(((SymbolExpr) expr).getText()));
     }
 
     @Override
@@ -99,32 +101,58 @@
     }
 
     @Override
+    public List<ExecutionPath> toExecutionPath(List<ExecutionPath> paths) {
+        List<ExecutionPath> executionPaths = getPred().toExecutionPath(paths);
+        // now optionally add others
+        List<ExecutionPath> result = new ArrayList<ExecutionPath>();
+        for (ExecutionPath path : executionPaths) {
+            ExecutionPath ifTrue = path.addBranch(getPred(), true);
+            if (ifTrue != null) {
+                result.addAll(getIfTrue().toExecutionPath(ifTrue));
+            }
+            ExecutionPath ifFalse = path.addBranch(getPred(), false);
+            if (ifFalse != null) {
+                result.addAll(getIfFalse().toExecutionPath(ifFalse));
+            }
+        }
+        return addJustMeToExecutionPath(result);
+    }
+
+    @Override
     protected BitSet getPredicateInvalidFlags() {
         return getPred().getInvalidFlags();
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
+    protected KCode generateCode() {
         return new KCode()
-                .app("", getPred().toCode(expand))
-                .app(" ? ", getIfTrue().toCode(expand))
-                .app(" : ", getIfFalse().toCode(expand));
-
+                .app("(", getPred().toCode())
+                .app(") ? (", getIfTrue().toCode())
+                .app(") : (", getIfFalse().toCode())
+                .app(")");
     }
 
     @Override
-    public KCode toInverseCode(KCode variable) {
-        return new KCode()
-                .app("if (", getPred().toCode(true))
-                .app(") {")
-                .tab(getIfTrue().toInverseCode(variable))
-                .nl(new KCode("} else {"))
-                .tab(getIfFalse().toInverseCode(variable))
-                .nl(new KCode("}"));
+    public Expr generateInverse(ExprModel model, Expr value, String bindingClassName) {
+        final Expr pred = getPred().cloneToModel(model);
+        final Expr ifTrue = getIfTrue().generateInverse(model, value, bindingClassName);
+        final Expr ifFalse = getIfFalse().generateInverse(model, value, bindingClassName);
+        return model.ternary(pred, ifTrue, ifFalse);
+    }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.ternary(getPred().cloneToModel(model), getIfTrue().cloneToModel(model),
+                getIfFalse().cloneToModel(model));
     }
 
     @Override
     public boolean isConditional() {
         return true;
     }
+
+    @Override
+    public String toString() {
+        return getPred().toString() + " ? " + getIfTrue() + " : " + getIfFalse();
+    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/TwoWayListenerExpr.java b/compiler/src/main/java/android/databinding/tool/expr/TwoWayListenerExpr.java
index 1a65673..c14cdd6 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/TwoWayListenerExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/TwoWayListenerExpr.java
@@ -45,12 +45,17 @@
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
+    protected KCode generateCode() {
         final String fieldName = LayoutBinderWriterKt.getFieldName(mInverseBinding);
         return new KCode(fieldName);
     }
 
     @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.twoWayListenerExpr(mInverseBinding);
+    }
+
+    @Override
     protected String computeUniqueKey() {
         return "event(" + mInverseBinding.getEventAttribute() + ", " +
                 System.identityHashCode(mInverseBinding) + ")";
diff --git a/compiler/src/main/java/android/databinding/tool/expr/UnaryExpr.java b/compiler/src/main/java/android/databinding/tool/expr/UnaryExpr.java
index 881a352..18e5985 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/UnaryExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/UnaryExpr.java
@@ -36,17 +36,22 @@
 
     @Override
     protected String computeUniqueKey() {
-        return addTwoWay(join(getOpStr(), getExpr().getUniqueKey()));
+        return join(getOpStr(), getExpr().getUniqueKey());
     }
 
     @Override
-    public KCode toInverseCode(KCode value) {
-        return getExpr().toInverseCode(new KCode().app(mOp, value));
+    public Expr generateInverse(ExprModel model, Expr value, String bindingClassName) {
+        return model.unary(mOp, getExpr().generateInverse(model, value, bindingClassName));
     }
 
     @Override
-    protected KCode generateCode(boolean expand) {
-        return new KCode().app(getOp(), getExpr().toCode(expand));
+    public Expr cloneToModel(ExprModel model) {
+        return model.unary(mOp, getExpr().cloneToModel(model));
+    }
+
+    @Override
+    protected KCode generateCode() {
+        return new KCode().app(getOp(), getExpr().toCode());
     }
 
     @Override
@@ -76,4 +81,9 @@
     public Expr getExpr() {
         return getChildren().get(0);
     }
+
+    @Override
+    public String toString() {
+        return mOp + getExpr();
+    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/expr/ViewFieldExpr.java b/compiler/src/main/java/android/databinding/tool/expr/ViewFieldExpr.java
index 0a6b15b..59c0dbe 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/ViewFieldExpr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/ViewFieldExpr.java
@@ -25,7 +25,7 @@
     private final BindingTarget mBindingTarget;
 
     ViewFieldExpr(BindingTarget bindingTarget) {
-        super(LayoutBinderWriterKt.getFieldName(bindingTarget), initialType(bindingTarget),
+        super(LayoutBinderWriterKt.getFieldName(bindingTarget), bindingTarget.getInterfaceType(),
                 LayoutBinderWriterKt.getFieldName(bindingTarget));
         mBindingTarget = bindingTarget;
     }
@@ -35,12 +35,6 @@
         return "View fields may not be the target of two-way binding";
     }
 
-    private static String initialType(BindingTarget bindingTarget) {
-        return bindingTarget.isBinder()
-                ? "android.databinding.ViewDataBinding"
-                : bindingTarget.getInterfaceType();
-    }
-
     public BindingTarget getBindingTarget() {
         return mBindingTarget;
     }
@@ -49,8 +43,13 @@
     protected ModelClass resolveType(ModelAnalyzer modelAnalyzer) {
         final ModelClass type = modelAnalyzer.findClass(mBindingTarget.getInterfaceType(), null);
         if (type == null) {
-            return modelAnalyzer.findClass("android.databinding.ViewDataBinding", null);
+            return modelAnalyzer.findClass(ModelAnalyzer.VIEW_DATA_BINDING, null);
         }
         return type;
     }
+
+    @Override
+    public Expr cloneToModel(ExprModel model) {
+        return model.viewFieldExpr(mBindingTarget);
+    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/Callable.java b/compiler/src/main/java/android/databinding/tool/reflection/Callable.java
index 5b9acf2..5088523 100644
--- a/compiler/src/main/java/android/databinding/tool/reflection/Callable.java
+++ b/compiler/src/main/java/android/databinding/tool/reflection/Callable.java
@@ -15,8 +15,9 @@
  */
 package android.databinding.tool.reflection;
 
-public class Callable {
+import org.jetbrains.annotations.Nullable;
 
+public class Callable {
     public enum Type {
         METHOD,
         FIELD
@@ -34,18 +35,22 @@
 
     public final ModelClass resolvedType;
 
+    @Nullable
+    public final ModelMethod method;
+
     private final int mFlags;
 
     private final int mParameterCount;
 
     public Callable(Type type, String name, String setterName, ModelClass resolvedType,
-                    int parameterCount, int flags) {
+            int parameterCount, int flags, ModelMethod method) {
         this.type = type;
         this.name = name;
         this.resolvedType = resolvedType;
         mParameterCount = parameterCount;
         this.setterName = setterName;
         mFlags = flags;
+        this.method = method;
     }
 
     public String getTypeCodeName() {
@@ -81,6 +86,7 @@
                 ", isDynamic=" + isDynamic() +
                 ", canBeInvalidated=" + canBeInvalidated() +
                 ", static=" + isStatic() +
+                ", method=" + method +
                 '}';
     }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.java b/compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.java
new file mode 100644
index 0000000..4585799
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/reflection/InjectedClass.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.tool.reflection;
+
+import android.databinding.tool.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A class that can be used by ModelAnalyzer without any backing model. This is used
+ * for ViewDataBinding subclasses that haven't been generated yet, but we still want
+ * to resolve methods and fields for them.
+ *
+ * @see ModelAnalyzer#injectViewDataBinding(String, Map, Map)
+ */
+public class InjectedClass extends ModelClass {
+    private final String mClassName;
+    private final String mSuperClass;
+    private final List<InjectedMethod> mMethods = new ArrayList<InjectedMethod>();
+    private final List<InjectedField> mFields = new ArrayList<InjectedField>();
+
+    public InjectedClass(String className, String superClass) {
+        mClassName = className;
+        mSuperClass = superClass;
+    }
+
+    public void addField(InjectedField field) {
+        mFields.add(field);
+    }
+
+    public void addMethod(InjectedMethod method) {
+        mMethods.add(method);
+    }
+
+    @Override
+    public String toJavaCode() {
+        return mClassName;
+    }
+
+    @Override
+    public boolean isArray() {
+        return false;
+    }
+
+    @Override
+    public ModelClass getComponentType() {
+        return null;
+    }
+
+    @Override
+    public boolean isNullable() {
+        return true;
+    }
+
+    @Override
+    public boolean isPrimitive() {
+        return false;
+    }
+
+    @Override
+    public boolean isBoolean() {
+        return false;
+    }
+
+    @Override
+    public boolean isChar() {
+        return false;
+    }
+
+    @Override
+    public boolean isByte() {
+        return false;
+    }
+
+    @Override
+    public boolean isShort() {
+        return false;
+    }
+
+    @Override
+    public boolean isInt() {
+        return false;
+    }
+
+    @Override
+    public boolean isLong() {
+        return false;
+    }
+
+    @Override
+    public boolean isFloat() {
+        return false;
+    }
+
+    @Override
+    public boolean isDouble() {
+        return false;
+    }
+
+    @Override
+    public boolean isGeneric() {
+        return false;
+    }
+
+    @Override
+    public List<ModelClass> getTypeArguments() {
+        return null;
+    }
+
+    @Override
+    public boolean isTypeVar() {
+        return false;
+    }
+
+    @Override
+    public boolean isWildcard() {
+        return false;
+    }
+
+    @Override
+    public boolean isInterface() {
+        return false;
+    }
+
+    @Override
+    public boolean isVoid() {
+        return false;
+    }
+
+    @Override
+    public ModelClass unbox() {
+        return this;
+    }
+
+    @Override
+    public ModelClass box() {
+        return this;
+    }
+
+    @Override
+    public boolean isObservable() {
+        return getSuperclass().isObservable();
+    }
+
+    @Override
+    public boolean isAssignableFrom(ModelClass that) {
+        ModelClass superClass = that;
+        while (superClass != null && !superClass.isObject()) {
+            if (superClass.toJavaCode().equals(mClassName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public ModelClass getSuperclass() {
+        return ModelAnalyzer.getInstance().findClass(mSuperClass, null);
+    }
+
+    @Override
+    public ModelClass erasure() {
+        return this;
+    }
+
+    @Override
+    public String getJniDescription() {
+        return TypeUtil.getInstance().getDescription(this);
+    }
+
+    @Override
+    protected ModelField[] getDeclaredFields() {
+        ModelClass superClass = getSuperclass();
+        final ModelField[] superFields = superClass.getDeclaredFields();
+        final int initialCount = superFields.length;
+        final int fieldCount = initialCount + mFields.size();
+        final ModelField[] fields = Arrays.copyOf(superFields, fieldCount);
+        for (int i = 0; i < mFields.size(); i++) {
+            fields[i + initialCount] = mFields.get(i);
+        }
+        return fields;
+    }
+
+    @Override
+    protected ModelMethod[] getDeclaredMethods() {
+        ModelClass superClass = getSuperclass();
+        final ModelMethod[] superMethods = superClass.getDeclaredMethods();
+        final int initialCount = superMethods.length;
+        final int methodCount = initialCount + mMethods.size();
+        final ModelMethod[] methods = Arrays.copyOf(superMethods, methodCount);
+        for (int i = 0; i < mMethods.size(); i++) {
+            methods[i + initialCount] = mMethods.get(i);
+        }
+        return methods;
+    }
+
+    @Override
+    public String toString() {
+        return "Injected Class: " + mClassName;
+    }
+}
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/InjectedField.java b/compiler/src/main/java/android/databinding/tool/reflection/InjectedField.java
new file mode 100644
index 0000000..85719f1
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/reflection/InjectedField.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.tool.reflection;
+
+import java.util.Map;
+
+/**
+ * A class that can be used by ModelAnalyzer without any backing model. This is used
+ * for fields on ViewDataBinding subclasses that haven't been generated yet.
+ *
+ * @see ModelAnalyzer#injectViewDataBinding(String, Map, Map)
+ */
+public class InjectedField extends ModelField {
+    private final String mType;
+    private final String mName;
+
+    public InjectedField(String name, String type) {
+        mName = name;
+        mType = type;
+    }
+
+    @Override
+    public boolean isBindable() {
+        return false;
+    }
+
+    @Override
+    public String getName() {
+        return mName;
+    }
+
+    @Override
+    public boolean isPublic() {
+        return true;
+    }
+
+    @Override
+    public boolean isStatic() {
+        return false;
+    }
+
+    @Override
+    public boolean isFinal() {
+        return true;
+    }
+
+    @Override
+    public ModelClass getFieldType() {
+        return ModelAnalyzer.getInstance().findClass(mType, null);
+    }
+}
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/InjectedMethod.java b/compiler/src/main/java/android/databinding/tool/reflection/InjectedMethod.java
new file mode 100644
index 0000000..f47442b
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/reflection/InjectedMethod.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.tool.reflection;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A class that can be used by ModelAnalyzer without any backing model. This is used
+ * for methods on ViewDataBinding subclasses that haven't been generated yet.
+ *
+ * @see ModelAnalyzer#injectViewDataBinding(String, Map, Map)
+ */
+public class InjectedMethod extends ModelMethod {
+    private final InjectedClass mContainingClass;
+    private final String mName;
+    private final String mReturnTypeName;
+    private final String[] mParameterTypeNames;
+    private ModelClass[] mParameterTypes;
+    private ModelClass mReturnType;
+    private boolean mIsStatic;
+
+    public InjectedMethod(InjectedClass containingClass, boolean isStatic, String name,
+            String returnType, String... parameters) {
+        mContainingClass = containingClass;
+        mName = name;
+        mIsStatic = isStatic;
+        mReturnTypeName = returnType;
+        mParameterTypeNames = parameters;
+    }
+
+    @Override
+    public ModelClass getDeclaringClass() {
+        return mContainingClass;
+    }
+
+    @Override
+    public ModelClass[] getParameterTypes() {
+        if (mParameterTypes == null) {
+            if (mParameterTypeNames == null) {
+                mParameterTypes = new ModelClass[0];
+            } else {
+                mParameterTypes = new ModelClass[mParameterTypeNames.length];
+                ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance();
+                for (int i = 0; i < mParameterTypeNames.length; i++) {
+                    mParameterTypes[i] = modelAnalyzer.findClass(mParameterTypeNames[i], null);
+                }
+            }
+        }
+        return mParameterTypes;
+    }
+
+    @Override
+    public String getName() {
+        return mName;
+    }
+
+    @Override
+    public ModelClass getReturnType(List<ModelClass> args) {
+        if (mReturnType == null) {
+            mReturnType = ModelAnalyzer.getInstance().findClass(mReturnTypeName, null);
+        }
+        return mReturnType;
+    }
+
+    @Override
+    public boolean isVoid() {
+        return getReturnType().isVoid();
+    }
+
+    @Override
+    public boolean isPublic() {
+        return true;
+    }
+
+    @Override
+    public boolean isProtected() {
+        return false;
+    }
+
+    @Override
+    public boolean isStatic() {
+        return mIsStatic;
+    }
+
+    @Override
+    public boolean isAbstract() {
+        return true;
+    }
+
+    @Override
+    public boolean isBindable() {
+        return false;
+    }
+
+    @Override
+    public int getMinApi() {
+        return 0;
+    }
+
+    @Override
+    public String getJniDescription() {
+        return TypeUtil.getInstance().getDescription(this);
+    }
+
+    @Override
+    public boolean isVarArgs() {
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("public ");
+        if (mIsStatic) {
+            sb.append("static ");
+        }
+        sb.append(mReturnTypeName)
+                .append(' ')
+                .append(mName)
+                .append("(");
+        if (mParameterTypeNames != null) {
+            for (int i = 0; i < mParameterTypeNames.length; i++) {
+                if (i != 0) {
+                    sb.append(", ");
+                }
+                sb.append(mParameterTypeNames[i]);
+            }
+        }
+        sb.append(')');
+        return sb.toString();
+    }
+}
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.java b/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.java
index b1de46e..995ae21 100644
--- a/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.java
+++ b/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.java
@@ -18,7 +18,9 @@
 import android.databinding.tool.reflection.annotation.AnnotationAnalyzer;
 import android.databinding.tool.util.L;
 import android.databinding.tool.util.Preconditions;
+import android.databinding.tool.util.StringUtils;
 
+import java.util.HashMap;
 import java.util.Map;
 
 import javax.annotation.processing.ProcessingEnvironment;
@@ -82,13 +84,19 @@
     private ModelClass mViewStubType;
 
     private static ModelAnalyzer sAnalyzer;
+    private final Map<String, InjectedClass> mInjectedClasses =
+            new HashMap<String, InjectedClass>();
 
     protected void setInstance(ModelAnalyzer analyzer) {
         sAnalyzer = analyzer;
     }
 
-    public ModelClass findCommonParentOf(ModelClass modelClass1,
-            ModelClass modelClass2) {
+    public ModelClass findCommonParentOf(ModelClass modelClass1, ModelClass modelClass2) {
+        return findCommonParentOf(modelClass1, modelClass2, true);
+    }
+
+    public ModelClass findCommonParentOf(ModelClass modelClass1, ModelClass modelClass2,
+            boolean failOnError) {
         ModelClass curr = modelClass1;
         while (curr != null && !curr.isAssignableFrom(modelClass2)) {
             curr = curr.getSuperclass();
@@ -103,13 +111,15 @@
             ModelClass primitive1 = modelClass1.unbox();
             ModelClass primitive2 = modelClass2.unbox();
             if (!modelClass1.equals(primitive1) || !modelClass2.equals(primitive2)) {
-                return findCommonParentOf(primitive1, primitive2);
+                return findCommonParentOf(primitive1, primitive2, failOnError);
             }
         }
-        Preconditions.checkNotNull(curr,
-                "must be able to find a common parent for " + modelClass1 + " and " + modelClass2);
+        if (failOnError) {
+            Preconditions.checkNotNull(curr,
+                    "must be able to find a common parent for " + modelClass1 + " and "
+                            + modelClass2);
+        }
         return curr;
-
     }
 
     public abstract ModelClass loadPrimitive(String className);
@@ -124,8 +134,7 @@
                     + "change class loader after that");
         }
         L.d("setting processing env to %s", processingEnvironment);
-        AnnotationAnalyzer annotationAnalyzer = new AnnotationAnalyzer(processingEnvironment);
-        sAnalyzer = annotationAnalyzer;
+        sAnalyzer = new AnnotationAnalyzer(processingEnvironment);
     }
 
     /**
@@ -213,12 +222,50 @@
         return "null";
     }
 
-    public abstract ModelClass findClass(String className, Map<String, String> imports);
+    public final ModelClass findClass(String className, Map<String, String> imports) {
+        if (mInjectedClasses.containsKey(className)) {
+            return mInjectedClasses.get(className);
+        }
+        return findClassInternal(className, imports);
+    }
+
+    public abstract ModelClass findClassInternal(String className, Map<String, String> imports);
 
     public abstract ModelClass findClass(Class classType);
 
     public abstract TypeUtil createTypeUtil();
 
+    public ModelClass injectClass(InjectedClass injectedClass) {
+        mInjectedClasses.put(injectedClass.getCanonicalName(), injectedClass);
+        return injectedClass;
+    }
+
+    public ModelClass injectViewDataBinding(String className, Map<String, String> variables,
+            Map<String, String> fields) {
+        InjectedClass injectedClass = new InjectedClass(className,
+                ModelAnalyzer.VIEW_DATA_BINDING);
+
+        if (fields != null) {
+            for (String name : fields.keySet()) {
+                String type = fields.get(name);
+                injectedClass.addField(new InjectedField(name, type));
+            }
+        }
+        if (variables != null) {
+            for (String name : variables.keySet()) {
+                String type = variables.get(name);
+                String capName = StringUtils.capitalize(name);
+                String setName = "set" + capName;
+                String getName = "get" + capName;
+                injectedClass.addMethod(new InjectedMethod(injectedClass, false, getName, type));
+                injectedClass.addMethod(new InjectedMethod(injectedClass, false, setName, "void",
+                        type));
+            }
+        }
+        mInjectedClasses.put(className, injectedClass);
+        return injectedClass;
+    }
+
     ModelClass[] getListTypes() {
         if (mListTypes == null) {
             mListTypes = new ModelClass[LIST_CLASS_NAMES.length];
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.java b/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.java
index 6fbc5a0..243fcde 100644
--- a/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.java
+++ b/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.java
@@ -19,6 +19,8 @@
 import android.databinding.tool.util.L;
 import android.databinding.tool.util.StringUtils;
 
+import org.jetbrains.annotations.NotNull;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -233,23 +235,27 @@
     public abstract boolean isAssignableFrom(ModelClass that);
 
     /**
-     * Returns an array containing all public methods on the type represented by this ModelClass
-     * with the name <code>name</code> and can take the passed-in types as arguments. This will
-     * also work if the arguments match VarArgs parameter.
+     * Returns an array containing all public methods (or protected if allowProtected is true)
+     * on the type represented by this ModelClass with the name <code>name</code> and can
+     * take the passed-in types as arguments. This will also work if the arguments match
+     * VarArgs parameter.
      *
      * @param name The name of the method to find.
      * @param args The types that the method should accept.
      * @param staticOnly Whether only static methods should be returned or both instance methods
      *                 and static methods are valid.
+     * @param allowProtected true if the method can be protected as well as public.
      *
      * @return An array containing all public methods with the name <code>name</code> and taking
      * <code>args</code> parameters.
      */
-    public ModelMethod[] getMethods(String name, List<ModelClass> args, boolean staticOnly) {
+    public ModelMethod[] getMethods(String name, List<ModelClass> args, boolean staticOnly,
+            boolean allowProtected) {
         ModelMethod[] methods = getDeclaredMethods();
         ArrayList<ModelMethod> matching = new ArrayList<ModelMethod>();
         for (ModelMethod method : methods) {
-            if (method.isPublic() && (!staticOnly || method.isStatic()) &&
+            if ((method.isPublic() || (allowProtected && method.isProtected())) &&
+                    (!staticOnly || method.isStatic()) &&
                     name.equals(method.getName()) && method.acceptsArguments(args)) {
                 matching.add(method);
             }
@@ -286,9 +292,11 @@
      * @param args The arguments that the method should accept
      * @param staticOnly true if the returned method must be static or false if it does not
      *                     matter.
+     * @param allowProtected true if the method can be protected as well as public.
      */
-    public ModelMethod getMethod(String name, List<ModelClass> args, boolean staticOnly) {
-        ModelMethod[] methods = getMethods(name, args, staticOnly);
+    public ModelMethod getMethod(String name, List<ModelClass> args, boolean staticOnly,
+            boolean allowProtected) {
+        ModelMethod[] methods = getMethods(name, args, staticOnly, allowProtected);
         L.d("looking methods for %s. static only ? %s . method count: %d", name, staticOnly,
                 methods.length);
         for (ModelMethod method : methods) {
@@ -363,6 +371,7 @@
     /**
      * Returns a list of all abstract methods in the type.
      */
+    @NotNull
     public List<ModelMethod> getAbstractMethods() {
         ArrayList<ModelMethod> abstractMethods = new ArrayList<ModelMethod>();
         ModelMethod[] methods = getDeclaredMethods();
@@ -385,7 +394,7 @@
     public Callable findGetterOrField(String name, boolean staticOnly) {
         if ("length".equals(name) && isArray()) {
             return new Callable(Type.FIELD, name, null,
-                    ModelAnalyzer.getInstance().loadPrimitive("int"), 0, 0);
+                    ModelAnalyzer.getInstance().loadPrimitive("int"), 0, 0, null);
         }
         String capitalized = StringUtils.capitalize(name);
         String[] methodNames = {
@@ -394,7 +403,8 @@
                 name
         };
         for (String methodName : methodNames) {
-            ModelMethod[] methods = getMethods(methodName, new ArrayList<ModelClass>(), staticOnly);
+            ModelMethod[] methods =
+                    getMethods(methodName, new ArrayList<ModelClass>(), staticOnly, false);
             for (ModelMethod method : methods) {
                 if (method.isPublic() && (!staticOnly || method.isStatic()) &&
                         !method.getReturnType(Arrays.asList(method.getParameterTypes())).isVoid()) {
@@ -417,7 +427,7 @@
                     final String setterName = setterMethod == null ? null : setterMethod.getName();
                     final Callable result = new Callable(Callable.Type.METHOD, methodName,
                             setterName, method.getReturnType(null), method.getParameterTypes().length,
-                            flags);
+                            flags, method);
                     return result;
                 }
             }
@@ -451,7 +461,7 @@
         if (publicField.isBindable()) {
             flags |= CAN_BE_INVALIDATED;
         }
-        return new Callable(Callable.Type.FIELD, name, setterFieldName, fieldType, 0, flags);
+        return new Callable(Callable.Type.FIELD, name, setterFieldName, fieldType, 0, flags, null);
     }
 
     public ModelMethod findInstanceGetter(String name) {
@@ -462,7 +472,8 @@
                 name
         };
         for (String methodName : methodNames) {
-            ModelMethod[] methods = getMethods(methodName, new ArrayList<ModelClass>(), false);
+            ModelMethod[] methods =
+                    getMethods(methodName, new ArrayList<ModelClass>(), false, false);
             for (ModelMethod method : methods) {
                 if (method.isPublic() && !method.isStatic() &&
                         !method.getReturnType(Arrays.asList(method.getParameterTypes())).isVoid()) {
@@ -498,15 +509,13 @@
         }
         for (String name : possibleNames) {
             List<ModelMethod> methods = findMethods(name, getter.isStatic());
-            if (methods != null) {
-                ModelClass param = getter.getReturnType(null);
-                for (ModelMethod method : methods) {
-                    ModelClass[] parameterTypes = method.getParameterTypes();
-                    if (parameterTypes != null && parameterTypes.length == 1 &&
-                            parameterTypes[0].equals(param) &&
-                            method.isStatic() == getter.isStatic()) {
-                        return method;
-                    }
+            ModelClass param = getter.getReturnType(null);
+            for (ModelMethod method : methods) {
+                ModelClass[] parameterTypes = method.getParameterTypes();
+                if (parameterTypes != null && parameterTypes.length == 1 &&
+                        parameterTypes[0].equals(param) &&
+                        method.isStatic() == getter.isStatic()) {
+                    return method;
                 }
             }
         }
@@ -517,6 +526,7 @@
      * Finds public methods that matches the given name exactly. These may be resolved into
      * listener methods during Expr.resolveListeners.
      */
+    @NotNull
     public List<ModelMethod> findMethods(String name, boolean staticOnly) {
         ModelMethod[] methods = getDeclaredMethods();
         ArrayList<ModelMethod> matching = new ArrayList<ModelMethod>();
@@ -526,9 +536,6 @@
                 matching.add(method);
             }
         }
-        if (matching.isEmpty()) {
-            return null;
-        }
         return matching;
     }
 
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/ModelMethod.java b/compiler/src/main/java/android/databinding/tool/reflection/ModelMethod.java
index 9965715..3ec7ff8 100644
--- a/compiler/src/main/java/android/databinding/tool/reflection/ModelMethod.java
+++ b/compiler/src/main/java/android/databinding/tool/reflection/ModelMethod.java
@@ -32,6 +32,8 @@
 
     public abstract boolean isPublic();
 
+    public abstract boolean isProtected();
+
     public abstract boolean isStatic();
 
     public abstract boolean isAbstract();
@@ -76,6 +78,9 @@
         for (int i = 0; i < args.size(); i++) {
             ModelClass parameterType = getParameter(i, parameterTypes);
             ModelClass arg = args.get(i);
+            if (parameterType.isIncomplete()) {
+                parameterType = parameterType.erasure();
+            }
             if (!parameterType.isAssignableFrom(arg) && !isImplicitConversion(arg, parameterType)) {
                 parametersMatch = false;
                 break;
@@ -91,6 +96,9 @@
             final ModelClass arg = args.get(i);
             final ModelClass thisParameter = getParameter(i, parameterTypes);
             final ModelClass thatParameter = other.getParameter(i, otherParameterTypes);
+            if (thisParameter.equals(thatParameter)) {
+                continue;
+            }
             final int diff = compareParameter(arg, thisParameter, thatParameter);
             if (diff != 0) {
                 return diff < 0;
@@ -99,6 +107,10 @@
         return false;
     }
 
+    public ModelClass getReturnType() {
+        return getReturnType(null);
+    }
+
     private ModelClass getParameter(int index, ModelClass[] parameterTypes) {
         int normalParamCount = isVarArgs() ? parameterTypes.length - 1 : parameterTypes.length;
         if (index < normalParamCount) {
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationAnalyzer.java b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationAnalyzer.java
index 4773f17..80664cd 100644
--- a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationAnalyzer.java
+++ b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationAnalyzer.java
@@ -26,7 +26,6 @@
 
 import javax.annotation.processing.Messager;
 import javax.annotation.processing.ProcessingEnvironment;
-import javax.lang.model.element.AnnotationMirror;
 import javax.lang.model.element.Element;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.type.DeclaredType;
@@ -85,7 +84,7 @@
     }
 
     @Override
-    public AnnotationClass findClass(String className, Map<String, String> imports) {
+    public ModelClass findClassInternal(String className, Map<String, String> imports) {
         className = className.trim();
         int numDimensions = 0;
         while (className.endsWith("[]")) {
@@ -96,6 +95,9 @@
         if (primitive != null) {
             return addDimension(primitive.mTypeMirror, numDimensions);
         }
+        if ("void".equals(className.toLowerCase())) {
+            return addDimension(getTypeUtils().getNoType(TypeKind.VOID), numDimensions);
+        }
         int templateOpenIndex = className.indexOf('<');
         DeclaredType declaredType;
         if (templateOpenIndex < 0) {
@@ -118,7 +120,8 @@
             ArrayList<String> templateParameters = splitTemplateParameters(paramStr);
             TypeMirror[] typeArgs = new TypeMirror[templateParameters.size()];
             for (int i = 0; i < typeArgs.length; i++) {
-                final AnnotationClass clazz = findClass(templateParameters.get(i), imports);
+                final AnnotationClass clazz = (AnnotationClass)
+                        findClass(templateParameters.get(i), imports);
                 if (clazz == null) {
                     L.e("cannot find type argument for %s in %s", templateParameters.get(i),
                             baseClassName);
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationClass.java b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationClass.java
index 02e767e..feae09d 100644
--- a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationClass.java
+++ b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationClass.java
@@ -286,10 +286,17 @@
 
     @Override
     public boolean isAssignableFrom(ModelClass that) {
-        if (that == null) {
+        ModelClass other = that;
+        while (other != null && !(other instanceof AnnotationClass)) {
+            other = other.getSuperclass();
+        }
+        if (other == null) {
             return false;
         }
-        AnnotationClass thatAnnotationClass = (AnnotationClass) that;
+        if (equals(other)) {
+            return true;
+        }
+        AnnotationClass thatAnnotationClass = (AnnotationClass) other;
         return getTypeUtils().isAssignable(thatAnnotationClass.mTypeMirror, this.mTypeMirror);
     }
 
@@ -364,6 +371,19 @@
         return declaredFields;
     }
 
+    private static Types getTypeUtils() {
+        return AnnotationAnalyzer.get().mProcessingEnv.getTypeUtils();
+    }
+
+    private static Elements getElementUtils() {
+        return AnnotationAnalyzer.get().mProcessingEnv.getElementUtils();
+    }
+
+    @Override
+    public String toString() {
+        return mTypeMirror.toString();
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (obj instanceof AnnotationClass) {
@@ -377,17 +397,4 @@
     public int hashCode() {
         return mTypeMirror.toString().hashCode();
     }
-
-    private static Types getTypeUtils() {
-        return AnnotationAnalyzer.get().mProcessingEnv.getTypeUtils();
-    }
-
-    private static Elements getElementUtils() {
-        return AnnotationAnalyzer.get().mProcessingEnv.getElementUtils();
-    }
-
-    @Override
-    public String toString() {
-        return mTypeMirror.toString();
-    }
 }
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationMethod.java b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationMethod.java
index d7caa45..66c1dbc 100644
--- a/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationMethod.java
+++ b/compiler/src/main/java/android/databinding/tool/reflection/annotation/AnnotationMethod.java
@@ -127,6 +127,11 @@
     }
 
     @Override
+    public boolean isProtected() {
+        return mExecutableElement.getModifiers().contains(Modifier.PROTECTED);
+    }
+
+    @Override
     public boolean isStatic() {
         return mExecutableElement.getModifiers().contains(Modifier.STATIC);
     }
diff --git a/compiler/src/main/java/android/databinding/tool/solver/ExecutionBranch.java b/compiler/src/main/java/android/databinding/tool/solver/ExecutionBranch.java
new file mode 100644
index 0000000..bd93191
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/solver/ExecutionBranch.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.databinding.tool.solver;
+
+import android.databinding.tool.expr.Expr;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Represents if statements in the execution.
+ */
+public class ExecutionBranch {
+
+    @NotNull
+    private Expr mConditional;
+
+    private final boolean mExpectedCondition;
+
+    @NotNull
+    private final ExecutionPath mPath;
+
+    public ExecutionBranch(@NotNull ExecutionPath path, @NotNull Expr conditional,
+            boolean expectedCondition) {
+        mConditional = conditional;
+        mExpectedCondition = expectedCondition;
+        mPath = path;
+    }
+
+    @NotNull
+    public Expr getConditional() {
+        return mConditional;
+    }
+
+    public boolean getExpectedCondition() {
+        return mExpectedCondition;
+    }
+
+    @NotNull
+    public ExecutionPath getPath() {
+        return mPath;
+    }
+}
diff --git a/compiler/src/main/java/android/databinding/tool/solver/ExecutionPath.java b/compiler/src/main/java/android/databinding/tool/solver/ExecutionPath.java
new file mode 100644
index 0000000..411ce4f
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/solver/ExecutionPath.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.databinding.tool.solver;
+
+import android.databinding.tool.expr.Expr;
+import android.databinding.tool.util.Preconditions;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Represents all possible outcomes of an expressions with its branching.
+ */
+public class ExecutionPath {
+    @Nullable //null for root and branches
+    private final Expr mExpr;
+    @NotNull
+    private List<ExecutionPath> mChildren = new ArrayList<ExecutionPath>();
+
+    @Nullable
+    private ExecutionBranch mTrueBranch;
+
+    @Nullable
+    private ExecutionBranch mFalseBranch;
+
+    // values that we know due to branching
+    private Map<Expr, Boolean> mKnownValues = new HashMap<Expr, Boolean>();
+
+    // expressions that are available right now
+    private Set<Expr> mScopeExpressions = new HashSet<Expr>();
+
+    private final boolean mIsAlreadyEvaluated;
+
+    public static ExecutionPath createRoot() {
+        return new ExecutionPath(null, false);
+    }
+
+    private ExecutionPath(@Nullable Expr expr, boolean isAlreadyEvaluated) {
+        mExpr = expr;
+        mIsAlreadyEvaluated = isAlreadyEvaluated;
+    }
+
+    @Nullable
+    public ExecutionPath addBranch(Expr pred, boolean expectedValue) {
+        // TODO special predicates like Symbol(true, false)
+        Preconditions.checkNull(expectedValue ? mTrueBranch : mFalseBranch,
+                "Cannot add two " + expectedValue + "branches");
+        final Boolean knownValue = mKnownValues.get(pred);
+        if (knownValue != null) {
+            // we know the result. cut the branch
+            if (expectedValue == knownValue) {
+                // just add as a path
+                return addPath(null);
+            } else {
+                // drop path. this cannot happen
+                return null;
+            }
+        } else {
+            ExecutionPath path = createPath(null);
+            ExecutionBranch edge = new ExecutionBranch(path, pred, expectedValue);
+            path.mKnownValues.put(pred, expectedValue);
+            if (expectedValue) {
+                if (mFalseBranch != null) {
+                    Preconditions.check(mFalseBranch.getConditional() == pred, "Cannot add"
+                            + " branches w/ different conditionals.");
+                }
+                mTrueBranch = edge;
+            } else {
+                if (mTrueBranch != null) {
+                    Preconditions.check(mTrueBranch.getConditional() == pred, "Cannot add"
+                            + " branches w/ different conditionals.");
+                }
+                mFalseBranch = edge;
+            }
+            return path;
+        }
+    }
+
+    private ExecutionPath createPath(@Nullable Expr expr) {
+        ExecutionPath path = new ExecutionPath(expr, expr == null ||
+                mScopeExpressions.contains(expr));
+        // now pass down all values etc
+        path.mKnownValues.putAll(mKnownValues);
+        path.mScopeExpressions.addAll(mScopeExpressions);
+        return path;
+    }
+
+    @NotNull
+    public ExecutionPath addPath(@Nullable Expr expr) {
+        Preconditions.checkNull(mFalseBranch, "Cannot add path after branches are set");
+        Preconditions.checkNull(mTrueBranch, "Cannot add path after branches are set");
+        final ExecutionPath path = createPath(expr);
+        if (expr != null) {
+            mScopeExpressions.add(expr);
+            path.mScopeExpressions.add(expr);
+        }
+        mChildren.add(path);
+        return path;
+    }
+
+    public void debug(StringBuilder builder, int offset) {
+        offset(builder, offset);
+        if (mExpr != null || !mIsAlreadyEvaluated) {
+            builder.append("expr:").append(mExpr == null ? "root" : mExpr.getUniqueKey());
+            builder.append(" isRead:").append(mIsAlreadyEvaluated);
+        } else {
+            builder.append("branch");
+        }
+        if (!mKnownValues.isEmpty()) {
+            builder.append(" I know:");
+            for (Map.Entry<Expr, Boolean> entry : mKnownValues.entrySet()) {
+                builder.append(" ");
+                builder.append(entry.getKey().getUniqueKey());
+                builder.append(" is ").append(entry.getValue());
+            }
+        }
+        for (ExecutionPath path : mChildren) {
+            builder.append("\n");
+            path.debug(builder, offset);
+        }
+        if (mTrueBranch != null) {
+            debug(builder, mTrueBranch, offset);
+        }
+        if (mFalseBranch != null) {
+            debug(builder, mFalseBranch, offset);
+        }
+    }
+
+    @Nullable
+    public Expr getExpr() {
+        return mExpr;
+    }
+
+    @NotNull
+    public List<ExecutionPath> getChildren() {
+        return mChildren;
+    }
+
+    @Nullable
+    public ExecutionBranch getTrueBranch() {
+        return mTrueBranch;
+    }
+
+    @Nullable
+    public ExecutionBranch getFalseBranch() {
+        return mFalseBranch;
+    }
+
+    public boolean isAlreadyEvaluated() {
+        return mIsAlreadyEvaluated;
+    }
+
+    private void debug(StringBuilder builder, ExecutionBranch branch, int offset) {
+        builder.append("\n");
+        offset(builder, offset);
+        builder.append("if ")
+                .append(branch.getConditional().getUniqueKey())
+                .append(" is ").append(branch.getExpectedCondition()).append("\n");
+        branch.getPath().debug(builder, offset + 1);
+    }
+
+    private void offset(StringBuilder builder, int offset) {
+        for (int i = 0; i < offset; i++) {
+            builder.append("  ");
+        }
+    }
+
+    public Map<Expr, Boolean> getKnownValues() {
+        return mKnownValues;
+    }
+}
diff --git a/compiler/src/main/java/android/databinding/tool/store/SetterStore.java b/compiler/src/main/java/android/databinding/tool/store/SetterStore.java
index 9568810..90f75e2 100644
--- a/compiler/src/main/java/android/databinding/tool/store/SetterStore.java
+++ b/compiler/src/main/java/android/databinding/tool/store/SetterStore.java
@@ -714,7 +714,7 @@
         if (viewType == null) {
             return null;
         } else if (viewType.isViewDataBinding()) {
-            return new ViewDataBindingGetterCall(attribute);
+            return new ViewDataBindingGetterCall(viewType, attribute);
         }
 
         attribute = stripNamespace(attribute);
@@ -758,11 +758,11 @@
                                                 viewType.getCanonicalName());
                                     } else {
                                         bestMethod.call = new AdapterGetter(inverseDescription,
-                                                setters.get(0));
+                                                setters.get(0), key.valueType);
                                     }
                                 } else {
                                     bestMethod.call = new AdapterGetter(inverseDescription,
-                                            eventCall);
+                                            eventCall, key.valueType);
                                 }
                             }
 
@@ -1271,6 +1271,7 @@
     }
 
     private static class IntermediateV2 extends IntermediateV1 {
+        private static final long serialVersionUID = 0xA45C2EB637E35C07L;
         public final HashMap<String, HashMap<AccessorKey, InverseDescription>> inverseAdapters =
                 new HashMap<String, HashMap<AccessorKey, InverseDescription>>();
         public final HashMap<String, HashMap<String, InverseDescription>> inverseMethods =
@@ -1635,6 +1636,8 @@
     public interface BindingGetterCall {
         String toJava(String componentExpression, String viewExpression);
 
+        String getGetterType();
+
         int getMinApi();
 
         String getBindingAdapterInstanceClass();
@@ -1650,12 +1653,14 @@
         private final String mGetter;
         private final BindingSetterCall mEventSetter;
         private final String mAttribute;
+        private final ModelClass mBindingClass;
 
-        public ViewDataBindingGetterCall(String attribute) {
+        public ViewDataBindingGetterCall(ModelClass bindingClass, String attribute) {
             final int colonIndex = attribute.indexOf(':');
             mAttribute = attribute.substring(colonIndex + 1);
             mGetter = "get" + StringUtils.capitalize(mAttribute);
             mEventSetter = new ViewDataBindingEventSetter();
+            mBindingClass = bindingClass;
         }
 
         @Override
@@ -1664,6 +1669,11 @@
         }
 
         @Override
+        public String getGetterType() {
+            return mBindingClass.findInstanceGetter(mGetter).getReturnType().toJavaCode();
+        }
+
+        @Override
         public int getMinApi() {
             return 0;
         }
@@ -1716,6 +1726,11 @@
         }
 
         @Override
+        public String getGetterType() {
+            return mMethod.getReturnType().toJavaCode();
+        }
+
+        @Override
         public int getMinApi() {
             return mMethod.getMinApi();
         }
@@ -1734,10 +1749,18 @@
         private final InverseDescription mInverseDescription;
         private String mBindingAdapterCall;
         private final BindingSetterCall mEventCall;
+        private final String mGetterType;
 
-        public AdapterGetter(InverseDescription description, BindingSetterCall eventCall) {
+        public AdapterGetter(InverseDescription description, BindingSetterCall eventCall,
+                String getterType) {
             mInverseDescription = description;
             mEventCall = eventCall;
+            mGetterType = getterType;
+        }
+
+        @Override
+        public String getGetterType() {
+            return mGetterType;
         }
 
         @Override
diff --git a/compiler/src/main/java/android/databinding/tool/writer/CallbackWrapperWriter.kt b/compiler/src/main/java/android/databinding/tool/writer/CallbackWrapperWriter.kt
new file mode 100644
index 0000000..a55108d
--- /dev/null
+++ b/compiler/src/main/java/android/databinding/tool/writer/CallbackWrapperWriter.kt
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.tool.writer
+
+import android.databinding.tool.CallbackWrapper
+
+fun CallbackWrapper.allArgsWithTypes() =
+        "int ${CallbackWrapper.SOURCE_ID} ${method.parameterTypes.withIndex().map { ", ${it.value.toJavaCode()} ${CallbackWrapper.ARG_PREFIX}${it.index}" }.joinToString("")}"
+
+fun CallbackWrapper.argsWithTypes() =
+        method.parameterTypes.withIndex().map { "${it.value.toJavaCode()} ${CallbackWrapper.ARG_PREFIX}${it.index}" }.joinToString(", ")
+
+fun CallbackWrapper.args() =
+        method.parameterTypes.withIndex().map { "${CallbackWrapper.ARG_PREFIX}${it.index}" }.joinToString(", ")
+
+fun CallbackWrapper.allArgs() =
+        "mSourceId ${method.parameterTypes.withIndex().map { ", ${CallbackWrapper.ARG_PREFIX}${it.index}" }.joinToString("")}"
+
+/**
+ * For any listener type we see, we create a class that can wrap around it. This wrapper has an
+ * interface which is implemented by the ViewDataBinding.
+ */
+public class CallbackWrapperWriter(val wrapper: CallbackWrapper) {
+
+    public fun write() = kcode("") {
+        with(wrapper) {
+            @Suppress("RemoveCurlyBracesFromTemplate")
+            app("package ${`package`};")
+            val extendsImplements = if (klass.isInterface) {
+                "implements"
+            } else {
+                "extends"
+            }
+            block("public final class $className $extendsImplements ${klass.canonicalName}") {
+                // declare the actual listener interface
+                nl("final $listenerInterfaceName mListener;")
+                nl("final int mSourceId;")
+                block("public $className($listenerInterfaceName listener, int sourceId)") {
+                    nl("mListener = listener;")
+                    nl("mSourceId = sourceId;")
+                }
+                nl("")
+                nl("@Override")
+                block("public ${method.returnType.canonicalName} ${method.name}(${wrapper.argsWithTypes()})") {
+                    val evaluate = "mListener.$listenerMethodName(${wrapper.allArgs()});"
+                    if (method.returnType.isVoid) {
+                        nl("$evaluate")
+                    } else {
+                        nl("return $evaluate")
+                    }
+                }
+                nl("")
+                block("public interface $listenerInterfaceName") {
+                    nl("${method.returnType} $listenerMethodName(${wrapper.allArgsWithTypes()});")
+                }
+            }
+        }
+    }.generate()
+}
\ No newline at end of file
diff --git a/compiler/src/main/kotlin/android/databinding/tool/expr/ExprWriters.kt b/compiler/src/main/kotlin/android/databinding/tool/expr/ExprWriters.kt
new file mode 100644
index 0000000..8488451
--- /dev/null
+++ b/compiler/src/main/kotlin/android/databinding/tool/expr/ExprWriters.kt
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.tool.expr
+
+import android.databinding.tool.reflection.Callable
+import android.databinding.tool.solver.ExecutionPath
+import android.databinding.tool.writer.KCode
+import android.databinding.tool.writer.fieldName
+import android.databinding.tool.writer.isForcedToLocalize
+import android.databinding.tool.writer.isVariable
+import android.databinding.tool.writer.kcode
+import android.databinding.tool.writer.scopedName
+
+fun Expr.shouldLocalizeInCallbacks() = canBeEvaluatedToAVariable() && !resolvedType.isVoid && (isDynamic || isForcedToLocalize())
+
+fun CallbackExprModel.localizeGlobalVariables(vararg ignore: Expr): KCode = kcode("// localize variables for thread safety") {
+    // puts all variables in this model to local values.
+    mExprMap.values.filter { it.shouldLocalizeInCallbacks() && !ignore.contains(it) }.forEach {
+        nl("// ${it.toString()}")
+        nl("${it.resolvedType.toJavaCode()} ${it.scopedName()} = ${if (it.isVariable()) it.fieldName else it.defaultValue};")
+    }
+}
+
+fun ExecutionPath.toCode(): KCode = kcode("") {
+    val myExpr = expr
+    if (myExpr != null && !isAlreadyEvaluated) {
+        // variables are read up top
+        val localize = myExpr.shouldLocalizeInCallbacks() && !myExpr.isVariable()
+        // if this is not a method call (or method call via field access, don't do anything
+        val eligible = localize || (myExpr is MethodCallExpr || (myExpr is FieldAccessExpr && myExpr.getter.type == Callable.Type.METHOD))
+        if (eligible) {
+            val assign = if (localize) {
+                "${myExpr.scopedName()} = "
+            } else {
+                ""
+            }
+            if (myExpr is TernaryExpr) {
+                // if i know the value, short circuit it
+                if (knownValues.containsKey(myExpr.pred)) {
+                    val chosen = if (knownValues[myExpr.pred]!!) myExpr.ifTrue else myExpr.ifFalse
+                    // fast read me
+                    nl("$assign${chosen.toCode().generate()};")
+                } else {
+                    // read me
+                    nl("$assign${myExpr.toFullCode().generate()};")
+                }
+            } else {
+                // read me
+                nl("$assign${myExpr.toFullCode().generate()};")
+            }
+        }
+    }
+    children.forEach {
+        nl(it.toCode())
+    }
+    // if i have branches, execute them
+    val myTrue = trueBranch
+    val myFalse = falseBranch
+    if (myTrue != null) {
+        val condition = with(myTrue.conditional) {
+            if (shouldLocalizeInCallbacks()) {
+                scopedName()
+            } else {
+                toFullCode().generate()
+            }
+        }
+        block("if ($condition)") {
+            nl(myTrue.path.toCode())
+        }
+        if (myFalse != null) {
+            block("else") {
+                nl(myFalse.path.toCode())
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/compiler/src/main/kotlin/android/databinding/tool/writer/BRWriter.kt b/compiler/src/main/kotlin/android/databinding/tool/writer/BRWriter.kt
index 261025d..a11804f 100644
--- a/compiler/src/main/kotlin/android/databinding/tool/writer/BRWriter.kt
+++ b/compiler/src/main/kotlin/android/databinding/tool/writer/BRWriter.kt
@@ -24,12 +24,12 @@
     val klass: String by lazy {
         kcode("") {
             val prefix = if (useFinal) "final " else "";
-            nl("public class BR {") {
+            block("public class BR") {
                 tab("public static ${prefix}int _all = 0;")
                 indexedProps.forEach {
                     tab ("public static ${prefix}int ${it.value} = ${it.index + 1};")
                 }
-            } nl ("}")
+            }
         }.generate()
     }
 }
diff --git a/compiler/src/main/kotlin/android/databinding/tool/writer/DataBinderWriter.kt b/compiler/src/main/kotlin/android/databinding/tool/writer/DataBinderWriter.kt
index da953e4..9bd06a0 100644
--- a/compiler/src/main/kotlin/android/databinding/tool/writer/DataBinderWriter.kt
+++ b/compiler/src/main/kotlin/android/databinding/tool/writer/DataBinderWriter.kt
@@ -20,15 +20,14 @@
     fun write(brWriter : BRWriter) = kcode("") {
         nl("package $pkg;")
         nl("import $projectPackage.BR;")
-        nl("class $className {") {
-            tab("final static int TARGET_MIN_SDK = $minSdk;")
+        block("class $className") {
+            nl("final static int TARGET_MIN_SDK = $minSdk;")
             nl("")
-            tab("public $className() {") {
+            block("public $className()") {
             }
-            tab("}")
             nl("")
-            tab("public android.databinding.ViewDataBinding getDataBinder(android.databinding.DataBindingComponent bindingComponent, android.view.View view, int layoutId) {") {
-                tab("switch(layoutId) {") {
+            block("public android.databinding.ViewDataBinding getDataBinder(android.databinding.DataBindingComponent bindingComponent, android.view.View view, int layoutId)") {
+                block("switch(layoutId)") {
                     layoutBinders.groupBy{it.layoutname }.forEach {
                         val firstVal = it.value[0]
                         tab("case ${firstVal.modulePackage}.R.layout.${firstVal.layoutname}:") {
@@ -40,98 +39,87 @@
                                 }
                             } else {
                                 // we should check the tag to decide which layout we need to inflate
-                                tab("{") {
+                                block("") {
                                     tab("final Object tag = view.getTag();")
                                     tab("if(tag == null) throw new java.lang.RuntimeException(\"view must have a tag\");")
                                     it.value.forEach {
-                                        tab("if (\"${it.tag}_0\".equals(tag)) {") {
+                                        block("if (\"${it.tag}_0\".equals(tag))") {
                                             if (it.isMerge) {
                                                 tab("return new ${it.`package`}.${it.implementationName}(bindingComponent, new android.view.View[]{view});")
                                             } else {
                                                 tab("return new ${it.`package`}.${it.implementationName}(bindingComponent, view);")
                                             }
-                                        } tab("}")
+                                        }
                                     }
                                     tab("throw new java.lang.IllegalArgumentException(\"The tag for ${firstVal.layoutname} is invalid. Received: \" + tag);");
-                                }tab("}")
+                                }
                             }
 
                         }
                     }
                 }
-                tab("}")
-                tab("return null;")
+                nl("return null;")
             }
-            tab("}")
-
-            tab("android.databinding.ViewDataBinding getDataBinder(android.databinding.DataBindingComponent bindingComponent, android.view.View[] views, int layoutId) {") {
-                tab("switch(layoutId) {") {
+            block("android.databinding.ViewDataBinding getDataBinder(android.databinding.DataBindingComponent bindingComponent, android.view.View[] views, int layoutId)") {
+                block("switch(layoutId)") {
                     layoutBinders.filter{it.isMerge }.groupBy{it.layoutname }.forEach {
                         val firstVal = it.value[0]
-                        tab("case ${firstVal.modulePackage}.R.layout.${firstVal.layoutname}:") {
+                        block("case ${firstVal.modulePackage}.R.layout.${firstVal.layoutname}:") {
                             if (it.value.size == 1) {
                                 tab("return new ${firstVal.`package`}.${firstVal.implementationName}(bindingComponent, views);")
                             } else {
                                 // we should check the tag to decide which layout we need to inflate
-                                tab("{") {
-                                    tab("final Object tag = views[0].getTag();")
-                                    tab("if(tag == null) throw new java.lang.RuntimeException(\"view must have a tag\");")
-                                    it.value.forEach {
-                                        tab("if (\"${it.tag}_0\".equals(tag)) {") {
-                                            tab("return new ${it.`package`}.${it.implementationName}(bindingComponent, views);")
-                                        } tab("}")
+                                nl("final Object tag = views[0].getTag();")
+                                nl("if(tag == null) throw new java.lang.RuntimeException(\"view must have a tag\");")
+                                it.value.forEach {
+                                    block("if (\"${it.tag}_0\".equals(tag))") {
+                                        nl("return new ${it.`package`}.${it.implementationName}(bindingComponent, views);")
                                     }
-                                }tab("}")
-                            }
-                        }
-                    }
-                }
-                tab("}")
-                tab("return null;")
-            }
-            tab("}")
-
-            tab("int getLayoutId(String tag) {") {
-                tab("if (tag == null) {") {
-                    tab("return 0;");
-                }
-                tab("}")
-                // String.hashCode is well defined in the API so we can rely on it being the same on the device and the host machine
-                tab("final int code = tag.hashCode();");
-                tab("switch(code) {") {
-                    layoutBinders.groupBy {"${it.tag}_0".hashCode()}.forEach {
-                        tab("case ${it.key}:") {
-                            it.value.forEach {
-                                tab("if(tag.equals(\"${it.tag}_0\"))") {
-                                    tab("return ${it.modulePackage}.R.layout.${it.layoutname};")
                                 }
                             }
-                            tab("break;")
+                        }
+                    }
+                }
+                nl("return null;")
+            }
+
+            block("int getLayoutId(String tag)") {
+                block("if (tag == null)") {
+                    nl("return 0;");
+                }
+                // String.hashCode is well defined in the API so we can rely on it being the same on the device and the host machine
+                nl("final int code = tag.hashCode();");
+                block("switch(code)") {
+                    layoutBinders.groupBy {"${it.tag}_0".hashCode()}.forEach {
+                        block("case ${it.key}:") {
+                            it.value.forEach {
+                                block("if(tag.equals(\"${it.tag}_0\"))") {
+                                    nl("return ${it.modulePackage}.R.layout.${it.layoutname};")
+                                }
+                            }
+                            nl("break;")
                         }
 
                     }
                 }
-                tab("}")
-                tab("return 0;")
+                nl("return 0;")
             }
-            tab("}")
 
-            tab("String convertBrIdToString(int id) {") {
-                tab("if (id < 0 || id >= InnerBrLookup.sKeys.length) {") {
-                    tab("return null;")
-                } tab("}")
-                tab("return InnerBrLookup.sKeys[id];")
-            } tab("}")
+            block("String convertBrIdToString(int id)") {
+                block("if (id < 0 || id >= InnerBrLookup.sKeys.length)") {
+                    nl("return null;")
+                }
+                nl("return InnerBrLookup.sKeys[id];")
+            }
 
-            tab("private static class InnerBrLookup {") {
-                tab("static String[] sKeys = new String[]{") {
+            block("private static class InnerBrLookup") {
+                nl("static String[] sKeys = new String[]{") {
                     tab("\"_all\"")
                     brWriter.indexedProps.forEach {
                         tab(",\"${it.value}\"")
                     }
                 }.app("};")
-            } tab("}")
+            }
         }
-        nl("}")
     }.generate()
 }
\ No newline at end of file
diff --git a/compiler/src/main/kotlin/android/databinding/tool/writer/DynamicUtilWriter.kt b/compiler/src/main/kotlin/android/databinding/tool/writer/DynamicUtilWriter.kt
index 34ac043..e731460 100644
--- a/compiler/src/main/kotlin/android/databinding/tool/writer/DynamicUtilWriter.kt
+++ b/compiler/src/main/kotlin/android/databinding/tool/writer/DynamicUtilWriter.kt
@@ -6,18 +6,97 @@
         nl("import android.os.Build.VERSION;")
         nl("import android.os.Build.VERSION_CODES;")
         nl("")
-        nl("public class DynamicUtil {")
-        tab("@SuppressWarnings(\"deprecation\")")
-        tab("public static int getColorFromResource(final android.view.View root, final int resourceId) {") {
-            if (targetSdk >= 23) {
-                tab("if (VERSION.SDK_INT >= VERSION_CODES.M) {") {
-                    tab("return root.getContext().getColor(resourceId);")
+        block("public class DynamicUtil") {
+            nl("@SuppressWarnings(\"deprecation\")")
+            block("public static int getColorFromResource(final android.view.View view, final int resourceId)") {
+                if (targetSdk >= 23) {
+                    block("if (VERSION.SDK_INT >= VERSION_CODES.M)") {
+                        nl("return view.getContext().getColor(resourceId);")
+                    }
                 }
-                tab("}")
+                nl("return view.getResources().getColor(resourceId);")
             }
-            tab("return root.getResources().getColor(resourceId);")
+
+            nl("@SuppressWarnings(\"deprecation\")")
+            block("public static android.content.res.ColorStateList getColorStateListFromResource(final android.view.View view, final int resourceId)") {
+                if (targetSdk >= 23) {
+                    block("if (VERSION.SDK_INT >= VERSION_CODES.M)") {
+                        nl("return view.getContext().getColorStateList(resourceId);")
+                    }
+                }
+                nl("return view.getResources().getColorStateList(resourceId);")
+            }
+
+            nl("@SuppressWarnings(\"deprecation\")")
+            block("public static android.graphics.drawable.Drawable getDrawableFromResource(final android.view.View view, final int resourceId)") {
+                if (targetSdk >= 21) {
+                    block("if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP)") {
+                        nl("return view.getContext().getDrawable(resourceId);")
+                    }
+                }
+                nl("return view.getResources().getDrawable(resourceId);")
+            }
+
+            block("public static boolean parse(String str, boolean fallback)") {
+                block("if (str == null)") {
+                    nl("return fallback;");
+                }
+                nl("return Boolean.parseBoolean(str);")
+            }
+            block("public static byte parse(String str, byte fallback)") {
+                block("try") {
+                    nl("return Byte.parseByte(str);")
+                }
+                block("catch (NumberFormatException e)") {
+                    nl("return fallback;")
+                }
+            }
+            block("public static short parse(String str, short fallback)") {
+                block("try") {
+                    nl("return Short.parseShort(str);")
+                }
+                block("catch (NumberFormatException e)") {
+                    nl("return fallback;")
+                }
+            }
+            block("public static int parse(String str, int fallback)") {
+                block("try") {
+                    nl("return Integer.parseInt(str);")
+                }
+                block("catch (NumberFormatException e)") {
+                    nl("return fallback;")
+                }
+            }
+            block("public static long parse(String str, long fallback)") {
+                block("try") {
+                    nl("return Long.parseLong(str);")
+                }
+                block("catch (NumberFormatException e)") {
+                    nl("return fallback;")
+                }
+            }
+            block("public static float parse(String str, float fallback)") {
+                block("try") {
+                    nl("return Float.parseFloat(str);")
+                }
+                block("catch (NumberFormatException e)") {
+                    nl("return fallback;")
+                }
+            }
+            block("public static double parse(String str, double fallback)") {
+                block("try") {
+                    nl("return Double.parseDouble(str);")
+                }
+                block("catch (NumberFormatException e)") {
+                    nl("return fallback;")
+                }
+            }
+            block("public static char parse(String str, char fallback)") {
+                block ("if (str == null || str.isEmpty())") {
+                    nl("return fallback;")
+                }
+                nl("return str.charAt(0);")
+            }
         }
-        tab("}")
-        nl("}")
-    }
+   }
 }
\ No newline at end of file
diff --git a/compiler/src/main/kotlin/android/databinding/tool/writer/KCode.kt b/compiler/src/main/kotlin/android/databinding/tool/writer/KCode.kt
index a9b282a..98438f6 100644
--- a/compiler/src/main/kotlin/android/databinding/tool/writer/KCode.kt
+++ b/compiler/src/main/kotlin/android/databinding/tool/writer/KCode.kt
@@ -38,24 +38,24 @@
             while (indentCache.size <= n) {
                 indentCache.add("");
             }
-            indentCache[n] = s
+            indentCache.set(n, s)
             return s
         }
     }
 
     fun isNull(kcode : KCode?) = kcode == null || (kcode.nodes.isEmpty() && (kcode.s == null || kcode.s.trim() == ""))
 
-    fun tab(vararg codes : KCode?) : KCode {
+    public fun tab(vararg codes : KCode?) : KCode {
         codes.forEach { tab(it) }
         return this
     }
 
-    fun tab(codes : Collection<KCode?> ) : KCode {
+    public fun tab(codes : Collection<KCode?> ) : KCode {
         codes.forEach { tab(it) }
         return this
     }
 
-    infix fun tab(s : String?, init : (KCode.() -> Unit)? = null) : KCode {
+    fun tab(s : String?, init : (KCode.() -> Unit)? = null) : KCode {
         val c = KCode(s)
         if (init != null) {
             c.init()
@@ -80,7 +80,7 @@
         return this
     }
 
-    infix fun nl(s : String?, init : (KCode.() -> Unit)? = null) : KCode {
+    fun nl(s : String?, init : (KCode.() -> Unit)? = null) : KCode {
         val c = KCode(s)
         if (init != null) {
             c.init()
@@ -88,6 +88,18 @@
         return nl(c)
     }
 
+    fun block(s : String, init : (KCode.() -> Unit)? = null) : KCode {
+        val c = KCode()
+        if (init != null) {
+            c.init()
+        }
+        return nl(s) {
+            app(" {")
+            tab(c)
+            nl("}")
+        }
+    }
+
     fun app(glue : String = "", c : KCode?) : KCode {
         if (isNull(c)) {
             return this
@@ -125,9 +137,13 @@
                 val childTab = n + (if(it.sameLine) 0 else 1)
                 if (addedChild || newlineFirstNode) {
                     sb.append(lineSeparator)
-                    sb.append("${indent(childTab)}")
                 }
-                it.toS(childTab, sb)
+                if (!isNull(it)) { // avoid spaces for empty lines
+                    if (it.s != null && it.s.trim() != "") {
+                        sb.append("${indent(childTab)}")
+                    }
+                    it.toS(childTab, sb)
+                }
                 addedChild = true
             }
         } }
@@ -147,4 +163,4 @@
         c.init()
     }
     return c
-}
+}
\ No newline at end of file
diff --git a/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt b/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt
index 690a4d6..30b2583 100644
--- a/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt
+++ b/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt
@@ -13,16 +13,22 @@
 
 package android.databinding.tool.writer
 
+import android.databinding.tool.Binding
 import android.databinding.tool.BindingTarget
+import android.databinding.tool.CallbackWrapper
 import android.databinding.tool.InverseBinding
 import android.databinding.tool.LayoutBinder
 import android.databinding.tool.expr.Expr
 import android.databinding.tool.expr.ExprModel
 import android.databinding.tool.expr.FieldAccessExpr
 import android.databinding.tool.expr.IdentifierExpr
+import android.databinding.tool.expr.LambdaExpr
 import android.databinding.tool.expr.ListenerExpr
 import android.databinding.tool.expr.ResourceExpr
 import android.databinding.tool.expr.TernaryExpr
+import android.databinding.tool.expr.localizeGlobalVariables
+import android.databinding.tool.expr.shouldLocalizeInCallbacks
+import android.databinding.tool.expr.toCode
 import android.databinding.tool.ext.androidId
 import android.databinding.tool.ext.br
 import android.databinding.tool.ext.joinToCamelCaseAsVar
@@ -30,7 +36,9 @@
 import android.databinding.tool.ext.versionedLazy
 import android.databinding.tool.processing.ErrorMessages
 import android.databinding.tool.reflection.ModelAnalyzer
+import android.databinding.tool.reflection.ModelClass
 import android.databinding.tool.util.L
+import android.databinding.tool.util.Preconditions
 import java.util.ArrayList
 import java.util.Arrays
 import java.util.BitSet
@@ -39,11 +47,30 @@
 fun String.stripNonJava() = this.split("[^a-zA-Z0-9]".toRegex()).map{ it.trim() }.joinToCamelCaseAsVar()
 
 enum class Scope {
+    GLOBAL,
     FIELD,
     METHOD,
     FLAG,
     EXECUTE_PENDING_METHOD,
-    CONSTRUCTOR_PARAM
+    CONSTRUCTOR_PARAM,
+    CALLBACK;
+    companion object {
+        var currentScope = GLOBAL;
+        private val scopeStack = arrayListOf<Scope>()
+        fun enter(scope : Scope) {
+            scopeStack.add(currentScope)
+            currentScope = scope
+        }
+
+        fun exit() {
+            currentScope = scopeStack.removeAt(scopeStack.size - 1)
+        }
+
+        fun reset() {
+            scopeStack.clear()
+            currentScope = GLOBAL
+        }
+    }
 }
 
 class ExprModelExt {
@@ -51,6 +78,9 @@
     init {
         Scope.values().forEach { usedFieldNames[it] = hashSetOf<String>() }
     }
+
+    internal val forceLocalize = hashSetOf<Expr>()
+
     val localizedFlags = arrayListOf<FlagSet>()
 
     fun localizeFlag(set : FlagSet, name:String) : FlagSet {
@@ -66,6 +96,9 @@
             candidateBase = candidateBase.substring(0, 20);
         }
         var candidate = candidateBase
+        if (scope == Scope.CALLBACK || scope == Scope.EXECUTE_PENDING_METHOD) {
+            candidate = candidate.decapitalize()
+        }
         var i = 0
         while (usedFieldNames[scope]!!.contains(candidate)) {
             i ++
@@ -76,20 +109,17 @@
     }
 }
 
-val ExprModel.ext by lazyProp { target : ExprModel ->
-    ExprModelExt()
-}
-
+fun ModelClass.defaultValue() = ModelAnalyzer.getInstance().getDefaultValue(toJavaCode())
 fun ExprModel.getUniqueFieldName(base : String, isPublic : kotlin.Boolean) : String = ext.getUniqueName(base, Scope.FIELD, isPublic)
 fun ExprModel.getUniqueMethodName(base : String, isPublic : kotlin.Boolean) : String = ext.getUniqueName(base, Scope.METHOD, isPublic)
 fun ExprModel.getConstructorParamName(base : String) : String = ext.getUniqueName(base, Scope.CONSTRUCTOR_PARAM, false)
-
 fun ExprModel.localizeFlag(set : FlagSet, base : String) : FlagSet = ext.localizeFlag(set, base)
 
 val Expr.needsLocalField by lazyProp { expr : Expr ->
     expr.canBeEvaluatedToAVariable() && !(expr.isVariable() && !expr.isUsed) && (expr.isDynamic || expr is ResourceExpr)
 }
 
+fun Expr.isForcedToLocalize() = model.ext.forceLocalize.contains(this)
 
 // not necessarily unique. Uniqueness is solved per scope
 val BindingTarget.readableName by lazyProp { target: BindingTarget ->
@@ -143,7 +173,7 @@
 
 // not necessarily unique. Uniqueness is decided per scope
 val Expr.readableName by lazyProp { expr : Expr ->
-    val stripped = "${expr.uniqueKey.stripNonJava()}"
+    val stripped = expr.uniqueKey.stripNonJava()
     L.d("readableUniqueName for [%s] %s is %s", System.identityHashCode(expr), expr.uniqueKey, stripped)
     stripped
 }
@@ -166,8 +196,18 @@
     expr.model.getUniqueFieldName("mOld${expr.readableName.capitalize()}", false)
 }
 
+fun Expr.scopedName() : String = when(Scope.currentScope) {
+    Scope.CALLBACK -> callbackLocalName
+    else -> executePendingLocalName
+}
+
+val Expr.callbackLocalName by lazyProp { expr : Expr ->
+    if(expr.shouldLocalizeInCallbacks()) "${expr.model.ext.getUniqueName(expr.readableName, Scope.CALLBACK, false)}"
+    else expr.toCode().generate()
+}
+
 val Expr.executePendingLocalName by lazyProp { expr : Expr ->
-    if(expr.needsLocalField) "${expr.model.ext.getUniqueName(expr.readableName, Scope.EXECUTE_PENDING_METHOD, false)}"
+    if(expr.isDynamic || expr.needsLocalField) "${expr.model.ext.getUniqueName(expr.readableName, Scope.EXECUTE_PENDING_METHOD, false)}"
     else expr.toCode().generate()
 }
 
@@ -206,6 +246,17 @@
             FlagSet(expr.getRequirementFlagIndex(true)))
 }
 
+fun Binding.toAssignmentCode() : String {
+    val fieldName: String
+    if (this.target.viewClass.
+            equals(this.target.interfaceType)) {
+        fieldName = "this.${this.target.fieldName}"
+    } else {
+        fieldName = "((${this.target.viewClass}) this.${this.target.fieldName})"
+    }
+    return this.toJavaCode(fieldName, "this.mBindingComponent")
+}
+
 val LayoutBinder.requiredComponent by lazyProp { layoutBinder: LayoutBinder ->
     val requiredFromBindings = layoutBinder.
             bindingTargets.
@@ -287,10 +338,15 @@
     }
 
     val usedVariables by lazy {
-        variables.filter {it.isUsed }
+        variables.filter {it.isUsed || it.isIsUsedInCallback }
+    }
+
+    val callbacks by lazy {
+        model.exprMap.values.filterIsInstance(LambdaExpr::class.java)
     }
 
     public fun write(minSdk : kotlin.Int) : String  {
+        Scope.reset()
         layoutBinder.resolveWhichExpressionsAreUsed()
         calculateIndices();
         return kcode("package ${layoutBinder.`package`};") {
@@ -303,33 +359,56 @@
             } else {
                 classDeclaration = "$className extends android.databinding.ViewDataBinding"
             }
-            nl("public class $classDeclaration {") {
-                tab(declareIncludeViews())
-                tab(declareViews())
-                tab(declareVariables())
-                tab(declareBoundValues())
-                tab(declareListeners())
-                tab(declareInverseBindingImpls());
-                tab(declareConstructor(minSdk))
-                tab(declareInvalidateAll())
-                tab(declareHasPendingBindings())
-                tab(declareSetVariable())
-                tab(variableSettersAndGetters())
-                tab(onFieldChange())
-
-                tab(executePendingBindings())
-
-                tab(declareListenerImpls())
-                tab(declareDirtyFlags())
-                if (!layoutBinder.hasVariations()) {
-                    tab(declareFactories())
+            block("public class $classDeclaration ${buildImplements()}") {
+                nl(declareIncludeViews())
+                nl(declareViews())
+                nl(declareVariables())
+                nl(declareBoundValues())
+                nl(declareListeners())
+                try {
+                    Scope.enter(Scope.GLOBAL)
+                    nl(declareInverseBindingImpls());
+                } finally {
+                    Scope.exit()
                 }
+                nl(declareConstructor(minSdk))
+                nl(declareInvalidateAll())
+                nl(declareHasPendingBindings())
+                nl(declareSetVariable())
+                nl(variableSettersAndGetters())
+                nl(onFieldChange())
+                try {
+                    Scope.enter(Scope.GLOBAL)
+                    nl(executePendingBindings())
+                } finally {
+                    Scope.exit()
+                }
+
+                nl(declareListenerImpls())
+                try {
+                    Scope.enter(Scope.CALLBACK)
+                    nl(declareCallbackImplementations())
+                } finally {
+                    Scope.exit()
+                }
+
+                nl(declareDirtyFlags())
+                if (!layoutBinder.hasVariations()) {
+                    nl(declareFactories())
+                }
+                nl(flagMapping())
+                nl("//end")
             }
-            nl("}")
-            tab(flagMapping())
-            tab("//end")
         }.generate()
     }
+    fun buildImplements() : String {
+        return if (callbacks.isEmpty()) {
+            ""
+        } else {
+            "implements " + callbacks.map { it.callbackWrapper.cannonicalListenerName }.distinct().joinToString(", ")
+        }
+    }
+
     fun calculateIndices() : Unit {
         val taggedViews = layoutBinder.bindingTargets.filter{
             it.isUsed && it.tag != null && !it.isBinder
@@ -481,10 +560,76 @@
             }
         }
         tab("setRootTag(root);")
+        tab(declareCallbackInstances())
         tab("invalidateAll();");
         nl("}")
     }
 
+    fun declareCallbackInstances() = kcode("// listeners") {
+        callbacks.groupBy { it.callbackWrapper.minApi }
+                .forEach {
+                    if (it.key > 1) {
+                        block("if(getBuildSdkInt() < ${it.key})") {
+                            it.value.forEach { lambda ->
+                                nl("${lambda.fieldName} = null;")
+                            }
+                        }
+                        block("else") {
+                            it.value.forEach { lambda ->
+                                nl("${lambda.fieldName} = ${lambda.generateConstructor()};")
+                            }
+                        }
+                    } else {
+                        it.value.forEach { lambda ->
+                            nl("${lambda.fieldName} = ${lambda.generateConstructor()};")
+                        }
+                    }
+                }
+    }
+
+    fun declareCallbackImplementations() = kcode("// callback impls") {
+        callbacks.groupBy { it.callbackWrapper }.forEach {
+            val wrapper = it.key
+            val lambdas = it.value
+            val shouldReturn = !wrapper.method.returnType.isVoid
+            if (shouldReturn) {
+                lambdas.forEach {
+                    it.callbackExprModel.ext.forceLocalize.add(it.expr)
+                }
+            }
+            block("public final ${wrapper.method.returnType.canonicalName} ${wrapper.listenerMethodName}(${wrapper.allArgsWithTypes()})") {
+                Preconditions.check(lambdas.size > 0, "bindings list should not be empty")
+                if (lambdas.size == 1) {
+                    val lambda = lambdas[0]
+                    nl(lambda.callbackExprModel.localizeGlobalVariables(lambda))
+                    nl(lambda.executionPath.toCode())
+                    if (shouldReturn) {
+                        nl("return ${lambda.expr.scopedName()};")
+                    }
+                } else {
+                    block("switch(${CallbackWrapper.SOURCE_ID})") {
+                        lambdas.forEach { lambda ->
+                            block("case ${lambda.callbackId}:") {
+                                nl(lambda.callbackExprModel.localizeGlobalVariables(lambda))
+                                nl(lambda.executionPath.toCode())
+                                if (shouldReturn) {
+                                    nl("return ${lambda.expr.scopedName()};")
+                                } else {
+                                    nl("break;")
+                                }
+                            }
+                        }
+                        if (shouldReturn) {
+                            block("default:") {
+                                nl("return ${wrapper.method.returnType.defaultValue()};")
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     fun fieldConversion(target : BindingTarget) : String {
         if (!target.isUsed) {
             return "null"
@@ -497,20 +642,19 @@
 
     fun declareInvalidateAll() = kcode("") {
         nl("@Override")
-        nl("public void invalidateAll() {") {
+        block("public void invalidateAll()") {
             val fs = FlagSet(layoutBinder.model.invalidateAnyBitSet,
                     layoutBinder.model.flagBucketCount);
-            tab("synchronized(this) {") {
+            block("synchronized(this)") {
                 for (i in (0..(mDirtyFlags.buckets.size - 1))) {
                     tab("${mDirtyFlags.localValue(i)} = ${fs.localValue(i)};")
                 }
-            } tab("}")
-            includedBinders.filter{it.isUsed }.forEach { binder ->
-                tab("${binder.fieldName}.invalidateAll();")
             }
-            tab("requestRebind();");
+            includedBinders.filter{it.isUsed }.forEach { binder ->
+                nl("${binder.fieldName}.invalidateAll();")
+            }
+            nl("requestRebind();");
         }
-        nl("}")
     }
 
     fun declareHasPendingBindings()  = kcode("") {
@@ -548,7 +692,7 @@
                         tab("return true;")
                     }
                 }
-                val declaredOnly = variables.filter { !it.isUsed && it.isDeclared };
+                val declaredOnly = variables.filter { !it.isUsed && !it.isIsUsedInCallback && it.isDeclared };
                 declaredOnly.forEachIndexed { i, identifierExpr ->
                     tab ("case ${identifierExpr.name.br()} :") {
                         if (i == declaredOnly.size - 1) {
@@ -564,7 +708,7 @@
     }
 
     fun variableSettersAndGetters() = kcode("") {
-        variables.filterNot{it.isUsed }.forEach {
+        variables.filterNot{ usedVariables.contains(it) }.forEach {
             nl("public void ${it.setterName}(${it.resolvedType.toJavaCode()} ${it.readableName}) {") {
                 tab("// not used, ignore")
             }
@@ -577,30 +721,28 @@
         }
         usedVariables.forEach {
             if (it.userDefinedType != null) {
-                nl("public void ${it.setterName}(${it.resolvedType.toJavaCode()} ${it.readableName}) {") {
+                block("public void ${it.setterName}(${it.resolvedType.toJavaCode()} ${it.readableName})") {
                     if (it.isObservable) {
-                        tab("updateRegistration(${it.id}, ${it.readableName});");
+                        nl("updateRegistration(${it.id}, ${it.readableName});");
                     }
-                    tab("this.${it.fieldName} = ${it.readableName};")
+                    nl("this.${it.fieldName} = ${it.readableName};")
                     // set dirty flags!
                     val flagSet = it.invalidateFlagSet
-                    tab("synchronized(this) {") {
+                    block("synchronized(this)") {
                         mDirtyFlags.mapOr(flagSet) { suffix, index ->
-                            tab("${mDirtyFlags.localName}$suffix |= ${flagSet.localValue(index)};")
+                            nl("${mDirtyFlags.localName}$suffix |= ${flagSet.localValue(index)};")
                         }
-                    } tab ("}")
+                    }
                     // TODO: Remove this condition after releasing version 1.1 of SDK
                     if (ModelAnalyzer.getInstance().findClass("android.databinding.ViewDataBinding", null).isObservable) {
-                        tab("notifyPropertyChanged(${it.name.br()});")
+                        nl("notifyPropertyChanged(${it.name.br()});")
                     }
-                    tab("super.requestRebind();")
+                    nl("super.requestRebind();")
                 }
-                nl("}")
                 nl("")
-                nl("public ${it.resolvedType.toJavaCode()} ${it.getterName}() {") {
-                    tab("return ${it.fieldName};")
+                block("public ${it.resolvedType.toJavaCode()} ${it.getterName}()") {
+                    nl("return ${it.fieldName};")
                 }
-                nl("}")
             }
         }
     }
@@ -622,42 +764,39 @@
         nl("")
 
         model.observables.forEach {
-            nl("private boolean ${it.onChangeName}(${it.resolvedType.toJavaCode()} ${it.readableName}, int fieldId) {") {
-                tab("switch (fieldId) {", {
+            block("private boolean ${it.onChangeName}(${it.resolvedType.toJavaCode()} ${it.readableName}, int fieldId)") {
+                block("switch (fieldId)", {
                     val accessedFields: List<FieldAccessExpr> = it.parents.filterIsInstance(FieldAccessExpr::class.java)
-                    accessedFields.filter { it.hasBindableAnnotations() }
+                    accessedFields.filter { it.isUsed && it.hasBindableAnnotations() }
                             .groupBy { it.brName }
                             .forEach {
                                 // If two expressions look different but resolve to the same method,
                                 // we are not yet able to merge them. This is why we merge their
                                 // flags below.
-                                tab("case ${it.key}:") {
-                                    tab("synchronized(this) {") {
+                                block("case ${it.key}:") {
+                                    block("synchronized(this)") {
                                         val flagSet = it.value.foldRight(FlagSet()) { l, r -> l.invalidateFlagSet.or(r) }
 
                                         mDirtyFlags.mapOr(flagSet) { suffix, index ->
                                             tab("${mDirtyFlags.localValue(index)} |= ${flagSet.localValue(index)};")
                                         }
-                                    } tab("}")
-                                    tab("return true;")
+                                    }
+                                    nl("return true;")
                                 }
 
                             }
-                    tab("case ${"".br()}:") {
+                    block("case ${"".br()}:") {
                         val flagSet = it.invalidateFlagSet
-                        tab("synchronized(this) {") {
+                        block("synchronized(this)") {
                             mDirtyFlags.mapOr(flagSet) { suffix, index ->
                                 tab("${mDirtyFlags.localName}$suffix |= ${flagSet.localValue(index)};")
                             }
-                        } tab("}")
-                        tab("return true;")
+                        }
+                        nl("return true;")
                     }
-
                 })
-                tab("}")
-                tab("return false;")
+                nl("return false;")
             }
-            nl("}")
             nl("")
         }
     }
@@ -679,13 +818,17 @@
         usedVariables.forEach {
             nl("private ${it.resolvedType.toJavaCode()} ${it.fieldName};")
         }
+        callbacks.forEach {
+            val wrapper = it.callbackWrapper
+            nl("private final ${wrapper.klass.canonicalName} ${it.fieldName}").app(";")
+        }
     }
 
     fun declareBoundValues() = kcode("// values") {
         layoutBinder.sortedTargets.filter { it.isUsed }
                 .flatMap { it.bindings }
                 .filter { it.requiresOldValue() }
-                .flatMap{ it.componentExpressions.toArrayList() }
+                .flatMap{ it.componentExpressions.toList() }
                 .groupBy { it }
                 .forEach {
                     val expr = it.key
@@ -714,14 +857,30 @@
                     className = "android.databinding.InverseBindingListener"
                     param = ""
                 }
-                nl("private $className ${inverseBinding.fieldName} = new $className($param) {") {
-                    tab("@Override")
-                    tab("public void onChange() {") {
-                        tab(inverseBinding.toJavaCode("mBindingComponent", mDirtyFlags)).app(";");
+                block("private $className ${inverseBinding.fieldName} = new $className($param)") {
+                    nl("@Override")
+                    block("public void onChange()") {
+                        if (inverseBinding.inverseExpr != null) {
+                            val valueExpr = inverseBinding.variableExpr
+                            val getterCall = inverseBinding.getterCall
+                            nl("// Inverse of ${inverseBinding.expr}")
+                            nl("//         is ${inverseBinding.inverseExpr}")
+                            nl("${valueExpr.resolvedType.toJavaCode()} ${valueExpr.name} = ${getterCall.toJava("mBindingComponent", target.fieldName)};")
+                            nl(inverseBinding.callbackExprModel.localizeGlobalVariables(valueExpr))
+                            nl(inverseBinding.executionPath.toCode())
+                        } else {
+                            block("synchronized(this)") {
+                                val flagSet = inverseBinding.chainedExpressions.fold(FlagSet(), { initial, expr ->
+                                    initial.or(FlagSet(expr.id))
+                                })
+                                mDirtyFlags.mapOr(flagSet) { suffix, index ->
+                                    tab("${mDirtyFlags.localValue(index)} |= ${flagSet.binaryCode(index)};")
+                                }
+                            }
+                            nl("requestRebind();")
+                        }
                     }
-                    tab("}")
-                }
-                nl("};")
+                }.app(";")
             }
         }
     }
@@ -739,7 +898,7 @@
         if (model.flagMapping != null) {
             val mapping = model.flagMapping
             for (i in mapping.indices) {
-                tab("flag $i: ${mapping[i]}")
+                tab("flag $i (${longToBinary(1L + i)}): ${model.findFlagExpression(i)}")
             }
         }
         nl("flag mapping end*/")
@@ -747,24 +906,24 @@
 
     fun executePendingBindings() = kcode("") {
         nl("@Override")
-        nl("protected void executeBindings() {") {
+        block("protected void executeBindings()") {
             val tmpDirtyFlags = FlagSet(mDirtyFlags.buckets)
             tmpDirtyFlags.localName = "dirtyFlags";
             for (i in (0..mDirtyFlags.buckets.size - 1)) {
-                tab("${tmpDirtyFlags.type} ${tmpDirtyFlags.localValue(i)} = 0;")
+                nl("${tmpDirtyFlags.type} ${tmpDirtyFlags.localValue(i)} = 0;")
             }
-            tab("synchronized(this) {") {
+            block("synchronized(this)") {
                 for (i in (0..mDirtyFlags.buckets.size - 1)) {
-                    tab("${tmpDirtyFlags.localValue(i)} = ${mDirtyFlags.localValue(i)};")
-                    tab("${mDirtyFlags.localValue(i)} = 0;")
+                    nl("${tmpDirtyFlags.localValue(i)} = ${mDirtyFlags.localValue(i)};")
+                    nl("${mDirtyFlags.localValue(i)} = 0;")
                 }
-            } tab("}")
+            }
             model.pendingExpressions.filter { it.needsLocalField }.forEach {
-                tab("${it.resolvedType.toJavaCode()} ${it.executePendingLocalName} = ${if (it.isVariable()) it.fieldName else it.defaultValue};")
+                nl("${it.resolvedType.toJavaCode()} ${it.executePendingLocalName} = ${if (it.isVariable()) it.fieldName else it.defaultValue};")
             }
             L.d("writing executePendingBindings for %s", className)
             do {
-                val batch = ExprModel.filterShouldRead(model.pendingExpressions).toArrayList()
+                val batch = ExprModel.filterShouldRead(model.pendingExpressions)
                 val justRead = arrayListOf<Expr>()
                 L.d("batch: %s", batch)
                 while (!batch.none()) {
@@ -776,10 +935,10 @@
                     nl(readWithDependants(readNow, justRead, batch, tmpDirtyFlags))
                     batch.removeAll(justRead)
                 }
-                tab("// batch finished")
+                nl("// batch finished")
             } while (model.markBitsRead())
             // verify everything is read.
-            val batch = ExprModel.filterShouldRead(model.pendingExpressions).toArrayList()
+            val batch = ExprModel.filterShouldRead(model.pendingExpressions)
             if (batch.isNotEmpty()) {
                 L.e("could not generate code for %s. This might be caused by circular dependencies."
                         + "Please report on b.android.com. %d %s %s", layoutBinder.layoutname,
@@ -793,32 +952,23 @@
                             "(${tmpDirtyFlags.localValue(index)} & ${it.expr.dirtyFlagSet.localValue(index)}) != 0"
                         }.joinToString(" || ") }"
                     }.forEach {
-                tab("if (${it.key}) {") {
+                block("if (${it.key})") {
                     it.value.groupBy { Math.max(1, it.minApi) }.forEach {
                         val setterValues = kcode("") {
                             it.value.forEach { binding ->
-                                val fieldName: String
-                                if (binding.target.viewClass.
-                                        equals(binding.target.interfaceType)) {
-                                    fieldName = "this.${binding.target.fieldName}"
-                                } else {
-                                    fieldName = "((${binding.target.viewClass}) this.${binding.target.fieldName})"
-                                }
-                                tab(binding.toJavaCode(fieldName, "this.mBindingComponent")).app(";")
+                                nl(binding.toAssignmentCode()).app(";")
                             }
                         }
-                        tab("// api target ${it.key}")
+                        nl("// api target ${it.key}")
                         if (it.key > 1) {
-                            tab("if(getBuildSdkInt() >= ${it.key}) {") {
-                                app("", setterValues)
+                            block("if(getBuildSdkInt() >= ${it.key})") {
+                                nl(setterValues)
                             }
-                            tab("}")
                         } else {
-                            app("", setterValues)
+                            nl(setterValues)
                         }
                     }
                 }
-                tab("}")
             }
 
 
@@ -829,28 +979,25 @@
                         "(${tmpDirtyFlags.localValue(index)} & ${it.expr.dirtyFlagSet.localValue(index)}) != 0"
                     }.joinToString(" || ")
                     }"}.forEach {
-                tab("if (${it.key}) {") {
+                block("if (${it.key})") {
                     it.value.groupBy { it.expr }.map { it.value.first() }.forEach {
                         it.componentExpressions.forEach { expr ->
-                            tab("this.${expr.oldValueName} = ${expr.toCode().generate()};")
+                            nl("this.${expr.oldValueName} = ${expr.toCode().generate()};")
                         }
                     }
                 }
-                tab("}")
             }
             includedBinders.filter{it.isUsed }.forEach { binder ->
-                tab("${binder.fieldName}.executePendingBindings();")
+                nl("${binder.fieldName}.executePendingBindings();")
             }
             layoutBinder.sortedTargets.filter{
                 it.isUsed && it.resolvedType != null && it.resolvedType.extendsViewStub()
             }.forEach {
-                tab("if (${it.fieldName}.getBinding() != null) {") {
-                    tab("${it.fieldName}.getBinding().executePendingBindings();")
+                block("if (${it.fieldName}.getBinding() != null)") {
+                    nl("${it.fieldName}.getBinding().executePendingBindings();")
                 }
-                tab("}")
             }
         }
-        nl("}")
     }
 
     fun readWithDependants(expressionList: List<Expr>, justRead: MutableList<Expr>,
@@ -872,7 +1019,7 @@
                     if (!assignedValues.isEmpty()) {
                         val assignment = kcode("") {
                             assignedValues.forEach { expr: Expr ->
-                                tab("// read ${expr.uniqueKey}")
+                                tab("// read ${expr}")
                                 tab("${expr.executePendingLocalName}").app(" = ", expr.toFullCode()).app(";")
                             }
                         }
@@ -891,7 +1038,7 @@
 
                     it.value.forEach { expr: Expr ->
                         justRead.add(expr)
-                        L.d("%s / readWithDependants %s", className, expr.uniqueKey);
+                        L.d("%s / readWithDependants %s", className, expr);
                         L.d("flag set:%s . inherited flags: %s. need another if: %s", flagSet, inheritedFlags, needsIfWrapper);
 
                         // if I am the condition for an expression, set its flag
@@ -973,13 +1120,11 @@
             }
 
             if (needsIfWrapper) {
-                tab(ifClause) {
-                    app(" {")
-                    app("", readCode)
+                block(ifClause) {
+                    nl(readCode)
                 }
-                tab("}")
             } else {
-                app("", readCode)
+                nl(readCode)
             }
         }
     }
@@ -1013,9 +1158,9 @@
                 extendsImplements = "extends"
             }
             nl("public static class ${expr.listenerClassName} $extendsImplements ${listenerType.canonicalName}{") {
-                if (expr.child.isDynamic) {
-                    tab("private ${expr.child.resolvedType.toJavaCode()} value;")
-                    tab("public ${expr.listenerClassName} setValue(${expr.child.resolvedType.toJavaCode()} value) {") {
+                if (expr.target.isDynamic) {
+                    tab("private ${expr.target.resolvedType.toJavaCode()} value;")
+                    tab("public ${expr.listenerClassName} setValue(${expr.target.resolvedType.toJavaCode()} value) {") {
                         tab("this.value = value;")
                         tab("return value == null ? null : this;")
                     }
@@ -1023,7 +1168,7 @@
                 }
                 val listenerMethod = expr.method
                 val parameterTypes = listenerMethod.parameterTypes
-                val returnType = listenerMethod.getReturnType(parameterTypes.toArrayList())
+                val returnType = listenerMethod.getReturnType(parameterTypes.toList())
                 tab("@Override")
                 tab("public $returnType ${listenerMethod.name}(${
                     parameterTypes.withIndex().map {
@@ -1031,10 +1176,10 @@
                     }.joinToString(", ")
                 }) {") {
                     val obj : String
-                    if (expr.child.isDynamic) {
+                    if (expr.target.isDynamic) {
                         obj = "this.value"
                     } else {
-                        obj = expr.child.toCode().generate();
+                        obj = expr.target.toCode().generate();
                     }
                     val returnStr : String
                     if (!returnType.isVoid) {
@@ -1054,35 +1199,28 @@
     }
 
     fun declareFactories() = kcode("") {
-        nl("public static $baseClassName inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot) {") {
-            tab("return inflate(inflater, root, attachToRoot, android.databinding.DataBindingUtil.getDefaultComponent());")
+        block("public static $baseClassName inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot)") {
+            nl("return inflate(inflater, root, attachToRoot, android.databinding.DataBindingUtil.getDefaultComponent());")
         }
-        nl("}")
-        nl("public static $baseClassName inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot, android.databinding.DataBindingComponent bindingComponent) {") {
-            tab("return android.databinding.DataBindingUtil.<$baseClassName>inflate(inflater, ${layoutBinder.modulePackage}.R.layout.${layoutBinder.layoutname}, root, attachToRoot, bindingComponent);")
+        block("public static $baseClassName inflate(android.view.LayoutInflater inflater, android.view.ViewGroup root, boolean attachToRoot, android.databinding.DataBindingComponent bindingComponent)") {
+            nl("return android.databinding.DataBindingUtil.<$baseClassName>inflate(inflater, ${layoutBinder.modulePackage}.R.layout.${layoutBinder.layoutname}, root, attachToRoot, bindingComponent);")
         }
-        nl("}")
         if (!layoutBinder.isMerge) {
-            nl("public static $baseClassName inflate(android.view.LayoutInflater inflater) {") {
-                tab("return inflate(inflater, android.databinding.DataBindingUtil.getDefaultComponent());")
+            block("public static $baseClassName inflate(android.view.LayoutInflater inflater)") {
+                nl("return inflate(inflater, android.databinding.DataBindingUtil.getDefaultComponent());")
             }
-            nl("}")
-            nl("public static $baseClassName inflate(android.view.LayoutInflater inflater, android.databinding.DataBindingComponent bindingComponent) {") {
-                tab("return bind(inflater.inflate(${layoutBinder.modulePackage}.R.layout.${layoutBinder.layoutname}, null, false), bindingComponent);")
+            block("public static $baseClassName inflate(android.view.LayoutInflater inflater, android.databinding.DataBindingComponent bindingComponent)") {
+                nl("return bind(inflater.inflate(${layoutBinder.modulePackage}.R.layout.${layoutBinder.layoutname}, null, false), bindingComponent);")
             }
-            nl("}")
-            nl("public static $baseClassName bind(android.view.View view) {") {
-                tab("return bind(view, android.databinding.DataBindingUtil.getDefaultComponent());")
+            block("public static $baseClassName bind(android.view.View view)") {
+                nl("return bind(view, android.databinding.DataBindingUtil.getDefaultComponent());")
             }
-            nl("}")
-            nl("public static $baseClassName bind(android.view.View view, android.databinding.DataBindingComponent bindingComponent) {") {
-                tab("if (!\"${layoutBinder.tag}_0\".equals(view.getTag())) {") {
-                    tab("throw new RuntimeException(\"view tag isn't correct on view:\" + view.getTag());")
+            block("public static $baseClassName bind(android.view.View view, android.databinding.DataBindingComponent bindingComponent)") {
+                block("if (!\"${layoutBinder.tag}_0\".equals(view.getTag()))") {
+                    nl("throw new RuntimeException(\"view tag isn't correct on view:\" + view.getTag());")
                 }
-                tab("}")
-                tab("return new $baseClassName(bindingComponent, view);")
+                nl("return new $baseClassName(bindingComponent, view);")
             }
-            nl("}")
         }
     }
 
@@ -1091,6 +1229,7 @@
      */
     public fun writeBaseClass(forLibrary : Boolean) : String =
         kcode("package ${layoutBinder.`package`};") {
+            Scope.reset()
             nl("import android.databinding.Bindable;")
             nl("import android.databinding.DataBindingUtil;")
             nl("import android.databinding.ViewDataBinding;")
diff --git a/compiler/src/test/java/android/databinding/BindingExpressionParserTest.java b/compiler/src/test/java/android/databinding/BindingExpressionParserTest.java
index 9282479..419f1b0 100644
--- a/compiler/src/test/java/android/databinding/BindingExpressionParserTest.java
+++ b/compiler/src/test/java/android/databinding/BindingExpressionParserTest.java
@@ -15,6 +15,7 @@
  */
 package android.databinding;
 
+import android.databinding.parser.BindingExpressionBaseVisitor;
 import android.databinding.parser.BindingExpressionLexer;
 import android.databinding.parser.BindingExpressionParser;
 import android.databinding.parser.BindingExpressionParser.AndOrOpContext;
@@ -39,6 +40,7 @@
 import org.antlr.v4.runtime.ANTLRInputStream;
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.misc.NotNull;
 import org.antlr.v4.runtime.tree.TerminalNode;
 import org.junit.Test;
 
@@ -141,14 +143,6 @@
     }
 
     @Test
-    public void testVoidExtraction() throws Exception {
-        PrimaryContext primary = parsePrimary("void.class");
-        assertNotNull(primary.classExtraction());
-        assertNull(primary.classExtraction().type());
-        assertEquals("void", primary.classExtraction().getChild(0).getText());
-    }
-
-    @Test
     public void testPrimitiveClassExtraction() throws Exception {
         PrimaryContext primary = parsePrimary("int.class");
         PrimitiveTypeContext type = primary.classExtraction().type().primitiveType();
@@ -255,7 +249,14 @@
     @Test
     public void testDefaults() throws Exception {
         BindingSyntaxContext syntax = parseExpressionString("foo.bar, default = @id/foo_bar");
-        DefaultsContext defaults = syntax.defaults();
+        BindingExpressionParser.DefaultsContext defaults = syntax
+                .accept(new BindingExpressionBaseVisitor<DefaultsContext>() {
+                    @Override
+                    public BindingExpressionParser.DefaultsContext visitDefaults(
+                            @NotNull BindingExpressionParser.DefaultsContext ctx) {
+                        return ctx;
+                    }
+                });
         assertEquals("@id/foo_bar", defaults.constantValue().ResourceReference().getText());
     }
 
@@ -364,8 +365,13 @@
     }
 
     private <T extends ExpressionContext> T parseExpression(String value) throws Exception {
-        ExpressionContext expressionContext = parse(value).expression();
-        return (T) expressionContext;
+        return (T) parse(value).accept(new BindingExpressionBaseVisitor<ExpressionContext>() {
+            @Override
+            public ExpressionContext visitRootExpr(
+                    @NotNull BindingExpressionParser.RootExprContext ctx) {
+                return ctx.expression();
+            }
+        });
     }
 
     private PrimaryContext parsePrimary(String value) throws Exception {
diff --git a/compiler/src/test/java/android/databinding/tool/ExpressionVisitorTest.java b/compiler/src/test/java/android/databinding/tool/ExpressionVisitorTest.java
index 97331cf..3d3d8fe 100644
--- a/compiler/src/test/java/android/databinding/tool/ExpressionVisitorTest.java
+++ b/compiler/src/test/java/android/databinding/tool/ExpressionVisitorTest.java
@@ -51,7 +51,7 @@
     }
 
     private <T extends Expr> T parse(String input, Class<T> klass) {
-        final Expr parsed = mParser.parse(input, null);
+        final Expr parsed = mParser.parse(input, null, null);
         assertSame(klass, parsed.getClass());
         return (T) parsed;
     }
@@ -89,7 +89,7 @@
 
         @Test
         public void testComparison() {
-            final Expr res = mParser.parse("3 " + mOp + " 5", null);
+            final Expr res = mParser.parse("3 " + mOp + " 5", null, null);
             assertEquals(3, mParser.getModel().size());
             assertTrue(res instanceof ComparisonExpr);
             // 0 because they are both static
@@ -143,8 +143,8 @@
     @Test
     public void testInheritedFieldResolution() {
         final FieldAccessExpr parsed = parse("myStr.length", FieldAccessExpr.class);
-        assertTrue(parsed.getChild() instanceof IdentifierExpr);
-        final IdentifierExpr id = (IdentifierExpr) parsed.getChild();
+        assertTrue(parsed.getTarget() instanceof IdentifierExpr);
+        final IdentifierExpr id = (IdentifierExpr) parsed.getTarget();
         id.setUserDefinedType("java.lang.String");
         assertEquals(new JavaClass(int.class), parsed.getResolvedType());
         Callable getter = parsed.getGetter();
@@ -159,8 +159,8 @@
     @Test
     public void testGetterResolution() {
         final FieldAccessExpr parsed = parse("myStr.bytes", FieldAccessExpr.class);
-        assertTrue(parsed.getChild() instanceof IdentifierExpr);
-        final IdentifierExpr id = (IdentifierExpr) parsed.getChild();
+        assertTrue(parsed.getTarget() instanceof IdentifierExpr);
+        final IdentifierExpr id = (IdentifierExpr) parsed.getTarget();
         id.setUserDefinedType("java.lang.String");
         assertEquals(new JavaClass(byte[].class), parsed.getResolvedType());
         Callable getter = parsed.getGetter();
@@ -180,7 +180,7 @@
         assertEquals(0, parsed.getArgs().size());
         assertEquals(1, parsed.getDependencies().size());
         final Dependency dep = parsed.getDependencies().get(0);
-        assertSame(mParser.parse("user", null), dep.getOther());
+        assertSame(mParser.parse("user", null, null), dep.getOther());
         assertFalse(dep.isConditional());
     }
 
diff --git a/compiler/src/test/java/android/databinding/tool/LayoutBinderTest.java b/compiler/src/test/java/android/databinding/tool/LayoutBinderTest.java
index 8b1f820..564ecef 100644
--- a/compiler/src/test/java/android/databinding/tool/LayoutBinderTest.java
+++ b/compiler/src/test/java/android/databinding/tool/LayoutBinderTest.java
@@ -77,8 +77,8 @@
         int originalSize = mExprModel.size();
         mLayoutBinder.addVariable("user", "android.databinding.tool2.LayoutBinderTest.TestUser",
                 null);
-        mLayoutBinder.parse("user.name", false, null);
-        mLayoutBinder.parse("user.lastName", false, null);
+        mLayoutBinder.parse("user.name", null, null);
+        mLayoutBinder.parse("user.lastName", null, null);
         assertEquals(originalSize + 3, mExprModel.size());
         final List<Expr> bindingExprs = mExprModel.getBindingExpressions();
         assertEquals(2, bindingExprs.size());
@@ -94,7 +94,7 @@
     public void testParseWithMethods() {
         mLayoutBinder.addVariable("user", "android.databinding.tool.LayoutBinderTest.TestUser",
                 null);
-        mLayoutBinder.parse("user.fullName", false, null);
+        mLayoutBinder.parse("user.fullName", null, null);
         Expr item = mExprModel.getBindingExpressions().get(0);
         assertTrue(item instanceof FieldAccessExpr);
         IdentifierExpr id = mExprModel.identifier("user");
@@ -102,7 +102,7 @@
         fa.getResolvedType();
         final Callable getter = fa.getGetter();
         assertTrue(getter.type == Callable.Type.METHOD);
-        assertSame(id, fa.getChild());
+        assertSame(id, fa.getTarget());
         assertTrue(fa.isDynamic());
     }
 
diff --git a/compiler/src/test/java/android/databinding/tool/expr/ExecutionPathTest.java b/compiler/src/test/java/android/databinding/tool/expr/ExecutionPathTest.java
new file mode 100644
index 0000000..d6fb470
--- /dev/null
+++ b/compiler/src/test/java/android/databinding/tool/expr/ExecutionPathTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.databinding.tool.expr;
+
+
+import android.databinding.tool.MockLayoutBinder;
+import android.databinding.tool.reflection.java.JavaAnalyzer;
+import android.databinding.tool.solver.ExecutionPath;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(Parameterized.class)
+public class ExecutionPathTest {
+
+    private final String mExpression;
+
+    public ExecutionPathTest(String expression) {
+        mExpression = expression;
+    }
+
+
+    @Parameterized.Parameters
+    public static List<String> expressions() {
+        return Arrays.asList("a.b(3/2)",
+                "a ? (a ? b : c) : d",
+                "a ? (b ? d : f) : g",
+                "5 + 4 / 3 + 2 + 7 * 8",
+                "a ? b : c");
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        JavaAnalyzer.initForTests();
+    }
+
+    @Test
+    public void simpleExpr() {
+        MockLayoutBinder lb = new MockLayoutBinder();
+        ExprModel model = lb.getModel();
+        Expr parsed = lb.parse(mExpression, null, null);
+        List<ExecutionPath> paths = new ArrayList<ExecutionPath>();
+        ExecutionPath root = ExecutionPath.createRoot();
+        paths.add(root);
+        List<ExecutionPath> result = parsed.toExecutionPath(paths);
+        StringBuilder sb = new StringBuilder();
+        root.debug(sb, 0);
+        sb.toString();
+    }
+}
diff --git a/compiler/src/test/java/android/databinding/tool/expr/ExprModelTest.java b/compiler/src/test/java/android/databinding/tool/expr/ExprModelTest.java
index 04813e1..a661c30 100644
--- a/compiler/src/test/java/android/databinding/tool/expr/ExprModelTest.java
+++ b/compiler/src/test/java/android/databinding/tool/expr/ExprModelTest.java
@@ -42,10 +42,12 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+@SuppressWarnings("Duplicates")
 public class ExprModelTest {
 
     private static class DummyExpr extends Expr {
@@ -73,11 +75,16 @@
         }
 
         @Override
-        protected KCode generateCode(boolean full) {
+        protected KCode generateCode() {
             return new KCode();
         }
 
         @Override
+        public Expr cloneToModel(ExprModel model) {
+            return this;
+        }
+
+        @Override
         protected String getInvertibleError() {
             return "DummyExpr cannot be 2-way.";
         }
@@ -147,7 +154,7 @@
         IdentifierExpr a = lb.addVariable("a", "java.lang.String", null);
         IdentifierExpr b = lb.addVariable("b", "java.lang.String", null);
         IdentifierExpr c = lb.addVariable("c", "java.lang.String", null);
-        lb.parse("a == null ? b : c", false, null);
+        lb.parse("a == null ? b : c", null, null);
         mExprModel.comparison("==", a, mExprModel.symbol("null", Object.class));
         lb.getModel().seal();
         List<Expr> shouldRead = getShouldRead();
@@ -296,7 +303,7 @@
         IdentifierExpr c = lb.addVariable("c", "java.lang.String", null);
         IdentifierExpr d = lb.addVariable("d", "java.lang.String", null);
         IdentifierExpr e = lb.addVariable("e", "java.lang.String", null);
-        final Expr aTernary = lb.parse("a == null ? b == null ? c : d : e", false, null);
+        final Expr aTernary = lb.parse("a == null ? b == null ? c : d : e", null, null);
         assertTrue(aTernary instanceof TernaryExpr);
         final Expr bTernary = ((TernaryExpr) aTernary).getIfTrue();
         assertTrue(bTernary instanceof TernaryExpr);
@@ -425,13 +432,10 @@
         assertTrue(mExprModel.markBitsRead());
 
         shouldRead = getShouldRead();
-        // FIXME: there is no real case to read u1 anymore because if b>c was not true,
-        // u1.getCond(d) will never be set. Right now, we don't have mechanism to figure this out
-        // and also it does not affect correctness (just an unnecessary if stmt)
-        assertExactMatch(shouldRead, u1, u2, u1LastName, u2LastName, bcTernary.getIfTrue(), bcTernary);
+
+        assertExactMatch(shouldRead, u2, u1LastName, u2LastName, bcTernary.getIfTrue(), bcTernary);
         firstRead = getReadFirst(shouldRead);
-        assertExactMatch(firstRead, u1, u2);
-        assertFlags(u1, bcTernary.getIfTrue().getRequirementFlagIndex(true));
+        assertExactMatch(firstRead, u1LastName, u2);
         assertFlags(u2, bcTernary.getIfTrue().getRequirementFlagIndex(false));
         assertFlags(u1LastName, bcTernary.getIfTrue().getRequirementFlagIndex(true));
         assertFlags(u2LastName, bcTernary.getIfTrue().getRequirementFlagIndex(false));
@@ -597,12 +601,13 @@
         Collections.addAll(justRead, a, b, c);
         assertEquals(0, filterOut(getReadFirst(shouldRead, justRead), justRead).size());
         assertTrue(mExprModel.markBitsRead());
+
         shouldRead = getShouldRead();
         // if a and b are not invalid, a won't be read in the first step. But if c's expression
         // is invalid and c == true, a must be read. Depending on a, d might be read as well.
         // don't need to read b anymore because `a ? b : true` and `b ? a : false` has the same
         // invalidation flags.
-        assertExactMatch(shouldRead, a, abTernary, baTernary);
+        assertExactMatch(shouldRead, a, baTernary);
         justRead.clear();
 
         readFirst = getReadFirst(shouldRead);
@@ -611,20 +616,23 @@
         Collections.addAll(justRead, a);
 
         readFirst = filterOut(getReadFirst(shouldRead, justRead), justRead);
-        assertExactMatch(readFirst, abTernary, baTernary);
-        Collections.addAll(justRead, abTernary, baTernary);
+        assertExactMatch(readFirst, baTernary);
+        Collections.addAll(justRead, baTernary);
 
         readFirst = filterOut(getReadFirst(shouldRead, justRead), justRead);
         assertEquals(0, filterOut(getReadFirst(shouldRead, justRead), justRead).size());
         assertTrue(mExprModel.markBitsRead());
 
         shouldRead = getShouldRead();
+        // now we can read abTernary as well which had a conditional dependency on a but we did not
+        // elevate its dependency since we had other expressions elevated already
+
         // now we can read adf ternary and c ternary
         justRead.clear();
-        assertExactMatch(shouldRead, d, cTernary.getIfTrue(), cTernary);
+        assertExactMatch(shouldRead, abTernary, d, cTernary.getIfTrue(), cTernary);
         readFirst = getReadFirst(shouldRead);
-        assertExactMatch(readFirst, d);
-        Collections.addAll(justRead, d);
+        assertExactMatch(readFirst, d, abTernary);
+        Collections.addAll(justRead, d, abTernary);
         readFirst = filterOut(getReadFirst(shouldRead, justRead), justRead);
         assertExactMatch(readFirst, cTernary.getIfTrue());
         Collections.addAll(justRead, cTernary.getIfTrue());
@@ -688,6 +696,76 @@
     }
 
     @Test
+    public void testInvalidateConditional() {
+        MockLayoutBinder lb = new MockLayoutBinder();
+        mExprModel = lb.getModel();
+        final IdentifierExpr foo = lb.addVariable("foo", Foo.class.getCanonicalName(), null);
+        final IdentifierExpr c = lb.addVariable("c", "int", null);
+        final TernaryExpr ternary = parse(lb, "foo.a > 0 && (foo.b > 0 || c > 0)",
+                TernaryExpr.class);
+        final ComparisonExpr fooB0 = parse(lb, "foo.b > 0", ComparisonExpr.class);
+        final FieldAccessExpr fooB = (FieldAccessExpr) fooB0.getLeft();
+        mExprModel.seal();
+        final ComparisonExpr fooA0 = (ComparisonExpr) ternary.getPred();
+        final FieldAccessExpr fooA = (FieldAccessExpr) fooA0.getLeft();
+
+        // foo.b > 0 || c > 0
+        final TernaryExpr ternaryIfTrue = (TernaryExpr) ternary.getIfTrue();
+        final ComparisonExpr c0 = (ComparisonExpr) ternaryIfTrue.getIfFalse();
+
+        List<Expr> toRead = getShouldRead();
+        assertExactMatch(toRead, foo, fooA, fooA0, fooB, fooB0);
+        List<Expr> justRead = new ArrayList<Expr>();
+        List<Expr> readNow = getReadFirst(toRead, justRead);
+        assertExactMatch(readNow, foo);
+        justRead.addAll(readNow);
+
+        readNow = filterOut(getReadFirst(toRead, justRead), justRead);
+        assertExactMatch(readNow, fooA, fooB);
+        justRead.addAll(readNow);
+
+        readNow = filterOut(getReadFirst(toRead, justRead), justRead);
+        assertExactMatch(readNow, fooA0, fooB0);
+        justRead.addAll(readNow);
+
+        assertTrue(mExprModel.markBitsRead());
+        justRead.clear();
+        toRead = getShouldRead();
+
+        // there is a second path to calculate fooB, fooB0 where fooB is not invalid but fooA or
+        // c is invalid.
+        assertExactMatch(toRead, fooB, fooB0);
+        readNow = filterOut(getReadFirst(toRead, justRead), justRead);
+        assertExactMatch(readNow, fooB);
+        justRead.add(fooB);
+        readNow = filterOut(getReadFirst(toRead, justRead), justRead);
+        assertExactMatch(readNow, fooB0);
+
+        assertTrue(mExprModel.markBitsRead());
+        justRead.clear();
+        toRead = getShouldRead();
+
+        assertExactMatch(toRead, c, c0, ternary.getIfTrue(), ternary);
+        readNow = filterOut(getReadFirst(toRead, justRead), justRead);
+        assertExactMatch(readNow, c);
+        justRead.addAll(readNow);
+
+        readNow = filterOut(getReadFirst(toRead, justRead), justRead);
+        assertExactMatch(readNow, c0);
+        justRead.addAll(readNow);
+
+        readNow = filterOut(getReadFirst(toRead, justRead), justRead);
+        assertExactMatch(readNow, ternary.getIfTrue());
+        justRead.addAll(readNow);
+
+        readNow = filterOut(getReadFirst(toRead, justRead), justRead);
+        assertExactMatch(readNow, ternary);
+        justRead.addAll(readNow);
+
+        assertFalse(mExprModel.markBitsRead());
+    }
+
+    @Test
     public void testNoFlagsForNonBindingStatic() {
         MockLayoutBinder lb = new MockLayoutBinder();
         mExprModel = lb.getModel();
@@ -794,7 +872,7 @@
         assertFalse(fieldAccess.isDynamic());
         mExprModel.seal();
         assertEquals(0, getShouldRead().size());
-        final Expr child = fieldAccess.getChild();
+        final Expr child = fieldAccess.getTarget();
         assertTrue(child instanceof StaticIdentifierExpr);
         StaticIdentifierExpr id = (StaticIdentifierExpr) child;
         assertEquals(id.getResolvedType().getCanonicalName(), "android.view.View");
@@ -846,6 +924,86 @@
     }
 
     @Test
+    public void testVoid() {
+        MockLayoutBinder lb = new MockLayoutBinder();
+        mExprModel = lb.getModel();
+        final LambdaExpr lambda = parse(lb, "(v) -> cond1 ? obj4.clicked(v) : void", LambdaExpr.class);
+        assertNotSame(mExprModel, lambda.getCallbackExprModel());
+    }
+
+    @Test
+    public void testVoid2() {
+        MockLayoutBinder lb = new MockLayoutBinder();
+        mExprModel = lb.getModel();
+        final LambdaExpr lambda = parse(lb, "(v) -> cond1 ? obj4.clicked(v) : Void", LambdaExpr.class);
+        assertNotSame(mExprModel, lambda.getCallbackExprModel());
+    }
+
+    @Test
+    public void testShruggy() {
+        MockLayoutBinder lb = new MockLayoutBinder();
+        mExprModel = lb.getModel();
+        final LambdaExpr lambda = parse(lb, "(v) -> cond1 ? obj4.clicked(v) : ¯\\_(ツ)_/¯", LambdaExpr.class);
+        assertNotSame(mExprModel, lambda.getCallbackExprModel());
+    }
+
+    @Test
+    public void testParseNoArgLambda() {
+        MockLayoutBinder lb = new MockLayoutBinder();
+        mExprModel = lb.getModel();
+        final LambdaExpr lambda = parse(lb, "() -> user.name", LambdaExpr.class);
+        assertNotSame(mExprModel, lambda.getCallbackExprModel());
+    }
+
+    @Test
+    public void testParseLambdaWithSingleArg() {
+        MockLayoutBinder lb = new MockLayoutBinder();
+        mExprModel = lb.getModel();
+        final LambdaExpr lambda = parse(lb, "a -> user.name", LambdaExpr.class);
+        assertNotSame(mExprModel, lambda.getCallbackExprModel());
+        assertTrue("should have user", hasIdentifier(mExprModel, "user"));
+        assertTrue("should have user", hasIdentifier(lambda.getCallbackExprModel(), "user"));
+        assertSame("should have the same user", getIdentifier(mExprModel, "user"),
+                getIdentifier(lambda.getCallbackExprModel(), "user"));
+        assertTrue("should have a", hasCallbackIdentifier(lambda.getCallbackExprModel(), 0, "a"));
+        assertFalse("should not have a", hasCallbackIdentifier(mExprModel, 0, "a"));
+    }
+
+    @Test
+    public void testParseLambdaWithArguments() {
+        MockLayoutBinder lb = new MockLayoutBinder();
+        mExprModel = lb.getModel();
+        final LambdaExpr lambda = parse(lb, "(a, b, c, d) -> user.name", LambdaExpr.class);
+        final CallbackExprModel callbackModel = lambda.getCallbackExprModel();
+        assertNotSame(mExprModel, callbackModel);
+        assertTrue("should have user", hasIdentifier(mExprModel, "user"));
+        int index = 0;
+        for (String s : new String[]{"a", "b", "c", "d"}) {
+            assertTrue("should have " + s, hasCallbackIdentifier(callbackModel, index, s));
+            assertFalse("should not have " + s, hasIdentifier(mExprModel, s));
+            assertFalse("should not have " + s, hasCallbackIdentifier(mExprModel, index, s));
+            index ++;
+        }
+    }
+
+    private boolean hasIdentifier(ExprModel model, String name) {
+        return getIdentifier(model, name) != null;
+    }
+
+    private Expr getIdentifier(ExprModel model, String name) {
+        return model.getExprMap().get(new IdentifierExpr(name).getUniqueKey());
+    }
+
+    private boolean hasCallbackIdentifier(ExprModel model, int index, String name) {
+        return getCallbackIdentifier(model, index, name) != null;
+    }
+
+    private Expr getCallbackIdentifier(ExprModel model, int index, String name) {
+        return model.getExprMap().get(new CallbackArgExpr(index, name).getUniqueKey());
+    }
+
+
+    @Test
     public void testFinalOfStaticField() {
         MockLayoutBinder lb = new MockLayoutBinder();
         mExprModel = lb.getModel();
@@ -974,7 +1132,7 @@
     }
 
     private <T extends Expr> T parse(LayoutBinder binder, String input, Class<T> klass) {
-        final Expr parsed = binder.parse(input, false, null);
+        final Expr parsed = binder.parse(input, null, null);
         assertTrue(klass.isAssignableFrom(parsed.getClass()));
         return (T) parsed;
     }
@@ -1006,6 +1164,11 @@
         return ExprModel.filterShouldRead(mExprModel.getPendingExpressions());
     }
 
+    public static class Foo {
+        public final int a = 1;
+        public final int b = 1;
+    }
+
     public static class User implements Observable {
 
         String name;
diff --git a/compiler/src/test/java/android/databinding/tool/expr/ExprTest.java b/compiler/src/test/java/android/databinding/tool/expr/ExprTest.java
index 61d04cb..6966dd4 100644
--- a/compiler/src/test/java/android/databinding/tool/expr/ExprTest.java
+++ b/compiler/src/test/java/android/databinding/tool/expr/ExprTest.java
@@ -56,11 +56,16 @@
         }
 
         @Override
-        protected KCode generateCode(boolean full) {
+        protected KCode generateCode() {
             return new KCode();
         }
 
         @Override
+        public Expr cloneToModel(ExprModel model) {
+            return this;
+        }
+
+        @Override
         protected String getInvertibleError() {
             return null;
         }
@@ -90,11 +95,16 @@
             }
 
             @Override
-            protected KCode generateCode(boolean full) {
+            protected KCode generateCode() {
                 return new KCode();
             }
 
             @Override
+            public Expr cloneToModel(ExprModel model) {
+                return this;
+            }
+
+            @Override
             protected String getInvertibleError() {
                 return null;
             }
diff --git a/compiler/src/test/java/android/databinding/tool/reflection/java/JavaAnalyzer.java b/compiler/src/test/java/android/databinding/tool/reflection/java/JavaAnalyzer.java
index 1b97cd9..a79897c 100644
--- a/compiler/src/test/java/android/databinding/tool/reflection/java/JavaAnalyzer.java
+++ b/compiler/src/test/java/android/databinding/tool/reflection/java/JavaAnalyzer.java
@@ -13,17 +13,17 @@
 
 package android.databinding.tool.reflection.java;
 
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
-
-import org.apache.commons.io.FileUtils;
-
 import android.databinding.tool.reflection.ModelAnalyzer;
 import android.databinding.tool.reflection.ModelClass;
 import android.databinding.tool.reflection.SdkUtil;
 import android.databinding.tool.reflection.TypeUtil;
 import android.databinding.tool.util.L;
 
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+
+import org.apache.commons.io.FileUtils;
+
 import java.io.File;
 import java.io.IOException;
 import java.net.MalformedURLException;
@@ -66,13 +66,17 @@
         }
     }
 
+    public ClassLoader getClassLoader() {
+        return mClassLoader;
+    }
+
     @Override
     protected ModelClass[] getObservableFieldTypes() {
         return new ModelClass[0];
     }
 
     @Override
-    public ModelClass findClass(String className, Map<String, String> imports) {
+    public ModelClass findClassInternal(String className, Map<String, String> imports) {
         // TODO handle imports
         JavaClass loaded = mClassCache.get(className);
         if (loaded != null) {
diff --git a/compiler/src/test/java/android/databinding/tool/reflection/java/JavaMethod.java b/compiler/src/test/java/android/databinding/tool/reflection/java/JavaMethod.java
index 0d00c57..b7b626c 100644
--- a/compiler/src/test/java/android/databinding/tool/reflection/java/JavaMethod.java
+++ b/compiler/src/test/java/android/databinding/tool/reflection/java/JavaMethod.java
@@ -68,6 +68,11 @@
     }
 
     @Override
+    public boolean isProtected() {
+        return Modifier.isProtected(mMethod.getModifiers());
+    }
+
+    @Override
     public boolean isStatic() {
         return Modifier.isStatic(mMethod.getModifiers());
     }
diff --git a/compilerCommon/BindingExpression.g4 b/compilerCommon/BindingExpression.g4
index 0835a14..f6f709d 100644
--- a/compilerCommon/BindingExpression.g4
+++ b/compilerCommon/BindingExpression.g4
@@ -26,28 +26,45 @@
 grammar BindingExpression;
 
 bindingSyntax
-    :   expression defaults?
+    :   expression defaults? # RootExpr
+    |   lambdaExpression # RootLambda
     ;
 
 defaults
     :   ',' 'default' '=' constantValue
     ;
+
 constantValue
     :   literal
     |   ResourceReference
     |   identifier
     ;
 
+lambdaExpression
+    :   args=lambdaParameters '->' expr=expression
+    ;
+
+lambdaParameters
+    :   Identifier # SingleLambdaParameter
+    |   '(' params=inferredFormalParameterList? ')' #LambdaParameterList
+    ;
+
+inferredFormalParameterList
+    :   Identifier (',' Identifier)*
+    ;
+
 expression
     :   '(' expression ')'                              # Grouping
 // this isn't allowed yet.
 //    |   THIS                                            # Primary
     |   literal                                         # Primary
+    |   VoidLiteral                                     # Primary
     |   identifier                                      # Primary
     |   classExtraction                                 # Primary
     |   resources                                       # Resource
 //    |   typeArguments (explicitGenericInvocationSuffix | 'this' arguments) # GenericCall
     |   expression '.' Identifier                       # DotOp
+    |   expression '::' Identifier                      # FunctionRef
 //    |   expression '.' 'this'                           # ThisReference
 //    |   expression '.' explicitGenericInvocation        # ExplicitGenericInvocationOp
     |   expression '[' expression ']'                   # BracketOp
@@ -76,7 +93,6 @@
 
 classExtraction
     :   type '.' 'class'
-    |   'void' '.' 'class'
     ;
 
 expressionList
@@ -100,6 +116,12 @@
     |   CharacterLiteral
     ;
 
+VoidLiteral
+    :   'Void'
+    |   'void'
+    |   '¯\\_(ツ)_/¯'
+    ;
+
 stringLiteral
     :   SingleQuoteString
     |   DoubleQuoteString
diff --git a/compilerCommon/build.gradle b/compilerCommon/build.gradle
index 91ce05d..0f260e4 100644
--- a/compilerCommon/build.gradle
+++ b/compilerCommon/build.gradle
@@ -16,9 +16,6 @@
 
 apply plugin: 'java'
 
-sourceCompatibility = dataBindingConfig.javaSourceCompatibility
-targetCompatibility = dataBindingConfig.javaTargetCompatibility
-
 sourceSets {
     main {
         java {
@@ -38,17 +35,26 @@
 dependencies {
     testCompile 'junit:junit:4.12'
     compile project(':dataBinding:baseLibrary')
-    compile 'com.tunnelvisionlabs:antlr4:4.5'
+    compile 'org.antlr:antlr4:4.5.3'
     compile 'commons-io:commons-io:2.4'
     compile 'com.googlecode.juniversalchardet:juniversalchardet:1.0.3'
     compile 'com.google.guava:guava:17.0'
+    compile 'com.android.tools:annotations:24.5.0'
+}
+
+project.tasks.create(name : "generateXmlLexer", type : JavaExec) {
+    classpath configurations.runtime
+    main "org.antlr.v4.Tool"
+    workingDir projectDir
+    args "XMLLexer.g4", "-visitor", "-lib", projectDir.absolutePath, "-o", "src/main/xml-gen/android/databinding/parser", "-package", "android.databinding.parser"
 }
 
 project.tasks.create(name : "generateXmlParser", type : JavaExec) {
     classpath configurations.runtime
     main "org.antlr.v4.Tool"
     workingDir projectDir
-    args "XMLParser.g4", "-visitor", "-o", "src/main/java/android/databinding/parser", "-package", "android.databinding.parser", "-lib", "."
+    args "XMLParser.g4", "-visitor", "-lib", projectDir.absolutePath, "-o", "src/main/xml-gen/android/databinding/parser", "-package", "android.databinding.parser"
+    dependsOn "generateXmlLexer"
 }
 
 project.tasks.create(name : "generateGrammar", type : JavaExec) {
diff --git a/compilerCommon/compilerCommon.iml b/compilerCommon/compilerCommon.iml
deleted file mode 100644
index d9cc2c6..0000000
--- a/compilerCommon/compilerCommon.iml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module external.linked.project.id=":dataBinding:compilerCommon" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.version="1.1" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="false">
-    <output url="file://$MODULE_DIR$/build/classes/main" />
-    <output-test url="file://$MODULE_DIR$/build/classes/test" />
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src/main/grammar-gen" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/main/xml-gen" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
-      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
-      <excludeFolder url="file://$MODULE_DIR$/.gradle" />
-      <excludeFolder url="file://$MODULE_DIR$/build" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="module" module-name="baseLibrary" />
-    <orderEntry type="library" name="Gradle: com.tunnelvisionlabs:antlr4:4.5" level="project" />
-    <orderEntry type="library" name="Gradle: commons-io:commons-io:2.4" level="project" />
-    <orderEntry type="library" name="Gradle: com.googlecode.juniversalchardet:juniversalchardet:1.0.3" level="project" />
-    <orderEntry type="library" name="Gradle: com.tunnelvisionlabs:antlr4-runtime:4.5" level="project" />
-    <orderEntry type="library" name="Gradle: com.tunnelvisionlabs:antlr4-annotations:4.5" level="project" />
-    <orderEntry type="library" name="Gradle: org.antlr:antlr-runtime:3.5.2" level="project" />
-    <orderEntry type="library" name="Gradle: org.antlr:ST4:4.0.8" level="project" />
-    <orderEntry type="library" name="Gradle: org.abego.treelayout:org.abego.treelayout.core:1.0.1" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: junit:junit:4.12" level="project" />
-    <orderEntry type="library" scope="TEST" name="Gradle: org.hamcrest:hamcrest-core:1.3" level="project" />
-    <orderEntry type="library" name="Gradle: com.google.guava:guava:17.0" level="project" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/compilerCommon/db-compilerCommon-base.iml b/compilerCommon/db-compilerCommon-base.iml
index 38f8122..bc880d5 100644
--- a/compilerCommon/db-compilerCommon-base.iml
+++ b/compilerCommon/db-compilerCommon-base.iml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <module relativePaths="true" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
     <exclude-output />
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
@@ -16,7 +16,7 @@
     <orderEntry type="module-library" exported="">
       <library>
         <CLASSES>
-          <root url="jar://$MODULE_DIR$/../../../prebuilts/tools/common/m2/repository/com/tunnelvisionlabs/antlr4/4.5/antlr4-4.5.jar!/" />
+          <root url="jar://$MODULE_DIR$/../../../prebuilts/tools/common/m2/repository/org/antlr/antlr4/4.5.3/antlr4-4.5.3.jar!/" />
         </CLASSES>
         <JAVADOC />
         <SOURCES />
@@ -45,42 +45,6 @@
     <orderEntry type="module-library" exported="">
       <library>
         <CLASSES>
-          <root url="jar://$MODULE_DIR$/../../../prebuilts/tools/common/m2/repository/com/tunnelvisionlabs/antlr4-runtime/4.5/antlr4-runtime-4.5.jar!/" />
-        </CLASSES>
-        <JAVADOC />
-        <SOURCES />
-      </library>
-    </orderEntry>
-    <orderEntry type="module-library" exported="">
-      <library>
-        <CLASSES>
-          <root url="jar://$MODULE_DIR$/../../../prebuilts/tools/common/m2/repository/com/tunnelvisionlabs/antlr4-annotations/4.5/antlr4-annotations-4.5.jar!/" />
-        </CLASSES>
-        <JAVADOC />
-        <SOURCES />
-      </library>
-    </orderEntry>
-    <orderEntry type="module-library" exported="">
-      <library>
-        <CLASSES>
-          <root url="jar://$MODULE_DIR$/../../../prebuilts/tools/common/m2/repository/org/antlr/antlr-runtime/3.5.2/antlr-runtime-3.5.2.jar!/" />
-        </CLASSES>
-        <JAVADOC />
-        <SOURCES />
-      </library>
-    </orderEntry>
-    <orderEntry type="module-library" exported="">
-      <library>
-        <CLASSES>
-          <root url="jar://$MODULE_DIR$/../../../prebuilts/tools/common/m2/repository/org/antlr/ST4/4.0.8/ST4-4.0.8.jar!/" />
-        </CLASSES>
-        <JAVADOC />
-        <SOURCES />
-      </library>
-    </orderEntry>
-    <orderEntry type="module-library" exported="">
-      <library>
-        <CLASSES>
           <root url="jar://$MODULE_DIR$/../../../prebuilts/tools/common/m2/repository/org/abego/treelayout/org.abego.treelayout.core/1.0.1/org.abego.treelayout.core-1.0.1.jar!/" />
         </CLASSES>
         <JAVADOC />
@@ -110,5 +74,6 @@
       </library>
     </orderEntry>
     <orderEntry type="library" exported="" name="guava-tools" level="project" />
+    <orderEntry type="module" module-name="android-annotations" />
   </component>
 </module>
\ No newline at end of file
diff --git a/compilerCommon/db-compilerCommon.iml b/compilerCommon/db-compilerCommon.iml
index 3b18b8a..eb53363 100644
--- a/compilerCommon/db-compilerCommon.iml
+++ b/compilerCommon/db-compilerCommon.iml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <module relativePaths="true" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
     <exclude-output />
     <content url="file://$MODULE_DIR$">
       <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
@@ -25,8 +25,7 @@
         <SOURCES />
       </library>
     </orderEntry>
-    <orderEntry type="library" exported="" name="antlr4-runtime-4.5" level="project" />
-    <orderEntry type="library" exported="" name="antlr4-annotations-4.5" level="project" />
+    <orderEntry type="library" exported="" name="antlr4-runtime-4.5.3" level="project" />
     <orderEntry type="module-library" scope="TEST">
       <library>
         <CLASSES>
@@ -49,5 +48,6 @@
         </SOURCES>
       </library>
     </orderEntry>
+    <orderEntry type="module" module-name="android-annotations" exported="" />
   </component>
 </module>
\ No newline at end of file
diff --git a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpression.tokens b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpression.tokens
index d9d1035..f80b7e6 100644
--- a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpression.tokens
+++ b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpression.tokens
@@ -41,61 +41,64 @@
 T__40=41
 T__41=42
 T__42=43
-THIS=44
-IntegerLiteral=45
-FloatingPointLiteral=46
-BooleanLiteral=47
-CharacterLiteral=48
-SingleQuoteString=49
-DoubleQuoteString=50
-NullLiteral=51
-Identifier=52
-WS=53
-ResourceReference=54
-PackageName=55
-ResourceType=56
+T__43=44
+THIS=45
+VoidLiteral=46
+IntegerLiteral=47
+FloatingPointLiteral=48
+BooleanLiteral=49
+CharacterLiteral=50
+SingleQuoteString=51
+DoubleQuoteString=52
+NullLiteral=53
+Identifier=54
+WS=55
+ResourceReference=56
+PackageName=57
+ResourceType=58
 ','=1
 'default'=2
 '='=3
-'('=4
-')'=5
-'.'=6
-'['=7
-']'=8
-'+'=9
-'-'=10
-'~'=11
-'!'=12
-'*'=13
-'/'=14
-'%'=15
-'<<'=16
-'>>>'=17
-'>>'=18
-'<='=19
-'>='=20
-'>'=21
-'<'=22
-'instanceof'=23
-'=='=24
-'!='=25
-'&'=26
-'^'=27
-'|'=28
-'&&'=29
-'||'=30
-'?'=31
-':'=32
-'??'=33
-'class'=34
-'void'=35
-'boolean'=36
-'char'=37
-'byte'=38
-'short'=39
-'int'=40
-'long'=41
-'float'=42
-'double'=43
-'this'=44
-'null'=51
+'->'=4
+'('=5
+')'=6
+'.'=7
+'::'=8
+'['=9
+']'=10
+'+'=11
+'-'=12
+'~'=13
+'!'=14
+'*'=15
+'/'=16
+'%'=17
+'<<'=18
+'>>>'=19
+'>>'=20
+'<='=21
+'>='=22
+'>'=23
+'<'=24
+'instanceof'=25
+'=='=26
+'!='=27
+'&'=28
+'^'=29
+'|'=30
+'&&'=31
+'||'=32
+'?'=33
+':'=34
+'??'=35
+'class'=36
+'boolean'=37
+'char'=38
+'byte'=39
+'short'=40
+'int'=41
+'long'=42
+'float'=43
+'double'=44
+'this'=45
+'null'=53
diff --git a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionBaseListener.java b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionBaseListener.java
index 2b11492..c9ccebd 100644
--- a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionBaseListener.java
+++ b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionBaseListener.java
@@ -1,9 +1,7 @@
-// Generated from BindingExpression.g4 by ANTLR 4.5
+// Generated from BindingExpression.g4 by ANTLR 4.5.3
 package android.databinding.parser;
 
 import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.misc.NotNull;
 import org.antlr.v4.runtime.tree.ErrorNode;
 import org.antlr.v4.runtime.tree.TerminalNode;
 
@@ -18,478 +16,504 @@
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterBracketOp(@NotNull BindingExpressionParser.BracketOpContext ctx) { }
+	@Override public void enterRootExpr(BindingExpressionParser.RootExprContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitBracketOp(@NotNull BindingExpressionParser.BracketOpContext ctx) { }
+	@Override public void exitRootExpr(BindingExpressionParser.RootExprContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterRootLambda(BindingExpressionParser.RootLambdaContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitRootLambda(BindingExpressionParser.RootLambdaContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterDefaults(BindingExpressionParser.DefaultsContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitDefaults(BindingExpressionParser.DefaultsContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterConstantValue(BindingExpressionParser.ConstantValueContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitConstantValue(BindingExpressionParser.ConstantValueContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterLambdaExpression(BindingExpressionParser.LambdaExpressionContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitLambdaExpression(BindingExpressionParser.LambdaExpressionContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterSingleLambdaParameter(BindingExpressionParser.SingleLambdaParameterContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitSingleLambdaParameter(BindingExpressionParser.SingleLambdaParameterContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterLambdaParameterList(BindingExpressionParser.LambdaParameterListContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitLambdaParameterList(BindingExpressionParser.LambdaParameterListContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterInferredFormalParameterList(BindingExpressionParser.InferredFormalParameterListContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitInferredFormalParameterList(BindingExpressionParser.InferredFormalParameterListContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterCastOp(BindingExpressionParser.CastOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitCastOp(BindingExpressionParser.CastOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterComparisonOp(BindingExpressionParser.ComparisonOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitComparisonOp(BindingExpressionParser.ComparisonOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterUnaryOp(BindingExpressionParser.UnaryOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitUnaryOp(BindingExpressionParser.UnaryOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterBracketOp(BindingExpressionParser.BracketOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitBracketOp(BindingExpressionParser.BracketOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterResource(BindingExpressionParser.ResourceContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitResource(BindingExpressionParser.ResourceContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterQuestionQuestionOp(BindingExpressionParser.QuestionQuestionOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitQuestionQuestionOp(BindingExpressionParser.QuestionQuestionOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterGrouping(BindingExpressionParser.GroupingContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitGrouping(BindingExpressionParser.GroupingContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterMethodInvocation(BindingExpressionParser.MethodInvocationContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitMethodInvocation(BindingExpressionParser.MethodInvocationContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterBitShiftOp(BindingExpressionParser.BitShiftOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitBitShiftOp(BindingExpressionParser.BitShiftOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterAndOrOp(BindingExpressionParser.AndOrOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitAndOrOp(BindingExpressionParser.AndOrOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterTernaryOp(BindingExpressionParser.TernaryOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitTernaryOp(BindingExpressionParser.TernaryOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterPrimary(BindingExpressionParser.PrimaryContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitPrimary(BindingExpressionParser.PrimaryContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterDotOp(BindingExpressionParser.DotOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitDotOp(BindingExpressionParser.DotOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterMathOp(BindingExpressionParser.MathOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitMathOp(BindingExpressionParser.MathOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterInstanceOfOp(BindingExpressionParser.InstanceOfOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitInstanceOfOp(BindingExpressionParser.InstanceOfOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterBinaryOp(BindingExpressionParser.BinaryOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitBinaryOp(BindingExpressionParser.BinaryOpContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterFunctionRef(BindingExpressionParser.FunctionRefContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitFunctionRef(BindingExpressionParser.FunctionRefContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterClassExtraction(BindingExpressionParser.ClassExtractionContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitClassExtraction(BindingExpressionParser.ClassExtractionContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterExpressionList(BindingExpressionParser.ExpressionListContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitExpressionList(BindingExpressionParser.ExpressionListContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterLiteral(BindingExpressionParser.LiteralContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitLiteral(BindingExpressionParser.LiteralContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterIdentifier(BindingExpressionParser.IdentifierContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitIdentifier(BindingExpressionParser.IdentifierContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterJavaLiteral(BindingExpressionParser.JavaLiteralContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitJavaLiteral(BindingExpressionParser.JavaLiteralContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterStringLiteral(BindingExpressionParser.StringLiteralContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitStringLiteral(BindingExpressionParser.StringLiteralContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterExplicitGenericInvocation(BindingExpressionParser.ExplicitGenericInvocationContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitExplicitGenericInvocation(BindingExpressionParser.ExplicitGenericInvocationContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterTypeArguments(BindingExpressionParser.TypeArgumentsContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitTypeArguments(BindingExpressionParser.TypeArgumentsContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterType(BindingExpressionParser.TypeContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitType(BindingExpressionParser.TypeContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterExplicitGenericInvocationSuffix(BindingExpressionParser.ExplicitGenericInvocationSuffixContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitExplicitGenericInvocationSuffix(BindingExpressionParser.ExplicitGenericInvocationSuffixContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterArguments(BindingExpressionParser.ArgumentsContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitArguments(BindingExpressionParser.ArgumentsContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterClassOrInterfaceType(BindingExpressionParser.ClassOrInterfaceTypeContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitClassOrInterfaceType(BindingExpressionParser.ClassOrInterfaceTypeContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterPrimitiveType(BindingExpressionParser.PrimitiveTypeContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitPrimitiveType(BindingExpressionParser.PrimitiveTypeContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterResources(BindingExpressionParser.ResourcesContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitResources(BindingExpressionParser.ResourcesContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterResourceParameters(BindingExpressionParser.ResourceParametersContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitResourceParameters(BindingExpressionParser.ResourceParametersContext ctx) { }
 
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterResource(@NotNull BindingExpressionParser.ResourceContext ctx) { }
+	@Override public void enterEveryRule(ParserRuleContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitResource(@NotNull BindingExpressionParser.ResourceContext ctx) { }
-
+	@Override public void exitEveryRule(ParserRuleContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterCastOp(@NotNull BindingExpressionParser.CastOpContext ctx) { }
+	@Override public void visitTerminal(TerminalNode node) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitCastOp(@NotNull BindingExpressionParser.CastOpContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterUnaryOp(@NotNull BindingExpressionParser.UnaryOpContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitUnaryOp(@NotNull BindingExpressionParser.UnaryOpContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterAndOrOp(@NotNull BindingExpressionParser.AndOrOpContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitAndOrOp(@NotNull BindingExpressionParser.AndOrOpContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterMethodInvocation(@NotNull BindingExpressionParser.MethodInvocationContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitMethodInvocation(@NotNull BindingExpressionParser.MethodInvocationContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterPrimary(@NotNull BindingExpressionParser.PrimaryContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitPrimary(@NotNull BindingExpressionParser.PrimaryContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterGrouping(@NotNull BindingExpressionParser.GroupingContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitGrouping(@NotNull BindingExpressionParser.GroupingContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterTernaryOp(@NotNull BindingExpressionParser.TernaryOpContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitTernaryOp(@NotNull BindingExpressionParser.TernaryOpContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterComparisonOp(@NotNull BindingExpressionParser.ComparisonOpContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitComparisonOp(@NotNull BindingExpressionParser.ComparisonOpContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterDotOp(@NotNull BindingExpressionParser.DotOpContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitDotOp(@NotNull BindingExpressionParser.DotOpContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterMathOp(@NotNull BindingExpressionParser.MathOpContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitMathOp(@NotNull BindingExpressionParser.MathOpContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterQuestionQuestionOp(@NotNull BindingExpressionParser.QuestionQuestionOpContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitQuestionQuestionOp(@NotNull BindingExpressionParser.QuestionQuestionOpContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterBitShiftOp(@NotNull BindingExpressionParser.BitShiftOpContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitBitShiftOp(@NotNull BindingExpressionParser.BitShiftOpContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterInstanceOfOp(@NotNull BindingExpressionParser.InstanceOfOpContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitInstanceOfOp(@NotNull BindingExpressionParser.InstanceOfOpContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterBinaryOp(@NotNull BindingExpressionParser.BinaryOpContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitBinaryOp(@NotNull BindingExpressionParser.BinaryOpContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterBindingSyntax(@NotNull BindingExpressionParser.BindingSyntaxContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitBindingSyntax(@NotNull BindingExpressionParser.BindingSyntaxContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterDefaults(@NotNull BindingExpressionParser.DefaultsContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitDefaults(@NotNull BindingExpressionParser.DefaultsContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterConstantValue(@NotNull BindingExpressionParser.ConstantValueContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitConstantValue(@NotNull BindingExpressionParser.ConstantValueContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterExpression(@NotNull BindingExpressionParser.ExpressionContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitExpression(@NotNull BindingExpressionParser.ExpressionContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterClassExtraction(@NotNull BindingExpressionParser.ClassExtractionContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitClassExtraction(@NotNull BindingExpressionParser.ClassExtractionContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterExpressionList(@NotNull BindingExpressionParser.ExpressionListContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitExpressionList(@NotNull BindingExpressionParser.ExpressionListContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterLiteral(@NotNull BindingExpressionParser.LiteralContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitLiteral(@NotNull BindingExpressionParser.LiteralContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterIdentifier(@NotNull BindingExpressionParser.IdentifierContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitIdentifier(@NotNull BindingExpressionParser.IdentifierContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterJavaLiteral(@NotNull BindingExpressionParser.JavaLiteralContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitJavaLiteral(@NotNull BindingExpressionParser.JavaLiteralContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterStringLiteral(@NotNull BindingExpressionParser.StringLiteralContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitStringLiteral(@NotNull BindingExpressionParser.StringLiteralContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterExplicitGenericInvocation(@NotNull BindingExpressionParser.ExplicitGenericInvocationContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitExplicitGenericInvocation(@NotNull BindingExpressionParser.ExplicitGenericInvocationContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterTypeArguments(@NotNull BindingExpressionParser.TypeArgumentsContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitTypeArguments(@NotNull BindingExpressionParser.TypeArgumentsContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterType(@NotNull BindingExpressionParser.TypeContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitType(@NotNull BindingExpressionParser.TypeContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterExplicitGenericInvocationSuffix(@NotNull BindingExpressionParser.ExplicitGenericInvocationSuffixContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitExplicitGenericInvocationSuffix(@NotNull BindingExpressionParser.ExplicitGenericInvocationSuffixContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterArguments(@NotNull BindingExpressionParser.ArgumentsContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitArguments(@NotNull BindingExpressionParser.ArgumentsContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterClassOrInterfaceType(@NotNull BindingExpressionParser.ClassOrInterfaceTypeContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitClassOrInterfaceType(@NotNull BindingExpressionParser.ClassOrInterfaceTypeContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterPrimitiveType(@NotNull BindingExpressionParser.PrimitiveTypeContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitPrimitiveType(@NotNull BindingExpressionParser.PrimitiveTypeContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterResources(@NotNull BindingExpressionParser.ResourcesContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitResources(@NotNull BindingExpressionParser.ResourcesContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterResourceParameters(@NotNull BindingExpressionParser.ResourceParametersContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitResourceParameters(@NotNull BindingExpressionParser.ResourceParametersContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterEveryRule(@NotNull ParserRuleContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitEveryRule(@NotNull ParserRuleContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void visitTerminal(@NotNull TerminalNode node) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void visitErrorNode(@NotNull ErrorNode node) { }
+	@Override public void visitErrorNode(ErrorNode node) { }
 }
\ No newline at end of file
diff --git a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionBaseVisitor.java b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionBaseVisitor.java
index 08c54fa..5ba08ba 100644
--- a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionBaseVisitor.java
+++ b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionBaseVisitor.java
@@ -1,7 +1,5 @@
-// Generated from BindingExpression.g4 by ANTLR 4.5
+// Generated from BindingExpression.g4 by ANTLR 4.5.3
 package android.databinding.parser;
-import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.misc.NotNull;
 import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
 
 /**
@@ -9,287 +7,288 @@
  * which can be extended to create a visitor which only needs to handle a subset
  * of the available methods.
  *
- * @param <Result> The return type of the visit operation. Use {@link Void} for
+ * @param <T> The return type of the visit operation. Use {@link Void} for
  * operations with no return type.
  */
-public class BindingExpressionBaseVisitor<Result> extends AbstractParseTreeVisitor<Result> implements BindingExpressionVisitor<Result> {
+public class BindingExpressionBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements BindingExpressionVisitor<T> {
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitBracketOp(@NotNull BindingExpressionParser.BracketOpContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitRootExpr(BindingExpressionParser.RootExprContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitResource(@NotNull BindingExpressionParser.ResourceContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitRootLambda(BindingExpressionParser.RootLambdaContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitCastOp(@NotNull BindingExpressionParser.CastOpContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitDefaults(BindingExpressionParser.DefaultsContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitUnaryOp(@NotNull BindingExpressionParser.UnaryOpContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitConstantValue(BindingExpressionParser.ConstantValueContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitAndOrOp(@NotNull BindingExpressionParser.AndOrOpContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitLambdaExpression(BindingExpressionParser.LambdaExpressionContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitMethodInvocation(@NotNull BindingExpressionParser.MethodInvocationContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitSingleLambdaParameter(BindingExpressionParser.SingleLambdaParameterContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitPrimary(@NotNull BindingExpressionParser.PrimaryContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitLambdaParameterList(BindingExpressionParser.LambdaParameterListContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitGrouping(@NotNull BindingExpressionParser.GroupingContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitInferredFormalParameterList(BindingExpressionParser.InferredFormalParameterListContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitTernaryOp(@NotNull BindingExpressionParser.TernaryOpContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitCastOp(BindingExpressionParser.CastOpContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitComparisonOp(@NotNull BindingExpressionParser.ComparisonOpContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitComparisonOp(BindingExpressionParser.ComparisonOpContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitDotOp(@NotNull BindingExpressionParser.DotOpContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitUnaryOp(BindingExpressionParser.UnaryOpContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitMathOp(@NotNull BindingExpressionParser.MathOpContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitBracketOp(BindingExpressionParser.BracketOpContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitQuestionQuestionOp(@NotNull BindingExpressionParser.QuestionQuestionOpContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitResource(BindingExpressionParser.ResourceContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitBitShiftOp(@NotNull BindingExpressionParser.BitShiftOpContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitQuestionQuestionOp(BindingExpressionParser.QuestionQuestionOpContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitInstanceOfOp(@NotNull BindingExpressionParser.InstanceOfOpContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitGrouping(BindingExpressionParser.GroupingContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitBinaryOp(@NotNull BindingExpressionParser.BinaryOpContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitMethodInvocation(BindingExpressionParser.MethodInvocationContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitBindingSyntax(@NotNull BindingExpressionParser.BindingSyntaxContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitBitShiftOp(BindingExpressionParser.BitShiftOpContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitDefaults(@NotNull BindingExpressionParser.DefaultsContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitAndOrOp(BindingExpressionParser.AndOrOpContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitConstantValue(@NotNull BindingExpressionParser.ConstantValueContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitTernaryOp(BindingExpressionParser.TernaryOpContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitExpression(@NotNull BindingExpressionParser.ExpressionContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitPrimary(BindingExpressionParser.PrimaryContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitClassExtraction(@NotNull BindingExpressionParser.ClassExtractionContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitDotOp(BindingExpressionParser.DotOpContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitExpressionList(@NotNull BindingExpressionParser.ExpressionListContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitMathOp(BindingExpressionParser.MathOpContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitLiteral(@NotNull BindingExpressionParser.LiteralContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitInstanceOfOp(BindingExpressionParser.InstanceOfOpContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitIdentifier(@NotNull BindingExpressionParser.IdentifierContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitBinaryOp(BindingExpressionParser.BinaryOpContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitJavaLiteral(@NotNull BindingExpressionParser.JavaLiteralContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitFunctionRef(BindingExpressionParser.FunctionRefContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitStringLiteral(@NotNull BindingExpressionParser.StringLiteralContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitClassExtraction(BindingExpressionParser.ClassExtractionContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitExplicitGenericInvocation(@NotNull BindingExpressionParser.ExplicitGenericInvocationContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitExpressionList(BindingExpressionParser.ExpressionListContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitTypeArguments(@NotNull BindingExpressionParser.TypeArgumentsContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitLiteral(BindingExpressionParser.LiteralContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitType(@NotNull BindingExpressionParser.TypeContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitIdentifier(BindingExpressionParser.IdentifierContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitExplicitGenericInvocationSuffix(@NotNull BindingExpressionParser.ExplicitGenericInvocationSuffixContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitJavaLiteral(BindingExpressionParser.JavaLiteralContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitArguments(@NotNull BindingExpressionParser.ArgumentsContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitStringLiteral(BindingExpressionParser.StringLiteralContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitClassOrInterfaceType(@NotNull BindingExpressionParser.ClassOrInterfaceTypeContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitExplicitGenericInvocation(BindingExpressionParser.ExplicitGenericInvocationContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitPrimitiveType(@NotNull BindingExpressionParser.PrimitiveTypeContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitTypeArguments(BindingExpressionParser.TypeArgumentsContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitResources(@NotNull BindingExpressionParser.ResourcesContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitType(BindingExpressionParser.TypeContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitResourceParameters(@NotNull BindingExpressionParser.ResourceParametersContext ctx) { return visitChildren(ctx); }
+	@Override public T visitExplicitGenericInvocationSuffix(BindingExpressionParser.ExplicitGenericInvocationSuffixContext ctx) { return visitChildren(ctx); }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public T visitArguments(BindingExpressionParser.ArgumentsContext ctx) { return visitChildren(ctx); }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public T visitClassOrInterfaceType(BindingExpressionParser.ClassOrInterfaceTypeContext ctx) { return visitChildren(ctx); }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public T visitPrimitiveType(BindingExpressionParser.PrimitiveTypeContext ctx) { return visitChildren(ctx); }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public T visitResources(BindingExpressionParser.ResourcesContext ctx) { return visitChildren(ctx); }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation returns the result of calling
+	 * {@link #visitChildren} on {@code ctx}.</p>
+	 */
+	@Override public T visitResourceParameters(BindingExpressionParser.ResourceParametersContext ctx) { return visitChildren(ctx); }
 }
\ No newline at end of file
diff --git a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionLexer.java b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionLexer.java
index 898ab4e..d89c63e 100644
--- a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionLexer.java
+++ b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionLexer.java
@@ -1,4 +1,4 @@
-// Generated from BindingExpression.g4 by ANTLR 4.5
+// Generated from BindingExpression.g4 by ANTLR 4.5.3
 package android.databinding.parser;
 import org.antlr.v4.runtime.Lexer;
 import org.antlr.v4.runtime.CharStream;
@@ -9,17 +9,23 @@
 import org.antlr.v4.runtime.dfa.DFA;
 import org.antlr.v4.runtime.misc.*;
 
+@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
 public class BindingExpressionLexer extends Lexer {
+	static { RuntimeMetaData.checkVersion("4.5.3", RuntimeMetaData.VERSION); }
+
+	protected static final DFA[] _decisionToDFA;
+	protected static final PredictionContextCache _sharedContextCache =
+		new PredictionContextCache();
 	public static final int
 		T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, 
 		T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, 
 		T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, 
 		T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, 
 		T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, 
-		T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, THIS=44, IntegerLiteral=45, 
-		FloatingPointLiteral=46, BooleanLiteral=47, CharacterLiteral=48, SingleQuoteString=49, 
-		DoubleQuoteString=50, NullLiteral=51, Identifier=52, WS=53, ResourceReference=54, 
-		PackageName=55, ResourceType=56;
+		T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, THIS=45, VoidLiteral=46, 
+		IntegerLiteral=47, FloatingPointLiteral=48, BooleanLiteral=49, CharacterLiteral=50, 
+		SingleQuoteString=51, DoubleQuoteString=52, NullLiteral=53, Identifier=54, 
+		WS=55, ResourceReference=56, PackageName=57, ResourceType=58;
 	public static String[] modeNames = {
 		"DEFAULT_MODE"
 	};
@@ -30,37 +36,38 @@
 		"T__17", "T__18", "T__19", "T__20", "T__21", "T__22", "T__23", "T__24", 
 		"T__25", "T__26", "T__27", "T__28", "T__29", "T__30", "T__31", "T__32", 
 		"T__33", "T__34", "T__35", "T__36", "T__37", "T__38", "T__39", "T__40", 
-		"T__41", "T__42", "THIS", "IntegerLiteral", "DecimalIntegerLiteral", "HexIntegerLiteral", 
-		"OctalIntegerLiteral", "BinaryIntegerLiteral", "IntegerTypeSuffix", "DecimalNumeral", 
-		"Digits", "Digit", "NonZeroDigit", "DigitOrUnderscore", "Underscores", 
-		"HexNumeral", "HexDigits", "HexDigit", "HexDigitOrUnderscore", "OctalNumeral", 
-		"OctalDigits", "OctalDigit", "OctalDigitOrUnderscore", "BinaryNumeral", 
-		"BinaryDigits", "BinaryDigit", "BinaryDigitOrUnderscore", "FloatingPointLiteral", 
-		"DecimalFloatingPointLiteral", "ExponentPart", "ExponentIndicator", "SignedInteger", 
-		"Sign", "FloatTypeSuffix", "HexadecimalFloatingPointLiteral", "HexSignificand", 
-		"BinaryExponent", "BinaryExponentIndicator", "BooleanLiteral", "CharacterLiteral", 
-		"SingleCharacter", "SingleQuoteString", "DoubleQuoteString", "StringCharacters", 
-		"StringCharacter", "SingleQuoteStringCharacter", "EscapeSequence", "OctalEscape", 
-		"UnicodeEscape", "ZeroToThree", "NullLiteral", "Identifier", "JavaLetter", 
-		"JavaLetterOrDigit", "WS", "ResourceReference", "PackageName", "ResourceType"
+		"T__41", "T__42", "T__43", "THIS", "VoidLiteral", "IntegerLiteral", "DecimalIntegerLiteral", 
+		"HexIntegerLiteral", "OctalIntegerLiteral", "BinaryIntegerLiteral", "IntegerTypeSuffix", 
+		"DecimalNumeral", "Digits", "Digit", "NonZeroDigit", "DigitOrUnderscore", 
+		"Underscores", "HexNumeral", "HexDigits", "HexDigit", "HexDigitOrUnderscore", 
+		"OctalNumeral", "OctalDigits", "OctalDigit", "OctalDigitOrUnderscore", 
+		"BinaryNumeral", "BinaryDigits", "BinaryDigit", "BinaryDigitOrUnderscore", 
+		"FloatingPointLiteral", "DecimalFloatingPointLiteral", "ExponentPart", 
+		"ExponentIndicator", "SignedInteger", "Sign", "FloatTypeSuffix", "HexadecimalFloatingPointLiteral", 
+		"HexSignificand", "BinaryExponent", "BinaryExponentIndicator", "BooleanLiteral", 
+		"CharacterLiteral", "SingleCharacter", "SingleQuoteString", "DoubleQuoteString", 
+		"StringCharacters", "StringCharacter", "SingleQuoteStringCharacter", "EscapeSequence", 
+		"OctalEscape", "UnicodeEscape", "ZeroToThree", "NullLiteral", "Identifier", 
+		"JavaLetter", "JavaLetterOrDigit", "WS", "ResourceReference", "PackageName", 
+		"ResourceType"
 	};
 
 	private static final String[] _LITERAL_NAMES = {
-		null, "','", "'default'", "'='", "'('", "')'", "'.'", "'['", "']'", "'+'", 
-		"'-'", "'~'", "'!'", "'*'", "'/'", "'%'", "'<<'", "'>>>'", "'>>'", "'<='", 
-		"'>='", "'>'", "'<'", "'instanceof'", "'=='", "'!='", "'&'", "'^'", "'|'", 
-		"'&&'", "'||'", "'?'", "':'", "'??'", "'class'", "'void'", "'boolean'", 
-		"'char'", "'byte'", "'short'", "'int'", "'long'", "'float'", "'double'", 
-		"'this'", null, null, null, null, null, null, "'null'"
+		null, "','", "'default'", "'='", "'->'", "'('", "')'", "'.'", "'::'", 
+		"'['", "']'", "'+'", "'-'", "'~'", "'!'", "'*'", "'/'", "'%'", "'<<'", 
+		"'>>>'", "'>>'", "'<='", "'>='", "'>'", "'<'", "'instanceof'", "'=='", 
+		"'!='", "'&'", "'^'", "'|'", "'&&'", "'||'", "'?'", "':'", "'??'", "'class'", 
+		"'boolean'", "'char'", "'byte'", "'short'", "'int'", "'long'", "'float'", 
+		"'double'", "'this'", null, null, null, null, null, null, null, "'null'"
 	};
 	private static final String[] _SYMBOLIC_NAMES = {
 		null, null, null, null, null, null, null, null, null, null, null, null, 
 		null, null, null, null, null, null, null, null, null, null, null, null, 
 		null, null, null, null, null, null, null, null, null, null, null, null, 
-		null, null, null, null, null, null, null, null, "THIS", "IntegerLiteral", 
-		"FloatingPointLiteral", "BooleanLiteral", "CharacterLiteral", "SingleQuoteString", 
-		"DoubleQuoteString", "NullLiteral", "Identifier", "WS", "ResourceReference", 
-		"PackageName", "ResourceType"
+		null, null, null, null, null, null, null, null, null, "THIS", "VoidLiteral", 
+		"IntegerLiteral", "FloatingPointLiteral", "BooleanLiteral", "CharacterLiteral", 
+		"SingleQuoteString", "DoubleQuoteString", "NullLiteral", "Identifier", 
+		"WS", "ResourceReference", "PackageName", "ResourceType"
 	};
 	public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
 
@@ -90,7 +97,7 @@
 	}
 
 	@Override
-	@NotNull
+
 	public Vocabulary getVocabulary() {
 		return VOCABULARY;
 	}
@@ -98,7 +105,7 @@
 
 	public BindingExpressionLexer(CharStream input) {
 		super(input);
-		_interp = new LexerATNSimulator(this,_ATN);
+		_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
 	}
 
 	@Override
@@ -114,13 +121,15 @@
 	public String[] getModeNames() { return modeNames; }
 
 	@Override
+	public ATN getATN() { return _ATN; }
+
+	@Override
 	public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) {
 		switch (ruleIndex) {
-		case 93:
-			return JavaLetter_sempred(_localctx, predIndex);
-
-		case 94:
-			return JavaLetterOrDigit_sempred(_localctx, predIndex);
+		case 95:
+			return JavaLetter_sempred((RuleContext)_localctx, predIndex);
+		case 96:
+			return JavaLetterOrDigit_sempred((RuleContext)_localctx, predIndex);
 		}
 		return true;
 	}
@@ -128,7 +137,6 @@
 		switch (predIndex) {
 		case 0:
 			return Character.isJavaIdentifierStart(_input.LA(-1));
-
 		case 1:
 			return Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)));
 		}
@@ -138,7 +146,6 @@
 		switch (predIndex) {
 		case 2:
 			return Character.isJavaIdentifierPart(_input.LA(-1));
-
 		case 3:
 			return Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)));
 		}
@@ -146,7 +153,7 @@
 	}
 
 	public static final String _serializedATN =
-		"\3\uaf6f\u8320\u479d\ub75c\u4880\u1605\u191c\uab37\2:\u0358\b\1\4\2\t"+
+		"\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2<\u0370\b\1\4\2\t"+
 		"\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13"+
 		"\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
 		"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t\30\4\31\t\31"+
@@ -157,300 +164,311 @@
 		"\4>\t>\4?\t?\4@\t@\4A\tA\4B\tB\4C\tC\4D\tD\4E\tE\4F\tF\4G\tG\4H\tH\4I"+
 		"\tI\4J\tJ\4K\tK\4L\tL\4M\tM\4N\tN\4O\tO\4P\tP\4Q\tQ\4R\tR\4S\tS\4T\tT"+
 		"\4U\tU\4V\tV\4W\tW\4X\tX\4Y\tY\4Z\tZ\4[\t[\4\\\t\\\4]\t]\4^\t^\4_\t_\4"+
-		"`\t`\4a\ta\4b\tb\4c\tc\4d\td\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3"+
-		"\4\3\4\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\n\3\n\3\13\3\13\3\f\3"+
-		"\f\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\21\3\21\3\21\3\22\3\22\3\22"+
-		"\3\22\3\23\3\23\3\23\3\24\3\24\3\24\3\25\3\25\3\25\3\26\3\26\3\27\3\27"+
-		"\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3\31"+
-		"\3\32\3\32\3\32\3\33\3\33\3\34\3\34\3\35\3\35\3\36\3\36\3\36\3\37\3\37"+
-		"\3\37\3 \3 \3!\3!\3\"\3\"\3\"\3#\3#\3#\3#\3#\3#\3$\3$\3$\3$\3$\3%\3%\3"+
-		"%\3%\3%\3%\3%\3%\3&\3&\3&\3&\3&\3\'\3\'\3\'\3\'\3\'\3(\3(\3(\3(\3(\3("+
-		"\3)\3)\3)\3)\3*\3*\3*\3*\3*\3+\3+\3+\3+\3+\3+\3,\3,\3,\3,\3,\3,\3,\3-"+
-		"\3-\3-\3-\3-\3.\3.\3.\3.\5.\u0168\n.\3/\3/\5/\u016c\n/\3\60\3\60\5\60"+
-		"\u0170\n\60\3\61\3\61\5\61\u0174\n\61\3\62\3\62\5\62\u0178\n\62\3\63\3"+
-		"\63\3\64\3\64\3\64\5\64\u017f\n\64\3\64\3\64\3\64\5\64\u0184\n\64\5\64"+
-		"\u0186\n\64\3\65\3\65\7\65\u018a\n\65\f\65\16\65\u018d\13\65\3\65\5\65"+
-		"\u0190\n\65\3\66\3\66\5\66\u0194\n\66\3\67\3\67\38\38\58\u019a\n8\39\6"+
-		"9\u019d\n9\r9\169\u019e\3:\3:\3:\3:\3;\3;\7;\u01a7\n;\f;\16;\u01aa\13"+
-		";\3;\5;\u01ad\n;\3<\3<\3=\3=\5=\u01b3\n=\3>\3>\5>\u01b7\n>\3>\3>\3?\3"+
-		"?\7?\u01bd\n?\f?\16?\u01c0\13?\3?\5?\u01c3\n?\3@\3@\3A\3A\5A\u01c9\nA"+
-		"\3B\3B\3B\3B\3C\3C\7C\u01d1\nC\fC\16C\u01d4\13C\3C\5C\u01d7\nC\3D\3D\3"+
-		"E\3E\5E\u01dd\nE\3F\3F\5F\u01e1\nF\3G\3G\3G\5G\u01e6\nG\3G\5G\u01e9\n"+
-		"G\3G\5G\u01ec\nG\3G\3G\3G\5G\u01f1\nG\3G\5G\u01f4\nG\3G\3G\3G\5G\u01f9"+
-		"\nG\3G\3G\3G\5G\u01fe\nG\3H\3H\3H\3I\3I\3J\5J\u0206\nJ\3J\3J\3K\3K\3L"+
-		"\3L\3M\3M\3M\5M\u0211\nM\3N\3N\5N\u0215\nN\3N\3N\3N\5N\u021a\nN\3N\3N"+
-		"\5N\u021e\nN\3O\3O\3O\3P\3P\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\3Q\5Q\u022e\nQ\3R"+
-		"\3R\3R\3R\3R\3R\3R\3R\5R\u0238\nR\3S\3S\3T\3T\7T\u023e\nT\fT\16T\u0241"+
-		"\13T\3T\3T\3U\3U\5U\u0247\nU\3U\3U\3V\6V\u024c\nV\rV\16V\u024d\3W\3W\5"+
-		"W\u0252\nW\3X\3X\5X\u0256\nX\3Y\3Y\3Y\3Y\5Y\u025c\nY\3Z\3Z\3Z\3Z\3Z\3"+
-		"Z\3Z\3Z\3Z\3Z\3Z\5Z\u0269\nZ\3[\3[\3[\3[\3[\3[\3[\3\\\3\\\3]\3]\3]\3]"+
-		"\3]\3^\3^\7^\u027b\n^\f^\16^\u027e\13^\3_\3_\3_\3_\3_\3_\5_\u0286\n_\3"+
-		"`\3`\3`\3`\3`\3`\5`\u028e\n`\3a\6a\u0291\na\ra\16a\u0292\3a\3a\3b\3b\3"+
-		"b\3b\5b\u029b\nb\3b\3b\3b\3b\3c\3c\3c\3c\3c\3c\3c\3c\5c\u02a9\nc\3d\3"+
-		"d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3"+
-		"d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3"+
-		"d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3"+
-		"d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3"+
-		"d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3"+
-		"d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3"+
-		"d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3d\3"+
-		"d\3d\3d\3d\3d\3d\3d\3d\3d\3d\5d\u0357\nd\2\2\2e\3\2\3\5\2\4\7\2\5\t\2"+
-		"\6\13\2\7\r\2\b\17\2\t\21\2\n\23\2\13\25\2\f\27\2\r\31\2\16\33\2\17\35"+
-		"\2\20\37\2\21!\2\22#\2\23%\2\24\'\2\25)\2\26+\2\27-\2\30/\2\31\61\2\32"+
-		"\63\2\33\65\2\34\67\2\359\2\36;\2\37=\2 ?\2!A\2\"C\2#E\2$G\2%I\2&K\2\'"+
-		"M\2(O\2)Q\2*S\2+U\2,W\2-Y\2.[\2/]\2\2_\2\2a\2\2c\2\2e\2\2g\2\2i\2\2k\2"+
-		"\2m\2\2o\2\2q\2\2s\2\2u\2\2w\2\2y\2\2{\2\2}\2\2\177\2\2\u0081\2\2\u0083"+
-		"\2\2\u0085\2\2\u0087\2\2\u0089\2\2\u008b\2\60\u008d\2\2\u008f\2\2\u0091"+
-		"\2\2\u0093\2\2\u0095\2\2\u0097\2\2\u0099\2\2\u009b\2\2\u009d\2\2\u009f"+
-		"\2\2\u00a1\2\61\u00a3\2\62\u00a5\2\2\u00a7\2\63\u00a9\2\64\u00ab\2\2\u00ad"+
-		"\2\2\u00af\2\2\u00b1\2\2\u00b3\2\2\u00b5\2\2\u00b7\2\2\u00b9\2\65\u00bb"+
-		"\2\66\u00bd\2\2\u00bf\2\2\u00c1\2\67\u00c3\28\u00c5\29\u00c7\2:\3\2\30"+
-		"\4\2NNnn\3\2\63;\4\2ZZzz\5\2\62;CHch\3\2\629\4\2DDdd\3\2\62\63\4\2GGg"+
-		"g\4\2--//\6\2FFHHffhh\4\2RRrr\4\2))^^\4\2$$^^\4\2^^bb\13\2$$))^^bbddh"+
-		"hppttvv\3\2\62\65\6\2&&C\\aac|\4\2\2\u0101\ud802\udc01\3\2\ud802\udc01"+
-		"\3\2\udc02\ue001\7\2&&\62;C\\aac|\5\2\13\f\16\17\"\"\u037b\2\3\3\2\2\2"+
-		"\2\5\3\2\2\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2"+
-		"\2\2\2\21\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2"+
-		"\2\33\3\2\2\2\2\35\3\2\2\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2"+
-		"\2\2\'\3\2\2\2\2)\3\2\2\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2"+
-		"\2\2\63\3\2\2\2\2\65\3\2\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2"+
-		"\2\2\2?\3\2\2\2\2A\3\2\2\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2"+
-		"\2K\3\2\2\2\2M\3\2\2\2\2O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W"+
-		"\3\2\2\2\2Y\3\2\2\2\2[\3\2\2\2\2\u008b\3\2\2\2\2\u00a1\3\2\2\2\2\u00a3"+
-		"\3\2\2\2\2\u00a7\3\2\2\2\2\u00a9\3\2\2\2\2\u00b9\3\2\2\2\2\u00bb\3\2\2"+
-		"\2\2\u00c1\3\2\2\2\2\u00c3\3\2\2\2\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\3\u00c9"+
-		"\3\2\2\2\5\u00cb\3\2\2\2\7\u00d3\3\2\2\2\t\u00d5\3\2\2\2\13\u00d7\3\2"+
-		"\2\2\r\u00d9\3\2\2\2\17\u00db\3\2\2\2\21\u00dd\3\2\2\2\23\u00df\3\2\2"+
-		"\2\25\u00e1\3\2\2\2\27\u00e3\3\2\2\2\31\u00e5\3\2\2\2\33\u00e7\3\2\2\2"+
-		"\35\u00e9\3\2\2\2\37\u00eb\3\2\2\2!\u00ed\3\2\2\2#\u00f0\3\2\2\2%\u00f4"+
-		"\3\2\2\2\'\u00f7\3\2\2\2)\u00fa\3\2\2\2+\u00fd\3\2\2\2-\u00ff\3\2\2\2"+
-		"/\u0101\3\2\2\2\61\u010c\3\2\2\2\63\u010f\3\2\2\2\65\u0112\3\2\2\2\67"+
-		"\u0114\3\2\2\29\u0116\3\2\2\2;\u0118\3\2\2\2=\u011b\3\2\2\2?\u011e\3\2"+
-		"\2\2A\u0120\3\2\2\2C\u0122\3\2\2\2E\u0125\3\2\2\2G\u012b\3\2\2\2I\u0130"+
-		"\3\2\2\2K\u0138\3\2\2\2M\u013d\3\2\2\2O\u0142\3\2\2\2Q\u0148\3\2\2\2S"+
-		"\u014c\3\2\2\2U\u0151\3\2\2\2W\u0157\3\2\2\2Y\u015e\3\2\2\2[\u0167\3\2"+
-		"\2\2]\u0169\3\2\2\2_\u016d\3\2\2\2a\u0171\3\2\2\2c\u0175\3\2\2\2e\u0179"+
-		"\3\2\2\2g\u0185\3\2\2\2i\u0187\3\2\2\2k\u0193\3\2\2\2m\u0195\3\2\2\2o"+
-		"\u0199\3\2\2\2q\u019c\3\2\2\2s\u01a0\3\2\2\2u\u01a4\3\2\2\2w\u01ae\3\2"+
-		"\2\2y\u01b2\3\2\2\2{\u01b4\3\2\2\2}\u01ba\3\2\2\2\177\u01c4\3\2\2\2\u0081"+
-		"\u01c8\3\2\2\2\u0083\u01ca\3\2\2\2\u0085\u01ce\3\2\2\2\u0087\u01d8\3\2"+
-		"\2\2\u0089\u01dc\3\2\2\2\u008b\u01e0\3\2\2\2\u008d\u01fd\3\2\2\2\u008f"+
-		"\u01ff\3\2\2\2\u0091\u0202\3\2\2\2\u0093\u0205\3\2\2\2\u0095\u0209\3\2"+
-		"\2\2\u0097\u020b\3\2\2\2\u0099\u020d\3\2\2\2\u009b\u021d\3\2\2\2\u009d"+
-		"\u021f\3\2\2\2\u009f\u0222\3\2\2\2\u00a1\u022d\3\2\2\2\u00a3\u0237\3\2"+
-		"\2\2\u00a5\u0239\3\2\2\2\u00a7\u023b\3\2\2\2\u00a9\u0244\3\2\2\2\u00ab"+
-		"\u024b\3\2\2\2\u00ad\u0251\3\2\2\2\u00af\u0255\3\2\2\2\u00b1\u025b\3\2"+
-		"\2\2\u00b3\u0268\3\2\2\2\u00b5\u026a\3\2\2\2\u00b7\u0271\3\2\2\2\u00b9"+
-		"\u0273\3\2\2\2\u00bb\u0278\3\2\2\2\u00bd\u0285\3\2\2\2\u00bf\u028d\3\2"+
-		"\2\2\u00c1\u0290\3\2\2\2\u00c3\u0296\3\2\2\2\u00c5\u02a8\3\2\2\2\u00c7"+
-		"\u0356\3\2\2\2\u00c9\u00ca\7.\2\2\u00ca\4\3\2\2\2\u00cb\u00cc\7f\2\2\u00cc"+
-		"\u00cd\7g\2\2\u00cd\u00ce\7h\2\2\u00ce\u00cf\7c\2\2\u00cf\u00d0\7w\2\2"+
-		"\u00d0\u00d1\7n\2\2\u00d1\u00d2\7v\2\2\u00d2\6\3\2\2\2\u00d3\u00d4\7?"+
-		"\2\2\u00d4\b\3\2\2\2\u00d5\u00d6\7*\2\2\u00d6\n\3\2\2\2\u00d7\u00d8\7"+
-		"+\2\2\u00d8\f\3\2\2\2\u00d9\u00da\7\60\2\2\u00da\16\3\2\2\2\u00db\u00dc"+
-		"\7]\2\2\u00dc\20\3\2\2\2\u00dd\u00de\7_\2\2\u00de\22\3\2\2\2\u00df\u00e0"+
-		"\7-\2\2\u00e0\24\3\2\2\2\u00e1\u00e2\7/\2\2\u00e2\26\3\2\2\2\u00e3\u00e4"+
-		"\7\u0080\2\2\u00e4\30\3\2\2\2\u00e5\u00e6\7#\2\2\u00e6\32\3\2\2\2\u00e7"+
-		"\u00e8\7,\2\2\u00e8\34\3\2\2\2\u00e9\u00ea\7\61\2\2\u00ea\36\3\2\2\2\u00eb"+
-		"\u00ec\7\'\2\2\u00ec \3\2\2\2\u00ed\u00ee\7>\2\2\u00ee\u00ef\7>\2\2\u00ef"+
-		"\"\3\2\2\2\u00f0\u00f1\7@\2\2\u00f1\u00f2\7@\2\2\u00f2\u00f3\7@\2\2\u00f3"+
-		"$\3\2\2\2\u00f4\u00f5\7@\2\2\u00f5\u00f6\7@\2\2\u00f6&\3\2\2\2\u00f7\u00f8"+
-		"\7>\2\2\u00f8\u00f9\7?\2\2\u00f9(\3\2\2\2\u00fa\u00fb\7@\2\2\u00fb\u00fc"+
-		"\7?\2\2\u00fc*\3\2\2\2\u00fd\u00fe\7@\2\2\u00fe,\3\2\2\2\u00ff\u0100\7"+
-		">\2\2\u0100.\3\2\2\2\u0101\u0102\7k\2\2\u0102\u0103\7p\2\2\u0103\u0104"+
-		"\7u\2\2\u0104\u0105\7v\2\2\u0105\u0106\7c\2\2\u0106\u0107\7p\2\2\u0107"+
-		"\u0108\7e\2\2\u0108\u0109\7g\2\2\u0109\u010a\7q\2\2\u010a\u010b\7h\2\2"+
-		"\u010b\60\3\2\2\2\u010c\u010d\7?\2\2\u010d\u010e\7?\2\2\u010e\62\3\2\2"+
-		"\2\u010f\u0110\7#\2\2\u0110\u0111\7?\2\2\u0111\64\3\2\2\2\u0112\u0113"+
-		"\7(\2\2\u0113\66\3\2\2\2\u0114\u0115\7`\2\2\u01158\3\2\2\2\u0116\u0117"+
-		"\7~\2\2\u0117:\3\2\2\2\u0118\u0119\7(\2\2\u0119\u011a\7(\2\2\u011a<\3"+
-		"\2\2\2\u011b\u011c\7~\2\2\u011c\u011d\7~\2\2\u011d>\3\2\2\2\u011e\u011f"+
-		"\7A\2\2\u011f@\3\2\2\2\u0120\u0121\7<\2\2\u0121B\3\2\2\2\u0122\u0123\7"+
-		"A\2\2\u0123\u0124\7A\2\2\u0124D\3\2\2\2\u0125\u0126\7e\2\2\u0126\u0127"+
-		"\7n\2\2\u0127\u0128\7c\2\2\u0128\u0129\7u\2\2\u0129\u012a\7u\2\2\u012a"+
-		"F\3\2\2\2\u012b\u012c\7x\2\2\u012c\u012d\7q\2\2\u012d\u012e\7k\2\2\u012e"+
-		"\u012f\7f\2\2\u012fH\3\2\2\2\u0130\u0131\7d\2\2\u0131\u0132\7q\2\2\u0132"+
-		"\u0133\7q\2\2\u0133\u0134\7n\2\2\u0134\u0135\7g\2\2\u0135\u0136\7c\2\2"+
-		"\u0136\u0137\7p\2\2\u0137J\3\2\2\2\u0138\u0139\7e\2\2\u0139\u013a\7j\2"+
-		"\2\u013a\u013b\7c\2\2\u013b\u013c\7t\2\2\u013cL\3\2\2\2\u013d\u013e\7"+
-		"d\2\2\u013e\u013f\7{\2\2\u013f\u0140\7v\2\2\u0140\u0141\7g\2\2\u0141N"+
-		"\3\2\2\2\u0142\u0143\7u\2\2\u0143\u0144\7j\2\2\u0144\u0145\7q\2\2\u0145"+
-		"\u0146\7t\2\2\u0146\u0147\7v\2\2\u0147P\3\2\2\2\u0148\u0149\7k\2\2\u0149"+
-		"\u014a\7p\2\2\u014a\u014b\7v\2\2\u014bR\3\2\2\2\u014c\u014d\7n\2\2\u014d"+
-		"\u014e\7q\2\2\u014e\u014f\7p\2\2\u014f\u0150\7i\2\2\u0150T\3\2\2\2\u0151"+
-		"\u0152\7h\2\2\u0152\u0153\7n\2\2\u0153\u0154\7q\2\2\u0154\u0155\7c\2\2"+
-		"\u0155\u0156\7v\2\2\u0156V\3\2\2\2\u0157\u0158\7f\2\2\u0158\u0159\7q\2"+
-		"\2\u0159\u015a\7w\2\2\u015a\u015b\7d\2\2\u015b\u015c\7n\2\2\u015c\u015d"+
-		"\7g\2\2\u015dX\3\2\2\2\u015e\u015f\7v\2\2\u015f\u0160\7j\2\2\u0160\u0161"+
-		"\7k\2\2\u0161\u0162\7u\2\2\u0162Z\3\2\2\2\u0163\u0168\5]/\2\u0164\u0168"+
-		"\5_\60\2\u0165\u0168\5a\61\2\u0166\u0168\5c\62\2\u0167\u0163\3\2\2\2\u0167"+
-		"\u0164\3\2\2\2\u0167\u0165\3\2\2\2\u0167\u0166\3\2\2\2\u0168\\\3\2\2\2"+
-		"\u0169\u016b\5g\64\2\u016a\u016c\5e\63\2\u016b\u016a\3\2\2\2\u016b\u016c"+
-		"\3\2\2\2\u016c^\3\2\2\2\u016d\u016f\5s:\2\u016e\u0170\5e\63\2\u016f\u016e"+
-		"\3\2\2\2\u016f\u0170\3\2\2\2\u0170`\3\2\2\2\u0171\u0173\5{>\2\u0172\u0174"+
-		"\5e\63\2\u0173\u0172\3\2\2\2\u0173\u0174\3\2\2\2\u0174b\3\2\2\2\u0175"+
-		"\u0177\5\u0083B\2\u0176\u0178\5e\63\2\u0177\u0176\3\2\2\2\u0177\u0178"+
-		"\3\2\2\2\u0178d\3\2\2\2\u0179\u017a\t\2\2\2\u017af\3\2\2\2\u017b\u0186"+
-		"\7\62\2\2\u017c\u0183\5m\67\2\u017d\u017f\5i\65\2\u017e\u017d\3\2\2\2"+
-		"\u017e\u017f\3\2\2\2\u017f\u0184\3\2\2\2\u0180\u0181\5q9\2\u0181\u0182"+
-		"\5i\65\2\u0182\u0184\3\2\2\2\u0183\u017e\3\2\2\2\u0183\u0180\3\2\2\2\u0184"+
-		"\u0186\3\2\2\2\u0185\u017b\3\2\2\2\u0185\u017c\3\2\2\2\u0186h\3\2\2\2"+
-		"\u0187\u018f\5k\66\2\u0188\u018a\5o8\2\u0189\u0188\3\2\2\2\u018a\u018d"+
-		"\3\2\2\2\u018b\u0189\3\2\2\2\u018b\u018c\3\2\2\2\u018c\u018e\3\2\2\2\u018d"+
-		"\u018b\3\2\2\2\u018e\u0190\5k\66\2\u018f\u018b\3\2\2\2\u018f\u0190\3\2"+
-		"\2\2\u0190j\3\2\2\2\u0191\u0194\7\62\2\2\u0192\u0194\5m\67\2\u0193\u0191"+
-		"\3\2\2\2\u0193\u0192\3\2\2\2\u0194l\3\2\2\2\u0195\u0196\t\3\2\2\u0196"+
-		"n\3\2\2\2\u0197\u019a\5k\66\2\u0198\u019a\7a\2\2\u0199\u0197\3\2\2\2\u0199"+
-		"\u0198\3\2\2\2\u019ap\3\2\2\2\u019b\u019d\7a\2\2\u019c\u019b\3\2\2\2\u019d"+
-		"\u019e\3\2\2\2\u019e\u019c\3\2\2\2\u019e\u019f\3\2\2\2\u019fr\3\2\2\2"+
-		"\u01a0\u01a1\7\62\2\2\u01a1\u01a2\t\4\2\2\u01a2\u01a3\5u;\2\u01a3t\3\2"+
-		"\2\2\u01a4\u01ac\5w<\2\u01a5\u01a7\5y=\2\u01a6\u01a5\3\2\2\2\u01a7\u01aa"+
-		"\3\2\2\2\u01a8\u01a6\3\2\2\2\u01a8\u01a9\3\2\2\2\u01a9\u01ab\3\2\2\2\u01aa"+
-		"\u01a8\3\2\2\2\u01ab\u01ad\5w<\2\u01ac\u01a8\3\2\2\2\u01ac\u01ad\3\2\2"+
-		"\2\u01adv\3\2\2\2\u01ae\u01af\t\5\2\2\u01afx\3\2\2\2\u01b0\u01b3\5w<\2"+
-		"\u01b1\u01b3\7a\2\2\u01b2\u01b0\3\2\2\2\u01b2\u01b1\3\2\2\2\u01b3z\3\2"+
-		"\2\2\u01b4\u01b6\7\62\2\2\u01b5\u01b7\5q9\2\u01b6\u01b5\3\2\2\2\u01b6"+
-		"\u01b7\3\2\2\2\u01b7\u01b8\3\2\2\2\u01b8\u01b9\5}?\2\u01b9|\3\2\2\2\u01ba"+
-		"\u01c2\5\177@\2\u01bb\u01bd\5\u0081A\2\u01bc\u01bb\3\2\2\2\u01bd\u01c0"+
-		"\3\2\2\2\u01be\u01bc\3\2\2\2\u01be\u01bf\3\2\2\2\u01bf\u01c1\3\2\2\2\u01c0"+
-		"\u01be\3\2\2\2\u01c1\u01c3\5\177@\2\u01c2\u01be\3\2\2\2\u01c2\u01c3\3"+
-		"\2\2\2\u01c3~\3\2\2\2\u01c4\u01c5\t\6\2\2\u01c5\u0080\3\2\2\2\u01c6\u01c9"+
-		"\5\177@\2\u01c7\u01c9\7a\2\2\u01c8\u01c6\3\2\2\2\u01c8\u01c7\3\2\2\2\u01c9"+
-		"\u0082\3\2\2\2\u01ca\u01cb\7\62\2\2\u01cb\u01cc\t\7\2\2\u01cc\u01cd\5"+
-		"\u0085C\2\u01cd\u0084\3\2\2\2\u01ce\u01d6\5\u0087D\2\u01cf\u01d1\5\u0089"+
-		"E\2\u01d0\u01cf\3\2\2\2\u01d1\u01d4\3\2\2\2\u01d2\u01d0\3\2\2\2\u01d2"+
-		"\u01d3\3\2\2\2\u01d3\u01d5\3\2\2\2\u01d4\u01d2\3\2\2\2\u01d5\u01d7\5\u0087"+
-		"D\2\u01d6\u01d2\3\2\2\2\u01d6\u01d7\3\2\2\2\u01d7\u0086\3\2\2\2\u01d8"+
-		"\u01d9\t\b\2\2\u01d9\u0088\3\2\2\2\u01da\u01dd\5\u0087D\2\u01db\u01dd"+
-		"\7a\2\2\u01dc\u01da\3\2\2\2\u01dc\u01db\3\2\2\2\u01dd\u008a\3\2\2\2\u01de"+
-		"\u01e1\5\u008dG\2\u01df\u01e1\5\u0099M\2\u01e0\u01de\3\2\2\2\u01e0\u01df"+
-		"\3\2\2\2\u01e1\u008c\3\2\2\2\u01e2\u01e3\5i\65\2\u01e3\u01e5\7\60\2\2"+
-		"\u01e4\u01e6\5i\65\2\u01e5\u01e4\3\2\2\2\u01e5\u01e6\3\2\2\2\u01e6\u01e8"+
-		"\3\2\2\2\u01e7\u01e9\5\u008fH\2\u01e8\u01e7\3\2\2\2\u01e8\u01e9\3\2\2"+
-		"\2\u01e9\u01eb\3\2\2\2\u01ea\u01ec\5\u0097L\2\u01eb\u01ea\3\2\2\2\u01eb"+
-		"\u01ec\3\2\2\2\u01ec\u01fe\3\2\2\2\u01ed\u01ee\7\60\2\2\u01ee\u01f0\5"+
-		"i\65\2\u01ef\u01f1\5\u008fH\2\u01f0\u01ef\3\2\2\2\u01f0\u01f1\3\2\2\2"+
-		"\u01f1\u01f3\3\2\2\2\u01f2\u01f4\5\u0097L\2\u01f3\u01f2\3\2\2\2\u01f3"+
-		"\u01f4\3\2\2\2\u01f4\u01fe\3\2\2\2\u01f5\u01f6\5i\65\2\u01f6\u01f8\5\u008f"+
-		"H\2\u01f7\u01f9\5\u0097L\2\u01f8\u01f7\3\2\2\2\u01f8\u01f9\3\2\2\2\u01f9"+
-		"\u01fe\3\2\2\2\u01fa\u01fb\5i\65\2\u01fb\u01fc\5\u0097L\2\u01fc\u01fe"+
-		"\3\2\2\2\u01fd\u01e2\3\2\2\2\u01fd\u01ed\3\2\2\2\u01fd\u01f5\3\2\2\2\u01fd"+
-		"\u01fa\3\2\2\2\u01fe\u008e\3\2\2\2\u01ff\u0200\5\u0091I\2\u0200\u0201"+
-		"\5\u0093J\2\u0201\u0090\3\2\2\2\u0202\u0203\t\t\2\2\u0203\u0092\3\2\2"+
-		"\2\u0204\u0206\5\u0095K\2\u0205\u0204\3\2\2\2\u0205\u0206\3\2\2\2\u0206"+
-		"\u0207\3\2\2\2\u0207\u0208\5i\65\2\u0208\u0094\3\2\2\2\u0209\u020a\t\n"+
-		"\2\2\u020a\u0096\3\2\2\2\u020b\u020c\t\13\2\2\u020c\u0098\3\2\2\2\u020d"+
-		"\u020e\5\u009bN\2\u020e\u0210\5\u009dO\2\u020f\u0211\5\u0097L\2\u0210"+
-		"\u020f\3\2\2\2\u0210\u0211\3\2\2\2\u0211\u009a\3\2\2\2\u0212\u0214\5s"+
-		":\2\u0213\u0215\7\60\2\2\u0214\u0213\3\2\2\2\u0214\u0215\3\2\2\2\u0215"+
-		"\u021e\3\2\2\2\u0216\u0217\7\62\2\2\u0217\u0219\t\4\2\2\u0218\u021a\5"+
-		"u;\2\u0219\u0218\3\2\2\2\u0219\u021a\3\2\2\2\u021a\u021b\3\2\2\2\u021b"+
-		"\u021c\7\60\2\2\u021c\u021e\5u;\2\u021d\u0212\3\2\2\2\u021d\u0216\3\2"+
-		"\2\2\u021e\u009c\3\2\2\2\u021f\u0220\5\u009fP\2\u0220\u0221\5\u0093J\2"+
-		"\u0221\u009e\3\2\2\2\u0222\u0223\t\f\2\2\u0223\u00a0\3\2\2\2\u0224\u0225"+
-		"\7v\2\2\u0225\u0226\7t\2\2\u0226\u0227\7w\2\2\u0227\u022e\7g\2\2\u0228"+
-		"\u0229\7h\2\2\u0229\u022a\7c\2\2\u022a\u022b\7n\2\2\u022b\u022c\7u\2\2"+
-		"\u022c\u022e\7g\2\2\u022d\u0224\3\2\2\2\u022d\u0228\3\2\2\2\u022e\u00a2"+
-		"\3\2\2\2\u022f\u0230\7)\2\2\u0230\u0231\5\u00a5S\2\u0231\u0232\7)\2\2"+
-		"\u0232\u0238\3\2\2\2\u0233\u0234\7)\2\2\u0234\u0235\5\u00b1Y\2\u0235\u0236"+
-		"\7)\2\2\u0236\u0238\3\2\2\2\u0237\u022f\3\2\2\2\u0237\u0233\3\2\2\2\u0238"+
-		"\u00a4\3\2\2\2\u0239\u023a\n\r\2\2\u023a\u00a6\3\2\2\2\u023b\u023f\7b"+
-		"\2\2\u023c\u023e\5\u00afX\2\u023d\u023c\3\2\2\2\u023e\u0241\3\2\2\2\u023f"+
-		"\u023d\3\2\2\2\u023f\u0240\3\2\2\2\u0240\u0242\3\2\2\2\u0241\u023f\3\2"+
-		"\2\2\u0242\u0243\7b\2\2\u0243\u00a8\3\2\2\2\u0244\u0246\7$\2\2\u0245\u0247"+
-		"\5\u00abV\2\u0246\u0245\3\2\2\2\u0246\u0247\3\2\2\2\u0247\u0248\3\2\2"+
-		"\2\u0248\u0249\7$\2\2\u0249\u00aa\3\2\2\2\u024a\u024c\5\u00adW\2\u024b"+
-		"\u024a\3\2\2\2\u024c\u024d\3\2\2\2\u024d\u024b\3\2\2\2\u024d\u024e\3\2"+
-		"\2\2\u024e\u00ac\3\2\2\2\u024f\u0252\n\16\2\2\u0250\u0252\5\u00b1Y\2\u0251"+
-		"\u024f\3\2\2\2\u0251\u0250\3\2\2\2\u0252\u00ae\3\2\2\2\u0253\u0256\n\17"+
-		"\2\2\u0254\u0256\5\u00b1Y\2\u0255\u0253\3\2\2\2\u0255\u0254\3\2\2\2\u0256"+
-		"\u00b0\3\2\2\2\u0257\u0258\7^\2\2\u0258\u025c\t\20\2\2\u0259\u025c\5\u00b3"+
-		"Z\2\u025a\u025c\5\u00b5[\2\u025b\u0257\3\2\2\2\u025b\u0259\3\2\2\2\u025b"+
-		"\u025a\3\2\2\2\u025c\u00b2\3\2\2\2\u025d\u025e\7^\2\2\u025e\u0269\5\177"+
-		"@\2\u025f\u0260\7^\2\2\u0260\u0261\5\177@\2\u0261\u0262\5\177@\2\u0262"+
-		"\u0269\3\2\2\2\u0263\u0264\7^\2\2\u0264\u0265\5\u00b7\\\2\u0265\u0266"+
-		"\5\177@\2\u0266\u0267\5\177@\2\u0267\u0269\3\2\2\2\u0268\u025d\3\2\2\2"+
-		"\u0268\u025f\3\2\2\2\u0268\u0263\3\2\2\2\u0269\u00b4\3\2\2\2\u026a\u026b"+
-		"\7^\2\2\u026b\u026c\7w\2\2\u026c\u026d\5w<\2\u026d\u026e\5w<\2\u026e\u026f"+
-		"\5w<\2\u026f\u0270\5w<\2\u0270\u00b6\3\2\2\2\u0271\u0272\t\21\2\2\u0272"+
-		"\u00b8\3\2\2\2\u0273\u0274\7p\2\2\u0274\u0275\7w\2\2\u0275\u0276\7n\2"+
-		"\2\u0276\u0277\7n\2\2\u0277\u00ba\3\2\2\2\u0278\u027c\5\u00bd_\2\u0279"+
-		"\u027b\5\u00bf`\2\u027a\u0279\3\2\2\2\u027b\u027e\3\2\2\2\u027c\u027a"+
-		"\3\2\2\2\u027c\u027d\3\2\2\2\u027d\u00bc\3\2\2\2\u027e\u027c\3\2\2\2\u027f"+
-		"\u0286\t\22\2\2\u0280\u0281\n\23\2\2\u0281\u0286\6_\2\2\u0282\u0283\t"+
-		"\24\2\2\u0283\u0284\t\25\2\2\u0284\u0286\6_\3\2\u0285\u027f\3\2\2\2\u0285"+
-		"\u0280\3\2\2\2\u0285\u0282\3\2\2\2\u0286\u00be\3\2\2\2\u0287\u028e\t\26"+
-		"\2\2\u0288\u0289\n\23\2\2\u0289\u028e\6`\4\2\u028a\u028b\t\24\2\2\u028b"+
-		"\u028c\t\25\2\2\u028c\u028e\6`\5\2\u028d\u0287\3\2\2\2\u028d\u0288\3\2"+
-		"\2\2\u028d\u028a\3\2\2\2\u028e\u00c0\3\2\2\2\u028f\u0291\t\27\2\2\u0290"+
-		"\u028f\3\2\2\2\u0291\u0292\3\2\2\2\u0292\u0290\3\2\2\2\u0292\u0293\3\2"+
-		"\2\2\u0293\u0294\3\2\2\2\u0294\u0295\ba\2\2\u0295\u00c2\3\2\2\2\u0296"+
-		"\u029a\7B\2\2\u0297\u0298\5\u00c5c\2\u0298\u0299\7<\2\2\u0299\u029b\3"+
-		"\2\2\2\u029a\u0297\3\2\2\2\u029a\u029b\3\2\2\2\u029b\u029c\3\2\2\2\u029c"+
-		"\u029d\5\u00c7d\2\u029d\u029e\7\61\2\2\u029e\u029f\5\u00bb^\2\u029f\u00c4"+
-		"\3\2\2\2\u02a0\u02a1\7c\2\2\u02a1\u02a2\7p\2\2\u02a2\u02a3\7f\2\2\u02a3"+
-		"\u02a4\7t\2\2\u02a4\u02a5\7q\2\2\u02a5\u02a6\7k\2\2\u02a6\u02a9\7f\2\2"+
-		"\u02a7\u02a9\5\u00bb^\2\u02a8\u02a0\3\2\2\2\u02a8\u02a7\3\2\2\2\u02a9"+
-		"\u00c6\3\2\2\2\u02aa\u02ab\7c\2\2\u02ab\u02ac\7p\2\2\u02ac\u02ad\7k\2"+
-		"\2\u02ad\u0357\7o\2\2\u02ae\u02af\7c\2\2\u02af\u02b0\7p\2\2\u02b0\u02b1"+
-		"\7k\2\2\u02b1\u02b2\7o\2\2\u02b2\u02b3\7c\2\2\u02b3\u02b4\7v\2\2\u02b4"+
-		"\u02b5\7q\2\2\u02b5\u0357\7t\2\2\u02b6\u02b7\7d\2\2\u02b7\u02b8\7q\2\2"+
-		"\u02b8\u02b9\7q\2\2\u02b9\u0357\7n\2\2\u02ba\u02bb\7e\2\2\u02bb\u02bc"+
-		"\7q\2\2\u02bc\u02bd\7n\2\2\u02bd\u02be\7q\2\2\u02be\u0357\7t\2\2\u02bf"+
-		"\u02c0\7e\2\2\u02c0\u02c1\7q\2\2\u02c1\u02c2\7n\2\2\u02c2\u02c3\7q\2\2"+
-		"\u02c3\u02c4\7t\2\2\u02c4\u02c5\7U\2\2\u02c5\u02c6\7v\2\2\u02c6\u02c7"+
-		"\7c\2\2\u02c7\u02c8\7v\2\2\u02c8\u02c9\7g\2\2\u02c9\u02ca\7N\2\2\u02ca"+
-		"\u02cb\7k\2\2\u02cb\u02cc\7u\2\2\u02cc\u0357\7v\2\2\u02cd\u02ce\7f\2\2"+
-		"\u02ce\u02cf\7k\2\2\u02cf\u02d0\7o\2\2\u02d0\u02d1\7g\2\2\u02d1\u0357"+
-		"\7p\2\2\u02d2\u02d3\7f\2\2\u02d3\u02d4\7k\2\2\u02d4\u02d5\7o\2\2\u02d5"+
-		"\u02d6\7g\2\2\u02d6\u02d7\7p\2\2\u02d7\u02d8\7Q\2\2\u02d8\u02d9\7h\2\2"+
-		"\u02d9\u02da\7h\2\2\u02da\u02db\7u\2\2\u02db\u02dc\7g\2\2\u02dc\u0357"+
-		"\7v\2\2\u02dd\u02de\7f\2\2\u02de\u02df\7k\2\2\u02df\u02e0\7o\2\2\u02e0"+
-		"\u02e1\7g\2\2\u02e1\u02e2\7p\2\2\u02e2\u02e3\7U\2\2\u02e3\u02e4\7k\2\2"+
-		"\u02e4\u02e5\7|\2\2\u02e5\u0357\7g\2\2\u02e6\u02e7\7f\2\2\u02e7\u02e8"+
-		"\7t\2\2\u02e8\u02e9\7c\2\2\u02e9\u02ea\7y\2\2\u02ea\u02eb\7c\2\2\u02eb"+
-		"\u02ec\7d\2\2\u02ec\u02ed\7n\2\2\u02ed\u0357\7g\2\2\u02ee\u02ef\7h\2\2"+
-		"\u02ef\u02f0\7t\2\2\u02f0\u02f1\7c\2\2\u02f1\u02f2\7e\2\2\u02f2\u02f3"+
-		"\7v\2\2\u02f3\u02f4\7k\2\2\u02f4\u02f5\7q\2\2\u02f5\u0357\7p\2\2\u02f6"+
-		"\u02f7\7k\2\2\u02f7\u0357\7f\2\2\u02f8\u02f9\7k\2\2\u02f9\u02fa\7p\2\2"+
-		"\u02fa\u02fb\7v\2\2\u02fb\u02fc\7g\2\2\u02fc\u02fd\7i\2\2\u02fd\u02fe"+
-		"\7g\2\2\u02fe\u0357\7t\2\2\u02ff\u0300\7k\2\2\u0300\u0301\7p\2\2\u0301"+
-		"\u0302\7v\2\2\u0302\u0303\7C\2\2\u0303\u0304\7t\2\2\u0304\u0305\7t\2\2"+
-		"\u0305\u0306\7c\2\2\u0306\u0357\7{\2\2\u0307\u0308\7k\2\2\u0308\u0309"+
-		"\7p\2\2\u0309\u030a\7v\2\2\u030a\u030b\7g\2\2\u030b\u030c\7t\2\2\u030c"+
-		"\u030d\7r\2\2\u030d\u030e\7q\2\2\u030e\u030f\7n\2\2\u030f\u0310\7c\2\2"+
-		"\u0310\u0311\7v\2\2\u0311\u0312\7q\2\2\u0312\u0357\7t\2\2\u0313\u0314"+
-		"\7n\2\2\u0314\u0315\7c\2\2\u0315\u0316\7{\2\2\u0316\u0317\7q\2\2\u0317"+
-		"\u0318\7w\2\2\u0318\u0357\7v\2\2\u0319\u031a\7r\2\2\u031a\u031b\7n\2\2"+
-		"\u031b\u031c\7w\2\2\u031c\u031d\7t\2\2\u031d\u031e\7c\2\2\u031e\u031f"+
-		"\7n\2\2\u031f\u0357\7u\2\2\u0320\u0321\7u\2\2\u0321\u0322\7v\2\2\u0322"+
-		"\u0323\7c\2\2\u0323\u0324\7v\2\2\u0324\u0325\7g\2\2\u0325\u0326\7N\2\2"+
-		"\u0326\u0327\7k\2\2\u0327\u0328\7u\2\2\u0328\u0329\7v\2\2\u0329\u032a"+
-		"\7C\2\2\u032a\u032b\7p\2\2\u032b\u032c\7k\2\2\u032c\u032d\7o\2\2\u032d"+
-		"\u032e\7c\2\2\u032e\u032f\7v\2\2\u032f\u0330\7q\2\2\u0330\u0357\7t\2\2"+
-		"\u0331\u0332\7u\2\2\u0332\u0333\7v\2\2\u0333\u0334\7t\2\2\u0334\u0335"+
-		"\7k\2\2\u0335\u0336\7p\2\2\u0336\u0357\7i\2\2\u0337\u0338\7u\2\2\u0338"+
-		"\u0339\7v\2\2\u0339\u033a\7t\2\2\u033a\u033b\7k\2\2\u033b\u033c\7p\2\2"+
-		"\u033c\u033d\7i\2\2\u033d\u033e\7C\2\2\u033e\u033f\7t\2\2\u033f\u0340"+
-		"\7t\2\2\u0340\u0341\7c\2\2\u0341\u0357\7{\2\2\u0342\u0343\7v\2\2\u0343"+
-		"\u0344\7t\2\2\u0344\u0345\7c\2\2\u0345\u0346\7p\2\2\u0346\u0347\7u\2\2"+
-		"\u0347\u0348\7k\2\2\u0348\u0349\7v\2\2\u0349\u034a\7k\2\2\u034a\u034b"+
-		"\7q\2\2\u034b\u0357\7p\2\2\u034c\u034d\7v\2\2\u034d\u034e\7{\2\2\u034e"+
-		"\u034f\7r\2\2\u034f\u0350\7g\2\2\u0350\u0351\7f\2\2\u0351\u0352\7C\2\2"+
-		"\u0352\u0353\7t\2\2\u0353\u0354\7t\2\2\u0354\u0355\7c\2\2\u0355\u0357"+
-		"\7{\2\2\u0356\u02aa\3\2\2\2\u0356\u02ae\3\2\2\2\u0356\u02b6\3\2\2\2\u0356"+
-		"\u02ba\3\2\2\2\u0356\u02bf\3\2\2\2\u0356\u02cd\3\2\2\2\u0356\u02d2\3\2"+
-		"\2\2\u0356\u02dd\3\2\2\2\u0356\u02e6\3\2\2\2\u0356\u02ee\3\2\2\2\u0356"+
-		"\u02f6\3\2\2\2\u0356\u02f8\3\2\2\2\u0356\u02ff\3\2\2\2\u0356\u0307\3\2"+
-		"\2\2\u0356\u0313\3\2\2\2\u0356\u0319\3\2\2\2\u0356\u0320\3\2\2\2\u0356"+
-		"\u0331\3\2\2\2\u0356\u0337\3\2\2\2\u0356\u0342\3\2\2\2\u0356\u034c\3\2"+
-		"\2\2\u0357\u00c8\3\2\2\2\67\2\u0167\u016b\u016f\u0173\u0177\u017e\u0183"+
-		"\u0185\u018b\u018f\u0193\u0199\u019e\u01a8\u01ac\u01b2\u01b6\u01be\u01c2"+
-		"\u01c8\u01d2\u01d6\u01dc\u01e0\u01e5\u01e8\u01eb\u01f0\u01f3\u01f8\u01fd"+
-		"\u0205\u0210\u0214\u0219\u021d\u022d\u0237\u023f\u0246\u024d\u0251\u0255"+
-		"\u025b\u0268\u027c\u0285\u028d\u0292\u029a\u02a8\u0356\3\b\2\2";
+		"`\t`\4a\ta\4b\tb\4c\tc\4d\td\4e\te\4f\tf\3\2\3\2\3\3\3\3\3\3\3\3\3\3\3"+
+		"\3\3\3\3\3\3\4\3\4\3\5\3\5\3\5\3\6\3\6\3\7\3\7\3\b\3\b\3\t\3\t\3\t\3\n"+
+		"\3\n\3\13\3\13\3\f\3\f\3\r\3\r\3\16\3\16\3\17\3\17\3\20\3\20\3\21\3\21"+
+		"\3\22\3\22\3\23\3\23\3\23\3\24\3\24\3\24\3\24\3\25\3\25\3\25\3\26\3\26"+
+		"\3\26\3\27\3\27\3\27\3\30\3\30\3\31\3\31\3\32\3\32\3\32\3\32\3\32\3\32"+
+		"\3\32\3\32\3\32\3\32\3\32\3\33\3\33\3\33\3\34\3\34\3\34\3\35\3\35\3\36"+
+		"\3\36\3\37\3\37\3 \3 \3 \3!\3!\3!\3\"\3\"\3#\3#\3$\3$\3$\3%\3%\3%\3%\3"+
+		"%\3%\3&\3&\3&\3&\3&\3&\3&\3&\3\'\3\'\3\'\3\'\3\'\3(\3(\3(\3(\3(\3)\3)"+
+		"\3)\3)\3)\3)\3*\3*\3*\3*\3+\3+\3+\3+\3+\3,\3,\3,\3,\3,\3,\3-\3-\3-\3-"+
+		"\3-\3-\3-\3.\3.\3.\3.\3.\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/\3/"+
+		"\3/\3/\5/\u017a\n/\3\60\3\60\3\60\3\60\5\60\u0180\n\60\3\61\3\61\5\61"+
+		"\u0184\n\61\3\62\3\62\5\62\u0188\n\62\3\63\3\63\5\63\u018c\n\63\3\64\3"+
+		"\64\5\64\u0190\n\64\3\65\3\65\3\66\3\66\3\66\5\66\u0197\n\66\3\66\3\66"+
+		"\3\66\5\66\u019c\n\66\5\66\u019e\n\66\3\67\3\67\7\67\u01a2\n\67\f\67\16"+
+		"\67\u01a5\13\67\3\67\5\67\u01a8\n\67\38\38\58\u01ac\n8\39\39\3:\3:\5:"+
+		"\u01b2\n:\3;\6;\u01b5\n;\r;\16;\u01b6\3<\3<\3<\3<\3=\3=\7=\u01bf\n=\f"+
+		"=\16=\u01c2\13=\3=\5=\u01c5\n=\3>\3>\3?\3?\5?\u01cb\n?\3@\3@\5@\u01cf"+
+		"\n@\3@\3@\3A\3A\7A\u01d5\nA\fA\16A\u01d8\13A\3A\5A\u01db\nA\3B\3B\3C\3"+
+		"C\5C\u01e1\nC\3D\3D\3D\3D\3E\3E\7E\u01e9\nE\fE\16E\u01ec\13E\3E\5E\u01ef"+
+		"\nE\3F\3F\3G\3G\5G\u01f5\nG\3H\3H\5H\u01f9\nH\3I\3I\3I\5I\u01fe\nI\3I"+
+		"\5I\u0201\nI\3I\5I\u0204\nI\3I\3I\3I\5I\u0209\nI\3I\5I\u020c\nI\3I\3I"+
+		"\3I\5I\u0211\nI\3I\3I\3I\5I\u0216\nI\3J\3J\3J\3K\3K\3L\5L\u021e\nL\3L"+
+		"\3L\3M\3M\3N\3N\3O\3O\3O\5O\u0229\nO\3P\3P\5P\u022d\nP\3P\3P\3P\5P\u0232"+
+		"\nP\3P\3P\5P\u0236\nP\3Q\3Q\3Q\3R\3R\3S\3S\3S\3S\3S\3S\3S\3S\3S\5S\u0246"+
+		"\nS\3T\3T\3T\3T\3T\3T\3T\3T\5T\u0250\nT\3U\3U\3V\3V\7V\u0256\nV\fV\16"+
+		"V\u0259\13V\3V\3V\3W\3W\5W\u025f\nW\3W\3W\3X\6X\u0264\nX\rX\16X\u0265"+
+		"\3Y\3Y\5Y\u026a\nY\3Z\3Z\5Z\u026e\nZ\3[\3[\3[\3[\5[\u0274\n[\3\\\3\\\3"+
+		"\\\3\\\3\\\3\\\3\\\3\\\3\\\3\\\3\\\5\\\u0281\n\\\3]\3]\3]\3]\3]\3]\3]"+
+		"\3^\3^\3_\3_\3_\3_\3_\3`\3`\7`\u0293\n`\f`\16`\u0296\13`\3a\3a\3a\3a\3"+
+		"a\3a\5a\u029e\na\3b\3b\3b\3b\3b\3b\5b\u02a6\nb\3c\6c\u02a9\nc\rc\16c\u02aa"+
+		"\3c\3c\3d\3d\3d\3d\5d\u02b3\nd\3d\3d\3d\3d\3e\3e\3e\3e\3e\3e\3e\3e\5e"+
+		"\u02c1\ne\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f"+
+		"\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f"+
+		"\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f"+
+		"\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f"+
+		"\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f"+
+		"\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f"+
+		"\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f"+
+		"\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\3f\5f\u036f\nf\2\2g\3\3\5\4\7"+
+		"\5\t\6\13\7\r\b\17\t\21\n\23\13\25\f\27\r\31\16\33\17\35\20\37\21!\22"+
+		"#\23%\24\'\25)\26+\27-\30/\31\61\32\63\33\65\34\67\359\36;\37= ?!A\"C"+
+		"#E$G%I&K\'M(O)Q*S+U,W-Y.[/]\60_\61a\2c\2e\2g\2i\2k\2m\2o\2q\2s\2u\2w\2"+
+		"y\2{\2}\2\177\2\u0081\2\u0083\2\u0085\2\u0087\2\u0089\2\u008b\2\u008d"+
+		"\2\u008f\62\u0091\2\u0093\2\u0095\2\u0097\2\u0099\2\u009b\2\u009d\2\u009f"+
+		"\2\u00a1\2\u00a3\2\u00a5\63\u00a7\64\u00a9\2\u00ab\65\u00ad\66\u00af\2"+
+		"\u00b1\2\u00b3\2\u00b5\2\u00b7\2\u00b9\2\u00bb\2\u00bd\67\u00bf8\u00c1"+
+		"\2\u00c3\2\u00c59\u00c7:\u00c9;\u00cb<\3\2\30\4\2NNnn\3\2\63;\4\2ZZzz"+
+		"\5\2\62;CHch\3\2\629\4\2DDdd\3\2\62\63\4\2GGgg\4\2--//\6\2FFHHffhh\4\2"+
+		"RRrr\4\2))^^\4\2$$^^\4\2^^bb\13\2$$))^^bbddhhppttvv\3\2\62\65\6\2&&C\\"+
+		"aac|\4\2\2\u0101\ud802\udc01\3\2\ud802\udc01\3\2\udc02\ue001\7\2&&\62"+
+		";C\\aac|\5\2\13\f\16\17\"\"\u0395\2\3\3\2\2\2\2\5\3\2\2\2\2\7\3\2\2\2"+
+		"\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3"+
+		"\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\2\31\3\2\2\2\2\33\3\2\2\2\2\35\3\2\2"+
+		"\2\2\37\3\2\2\2\2!\3\2\2\2\2#\3\2\2\2\2%\3\2\2\2\2\'\3\2\2\2\2)\3\2\2"+
+		"\2\2+\3\2\2\2\2-\3\2\2\2\2/\3\2\2\2\2\61\3\2\2\2\2\63\3\2\2\2\2\65\3\2"+
+		"\2\2\2\67\3\2\2\2\29\3\2\2\2\2;\3\2\2\2\2=\3\2\2\2\2?\3\2\2\2\2A\3\2\2"+
+		"\2\2C\3\2\2\2\2E\3\2\2\2\2G\3\2\2\2\2I\3\2\2\2\2K\3\2\2\2\2M\3\2\2\2\2"+
+		"O\3\2\2\2\2Q\3\2\2\2\2S\3\2\2\2\2U\3\2\2\2\2W\3\2\2\2\2Y\3\2\2\2\2[\3"+
+		"\2\2\2\2]\3\2\2\2\2_\3\2\2\2\2\u008f\3\2\2\2\2\u00a5\3\2\2\2\2\u00a7\3"+
+		"\2\2\2\2\u00ab\3\2\2\2\2\u00ad\3\2\2\2\2\u00bd\3\2\2\2\2\u00bf\3\2\2\2"+
+		"\2\u00c5\3\2\2\2\2\u00c7\3\2\2\2\2\u00c9\3\2\2\2\2\u00cb\3\2\2\2\3\u00cd"+
+		"\3\2\2\2\5\u00cf\3\2\2\2\7\u00d7\3\2\2\2\t\u00d9\3\2\2\2\13\u00dc\3\2"+
+		"\2\2\r\u00de\3\2\2\2\17\u00e0\3\2\2\2\21\u00e2\3\2\2\2\23\u00e5\3\2\2"+
+		"\2\25\u00e7\3\2\2\2\27\u00e9\3\2\2\2\31\u00eb\3\2\2\2\33\u00ed\3\2\2\2"+
+		"\35\u00ef\3\2\2\2\37\u00f1\3\2\2\2!\u00f3\3\2\2\2#\u00f5\3\2\2\2%\u00f7"+
+		"\3\2\2\2\'\u00fa\3\2\2\2)\u00fe\3\2\2\2+\u0101\3\2\2\2-\u0104\3\2\2\2"+
+		"/\u0107\3\2\2\2\61\u0109\3\2\2\2\63\u010b\3\2\2\2\65\u0116\3\2\2\2\67"+
+		"\u0119\3\2\2\29\u011c\3\2\2\2;\u011e\3\2\2\2=\u0120\3\2\2\2?\u0122\3\2"+
+		"\2\2A\u0125\3\2\2\2C\u0128\3\2\2\2E\u012a\3\2\2\2G\u012c\3\2\2\2I\u012f"+
+		"\3\2\2\2K\u0135\3\2\2\2M\u013d\3\2\2\2O\u0142\3\2\2\2Q\u0147\3\2\2\2S"+
+		"\u014d\3\2\2\2U\u0151\3\2\2\2W\u0156\3\2\2\2Y\u015c\3\2\2\2[\u0163\3\2"+
+		"\2\2]\u0179\3\2\2\2_\u017f\3\2\2\2a\u0181\3\2\2\2c\u0185\3\2\2\2e\u0189"+
+		"\3\2\2\2g\u018d\3\2\2\2i\u0191\3\2\2\2k\u019d\3\2\2\2m\u019f\3\2\2\2o"+
+		"\u01ab\3\2\2\2q\u01ad\3\2\2\2s\u01b1\3\2\2\2u\u01b4\3\2\2\2w\u01b8\3\2"+
+		"\2\2y\u01bc\3\2\2\2{\u01c6\3\2\2\2}\u01ca\3\2\2\2\177\u01cc\3\2\2\2\u0081"+
+		"\u01d2\3\2\2\2\u0083\u01dc\3\2\2\2\u0085\u01e0\3\2\2\2\u0087\u01e2\3\2"+
+		"\2\2\u0089\u01e6\3\2\2\2\u008b\u01f0\3\2\2\2\u008d\u01f4\3\2\2\2\u008f"+
+		"\u01f8\3\2\2\2\u0091\u0215\3\2\2\2\u0093\u0217\3\2\2\2\u0095\u021a\3\2"+
+		"\2\2\u0097\u021d\3\2\2\2\u0099\u0221\3\2\2\2\u009b\u0223\3\2\2\2\u009d"+
+		"\u0225\3\2\2\2\u009f\u0235\3\2\2\2\u00a1\u0237\3\2\2\2\u00a3\u023a\3\2"+
+		"\2\2\u00a5\u0245\3\2\2\2\u00a7\u024f\3\2\2\2\u00a9\u0251\3\2\2\2\u00ab"+
+		"\u0253\3\2\2\2\u00ad\u025c\3\2\2\2\u00af\u0263\3\2\2\2\u00b1\u0269\3\2"+
+		"\2\2\u00b3\u026d\3\2\2\2\u00b5\u0273\3\2\2\2\u00b7\u0280\3\2\2\2\u00b9"+
+		"\u0282\3\2\2\2\u00bb\u0289\3\2\2\2\u00bd\u028b\3\2\2\2\u00bf\u0290\3\2"+
+		"\2\2\u00c1\u029d\3\2\2\2\u00c3\u02a5\3\2\2\2\u00c5\u02a8\3\2\2\2\u00c7"+
+		"\u02ae\3\2\2\2\u00c9\u02c0\3\2\2\2\u00cb\u036e\3\2\2\2\u00cd\u00ce\7."+
+		"\2\2\u00ce\4\3\2\2\2\u00cf\u00d0\7f\2\2\u00d0\u00d1\7g\2\2\u00d1\u00d2"+
+		"\7h\2\2\u00d2\u00d3\7c\2\2\u00d3\u00d4\7w\2\2\u00d4\u00d5\7n\2\2\u00d5"+
+		"\u00d6\7v\2\2\u00d6\6\3\2\2\2\u00d7\u00d8\7?\2\2\u00d8\b\3\2\2\2\u00d9"+
+		"\u00da\7/\2\2\u00da\u00db\7@\2\2\u00db\n\3\2\2\2\u00dc\u00dd\7*\2\2\u00dd"+
+		"\f\3\2\2\2\u00de\u00df\7+\2\2\u00df\16\3\2\2\2\u00e0\u00e1\7\60\2\2\u00e1"+
+		"\20\3\2\2\2\u00e2\u00e3\7<\2\2\u00e3\u00e4\7<\2\2\u00e4\22\3\2\2\2\u00e5"+
+		"\u00e6\7]\2\2\u00e6\24\3\2\2\2\u00e7\u00e8\7_\2\2\u00e8\26\3\2\2\2\u00e9"+
+		"\u00ea\7-\2\2\u00ea\30\3\2\2\2\u00eb\u00ec\7/\2\2\u00ec\32\3\2\2\2\u00ed"+
+		"\u00ee\7\u0080\2\2\u00ee\34\3\2\2\2\u00ef\u00f0\7#\2\2\u00f0\36\3\2\2"+
+		"\2\u00f1\u00f2\7,\2\2\u00f2 \3\2\2\2\u00f3\u00f4\7\61\2\2\u00f4\"\3\2"+
+		"\2\2\u00f5\u00f6\7\'\2\2\u00f6$\3\2\2\2\u00f7\u00f8\7>\2\2\u00f8\u00f9"+
+		"\7>\2\2\u00f9&\3\2\2\2\u00fa\u00fb\7@\2\2\u00fb\u00fc\7@\2\2\u00fc\u00fd"+
+		"\7@\2\2\u00fd(\3\2\2\2\u00fe\u00ff\7@\2\2\u00ff\u0100\7@\2\2\u0100*\3"+
+		"\2\2\2\u0101\u0102\7>\2\2\u0102\u0103\7?\2\2\u0103,\3\2\2\2\u0104\u0105"+
+		"\7@\2\2\u0105\u0106\7?\2\2\u0106.\3\2\2\2\u0107\u0108\7@\2\2\u0108\60"+
+		"\3\2\2\2\u0109\u010a\7>\2\2\u010a\62\3\2\2\2\u010b\u010c\7k\2\2\u010c"+
+		"\u010d\7p\2\2\u010d\u010e\7u\2\2\u010e\u010f\7v\2\2\u010f\u0110\7c\2\2"+
+		"\u0110\u0111\7p\2\2\u0111\u0112\7e\2\2\u0112\u0113\7g\2\2\u0113\u0114"+
+		"\7q\2\2\u0114\u0115\7h\2\2\u0115\64\3\2\2\2\u0116\u0117\7?\2\2\u0117\u0118"+
+		"\7?\2\2\u0118\66\3\2\2\2\u0119\u011a\7#\2\2\u011a\u011b\7?\2\2\u011b8"+
+		"\3\2\2\2\u011c\u011d\7(\2\2\u011d:\3\2\2\2\u011e\u011f\7`\2\2\u011f<\3"+
+		"\2\2\2\u0120\u0121\7~\2\2\u0121>\3\2\2\2\u0122\u0123\7(\2\2\u0123\u0124"+
+		"\7(\2\2\u0124@\3\2\2\2\u0125\u0126\7~\2\2\u0126\u0127\7~\2\2\u0127B\3"+
+		"\2\2\2\u0128\u0129\7A\2\2\u0129D\3\2\2\2\u012a\u012b\7<\2\2\u012bF\3\2"+
+		"\2\2\u012c\u012d\7A\2\2\u012d\u012e\7A\2\2\u012eH\3\2\2\2\u012f\u0130"+
+		"\7e\2\2\u0130\u0131\7n\2\2\u0131\u0132\7c\2\2\u0132\u0133\7u\2\2\u0133"+
+		"\u0134\7u\2\2\u0134J\3\2\2\2\u0135\u0136\7d\2\2\u0136\u0137\7q\2\2\u0137"+
+		"\u0138\7q\2\2\u0138\u0139\7n\2\2\u0139\u013a\7g\2\2\u013a\u013b\7c\2\2"+
+		"\u013b\u013c\7p\2\2\u013cL\3\2\2\2\u013d\u013e\7e\2\2\u013e\u013f\7j\2"+
+		"\2\u013f\u0140\7c\2\2\u0140\u0141\7t\2\2\u0141N\3\2\2\2\u0142\u0143\7"+
+		"d\2\2\u0143\u0144\7{\2\2\u0144\u0145\7v\2\2\u0145\u0146\7g\2\2\u0146P"+
+		"\3\2\2\2\u0147\u0148\7u\2\2\u0148\u0149\7j\2\2\u0149\u014a\7q\2\2\u014a"+
+		"\u014b\7t\2\2\u014b\u014c\7v\2\2\u014cR\3\2\2\2\u014d\u014e\7k\2\2\u014e"+
+		"\u014f\7p\2\2\u014f\u0150\7v\2\2\u0150T\3\2\2\2\u0151\u0152\7n\2\2\u0152"+
+		"\u0153\7q\2\2\u0153\u0154\7p\2\2\u0154\u0155\7i\2\2\u0155V\3\2\2\2\u0156"+
+		"\u0157\7h\2\2\u0157\u0158\7n\2\2\u0158\u0159\7q\2\2\u0159\u015a\7c\2\2"+
+		"\u015a\u015b\7v\2\2\u015bX\3\2\2\2\u015c\u015d\7f\2\2\u015d\u015e\7q\2"+
+		"\2\u015e\u015f\7w\2\2\u015f\u0160\7d\2\2\u0160\u0161\7n\2\2\u0161\u0162"+
+		"\7g\2\2\u0162Z\3\2\2\2\u0163\u0164\7v\2\2\u0164\u0165\7j\2\2\u0165\u0166"+
+		"\7k\2\2\u0166\u0167\7u\2\2\u0167\\\3\2\2\2\u0168\u0169\7X\2\2\u0169\u016a"+
+		"\7q\2\2\u016a\u016b\7k\2\2\u016b\u017a\7f\2\2\u016c\u016d\7x\2\2\u016d"+
+		"\u016e\7q\2\2\u016e\u016f\7k\2\2\u016f\u017a\7f\2\2\u0170\u0171\7\u00b1"+
+		"\2\2\u0171\u0172\7^\2\2\u0172\u0173\7a\2\2\u0173\u0174\7*\2\2\u0174\u0175"+
+		"\7\u30c6\2\2\u0175\u0176\7+\2\2\u0176\u0177\7a\2\2\u0177\u0178\7\61\2"+
+		"\2\u0178\u017a\7\u00b1\2\2\u0179\u0168\3\2\2\2\u0179\u016c\3\2\2\2\u0179"+
+		"\u0170\3\2\2\2\u017a^\3\2\2\2\u017b\u0180\5a\61\2\u017c\u0180\5c\62\2"+
+		"\u017d\u0180\5e\63\2\u017e\u0180\5g\64\2\u017f\u017b\3\2\2\2\u017f\u017c"+
+		"\3\2\2\2\u017f\u017d\3\2\2\2\u017f\u017e\3\2\2\2\u0180`\3\2\2\2\u0181"+
+		"\u0183\5k\66\2\u0182\u0184\5i\65\2\u0183\u0182\3\2\2\2\u0183\u0184\3\2"+
+		"\2\2\u0184b\3\2\2\2\u0185\u0187\5w<\2\u0186\u0188\5i\65\2\u0187\u0186"+
+		"\3\2\2\2\u0187\u0188\3\2\2\2\u0188d\3\2\2\2\u0189\u018b\5\177@\2\u018a"+
+		"\u018c\5i\65\2\u018b\u018a\3\2\2\2\u018b\u018c\3\2\2\2\u018cf\3\2\2\2"+
+		"\u018d\u018f\5\u0087D\2\u018e\u0190\5i\65\2\u018f\u018e\3\2\2\2\u018f"+
+		"\u0190\3\2\2\2\u0190h\3\2\2\2\u0191\u0192\t\2\2\2\u0192j\3\2\2\2\u0193"+
+		"\u019e\7\62\2\2\u0194\u019b\5q9\2\u0195\u0197\5m\67\2\u0196\u0195\3\2"+
+		"\2\2\u0196\u0197\3\2\2\2\u0197\u019c\3\2\2\2\u0198\u0199\5u;\2\u0199\u019a"+
+		"\5m\67\2\u019a\u019c\3\2\2\2\u019b\u0196\3\2\2\2\u019b\u0198\3\2\2\2\u019c"+
+		"\u019e\3\2\2\2\u019d\u0193\3\2\2\2\u019d\u0194\3\2\2\2\u019el\3\2\2\2"+
+		"\u019f\u01a7\5o8\2\u01a0\u01a2\5s:\2\u01a1\u01a0\3\2\2\2\u01a2\u01a5\3"+
+		"\2\2\2\u01a3\u01a1\3\2\2\2\u01a3\u01a4\3\2\2\2\u01a4\u01a6\3\2\2\2\u01a5"+
+		"\u01a3\3\2\2\2\u01a6\u01a8\5o8\2\u01a7\u01a3\3\2\2\2\u01a7\u01a8\3\2\2"+
+		"\2\u01a8n\3\2\2\2\u01a9\u01ac\7\62\2\2\u01aa\u01ac\5q9\2\u01ab\u01a9\3"+
+		"\2\2\2\u01ab\u01aa\3\2\2\2\u01acp\3\2\2\2\u01ad\u01ae\t\3\2\2\u01aer\3"+
+		"\2\2\2\u01af\u01b2\5o8\2\u01b0\u01b2\7a\2\2\u01b1\u01af\3\2\2\2\u01b1"+
+		"\u01b0\3\2\2\2\u01b2t\3\2\2\2\u01b3\u01b5\7a\2\2\u01b4\u01b3\3\2\2\2\u01b5"+
+		"\u01b6\3\2\2\2\u01b6\u01b4\3\2\2\2\u01b6\u01b7\3\2\2\2\u01b7v\3\2\2\2"+
+		"\u01b8\u01b9\7\62\2\2\u01b9\u01ba\t\4\2\2\u01ba\u01bb\5y=\2\u01bbx\3\2"+
+		"\2\2\u01bc\u01c4\5{>\2\u01bd\u01bf\5}?\2\u01be\u01bd\3\2\2\2\u01bf\u01c2"+
+		"\3\2\2\2\u01c0\u01be\3\2\2\2\u01c0\u01c1\3\2\2\2\u01c1\u01c3\3\2\2\2\u01c2"+
+		"\u01c0\3\2\2\2\u01c3\u01c5\5{>\2\u01c4\u01c0\3\2\2\2\u01c4\u01c5\3\2\2"+
+		"\2\u01c5z\3\2\2\2\u01c6\u01c7\t\5\2\2\u01c7|\3\2\2\2\u01c8\u01cb\5{>\2"+
+		"\u01c9\u01cb\7a\2\2\u01ca\u01c8\3\2\2\2\u01ca\u01c9\3\2\2\2\u01cb~\3\2"+
+		"\2\2\u01cc\u01ce\7\62\2\2\u01cd\u01cf\5u;\2\u01ce\u01cd\3\2\2\2\u01ce"+
+		"\u01cf\3\2\2\2\u01cf\u01d0\3\2\2\2\u01d0\u01d1\5\u0081A\2\u01d1\u0080"+
+		"\3\2\2\2\u01d2\u01da\5\u0083B\2\u01d3\u01d5\5\u0085C\2\u01d4\u01d3\3\2"+
+		"\2\2\u01d5\u01d8\3\2\2\2\u01d6\u01d4\3\2\2\2\u01d6\u01d7\3\2\2\2\u01d7"+
+		"\u01d9\3\2\2\2\u01d8\u01d6\3\2\2\2\u01d9\u01db\5\u0083B\2\u01da\u01d6"+
+		"\3\2\2\2\u01da\u01db\3\2\2\2\u01db\u0082\3\2\2\2\u01dc\u01dd\t\6\2\2\u01dd"+
+		"\u0084\3\2\2\2\u01de\u01e1\5\u0083B\2\u01df\u01e1\7a\2\2\u01e0\u01de\3"+
+		"\2\2\2\u01e0\u01df\3\2\2\2\u01e1\u0086\3\2\2\2\u01e2\u01e3\7\62\2\2\u01e3"+
+		"\u01e4\t\7\2\2\u01e4\u01e5\5\u0089E\2\u01e5\u0088\3\2\2\2\u01e6\u01ee"+
+		"\5\u008bF\2\u01e7\u01e9\5\u008dG\2\u01e8\u01e7\3\2\2\2\u01e9\u01ec\3\2"+
+		"\2\2\u01ea\u01e8\3\2\2\2\u01ea\u01eb\3\2\2\2\u01eb\u01ed\3\2\2\2\u01ec"+
+		"\u01ea\3\2\2\2\u01ed\u01ef\5\u008bF\2\u01ee\u01ea\3\2\2\2\u01ee\u01ef"+
+		"\3\2\2\2\u01ef\u008a\3\2\2\2\u01f0\u01f1\t\b\2\2\u01f1\u008c\3\2\2\2\u01f2"+
+		"\u01f5\5\u008bF\2\u01f3\u01f5\7a\2\2\u01f4\u01f2\3\2\2\2\u01f4\u01f3\3"+
+		"\2\2\2\u01f5\u008e\3\2\2\2\u01f6\u01f9\5\u0091I\2\u01f7\u01f9\5\u009d"+
+		"O\2\u01f8\u01f6\3\2\2\2\u01f8\u01f7\3\2\2\2\u01f9\u0090\3\2\2\2\u01fa"+
+		"\u01fb\5m\67\2\u01fb\u01fd\7\60\2\2\u01fc\u01fe\5m\67\2\u01fd\u01fc\3"+
+		"\2\2\2\u01fd\u01fe\3\2\2\2\u01fe\u0200\3\2\2\2\u01ff\u0201\5\u0093J\2"+
+		"\u0200\u01ff\3\2\2\2\u0200\u0201\3\2\2\2\u0201\u0203\3\2\2\2\u0202\u0204"+
+		"\5\u009bN\2\u0203\u0202\3\2\2\2\u0203\u0204\3\2\2\2\u0204\u0216\3\2\2"+
+		"\2\u0205\u0206\7\60\2\2\u0206\u0208\5m\67\2\u0207\u0209\5\u0093J\2\u0208"+
+		"\u0207\3\2\2\2\u0208\u0209\3\2\2\2\u0209\u020b\3\2\2\2\u020a\u020c\5\u009b"+
+		"N\2\u020b\u020a\3\2\2\2\u020b\u020c\3\2\2\2\u020c\u0216\3\2\2\2\u020d"+
+		"\u020e\5m\67\2\u020e\u0210\5\u0093J\2\u020f\u0211\5\u009bN\2\u0210\u020f"+
+		"\3\2\2\2\u0210\u0211\3\2\2\2\u0211\u0216\3\2\2\2\u0212\u0213\5m\67\2\u0213"+
+		"\u0214\5\u009bN\2\u0214\u0216\3\2\2\2\u0215\u01fa\3\2\2\2\u0215\u0205"+
+		"\3\2\2\2\u0215\u020d\3\2\2\2\u0215\u0212\3\2\2\2\u0216\u0092\3\2\2\2\u0217"+
+		"\u0218\5\u0095K\2\u0218\u0219\5\u0097L\2\u0219\u0094\3\2\2\2\u021a\u021b"+
+		"\t\t\2\2\u021b\u0096\3\2\2\2\u021c\u021e\5\u0099M\2\u021d\u021c\3\2\2"+
+		"\2\u021d\u021e\3\2\2\2\u021e\u021f\3\2\2\2\u021f\u0220\5m\67\2\u0220\u0098"+
+		"\3\2\2\2\u0221\u0222\t\n\2\2\u0222\u009a\3\2\2\2\u0223\u0224\t\13\2\2"+
+		"\u0224\u009c\3\2\2\2\u0225\u0226\5\u009fP\2\u0226\u0228\5\u00a1Q\2\u0227"+
+		"\u0229\5\u009bN\2\u0228\u0227\3\2\2\2\u0228\u0229\3\2\2\2\u0229\u009e"+
+		"\3\2\2\2\u022a\u022c\5w<\2\u022b\u022d\7\60\2\2\u022c\u022b\3\2\2\2\u022c"+
+		"\u022d\3\2\2\2\u022d\u0236\3\2\2\2\u022e\u022f\7\62\2\2\u022f\u0231\t"+
+		"\4\2\2\u0230\u0232\5y=\2\u0231\u0230\3\2\2\2\u0231\u0232\3\2\2\2\u0232"+
+		"\u0233\3\2\2\2\u0233\u0234\7\60\2\2\u0234\u0236\5y=\2\u0235\u022a\3\2"+
+		"\2\2\u0235\u022e\3\2\2\2\u0236\u00a0\3\2\2\2\u0237\u0238\5\u00a3R\2\u0238"+
+		"\u0239\5\u0097L\2\u0239\u00a2\3\2\2\2\u023a\u023b\t\f\2\2\u023b\u00a4"+
+		"\3\2\2\2\u023c\u023d\7v\2\2\u023d\u023e\7t\2\2\u023e\u023f\7w\2\2\u023f"+
+		"\u0246\7g\2\2\u0240\u0241\7h\2\2\u0241\u0242\7c\2\2\u0242\u0243\7n\2\2"+
+		"\u0243\u0244\7u\2\2\u0244\u0246\7g\2\2\u0245\u023c\3\2\2\2\u0245\u0240"+
+		"\3\2\2\2\u0246\u00a6\3\2\2\2\u0247\u0248\7)\2\2\u0248\u0249\5\u00a9U\2"+
+		"\u0249\u024a\7)\2\2\u024a\u0250\3\2\2\2\u024b\u024c\7)\2\2\u024c\u024d"+
+		"\5\u00b5[\2\u024d\u024e\7)\2\2\u024e\u0250\3\2\2\2\u024f\u0247\3\2\2\2"+
+		"\u024f\u024b\3\2\2\2\u0250\u00a8\3\2\2\2\u0251\u0252\n\r\2\2\u0252\u00aa"+
+		"\3\2\2\2\u0253\u0257\7b\2\2\u0254\u0256\5\u00b3Z\2\u0255\u0254\3\2\2\2"+
+		"\u0256\u0259\3\2\2\2\u0257\u0255\3\2\2\2\u0257\u0258\3\2\2\2\u0258\u025a"+
+		"\3\2\2\2\u0259\u0257\3\2\2\2\u025a\u025b\7b\2\2\u025b\u00ac\3\2\2\2\u025c"+
+		"\u025e\7$\2\2\u025d\u025f\5\u00afX\2\u025e\u025d\3\2\2\2\u025e\u025f\3"+
+		"\2\2\2\u025f\u0260\3\2\2\2\u0260\u0261\7$\2\2\u0261\u00ae\3\2\2\2\u0262"+
+		"\u0264\5\u00b1Y\2\u0263\u0262\3\2\2\2\u0264\u0265\3\2\2\2\u0265\u0263"+
+		"\3\2\2\2\u0265\u0266\3\2\2\2\u0266\u00b0\3\2\2\2\u0267\u026a\n\16\2\2"+
+		"\u0268\u026a\5\u00b5[\2\u0269\u0267\3\2\2\2\u0269\u0268\3\2\2\2\u026a"+
+		"\u00b2\3\2\2\2\u026b\u026e\n\17\2\2\u026c\u026e\5\u00b5[\2\u026d\u026b"+
+		"\3\2\2\2\u026d\u026c\3\2\2\2\u026e\u00b4\3\2\2\2\u026f\u0270\7^\2\2\u0270"+
+		"\u0274\t\20\2\2\u0271\u0274\5\u00b7\\\2\u0272\u0274\5\u00b9]\2\u0273\u026f"+
+		"\3\2\2\2\u0273\u0271\3\2\2\2\u0273\u0272\3\2\2\2\u0274\u00b6\3\2\2\2\u0275"+
+		"\u0276\7^\2\2\u0276\u0281\5\u0083B\2\u0277\u0278\7^\2\2\u0278\u0279\5"+
+		"\u0083B\2\u0279\u027a\5\u0083B\2\u027a\u0281\3\2\2\2\u027b\u027c\7^\2"+
+		"\2\u027c\u027d\5\u00bb^\2\u027d\u027e\5\u0083B\2\u027e\u027f\5\u0083B"+
+		"\2\u027f\u0281\3\2\2\2\u0280\u0275\3\2\2\2\u0280\u0277\3\2\2\2\u0280\u027b"+
+		"\3\2\2\2\u0281\u00b8\3\2\2\2\u0282\u0283\7^\2\2\u0283\u0284\7w\2\2\u0284"+
+		"\u0285\5{>\2\u0285\u0286\5{>\2\u0286\u0287\5{>\2\u0287\u0288\5{>\2\u0288"+
+		"\u00ba\3\2\2\2\u0289\u028a\t\21\2\2\u028a\u00bc\3\2\2\2\u028b\u028c\7"+
+		"p\2\2\u028c\u028d\7w\2\2\u028d\u028e\7n\2\2\u028e\u028f\7n\2\2\u028f\u00be"+
+		"\3\2\2\2\u0290\u0294\5\u00c1a\2\u0291\u0293\5\u00c3b\2\u0292\u0291\3\2"+
+		"\2\2\u0293\u0296\3\2\2\2\u0294\u0292\3\2\2\2\u0294\u0295\3\2\2\2\u0295"+
+		"\u00c0\3\2\2\2\u0296\u0294\3\2\2\2\u0297\u029e\t\22\2\2\u0298\u0299\n"+
+		"\23\2\2\u0299\u029e\6a\2\2\u029a\u029b\t\24\2\2\u029b\u029c\t\25\2\2\u029c"+
+		"\u029e\6a\3\2\u029d\u0297\3\2\2\2\u029d\u0298\3\2\2\2\u029d\u029a\3\2"+
+		"\2\2\u029e\u00c2\3\2\2\2\u029f\u02a6\t\26\2\2\u02a0\u02a1\n\23\2\2\u02a1"+
+		"\u02a6\6b\4\2\u02a2\u02a3\t\24\2\2\u02a3\u02a4\t\25\2\2\u02a4\u02a6\6"+
+		"b\5\2\u02a5\u029f\3\2\2\2\u02a5\u02a0\3\2\2\2\u02a5\u02a2\3\2\2\2\u02a6"+
+		"\u00c4\3\2\2\2\u02a7\u02a9\t\27\2\2\u02a8\u02a7\3\2\2\2\u02a9\u02aa\3"+
+		"\2\2\2\u02aa\u02a8\3\2\2\2\u02aa\u02ab\3\2\2\2\u02ab\u02ac\3\2\2\2\u02ac"+
+		"\u02ad\bc\2\2\u02ad\u00c6\3\2\2\2\u02ae\u02b2\7B\2\2\u02af\u02b0\5\u00c9"+
+		"e\2\u02b0\u02b1\7<\2\2\u02b1\u02b3\3\2\2\2\u02b2\u02af\3\2\2\2\u02b2\u02b3"+
+		"\3\2\2\2\u02b3\u02b4\3\2\2\2\u02b4\u02b5\5\u00cbf\2\u02b5\u02b6\7\61\2"+
+		"\2\u02b6\u02b7\5\u00bf`\2\u02b7\u00c8\3\2\2\2\u02b8\u02b9\7c\2\2\u02b9"+
+		"\u02ba\7p\2\2\u02ba\u02bb\7f\2\2\u02bb\u02bc\7t\2\2\u02bc\u02bd\7q\2\2"+
+		"\u02bd\u02be\7k\2\2\u02be\u02c1\7f\2\2\u02bf\u02c1\5\u00bf`\2\u02c0\u02b8"+
+		"\3\2\2\2\u02c0\u02bf\3\2\2\2\u02c1\u00ca\3\2\2\2\u02c2\u02c3\7c\2\2\u02c3"+
+		"\u02c4\7p\2\2\u02c4\u02c5\7k\2\2\u02c5\u036f\7o\2\2\u02c6\u02c7\7c\2\2"+
+		"\u02c7\u02c8\7p\2\2\u02c8\u02c9\7k\2\2\u02c9\u02ca\7o\2\2\u02ca\u02cb"+
+		"\7c\2\2\u02cb\u02cc\7v\2\2\u02cc\u02cd\7q\2\2\u02cd\u036f\7t\2\2\u02ce"+
+		"\u02cf\7d\2\2\u02cf\u02d0\7q\2\2\u02d0\u02d1\7q\2\2\u02d1\u036f\7n\2\2"+
+		"\u02d2\u02d3\7e\2\2\u02d3\u02d4\7q\2\2\u02d4\u02d5\7n\2\2\u02d5\u02d6"+
+		"\7q\2\2\u02d6\u036f\7t\2\2\u02d7\u02d8\7e\2\2\u02d8\u02d9\7q\2\2\u02d9"+
+		"\u02da\7n\2\2\u02da\u02db\7q\2\2\u02db\u02dc\7t\2\2\u02dc\u02dd\7U\2\2"+
+		"\u02dd\u02de\7v\2\2\u02de\u02df\7c\2\2\u02df\u02e0\7v\2\2\u02e0\u02e1"+
+		"\7g\2\2\u02e1\u02e2\7N\2\2\u02e2\u02e3\7k\2\2\u02e3\u02e4\7u\2\2\u02e4"+
+		"\u036f\7v\2\2\u02e5\u02e6\7f\2\2\u02e6\u02e7\7k\2\2\u02e7\u02e8\7o\2\2"+
+		"\u02e8\u02e9\7g\2\2\u02e9\u036f\7p\2\2\u02ea\u02eb\7f\2\2\u02eb\u02ec"+
+		"\7k\2\2\u02ec\u02ed\7o\2\2\u02ed\u02ee\7g\2\2\u02ee\u02ef\7p\2\2\u02ef"+
+		"\u02f0\7Q\2\2\u02f0\u02f1\7h\2\2\u02f1\u02f2\7h\2\2\u02f2\u02f3\7u\2\2"+
+		"\u02f3\u02f4\7g\2\2\u02f4\u036f\7v\2\2\u02f5\u02f6\7f\2\2\u02f6\u02f7"+
+		"\7k\2\2\u02f7\u02f8\7o\2\2\u02f8\u02f9\7g\2\2\u02f9\u02fa\7p\2\2\u02fa"+
+		"\u02fb\7U\2\2\u02fb\u02fc\7k\2\2\u02fc\u02fd\7|\2\2\u02fd\u036f\7g\2\2"+
+		"\u02fe\u02ff\7f\2\2\u02ff\u0300\7t\2\2\u0300\u0301\7c\2\2\u0301\u0302"+
+		"\7y\2\2\u0302\u0303\7c\2\2\u0303\u0304\7d\2\2\u0304\u0305\7n\2\2\u0305"+
+		"\u036f\7g\2\2\u0306\u0307\7h\2\2\u0307\u0308\7t\2\2\u0308\u0309\7c\2\2"+
+		"\u0309\u030a\7e\2\2\u030a\u030b\7v\2\2\u030b\u030c\7k\2\2\u030c\u030d"+
+		"\7q\2\2\u030d\u036f\7p\2\2\u030e\u030f\7k\2\2\u030f\u036f\7f\2\2\u0310"+
+		"\u0311\7k\2\2\u0311\u0312\7p\2\2\u0312\u0313\7v\2\2\u0313\u0314\7g\2\2"+
+		"\u0314\u0315\7i\2\2\u0315\u0316\7g\2\2\u0316\u036f\7t\2\2\u0317\u0318"+
+		"\7k\2\2\u0318\u0319\7p\2\2\u0319\u031a\7v\2\2\u031a\u031b\7C\2\2\u031b"+
+		"\u031c\7t\2\2\u031c\u031d\7t\2\2\u031d\u031e\7c\2\2\u031e\u036f\7{\2\2"+
+		"\u031f\u0320\7k\2\2\u0320\u0321\7p\2\2\u0321\u0322\7v\2\2\u0322\u0323"+
+		"\7g\2\2\u0323\u0324\7t\2\2\u0324\u0325\7r\2\2\u0325\u0326\7q\2\2\u0326"+
+		"\u0327\7n\2\2\u0327\u0328\7c\2\2\u0328\u0329\7v\2\2\u0329\u032a\7q\2\2"+
+		"\u032a\u036f\7t\2\2\u032b\u032c\7n\2\2\u032c\u032d\7c\2\2\u032d\u032e"+
+		"\7{\2\2\u032e\u032f\7q\2\2\u032f\u0330\7w\2\2\u0330\u036f\7v\2\2\u0331"+
+		"\u0332\7r\2\2\u0332\u0333\7n\2\2\u0333\u0334\7w\2\2\u0334\u0335\7t\2\2"+
+		"\u0335\u0336\7c\2\2\u0336\u0337\7n\2\2\u0337\u036f\7u\2\2\u0338\u0339"+
+		"\7u\2\2\u0339\u033a\7v\2\2\u033a\u033b\7c\2\2\u033b\u033c\7v\2\2\u033c"+
+		"\u033d\7g\2\2\u033d\u033e\7N\2\2\u033e\u033f\7k\2\2\u033f\u0340\7u\2\2"+
+		"\u0340\u0341\7v\2\2\u0341\u0342\7C\2\2\u0342\u0343\7p\2\2\u0343\u0344"+
+		"\7k\2\2\u0344\u0345\7o\2\2\u0345\u0346\7c\2\2\u0346\u0347\7v\2\2\u0347"+
+		"\u0348\7q\2\2\u0348\u036f\7t\2\2\u0349\u034a\7u\2\2\u034a\u034b\7v\2\2"+
+		"\u034b\u034c\7t\2\2\u034c\u034d\7k\2\2\u034d\u034e\7p\2\2\u034e\u036f"+
+		"\7i\2\2\u034f\u0350\7u\2\2\u0350\u0351\7v\2\2\u0351\u0352\7t\2\2\u0352"+
+		"\u0353\7k\2\2\u0353\u0354\7p\2\2\u0354\u0355\7i\2\2\u0355\u0356\7C\2\2"+
+		"\u0356\u0357\7t\2\2\u0357\u0358\7t\2\2\u0358\u0359\7c\2\2\u0359\u036f"+
+		"\7{\2\2\u035a\u035b\7v\2\2\u035b\u035c\7t\2\2\u035c\u035d\7c\2\2\u035d"+
+		"\u035e\7p\2\2\u035e\u035f\7u\2\2\u035f\u0360\7k\2\2\u0360\u0361\7v\2\2"+
+		"\u0361\u0362\7k\2\2\u0362\u0363\7q\2\2\u0363\u036f\7p\2\2\u0364\u0365"+
+		"\7v\2\2\u0365\u0366\7{\2\2\u0366\u0367\7r\2\2\u0367\u0368\7g\2\2\u0368"+
+		"\u0369\7f\2\2\u0369\u036a\7C\2\2\u036a\u036b\7t\2\2\u036b\u036c\7t\2\2"+
+		"\u036c\u036d\7c\2\2\u036d\u036f\7{\2\2\u036e\u02c2\3\2\2\2\u036e\u02c6"+
+		"\3\2\2\2\u036e\u02ce\3\2\2\2\u036e\u02d2\3\2\2\2\u036e\u02d7\3\2\2\2\u036e"+
+		"\u02e5\3\2\2\2\u036e\u02ea\3\2\2\2\u036e\u02f5\3\2\2\2\u036e\u02fe\3\2"+
+		"\2\2\u036e\u0306\3\2\2\2\u036e\u030e\3\2\2\2\u036e\u0310\3\2\2\2\u036e"+
+		"\u0317\3\2\2\2\u036e\u031f\3\2\2\2\u036e\u032b\3\2\2\2\u036e\u0331\3\2"+
+		"\2\2\u036e\u0338\3\2\2\2\u036e\u0349\3\2\2\2\u036e\u034f\3\2\2\2\u036e"+
+		"\u035a\3\2\2\2\u036e\u0364\3\2\2\2\u036f\u00cc\3\2\2\28\2\u0179\u017f"+
+		"\u0183\u0187\u018b\u018f\u0196\u019b\u019d\u01a3\u01a7\u01ab\u01b1\u01b6"+
+		"\u01c0\u01c4\u01ca\u01ce\u01d6\u01da\u01e0\u01ea\u01ee\u01f4\u01f8\u01fd"+
+		"\u0200\u0203\u0208\u020b\u0210\u0215\u021d\u0228\u022c\u0231\u0235\u0245"+
+		"\u024f\u0257\u025e\u0265\u0269\u026d\u0273\u0280\u0294\u029d\u02a5\u02aa"+
+		"\u02b2\u02c0\u036e\3\b\2\2";
 	public static final ATN _ATN =
 		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
 	static {
+		_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
+		for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
+			_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
+		}
 	}
 }
\ No newline at end of file
diff --git a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionLexer.tokens b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionLexer.tokens
index d9d1035..f80b7e6 100644
--- a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionLexer.tokens
+++ b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionLexer.tokens
@@ -41,61 +41,64 @@
 T__40=41
 T__41=42
 T__42=43
-THIS=44
-IntegerLiteral=45
-FloatingPointLiteral=46
-BooleanLiteral=47
-CharacterLiteral=48
-SingleQuoteString=49
-DoubleQuoteString=50
-NullLiteral=51
-Identifier=52
-WS=53
-ResourceReference=54
-PackageName=55
-ResourceType=56
+T__43=44
+THIS=45
+VoidLiteral=46
+IntegerLiteral=47
+FloatingPointLiteral=48
+BooleanLiteral=49
+CharacterLiteral=50
+SingleQuoteString=51
+DoubleQuoteString=52
+NullLiteral=53
+Identifier=54
+WS=55
+ResourceReference=56
+PackageName=57
+ResourceType=58
 ','=1
 'default'=2
 '='=3
-'('=4
-')'=5
-'.'=6
-'['=7
-']'=8
-'+'=9
-'-'=10
-'~'=11
-'!'=12
-'*'=13
-'/'=14
-'%'=15
-'<<'=16
-'>>>'=17
-'>>'=18
-'<='=19
-'>='=20
-'>'=21
-'<'=22
-'instanceof'=23
-'=='=24
-'!='=25
-'&'=26
-'^'=27
-'|'=28
-'&&'=29
-'||'=30
-'?'=31
-':'=32
-'??'=33
-'class'=34
-'void'=35
-'boolean'=36
-'char'=37
-'byte'=38
-'short'=39
-'int'=40
-'long'=41
-'float'=42
-'double'=43
-'this'=44
-'null'=51
+'->'=4
+'('=5
+')'=6
+'.'=7
+'::'=8
+'['=9
+']'=10
+'+'=11
+'-'=12
+'~'=13
+'!'=14
+'*'=15
+'/'=16
+'%'=17
+'<<'=18
+'>>>'=19
+'>>'=20
+'<='=21
+'>='=22
+'>'=23
+'<'=24
+'instanceof'=25
+'=='=26
+'!='=27
+'&'=28
+'^'=29
+'|'=30
+'&&'=31
+'||'=32
+'?'=33
+':'=34
+'??'=35
+'class'=36
+'boolean'=37
+'char'=38
+'byte'=39
+'short'=40
+'int'=41
+'long'=42
+'float'=43
+'double'=44
+'this'=45
+'null'=53
diff --git a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionListener.java b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionListener.java
index acd4c22..23d2d84 100644
--- a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionListener.java
+++ b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionListener.java
@@ -1,7 +1,5 @@
-// Generated from BindingExpression.g4 by ANTLR 4.5
+// Generated from BindingExpression.g4 by ANTLR 4.5.3
 package android.databinding.parser;
-import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.misc.NotNull;
 import org.antlr.v4.runtime.tree.ParseTreeListener;
 
 /**
@@ -10,419 +8,445 @@
  */
 public interface BindingExpressionListener extends ParseTreeListener {
 	/**
-	 * Enter a parse tree produced by the {@code BracketOp}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * Enter a parse tree produced by the {@code RootExpr}
+	 * labeled alternative in {@link BindingExpressionParser#bindingSyntax}.
 	 * @param ctx the parse tree
 	 */
-	void enterBracketOp(@NotNull BindingExpressionParser.BracketOpContext ctx);
+	void enterRootExpr(BindingExpressionParser.RootExprContext ctx);
 	/**
-	 * Exit a parse tree produced by the {@code BracketOp}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * Exit a parse tree produced by the {@code RootExpr}
+	 * labeled alternative in {@link BindingExpressionParser#bindingSyntax}.
 	 * @param ctx the parse tree
 	 */
-	void exitBracketOp(@NotNull BindingExpressionParser.BracketOpContext ctx);
-
+	void exitRootExpr(BindingExpressionParser.RootExprContext ctx);
 	/**
-	 * Enter a parse tree produced by the {@code Resource}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * Enter a parse tree produced by the {@code RootLambda}
+	 * labeled alternative in {@link BindingExpressionParser#bindingSyntax}.
 	 * @param ctx the parse tree
 	 */
-	void enterResource(@NotNull BindingExpressionParser.ResourceContext ctx);
+	void enterRootLambda(BindingExpressionParser.RootLambdaContext ctx);
 	/**
-	 * Exit a parse tree produced by the {@code Resource}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * Exit a parse tree produced by the {@code RootLambda}
+	 * labeled alternative in {@link BindingExpressionParser#bindingSyntax}.
 	 * @param ctx the parse tree
 	 */
-	void exitResource(@NotNull BindingExpressionParser.ResourceContext ctx);
-
+	void exitRootLambda(BindingExpressionParser.RootLambdaContext ctx);
+	/**
+	 * Enter a parse tree produced by {@link BindingExpressionParser#defaults}.
+	 * @param ctx the parse tree
+	 */
+	void enterDefaults(BindingExpressionParser.DefaultsContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link BindingExpressionParser#defaults}.
+	 * @param ctx the parse tree
+	 */
+	void exitDefaults(BindingExpressionParser.DefaultsContext ctx);
+	/**
+	 * Enter a parse tree produced by {@link BindingExpressionParser#constantValue}.
+	 * @param ctx the parse tree
+	 */
+	void enterConstantValue(BindingExpressionParser.ConstantValueContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link BindingExpressionParser#constantValue}.
+	 * @param ctx the parse tree
+	 */
+	void exitConstantValue(BindingExpressionParser.ConstantValueContext ctx);
+	/**
+	 * Enter a parse tree produced by {@link BindingExpressionParser#lambdaExpression}.
+	 * @param ctx the parse tree
+	 */
+	void enterLambdaExpression(BindingExpressionParser.LambdaExpressionContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link BindingExpressionParser#lambdaExpression}.
+	 * @param ctx the parse tree
+	 */
+	void exitLambdaExpression(BindingExpressionParser.LambdaExpressionContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code SingleLambdaParameter}
+	 * labeled alternative in {@link BindingExpressionParser#lambdaParameters}.
+	 * @param ctx the parse tree
+	 */
+	void enterSingleLambdaParameter(BindingExpressionParser.SingleLambdaParameterContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code SingleLambdaParameter}
+	 * labeled alternative in {@link BindingExpressionParser#lambdaParameters}.
+	 * @param ctx the parse tree
+	 */
+	void exitSingleLambdaParameter(BindingExpressionParser.SingleLambdaParameterContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code LambdaParameterList}
+	 * labeled alternative in {@link BindingExpressionParser#lambdaParameters}.
+	 * @param ctx the parse tree
+	 */
+	void enterLambdaParameterList(BindingExpressionParser.LambdaParameterListContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code LambdaParameterList}
+	 * labeled alternative in {@link BindingExpressionParser#lambdaParameters}.
+	 * @param ctx the parse tree
+	 */
+	void exitLambdaParameterList(BindingExpressionParser.LambdaParameterListContext ctx);
+	/**
+	 * Enter a parse tree produced by {@link BindingExpressionParser#inferredFormalParameterList}.
+	 * @param ctx the parse tree
+	 */
+	void enterInferredFormalParameterList(BindingExpressionParser.InferredFormalParameterListContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link BindingExpressionParser#inferredFormalParameterList}.
+	 * @param ctx the parse tree
+	 */
+	void exitInferredFormalParameterList(BindingExpressionParser.InferredFormalParameterListContext ctx);
 	/**
 	 * Enter a parse tree produced by the {@code CastOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void enterCastOp(@NotNull BindingExpressionParser.CastOpContext ctx);
+	void enterCastOp(BindingExpressionParser.CastOpContext ctx);
 	/**
 	 * Exit a parse tree produced by the {@code CastOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void exitCastOp(@NotNull BindingExpressionParser.CastOpContext ctx);
-
-	/**
-	 * Enter a parse tree produced by the {@code UnaryOp}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void enterUnaryOp(@NotNull BindingExpressionParser.UnaryOpContext ctx);
-	/**
-	 * Exit a parse tree produced by the {@code UnaryOp}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void exitUnaryOp(@NotNull BindingExpressionParser.UnaryOpContext ctx);
-
-	/**
-	 * Enter a parse tree produced by the {@code AndOrOp}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void enterAndOrOp(@NotNull BindingExpressionParser.AndOrOpContext ctx);
-	/**
-	 * Exit a parse tree produced by the {@code AndOrOp}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void exitAndOrOp(@NotNull BindingExpressionParser.AndOrOpContext ctx);
-
-	/**
-	 * Enter a parse tree produced by the {@code MethodInvocation}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void enterMethodInvocation(@NotNull BindingExpressionParser.MethodInvocationContext ctx);
-	/**
-	 * Exit a parse tree produced by the {@code MethodInvocation}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void exitMethodInvocation(@NotNull BindingExpressionParser.MethodInvocationContext ctx);
-
-	/**
-	 * Enter a parse tree produced by the {@code Primary}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void enterPrimary(@NotNull BindingExpressionParser.PrimaryContext ctx);
-	/**
-	 * Exit a parse tree produced by the {@code Primary}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void exitPrimary(@NotNull BindingExpressionParser.PrimaryContext ctx);
-
-	/**
-	 * Enter a parse tree produced by the {@code Grouping}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void enterGrouping(@NotNull BindingExpressionParser.GroupingContext ctx);
-	/**
-	 * Exit a parse tree produced by the {@code Grouping}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void exitGrouping(@NotNull BindingExpressionParser.GroupingContext ctx);
-
-	/**
-	 * Enter a parse tree produced by the {@code TernaryOp}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void enterTernaryOp(@NotNull BindingExpressionParser.TernaryOpContext ctx);
-	/**
-	 * Exit a parse tree produced by the {@code TernaryOp}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void exitTernaryOp(@NotNull BindingExpressionParser.TernaryOpContext ctx);
-
+	void exitCastOp(BindingExpressionParser.CastOpContext ctx);
 	/**
 	 * Enter a parse tree produced by the {@code ComparisonOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void enterComparisonOp(@NotNull BindingExpressionParser.ComparisonOpContext ctx);
+	void enterComparisonOp(BindingExpressionParser.ComparisonOpContext ctx);
 	/**
 	 * Exit a parse tree produced by the {@code ComparisonOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void exitComparisonOp(@NotNull BindingExpressionParser.ComparisonOpContext ctx);
-
+	void exitComparisonOp(BindingExpressionParser.ComparisonOpContext ctx);
 	/**
-	 * Enter a parse tree produced by the {@code DotOp}
+	 * Enter a parse tree produced by the {@code UnaryOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void enterDotOp(@NotNull BindingExpressionParser.DotOpContext ctx);
+	void enterUnaryOp(BindingExpressionParser.UnaryOpContext ctx);
 	/**
-	 * Exit a parse tree produced by the {@code DotOp}
+	 * Exit a parse tree produced by the {@code UnaryOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void exitDotOp(@NotNull BindingExpressionParser.DotOpContext ctx);
-
+	void exitUnaryOp(BindingExpressionParser.UnaryOpContext ctx);
 	/**
-	 * Enter a parse tree produced by the {@code MathOp}
+	 * Enter a parse tree produced by the {@code BracketOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void enterMathOp(@NotNull BindingExpressionParser.MathOpContext ctx);
+	void enterBracketOp(BindingExpressionParser.BracketOpContext ctx);
 	/**
-	 * Exit a parse tree produced by the {@code MathOp}
+	 * Exit a parse tree produced by the {@code BracketOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void exitMathOp(@NotNull BindingExpressionParser.MathOpContext ctx);
-
+	void exitBracketOp(BindingExpressionParser.BracketOpContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code Resource}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void enterResource(BindingExpressionParser.ResourceContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code Resource}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void exitResource(BindingExpressionParser.ResourceContext ctx);
 	/**
 	 * Enter a parse tree produced by the {@code QuestionQuestionOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void enterQuestionQuestionOp(@NotNull BindingExpressionParser.QuestionQuestionOpContext ctx);
+	void enterQuestionQuestionOp(BindingExpressionParser.QuestionQuestionOpContext ctx);
 	/**
 	 * Exit a parse tree produced by the {@code QuestionQuestionOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void exitQuestionQuestionOp(@NotNull BindingExpressionParser.QuestionQuestionOpContext ctx);
-
+	void exitQuestionQuestionOp(BindingExpressionParser.QuestionQuestionOpContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code Grouping}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void enterGrouping(BindingExpressionParser.GroupingContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code Grouping}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void exitGrouping(BindingExpressionParser.GroupingContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code MethodInvocation}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void enterMethodInvocation(BindingExpressionParser.MethodInvocationContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code MethodInvocation}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void exitMethodInvocation(BindingExpressionParser.MethodInvocationContext ctx);
 	/**
 	 * Enter a parse tree produced by the {@code BitShiftOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void enterBitShiftOp(@NotNull BindingExpressionParser.BitShiftOpContext ctx);
+	void enterBitShiftOp(BindingExpressionParser.BitShiftOpContext ctx);
 	/**
 	 * Exit a parse tree produced by the {@code BitShiftOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void exitBitShiftOp(@NotNull BindingExpressionParser.BitShiftOpContext ctx);
-
+	void exitBitShiftOp(BindingExpressionParser.BitShiftOpContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code AndOrOp}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void enterAndOrOp(BindingExpressionParser.AndOrOpContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code AndOrOp}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void exitAndOrOp(BindingExpressionParser.AndOrOpContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code TernaryOp}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void enterTernaryOp(BindingExpressionParser.TernaryOpContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code TernaryOp}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void exitTernaryOp(BindingExpressionParser.TernaryOpContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code Primary}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void enterPrimary(BindingExpressionParser.PrimaryContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code Primary}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void exitPrimary(BindingExpressionParser.PrimaryContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code DotOp}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void enterDotOp(BindingExpressionParser.DotOpContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code DotOp}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void exitDotOp(BindingExpressionParser.DotOpContext ctx);
+	/**
+	 * Enter a parse tree produced by the {@code MathOp}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void enterMathOp(BindingExpressionParser.MathOpContext ctx);
+	/**
+	 * Exit a parse tree produced by the {@code MathOp}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 */
+	void exitMathOp(BindingExpressionParser.MathOpContext ctx);
 	/**
 	 * Enter a parse tree produced by the {@code InstanceOfOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void enterInstanceOfOp(@NotNull BindingExpressionParser.InstanceOfOpContext ctx);
+	void enterInstanceOfOp(BindingExpressionParser.InstanceOfOpContext ctx);
 	/**
 	 * Exit a parse tree produced by the {@code InstanceOfOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void exitInstanceOfOp(@NotNull BindingExpressionParser.InstanceOfOpContext ctx);
-
+	void exitInstanceOfOp(BindingExpressionParser.InstanceOfOpContext ctx);
 	/**
 	 * Enter a parse tree produced by the {@code BinaryOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void enterBinaryOp(@NotNull BindingExpressionParser.BinaryOpContext ctx);
+	void enterBinaryOp(BindingExpressionParser.BinaryOpContext ctx);
 	/**
 	 * Exit a parse tree produced by the {@code BinaryOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void exitBinaryOp(@NotNull BindingExpressionParser.BinaryOpContext ctx);
-
+	void exitBinaryOp(BindingExpressionParser.BinaryOpContext ctx);
 	/**
-	 * Enter a parse tree produced by {@link BindingExpressionParser#bindingSyntax}.
+	 * Enter a parse tree produced by the {@code FunctionRef}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void enterBindingSyntax(@NotNull BindingExpressionParser.BindingSyntaxContext ctx);
+	void enterFunctionRef(BindingExpressionParser.FunctionRefContext ctx);
 	/**
-	 * Exit a parse tree produced by {@link BindingExpressionParser#bindingSyntax}.
+	 * Exit a parse tree produced by the {@code FunctionRef}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 */
-	void exitBindingSyntax(@NotNull BindingExpressionParser.BindingSyntaxContext ctx);
-
-	/**
-	 * Enter a parse tree produced by {@link BindingExpressionParser#defaults}.
-	 * @param ctx the parse tree
-	 */
-	void enterDefaults(@NotNull BindingExpressionParser.DefaultsContext ctx);
-	/**
-	 * Exit a parse tree produced by {@link BindingExpressionParser#defaults}.
-	 * @param ctx the parse tree
-	 */
-	void exitDefaults(@NotNull BindingExpressionParser.DefaultsContext ctx);
-
-	/**
-	 * Enter a parse tree produced by {@link BindingExpressionParser#constantValue}.
-	 * @param ctx the parse tree
-	 */
-	void enterConstantValue(@NotNull BindingExpressionParser.ConstantValueContext ctx);
-	/**
-	 * Exit a parse tree produced by {@link BindingExpressionParser#constantValue}.
-	 * @param ctx the parse tree
-	 */
-	void exitConstantValue(@NotNull BindingExpressionParser.ConstantValueContext ctx);
-
-	/**
-	 * Enter a parse tree produced by {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void enterExpression(@NotNull BindingExpressionParser.ExpressionContext ctx);
-	/**
-	 * Exit a parse tree produced by {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 */
-	void exitExpression(@NotNull BindingExpressionParser.ExpressionContext ctx);
-
+	void exitFunctionRef(BindingExpressionParser.FunctionRefContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#classExtraction}.
 	 * @param ctx the parse tree
 	 */
-	void enterClassExtraction(@NotNull BindingExpressionParser.ClassExtractionContext ctx);
+	void enterClassExtraction(BindingExpressionParser.ClassExtractionContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#classExtraction}.
 	 * @param ctx the parse tree
 	 */
-	void exitClassExtraction(@NotNull BindingExpressionParser.ClassExtractionContext ctx);
-
+	void exitClassExtraction(BindingExpressionParser.ClassExtractionContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#expressionList}.
 	 * @param ctx the parse tree
 	 */
-	void enterExpressionList(@NotNull BindingExpressionParser.ExpressionListContext ctx);
+	void enterExpressionList(BindingExpressionParser.ExpressionListContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#expressionList}.
 	 * @param ctx the parse tree
 	 */
-	void exitExpressionList(@NotNull BindingExpressionParser.ExpressionListContext ctx);
-
+	void exitExpressionList(BindingExpressionParser.ExpressionListContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#literal}.
 	 * @param ctx the parse tree
 	 */
-	void enterLiteral(@NotNull BindingExpressionParser.LiteralContext ctx);
+	void enterLiteral(BindingExpressionParser.LiteralContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#literal}.
 	 * @param ctx the parse tree
 	 */
-	void exitLiteral(@NotNull BindingExpressionParser.LiteralContext ctx);
-
+	void exitLiteral(BindingExpressionParser.LiteralContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#identifier}.
 	 * @param ctx the parse tree
 	 */
-	void enterIdentifier(@NotNull BindingExpressionParser.IdentifierContext ctx);
+	void enterIdentifier(BindingExpressionParser.IdentifierContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#identifier}.
 	 * @param ctx the parse tree
 	 */
-	void exitIdentifier(@NotNull BindingExpressionParser.IdentifierContext ctx);
-
+	void exitIdentifier(BindingExpressionParser.IdentifierContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#javaLiteral}.
 	 * @param ctx the parse tree
 	 */
-	void enterJavaLiteral(@NotNull BindingExpressionParser.JavaLiteralContext ctx);
+	void enterJavaLiteral(BindingExpressionParser.JavaLiteralContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#javaLiteral}.
 	 * @param ctx the parse tree
 	 */
-	void exitJavaLiteral(@NotNull BindingExpressionParser.JavaLiteralContext ctx);
-
+	void exitJavaLiteral(BindingExpressionParser.JavaLiteralContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#stringLiteral}.
 	 * @param ctx the parse tree
 	 */
-	void enterStringLiteral(@NotNull BindingExpressionParser.StringLiteralContext ctx);
+	void enterStringLiteral(BindingExpressionParser.StringLiteralContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#stringLiteral}.
 	 * @param ctx the parse tree
 	 */
-	void exitStringLiteral(@NotNull BindingExpressionParser.StringLiteralContext ctx);
-
+	void exitStringLiteral(BindingExpressionParser.StringLiteralContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#explicitGenericInvocation}.
 	 * @param ctx the parse tree
 	 */
-	void enterExplicitGenericInvocation(@NotNull BindingExpressionParser.ExplicitGenericInvocationContext ctx);
+	void enterExplicitGenericInvocation(BindingExpressionParser.ExplicitGenericInvocationContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#explicitGenericInvocation}.
 	 * @param ctx the parse tree
 	 */
-	void exitExplicitGenericInvocation(@NotNull BindingExpressionParser.ExplicitGenericInvocationContext ctx);
-
+	void exitExplicitGenericInvocation(BindingExpressionParser.ExplicitGenericInvocationContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#typeArguments}.
 	 * @param ctx the parse tree
 	 */
-	void enterTypeArguments(@NotNull BindingExpressionParser.TypeArgumentsContext ctx);
+	void enterTypeArguments(BindingExpressionParser.TypeArgumentsContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#typeArguments}.
 	 * @param ctx the parse tree
 	 */
-	void exitTypeArguments(@NotNull BindingExpressionParser.TypeArgumentsContext ctx);
-
+	void exitTypeArguments(BindingExpressionParser.TypeArgumentsContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#type}.
 	 * @param ctx the parse tree
 	 */
-	void enterType(@NotNull BindingExpressionParser.TypeContext ctx);
+	void enterType(BindingExpressionParser.TypeContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#type}.
 	 * @param ctx the parse tree
 	 */
-	void exitType(@NotNull BindingExpressionParser.TypeContext ctx);
-
+	void exitType(BindingExpressionParser.TypeContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#explicitGenericInvocationSuffix}.
 	 * @param ctx the parse tree
 	 */
-	void enterExplicitGenericInvocationSuffix(@NotNull BindingExpressionParser.ExplicitGenericInvocationSuffixContext ctx);
+	void enterExplicitGenericInvocationSuffix(BindingExpressionParser.ExplicitGenericInvocationSuffixContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#explicitGenericInvocationSuffix}.
 	 * @param ctx the parse tree
 	 */
-	void exitExplicitGenericInvocationSuffix(@NotNull BindingExpressionParser.ExplicitGenericInvocationSuffixContext ctx);
-
+	void exitExplicitGenericInvocationSuffix(BindingExpressionParser.ExplicitGenericInvocationSuffixContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#arguments}.
 	 * @param ctx the parse tree
 	 */
-	void enterArguments(@NotNull BindingExpressionParser.ArgumentsContext ctx);
+	void enterArguments(BindingExpressionParser.ArgumentsContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#arguments}.
 	 * @param ctx the parse tree
 	 */
-	void exitArguments(@NotNull BindingExpressionParser.ArgumentsContext ctx);
-
+	void exitArguments(BindingExpressionParser.ArgumentsContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#classOrInterfaceType}.
 	 * @param ctx the parse tree
 	 */
-	void enterClassOrInterfaceType(@NotNull BindingExpressionParser.ClassOrInterfaceTypeContext ctx);
+	void enterClassOrInterfaceType(BindingExpressionParser.ClassOrInterfaceTypeContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#classOrInterfaceType}.
 	 * @param ctx the parse tree
 	 */
-	void exitClassOrInterfaceType(@NotNull BindingExpressionParser.ClassOrInterfaceTypeContext ctx);
-
+	void exitClassOrInterfaceType(BindingExpressionParser.ClassOrInterfaceTypeContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#primitiveType}.
 	 * @param ctx the parse tree
 	 */
-	void enterPrimitiveType(@NotNull BindingExpressionParser.PrimitiveTypeContext ctx);
+	void enterPrimitiveType(BindingExpressionParser.PrimitiveTypeContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#primitiveType}.
 	 * @param ctx the parse tree
 	 */
-	void exitPrimitiveType(@NotNull BindingExpressionParser.PrimitiveTypeContext ctx);
-
+	void exitPrimitiveType(BindingExpressionParser.PrimitiveTypeContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#resources}.
 	 * @param ctx the parse tree
 	 */
-	void enterResources(@NotNull BindingExpressionParser.ResourcesContext ctx);
+	void enterResources(BindingExpressionParser.ResourcesContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#resources}.
 	 * @param ctx the parse tree
 	 */
-	void exitResources(@NotNull BindingExpressionParser.ResourcesContext ctx);
-
+	void exitResources(BindingExpressionParser.ResourcesContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link BindingExpressionParser#resourceParameters}.
 	 * @param ctx the parse tree
 	 */
-	void enterResourceParameters(@NotNull BindingExpressionParser.ResourceParametersContext ctx);
+	void enterResourceParameters(BindingExpressionParser.ResourceParametersContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link BindingExpressionParser#resourceParameters}.
 	 * @param ctx the parse tree
 	 */
-	void exitResourceParameters(@NotNull BindingExpressionParser.ResourceParametersContext ctx);
+	void exitResourceParameters(BindingExpressionParser.ResourceParametersContext ctx);
 }
\ No newline at end of file
diff --git a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionParser.java b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionParser.java
index b469d2d..9633908 100644
--- a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionParser.java
+++ b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionParser.java
@@ -1,4 +1,4 @@
-// Generated from BindingExpression.g4 by ANTLR 4.5
+// Generated from BindingExpression.g4 by ANTLR 4.5.3
 package android.databinding.parser;
 import org.antlr.v4.runtime.atn.*;
 import org.antlr.v4.runtime.dfa.DFA;
@@ -9,47 +9,55 @@
 import java.util.Iterator;
 import java.util.ArrayList;
 
+@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
 public class BindingExpressionParser extends Parser {
+	static { RuntimeMetaData.checkVersion("4.5.3", RuntimeMetaData.VERSION); }
+
+	protected static final DFA[] _decisionToDFA;
+	protected static final PredictionContextCache _sharedContextCache =
+		new PredictionContextCache();
 	public static final int
 		T__0=1, T__1=2, T__2=3, T__3=4, T__4=5, T__5=6, T__6=7, T__7=8, T__8=9, 
 		T__9=10, T__10=11, T__11=12, T__12=13, T__13=14, T__14=15, T__15=16, T__16=17, 
 		T__17=18, T__18=19, T__19=20, T__20=21, T__21=22, T__22=23, T__23=24, 
 		T__24=25, T__25=26, T__26=27, T__27=28, T__28=29, T__29=30, T__30=31, 
 		T__31=32, T__32=33, T__33=34, T__34=35, T__35=36, T__36=37, T__37=38, 
-		T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, THIS=44, IntegerLiteral=45, 
-		FloatingPointLiteral=46, BooleanLiteral=47, CharacterLiteral=48, SingleQuoteString=49, 
-		DoubleQuoteString=50, NullLiteral=51, Identifier=52, WS=53, ResourceReference=54, 
-		PackageName=55, ResourceType=56;
+		T__38=39, T__39=40, T__40=41, T__41=42, T__42=43, T__43=44, THIS=45, VoidLiteral=46, 
+		IntegerLiteral=47, FloatingPointLiteral=48, BooleanLiteral=49, CharacterLiteral=50, 
+		SingleQuoteString=51, DoubleQuoteString=52, NullLiteral=53, Identifier=54, 
+		WS=55, ResourceReference=56, PackageName=57, ResourceType=58;
 	public static final int
-		RULE_bindingSyntax = 0, RULE_defaults = 1, RULE_constantValue = 2, RULE_expression = 3, 
-		RULE_classExtraction = 4, RULE_expressionList = 5, RULE_literal = 6, RULE_identifier = 7, 
-		RULE_javaLiteral = 8, RULE_stringLiteral = 9, RULE_explicitGenericInvocation = 10, 
-		RULE_typeArguments = 11, RULE_type = 12, RULE_explicitGenericInvocationSuffix = 13, 
-		RULE_arguments = 14, RULE_classOrInterfaceType = 15, RULE_primitiveType = 16, 
-		RULE_resources = 17, RULE_resourceParameters = 18;
+		RULE_bindingSyntax = 0, RULE_defaults = 1, RULE_constantValue = 2, RULE_lambdaExpression = 3, 
+		RULE_lambdaParameters = 4, RULE_inferredFormalParameterList = 5, RULE_expression = 6, 
+		RULE_classExtraction = 7, RULE_expressionList = 8, RULE_literal = 9, RULE_identifier = 10, 
+		RULE_javaLiteral = 11, RULE_stringLiteral = 12, RULE_explicitGenericInvocation = 13, 
+		RULE_typeArguments = 14, RULE_type = 15, RULE_explicitGenericInvocationSuffix = 16, 
+		RULE_arguments = 17, RULE_classOrInterfaceType = 18, RULE_primitiveType = 19, 
+		RULE_resources = 20, RULE_resourceParameters = 21;
 	public static final String[] ruleNames = {
-		"bindingSyntax", "defaults", "constantValue", "expression", "classExtraction", 
-		"expressionList", "literal", "identifier", "javaLiteral", "stringLiteral", 
-		"explicitGenericInvocation", "typeArguments", "type", "explicitGenericInvocationSuffix", 
-		"arguments", "classOrInterfaceType", "primitiveType", "resources", "resourceParameters"
+		"bindingSyntax", "defaults", "constantValue", "lambdaExpression", "lambdaParameters", 
+		"inferredFormalParameterList", "expression", "classExtraction", "expressionList", 
+		"literal", "identifier", "javaLiteral", "stringLiteral", "explicitGenericInvocation", 
+		"typeArguments", "type", "explicitGenericInvocationSuffix", "arguments", 
+		"classOrInterfaceType", "primitiveType", "resources", "resourceParameters"
 	};
 
 	private static final String[] _LITERAL_NAMES = {
-		null, "','", "'default'", "'='", "'('", "')'", "'.'", "'['", "']'", "'+'", 
-		"'-'", "'~'", "'!'", "'*'", "'/'", "'%'", "'<<'", "'>>>'", "'>>'", "'<='", 
-		"'>='", "'>'", "'<'", "'instanceof'", "'=='", "'!='", "'&'", "'^'", "'|'", 
-		"'&&'", "'||'", "'?'", "':'", "'??'", "'class'", "'void'", "'boolean'", 
-		"'char'", "'byte'", "'short'", "'int'", "'long'", "'float'", "'double'", 
-		"'this'", null, null, null, null, null, null, "'null'"
+		null, "','", "'default'", "'='", "'->'", "'('", "')'", "'.'", "'::'", 
+		"'['", "']'", "'+'", "'-'", "'~'", "'!'", "'*'", "'/'", "'%'", "'<<'", 
+		"'>>>'", "'>>'", "'<='", "'>='", "'>'", "'<'", "'instanceof'", "'=='", 
+		"'!='", "'&'", "'^'", "'|'", "'&&'", "'||'", "'?'", "':'", "'??'", "'class'", 
+		"'boolean'", "'char'", "'byte'", "'short'", "'int'", "'long'", "'float'", 
+		"'double'", "'this'", null, null, null, null, null, null, null, "'null'"
 	};
 	private static final String[] _SYMBOLIC_NAMES = {
 		null, null, null, null, null, null, null, null, null, null, null, null, 
 		null, null, null, null, null, null, null, null, null, null, null, null, 
 		null, null, null, null, null, null, null, null, null, null, null, null, 
-		null, null, null, null, null, null, null, null, "THIS", "IntegerLiteral", 
-		"FloatingPointLiteral", "BooleanLiteral", "CharacterLiteral", "SingleQuoteString", 
-		"DoubleQuoteString", "NullLiteral", "Identifier", "WS", "ResourceReference", 
-		"PackageName", "ResourceType"
+		null, null, null, null, null, null, null, null, null, "THIS", "VoidLiteral", 
+		"IntegerLiteral", "FloatingPointLiteral", "BooleanLiteral", "CharacterLiteral", 
+		"SingleQuoteString", "DoubleQuoteString", "NullLiteral", "Identifier", 
+		"WS", "ResourceReference", "PackageName", "ResourceType"
 	};
 	public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
 
@@ -79,7 +87,7 @@
 	}
 
 	@Override
-	@NotNull
+
 	public Vocabulary getVocabulary() {
 		return VOCABULARY;
 	}
@@ -93,55 +101,99 @@
 	@Override
 	public String getSerializedATN() { return _serializedATN; }
 
+	@Override
+	public ATN getATN() { return _ATN; }
+
 	public BindingExpressionParser(TokenStream input) {
 		super(input);
-		_interp = new ParserATNSimulator(this,_ATN);
+		_interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
 	}
 	public static class BindingSyntaxContext extends ParserRuleContext {
+		public BindingSyntaxContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_bindingSyntax; }
+	 
+		public BindingSyntaxContext() { }
+		public void copyFrom(BindingSyntaxContext ctx) {
+			super.copyFrom(ctx);
+		}
+	}
+	public static class RootExprContext extends BindingSyntaxContext {
 		public ExpressionContext expression() {
 			return getRuleContext(ExpressionContext.class,0);
 		}
 		public DefaultsContext defaults() {
 			return getRuleContext(DefaultsContext.class,0);
 		}
-		public BindingSyntaxContext(ParserRuleContext parent, int invokingState) {
-			super(parent, invokingState);
-		}
-		@Override public int getRuleIndex() { return RULE_bindingSyntax; }
+		public RootExprContext(BindingSyntaxContext ctx) { copyFrom(ctx); }
 		@Override
 		public void enterRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterBindingSyntax(this);
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterRootExpr(this);
 		}
 		@Override
 		public void exitRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitBindingSyntax(this);
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitRootExpr(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitBindingSyntax(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitRootExpr(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+	public static class RootLambdaContext extends BindingSyntaxContext {
+		public LambdaExpressionContext lambdaExpression() {
+			return getRuleContext(LambdaExpressionContext.class,0);
+		}
+		public RootLambdaContext(BindingSyntaxContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterRootLambda(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitRootLambda(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitRootLambda(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final BindingSyntaxContext bindingSyntax() throws RecognitionException {
 		BindingSyntaxContext _localctx = new BindingSyntaxContext(_ctx, getState());
 		enterRule(_localctx, 0, RULE_bindingSyntax);
 		int _la;
 		try {
-			enterOuterAlt(_localctx, 1);
-			{
-			setState(38);
-			expression(0);
-			setState(40);
-			_la = _input.LA(1);
-			if (_la==T__0) {
+			setState(49);
+			_errHandler.sync(this);
+			switch ( getInterpreter().adaptivePredict(_input,1,_ctx) ) {
+			case 1:
+				_localctx = new RootExprContext(_localctx);
+				enterOuterAlt(_localctx, 1);
 				{
-				setState(39);
-				defaults();
+				setState(44);
+				expression(0);
+				setState(46);
+				_la = _input.LA(1);
+				if (_la==T__0) {
+					{
+					setState(45);
+					defaults();
+					}
 				}
-			}
 
+				}
+				break;
+			case 2:
+				_localctx = new RootLambdaContext(_localctx);
+				enterOuterAlt(_localctx, 2);
+				{
+				setState(48);
+				lambdaExpression();
+				}
+				break;
 			}
 		}
 		catch (RecognitionException re) {
@@ -172,26 +224,25 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitDefaults(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitDefaults(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitDefaults(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final DefaultsContext defaults() throws RecognitionException {
 		DefaultsContext _localctx = new DefaultsContext(_ctx, getState());
 		enterRule(_localctx, 2, RULE_defaults);
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(42);
+			setState(51);
 			match(T__0);
-			setState(43);
+			setState(52);
 			match(T__1);
-			setState(44);
+			setState(53);
 			match(T__2);
-			setState(45);
+			setState(54);
 			constantValue();
 			}
 		}
@@ -227,18 +278,17 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitConstantValue(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitConstantValue(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitConstantValue(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ConstantValueContext constantValue() throws RecognitionException {
 		ConstantValueContext _localctx = new ConstantValueContext(_ctx, getState());
 		enterRule(_localctx, 4, RULE_constantValue);
 		try {
-			setState(50);
+			setState(59);
 			switch (_input.LA(1)) {
 			case IntegerLiteral:
 			case FloatingPointLiteral:
@@ -249,21 +299,21 @@
 			case NullLiteral:
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(47);
+				setState(56);
 				literal();
 				}
 				break;
 			case ResourceReference:
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(48);
+				setState(57);
 				match(ResourceReference);
 				}
 				break;
 			case Identifier:
 				enterOuterAlt(_localctx, 3);
 				{
-				setState(49);
+				setState(58);
 				identifier();
 				}
 				break;
@@ -282,6 +332,219 @@
 		return _localctx;
 	}
 
+	public static class LambdaExpressionContext extends ParserRuleContext {
+		public LambdaParametersContext args;
+		public ExpressionContext expr;
+		public LambdaParametersContext lambdaParameters() {
+			return getRuleContext(LambdaParametersContext.class,0);
+		}
+		public ExpressionContext expression() {
+			return getRuleContext(ExpressionContext.class,0);
+		}
+		public LambdaExpressionContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_lambdaExpression; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterLambdaExpression(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitLambdaExpression(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitLambdaExpression(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	public final LambdaExpressionContext lambdaExpression() throws RecognitionException {
+		LambdaExpressionContext _localctx = new LambdaExpressionContext(_ctx, getState());
+		enterRule(_localctx, 6, RULE_lambdaExpression);
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(61);
+			((LambdaExpressionContext)_localctx).args = lambdaParameters();
+			setState(62);
+			match(T__3);
+			setState(63);
+			((LambdaExpressionContext)_localctx).expr = expression(0);
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class LambdaParametersContext extends ParserRuleContext {
+		public LambdaParametersContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_lambdaParameters; }
+	 
+		public LambdaParametersContext() { }
+		public void copyFrom(LambdaParametersContext ctx) {
+			super.copyFrom(ctx);
+		}
+	}
+	public static class SingleLambdaParameterContext extends LambdaParametersContext {
+		public TerminalNode Identifier() { return getToken(BindingExpressionParser.Identifier, 0); }
+		public SingleLambdaParameterContext(LambdaParametersContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterSingleLambdaParameter(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitSingleLambdaParameter(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitSingleLambdaParameter(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+	public static class LambdaParameterListContext extends LambdaParametersContext {
+		public InferredFormalParameterListContext params;
+		public InferredFormalParameterListContext inferredFormalParameterList() {
+			return getRuleContext(InferredFormalParameterListContext.class,0);
+		}
+		public LambdaParameterListContext(LambdaParametersContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterLambdaParameterList(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitLambdaParameterList(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitLambdaParameterList(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	public final LambdaParametersContext lambdaParameters() throws RecognitionException {
+		LambdaParametersContext _localctx = new LambdaParametersContext(_ctx, getState());
+		enterRule(_localctx, 8, RULE_lambdaParameters);
+		int _la;
+		try {
+			setState(71);
+			switch (_input.LA(1)) {
+			case Identifier:
+				_localctx = new SingleLambdaParameterContext(_localctx);
+				enterOuterAlt(_localctx, 1);
+				{
+				setState(65);
+				match(Identifier);
+				}
+				break;
+			case T__4:
+				_localctx = new LambdaParameterListContext(_localctx);
+				enterOuterAlt(_localctx, 2);
+				{
+				setState(66);
+				match(T__4);
+				setState(68);
+				_la = _input.LA(1);
+				if (_la==Identifier) {
+					{
+					setState(67);
+					((LambdaParameterListContext)_localctx).params = inferredFormalParameterList();
+					}
+				}
+
+				setState(70);
+				match(T__5);
+				}
+				break;
+			default:
+				throw new NoViableAltException(this);
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
+	public static class InferredFormalParameterListContext extends ParserRuleContext {
+		public List<TerminalNode> Identifier() { return getTokens(BindingExpressionParser.Identifier); }
+		public TerminalNode Identifier(int i) {
+			return getToken(BindingExpressionParser.Identifier, i);
+		}
+		public InferredFormalParameterListContext(ParserRuleContext parent, int invokingState) {
+			super(parent, invokingState);
+		}
+		@Override public int getRuleIndex() { return RULE_inferredFormalParameterList; }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterInferredFormalParameterList(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitInferredFormalParameterList(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitInferredFormalParameterList(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+
+	public final InferredFormalParameterListContext inferredFormalParameterList() throws RecognitionException {
+		InferredFormalParameterListContext _localctx = new InferredFormalParameterListContext(_ctx, getState());
+		enterRule(_localctx, 10, RULE_inferredFormalParameterList);
+		int _la;
+		try {
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(73);
+			match(Identifier);
+			setState(78);
+			_errHandler.sync(this);
+			_la = _input.LA(1);
+			while (_la==T__0) {
+				{
+				{
+				setState(74);
+				match(T__0);
+				setState(75);
+				match(Identifier);
+				}
+				}
+				setState(80);
+				_errHandler.sync(this);
+				_la = _input.LA(1);
+			}
+			}
+		}
+		catch (RecognitionException re) {
+			_localctx.exception = re;
+			_errHandler.reportError(this, re);
+			_errHandler.recover(this, re);
+		}
+		finally {
+			exitRule();
+		}
+		return _localctx;
+	}
+
 	public static class ExpressionContext extends ParserRuleContext {
 		public ExpressionContext(ParserRuleContext parent, int invokingState) {
 			super(parent, invokingState);
@@ -293,47 +556,6 @@
 			super.copyFrom(ctx);
 		}
 	}
-	public static class BracketOpContext extends ExpressionContext {
-		public List<? extends ExpressionContext> expression() {
-			return getRuleContexts(ExpressionContext.class);
-		}
-		public ExpressionContext expression(int i) {
-			return getRuleContext(ExpressionContext.class,i);
-		}
-		public BracketOpContext(ExpressionContext ctx) { copyFrom(ctx); }
-		@Override
-		public void enterRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterBracketOp(this);
-		}
-		@Override
-		public void exitRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitBracketOp(this);
-		}
-		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitBracketOp(this);
-			else return visitor.visitChildren(this);
-		}
-	}
-	public static class ResourceContext extends ExpressionContext {
-		public ResourcesContext resources() {
-			return getRuleContext(ResourcesContext.class,0);
-		}
-		public ResourceContext(ExpressionContext ctx) { copyFrom(ctx); }
-		@Override
-		public void enterRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterResource(this);
-		}
-		@Override
-		public void exitRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitResource(this);
-		}
-		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitResource(this);
-			else return visitor.visitChildren(this);
-		}
-	}
 	public static class CastOpContext extends ExpressionContext {
 		public TypeContext type() {
 			return getRuleContext(TypeContext.class,0);
@@ -351,8 +573,33 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitCastOp(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitCastOp(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitCastOp(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+	public static class ComparisonOpContext extends ExpressionContext {
+		public ExpressionContext left;
+		public Token op;
+		public ExpressionContext right;
+		public List<ExpressionContext> expression() {
+			return getRuleContexts(ExpressionContext.class);
+		}
+		public ExpressionContext expression(int i) {
+			return getRuleContext(ExpressionContext.class,i);
+		}
+		public ComparisonOpContext(ExpressionContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterComparisonOp(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitComparisonOp(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitComparisonOp(this);
 			else return visitor.visitChildren(this);
 		}
 	}
@@ -371,33 +618,93 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitUnaryOp(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitUnaryOp(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitUnaryOp(this);
 			else return visitor.visitChildren(this);
 		}
 	}
-	public static class AndOrOpContext extends ExpressionContext {
-		public ExpressionContext left;
-		public Token op;
-		public ExpressionContext right;
-		public List<? extends ExpressionContext> expression() {
+	public static class BracketOpContext extends ExpressionContext {
+		public List<ExpressionContext> expression() {
 			return getRuleContexts(ExpressionContext.class);
 		}
 		public ExpressionContext expression(int i) {
 			return getRuleContext(ExpressionContext.class,i);
 		}
-		public AndOrOpContext(ExpressionContext ctx) { copyFrom(ctx); }
+		public BracketOpContext(ExpressionContext ctx) { copyFrom(ctx); }
 		@Override
 		public void enterRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterAndOrOp(this);
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterBracketOp(this);
 		}
 		@Override
 		public void exitRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitAndOrOp(this);
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitBracketOp(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitAndOrOp(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitBracketOp(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+	public static class ResourceContext extends ExpressionContext {
+		public ResourcesContext resources() {
+			return getRuleContext(ResourcesContext.class,0);
+		}
+		public ResourceContext(ExpressionContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterResource(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitResource(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitResource(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+	public static class QuestionQuestionOpContext extends ExpressionContext {
+		public ExpressionContext left;
+		public Token op;
+		public ExpressionContext right;
+		public List<ExpressionContext> expression() {
+			return getRuleContexts(ExpressionContext.class);
+		}
+		public ExpressionContext expression(int i) {
+			return getRuleContext(ExpressionContext.class,i);
+		}
+		public QuestionQuestionOpContext(ExpressionContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterQuestionQuestionOp(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitQuestionQuestionOp(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitQuestionQuestionOp(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+	public static class GroupingContext extends ExpressionContext {
+		public ExpressionContext expression() {
+			return getRuleContext(ExpressionContext.class,0);
+		}
+		public GroupingContext(ExpressionContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterGrouping(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitGrouping(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitGrouping(this);
 			else return visitor.visitChildren(this);
 		}
 	}
@@ -422,8 +729,84 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitMethodInvocation(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitMethodInvocation(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitMethodInvocation(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+	public static class BitShiftOpContext extends ExpressionContext {
+		public ExpressionContext left;
+		public Token op;
+		public ExpressionContext right;
+		public List<ExpressionContext> expression() {
+			return getRuleContexts(ExpressionContext.class);
+		}
+		public ExpressionContext expression(int i) {
+			return getRuleContext(ExpressionContext.class,i);
+		}
+		public BitShiftOpContext(ExpressionContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterBitShiftOp(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitBitShiftOp(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitBitShiftOp(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+	public static class AndOrOpContext extends ExpressionContext {
+		public ExpressionContext left;
+		public Token op;
+		public ExpressionContext right;
+		public List<ExpressionContext> expression() {
+			return getRuleContexts(ExpressionContext.class);
+		}
+		public ExpressionContext expression(int i) {
+			return getRuleContext(ExpressionContext.class,i);
+		}
+		public AndOrOpContext(ExpressionContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterAndOrOp(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitAndOrOp(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitAndOrOp(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+	public static class TernaryOpContext extends ExpressionContext {
+		public ExpressionContext left;
+		public Token op;
+		public ExpressionContext iftrue;
+		public ExpressionContext iffalse;
+		public List<ExpressionContext> expression() {
+			return getRuleContexts(ExpressionContext.class);
+		}
+		public ExpressionContext expression(int i) {
+			return getRuleContext(ExpressionContext.class,i);
+		}
+		public TernaryOpContext(ExpressionContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterTernaryOp(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitTernaryOp(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitTernaryOp(this);
 			else return visitor.visitChildren(this);
 		}
 	}
@@ -431,6 +814,7 @@
 		public LiteralContext literal() {
 			return getRuleContext(LiteralContext.class,0);
 		}
+		public TerminalNode VoidLiteral() { return getToken(BindingExpressionParser.VoidLiteral, 0); }
 		public IdentifierContext identifier() {
 			return getRuleContext(IdentifierContext.class,0);
 		}
@@ -447,78 +831,8 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitPrimary(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitPrimary(this);
-			else return visitor.visitChildren(this);
-		}
-	}
-	public static class GroupingContext extends ExpressionContext {
-		public ExpressionContext expression() {
-			return getRuleContext(ExpressionContext.class,0);
-		}
-		public GroupingContext(ExpressionContext ctx) { copyFrom(ctx); }
-		@Override
-		public void enterRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterGrouping(this);
-		}
-		@Override
-		public void exitRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitGrouping(this);
-		}
-		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitGrouping(this);
-			else return visitor.visitChildren(this);
-		}
-	}
-	public static class TernaryOpContext extends ExpressionContext {
-		public ExpressionContext left;
-		public Token op;
-		public ExpressionContext iftrue;
-		public ExpressionContext iffalse;
-		public List<? extends ExpressionContext> expression() {
-			return getRuleContexts(ExpressionContext.class);
-		}
-		public ExpressionContext expression(int i) {
-			return getRuleContext(ExpressionContext.class,i);
-		}
-		public TernaryOpContext(ExpressionContext ctx) { copyFrom(ctx); }
-		@Override
-		public void enterRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterTernaryOp(this);
-		}
-		@Override
-		public void exitRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitTernaryOp(this);
-		}
-		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitTernaryOp(this);
-			else return visitor.visitChildren(this);
-		}
-	}
-	public static class ComparisonOpContext extends ExpressionContext {
-		public ExpressionContext left;
-		public Token op;
-		public ExpressionContext right;
-		public List<? extends ExpressionContext> expression() {
-			return getRuleContexts(ExpressionContext.class);
-		}
-		public ExpressionContext expression(int i) {
-			return getRuleContext(ExpressionContext.class,i);
-		}
-		public ComparisonOpContext(ExpressionContext ctx) { copyFrom(ctx); }
-		@Override
-		public void enterRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterComparisonOp(this);
-		}
-		@Override
-		public void exitRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitComparisonOp(this);
-		}
-		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitComparisonOp(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitPrimary(this);
 			else return visitor.visitChildren(this);
 		}
 	}
@@ -537,8 +851,8 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitDotOp(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitDotOp(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitDotOp(this);
 			else return visitor.visitChildren(this);
 		}
 	}
@@ -546,7 +860,7 @@
 		public ExpressionContext left;
 		public Token op;
 		public ExpressionContext right;
-		public List<? extends ExpressionContext> expression() {
+		public List<ExpressionContext> expression() {
 			return getRuleContexts(ExpressionContext.class);
 		}
 		public ExpressionContext expression(int i) {
@@ -562,58 +876,8 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitMathOp(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitMathOp(this);
-			else return visitor.visitChildren(this);
-		}
-	}
-	public static class QuestionQuestionOpContext extends ExpressionContext {
-		public ExpressionContext left;
-		public Token op;
-		public ExpressionContext right;
-		public List<? extends ExpressionContext> expression() {
-			return getRuleContexts(ExpressionContext.class);
-		}
-		public ExpressionContext expression(int i) {
-			return getRuleContext(ExpressionContext.class,i);
-		}
-		public QuestionQuestionOpContext(ExpressionContext ctx) { copyFrom(ctx); }
-		@Override
-		public void enterRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterQuestionQuestionOp(this);
-		}
-		@Override
-		public void exitRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitQuestionQuestionOp(this);
-		}
-		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitQuestionQuestionOp(this);
-			else return visitor.visitChildren(this);
-		}
-	}
-	public static class BitShiftOpContext extends ExpressionContext {
-		public ExpressionContext left;
-		public Token op;
-		public ExpressionContext right;
-		public List<? extends ExpressionContext> expression() {
-			return getRuleContexts(ExpressionContext.class);
-		}
-		public ExpressionContext expression(int i) {
-			return getRuleContext(ExpressionContext.class,i);
-		}
-		public BitShiftOpContext(ExpressionContext ctx) { copyFrom(ctx); }
-		@Override
-		public void enterRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterBitShiftOp(this);
-		}
-		@Override
-		public void exitRule(ParseTreeListener listener) {
-			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitBitShiftOp(this);
-		}
-		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitBitShiftOp(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitMathOp(this);
 			else return visitor.visitChildren(this);
 		}
 	}
@@ -634,8 +898,8 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitInstanceOfOp(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitInstanceOfOp(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitInstanceOfOp(this);
 			else return visitor.visitChildren(this);
 		}
 	}
@@ -643,7 +907,7 @@
 		public ExpressionContext left;
 		public Token op;
 		public ExpressionContext right;
-		public List<? extends ExpressionContext> expression() {
+		public List<ExpressionContext> expression() {
 			return getRuleContexts(ExpressionContext.class);
 		}
 		public ExpressionContext expression(int i) {
@@ -659,13 +923,32 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitBinaryOp(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitBinaryOp(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitBinaryOp(this);
+			else return visitor.visitChildren(this);
+		}
+	}
+	public static class FunctionRefContext extends ExpressionContext {
+		public ExpressionContext expression() {
+			return getRuleContext(ExpressionContext.class,0);
+		}
+		public TerminalNode Identifier() { return getToken(BindingExpressionParser.Identifier, 0); }
+		public FunctionRefContext(ExpressionContext ctx) { copyFrom(ctx); }
+		@Override
+		public void enterRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).enterFunctionRef(this);
+		}
+		@Override
+		public void exitRule(ParseTreeListener listener) {
+			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitFunctionRef(this);
+		}
+		@Override
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitFunctionRef(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ExpressionContext expression() throws RecognitionException {
 		return expression(0);
 	}
@@ -675,408 +958,409 @@
 		int _parentState = getState();
 		ExpressionContext _localctx = new ExpressionContext(_ctx, _parentState);
 		ExpressionContext _prevctx = _localctx;
-		int _startState = 6;
-		enterRecursionRule(_localctx, 6, RULE_expression, _p);
+		int _startState = 12;
+		enterRecursionRule(_localctx, 12, RULE_expression, _p);
 		int _la;
 		try {
 			int _alt;
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(70);
-			switch ( getInterpreter().adaptivePredict(_input,2,_ctx) ) {
+			setState(100);
+			_errHandler.sync(this);
+			switch ( getInterpreter().adaptivePredict(_input,6,_ctx) ) {
 			case 1:
 				{
-				_localctx = new CastOpContext(_localctx);
-				_ctx = _localctx;
-				_prevctx = _localctx;
-
-				setState(53);
-				match(T__3);
-				setState(54);
-				type();
-				setState(55);
-				match(T__4);
-				setState(56);
-				expression(16);
-				}
-				break;
-
-			case 2:
-				{
-				_localctx = new UnaryOpContext(_localctx);
-				_ctx = _localctx;
-				_prevctx = _localctx;
-				setState(58);
-				((UnaryOpContext)_localctx).op = _input.LT(1);
-				_la = _input.LA(1);
-				if ( !(_la==T__8 || _la==T__9) ) {
-					((UnaryOpContext)_localctx).op = _errHandler.recoverInline(this);
-				} else {
-					consume();
-				}
-				setState(59);
-				expression(15);
-				}
-				break;
-
-			case 3:
-				{
-				_localctx = new UnaryOpContext(_localctx);
-				_ctx = _localctx;
-				_prevctx = _localctx;
-				setState(60);
-				((UnaryOpContext)_localctx).op = _input.LT(1);
-				_la = _input.LA(1);
-				if ( !(_la==T__10 || _la==T__11) ) {
-					((UnaryOpContext)_localctx).op = _errHandler.recoverInline(this);
-				} else {
-					consume();
-				}
-				setState(61);
-				expression(14);
-				}
-				break;
-
-			case 4:
-				{
 				_localctx = new GroupingContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(62);
-				match(T__3);
-				setState(63);
-				expression(0);
-				setState(64);
+
+				setState(82);
 				match(T__4);
+				setState(83);
+				expression(0);
+				setState(84);
+				match(T__5);
 				}
 				break;
-
+			case 2:
+				{
+				_localctx = new PrimaryContext(_localctx);
+				_ctx = _localctx;
+				_prevctx = _localctx;
+				setState(86);
+				literal();
+				}
+				break;
+			case 3:
+				{
+				_localctx = new PrimaryContext(_localctx);
+				_ctx = _localctx;
+				_prevctx = _localctx;
+				setState(87);
+				match(VoidLiteral);
+				}
+				break;
+			case 4:
+				{
+				_localctx = new PrimaryContext(_localctx);
+				_ctx = _localctx;
+				_prevctx = _localctx;
+				setState(88);
+				identifier();
+				}
+				break;
 			case 5:
 				{
 				_localctx = new PrimaryContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(66);
-				literal();
-				}
-				break;
-
-			case 6:
-				{
-				_localctx = new PrimaryContext(_localctx);
-				_ctx = _localctx;
-				_prevctx = _localctx;
-				setState(67);
-				identifier();
-				}
-				break;
-
-			case 7:
-				{
-				_localctx = new PrimaryContext(_localctx);
-				_ctx = _localctx;
-				_prevctx = _localctx;
-				setState(68);
+				setState(89);
 				classExtraction();
 				}
 				break;
-
-			case 8:
+			case 6:
 				{
 				_localctx = new ResourceContext(_localctx);
 				_ctx = _localctx;
 				_prevctx = _localctx;
-				setState(69);
+				setState(90);
 				resources();
 				}
 				break;
+			case 7:
+				{
+				_localctx = new CastOpContext(_localctx);
+				_ctx = _localctx;
+				_prevctx = _localctx;
+				setState(91);
+				match(T__4);
+				setState(92);
+				type();
+				setState(93);
+				match(T__5);
+				setState(94);
+				expression(16);
+				}
+				break;
+			case 8:
+				{
+				_localctx = new UnaryOpContext(_localctx);
+				_ctx = _localctx;
+				_prevctx = _localctx;
+				setState(96);
+				((UnaryOpContext)_localctx).op = _input.LT(1);
+				_la = _input.LA(1);
+				if ( !(_la==T__10 || _la==T__11) ) {
+					((UnaryOpContext)_localctx).op = (Token)_errHandler.recoverInline(this);
+				} else {
+					consume();
+				}
+				setState(97);
+				expression(15);
+				}
+				break;
+			case 9:
+				{
+				_localctx = new UnaryOpContext(_localctx);
+				_ctx = _localctx;
+				_prevctx = _localctx;
+				setState(98);
+				((UnaryOpContext)_localctx).op = _input.LT(1);
+				_la = _input.LA(1);
+				if ( !(_la==T__12 || _la==T__13) ) {
+					((UnaryOpContext)_localctx).op = (Token)_errHandler.recoverInline(this);
+				} else {
+					consume();
+				}
+				setState(99);
+				expression(14);
+				}
+				break;
 			}
 			_ctx.stop = _input.LT(-1);
-			setState(132);
+			setState(165);
 			_errHandler.sync(this);
-			_alt = getInterpreter().adaptivePredict(_input,5,_ctx);
+			_alt = getInterpreter().adaptivePredict(_input,9,_ctx);
 			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
 				if ( _alt==1 ) {
 					if ( _parseListeners!=null ) triggerExitRuleEvent();
 					_prevctx = _localctx;
 					{
-					setState(130);
-					switch ( getInterpreter().adaptivePredict(_input,4,_ctx) ) {
+					setState(163);
+					_errHandler.sync(this);
+					switch ( getInterpreter().adaptivePredict(_input,8,_ctx) ) {
 					case 1:
 						{
 						_localctx = new MathOpContext(new ExpressionContext(_parentctx, _parentState));
 						((MathOpContext)_localctx).left = _prevctx;
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(72);
+						setState(102);
 						if (!(precpred(_ctx, 13))) throw new FailedPredicateException(this, "precpred(_ctx, 13)");
-						setState(73);
+						setState(103);
 						((MathOpContext)_localctx).op = _input.LT(1);
 						_la = _input.LA(1);
-						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__12) | (1L << T__13) | (1L << T__14))) != 0)) ) {
-							((MathOpContext)_localctx).op = _errHandler.recoverInline(this);
+						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__14) | (1L << T__15) | (1L << T__16))) != 0)) ) {
+							((MathOpContext)_localctx).op = (Token)_errHandler.recoverInline(this);
 						} else {
 							consume();
 						}
-						setState(74);
+						setState(104);
 						((MathOpContext)_localctx).right = expression(14);
 						}
 						break;
-
 					case 2:
 						{
 						_localctx = new MathOpContext(new ExpressionContext(_parentctx, _parentState));
 						((MathOpContext)_localctx).left = _prevctx;
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(75);
+						setState(105);
 						if (!(precpred(_ctx, 12))) throw new FailedPredicateException(this, "precpred(_ctx, 12)");
-						setState(76);
+						setState(106);
 						((MathOpContext)_localctx).op = _input.LT(1);
 						_la = _input.LA(1);
-						if ( !(_la==T__8 || _la==T__9) ) {
-							((MathOpContext)_localctx).op = _errHandler.recoverInline(this);
+						if ( !(_la==T__10 || _la==T__11) ) {
+							((MathOpContext)_localctx).op = (Token)_errHandler.recoverInline(this);
 						} else {
 							consume();
 						}
-						setState(77);
+						setState(107);
 						((MathOpContext)_localctx).right = expression(13);
 						}
 						break;
-
 					case 3:
 						{
 						_localctx = new BitShiftOpContext(new ExpressionContext(_parentctx, _parentState));
 						((BitShiftOpContext)_localctx).left = _prevctx;
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(78);
+						setState(108);
 						if (!(precpred(_ctx, 11))) throw new FailedPredicateException(this, "precpred(_ctx, 11)");
-						setState(79);
+						setState(109);
 						((BitShiftOpContext)_localctx).op = _input.LT(1);
 						_la = _input.LA(1);
-						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__15) | (1L << T__16) | (1L << T__17))) != 0)) ) {
-							((BitShiftOpContext)_localctx).op = _errHandler.recoverInline(this);
+						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__17) | (1L << T__18) | (1L << T__19))) != 0)) ) {
+							((BitShiftOpContext)_localctx).op = (Token)_errHandler.recoverInline(this);
 						} else {
 							consume();
 						}
-						setState(80);
+						setState(110);
 						((BitShiftOpContext)_localctx).right = expression(12);
 						}
 						break;
-
 					case 4:
 						{
 						_localctx = new ComparisonOpContext(new ExpressionContext(_parentctx, _parentState));
 						((ComparisonOpContext)_localctx).left = _prevctx;
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(81);
+						setState(111);
 						if (!(precpred(_ctx, 10))) throw new FailedPredicateException(this, "precpred(_ctx, 10)");
-						setState(82);
+						setState(112);
 						((ComparisonOpContext)_localctx).op = _input.LT(1);
 						_la = _input.LA(1);
-						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__18) | (1L << T__19) | (1L << T__20) | (1L << T__21))) != 0)) ) {
-							((ComparisonOpContext)_localctx).op = _errHandler.recoverInline(this);
+						if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__20) | (1L << T__21) | (1L << T__22) | (1L << T__23))) != 0)) ) {
+							((ComparisonOpContext)_localctx).op = (Token)_errHandler.recoverInline(this);
 						} else {
 							consume();
 						}
-						setState(83);
+						setState(113);
 						((ComparisonOpContext)_localctx).right = expression(11);
 						}
 						break;
-
 					case 5:
 						{
 						_localctx = new ComparisonOpContext(new ExpressionContext(_parentctx, _parentState));
 						((ComparisonOpContext)_localctx).left = _prevctx;
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(84);
+						setState(114);
 						if (!(precpred(_ctx, 8))) throw new FailedPredicateException(this, "precpred(_ctx, 8)");
-						setState(85);
+						setState(115);
 						((ComparisonOpContext)_localctx).op = _input.LT(1);
 						_la = _input.LA(1);
-						if ( !(_la==T__23 || _la==T__24) ) {
-							((ComparisonOpContext)_localctx).op = _errHandler.recoverInline(this);
+						if ( !(_la==T__25 || _la==T__26) ) {
+							((ComparisonOpContext)_localctx).op = (Token)_errHandler.recoverInline(this);
 						} else {
 							consume();
 						}
-						setState(86);
+						setState(116);
 						((ComparisonOpContext)_localctx).right = expression(9);
 						}
 						break;
-
 					case 6:
 						{
 						_localctx = new BinaryOpContext(new ExpressionContext(_parentctx, _parentState));
 						((BinaryOpContext)_localctx).left = _prevctx;
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(87);
+						setState(117);
 						if (!(precpred(_ctx, 7))) throw new FailedPredicateException(this, "precpred(_ctx, 7)");
-						setState(88);
-						((BinaryOpContext)_localctx).op = match(T__25);
-						setState(89);
+						setState(118);
+						((BinaryOpContext)_localctx).op = match(T__27);
+						setState(119);
 						((BinaryOpContext)_localctx).right = expression(8);
 						}
 						break;
-
 					case 7:
 						{
 						_localctx = new BinaryOpContext(new ExpressionContext(_parentctx, _parentState));
 						((BinaryOpContext)_localctx).left = _prevctx;
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(90);
+						setState(120);
 						if (!(precpred(_ctx, 6))) throw new FailedPredicateException(this, "precpred(_ctx, 6)");
-						setState(91);
-						((BinaryOpContext)_localctx).op = match(T__26);
-						setState(92);
+						setState(121);
+						((BinaryOpContext)_localctx).op = match(T__28);
+						setState(122);
 						((BinaryOpContext)_localctx).right = expression(7);
 						}
 						break;
-
 					case 8:
 						{
 						_localctx = new BinaryOpContext(new ExpressionContext(_parentctx, _parentState));
 						((BinaryOpContext)_localctx).left = _prevctx;
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(93);
+						setState(123);
 						if (!(precpred(_ctx, 5))) throw new FailedPredicateException(this, "precpred(_ctx, 5)");
-						setState(94);
-						((BinaryOpContext)_localctx).op = match(T__27);
-						setState(95);
+						setState(124);
+						((BinaryOpContext)_localctx).op = match(T__29);
+						setState(125);
 						((BinaryOpContext)_localctx).right = expression(6);
 						}
 						break;
-
 					case 9:
 						{
 						_localctx = new AndOrOpContext(new ExpressionContext(_parentctx, _parentState));
 						((AndOrOpContext)_localctx).left = _prevctx;
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(96);
+						setState(126);
 						if (!(precpred(_ctx, 4))) throw new FailedPredicateException(this, "precpred(_ctx, 4)");
-						setState(97);
-						((AndOrOpContext)_localctx).op = match(T__28);
-						setState(98);
+						setState(127);
+						((AndOrOpContext)_localctx).op = match(T__30);
+						setState(128);
 						((AndOrOpContext)_localctx).right = expression(5);
 						}
 						break;
-
 					case 10:
 						{
 						_localctx = new AndOrOpContext(new ExpressionContext(_parentctx, _parentState));
 						((AndOrOpContext)_localctx).left = _prevctx;
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(99);
+						setState(129);
 						if (!(precpred(_ctx, 3))) throw new FailedPredicateException(this, "precpred(_ctx, 3)");
-						setState(100);
-						((AndOrOpContext)_localctx).op = match(T__29);
-						setState(101);
+						setState(130);
+						((AndOrOpContext)_localctx).op = match(T__31);
+						setState(131);
 						((AndOrOpContext)_localctx).right = expression(4);
 						}
 						break;
-
 					case 11:
 						{
 						_localctx = new TernaryOpContext(new ExpressionContext(_parentctx, _parentState));
 						((TernaryOpContext)_localctx).left = _prevctx;
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(102);
+						setState(132);
 						if (!(precpred(_ctx, 2))) throw new FailedPredicateException(this, "precpred(_ctx, 2)");
-						setState(103);
-						((TernaryOpContext)_localctx).op = match(T__30);
-						setState(104);
+						setState(133);
+						((TernaryOpContext)_localctx).op = match(T__32);
+						setState(134);
 						((TernaryOpContext)_localctx).iftrue = expression(0);
-						setState(105);
-						match(T__31);
-						setState(106);
+						setState(135);
+						match(T__33);
+						setState(136);
 						((TernaryOpContext)_localctx).iffalse = expression(2);
 						}
 						break;
-
 					case 12:
 						{
 						_localctx = new QuestionQuestionOpContext(new ExpressionContext(_parentctx, _parentState));
 						((QuestionQuestionOpContext)_localctx).left = _prevctx;
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(108);
+						setState(138);
 						if (!(precpred(_ctx, 1))) throw new FailedPredicateException(this, "precpred(_ctx, 1)");
-						setState(109);
-						((QuestionQuestionOpContext)_localctx).op = match(T__32);
-						setState(110);
+						setState(139);
+						((QuestionQuestionOpContext)_localctx).op = match(T__34);
+						setState(140);
 						((QuestionQuestionOpContext)_localctx).right = expression(2);
 						}
 						break;
-
 					case 13:
 						{
 						_localctx = new DotOpContext(new ExpressionContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(111);
-						if (!(precpred(_ctx, 19))) throw new FailedPredicateException(this, "precpred(_ctx, 19)");
-						setState(112);
-						match(T__5);
-						setState(113);
+						setState(141);
+						if (!(precpred(_ctx, 20))) throw new FailedPredicateException(this, "precpred(_ctx, 20)");
+						setState(142);
+						match(T__6);
+						setState(143);
 						match(Identifier);
 						}
 						break;
-
 					case 14:
 						{
+						_localctx = new FunctionRefContext(new ExpressionContext(_parentctx, _parentState));
+						pushNewRecursionContext(_localctx, _startState, RULE_expression);
+						setState(144);
+						if (!(precpred(_ctx, 19))) throw new FailedPredicateException(this, "precpred(_ctx, 19)");
+						setState(145);
+						match(T__7);
+						setState(146);
+						match(Identifier);
+						}
+						break;
+					case 15:
+						{
 						_localctx = new BracketOpContext(new ExpressionContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(114);
+						setState(147);
 						if (!(precpred(_ctx, 18))) throw new FailedPredicateException(this, "precpred(_ctx, 18)");
-						setState(115);
-						match(T__6);
-						setState(116);
+						setState(148);
+						match(T__8);
+						setState(149);
 						expression(0);
-						setState(117);
-						match(T__7);
+						setState(150);
+						match(T__9);
 						}
 						break;
-
-					case 15:
+					case 16:
 						{
 						_localctx = new MethodInvocationContext(new ExpressionContext(_parentctx, _parentState));
 						((MethodInvocationContext)_localctx).target = _prevctx;
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(119);
+						setState(152);
 						if (!(precpred(_ctx, 17))) throw new FailedPredicateException(this, "precpred(_ctx, 17)");
-						setState(120);
-						match(T__5);
-						setState(121);
+						setState(153);
+						match(T__6);
+						setState(154);
 						((MethodInvocationContext)_localctx).methodName = match(Identifier);
-						setState(122);
-						match(T__3);
-						setState(124);
+						setState(155);
+						match(T__4);
+						setState(157);
 						_la = _input.LA(1);
-						if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__3) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << IntegerLiteral) | (1L << FloatingPointLiteral) | (1L << BooleanLiteral) | (1L << CharacterLiteral) | (1L << SingleQuoteString) | (1L << DoubleQuoteString) | (1L << NullLiteral) | (1L << Identifier) | (1L << ResourceReference))) != 0)) {
+						if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << VoidLiteral) | (1L << IntegerLiteral) | (1L << FloatingPointLiteral) | (1L << BooleanLiteral) | (1L << CharacterLiteral) | (1L << SingleQuoteString) | (1L << DoubleQuoteString) | (1L << NullLiteral) | (1L << Identifier) | (1L << ResourceReference))) != 0)) {
 							{
-							setState(123);
+							setState(156);
 							((MethodInvocationContext)_localctx).args = expressionList();
 							}
 						}
 
-						setState(126);
-						match(T__4);
+						setState(159);
+						match(T__5);
 						}
 						break;
-
-					case 16:
+					case 17:
 						{
 						_localctx = new InstanceOfOpContext(new ExpressionContext(_parentctx, _parentState));
 						pushNewRecursionContext(_localctx, _startState, RULE_expression);
-						setState(127);
+						setState(160);
 						if (!(precpred(_ctx, 9))) throw new FailedPredicateException(this, "precpred(_ctx, 9)");
-						setState(128);
-						match(T__22);
-						setState(129);
+						setState(161);
+						match(T__24);
+						setState(162);
 						type();
 						}
 						break;
 					}
 					} 
 				}
-				setState(134);
+				setState(167);
 				_errHandler.sync(this);
-				_alt = getInterpreter().adaptivePredict(_input,5,_ctx);
+				_alt = getInterpreter().adaptivePredict(_input,9,_ctx);
 			}
 			}
 		}
@@ -1108,51 +1392,24 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitClassExtraction(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitClassExtraction(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitClassExtraction(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ClassExtractionContext classExtraction() throws RecognitionException {
 		ClassExtractionContext _localctx = new ClassExtractionContext(_ctx, getState());
-		enterRule(_localctx, 8, RULE_classExtraction);
+		enterRule(_localctx, 14, RULE_classExtraction);
 		try {
-			setState(142);
-			switch (_input.LA(1)) {
-			case T__35:
-			case T__36:
-			case T__37:
-			case T__38:
-			case T__39:
-			case T__40:
-			case T__41:
-			case T__42:
-			case Identifier:
-				enterOuterAlt(_localctx, 1);
-				{
-				setState(135);
-				type();
-				setState(136);
-				match(T__5);
-				setState(137);
-				match(T__33);
-				}
-				break;
-			case T__34:
-				enterOuterAlt(_localctx, 2);
-				{
-				setState(139);
-				match(T__34);
-				setState(140);
-				match(T__5);
-				setState(141);
-				match(T__33);
-				}
-				break;
-			default:
-				throw new NoViableAltException(this);
+			enterOuterAlt(_localctx, 1);
+			{
+			setState(168);
+			type();
+			setState(169);
+			match(T__6);
+			setState(170);
+			match(T__35);
 			}
 		}
 		catch (RecognitionException re) {
@@ -1167,7 +1424,7 @@
 	}
 
 	public static class ExpressionListContext extends ParserRuleContext {
-		public List<? extends ExpressionContext> expression() {
+		public List<ExpressionContext> expression() {
 			return getRuleContexts(ExpressionContext.class);
 		}
 		public ExpressionContext expression(int i) {
@@ -1186,35 +1443,34 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitExpressionList(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitExpressionList(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitExpressionList(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ExpressionListContext expressionList() throws RecognitionException {
 		ExpressionListContext _localctx = new ExpressionListContext(_ctx, getState());
-		enterRule(_localctx, 10, RULE_expressionList);
+		enterRule(_localctx, 16, RULE_expressionList);
 		int _la;
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(144);
+			setState(172);
 			expression(0);
-			setState(149);
+			setState(177);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__0) {
 				{
 				{
-				setState(145);
+				setState(173);
 				match(T__0);
-				setState(146);
+				setState(174);
 				expression(0);
 				}
 				}
-				setState(151);
+				setState(179);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
@@ -1251,18 +1507,17 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitLiteral(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitLiteral(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitLiteral(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final LiteralContext literal() throws RecognitionException {
 		LiteralContext _localctx = new LiteralContext(_ctx, getState());
-		enterRule(_localctx, 12, RULE_literal);
+		enterRule(_localctx, 18, RULE_literal);
 		try {
-			setState(154);
+			setState(182);
 			switch (_input.LA(1)) {
 			case IntegerLiteral:
 			case FloatingPointLiteral:
@@ -1271,7 +1526,7 @@
 			case NullLiteral:
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(152);
+				setState(180);
 				javaLiteral();
 				}
 				break;
@@ -1279,7 +1534,7 @@
 			case DoubleQuoteString:
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(153);
+				setState(181);
 				stringLiteral();
 				}
 				break;
@@ -1313,20 +1568,19 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitIdentifier(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitIdentifier(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitIdentifier(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final IdentifierContext identifier() throws RecognitionException {
 		IdentifierContext _localctx = new IdentifierContext(_ctx, getState());
-		enterRule(_localctx, 14, RULE_identifier);
+		enterRule(_localctx, 20, RULE_identifier);
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(156);
+			setState(184);
 			match(Identifier);
 			}
 		}
@@ -1360,21 +1614,20 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitJavaLiteral(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitJavaLiteral(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitJavaLiteral(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final JavaLiteralContext javaLiteral() throws RecognitionException {
 		JavaLiteralContext _localctx = new JavaLiteralContext(_ctx, getState());
-		enterRule(_localctx, 16, RULE_javaLiteral);
+		enterRule(_localctx, 22, RULE_javaLiteral);
 		int _la;
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(158);
+			setState(186);
 			_la = _input.LA(1);
 			if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << IntegerLiteral) | (1L << FloatingPointLiteral) | (1L << BooleanLiteral) | (1L << CharacterLiteral) | (1L << NullLiteral))) != 0)) ) {
 			_errHandler.recoverInline(this);
@@ -1410,21 +1663,20 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitStringLiteral(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitStringLiteral(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitStringLiteral(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final StringLiteralContext stringLiteral() throws RecognitionException {
 		StringLiteralContext _localctx = new StringLiteralContext(_ctx, getState());
-		enterRule(_localctx, 18, RULE_stringLiteral);
+		enterRule(_localctx, 24, RULE_stringLiteral);
 		int _la;
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(160);
+			setState(188);
 			_la = _input.LA(1);
 			if ( !(_la==SingleQuoteString || _la==DoubleQuoteString) ) {
 			_errHandler.recoverInline(this);
@@ -1464,22 +1716,21 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitExplicitGenericInvocation(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitExplicitGenericInvocation(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitExplicitGenericInvocation(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ExplicitGenericInvocationContext explicitGenericInvocation() throws RecognitionException {
 		ExplicitGenericInvocationContext _localctx = new ExplicitGenericInvocationContext(_ctx, getState());
-		enterRule(_localctx, 20, RULE_explicitGenericInvocation);
+		enterRule(_localctx, 26, RULE_explicitGenericInvocation);
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(162);
+			setState(190);
 			typeArguments();
-			setState(163);
+			setState(191);
 			explicitGenericInvocationSuffix();
 			}
 		}
@@ -1495,7 +1746,7 @@
 	}
 
 	public static class TypeArgumentsContext extends ParserRuleContext {
-		public List<? extends TypeContext> type() {
+		public List<TypeContext> type() {
 			return getRuleContexts(TypeContext.class);
 		}
 		public TypeContext type(int i) {
@@ -1514,42 +1765,41 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitTypeArguments(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitTypeArguments(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitTypeArguments(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final TypeArgumentsContext typeArguments() throws RecognitionException {
 		TypeArgumentsContext _localctx = new TypeArgumentsContext(_ctx, getState());
-		enterRule(_localctx, 22, RULE_typeArguments);
+		enterRule(_localctx, 28, RULE_typeArguments);
 		int _la;
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(165);
-			match(T__21);
-			setState(166);
+			setState(193);
+			match(T__23);
+			setState(194);
 			type();
-			setState(171);
+			setState(199);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==T__0) {
 				{
 				{
-				setState(167);
+				setState(195);
 				match(T__0);
-				setState(168);
+				setState(196);
 				type();
 				}
 				}
-				setState(173);
+				setState(201);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
-			setState(174);
-			match(T__20);
+			setState(202);
+			match(T__22);
 			}
 		}
 		catch (RecognitionException re) {
@@ -1583,46 +1833,44 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitType(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitType(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitType(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final TypeContext type() throws RecognitionException {
 		TypeContext _localctx = new TypeContext(_ctx, getState());
-		enterRule(_localctx, 24, RULE_type);
+		enterRule(_localctx, 30, RULE_type);
 		try {
 			int _alt;
-			setState(192);
+			setState(220);
 			switch (_input.LA(1)) {
 			case Identifier:
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(176);
+				setState(204);
 				classOrInterfaceType();
-				setState(181);
+				setState(209);
 				_errHandler.sync(this);
-				_alt = getInterpreter().adaptivePredict(_input,10,_ctx);
+				_alt = getInterpreter().adaptivePredict(_input,13,_ctx);
 				while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
 					if ( _alt==1 ) {
 						{
 						{
-						setState(177);
-						match(T__6);
-						setState(178);
-						match(T__7);
+						setState(205);
+						match(T__8);
+						setState(206);
+						match(T__9);
 						}
 						} 
 					}
-					setState(183);
+					setState(211);
 					_errHandler.sync(this);
-					_alt = getInterpreter().adaptivePredict(_input,10,_ctx);
+					_alt = getInterpreter().adaptivePredict(_input,13,_ctx);
 				}
 				}
 				break;
-			case T__35:
 			case T__36:
 			case T__37:
 			case T__38:
@@ -1630,27 +1878,28 @@
 			case T__40:
 			case T__41:
 			case T__42:
+			case T__43:
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(184);
+				setState(212);
 				primitiveType();
-				setState(189);
+				setState(217);
 				_errHandler.sync(this);
-				_alt = getInterpreter().adaptivePredict(_input,11,_ctx);
+				_alt = getInterpreter().adaptivePredict(_input,14,_ctx);
 				while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
 					if ( _alt==1 ) {
 						{
 						{
-						setState(185);
-						match(T__6);
-						setState(186);
-						match(T__7);
+						setState(213);
+						match(T__8);
+						setState(214);
+						match(T__9);
 						}
 						} 
 					}
-					setState(191);
+					setState(219);
 					_errHandler.sync(this);
-					_alt = getInterpreter().adaptivePredict(_input,11,_ctx);
+					_alt = getInterpreter().adaptivePredict(_input,14,_ctx);
 				}
 				}
 				break;
@@ -1687,22 +1936,21 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitExplicitGenericInvocationSuffix(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitExplicitGenericInvocationSuffix(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitExplicitGenericInvocationSuffix(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ExplicitGenericInvocationSuffixContext explicitGenericInvocationSuffix() throws RecognitionException {
 		ExplicitGenericInvocationSuffixContext _localctx = new ExplicitGenericInvocationSuffixContext(_ctx, getState());
-		enterRule(_localctx, 26, RULE_explicitGenericInvocationSuffix);
+		enterRule(_localctx, 32, RULE_explicitGenericInvocationSuffix);
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(194);
+			setState(222);
 			match(Identifier);
-			setState(195);
+			setState(223);
 			arguments();
 			}
 		}
@@ -1734,33 +1982,32 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitArguments(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitArguments(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitArguments(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ArgumentsContext arguments() throws RecognitionException {
 		ArgumentsContext _localctx = new ArgumentsContext(_ctx, getState());
-		enterRule(_localctx, 28, RULE_arguments);
+		enterRule(_localctx, 34, RULE_arguments);
 		int _la;
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(197);
-			match(T__3);
-			setState(199);
+			setState(225);
+			match(T__4);
+			setState(227);
 			_la = _input.LA(1);
-			if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__3) | (1L << T__8) | (1L << T__9) | (1L << T__10) | (1L << T__11) | (1L << T__34) | (1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << IntegerLiteral) | (1L << FloatingPointLiteral) | (1L << BooleanLiteral) | (1L << CharacterLiteral) | (1L << SingleQuoteString) | (1L << DoubleQuoteString) | (1L << NullLiteral) | (1L << Identifier) | (1L << ResourceReference))) != 0)) {
+			if ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__4) | (1L << T__10) | (1L << T__11) | (1L << T__12) | (1L << T__13) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43) | (1L << VoidLiteral) | (1L << IntegerLiteral) | (1L << FloatingPointLiteral) | (1L << BooleanLiteral) | (1L << CharacterLiteral) | (1L << SingleQuoteString) | (1L << DoubleQuoteString) | (1L << NullLiteral) | (1L << Identifier) | (1L << ResourceReference))) != 0)) {
 				{
-				setState(198);
+				setState(226);
 				expressionList();
 				}
 			}
 
-			setState(201);
-			match(T__4);
+			setState(229);
+			match(T__5);
 			}
 		}
 		catch (RecognitionException re) {
@@ -1778,13 +2025,13 @@
 		public IdentifierContext identifier() {
 			return getRuleContext(IdentifierContext.class,0);
 		}
-		public List<? extends TypeArgumentsContext> typeArguments() {
+		public List<TypeArgumentsContext> typeArguments() {
 			return getRuleContexts(TypeArgumentsContext.class);
 		}
 		public TypeArgumentsContext typeArguments(int i) {
 			return getRuleContext(TypeArgumentsContext.class,i);
 		}
-		public List<? extends TerminalNode> Identifier() { return getTokens(BindingExpressionParser.Identifier); }
+		public List<TerminalNode> Identifier() { return getTokens(BindingExpressionParser.Identifier); }
 		public TerminalNode Identifier(int i) {
 			return getToken(BindingExpressionParser.Identifier, i);
 		}
@@ -1801,47 +2048,48 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitClassOrInterfaceType(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitClassOrInterfaceType(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitClassOrInterfaceType(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ClassOrInterfaceTypeContext classOrInterfaceType() throws RecognitionException {
 		ClassOrInterfaceTypeContext _localctx = new ClassOrInterfaceTypeContext(_ctx, getState());
-		enterRule(_localctx, 30, RULE_classOrInterfaceType);
+		enterRule(_localctx, 36, RULE_classOrInterfaceType);
 		try {
 			int _alt;
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(203);
+			setState(231);
 			identifier();
-			setState(205);
-			switch ( getInterpreter().adaptivePredict(_input,14,_ctx) ) {
+			setState(233);
+			_errHandler.sync(this);
+			switch ( getInterpreter().adaptivePredict(_input,17,_ctx) ) {
 			case 1:
 				{
-				setState(204);
+				setState(232);
 				typeArguments();
 				}
 				break;
 			}
-			setState(214);
+			setState(242);
 			_errHandler.sync(this);
-			_alt = getInterpreter().adaptivePredict(_input,16,_ctx);
+			_alt = getInterpreter().adaptivePredict(_input,19,_ctx);
 			while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) {
 				if ( _alt==1 ) {
 					{
 					{
-					setState(207);
-					match(T__5);
-					setState(208);
+					setState(235);
+					match(T__6);
+					setState(236);
 					match(Identifier);
-					setState(210);
-					switch ( getInterpreter().adaptivePredict(_input,15,_ctx) ) {
+					setState(238);
+					_errHandler.sync(this);
+					switch ( getInterpreter().adaptivePredict(_input,18,_ctx) ) {
 					case 1:
 						{
-						setState(209);
+						setState(237);
 						typeArguments();
 						}
 						break;
@@ -1849,9 +2097,9 @@
 					}
 					} 
 				}
-				setState(216);
+				setState(244);
 				_errHandler.sync(this);
-				_alt = getInterpreter().adaptivePredict(_input,16,_ctx);
+				_alt = getInterpreter().adaptivePredict(_input,19,_ctx);
 			}
 			}
 		}
@@ -1880,23 +2128,22 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitPrimitiveType(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitPrimitiveType(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitPrimitiveType(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final PrimitiveTypeContext primitiveType() throws RecognitionException {
 		PrimitiveTypeContext _localctx = new PrimitiveTypeContext(_ctx, getState());
-		enterRule(_localctx, 32, RULE_primitiveType);
+		enterRule(_localctx, 38, RULE_primitiveType);
 		int _la;
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(217);
+			setState(245);
 			_la = _input.LA(1);
-			if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__35) | (1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42))) != 0)) ) {
+			if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << T__36) | (1L << T__37) | (1L << T__38) | (1L << T__39) | (1L << T__40) | (1L << T__41) | (1L << T__42) | (1L << T__43))) != 0)) ) {
 			_errHandler.recoverInline(this);
 			} else {
 				consume();
@@ -1932,26 +2179,26 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitResources(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitResources(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitResources(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ResourcesContext resources() throws RecognitionException {
 		ResourcesContext _localctx = new ResourcesContext(_ctx, getState());
-		enterRule(_localctx, 34, RULE_resources);
+		enterRule(_localctx, 40, RULE_resources);
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(219);
+			setState(247);
 			match(ResourceReference);
-			setState(221);
-			switch ( getInterpreter().adaptivePredict(_input,17,_ctx) ) {
+			setState(249);
+			_errHandler.sync(this);
+			switch ( getInterpreter().adaptivePredict(_input,20,_ctx) ) {
 			case 1:
 				{
-				setState(220);
+				setState(248);
 				resourceParameters();
 				}
 				break;
@@ -1986,25 +2233,24 @@
 			if ( listener instanceof BindingExpressionListener ) ((BindingExpressionListener)listener).exitResourceParameters(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof BindingExpressionVisitor<?> ) return ((BindingExpressionVisitor<? extends Result>)visitor).visitResourceParameters(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof BindingExpressionVisitor ) return ((BindingExpressionVisitor<? extends T>)visitor).visitResourceParameters(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ResourceParametersContext resourceParameters() throws RecognitionException {
 		ResourceParametersContext _localctx = new ResourceParametersContext(_ctx, getState());
-		enterRule(_localctx, 36, RULE_resourceParameters);
+		enterRule(_localctx, 42, RULE_resourceParameters);
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(223);
-			match(T__3);
-			setState(224);
-			expressionList();
-			setState(225);
+			setState(251);
 			match(T__4);
+			setState(252);
+			expressionList();
+			setState(253);
+			match(T__5);
 			}
 		}
 		catch (RecognitionException re) {
@@ -2020,7 +2266,7 @@
 
 	public boolean sempred(RuleContext _localctx, int ruleIndex, int predIndex) {
 		switch (ruleIndex) {
-		case 3:
+		case 6:
 			return expression_sempred((ExpressionContext)_localctx, predIndex);
 		}
 		return true;
@@ -2029,135 +2275,136 @@
 		switch (predIndex) {
 		case 0:
 			return precpred(_ctx, 13);
-
 		case 1:
 			return precpred(_ctx, 12);
-
 		case 2:
 			return precpred(_ctx, 11);
-
 		case 3:
 			return precpred(_ctx, 10);
-
 		case 4:
 			return precpred(_ctx, 8);
-
 		case 5:
 			return precpred(_ctx, 7);
-
 		case 6:
 			return precpred(_ctx, 6);
-
 		case 7:
 			return precpred(_ctx, 5);
-
 		case 8:
 			return precpred(_ctx, 4);
-
 		case 9:
 			return precpred(_ctx, 3);
-
 		case 10:
 			return precpred(_ctx, 2);
-
 		case 11:
 			return precpred(_ctx, 1);
-
 		case 12:
-			return precpred(_ctx, 19);
-
+			return precpred(_ctx, 20);
 		case 13:
-			return precpred(_ctx, 18);
-
+			return precpred(_ctx, 19);
 		case 14:
-			return precpred(_ctx, 17);
-
+			return precpred(_ctx, 18);
 		case 15:
+			return precpred(_ctx, 17);
+		case 16:
 			return precpred(_ctx, 9);
 		}
 		return true;
 	}
 
 	public static final String _serializedATN =
-		"\3\uaf6f\u8320\u479d\ub75c\u4880\u1605\u191c\uab37\3:\u00e6\4\2\t\2\4"+
+		"\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3<\u0102\4\2\t\2\4"+
 		"\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4\n\t\n\4\13\t"+
 		"\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t\21\4\22\t\22"+
-		"\4\23\t\23\4\24\t\24\3\2\3\2\5\2+\n\2\3\3\3\3\3\3\3\3\3\3\3\4\3\4\3\4"+
-		"\5\4\65\n\4\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3"+
-		"\5\3\5\3\5\3\5\5\5I\n\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3"+
-		"\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5"+
-		"\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3"+
-		"\5\3\5\3\5\3\5\3\5\3\5\5\5\177\n\5\3\5\3\5\3\5\3\5\7\5\u0085\n\5\f\5\16"+
-		"\5\u0088\13\5\3\6\3\6\3\6\3\6\3\6\3\6\3\6\5\6\u0091\n\6\3\7\3\7\3\7\7"+
-		"\7\u0096\n\7\f\7\16\7\u0099\13\7\3\b\3\b\5\b\u009d\n\b\3\t\3\t\3\n\3\n"+
-		"\3\13\3\13\3\f\3\f\3\f\3\r\3\r\3\r\3\r\7\r\u00ac\n\r\f\r\16\r\u00af\13"+
-		"\r\3\r\3\r\3\16\3\16\3\16\7\16\u00b6\n\16\f\16\16\16\u00b9\13\16\3\16"+
-		"\3\16\3\16\7\16\u00be\n\16\f\16\16\16\u00c1\13\16\5\16\u00c3\n\16\3\17"+
-		"\3\17\3\17\3\20\3\20\5\20\u00ca\n\20\3\20\3\20\3\21\3\21\5\21\u00d0\n"+
-		"\21\3\21\3\21\3\21\5\21\u00d5\n\21\7\21\u00d7\n\21\f\21\16\21\u00da\13"+
-		"\21\3\22\3\22\3\23\3\23\5\23\u00e0\n\23\3\24\3\24\3\24\3\24\3\24\2\2\3"+
-		"\b\25\2\2\4\2\6\2\b\2\n\2\f\2\16\2\20\2\22\2\24\2\26\2\30\2\32\2\34\2"+
-		"\36\2 \2\"\2$\2&\2\2\13\3\2\13\f\3\2\r\16\3\2\17\21\3\2\22\24\3\2\25\30"+
-		"\3\2\32\33\4\2/\62\65\65\3\2\63\64\3\2&-\u00f9\2(\3\2\2\2\4,\3\2\2\2\6"+
-		"\64\3\2\2\2\bH\3\2\2\2\n\u0090\3\2\2\2\f\u0092\3\2\2\2\16\u009c\3\2\2"+
-		"\2\20\u009e\3\2\2\2\22\u00a0\3\2\2\2\24\u00a2\3\2\2\2\26\u00a4\3\2\2\2"+
-		"\30\u00a7\3\2\2\2\32\u00c2\3\2\2\2\34\u00c4\3\2\2\2\36\u00c7\3\2\2\2 "+
-		"\u00cd\3\2\2\2\"\u00db\3\2\2\2$\u00dd\3\2\2\2&\u00e1\3\2\2\2(*\5\b\5\2"+
-		")+\5\4\3\2*)\3\2\2\2*+\3\2\2\2+\3\3\2\2\2,-\7\3\2\2-.\7\4\2\2./\7\5\2"+
-		"\2/\60\5\6\4\2\60\5\3\2\2\2\61\65\5\16\b\2\62\65\78\2\2\63\65\5\20\t\2"+
-		"\64\61\3\2\2\2\64\62\3\2\2\2\64\63\3\2\2\2\65\7\3\2\2\2\66\67\b\5\1\2"+
-		"\678\7\6\2\289\5\32\16\29:\7\7\2\2:;\5\b\5\22;I\3\2\2\2<=\t\2\2\2=I\5"+
-		"\b\5\21>?\t\3\2\2?I\5\b\5\20@A\7\6\2\2AB\5\b\5\2BC\7\7\2\2CI\3\2\2\2D"+
-		"I\5\16\b\2EI\5\20\t\2FI\5\n\6\2GI\5$\23\2H\66\3\2\2\2H<\3\2\2\2H>\3\2"+
-		"\2\2H@\3\2\2\2HD\3\2\2\2HE\3\2\2\2HF\3\2\2\2HG\3\2\2\2I\u0086\3\2\2\2"+
-		"JK\f\17\2\2KL\t\4\2\2L\u0085\5\b\5\20MN\f\16\2\2NO\t\2\2\2O\u0085\5\b"+
-		"\5\17PQ\f\r\2\2QR\t\5\2\2R\u0085\5\b\5\16ST\f\f\2\2TU\t\6\2\2U\u0085\5"+
-		"\b\5\rVW\f\n\2\2WX\t\7\2\2X\u0085\5\b\5\13YZ\f\t\2\2Z[\7\34\2\2[\u0085"+
-		"\5\b\5\n\\]\f\b\2\2]^\7\35\2\2^\u0085\5\b\5\t_`\f\7\2\2`a\7\36\2\2a\u0085"+
-		"\5\b\5\bbc\f\6\2\2cd\7\37\2\2d\u0085\5\b\5\7ef\f\5\2\2fg\7 \2\2g\u0085"+
-		"\5\b\5\6hi\f\4\2\2ij\7!\2\2jk\5\b\5\2kl\7\"\2\2lm\5\b\5\4m\u0085\3\2\2"+
-		"\2no\f\3\2\2op\7#\2\2p\u0085\5\b\5\4qr\f\25\2\2rs\7\b\2\2s\u0085\7\66"+
-		"\2\2tu\f\24\2\2uv\7\t\2\2vw\5\b\5\2wx\7\n\2\2x\u0085\3\2\2\2yz\f\23\2"+
-		"\2z{\7\b\2\2{|\7\66\2\2|~\7\6\2\2}\177\5\f\7\2~}\3\2\2\2~\177\3\2\2\2"+
-		"\177\u0080\3\2\2\2\u0080\u0085\7\7\2\2\u0081\u0082\f\13\2\2\u0082\u0083"+
-		"\7\31\2\2\u0083\u0085\5\32\16\2\u0084J\3\2\2\2\u0084M\3\2\2\2\u0084P\3"+
-		"\2\2\2\u0084S\3\2\2\2\u0084V\3\2\2\2\u0084Y\3\2\2\2\u0084\\\3\2\2\2\u0084"+
-		"_\3\2\2\2\u0084b\3\2\2\2\u0084e\3\2\2\2\u0084h\3\2\2\2\u0084n\3\2\2\2"+
-		"\u0084q\3\2\2\2\u0084t\3\2\2\2\u0084y\3\2\2\2\u0084\u0081\3\2\2\2\u0085"+
-		"\u0088\3\2\2\2\u0086\u0084\3\2\2\2\u0086\u0087\3\2\2\2\u0087\t\3\2\2\2"+
-		"\u0088\u0086\3\2\2\2\u0089\u008a\5\32\16\2\u008a\u008b\7\b\2\2\u008b\u008c"+
-		"\7$\2\2\u008c\u0091\3\2\2\2\u008d\u008e\7%\2\2\u008e\u008f\7\b\2\2\u008f"+
-		"\u0091\7$\2\2\u0090\u0089\3\2\2\2\u0090\u008d\3\2\2\2\u0091\13\3\2\2\2"+
-		"\u0092\u0097\5\b\5\2\u0093\u0094\7\3\2\2\u0094\u0096\5\b\5\2\u0095\u0093"+
-		"\3\2\2\2\u0096\u0099\3\2\2\2\u0097\u0095\3\2\2\2\u0097\u0098\3\2\2\2\u0098"+
-		"\r\3\2\2\2\u0099\u0097\3\2\2\2\u009a\u009d\5\22\n\2\u009b\u009d\5\24\13"+
-		"\2\u009c\u009a\3\2\2\2\u009c\u009b\3\2\2\2\u009d\17\3\2\2\2\u009e\u009f"+
-		"\7\66\2\2\u009f\21\3\2\2\2\u00a0\u00a1\t\b\2\2\u00a1\23\3\2\2\2\u00a2"+
-		"\u00a3\t\t\2\2\u00a3\25\3\2\2\2\u00a4\u00a5\5\30\r\2\u00a5\u00a6\5\34"+
-		"\17\2\u00a6\27\3\2\2\2\u00a7\u00a8\7\30\2\2\u00a8\u00ad\5\32\16\2\u00a9"+
-		"\u00aa\7\3\2\2\u00aa\u00ac\5\32\16\2\u00ab\u00a9\3\2\2\2\u00ac\u00af\3"+
-		"\2\2\2\u00ad\u00ab\3\2\2\2\u00ad\u00ae\3\2\2\2\u00ae\u00b0\3\2\2\2\u00af"+
-		"\u00ad\3\2\2\2\u00b0\u00b1\7\27\2\2\u00b1\31\3\2\2\2\u00b2\u00b7\5 \21"+
-		"\2\u00b3\u00b4\7\t\2\2\u00b4\u00b6\7\n\2\2\u00b5\u00b3\3\2\2\2\u00b6\u00b9"+
-		"\3\2\2\2\u00b7\u00b5\3\2\2\2\u00b7\u00b8\3\2\2\2\u00b8\u00c3\3\2\2\2\u00b9"+
-		"\u00b7\3\2\2\2\u00ba\u00bf\5\"\22\2\u00bb\u00bc\7\t\2\2\u00bc\u00be\7"+
-		"\n\2\2\u00bd\u00bb\3\2\2\2\u00be\u00c1\3\2\2\2\u00bf\u00bd\3\2\2\2\u00bf"+
-		"\u00c0\3\2\2\2\u00c0\u00c3\3\2\2\2\u00c1\u00bf\3\2\2\2\u00c2\u00b2\3\2"+
-		"\2\2\u00c2\u00ba\3\2\2\2\u00c3\33\3\2\2\2\u00c4\u00c5\7\66\2\2\u00c5\u00c6"+
-		"\5\36\20\2\u00c6\35\3\2\2\2\u00c7\u00c9\7\6\2\2\u00c8\u00ca\5\f\7\2\u00c9"+
-		"\u00c8\3\2\2\2\u00c9\u00ca\3\2\2\2\u00ca\u00cb\3\2\2\2\u00cb\u00cc\7\7"+
-		"\2\2\u00cc\37\3\2\2\2\u00cd\u00cf\5\20\t\2\u00ce\u00d0\5\30\r\2\u00cf"+
-		"\u00ce\3\2\2\2\u00cf\u00d0\3\2\2\2\u00d0\u00d8\3\2\2\2\u00d1\u00d2\7\b"+
-		"\2\2\u00d2\u00d4\7\66\2\2\u00d3\u00d5\5\30\r\2\u00d4\u00d3\3\2\2\2\u00d4"+
-		"\u00d5\3\2\2\2\u00d5\u00d7\3\2\2\2\u00d6\u00d1\3\2\2\2\u00d7\u00da\3\2"+
-		"\2\2\u00d8\u00d6\3\2\2\2\u00d8\u00d9\3\2\2\2\u00d9!\3\2\2\2\u00da\u00d8"+
-		"\3\2\2\2\u00db\u00dc\t\n\2\2\u00dc#\3\2\2\2\u00dd\u00df\78\2\2\u00de\u00e0"+
-		"\5&\24\2\u00df\u00de\3\2\2\2\u00df\u00e0\3\2\2\2\u00e0%\3\2\2\2\u00e1"+
-		"\u00e2\7\6\2\2\u00e2\u00e3\5\f\7\2\u00e3\u00e4\7\7\2\2\u00e4\'\3\2\2\2"+
-		"\24*\64H~\u0084\u0086\u0090\u0097\u009c\u00ad\u00b7\u00bf\u00c2\u00c9"+
-		"\u00cf\u00d4\u00d8\u00df";
+		"\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\3\2\3\2\5\2\61\n\2"+
+		"\3\2\5\2\64\n\2\3\3\3\3\3\3\3\3\3\3\3\4\3\4\3\4\5\4>\n\4\3\5\3\5\3\5\3"+
+		"\5\3\6\3\6\3\6\5\6G\n\6\3\6\5\6J\n\6\3\7\3\7\3\7\7\7O\n\7\f\7\16\7R\13"+
+		"\7\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b"+
+		"\3\b\3\b\5\bg\n\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b"+
+		"\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3"+
+		"\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b\3\b"+
+		"\3\b\3\b\3\b\3\b\3\b\3\b\3\b\5\b\u00a0\n\b\3\b\3\b\3\b\3\b\7\b\u00a6\n"+
+		"\b\f\b\16\b\u00a9\13\b\3\t\3\t\3\t\3\t\3\n\3\n\3\n\7\n\u00b2\n\n\f\n\16"+
+		"\n\u00b5\13\n\3\13\3\13\5\13\u00b9\n\13\3\f\3\f\3\r\3\r\3\16\3\16\3\17"+
+		"\3\17\3\17\3\20\3\20\3\20\3\20\7\20\u00c8\n\20\f\20\16\20\u00cb\13\20"+
+		"\3\20\3\20\3\21\3\21\3\21\7\21\u00d2\n\21\f\21\16\21\u00d5\13\21\3\21"+
+		"\3\21\3\21\7\21\u00da\n\21\f\21\16\21\u00dd\13\21\5\21\u00df\n\21\3\22"+
+		"\3\22\3\22\3\23\3\23\5\23\u00e6\n\23\3\23\3\23\3\24\3\24\5\24\u00ec\n"+
+		"\24\3\24\3\24\3\24\5\24\u00f1\n\24\7\24\u00f3\n\24\f\24\16\24\u00f6\13"+
+		"\24\3\25\3\25\3\26\3\26\5\26\u00fc\n\26\3\27\3\27\3\27\3\27\3\27\2\3\16"+
+		"\30\2\4\6\b\n\f\16\20\22\24\26\30\32\34\36 \"$&(*,\2\13\3\2\r\16\3\2\17"+
+		"\20\3\2\21\23\3\2\24\26\3\2\27\32\3\2\34\35\4\2\61\64\67\67\3\2\65\66"+
+		"\3\2\'.\u0117\2\63\3\2\2\2\4\65\3\2\2\2\6=\3\2\2\2\b?\3\2\2\2\nI\3\2\2"+
+		"\2\fK\3\2\2\2\16f\3\2\2\2\20\u00aa\3\2\2\2\22\u00ae\3\2\2\2\24\u00b8\3"+
+		"\2\2\2\26\u00ba\3\2\2\2\30\u00bc\3\2\2\2\32\u00be\3\2\2\2\34\u00c0\3\2"+
+		"\2\2\36\u00c3\3\2\2\2 \u00de\3\2\2\2\"\u00e0\3\2\2\2$\u00e3\3\2\2\2&\u00e9"+
+		"\3\2\2\2(\u00f7\3\2\2\2*\u00f9\3\2\2\2,\u00fd\3\2\2\2.\60\5\16\b\2/\61"+
+		"\5\4\3\2\60/\3\2\2\2\60\61\3\2\2\2\61\64\3\2\2\2\62\64\5\b\5\2\63.\3\2"+
+		"\2\2\63\62\3\2\2\2\64\3\3\2\2\2\65\66\7\3\2\2\66\67\7\4\2\2\678\7\5\2"+
+		"\289\5\6\4\29\5\3\2\2\2:>\5\24\13\2;>\7:\2\2<>\5\26\f\2=:\3\2\2\2=;\3"+
+		"\2\2\2=<\3\2\2\2>\7\3\2\2\2?@\5\n\6\2@A\7\6\2\2AB\5\16\b\2B\t\3\2\2\2"+
+		"CJ\78\2\2DF\7\7\2\2EG\5\f\7\2FE\3\2\2\2FG\3\2\2\2GH\3\2\2\2HJ\7\b\2\2"+
+		"IC\3\2\2\2ID\3\2\2\2J\13\3\2\2\2KP\78\2\2LM\7\3\2\2MO\78\2\2NL\3\2\2\2"+
+		"OR\3\2\2\2PN\3\2\2\2PQ\3\2\2\2Q\r\3\2\2\2RP\3\2\2\2ST\b\b\1\2TU\7\7\2"+
+		"\2UV\5\16\b\2VW\7\b\2\2Wg\3\2\2\2Xg\5\24\13\2Yg\7\60\2\2Zg\5\26\f\2[g"+
+		"\5\20\t\2\\g\5*\26\2]^\7\7\2\2^_\5 \21\2_`\7\b\2\2`a\5\16\b\22ag\3\2\2"+
+		"\2bc\t\2\2\2cg\5\16\b\21de\t\3\2\2eg\5\16\b\20fS\3\2\2\2fX\3\2\2\2fY\3"+
+		"\2\2\2fZ\3\2\2\2f[\3\2\2\2f\\\3\2\2\2f]\3\2\2\2fb\3\2\2\2fd\3\2\2\2g\u00a7"+
+		"\3\2\2\2hi\f\17\2\2ij\t\4\2\2j\u00a6\5\16\b\20kl\f\16\2\2lm\t\2\2\2m\u00a6"+
+		"\5\16\b\17no\f\r\2\2op\t\5\2\2p\u00a6\5\16\b\16qr\f\f\2\2rs\t\6\2\2s\u00a6"+
+		"\5\16\b\rtu\f\n\2\2uv\t\7\2\2v\u00a6\5\16\b\13wx\f\t\2\2xy\7\36\2\2y\u00a6"+
+		"\5\16\b\nz{\f\b\2\2{|\7\37\2\2|\u00a6\5\16\b\t}~\f\7\2\2~\177\7 \2\2\177"+
+		"\u00a6\5\16\b\b\u0080\u0081\f\6\2\2\u0081\u0082\7!\2\2\u0082\u00a6\5\16"+
+		"\b\7\u0083\u0084\f\5\2\2\u0084\u0085\7\"\2\2\u0085\u00a6\5\16\b\6\u0086"+
+		"\u0087\f\4\2\2\u0087\u0088\7#\2\2\u0088\u0089\5\16\b\2\u0089\u008a\7$"+
+		"\2\2\u008a\u008b\5\16\b\4\u008b\u00a6\3\2\2\2\u008c\u008d\f\3\2\2\u008d"+
+		"\u008e\7%\2\2\u008e\u00a6\5\16\b\4\u008f\u0090\f\26\2\2\u0090\u0091\7"+
+		"\t\2\2\u0091\u00a6\78\2\2\u0092\u0093\f\25\2\2\u0093\u0094\7\n\2\2\u0094"+
+		"\u00a6\78\2\2\u0095\u0096\f\24\2\2\u0096\u0097\7\13\2\2\u0097\u0098\5"+
+		"\16\b\2\u0098\u0099\7\f\2\2\u0099\u00a6\3\2\2\2\u009a\u009b\f\23\2\2\u009b"+
+		"\u009c\7\t\2\2\u009c\u009d\78\2\2\u009d\u009f\7\7\2\2\u009e\u00a0\5\22"+
+		"\n\2\u009f\u009e\3\2\2\2\u009f\u00a0\3\2\2\2\u00a0\u00a1\3\2\2\2\u00a1"+
+		"\u00a6\7\b\2\2\u00a2\u00a3\f\13\2\2\u00a3\u00a4\7\33\2\2\u00a4\u00a6\5"+
+		" \21\2\u00a5h\3\2\2\2\u00a5k\3\2\2\2\u00a5n\3\2\2\2\u00a5q\3\2\2\2\u00a5"+
+		"t\3\2\2\2\u00a5w\3\2\2\2\u00a5z\3\2\2\2\u00a5}\3\2\2\2\u00a5\u0080\3\2"+
+		"\2\2\u00a5\u0083\3\2\2\2\u00a5\u0086\3\2\2\2\u00a5\u008c\3\2\2\2\u00a5"+
+		"\u008f\3\2\2\2\u00a5\u0092\3\2\2\2\u00a5\u0095\3\2\2\2\u00a5\u009a\3\2"+
+		"\2\2\u00a5\u00a2\3\2\2\2\u00a6\u00a9\3\2\2\2\u00a7\u00a5\3\2\2\2\u00a7"+
+		"\u00a8\3\2\2\2\u00a8\17\3\2\2\2\u00a9\u00a7\3\2\2\2\u00aa\u00ab\5 \21"+
+		"\2\u00ab\u00ac\7\t\2\2\u00ac\u00ad\7&\2\2\u00ad\21\3\2\2\2\u00ae\u00b3"+
+		"\5\16\b\2\u00af\u00b0\7\3\2\2\u00b0\u00b2\5\16\b\2\u00b1\u00af\3\2\2\2"+
+		"\u00b2\u00b5\3\2\2\2\u00b3\u00b1\3\2\2\2\u00b3\u00b4\3\2\2\2\u00b4\23"+
+		"\3\2\2\2\u00b5\u00b3\3\2\2\2\u00b6\u00b9\5\30\r\2\u00b7\u00b9\5\32\16"+
+		"\2\u00b8\u00b6\3\2\2\2\u00b8\u00b7\3\2\2\2\u00b9\25\3\2\2\2\u00ba\u00bb"+
+		"\78\2\2\u00bb\27\3\2\2\2\u00bc\u00bd\t\b\2\2\u00bd\31\3\2\2\2\u00be\u00bf"+
+		"\t\t\2\2\u00bf\33\3\2\2\2\u00c0\u00c1\5\36\20\2\u00c1\u00c2\5\"\22\2\u00c2"+
+		"\35\3\2\2\2\u00c3\u00c4\7\32\2\2\u00c4\u00c9\5 \21\2\u00c5\u00c6\7\3\2"+
+		"\2\u00c6\u00c8\5 \21\2\u00c7\u00c5\3\2\2\2\u00c8\u00cb\3\2\2\2\u00c9\u00c7"+
+		"\3\2\2\2\u00c9\u00ca\3\2\2\2\u00ca\u00cc\3\2\2\2\u00cb\u00c9\3\2\2\2\u00cc"+
+		"\u00cd\7\31\2\2\u00cd\37\3\2\2\2\u00ce\u00d3\5&\24\2\u00cf\u00d0\7\13"+
+		"\2\2\u00d0\u00d2\7\f\2\2\u00d1\u00cf\3\2\2\2\u00d2\u00d5\3\2\2\2\u00d3"+
+		"\u00d1\3\2\2\2\u00d3\u00d4\3\2\2\2\u00d4\u00df\3\2\2\2\u00d5\u00d3\3\2"+
+		"\2\2\u00d6\u00db\5(\25\2\u00d7\u00d8\7\13\2\2\u00d8\u00da\7\f\2\2\u00d9"+
+		"\u00d7\3\2\2\2\u00da\u00dd\3\2\2\2\u00db\u00d9\3\2\2\2\u00db\u00dc\3\2"+
+		"\2\2\u00dc\u00df\3\2\2\2\u00dd\u00db\3\2\2\2\u00de\u00ce\3\2\2\2\u00de"+
+		"\u00d6\3\2\2\2\u00df!\3\2\2\2\u00e0\u00e1\78\2\2\u00e1\u00e2\5$\23\2\u00e2"+
+		"#\3\2\2\2\u00e3\u00e5\7\7\2\2\u00e4\u00e6\5\22\n\2\u00e5\u00e4\3\2\2\2"+
+		"\u00e5\u00e6\3\2\2\2\u00e6\u00e7\3\2\2\2\u00e7\u00e8\7\b\2\2\u00e8%\3"+
+		"\2\2\2\u00e9\u00eb\5\26\f\2\u00ea\u00ec\5\36\20\2\u00eb\u00ea\3\2\2\2"+
+		"\u00eb\u00ec\3\2\2\2\u00ec\u00f4\3\2\2\2\u00ed\u00ee\7\t\2\2\u00ee\u00f0"+
+		"\78\2\2\u00ef\u00f1\5\36\20\2\u00f0\u00ef\3\2\2\2\u00f0\u00f1\3\2\2\2"+
+		"\u00f1\u00f3\3\2\2\2\u00f2\u00ed\3\2\2\2\u00f3\u00f6\3\2\2\2\u00f4\u00f2"+
+		"\3\2\2\2\u00f4\u00f5\3\2\2\2\u00f5\'\3\2\2\2\u00f6\u00f4\3\2\2\2\u00f7"+
+		"\u00f8\t\n\2\2\u00f8)\3\2\2\2\u00f9\u00fb\7:\2\2\u00fa\u00fc\5,\27\2\u00fb"+
+		"\u00fa\3\2\2\2\u00fb\u00fc\3\2\2\2\u00fc+\3\2\2\2\u00fd\u00fe\7\7\2\2"+
+		"\u00fe\u00ff\5\22\n\2\u00ff\u0100\7\b\2\2\u0100-\3\2\2\2\27\60\63=FIP"+
+		"f\u009f\u00a5\u00a7\u00b3\u00b8\u00c9\u00d3\u00db\u00de\u00e5\u00eb\u00f0"+
+		"\u00f4\u00fb";
 	public static final ATN _ATN =
 		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
 	static {
+		_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
+		for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
+			_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
+		}
 	}
 }
\ No newline at end of file
diff --git a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionVisitor.java b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionVisitor.java
index dfcf31d..c744364 100644
--- a/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionVisitor.java
+++ b/compilerCommon/src/main/grammar-gen/android/databinding/parser/BindingExpressionVisitor.java
@@ -1,275 +1,274 @@
-// Generated from BindingExpression.g4 by ANTLR 4.5
+// Generated from BindingExpression.g4 by ANTLR 4.5.3
 package android.databinding.parser;
-import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.misc.NotNull;
 import org.antlr.v4.runtime.tree.ParseTreeVisitor;
 
 /**
  * This interface defines a complete generic visitor for a parse tree produced
  * by {@link BindingExpressionParser}.
  *
- * @param <Result> The return type of the visit operation. Use {@link Void} for
+ * @param <T> The return type of the visit operation. Use {@link Void} for
  * operations with no return type.
  */
-public interface BindingExpressionVisitor<Result> extends ParseTreeVisitor<Result> {
+public interface BindingExpressionVisitor<T> extends ParseTreeVisitor<T> {
 	/**
-	 * Visit a parse tree produced by the {@code BracketOp}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * Visit a parse tree produced by the {@code RootExpr}
+	 * labeled alternative in {@link BindingExpressionParser#bindingSyntax}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitBracketOp(@NotNull BindingExpressionParser.BracketOpContext ctx);
-
+	T visitRootExpr(BindingExpressionParser.RootExprContext ctx);
 	/**
-	 * Visit a parse tree produced by the {@code Resource}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * Visit a parse tree produced by the {@code RootLambda}
+	 * labeled alternative in {@link BindingExpressionParser#bindingSyntax}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitResource(@NotNull BindingExpressionParser.ResourceContext ctx);
-
+	T visitRootLambda(BindingExpressionParser.RootLambdaContext ctx);
+	/**
+	 * Visit a parse tree produced by {@link BindingExpressionParser#defaults}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitDefaults(BindingExpressionParser.DefaultsContext ctx);
+	/**
+	 * Visit a parse tree produced by {@link BindingExpressionParser#constantValue}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitConstantValue(BindingExpressionParser.ConstantValueContext ctx);
+	/**
+	 * Visit a parse tree produced by {@link BindingExpressionParser#lambdaExpression}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitLambdaExpression(BindingExpressionParser.LambdaExpressionContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code SingleLambdaParameter}
+	 * labeled alternative in {@link BindingExpressionParser#lambdaParameters}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitSingleLambdaParameter(BindingExpressionParser.SingleLambdaParameterContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code LambdaParameterList}
+	 * labeled alternative in {@link BindingExpressionParser#lambdaParameters}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitLambdaParameterList(BindingExpressionParser.LambdaParameterListContext ctx);
+	/**
+	 * Visit a parse tree produced by {@link BindingExpressionParser#inferredFormalParameterList}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitInferredFormalParameterList(BindingExpressionParser.InferredFormalParameterListContext ctx);
 	/**
 	 * Visit a parse tree produced by the {@code CastOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitCastOp(@NotNull BindingExpressionParser.CastOpContext ctx);
-
-	/**
-	 * Visit a parse tree produced by the {@code UnaryOp}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 * @return the visitor result
-	 */
-	Result visitUnaryOp(@NotNull BindingExpressionParser.UnaryOpContext ctx);
-
-	/**
-	 * Visit a parse tree produced by the {@code AndOrOp}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 * @return the visitor result
-	 */
-	Result visitAndOrOp(@NotNull BindingExpressionParser.AndOrOpContext ctx);
-
-	/**
-	 * Visit a parse tree produced by the {@code MethodInvocation}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 * @return the visitor result
-	 */
-	Result visitMethodInvocation(@NotNull BindingExpressionParser.MethodInvocationContext ctx);
-
-	/**
-	 * Visit a parse tree produced by the {@code Primary}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 * @return the visitor result
-	 */
-	Result visitPrimary(@NotNull BindingExpressionParser.PrimaryContext ctx);
-
-	/**
-	 * Visit a parse tree produced by the {@code Grouping}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 * @return the visitor result
-	 */
-	Result visitGrouping(@NotNull BindingExpressionParser.GroupingContext ctx);
-
-	/**
-	 * Visit a parse tree produced by the {@code TernaryOp}
-	 * labeled alternative in {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 * @return the visitor result
-	 */
-	Result visitTernaryOp(@NotNull BindingExpressionParser.TernaryOpContext ctx);
-
+	T visitCastOp(BindingExpressionParser.CastOpContext ctx);
 	/**
 	 * Visit a parse tree produced by the {@code ComparisonOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitComparisonOp(@NotNull BindingExpressionParser.ComparisonOpContext ctx);
-
+	T visitComparisonOp(BindingExpressionParser.ComparisonOpContext ctx);
 	/**
-	 * Visit a parse tree produced by the {@code DotOp}
+	 * Visit a parse tree produced by the {@code UnaryOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitDotOp(@NotNull BindingExpressionParser.DotOpContext ctx);
-
+	T visitUnaryOp(BindingExpressionParser.UnaryOpContext ctx);
 	/**
-	 * Visit a parse tree produced by the {@code MathOp}
+	 * Visit a parse tree produced by the {@code BracketOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitMathOp(@NotNull BindingExpressionParser.MathOpContext ctx);
-
+	T visitBracketOp(BindingExpressionParser.BracketOpContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code Resource}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitResource(BindingExpressionParser.ResourceContext ctx);
 	/**
 	 * Visit a parse tree produced by the {@code QuestionQuestionOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitQuestionQuestionOp(@NotNull BindingExpressionParser.QuestionQuestionOpContext ctx);
-
+	T visitQuestionQuestionOp(BindingExpressionParser.QuestionQuestionOpContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code Grouping}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitGrouping(BindingExpressionParser.GroupingContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code MethodInvocation}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitMethodInvocation(BindingExpressionParser.MethodInvocationContext ctx);
 	/**
 	 * Visit a parse tree produced by the {@code BitShiftOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitBitShiftOp(@NotNull BindingExpressionParser.BitShiftOpContext ctx);
-
+	T visitBitShiftOp(BindingExpressionParser.BitShiftOpContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code AndOrOp}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitAndOrOp(BindingExpressionParser.AndOrOpContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code TernaryOp}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitTernaryOp(BindingExpressionParser.TernaryOpContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code Primary}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitPrimary(BindingExpressionParser.PrimaryContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code DotOp}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitDotOp(BindingExpressionParser.DotOpContext ctx);
+	/**
+	 * Visit a parse tree produced by the {@code MathOp}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitMathOp(BindingExpressionParser.MathOpContext ctx);
 	/**
 	 * Visit a parse tree produced by the {@code InstanceOfOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitInstanceOfOp(@NotNull BindingExpressionParser.InstanceOfOpContext ctx);
-
+	T visitInstanceOfOp(BindingExpressionParser.InstanceOfOpContext ctx);
 	/**
 	 * Visit a parse tree produced by the {@code BinaryOp}
 	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitBinaryOp(@NotNull BindingExpressionParser.BinaryOpContext ctx);
-
+	T visitBinaryOp(BindingExpressionParser.BinaryOpContext ctx);
 	/**
-	 * Visit a parse tree produced by {@link BindingExpressionParser#bindingSyntax}.
+	 * Visit a parse tree produced by the {@code FunctionRef}
+	 * labeled alternative in {@link BindingExpressionParser#expression}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitBindingSyntax(@NotNull BindingExpressionParser.BindingSyntaxContext ctx);
-
-	/**
-	 * Visit a parse tree produced by {@link BindingExpressionParser#defaults}.
-	 * @param ctx the parse tree
-	 * @return the visitor result
-	 */
-	Result visitDefaults(@NotNull BindingExpressionParser.DefaultsContext ctx);
-
-	/**
-	 * Visit a parse tree produced by {@link BindingExpressionParser#constantValue}.
-	 * @param ctx the parse tree
-	 * @return the visitor result
-	 */
-	Result visitConstantValue(@NotNull BindingExpressionParser.ConstantValueContext ctx);
-
-	/**
-	 * Visit a parse tree produced by {@link BindingExpressionParser#expression}.
-	 * @param ctx the parse tree
-	 * @return the visitor result
-	 */
-	Result visitExpression(@NotNull BindingExpressionParser.ExpressionContext ctx);
-
+	T visitFunctionRef(BindingExpressionParser.FunctionRefContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#classExtraction}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitClassExtraction(@NotNull BindingExpressionParser.ClassExtractionContext ctx);
-
+	T visitClassExtraction(BindingExpressionParser.ClassExtractionContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#expressionList}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitExpressionList(@NotNull BindingExpressionParser.ExpressionListContext ctx);
-
+	T visitExpressionList(BindingExpressionParser.ExpressionListContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#literal}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitLiteral(@NotNull BindingExpressionParser.LiteralContext ctx);
-
+	T visitLiteral(BindingExpressionParser.LiteralContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#identifier}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitIdentifier(@NotNull BindingExpressionParser.IdentifierContext ctx);
-
+	T visitIdentifier(BindingExpressionParser.IdentifierContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#javaLiteral}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitJavaLiteral(@NotNull BindingExpressionParser.JavaLiteralContext ctx);
-
+	T visitJavaLiteral(BindingExpressionParser.JavaLiteralContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#stringLiteral}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitStringLiteral(@NotNull BindingExpressionParser.StringLiteralContext ctx);
-
+	T visitStringLiteral(BindingExpressionParser.StringLiteralContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#explicitGenericInvocation}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitExplicitGenericInvocation(@NotNull BindingExpressionParser.ExplicitGenericInvocationContext ctx);
-
+	T visitExplicitGenericInvocation(BindingExpressionParser.ExplicitGenericInvocationContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#typeArguments}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitTypeArguments(@NotNull BindingExpressionParser.TypeArgumentsContext ctx);
-
+	T visitTypeArguments(BindingExpressionParser.TypeArgumentsContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#type}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitType(@NotNull BindingExpressionParser.TypeContext ctx);
-
+	T visitType(BindingExpressionParser.TypeContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#explicitGenericInvocationSuffix}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitExplicitGenericInvocationSuffix(@NotNull BindingExpressionParser.ExplicitGenericInvocationSuffixContext ctx);
-
+	T visitExplicitGenericInvocationSuffix(BindingExpressionParser.ExplicitGenericInvocationSuffixContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#arguments}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitArguments(@NotNull BindingExpressionParser.ArgumentsContext ctx);
-
+	T visitArguments(BindingExpressionParser.ArgumentsContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#classOrInterfaceType}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitClassOrInterfaceType(@NotNull BindingExpressionParser.ClassOrInterfaceTypeContext ctx);
-
+	T visitClassOrInterfaceType(BindingExpressionParser.ClassOrInterfaceTypeContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#primitiveType}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitPrimitiveType(@NotNull BindingExpressionParser.PrimitiveTypeContext ctx);
-
+	T visitPrimitiveType(BindingExpressionParser.PrimitiveTypeContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#resources}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitResources(@NotNull BindingExpressionParser.ResourcesContext ctx);
-
+	T visitResources(BindingExpressionParser.ResourcesContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link BindingExpressionParser#resourceParameters}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitResourceParameters(@NotNull BindingExpressionParser.ResourceParametersContext ctx);
+	T visitResourceParameters(BindingExpressionParser.ResourceParametersContext ctx);
 }
\ No newline at end of file
diff --git a/compilerCommon/src/main/java/android/databinding/tool/DataBindingBuilder.java b/compilerCommon/src/main/java/android/databinding/tool/DataBindingBuilder.java
index 0e5d757..2a567df 100644
--- a/compilerCommon/src/main/java/android/databinding/tool/DataBindingBuilder.java
+++ b/compilerCommon/src/main/java/android/databinding/tool/DataBindingBuilder.java
@@ -31,9 +31,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Properties;
 
 
diff --git a/compilerCommon/src/main/java/android/databinding/tool/processing/ErrorMessages.java b/compilerCommon/src/main/java/android/databinding/tool/processing/ErrorMessages.java
index a2ec898..746729e 100644
--- a/compilerCommon/src/main/java/android/databinding/tool/processing/ErrorMessages.java
+++ b/compilerCommon/src/main/java/android/databinding/tool/processing/ErrorMessages.java
@@ -22,7 +22,7 @@
     public static final String UNDEFINED_VARIABLE =
             "Identifiers must have user defined types from the XML file. %s is missing it";
     public static final String CANNOT_FIND_SETTER_CALL =
-            "Cannot find the setter for attribute '%s' with parameter type %s.";
+            "Cannot find the setter for attribute '%s' with parameter type %s on %s.";
     public static final String CANNOT_RESOLVE_TYPE =
             "Cannot resolve type for %s";
     public static final String MULTI_CONFIG_LAYOUT_CLASS_NAME_MISMATCH =
@@ -46,4 +46,18 @@
             "The expression %s cannot cannot be inverted: %s";
     public static final String TWO_WAY_EVENT_ATTRIBUTE =
             "The attribute %s is a two-way binding event attribute and cannot be assigned.";
+    public static final String CANNOT_FIND_ABSTRACT_METHOD =
+            "Cannot find the proper callback class for %s. Tried %s but it has %d abstract methods,"
+                    + " should have %d abstract methods.";
+    public static final String CALLBACK_ARGUMENT_COUNT_MISMATCH = "The callback %s#%s has %s"
+            + " methods but the lambda defined has %d. It should have either 0 or equal number of"
+            + " parameters.";
+    public static final String UNDEFINED_CALLBACK_ARGUMENT =
+            "%s is not defined. It should either be a variable defined in the layout file or a"
+                    + " parameter of the Callback.";
+    public static final String DUPLICATE_CALLBACK_ARGUMENT =
+            "Callback arguments must have unique names. %s is used twice or more.";
+    public static final String CALLBACK_VARIABLE_NAME_CLASH =
+            "%s in the callback definition will override the variable %s (%s) in the callback"
+                    + " scope.";
 }
diff --git a/compilerCommon/src/main/java/android/databinding/tool/processing/Scope.java b/compilerCommon/src/main/java/android/databinding/tool/processing/Scope.java
index 9e0a692..98c8281 100644
--- a/compilerCommon/src/main/java/android/databinding/tool/processing/Scope.java
+++ b/compilerCommon/src/main/java/android/databinding/tool/processing/Scope.java
@@ -24,6 +24,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 
@@ -40,7 +41,7 @@
         enter(new LocationScopeProvider() {
             @Override
             public List<Location> provideScopeLocation() {
-                return Arrays.asList(location);
+                return Collections.singletonList(location);
             }
         });
     }
@@ -162,7 +163,7 @@
             return null;
         }
         if (locations.size() == 1) {
-            return Arrays.asList(locations.get(0).toAbsoluteLocation());
+            return Collections.singletonList(locations.get(0).toAbsoluteLocation());
         }
         // We have more than 1 location. Depending on the scope, we may or may not want all of them
         List<Location> chosen = new ArrayList<Location>();
@@ -185,9 +186,11 @@
         }
         List<Location> absoluteParents = findAbsoluteLocationFrom(parent,
                 (LocationScopeProvider) provider);
-        for (Location location : absoluteParents) {
-            if (location.contains(absLocation)) {
-                return true;
+        if (absoluteParents != null) {
+            for (Location location : absoluteParents) {
+                if (location.contains(absLocation)) {
+                    return true;
+                }
             }
         }
         return false;
diff --git a/compilerCommon/src/main/java/android/databinding/tool/processing/ScopedException.java b/compilerCommon/src/main/java/android/databinding/tool/processing/ScopedException.java
index 0f98072..a91c7ad 100644
--- a/compilerCommon/src/main/java/android/databinding/tool/processing/ScopedException.java
+++ b/compilerCommon/src/main/java/android/databinding/tool/processing/ScopedException.java
@@ -64,7 +64,7 @@
         return sEncodeOutput ? createEncodedMessage() : createHumanReadableMessage();
     }
 
-    private String createHumanReadableMessage() {
+    public String createHumanReadableMessage() {
         ScopedErrorReport scopedError = getScopedErrorReport();
         StringBuilder sb = new StringBuilder();
         sb.append(super.getMessage()).append("\n")
diff --git a/compilerCommon/src/main/java/android/databinding/tool/util/L.java b/compilerCommon/src/main/java/android/databinding/tool/util/L.java
index 37292b2..b7c8f3d 100644
--- a/compilerCommon/src/main/java/android/databinding/tool/util/L.java
+++ b/compilerCommon/src/main/java/android/databinding/tool/util/L.java
@@ -16,7 +16,9 @@
 
 package android.databinding.tool.util;
 
+import android.databinding.tool.processing.ScopedErrorReport;
 import android.databinding.tool.processing.ScopedException;
+import android.databinding.tool.processing.scopes.LocationScopeProvider;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -113,6 +115,14 @@
     }
 
     private static void printMessage(Element element, Diagnostic.Kind kind, String message) {
+        if (kind == Kind.WARNING) {
+            // try to convert it to a scoped message
+            ScopedException ex = new ScopedException(message);
+            if (ex.isValid()) {
+                sClient.printMessage(kind, ex.createHumanReadableMessage(), element);
+                return;
+            }
+        }
         sClient.printMessage(kind, message, element);
         if (kind == Diagnostic.Kind.ERROR) {
             throw new RuntimeException("failure, see logs for details.\n" + message);
diff --git a/compilerCommon/src/main/java/android/databinding/tool/util/StringUtils.java b/compilerCommon/src/main/java/android/databinding/tool/util/StringUtils.java
index 5f535ba..5774183 100644
--- a/compilerCommon/src/main/java/android/databinding/tool/util/StringUtils.java
+++ b/compilerCommon/src/main/java/android/databinding/tool/util/StringUtils.java
@@ -19,8 +19,6 @@
 import com.google.common.base.StandardSystemProperty;
 import com.google.common.base.Strings;
 
-import org.antlr.v4.runtime.misc.Nullable;
-
 public class StringUtils {
 
     public static final String LINE_SEPARATOR = StandardSystemProperty.LINE_SEPARATOR.value();
@@ -41,7 +39,7 @@
     /** The entity for the line feed character */
     private static final String LFEED_ENTITY = "&#xA;";
 
-    public static boolean isNotBlank(@Nullable CharSequence string) {
+    public static boolean isNotBlank(CharSequence string) {
         if (string == null) {
             return false;
         }
@@ -53,7 +51,7 @@
         return false;
     }
 
-    public static String capitalize(@Nullable String string) {
+    public static String capitalize(String string) {
         if (Strings.isNullOrEmpty(string)) {
             return string;
         }
diff --git a/compilerCommon/src/main/java/android/databinding/tool/util/XmlEditor.java b/compilerCommon/src/main/java/android/databinding/tool/util/XmlEditor.java
index e5a3da2..6255416 100644
--- a/compilerCommon/src/main/java/android/databinding/tool/util/XmlEditor.java
+++ b/compilerCommon/src/main/java/android/databinding/tool/util/XmlEditor.java
@@ -16,6 +16,7 @@
 
 package android.databinding.tool.util;
 
+import android.databinding.parser.BindingExpressionBaseVisitor;
 import android.databinding.parser.BindingExpressionLexer;
 import android.databinding.parser.BindingExpressionParser;
 import android.databinding.parser.XMLLexer;
@@ -29,6 +30,7 @@
 import org.antlr.v4.runtime.ANTLRInputStream;
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.misc.NotNull;
 import org.antlr.v4.runtime.tree.TerminalNode;
 import org.apache.commons.io.FileUtils;
 
@@ -69,7 +71,7 @@
         }
 
         ArrayList<String> lines = new ArrayList<String>();
-        lines.addAll(FileUtils.readLines(f, "utf-8"));
+        lines.addAll(FileUtils.readLines(f, encoding));
 
         for (ElementContext it : dataNodes) {
             replace(lines, toPosition(it.getStart()), toEndPosition(it.getStop()), "");
@@ -343,7 +345,14 @@
         CommonTokenStream tokenStream = new CommonTokenStream(lexer);
         BindingExpressionParser parser = new BindingExpressionParser(tokenStream);
         BindingExpressionParser.BindingSyntaxContext root = parser.bindingSyntax();
-        BindingExpressionParser.DefaultsContext defaults = root.defaults();
+        BindingExpressionParser.DefaultsContext defaults = root
+                .accept(new BindingExpressionBaseVisitor<BindingExpressionParser.DefaultsContext>() {
+                    @Override
+                    public BindingExpressionParser.DefaultsContext visitDefaults(
+                            @NotNull BindingExpressionParser.DefaultsContext ctx) {
+                        return ctx;
+                    }
+                });
         if (defaults != null) {
             BindingExpressionParser.ConstantValueContext constantValue = defaults
                     .constantValue();
diff --git a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLLexer.java b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLLexer.java
index b8c79bb..352a2f1 100644
--- a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLLexer.java
+++ b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLLexer.java
@@ -1,13 +1,21 @@
-// Generated from XMLLexer.g4 by ANTLR 4.4
+// Generated from XMLLexer.g4 by ANTLR 4.5.3
 package android.databinding.parser;
-
-import org.antlr.v4.runtime.CharStream;
 import org.antlr.v4.runtime.Lexer;
-import org.antlr.v4.runtime.atn.ATN;
-import org.antlr.v4.runtime.atn.ATNDeserializer;
-import org.antlr.v4.runtime.atn.LexerATNSimulator;
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.TokenStream;
+import org.antlr.v4.runtime.*;
+import org.antlr.v4.runtime.atn.*;
+import org.antlr.v4.runtime.dfa.DFA;
+import org.antlr.v4.runtime.misc.*;
 
+@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
 public class XMLLexer extends Lexer {
+	static { RuntimeMetaData.checkVersion("4.5.3", RuntimeMetaData.VERSION); }
+
+	protected static final DFA[] _decisionToDFA;
+	protected static final PredictionContextCache _sharedContextCache =
+		new PredictionContextCache();
 	public static final int
 		COMMENT=1, CDATA=2, DTD=3, EntityRef=4, CharRef=5, SEA_WS=6, OPEN=7, XMLDeclOpen=8, 
 		TEXT=9, CLOSE=10, SPECIAL_CLOSE=11, SLASH_CLOSE=12, SLASH=13, EQUALS=14, 
@@ -18,11 +26,6 @@
 		"DEFAULT_MODE", "INSIDE", "PROC_INSTR"
 	};
 
-	public static final String[] tokenNames = {
-		"'\\u0000'", "'\\u0001'", "'\\u0002'", "'\\u0003'", "'\\u0004'", "'\\u0005'", 
-		"'\\u0006'", "'\\u0007'", "'\b'", "'\t'", "'\n'", "'\\u000B'", "'\f'", 
-		"'\r'", "'\\u000E'", "'\\u000F'", "'\\u0010'", "'\\u0011'", "'\\u0012'"
-	};
 	public static final String[] ruleNames = {
 		"COMMENT", "CDATA", "DTD", "EntityRef", "CharRef", "SEA_WS", "OPEN", "XMLDeclOpen", 
 		"SPECIAL_OPEN", "TEXT", "CLOSE", "SPECIAL_CLOSE", "SLASH_CLOSE", "SLASH", 
@@ -30,19 +33,58 @@
 		"PI", "IGNORE"
 	};
 
+	private static final String[] _LITERAL_NAMES = {
+		null, null, null, null, null, null, null, "'<'", null, null, "'>'", null, 
+		"'/>'", "'/'", "'='"
+	};
+	private static final String[] _SYMBOLIC_NAMES = {
+		null, "COMMENT", "CDATA", "DTD", "EntityRef", "CharRef", "SEA_WS", "OPEN", 
+		"XMLDeclOpen", "TEXT", "CLOSE", "SPECIAL_CLOSE", "SLASH_CLOSE", "SLASH", 
+		"EQUALS", "STRING", "Name", "S", "PI"
+	};
+	public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
+
+	/**
+	 * @deprecated Use {@link #VOCABULARY} instead.
+	 */
+	@Deprecated
+	public static final String[] tokenNames;
+	static {
+		tokenNames = new String[_SYMBOLIC_NAMES.length];
+		for (int i = 0; i < tokenNames.length; i++) {
+			tokenNames[i] = VOCABULARY.getLiteralName(i);
+			if (tokenNames[i] == null) {
+				tokenNames[i] = VOCABULARY.getSymbolicName(i);
+			}
+
+			if (tokenNames[i] == null) {
+				tokenNames[i] = "<INVALID>";
+			}
+		}
+	}
+
+	@Override
+	@Deprecated
+	public String[] getTokenNames() {
+		return tokenNames;
+	}
+
+	@Override
+
+	public Vocabulary getVocabulary() {
+		return VOCABULARY;
+	}
+
 
 	public XMLLexer(CharStream input) {
 		super(input);
-		_interp = new LexerATNSimulator(this,_ATN);
+		_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
 	}
 
 	@Override
 	public String getGrammarFileName() { return "XMLLexer.g4"; }
 
 	@Override
-	public String[] getTokenNames() { return tokenNames; }
-
-	@Override
 	public String[] getRuleNames() { return ruleNames; }
 
 	@Override
@@ -51,8 +93,11 @@
 	@Override
 	public String[] getModeNames() { return modeNames; }
 
+	@Override
+	public ATN getATN() { return _ATN; }
+
 	public static final String _serializedATN =
-		"\3\uaf6f\u8320\u479d\ub75c\u4880\u1605\u191c\uab37\2\24\u00e9\b\1\b\1"+
+		"\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\2\24\u00e9\b\1\b\1"+
 		"\b\1\4\2\t\2\4\3\t\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\4"+
 		"\n\t\n\4\13\t\13\4\f\t\f\4\r\t\r\4\16\t\16\4\17\t\17\4\20\t\20\4\21\t"+
 		"\21\4\22\t\22\4\23\t\23\4\24\t\24\4\25\t\25\4\26\t\26\4\27\t\27\4\30\t"+
@@ -69,68 +114,71 @@
 		"\13\21\3\21\5\21\u00c7\n\21\3\22\3\22\7\22\u00cb\n\22\f\22\16\22\u00ce"+
 		"\13\22\3\23\3\23\3\23\3\23\3\24\3\24\3\25\3\25\3\26\3\26\3\26\3\26\5\26"+
 		"\u00dc\n\26\3\27\5\27\u00df\n\27\3\30\3\30\3\30\3\30\3\30\3\31\3\31\3"+
-		"\31\3\31\5=Q^\2\2\32\5\2\3\7\2\4\t\2\5\13\2\6\r\2\7\17\2\b\21\2\t\23\2"+
-		"\n\25\2\2\27\2\13\31\2\f\33\2\r\35\2\16\37\2\17!\2\20#\2\21%\2\22\'\2"+
-		"\23)\2\2+\2\2-\2\2/\2\2\61\2\24\63\2\2\5\2\3\4\f\4\2\13\13\"\"\4\2((>"+
-		">\4\2$$>>\4\2))>>\5\2\13\f\17\17\"\"\5\2\62;CHch\3\2\62;\4\2/\60aa\5\2"+
-		"\u00b9\u00b9\u0302\u0371\u2041\u2042\n\2<<C\\c|\u2072\u2191\u2c02\u2ff1"+
-		"\u3003\ud801\uf902\ufdd1\ufdf2\uffff\u00f3\2\5\3\2\2\2\2\7\3\2\2\2\2\t"+
-		"\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21\3\2\2\2\2\23\3\2\2"+
-		"\2\2\25\3\2\2\2\2\27\3\2\2\2\3\31\3\2\2\2\3\33\3\2\2\2\3\35\3\2\2\2\3"+
-		"\37\3\2\2\2\3!\3\2\2\2\3#\3\2\2\2\3%\3\2\2\2\3\'\3\2\2\2\4\61\3\2\2\2"+
-		"\4\63\3\2\2\2\5\65\3\2\2\2\7D\3\2\2\2\tX\3\2\2\2\13e\3\2\2\2\r~\3\2\2"+
-		"\2\17\u0085\3\2\2\2\21\u0089\3\2\2\2\23\u008d\3\2\2\2\25\u0097\3\2\2\2"+
-		"\27\u00a0\3\2\2\2\31\u00a4\3\2\2\2\33\u00a8\3\2\2\2\35\u00ad\3\2\2\2\37"+
-		"\u00b2\3\2\2\2!\u00b4\3\2\2\2#\u00c6\3\2\2\2%\u00c8\3\2\2\2\'\u00cf\3"+
-		"\2\2\2)\u00d3\3\2\2\2+\u00d5\3\2\2\2-\u00db\3\2\2\2/\u00de\3\2\2\2\61"+
-		"\u00e0\3\2\2\2\63\u00e5\3\2\2\2\65\66\7>\2\2\66\67\7#\2\2\678\7/\2\28"+
-		"9\7/\2\29=\3\2\2\2:<\13\2\2\2;:\3\2\2\2<?\3\2\2\2=>\3\2\2\2=;\3\2\2\2"+
-		">@\3\2\2\2?=\3\2\2\2@A\7/\2\2AB\7/\2\2BC\7@\2\2C\6\3\2\2\2DE\7>\2\2EF"+
-		"\7#\2\2FG\7]\2\2GH\7E\2\2HI\7F\2\2IJ\7C\2\2JK\7V\2\2KL\7C\2\2LM\7]\2\2"+
-		"MQ\3\2\2\2NP\13\2\2\2ON\3\2\2\2PS\3\2\2\2QR\3\2\2\2QO\3\2\2\2RT\3\2\2"+
-		"\2SQ\3\2\2\2TU\7_\2\2UV\7_\2\2VW\7@\2\2W\b\3\2\2\2XY\7>\2\2YZ\7#\2\2Z"+
-		"^\3\2\2\2[]\13\2\2\2\\[\3\2\2\2]`\3\2\2\2^_\3\2\2\2^\\\3\2\2\2_a\3\2\2"+
-		"\2`^\3\2\2\2ab\7@\2\2bc\3\2\2\2cd\b\4\2\2d\n\3\2\2\2ef\7(\2\2fg\5%\22"+
-		"\2gh\7=\2\2h\f\3\2\2\2ij\7(\2\2jk\7%\2\2km\3\2\2\2ln\5+\25\2ml\3\2\2\2"+
-		"no\3\2\2\2om\3\2\2\2op\3\2\2\2pq\3\2\2\2qr\7=\2\2r\177\3\2\2\2st\7(\2"+
-		"\2tu\7%\2\2uv\7z\2\2vx\3\2\2\2wy\5)\24\2xw\3\2\2\2yz\3\2\2\2zx\3\2\2\2"+
-		"z{\3\2\2\2{|\3\2\2\2|}\7=\2\2}\177\3\2\2\2~i\3\2\2\2~s\3\2\2\2\177\16"+
-		"\3\2\2\2\u0080\u0086\t\2\2\2\u0081\u0083\7\17\2\2\u0082\u0081\3\2\2\2"+
-		"\u0082\u0083\3\2\2\2\u0083\u0084\3\2\2\2\u0084\u0086\7\f\2\2\u0085\u0080"+
-		"\3\2\2\2\u0085\u0082\3\2\2\2\u0086\u0087\3\2\2\2\u0087\u0085\3\2\2\2\u0087"+
-		"\u0088\3\2\2\2\u0088\20\3\2\2\2\u0089\u008a\7>\2\2\u008a\u008b\3\2\2\2"+
-		"\u008b\u008c\b\b\3\2\u008c\22\3\2\2\2\u008d\u008e\7>\2\2\u008e\u008f\7"+
-		"A\2\2\u008f\u0090\7z\2\2\u0090\u0091\7o\2\2\u0091\u0092\7n\2\2\u0092\u0093"+
-		"\3\2\2\2\u0093\u0094\5\'\23\2\u0094\u0095\3\2\2\2\u0095\u0096\b\t\3\2"+
-		"\u0096\24\3\2\2\2\u0097\u0098\7>\2\2\u0098\u0099\7A\2\2\u0099\u009a\3"+
-		"\2\2\2\u009a\u009b\5%\22\2\u009b\u009c\3\2\2\2\u009c\u009d\b\n\4\2\u009d"+
-		"\u009e\b\n\5\2\u009e\26\3\2\2\2\u009f\u00a1\n\3\2\2\u00a0\u009f\3\2\2"+
-		"\2\u00a1\u00a2\3\2\2\2\u00a2\u00a0\3\2\2\2\u00a2\u00a3\3\2\2\2\u00a3\30"+
-		"\3\2\2\2\u00a4\u00a5\7@\2\2\u00a5\u00a6\3\2\2\2\u00a6\u00a7\b\f\6\2\u00a7"+
-		"\32\3\2\2\2\u00a8\u00a9\7A\2\2\u00a9\u00aa\7@\2\2\u00aa\u00ab\3\2\2\2"+
-		"\u00ab\u00ac\b\r\6\2\u00ac\34\3\2\2\2\u00ad\u00ae\7\61\2\2\u00ae\u00af"+
-		"\7@\2\2\u00af\u00b0\3\2\2\2\u00b0\u00b1\b\16\6\2\u00b1\36\3\2\2\2\u00b2"+
-		"\u00b3\7\61\2\2\u00b3 \3\2\2\2\u00b4\u00b5\7?\2\2\u00b5\"\3\2\2\2\u00b6"+
-		"\u00ba\7$\2\2\u00b7\u00b9\n\4\2\2\u00b8\u00b7\3\2\2\2\u00b9\u00bc\3\2"+
-		"\2\2\u00ba\u00b8\3\2\2\2\u00ba\u00bb\3\2\2\2\u00bb\u00bd\3\2\2\2\u00bc"+
-		"\u00ba\3\2\2\2\u00bd\u00c7\7$\2\2\u00be\u00c2\7)\2\2\u00bf\u00c1\n\5\2"+
-		"\2\u00c0\u00bf\3\2\2\2\u00c1\u00c4\3\2\2\2\u00c2\u00c0\3\2\2\2\u00c2\u00c3"+
-		"\3\2\2\2\u00c3\u00c5\3\2\2\2\u00c4\u00c2\3\2\2\2\u00c5\u00c7\7)\2\2\u00c6"+
-		"\u00b6\3\2\2\2\u00c6\u00be\3\2\2\2\u00c7$\3\2\2\2\u00c8\u00cc\5/\27\2"+
-		"\u00c9\u00cb\5-\26\2\u00ca\u00c9\3\2\2\2\u00cb\u00ce\3\2\2\2\u00cc\u00ca"+
-		"\3\2\2\2\u00cc\u00cd\3\2\2\2\u00cd&\3\2\2\2\u00ce\u00cc\3\2\2\2\u00cf"+
-		"\u00d0\t\6\2\2\u00d0\u00d1\3\2\2\2\u00d1\u00d2\b\23\2\2\u00d2(\3\2\2\2"+
-		"\u00d3\u00d4\t\7\2\2\u00d4*\3\2\2\2\u00d5\u00d6\t\b\2\2\u00d6,\3\2\2\2"+
-		"\u00d7\u00dc\5/\27\2\u00d8\u00dc\t\t\2\2\u00d9\u00dc\5+\25\2\u00da\u00dc"+
-		"\t\n\2\2\u00db\u00d7\3\2\2\2\u00db\u00d8\3\2\2\2\u00db\u00d9\3\2\2\2\u00db"+
-		"\u00da\3\2\2\2\u00dc.\3\2\2\2\u00dd\u00df\t\13\2\2\u00de\u00dd\3\2\2\2"+
-		"\u00df\60\3\2\2\2\u00e0\u00e1\7A\2\2\u00e1\u00e2\7@\2\2\u00e2\u00e3\3"+
-		"\2\2\2\u00e3\u00e4\b\30\6\2\u00e4\62\3\2\2\2\u00e5\u00e6\13\2\2\2\u00e6"+
-		"\u00e7\3\2\2\2\u00e7\u00e8\b\31\4\2\u00e8\64\3\2\2\2\25\2\3\4=Q^oz~\u0082"+
-		"\u0085\u0087\u00a2\u00ba\u00c2\u00c6\u00cc\u00db\u00de\7\b\2\2\7\3\2\5"+
-		"\2\2\7\4\2\6\2\2";
+		"\31\3\31\5=Q^\2\32\5\3\7\4\t\5\13\6\r\7\17\b\21\t\23\n\25\2\27\13\31\f"+
+		"\33\r\35\16\37\17!\20#\21%\22\'\23)\2+\2-\2/\2\61\24\63\2\5\2\3\4\f\4"+
+		"\2\13\13\"\"\4\2((>>\4\2$$>>\4\2))>>\5\2\13\f\17\17\"\"\5\2\62;CHch\3"+
+		"\2\62;\4\2/\60aa\5\2\u00b9\u00b9\u0302\u0371\u2041\u2042\n\2<<C\\c|\u2072"+
+		"\u2191\u2c02\u2ff1\u3003\ud801\uf902\ufdd1\ufdf2\uffff\u00f3\2\5\3\2\2"+
+		"\2\2\7\3\2\2\2\2\t\3\2\2\2\2\13\3\2\2\2\2\r\3\2\2\2\2\17\3\2\2\2\2\21"+
+		"\3\2\2\2\2\23\3\2\2\2\2\25\3\2\2\2\2\27\3\2\2\2\3\31\3\2\2\2\3\33\3\2"+
+		"\2\2\3\35\3\2\2\2\3\37\3\2\2\2\3!\3\2\2\2\3#\3\2\2\2\3%\3\2\2\2\3\'\3"+
+		"\2\2\2\4\61\3\2\2\2\4\63\3\2\2\2\5\65\3\2\2\2\7D\3\2\2\2\tX\3\2\2\2\13"+
+		"e\3\2\2\2\r~\3\2\2\2\17\u0085\3\2\2\2\21\u0089\3\2\2\2\23\u008d\3\2\2"+
+		"\2\25\u0097\3\2\2\2\27\u00a0\3\2\2\2\31\u00a4\3\2\2\2\33\u00a8\3\2\2\2"+
+		"\35\u00ad\3\2\2\2\37\u00b2\3\2\2\2!\u00b4\3\2\2\2#\u00c6\3\2\2\2%\u00c8"+
+		"\3\2\2\2\'\u00cf\3\2\2\2)\u00d3\3\2\2\2+\u00d5\3\2\2\2-\u00db\3\2\2\2"+
+		"/\u00de\3\2\2\2\61\u00e0\3\2\2\2\63\u00e5\3\2\2\2\65\66\7>\2\2\66\67\7"+
+		"#\2\2\678\7/\2\289\7/\2\29=\3\2\2\2:<\13\2\2\2;:\3\2\2\2<?\3\2\2\2=>\3"+
+		"\2\2\2=;\3\2\2\2>@\3\2\2\2?=\3\2\2\2@A\7/\2\2AB\7/\2\2BC\7@\2\2C\6\3\2"+
+		"\2\2DE\7>\2\2EF\7#\2\2FG\7]\2\2GH\7E\2\2HI\7F\2\2IJ\7C\2\2JK\7V\2\2KL"+
+		"\7C\2\2LM\7]\2\2MQ\3\2\2\2NP\13\2\2\2ON\3\2\2\2PS\3\2\2\2QR\3\2\2\2QO"+
+		"\3\2\2\2RT\3\2\2\2SQ\3\2\2\2TU\7_\2\2UV\7_\2\2VW\7@\2\2W\b\3\2\2\2XY\7"+
+		">\2\2YZ\7#\2\2Z^\3\2\2\2[]\13\2\2\2\\[\3\2\2\2]`\3\2\2\2^_\3\2\2\2^\\"+
+		"\3\2\2\2_a\3\2\2\2`^\3\2\2\2ab\7@\2\2bc\3\2\2\2cd\b\4\2\2d\n\3\2\2\2e"+
+		"f\7(\2\2fg\5%\22\2gh\7=\2\2h\f\3\2\2\2ij\7(\2\2jk\7%\2\2km\3\2\2\2ln\5"+
+		"+\25\2ml\3\2\2\2no\3\2\2\2om\3\2\2\2op\3\2\2\2pq\3\2\2\2qr\7=\2\2r\177"+
+		"\3\2\2\2st\7(\2\2tu\7%\2\2uv\7z\2\2vx\3\2\2\2wy\5)\24\2xw\3\2\2\2yz\3"+
+		"\2\2\2zx\3\2\2\2z{\3\2\2\2{|\3\2\2\2|}\7=\2\2}\177\3\2\2\2~i\3\2\2\2~"+
+		"s\3\2\2\2\177\16\3\2\2\2\u0080\u0086\t\2\2\2\u0081\u0083\7\17\2\2\u0082"+
+		"\u0081\3\2\2\2\u0082\u0083\3\2\2\2\u0083\u0084\3\2\2\2\u0084\u0086\7\f"+
+		"\2\2\u0085\u0080\3\2\2\2\u0085\u0082\3\2\2\2\u0086\u0087\3\2\2\2\u0087"+
+		"\u0085\3\2\2\2\u0087\u0088\3\2\2\2\u0088\20\3\2\2\2\u0089\u008a\7>\2\2"+
+		"\u008a\u008b\3\2\2\2\u008b\u008c\b\b\3\2\u008c\22\3\2\2\2\u008d\u008e"+
+		"\7>\2\2\u008e\u008f\7A\2\2\u008f\u0090\7z\2\2\u0090\u0091\7o\2\2\u0091"+
+		"\u0092\7n\2\2\u0092\u0093\3\2\2\2\u0093\u0094\5\'\23\2\u0094\u0095\3\2"+
+		"\2\2\u0095\u0096\b\t\3\2\u0096\24\3\2\2\2\u0097\u0098\7>\2\2\u0098\u0099"+
+		"\7A\2\2\u0099\u009a\3\2\2\2\u009a\u009b\5%\22\2\u009b\u009c\3\2\2\2\u009c"+
+		"\u009d\b\n\4\2\u009d\u009e\b\n\5\2\u009e\26\3\2\2\2\u009f\u00a1\n\3\2"+
+		"\2\u00a0\u009f\3\2\2\2\u00a1\u00a2\3\2\2\2\u00a2\u00a0\3\2\2\2\u00a2\u00a3"+
+		"\3\2\2\2\u00a3\30\3\2\2\2\u00a4\u00a5\7@\2\2\u00a5\u00a6\3\2\2\2\u00a6"+
+		"\u00a7\b\f\6\2\u00a7\32\3\2\2\2\u00a8\u00a9\7A\2\2\u00a9\u00aa\7@\2\2"+
+		"\u00aa\u00ab\3\2\2\2\u00ab\u00ac\b\r\6\2\u00ac\34\3\2\2\2\u00ad\u00ae"+
+		"\7\61\2\2\u00ae\u00af\7@\2\2\u00af\u00b0\3\2\2\2\u00b0\u00b1\b\16\6\2"+
+		"\u00b1\36\3\2\2\2\u00b2\u00b3\7\61\2\2\u00b3 \3\2\2\2\u00b4\u00b5\7?\2"+
+		"\2\u00b5\"\3\2\2\2\u00b6\u00ba\7$\2\2\u00b7\u00b9\n\4\2\2\u00b8\u00b7"+
+		"\3\2\2\2\u00b9\u00bc\3\2\2\2\u00ba\u00b8\3\2\2\2\u00ba\u00bb\3\2\2\2\u00bb"+
+		"\u00bd\3\2\2\2\u00bc\u00ba\3\2\2\2\u00bd\u00c7\7$\2\2\u00be\u00c2\7)\2"+
+		"\2\u00bf\u00c1\n\5\2\2\u00c0\u00bf\3\2\2\2\u00c1\u00c4\3\2\2\2\u00c2\u00c0"+
+		"\3\2\2\2\u00c2\u00c3\3\2\2\2\u00c3\u00c5\3\2\2\2\u00c4\u00c2\3\2\2\2\u00c5"+
+		"\u00c7\7)\2\2\u00c6\u00b6\3\2\2\2\u00c6\u00be\3\2\2\2\u00c7$\3\2\2\2\u00c8"+
+		"\u00cc\5/\27\2\u00c9\u00cb\5-\26\2\u00ca\u00c9\3\2\2\2\u00cb\u00ce\3\2"+
+		"\2\2\u00cc\u00ca\3\2\2\2\u00cc\u00cd\3\2\2\2\u00cd&\3\2\2\2\u00ce\u00cc"+
+		"\3\2\2\2\u00cf\u00d0\t\6\2\2\u00d0\u00d1\3\2\2\2\u00d1\u00d2\b\23\2\2"+
+		"\u00d2(\3\2\2\2\u00d3\u00d4\t\7\2\2\u00d4*\3\2\2\2\u00d5\u00d6\t\b\2\2"+
+		"\u00d6,\3\2\2\2\u00d7\u00dc\5/\27\2\u00d8\u00dc\t\t\2\2\u00d9\u00dc\5"+
+		"+\25\2\u00da\u00dc\t\n\2\2\u00db\u00d7\3\2\2\2\u00db\u00d8\3\2\2\2\u00db"+
+		"\u00d9\3\2\2\2\u00db\u00da\3\2\2\2\u00dc.\3\2\2\2\u00dd\u00df\t\13\2\2"+
+		"\u00de\u00dd\3\2\2\2\u00df\60\3\2\2\2\u00e0\u00e1\7A\2\2\u00e1\u00e2\7"+
+		"@\2\2\u00e2\u00e3\3\2\2\2\u00e3\u00e4\b\30\6\2\u00e4\62\3\2\2\2\u00e5"+
+		"\u00e6\13\2\2\2\u00e6\u00e7\3\2\2\2\u00e7\u00e8\b\31\4\2\u00e8\64\3\2"+
+		"\2\2\25\2\3\4=Q^oz~\u0082\u0085\u0087\u00a2\u00ba\u00c2\u00c6\u00cc\u00db"+
+		"\u00de\7\b\2\2\7\3\2\5\2\2\7\4\2\6\2\2";
 	public static final ATN _ATN =
 		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
 	static {
+		_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
+		for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
+			_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
+		}
 	}
 }
\ No newline at end of file
diff --git a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLLexer.tokens b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLLexer.tokens
index cd122a4..d80683d 100644
--- a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLLexer.tokens
+++ b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLLexer.tokens
@@ -1,23 +1,23 @@
-OPEN=7
+COMMENT=1
 CDATA=2
-SLASH=13
+DTD=3
+EntityRef=4
 CharRef=5
 SEA_WS=6
-SPECIAL_CLOSE=11
-CLOSE=10
-DTD=3
-Name=16
-EQUALS=14
-PI=18
-S=17
-SLASH_CLOSE=12
-TEXT=9
-COMMENT=1
+OPEN=7
 XMLDeclOpen=8
-EntityRef=4
+TEXT=9
+CLOSE=10
+SPECIAL_CLOSE=11
+SLASH_CLOSE=12
+SLASH=13
+EQUALS=14
 STRING=15
-'='=14
-'/'=13
+Name=16
+S=17
+PI=18
 '<'=7
-'/>'=12
 '>'=10
+'/>'=12
+'/'=13
+'='=14
diff --git a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParser.java b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParser.java
index a375780..5eaad94 100644
--- a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParser.java
+++ b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParser.java
@@ -1,4 +1,4 @@
-// Generated from XMLParser.g4 by ANTLR 4.4
+// Generated from XMLParser.g4 by ANTLR 4.5.3
 package android.databinding.parser;
 import org.antlr.v4.runtime.atn.*;
 import org.antlr.v4.runtime.dfa.DFA;
@@ -6,17 +6,20 @@
 import org.antlr.v4.runtime.misc.*;
 import org.antlr.v4.runtime.tree.*;
 import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
 
+@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
 public class XMLParser extends Parser {
+	static { RuntimeMetaData.checkVersion("4.5.3", RuntimeMetaData.VERSION); }
+
+	protected static final DFA[] _decisionToDFA;
+	protected static final PredictionContextCache _sharedContextCache =
+		new PredictionContextCache();
 	public static final int
-		OPEN=7, CDATA=2, SLASH=13, CharRef=5, SEA_WS=6, SPECIAL_CLOSE=11, CLOSE=10, 
-		DTD=3, Name=16, EQUALS=14, PI=18, S=17, SLASH_CLOSE=12, TEXT=9, COMMENT=1, 
-		XMLDeclOpen=8, EntityRef=4, STRING=15;
-	public static final String[] tokenNames = {
-		"<INVALID>", "COMMENT", "CDATA", "DTD", "EntityRef", "CharRef", "SEA_WS", 
-		"'<'", "XMLDeclOpen", "TEXT", "'>'", "SPECIAL_CLOSE", "'/>'", "'/'", "'='", 
-		"STRING", "Name", "S", "PI"
-	};
+		COMMENT=1, CDATA=2, DTD=3, EntityRef=4, CharRef=5, SEA_WS=6, OPEN=7, XMLDeclOpen=8, 
+		TEXT=9, CLOSE=10, SPECIAL_CLOSE=11, SLASH_CLOSE=12, SLASH=13, EQUALS=14, 
+		STRING=15, Name=16, S=17, PI=18;
 	public static final int
 		RULE_document = 0, RULE_prolog = 1, RULE_content = 2, RULE_element = 3, 
 		RULE_reference = 4, RULE_attribute = 5, RULE_chardata = 6, RULE_misc = 7;
@@ -25,11 +28,50 @@
 		"chardata", "misc"
 	};
 
-	@Override
-	public String getGrammarFileName() { return "XMLParser.g4"; }
+	private static final String[] _LITERAL_NAMES = {
+		null, null, null, null, null, null, null, "'<'", null, null, "'>'", null, 
+		"'/>'", "'/'", "'='"
+	};
+	private static final String[] _SYMBOLIC_NAMES = {
+		null, "COMMENT", "CDATA", "DTD", "EntityRef", "CharRef", "SEA_WS", "OPEN", 
+		"XMLDeclOpen", "TEXT", "CLOSE", "SPECIAL_CLOSE", "SLASH_CLOSE", "SLASH", 
+		"EQUALS", "STRING", "Name", "S", "PI"
+	};
+	public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
+
+	/**
+	 * @deprecated Use {@link #VOCABULARY} instead.
+	 */
+	@Deprecated
+	public static final String[] tokenNames;
+	static {
+		tokenNames = new String[_SYMBOLIC_NAMES.length];
+		for (int i = 0; i < tokenNames.length; i++) {
+			tokenNames[i] = VOCABULARY.getLiteralName(i);
+			if (tokenNames[i] == null) {
+				tokenNames[i] = VOCABULARY.getSymbolicName(i);
+			}
+
+			if (tokenNames[i] == null) {
+				tokenNames[i] = "<INVALID>";
+			}
+		}
+	}
 
 	@Override
-	public String[] getTokenNames() { return tokenNames; }
+	@Deprecated
+	public String[] getTokenNames() {
+		return tokenNames;
+	}
+
+	@Override
+
+	public Vocabulary getVocabulary() {
+		return VOCABULARY;
+	}
+
+	@Override
+	public String getGrammarFileName() { return "XMLParser.g4"; }
 
 	@Override
 	public String[] getRuleNames() { return ruleNames; }
@@ -37,20 +79,23 @@
 	@Override
 	public String getSerializedATN() { return _serializedATN; }
 
+	@Override
+	public ATN getATN() { return _ATN; }
+
 	public XMLParser(TokenStream input) {
 		super(input);
-		_interp = new ParserATNSimulator(this,_ATN);
+		_interp = new ParserATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
 	}
 	public static class DocumentContext extends ParserRuleContext {
 		public ElementContext element() {
 			return getRuleContext(ElementContext.class,0);
 		}
-		public List<? extends MiscContext> misc() {
-			return getRuleContexts(MiscContext.class);
-		}
 		public PrologContext prolog() {
 			return getRuleContext(PrologContext.class,0);
 		}
+		public List<MiscContext> misc() {
+			return getRuleContexts(MiscContext.class);
+		}
 		public MiscContext misc(int i) {
 			return getRuleContext(MiscContext.class,i);
 		}
@@ -67,13 +112,12 @@
 			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitDocument(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitDocument(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof XMLParserVisitor ) return ((XMLParserVisitor<? extends T>)visitor).visitDocument(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final DocumentContext document() throws RecognitionException {
 		DocumentContext _localctx = new DocumentContext(_ctx, getState());
 		enterRule(_localctx, 0, RULE_document);
@@ -85,7 +129,8 @@
 			_la = _input.LA(1);
 			if (_la==XMLDeclOpen) {
 				{
-				setState(16); prolog();
+				setState(16);
+				prolog();
 				}
 			}
 
@@ -95,21 +140,24 @@
 			while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << COMMENT) | (1L << SEA_WS) | (1L << PI))) != 0)) {
 				{
 				{
-				setState(19); misc();
+				setState(19);
+				misc();
 				}
 				}
 				setState(24);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
-			setState(25); element();
+			setState(25);
+			element();
 			setState(29);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while ((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << COMMENT) | (1L << SEA_WS) | (1L << PI))) != 0)) {
 				{
 				{
-				setState(26); misc();
+				setState(26);
+				misc();
 				}
 				}
 				setState(31);
@@ -130,14 +178,14 @@
 	}
 
 	public static class PrologContext extends ParserRuleContext {
+		public TerminalNode XMLDeclOpen() { return getToken(XMLParser.XMLDeclOpen, 0); }
 		public TerminalNode SPECIAL_CLOSE() { return getToken(XMLParser.SPECIAL_CLOSE, 0); }
-		public List<? extends AttributeContext> attribute() {
+		public List<AttributeContext> attribute() {
 			return getRuleContexts(AttributeContext.class);
 		}
 		public AttributeContext attribute(int i) {
 			return getRuleContext(AttributeContext.class,i);
 		}
-		public TerminalNode XMLDeclOpen() { return getToken(XMLParser.XMLDeclOpen, 0); }
 		public PrologContext(ParserRuleContext parent, int invokingState) {
 			super(parent, invokingState);
 		}
@@ -151,13 +199,12 @@
 			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitProlog(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitProlog(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof XMLParserVisitor ) return ((XMLParserVisitor<? extends T>)visitor).visitProlog(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final PrologContext prolog() throws RecognitionException {
 		PrologContext _localctx = new PrologContext(_ctx, getState());
 		enterRule(_localctx, 2, RULE_prolog);
@@ -165,21 +212,24 @@
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(32); match(XMLDeclOpen);
+			setState(32);
+			match(XMLDeclOpen);
 			setState(36);
 			_errHandler.sync(this);
 			_la = _input.LA(1);
 			while (_la==Name) {
 				{
 				{
-				setState(33); attribute();
+				setState(33);
+				attribute();
 				}
 				}
 				setState(38);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 			}
-			setState(39); match(SPECIAL_CLOSE);
+			setState(39);
+			match(SPECIAL_CLOSE);
 			}
 		}
 		catch (RecognitionException re) {
@@ -194,35 +244,35 @@
 	}
 
 	public static class ContentContext extends ParserRuleContext {
-		public List<? extends TerminalNode> PI() { return getTokens(XMLParser.PI); }
-		public List<? extends TerminalNode> CDATA() { return getTokens(XMLParser.CDATA); }
-		public List<? extends ElementContext> element() {
-			return getRuleContexts(ElementContext.class);
+		public List<ChardataContext> chardata() {
+			return getRuleContexts(ChardataContext.class);
 		}
-		public TerminalNode PI(int i) {
-			return getToken(XMLParser.PI, i);
+		public ChardataContext chardata(int i) {
+			return getRuleContext(ChardataContext.class,i);
+		}
+		public List<ElementContext> element() {
+			return getRuleContexts(ElementContext.class);
 		}
 		public ElementContext element(int i) {
 			return getRuleContext(ElementContext.class,i);
 		}
-		public TerminalNode COMMENT(int i) {
-			return getToken(XMLParser.COMMENT, i);
-		}
-		public TerminalNode CDATA(int i) {
-			return getToken(XMLParser.CDATA, i);
+		public List<ReferenceContext> reference() {
+			return getRuleContexts(ReferenceContext.class);
 		}
 		public ReferenceContext reference(int i) {
 			return getRuleContext(ReferenceContext.class,i);
 		}
-		public List<? extends TerminalNode> COMMENT() { return getTokens(XMLParser.COMMENT); }
-		public ChardataContext chardata(int i) {
-			return getRuleContext(ChardataContext.class,i);
+		public List<TerminalNode> CDATA() { return getTokens(XMLParser.CDATA); }
+		public TerminalNode CDATA(int i) {
+			return getToken(XMLParser.CDATA, i);
 		}
-		public List<? extends ChardataContext> chardata() {
-			return getRuleContexts(ChardataContext.class);
+		public List<TerminalNode> PI() { return getTokens(XMLParser.PI); }
+		public TerminalNode PI(int i) {
+			return getToken(XMLParser.PI, i);
 		}
-		public List<? extends ReferenceContext> reference() {
-			return getRuleContexts(ReferenceContext.class);
+		public List<TerminalNode> COMMENT() { return getTokens(XMLParser.COMMENT); }
+		public TerminalNode COMMENT(int i) {
+			return getToken(XMLParser.COMMENT, i);
 		}
 		public ContentContext(ParserRuleContext parent, int invokingState) {
 			super(parent, invokingState);
@@ -237,13 +287,12 @@
 			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitContent(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitContent(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof XMLParserVisitor ) return ((XMLParserVisitor<? extends T>)visitor).visitContent(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ContentContext content() throws RecognitionException {
 		ContentContext _localctx = new ContentContext(_ctx, getState());
 		enterRule(_localctx, 4, RULE_content);
@@ -256,7 +305,8 @@
 			_la = _input.LA(1);
 			if (_la==SEA_WS || _la==TEXT) {
 				{
-				setState(41); chardata();
+				setState(41);
+				chardata();
 				}
 			}
 
@@ -271,28 +321,33 @@
 					switch (_input.LA(1)) {
 					case OPEN:
 						{
-						setState(44); element();
+						setState(44);
+						element();
 						}
 						break;
 					case EntityRef:
 					case CharRef:
 						{
-						setState(45); reference();
+						setState(45);
+						reference();
 						}
 						break;
 					case CDATA:
 						{
-						setState(46); match(CDATA);
+						setState(46);
+						match(CDATA);
 						}
 						break;
 					case PI:
 						{
-						setState(47); match(PI);
+						setState(47);
+						match(PI);
 						}
 						break;
 					case COMMENT:
 						{
-						setState(48); match(COMMENT);
+						setState(48);
+						match(COMMENT);
 						}
 						break;
 					default:
@@ -302,7 +357,8 @@
 					_la = _input.LA(1);
 					if (_la==SEA_WS || _la==TEXT) {
 						{
-						setState(51); chardata();
+						setState(51);
+						chardata();
 						}
 					}
 
@@ -328,19 +384,19 @@
 
 	public static class ElementContext extends ParserRuleContext {
 		public Token elmName;
-		public List<? extends AttributeContext> attribute() {
+		public ContentContext content() {
+			return getRuleContext(ContentContext.class,0);
+		}
+		public List<TerminalNode> Name() { return getTokens(XMLParser.Name); }
+		public TerminalNode Name(int i) {
+			return getToken(XMLParser.Name, i);
+		}
+		public List<AttributeContext> attribute() {
 			return getRuleContexts(AttributeContext.class);
 		}
 		public AttributeContext attribute(int i) {
 			return getRuleContext(AttributeContext.class,i);
 		}
-		public TerminalNode Name(int i) {
-			return getToken(XMLParser.Name, i);
-		}
-		public List<? extends TerminalNode> Name() { return getTokens(XMLParser.Name); }
-		public ContentContext content() {
-			return getRuleContext(ContentContext.class,0);
-		}
 		public ElementContext(ParserRuleContext parent, int invokingState) {
 			super(parent, invokingState);
 		}
@@ -354,66 +410,78 @@
 			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitElement(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitElement(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof XMLParserVisitor ) return ((XMLParserVisitor<? extends T>)visitor).visitElement(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ElementContext element() throws RecognitionException {
 		ElementContext _localctx = new ElementContext(_ctx, getState());
 		enterRule(_localctx, 6, RULE_element);
 		int _la;
 		try {
 			setState(83);
+			_errHandler.sync(this);
 			switch ( getInterpreter().adaptivePredict(_input,10,_ctx) ) {
 			case 1:
 				enterOuterAlt(_localctx, 1);
 				{
-				setState(59); match(OPEN);
-				setState(60); _localctx.elmName = match(Name);
+				setState(59);
+				match(OPEN);
+				setState(60);
+				((ElementContext)_localctx).elmName = match(Name);
 				setState(64);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 				while (_la==Name) {
 					{
 					{
-					setState(61); attribute();
+					setState(61);
+					attribute();
 					}
 					}
 					setState(66);
 					_errHandler.sync(this);
 					_la = _input.LA(1);
 				}
-				setState(67); match(CLOSE);
-				setState(68); content();
-				setState(69); match(OPEN);
-				setState(70); match(SLASH);
-				setState(71); match(Name);
-				setState(72); match(CLOSE);
+				setState(67);
+				match(CLOSE);
+				setState(68);
+				content();
+				setState(69);
+				match(OPEN);
+				setState(70);
+				match(SLASH);
+				setState(71);
+				match(Name);
+				setState(72);
+				match(CLOSE);
 				}
 				break;
-
 			case 2:
 				enterOuterAlt(_localctx, 2);
 				{
-				setState(74); match(OPEN);
-				setState(75); _localctx.elmName = match(Name);
+				setState(74);
+				match(OPEN);
+				setState(75);
+				((ElementContext)_localctx).elmName = match(Name);
 				setState(79);
 				_errHandler.sync(this);
 				_la = _input.LA(1);
 				while (_la==Name) {
 					{
 					{
-					setState(76); attribute();
+					setState(76);
+					attribute();
 					}
 					}
 					setState(81);
 					_errHandler.sync(this);
 					_la = _input.LA(1);
 				}
-				setState(82); match(SLASH_CLOSE);
+				setState(82);
+				match(SLASH_CLOSE);
 				}
 				break;
 			}
@@ -430,8 +498,8 @@
 	}
 
 	public static class ReferenceContext extends ParserRuleContext {
-		public TerminalNode CharRef() { return getToken(XMLParser.CharRef, 0); }
 		public TerminalNode EntityRef() { return getToken(XMLParser.EntityRef, 0); }
+		public TerminalNode CharRef() { return getToken(XMLParser.CharRef, 0); }
 		public ReferenceContext(ParserRuleContext parent, int invokingState) {
 			super(parent, invokingState);
 		}
@@ -445,13 +513,12 @@
 			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitReference(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitReference(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof XMLParserVisitor ) return ((XMLParserVisitor<? extends T>)visitor).visitReference(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ReferenceContext reference() throws RecognitionException {
 		ReferenceContext _localctx = new ReferenceContext(_ctx, getState());
 		enterRule(_localctx, 8, RULE_reference);
@@ -463,8 +530,9 @@
 			_la = _input.LA(1);
 			if ( !(_la==EntityRef || _la==CharRef) ) {
 			_errHandler.recoverInline(this);
+			} else {
+				consume();
 			}
-			consume();
 			}
 		}
 		catch (RecognitionException re) {
@@ -496,22 +564,24 @@
 			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitAttribute(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitAttribute(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof XMLParserVisitor ) return ((XMLParserVisitor<? extends T>)visitor).visitAttribute(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final AttributeContext attribute() throws RecognitionException {
 		AttributeContext _localctx = new AttributeContext(_ctx, getState());
 		enterRule(_localctx, 10, RULE_attribute);
 		try {
 			enterOuterAlt(_localctx, 1);
 			{
-			setState(87); _localctx.attrName = match(Name);
-			setState(88); match(EQUALS);
-			setState(89); _localctx.attrValue = match(STRING);
+			setState(87);
+			((AttributeContext)_localctx).attrName = match(Name);
+			setState(88);
+			match(EQUALS);
+			setState(89);
+			((AttributeContext)_localctx).attrValue = match(STRING);
 			}
 		}
 		catch (RecognitionException re) {
@@ -526,8 +596,8 @@
 	}
 
 	public static class ChardataContext extends ParserRuleContext {
-		public TerminalNode SEA_WS() { return getToken(XMLParser.SEA_WS, 0); }
 		public TerminalNode TEXT() { return getToken(XMLParser.TEXT, 0); }
+		public TerminalNode SEA_WS() { return getToken(XMLParser.SEA_WS, 0); }
 		public ChardataContext(ParserRuleContext parent, int invokingState) {
 			super(parent, invokingState);
 		}
@@ -541,13 +611,12 @@
 			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitChardata(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitChardata(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof XMLParserVisitor ) return ((XMLParserVisitor<? extends T>)visitor).visitChardata(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final ChardataContext chardata() throws RecognitionException {
 		ChardataContext _localctx = new ChardataContext(_ctx, getState());
 		enterRule(_localctx, 12, RULE_chardata);
@@ -559,8 +628,9 @@
 			_la = _input.LA(1);
 			if ( !(_la==SEA_WS || _la==TEXT) ) {
 			_errHandler.recoverInline(this);
+			} else {
+				consume();
 			}
-			consume();
 			}
 		}
 		catch (RecognitionException re) {
@@ -575,9 +645,9 @@
 	}
 
 	public static class MiscContext extends ParserRuleContext {
-		public TerminalNode SEA_WS() { return getToken(XMLParser.SEA_WS, 0); }
-		public TerminalNode PI() { return getToken(XMLParser.PI, 0); }
 		public TerminalNode COMMENT() { return getToken(XMLParser.COMMENT, 0); }
+		public TerminalNode PI() { return getToken(XMLParser.PI, 0); }
+		public TerminalNode SEA_WS() { return getToken(XMLParser.SEA_WS, 0); }
 		public MiscContext(ParserRuleContext parent, int invokingState) {
 			super(parent, invokingState);
 		}
@@ -591,13 +661,12 @@
 			if ( listener instanceof XMLParserListener ) ((XMLParserListener)listener).exitMisc(this);
 		}
 		@Override
-		public <Result> Result accept(ParseTreeVisitor<? extends Result> visitor) {
-			if ( visitor instanceof XMLParserVisitor<?> ) return ((XMLParserVisitor<? extends Result>)visitor).visitMisc(this);
+		public <T> T accept(ParseTreeVisitor<? extends T> visitor) {
+			if ( visitor instanceof XMLParserVisitor ) return ((XMLParserVisitor<? extends T>)visitor).visitMisc(this);
 			else return visitor.visitChildren(this);
 		}
 	}
 
-	@RuleVersion(0)
 	public final MiscContext misc() throws RecognitionException {
 		MiscContext _localctx = new MiscContext(_ctx, getState());
 		enterRule(_localctx, 14, RULE_misc);
@@ -609,8 +678,9 @@
 			_la = _input.LA(1);
 			if ( !((((_la) & ~0x3f) == 0 && ((1L << _la) & ((1L << COMMENT) | (1L << SEA_WS) | (1L << PI))) != 0)) ) {
 			_errHandler.recoverInline(this);
+			} else {
+				consume();
 			}
-			consume();
 			}
 		}
 		catch (RecognitionException re) {
@@ -625,34 +695,38 @@
 	}
 
 	public static final String _serializedATN =
-		"\3\uaf6f\u8320\u479d\ub75c\u4880\u1605\u191c\uab37\3\24b\4\2\t\2\4\3\t"+
+		"\3\u0430\ud6d1\u8206\uad2d\u4417\uaef1\u8d80\uaadd\3\24b\4\2\t\2\4\3\t"+
 		"\3\4\4\t\4\4\5\t\5\4\6\t\6\4\7\t\7\4\b\t\b\4\t\t\t\3\2\5\2\24\n\2\3\2"+
 		"\7\2\27\n\2\f\2\16\2\32\13\2\3\2\3\2\7\2\36\n\2\f\2\16\2!\13\2\3\3\3\3"+
 		"\7\3%\n\3\f\3\16\3(\13\3\3\3\3\3\3\4\5\4-\n\4\3\4\3\4\3\4\3\4\3\4\5\4"+
 		"\64\n\4\3\4\5\4\67\n\4\7\49\n\4\f\4\16\4<\13\4\3\5\3\5\3\5\7\5A\n\5\f"+
 		"\5\16\5D\13\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\3\5\7\5P\n\5\f\5\16"+
 		"\5S\13\5\3\5\5\5V\n\5\3\6\3\6\3\7\3\7\3\7\3\7\3\b\3\b\3\t\3\t\3\t\2\2"+
-		"\2\n\2\2\4\2\6\2\b\2\n\2\f\2\16\2\20\2\2\5\3\2\6\7\4\2\b\b\13\13\5\2\3"+
-		"\3\b\b\24\24g\2\23\3\2\2\2\4\"\3\2\2\2\6,\3\2\2\2\bU\3\2\2\2\nW\3\2\2"+
-		"\2\fY\3\2\2\2\16]\3\2\2\2\20_\3\2\2\2\22\24\5\4\3\2\23\22\3\2\2\2\23\24"+
-		"\3\2\2\2\24\30\3\2\2\2\25\27\5\20\t\2\26\25\3\2\2\2\27\32\3\2\2\2\30\26"+
-		"\3\2\2\2\30\31\3\2\2\2\31\33\3\2\2\2\32\30\3\2\2\2\33\37\5\b\5\2\34\36"+
-		"\5\20\t\2\35\34\3\2\2\2\36!\3\2\2\2\37\35\3\2\2\2\37 \3\2\2\2 \3\3\2\2"+
-		"\2!\37\3\2\2\2\"&\7\n\2\2#%\5\f\7\2$#\3\2\2\2%(\3\2\2\2&$\3\2\2\2&\'\3"+
-		"\2\2\2\')\3\2\2\2(&\3\2\2\2)*\7\r\2\2*\5\3\2\2\2+-\5\16\b\2,+\3\2\2\2"+
-		",-\3\2\2\2-:\3\2\2\2.\64\5\b\5\2/\64\5\n\6\2\60\64\7\4\2\2\61\64\7\24"+
-		"\2\2\62\64\7\3\2\2\63.\3\2\2\2\63/\3\2\2\2\63\60\3\2\2\2\63\61\3\2\2\2"+
-		"\63\62\3\2\2\2\64\66\3\2\2\2\65\67\5\16\b\2\66\65\3\2\2\2\66\67\3\2\2"+
-		"\2\679\3\2\2\28\63\3\2\2\29<\3\2\2\2:8\3\2\2\2:;\3\2\2\2;\7\3\2\2\2<:"+
-		"\3\2\2\2=>\7\t\2\2>B\7\22\2\2?A\5\f\7\2@?\3\2\2\2AD\3\2\2\2B@\3\2\2\2"+
-		"BC\3\2\2\2CE\3\2\2\2DB\3\2\2\2EF\7\f\2\2FG\5\6\4\2GH\7\t\2\2HI\7\17\2"+
-		"\2IJ\7\22\2\2JK\7\f\2\2KV\3\2\2\2LM\7\t\2\2MQ\7\22\2\2NP\5\f\7\2ON\3\2"+
-		"\2\2PS\3\2\2\2QO\3\2\2\2QR\3\2\2\2RT\3\2\2\2SQ\3\2\2\2TV\7\16\2\2U=\3"+
-		"\2\2\2UL\3\2\2\2V\t\3\2\2\2WX\t\2\2\2X\13\3\2\2\2YZ\7\22\2\2Z[\7\20\2"+
-		"\2[\\\7\21\2\2\\\r\3\2\2\2]^\t\3\2\2^\17\3\2\2\2_`\t\4\2\2`\21\3\2\2\2"+
-		"\r\23\30\37&,\63\66:BQU";
+		"\n\2\4\6\b\n\f\16\20\2\5\3\2\6\7\4\2\b\b\13\13\5\2\3\3\b\b\24\24g\2\23"+
+		"\3\2\2\2\4\"\3\2\2\2\6,\3\2\2\2\bU\3\2\2\2\nW\3\2\2\2\fY\3\2\2\2\16]\3"+
+		"\2\2\2\20_\3\2\2\2\22\24\5\4\3\2\23\22\3\2\2\2\23\24\3\2\2\2\24\30\3\2"+
+		"\2\2\25\27\5\20\t\2\26\25\3\2\2\2\27\32\3\2\2\2\30\26\3\2\2\2\30\31\3"+
+		"\2\2\2\31\33\3\2\2\2\32\30\3\2\2\2\33\37\5\b\5\2\34\36\5\20\t\2\35\34"+
+		"\3\2\2\2\36!\3\2\2\2\37\35\3\2\2\2\37 \3\2\2\2 \3\3\2\2\2!\37\3\2\2\2"+
+		"\"&\7\n\2\2#%\5\f\7\2$#\3\2\2\2%(\3\2\2\2&$\3\2\2\2&\'\3\2\2\2\')\3\2"+
+		"\2\2(&\3\2\2\2)*\7\r\2\2*\5\3\2\2\2+-\5\16\b\2,+\3\2\2\2,-\3\2\2\2-:\3"+
+		"\2\2\2.\64\5\b\5\2/\64\5\n\6\2\60\64\7\4\2\2\61\64\7\24\2\2\62\64\7\3"+
+		"\2\2\63.\3\2\2\2\63/\3\2\2\2\63\60\3\2\2\2\63\61\3\2\2\2\63\62\3\2\2\2"+
+		"\64\66\3\2\2\2\65\67\5\16\b\2\66\65\3\2\2\2\66\67\3\2\2\2\679\3\2\2\2"+
+		"8\63\3\2\2\29<\3\2\2\2:8\3\2\2\2:;\3\2\2\2;\7\3\2\2\2<:\3\2\2\2=>\7\t"+
+		"\2\2>B\7\22\2\2?A\5\f\7\2@?\3\2\2\2AD\3\2\2\2B@\3\2\2\2BC\3\2\2\2CE\3"+
+		"\2\2\2DB\3\2\2\2EF\7\f\2\2FG\5\6\4\2GH\7\t\2\2HI\7\17\2\2IJ\7\22\2\2J"+
+		"K\7\f\2\2KV\3\2\2\2LM\7\t\2\2MQ\7\22\2\2NP\5\f\7\2ON\3\2\2\2PS\3\2\2\2"+
+		"QO\3\2\2\2QR\3\2\2\2RT\3\2\2\2SQ\3\2\2\2TV\7\16\2\2U=\3\2\2\2UL\3\2\2"+
+		"\2V\t\3\2\2\2WX\t\2\2\2X\13\3\2\2\2YZ\7\22\2\2Z[\7\20\2\2[\\\7\21\2\2"+
+		"\\\r\3\2\2\2]^\t\3\2\2^\17\3\2\2\2_`\t\4\2\2`\21\3\2\2\2\r\23\30\37&,"+
+		"\63\66:BQU";
 	public static final ATN _ATN =
 		new ATNDeserializer().deserialize(_serializedATN.toCharArray());
 	static {
+		_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
+		for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
+			_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
+		}
 	}
 }
\ No newline at end of file
diff --git a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParser.tokens b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParser.tokens
index b1423a1..d80683d 100644
--- a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParser.tokens
+++ b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParser.tokens
@@ -1,23 +1,23 @@
-OPEN=7
+COMMENT=1
 CDATA=2
-SLASH=13
+DTD=3
+EntityRef=4
 CharRef=5
 SEA_WS=6
-SPECIAL_CLOSE=11
-CLOSE=10
-DTD=3
-Name=16
-EQUALS=14
-PI=18
-SLASH_CLOSE=12
-S=17
-TEXT=9
+OPEN=7
 XMLDeclOpen=8
-COMMENT=1
-EntityRef=4
+TEXT=9
+CLOSE=10
+SPECIAL_CLOSE=11
+SLASH_CLOSE=12
+SLASH=13
+EQUALS=14
 STRING=15
-'='=14
+Name=16
+S=17
+PI=18
 '<'=7
-'/'=13
-'/>'=12
 '>'=10
+'/>'=12
+'/'=13
+'='=14
diff --git a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserBaseListener.java b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserBaseListener.java
index 4c2bae2..0d237e7 100644
--- a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserBaseListener.java
+++ b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserBaseListener.java
@@ -1,9 +1,7 @@
-// Generated from XMLParser.g4 by ANTLR 4.4
+// Generated from XMLParser.g4 by ANTLR 4.5.3
 package android.databinding.parser;
 
 import org.antlr.v4.runtime.ParserRuleContext;
-import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.misc.NotNull;
 import org.antlr.v4.runtime.tree.ErrorNode;
 import org.antlr.v4.runtime.tree.TerminalNode;
 
@@ -18,127 +16,120 @@
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterContent(@NotNull XMLParser.ContentContext ctx) { }
+	@Override public void enterDocument(XMLParser.DocumentContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitContent(@NotNull XMLParser.ContentContext ctx) { }
+	@Override public void exitDocument(XMLParser.DocumentContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterProlog(XMLParser.PrologContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitProlog(XMLParser.PrologContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterContent(XMLParser.ContentContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitContent(XMLParser.ContentContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterElement(XMLParser.ElementContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitElement(XMLParser.ElementContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterReference(XMLParser.ReferenceContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitReference(XMLParser.ReferenceContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterAttribute(XMLParser.AttributeContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitAttribute(XMLParser.AttributeContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterChardata(XMLParser.ChardataContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitChardata(XMLParser.ChardataContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void enterMisc(XMLParser.MiscContext ctx) { }
+	/**
+	 * {@inheritDoc}
+	 *
+	 * <p>The default implementation does nothing.</p>
+	 */
+	@Override public void exitMisc(XMLParser.MiscContext ctx) { }
 
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterElement(@NotNull XMLParser.ElementContext ctx) { }
+	@Override public void enterEveryRule(ParserRuleContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitElement(@NotNull XMLParser.ElementContext ctx) { }
-
+	@Override public void exitEveryRule(ParserRuleContext ctx) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void enterProlog(@NotNull XMLParser.PrologContext ctx) { }
+	@Override public void visitTerminal(TerminalNode node) { }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation does nothing.</p>
 	 */
-	@Override public void exitProlog(@NotNull XMLParser.PrologContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterDocument(@NotNull XMLParser.DocumentContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitDocument(@NotNull XMLParser.DocumentContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterAttribute(@NotNull XMLParser.AttributeContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitAttribute(@NotNull XMLParser.AttributeContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterChardata(@NotNull XMLParser.ChardataContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitChardata(@NotNull XMLParser.ChardataContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterReference(@NotNull XMLParser.ReferenceContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitReference(@NotNull XMLParser.ReferenceContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterMisc(@NotNull XMLParser.MiscContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitMisc(@NotNull XMLParser.MiscContext ctx) { }
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void enterEveryRule(@NotNull ParserRuleContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void exitEveryRule(@NotNull ParserRuleContext ctx) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void visitTerminal(@NotNull TerminalNode node) { }
-	/**
-	 * {@inheritDoc}
-	 *
-	 * <p>The default implementation does nothing.</p>
-	 */
-	@Override public void visitErrorNode(@NotNull ErrorNode node) { }
+	@Override public void visitErrorNode(ErrorNode node) { }
 }
\ No newline at end of file
diff --git a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserBaseVisitor.java b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserBaseVisitor.java
index 6b04b77..c89b2d3 100644
--- a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserBaseVisitor.java
+++ b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserBaseVisitor.java
@@ -1,7 +1,5 @@
-// Generated from XMLParser.g4 by ANTLR 4.4
+// Generated from XMLParser.g4 by ANTLR 4.5.3
 package android.databinding.parser;
-import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.misc.NotNull;
 import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
 
 /**
@@ -9,71 +7,64 @@
  * which can be extended to create a visitor which only needs to handle a subset
  * of the available methods.
  *
- * @param <Result> The return type of the visit operation. Use {@link Void} for
+ * @param <T> The return type of the visit operation. Use {@link Void} for
  * operations with no return type.
  */
-public class XMLParserBaseVisitor<Result> extends AbstractParseTreeVisitor<Result> implements XMLParserVisitor<Result> {
+public class XMLParserBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements XMLParserVisitor<T> {
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitContent(@NotNull XMLParser.ContentContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitDocument(XMLParser.DocumentContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitElement(@NotNull XMLParser.ElementContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitProlog(XMLParser.PrologContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitProlog(@NotNull XMLParser.PrologContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitContent(XMLParser.ContentContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitDocument(@NotNull XMLParser.DocumentContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitElement(XMLParser.ElementContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitAttribute(@NotNull XMLParser.AttributeContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitReference(XMLParser.ReferenceContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitChardata(@NotNull XMLParser.ChardataContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitAttribute(XMLParser.AttributeContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitReference(@NotNull XMLParser.ReferenceContext ctx) { return visitChildren(ctx); }
-
+	@Override public T visitChardata(XMLParser.ChardataContext ctx) { return visitChildren(ctx); }
 	/**
 	 * {@inheritDoc}
 	 *
 	 * <p>The default implementation returns the result of calling
 	 * {@link #visitChildren} on {@code ctx}.</p>
 	 */
-	@Override public Result visitMisc(@NotNull XMLParser.MiscContext ctx) { return visitChildren(ctx); }
+	@Override public T visitMisc(XMLParser.MiscContext ctx) { return visitChildren(ctx); }
 }
\ No newline at end of file
diff --git a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserListener.java b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserListener.java
index 6bee172..c1b37e2 100644
--- a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserListener.java
+++ b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserListener.java
@@ -1,7 +1,5 @@
-// Generated from XMLParser.g4 by ANTLR 4.4
+// Generated from XMLParser.g4 by ANTLR 4.5.3
 package android.databinding.parser;
-import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.misc.NotNull;
 import org.antlr.v4.runtime.tree.ParseTreeListener;
 
 /**
@@ -10,90 +8,83 @@
  */
 public interface XMLParserListener extends ParseTreeListener {
 	/**
-	 * Enter a parse tree produced by {@link XMLParser#content}.
-	 * @param ctx the parse tree
-	 */
-	void enterContent(@NotNull XMLParser.ContentContext ctx);
-	/**
-	 * Exit a parse tree produced by {@link XMLParser#content}.
-	 * @param ctx the parse tree
-	 */
-	void exitContent(@NotNull XMLParser.ContentContext ctx);
-
-	/**
-	 * Enter a parse tree produced by {@link XMLParser#element}.
-	 * @param ctx the parse tree
-	 */
-	void enterElement(@NotNull XMLParser.ElementContext ctx);
-	/**
-	 * Exit a parse tree produced by {@link XMLParser#element}.
-	 * @param ctx the parse tree
-	 */
-	void exitElement(@NotNull XMLParser.ElementContext ctx);
-
-	/**
-	 * Enter a parse tree produced by {@link XMLParser#prolog}.
-	 * @param ctx the parse tree
-	 */
-	void enterProlog(@NotNull XMLParser.PrologContext ctx);
-	/**
-	 * Exit a parse tree produced by {@link XMLParser#prolog}.
-	 * @param ctx the parse tree
-	 */
-	void exitProlog(@NotNull XMLParser.PrologContext ctx);
-
-	/**
 	 * Enter a parse tree produced by {@link XMLParser#document}.
 	 * @param ctx the parse tree
 	 */
-	void enterDocument(@NotNull XMLParser.DocumentContext ctx);
+	void enterDocument(XMLParser.DocumentContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link XMLParser#document}.
 	 * @param ctx the parse tree
 	 */
-	void exitDocument(@NotNull XMLParser.DocumentContext ctx);
-
+	void exitDocument(XMLParser.DocumentContext ctx);
 	/**
-	 * Enter a parse tree produced by {@link XMLParser#attribute}.
+	 * Enter a parse tree produced by {@link XMLParser#prolog}.
 	 * @param ctx the parse tree
 	 */
-	void enterAttribute(@NotNull XMLParser.AttributeContext ctx);
+	void enterProlog(XMLParser.PrologContext ctx);
 	/**
-	 * Exit a parse tree produced by {@link XMLParser#attribute}.
+	 * Exit a parse tree produced by {@link XMLParser#prolog}.
 	 * @param ctx the parse tree
 	 */
-	void exitAttribute(@NotNull XMLParser.AttributeContext ctx);
-
+	void exitProlog(XMLParser.PrologContext ctx);
 	/**
-	 * Enter a parse tree produced by {@link XMLParser#chardata}.
+	 * Enter a parse tree produced by {@link XMLParser#content}.
 	 * @param ctx the parse tree
 	 */
-	void enterChardata(@NotNull XMLParser.ChardataContext ctx);
+	void enterContent(XMLParser.ContentContext ctx);
 	/**
-	 * Exit a parse tree produced by {@link XMLParser#chardata}.
+	 * Exit a parse tree produced by {@link XMLParser#content}.
 	 * @param ctx the parse tree
 	 */
-	void exitChardata(@NotNull XMLParser.ChardataContext ctx);
-
+	void exitContent(XMLParser.ContentContext ctx);
+	/**
+	 * Enter a parse tree produced by {@link XMLParser#element}.
+	 * @param ctx the parse tree
+	 */
+	void enterElement(XMLParser.ElementContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link XMLParser#element}.
+	 * @param ctx the parse tree
+	 */
+	void exitElement(XMLParser.ElementContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link XMLParser#reference}.
 	 * @param ctx the parse tree
 	 */
-	void enterReference(@NotNull XMLParser.ReferenceContext ctx);
+	void enterReference(XMLParser.ReferenceContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link XMLParser#reference}.
 	 * @param ctx the parse tree
 	 */
-	void exitReference(@NotNull XMLParser.ReferenceContext ctx);
-
+	void exitReference(XMLParser.ReferenceContext ctx);
+	/**
+	 * Enter a parse tree produced by {@link XMLParser#attribute}.
+	 * @param ctx the parse tree
+	 */
+	void enterAttribute(XMLParser.AttributeContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link XMLParser#attribute}.
+	 * @param ctx the parse tree
+	 */
+	void exitAttribute(XMLParser.AttributeContext ctx);
+	/**
+	 * Enter a parse tree produced by {@link XMLParser#chardata}.
+	 * @param ctx the parse tree
+	 */
+	void enterChardata(XMLParser.ChardataContext ctx);
+	/**
+	 * Exit a parse tree produced by {@link XMLParser#chardata}.
+	 * @param ctx the parse tree
+	 */
+	void exitChardata(XMLParser.ChardataContext ctx);
 	/**
 	 * Enter a parse tree produced by {@link XMLParser#misc}.
 	 * @param ctx the parse tree
 	 */
-	void enterMisc(@NotNull XMLParser.MiscContext ctx);
+	void enterMisc(XMLParser.MiscContext ctx);
 	/**
 	 * Exit a parse tree produced by {@link XMLParser#misc}.
 	 * @param ctx the parse tree
 	 */
-	void exitMisc(@NotNull XMLParser.MiscContext ctx);
+	void exitMisc(XMLParser.MiscContext ctx);
 }
\ No newline at end of file
diff --git a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserVisitor.java b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserVisitor.java
index 6a76a00..a1abfb7 100644
--- a/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserVisitor.java
+++ b/compilerCommon/src/main/xml-gen/android/databinding/parser/XMLParserVisitor.java
@@ -1,70 +1,61 @@
-// Generated from XMLParser.g4 by ANTLR 4.4
+// Generated from XMLParser.g4 by ANTLR 4.5.3
 package android.databinding.parser;
-import org.antlr.v4.runtime.Token;
-import org.antlr.v4.runtime.misc.NotNull;
 import org.antlr.v4.runtime.tree.ParseTreeVisitor;
 
 /**
  * This interface defines a complete generic visitor for a parse tree produced
  * by {@link XMLParser}.
  *
- * @param <Result> The return type of the visit operation. Use {@link Void} for
+ * @param <T> The return type of the visit operation. Use {@link Void} for
  * operations with no return type.
  */
-public interface XMLParserVisitor<Result> extends ParseTreeVisitor<Result> {
-	/**
-	 * Visit a parse tree produced by {@link XMLParser#content}.
-	 * @param ctx the parse tree
-	 * @return the visitor result
-	 */
-	Result visitContent(@NotNull XMLParser.ContentContext ctx);
-
-	/**
-	 * Visit a parse tree produced by {@link XMLParser#element}.
-	 * @param ctx the parse tree
-	 * @return the visitor result
-	 */
-	Result visitElement(@NotNull XMLParser.ElementContext ctx);
-
-	/**
-	 * Visit a parse tree produced by {@link XMLParser#prolog}.
-	 * @param ctx the parse tree
-	 * @return the visitor result
-	 */
-	Result visitProlog(@NotNull XMLParser.PrologContext ctx);
-
+public interface XMLParserVisitor<T> extends ParseTreeVisitor<T> {
 	/**
 	 * Visit a parse tree produced by {@link XMLParser#document}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitDocument(@NotNull XMLParser.DocumentContext ctx);
-
+	T visitDocument(XMLParser.DocumentContext ctx);
 	/**
-	 * Visit a parse tree produced by {@link XMLParser#attribute}.
+	 * Visit a parse tree produced by {@link XMLParser#prolog}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitAttribute(@NotNull XMLParser.AttributeContext ctx);
-
+	T visitProlog(XMLParser.PrologContext ctx);
 	/**
-	 * Visit a parse tree produced by {@link XMLParser#chardata}.
+	 * Visit a parse tree produced by {@link XMLParser#content}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitChardata(@NotNull XMLParser.ChardataContext ctx);
-
+	T visitContent(XMLParser.ContentContext ctx);
+	/**
+	 * Visit a parse tree produced by {@link XMLParser#element}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitElement(XMLParser.ElementContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link XMLParser#reference}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitReference(@NotNull XMLParser.ReferenceContext ctx);
-
+	T visitReference(XMLParser.ReferenceContext ctx);
+	/**
+	 * Visit a parse tree produced by {@link XMLParser#attribute}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitAttribute(XMLParser.AttributeContext ctx);
+	/**
+	 * Visit a parse tree produced by {@link XMLParser#chardata}.
+	 * @param ctx the parse tree
+	 * @return the visitor result
+	 */
+	T visitChardata(XMLParser.ChardataContext ctx);
 	/**
 	 * Visit a parse tree produced by {@link XMLParser#misc}.
 	 * @param ctx the parse tree
 	 * @return the visitor result
 	 */
-	Result visitMisc(@NotNull XMLParser.MiscContext ctx);
+	T visitMisc(XMLParser.MiscContext ctx);
 }
\ No newline at end of file
diff --git a/data-binding.iml b/data-binding.iml
deleted file mode 100644
index bebe401..0000000
--- a/data-binding.iml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module external.linked.project.id="data-binding" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="false">
-    <output url="file://$MODULE_DIR$/build" />
-    <output-test url="file://$MODULE_DIR$/build" />
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <excludeFolder url="file://$MODULE_DIR$/.gradle" />
-      <excludeFolder url="file://$MODULE_DIR$/build" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/dataBinding/dataBinding.iml b/dataBinding/dataBinding.iml
deleted file mode 100644
index 0d65182..0000000
--- a/dataBinding/dataBinding.iml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module external.linked.project.id=":dataBinding" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="com.android.databinding" external.system.module.version="1.1" type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="false">
-    <output url="file://$MODULE_DIR$/build" />
-    <output-test url="file://$MODULE_DIR$/build" />
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <excludeFolder url="file://$MODULE_DIR$/.gradle" />
-      <excludeFolder url="file://$MODULE_DIR$/build" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/databinding.properties b/databinding.properties
index 120a93e..b7e355b 100644
--- a/databinding.properties
+++ b/databinding.properties
@@ -1,10 +1,14 @@
 # global settings for projects
-kotlinVersion = 1.0.0-beta-4584
-extensionsVersion = 1.0-rc5
+kotlinVersion = 1.0.0
+extensionsVersion = 1.1
 # we use a public plugin so that it does not need data binding while compiling library
 androidPublicPluginVersion= 1.5.0
+# java versions for the code that runs on the device
 javaTargetCompatibility = 1.6
 javaSourceCompatibility = 1.6
+# java versions for the code that runs on the host machine
+compilerJavaTargetCompatibility = 1.8
+compilerJavaSourceCompatibility = 1.8
 buildToolsVersion = 22.0.1
 compileSdkVersionStr = 23
 prebuildFolderName=prebuilds
diff --git a/developmentPlugins/localizeMavenPlugin/src/main/groovy/android/databinding/ExportLicensesTask.groovy b/developmentPlugins/localizeMavenPlugin/src/main/groovy/android/databinding/ExportLicensesTask.groovy
index 4db1f39..f883f68 100644
--- a/developmentPlugins/localizeMavenPlugin/src/main/groovy/android/databinding/ExportLicensesTask.groovy
+++ b/developmentPlugins/localizeMavenPlugin/src/main/groovy/android/databinding/ExportLicensesTask.groovy
@@ -25,7 +25,7 @@
     static def knownLicenses = [
             [
                     libraries: ["kotlin-stdlib", "kotlin-runtime", "kotlin-annotation-processing", "kotlin-gradle-plugin", "kotlin-gradle-plugin-api",
-                    "kdoc", "kotlin-gradle-plugin-core", "kotlin-jdk-annotations", "kotlin-compiler", "kotlin-compiler-embeddable"],
+                    "kdoc", "kotlin-gradle-plugin-core", "kotlin-jdk-annotations", "kotlin-compiler", "kotlin-compiler-embeddable", "kotlin-android-extensions"],
                     licenses : ["https://raw.githubusercontent.com/JetBrains/kotlin/master/license/LICENSE.txt",
                                 "http://www.apache.org/licenses/LICENSE-2.0.txt"],
                     notices  : ["https://raw.githubusercontent.com/JetBrains/kotlin/master/license/NOTICE.txt"]
diff --git a/extensions/baseAdapters/build.gradle b/extensions/baseAdapters/build.gradle
index d375aeb..b27457f 100644
--- a/extensions/baseAdapters/build.gradle
+++ b/extensions/baseAdapters/build.gradle
@@ -41,7 +41,10 @@
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
         }
     }
-
+    compileOptions {
+        sourceCompatibility dataBindingConfig.javaTargetCompatibility
+        targetCompatibility dataBindingConfig.javaSourceCompatibility
+    }
     packagingOptions {
         exclude 'META-INF/services/javax.annotation.processing.Processor'
         exclude 'META-INF/LICENSE.txt'
diff --git a/extensions/library/build.gradle b/extensions/library/build.gradle
index 339a20f..d1c686b 100644
--- a/extensions/library/build.gradle
+++ b/extensions/library/build.gradle
@@ -46,8 +46,8 @@
         versionName "1.0"
     }
     compileOptions {
-        sourceCompatibility JavaVersion.VERSION_1_6
-        targetCompatibility JavaVersion.VERSION_1_6
+        sourceCompatibility dataBindingConfig.javaTargetCompatibility
+        targetCompatibility dataBindingConfig.javaSourceCompatibility
     }
     buildTypes {
         release {
@@ -83,6 +83,8 @@
 
     def javadocTask = project.tasks.create(name: "javadoc${suffix}", type: Javadoc) {
         source variant.javaCompile.source
+        options.showFromPublic()
+        options.tags = ['hide']
         classpath = files(variant.javaCompile.classpath.files) + files(
                 "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar")
     }
diff --git a/extensions/library/src/main/java/android/databinding/ObservableField.java b/extensions/library/src/main/java/android/databinding/ObservableField.java
index 6de798b..6b1021c 100644
--- a/extensions/library/src/main/java/android/databinding/ObservableField.java
+++ b/extensions/library/src/main/java/android/databinding/ObservableField.java
@@ -22,7 +22,7 @@
  * <p>
  * Observable field classes may be used instead of creating an Observable object:
  * <pre><code>public class MyDataObject {
- *     public final ObservableField&lt;String> name = new ObservableField&lt;String>();
+ *     public final ObservableField&lt;String&gt; name = new ObservableField&lt;String&gt;();
  *     public final ObservableInt age = new ObservableInt();
  * }</code></pre>
  * Fields of this type should be declared final because bindings only detect changes in the
diff --git a/extensions/library/src/main/java/android/databinding/ObservableInt.java b/extensions/library/src/main/java/android/databinding/ObservableInt.java
index cb25c56..5150225 100644
--- a/extensions/library/src/main/java/android/databinding/ObservableInt.java
+++ b/extensions/library/src/main/java/android/databinding/ObservableInt.java
@@ -25,7 +25,7 @@
  * <p>
  * Observable field classes may be used instead of creating an Observable object:
  * <pre><code>public class MyDataObject {
- *     public final ObservableField<String> name = new ObservableField<String>();
+ *     public final ObservableField&lt;String&gt; name = new ObservableField&lt;String&gt;();
  *     public final ObservableInt age = new ObservableInt();
  * }</code></pre>
  * Fields of this type should be declared final because bindings only detect changes in the
diff --git a/extensions/library/src/main/java/android/databinding/ObservableParcelable.java b/extensions/library/src/main/java/android/databinding/ObservableParcelable.java
index 96eec27..9677410 100644
--- a/extensions/library/src/main/java/android/databinding/ObservableParcelable.java
+++ b/extensions/library/src/main/java/android/databinding/ObservableParcelable.java
@@ -26,7 +26,7 @@
  * <p>
  * Observable field classes may be used instead of creating an Observable object:
  * <pre><code>public class MyDataObject {
- *     public final ObservableParcelable&lt;String> name = new ObservableParcelable&lt;String>();
+ *     public final ObservableParcelable&lt;String&gt; name = new ObservableParcelable&lt;String&gt;();
  *     public final ObservableInt age = new ObservableInt();
  * }</code></pre>
  * Fields of this type should be declared final because bindings only detect changes in the
diff --git a/extensions/library/src/main/java/android/databinding/ViewDataBinding.java b/extensions/library/src/main/java/android/databinding/ViewDataBinding.java
index 5e76023..70c79c4 100644
--- a/extensions/library/src/main/java/android/databinding/ViewDataBinding.java
+++ b/extensions/library/src/main/java/android/databinding/ViewDataBinding.java
@@ -570,29 +570,99 @@
     }
 
     /** @hide */
-    protected int getColorFromResource(int resourceId) {
-        if (VERSION.SDK_INT >= VERSION_CODES.M) {
-            return getRoot().getContext().getColor(resourceId);
-        } else {
-            return getRoot().getResources().getColor(resourceId);
+    protected static boolean parse(String str, boolean fallback) {
+        if (str == null) {
+            return fallback;
+        }
+        return Boolean.parseBoolean(str);
+    }
+
+    /** @hide */
+    protected static byte parse(String str, byte fallback) {
+        try {
+            return Byte.parseByte(str);
+        } catch (NumberFormatException e) {
+            return fallback;
         }
     }
 
     /** @hide */
-    protected ColorStateList getColorStateListFromResource(int resourceId) {
-        if (VERSION.SDK_INT >= VERSION_CODES.M) {
-            return getRoot().getContext().getColorStateList(resourceId);
-        } else {
-            return getRoot().getResources().getColorStateList(resourceId);
+    protected static short parse(String str, short fallback) {
+        try {
+            return Short.parseShort(str);
+        } catch (NumberFormatException e) {
+            return fallback;
         }
     }
 
     /** @hide */
-    protected Drawable getDrawableFromResource(int resourceId) {
+    protected static int parse(String str, int fallback) {
+        try {
+            return Integer.parseInt(str);
+        } catch (NumberFormatException e) {
+            return fallback;
+        }
+    }
+
+    /** @hide */
+    protected static long parse(String str, long fallback) {
+        try {
+            return Long.parseLong(str);
+        } catch (NumberFormatException e) {
+            return fallback;
+        }
+    }
+
+    /** @hide */
+    protected static float parse(String str, float fallback) {
+        try {
+            return Float.parseFloat(str);
+        } catch (NumberFormatException e) {
+            return fallback;
+        }
+    }
+
+    /** @hide */
+    protected static double parse(String str, double fallback) {
+        try {
+            return Double.parseDouble(str);
+        } catch (NumberFormatException e) {
+            return fallback;
+        }
+    }
+
+    /** @hide */
+    protected static char parse(String str, char fallback) {
+        if (str == null || str.isEmpty()) {
+            return fallback;
+        }
+        return str.charAt(0);
+    }
+
+    /** @hide */
+    protected static int getColorFromResource(View view, int resourceId) {
+        if (VERSION.SDK_INT >= VERSION_CODES.M) {
+            return view.getContext().getColor(resourceId);
+        } else {
+            return view.getResources().getColor(resourceId);
+        }
+    }
+
+    /** @hide */
+    protected static ColorStateList getColorStateListFromResource(View view, int resourceId) {
+        if (VERSION.SDK_INT >= VERSION_CODES.M) {
+            return view.getContext().getColorStateList(resourceId);
+        } else {
+            return view.getResources().getColorStateList(resourceId);
+        }
+    }
+
+    /** @hide */
+    protected static Drawable getDrawableFromResource(View view, int resourceId) {
         if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
-            return getRoot().getContext().getDrawable(resourceId);
+            return view.getContext().getDrawable(resourceId);
         } else {
-            return getRoot().getResources().getDrawable(resourceId);
+            return view.getResources().getDrawable(resourceId);
         }
     }
 
@@ -919,7 +989,8 @@
         if (existingBinding != null) {
             return;
         }
-        final String tag = (String) view.getTag();
+        Object objTag = view.getTag();
+        final String tag = (objTag instanceof String) ? (String) objTag : null;
         boolean isBound = false;
         if (isRoot && tag != null && tag.startsWith("layout")) {
             final int underscoreIndex = tag.lastIndexOf('_');
@@ -962,9 +1033,9 @@
             for (int i = 0; i < count; i++) {
                 final View child = viewGroup.getChildAt(i);
                 boolean isInclude = false;
-                if (indexInIncludes >= 0) {
+                if (indexInIncludes >= 0 && child.getTag() instanceof String) {
                     String childTag = (String) child.getTag();
-                    if (childTag != null && childTag.endsWith("_0") &&
+                    if (childTag.endsWith("_0") &&
                             childTag.startsWith("layout") && childTag.indexOf('/') > 0) {
                         // This *could* be an include. Test against the expected includes.
                         int includeIndex = findIncludeIndex(childTag, minInclude,
@@ -1024,7 +1095,8 @@
         int max = firstIncludedIndex;
         for (int i = firstIncludedIndex + 1; i < count; i++) {
             final View view = viewGroup.getChildAt(i);
-            final String tag = (String) view.getTag();
+            final Object objTag = view.getTag();
+            final String tag = objTag instanceof String ? (String) view.getTag() : null;
             if (tag != null && tag.startsWith(tagBase)) {
                 if (tag.length() == firstViewTag.length() && tag.charAt(tag.length() - 1) == '0') {
                     return max; // Found another instance of the include
diff --git a/integration-tests/MultiModuleTestApp/app/src/main/res/layout/another_layout.xml b/integration-tests/MultiModuleTestApp/app/src/main/res/layout/another_layout.xml
index 1332347..0aaf1b5 100644
--- a/integration-tests/MultiModuleTestApp/app/src/main/res/layout/another_layout.xml
+++ b/integration-tests/MultiModuleTestApp/app/src/main/res/layout/another_layout.xml
@@ -26,6 +26,7 @@
         <TextView
                 android:text='@{userName + " " + userLastName}'
                 android:layout_width="wrap_content"
+                android:onClick="@{() -> userName.length()}"
                 android:layout_height="wrap_content"/>
     </LinearLayout>
 </layout>
\ No newline at end of file
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/java/android/databinding/testlibrary/TestLibObject.java b/integration-tests/MultiModuleTestApp/testlibrary/src/main/java/android/databinding/testlibrary/TestLibObject.java
index 8139b75..bc4baef 100644
--- a/integration-tests/MultiModuleTestApp/testlibrary/src/main/java/android/databinding/testlibrary/TestLibObject.java
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/java/android/databinding/testlibrary/TestLibObject.java
@@ -18,6 +18,7 @@
 
 import android.databinding.Bindable;
 import android.databinding.BaseObservable;
+import android.view.View;
 
 public class TestLibObject extends BaseObservable {
     @Bindable
@@ -31,4 +32,8 @@
         this.mField = field;
         notifyPropertyChanged(BR.field);
     }
+
+    public void clickHandler(View view) {
+
+    }
 }
diff --git a/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/layout/library_only_layout.xml b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/layout/library_only_layout.xml
index 6b5fc56..02821f6 100644
--- a/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/layout/library_only_layout.xml
+++ b/integration-tests/MultiModuleTestApp/testlibrary/src/main/res/layout/library_only_layout.xml
@@ -29,7 +29,8 @@
                     tools:context=".TestLibraryMainActivity">
 
         <TextView android:text="@{obj1.field}" android:layout_width="wrap_content"
-                  android:layout_height="wrap_content"/>
+                  android:layout_height="wrap_content"
+        android:onClick="{(v) -> obj1.clickHandler(v)}"/>
 
     </RelativeLayout>
 </layout>
\ No newline at end of file
diff --git a/integration-tests/TestApp/app/build.gradle b/integration-tests/TestApp/app/build.gradle
index 0701944..1d3ba68 100644
--- a/integration-tests/TestApp/app/build.gradle
+++ b/integration-tests/TestApp/app/build.gradle
@@ -10,6 +10,7 @@
         targetSdkVersion 21
         versionCode 1
         versionName "1.0"
+        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
     }
     dataBinding {
         enabled = true
@@ -41,4 +42,14 @@
 dependencies {
     compile fileTree(dir: 'libs', include: ['*.jar'])
     compile "com.android.support:support-v4:+"
+    androidTestCompile ('com.android.support.test:runner:0.4.1') {
+        exclude module: 'support-annotations'
+    }
+    androidTestCompile ('com.android.support.test.espresso:espresso-core:2.2.1') {
+        exclude module: 'support-annotations'
+    }
+    testCompile 'junit:junit:4.12'
+    androidTestCompile "org.mockito:mockito-core:1.9.5"
+    androidTestCompile "com.google.dexmaker:dexmaker:1.2"
+    androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.2"
 }
diff --git a/integration-tests/TestApp/app/src/androidTest/AndroidManifest.xml b/integration-tests/TestApp/app/src/androidTest/AndroidManifest.xml
new file mode 100644
index 0000000..e327024
--- /dev/null
+++ b/integration-tests/TestApp/app/src/androidTest/AndroidManifest.xml
@@ -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.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:tools="http://schemas.android.com/tools"
+          package="android.databinding.testapp">
+    <uses-sdk android:minSdkVersion="7" tools:overrideLibrary="android.support.test,
+                      android.app, android.support.test.rule, android.support.test.espresso,
+                      android.support.test.espresso.idling"/>
+    <application android:allowBackup="true"
+                 android:label="@string/app_name"
+    >
+        <activity android:name=".TestActivity"
+                  android:screenOrientation="portrait"/>
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/integration-tests/TestApp/app/src/androidTestApi14/java/android/databinding/testapp/RootTag.java b/integration-tests/TestApp/app/src/androidTestApi14/java/android/databinding/testapp/RootTag.java
index 132beb6..9adc8f3 100644
--- a/integration-tests/TestApp/app/src/androidTestApi14/java/android/databinding/testapp/RootTag.java
+++ b/integration-tests/TestApp/app/src/androidTestApi14/java/android/databinding/testapp/RootTag.java
@@ -15,21 +15,17 @@
  */
 package android.databinding.testapp;
 
-import android.databinding.testapp.BaseDataBinderTest;
 import android.databinding.testapp.databinding.RootTagBinding;
+import android.test.UiThreadTest;
 
 public class RootTag extends BaseDataBinderTest<RootTagBinding> {
     public RootTag() {
         super(RootTagBinding.class);
     }
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        initBinder();
-    }
-
+    @UiThreadTest
     public void testRootTagSet() throws Throwable {
+        initBinder();
         mBinder.executePendingBindings();
         assertEquals("foo", mBinder.textView1.getTag());
         assertEquals("hello world", mBinder.textView1.getText().toString());
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/BindableObservablesTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/BindableObservablesTest.java
new file mode 100644
index 0000000..07e5075
--- /dev/null
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/BindableObservablesTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.testapp;
+
+import android.annotation.TargetApi;
+import android.databinding.ObservableField;
+import android.databinding.ObservableInt;
+import android.databinding.testapp.BR;
+import android.databinding.testapp.databinding.BindableObservablesBinding;
+import android.databinding.testapp.databinding.CallbacksBinding;
+import android.databinding.testapp.vo.ViewModel;
+import android.os.Build;
+import android.support.test.runner.AndroidJUnit4;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.CoreMatchers.*;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class BindableObservablesTest {
+    @Rule
+    public DataBindingTestRule<BindableObservablesBinding> mBindingRule = new DataBindingTestRule<>(
+            R.layout.bindable_observables
+    );
+
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+    @Test
+    public void publicBinding() {
+        ViewModel model = new ViewModel();
+        model.publicObservable.set(40);
+        BindableObservablesBinding binding = mBindingRule.getBinding();
+        binding.setModel(model);
+        mBindingRule.executePending();
+        assertThat(binding.view1.getMaxLines(), is(40));
+        model.publicObservable.set(20);
+        mBindingRule.executePending();
+        assertThat(binding.view1.getMaxLines(), is(20));
+    }
+
+    @Test
+    public void fieldBinding() {
+        ViewModel model = new ViewModel();
+        model.getFieldObservable().set("abc");
+        BindableObservablesBinding binding = mBindingRule.getBinding();
+        binding.setModel(model);
+        mBindingRule.executePending();
+        assertThat(binding.view2.getText().toString(), is("abc"));
+        model.getFieldObservable().set("def");
+        mBindingRule.executePending();
+        assertThat(binding.view2.getText().toString(), is("def"));
+    }
+
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+    @Test
+    public void methodBinding() {
+        ViewModel model = new ViewModel();
+        model.getMethodObservable().set(30);
+        BindableObservablesBinding binding = mBindingRule.getBinding();
+        binding.setModel(model);
+        mBindingRule.executePending();
+        assertThat(binding.view3.getMaxLines(), is(30));
+        model.getMethodObservable().set(15);
+        mBindingRule.executePending();
+        assertThat(binding.view3.getMaxLines(), is(15));
+    }
+
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+    @Test
+    public void publicBindingChangeObservable() {
+        ViewModel model = new ViewModel();
+        model.publicObservable.set(40);
+        BindableObservablesBinding binding = mBindingRule.getBinding();
+        binding.setModel(model);
+        mBindingRule.executePending();
+        assertThat(binding.view1.getMaxLines(), is(40));
+
+        model.publicObservable = new ObservableInt(20);
+
+        mBindingRule.executePending();
+        assertThat(binding.view1.getMaxLines(), is(40));
+
+        model.notifyPropertyChanged(BR.publicObservable);
+        mBindingRule.executePending();
+        assertThat(binding.view1.getMaxLines(), is(20));
+
+    }
+
+    @Test
+    public void fieldBindingChangeObservable() {
+        ViewModel model = new ViewModel();
+        model.getFieldObservable().set("abc");
+        BindableObservablesBinding binding = mBindingRule.getBinding();
+        binding.setModel(model);
+        mBindingRule.executePending();
+        assertThat(binding.view2.getText().toString(), is("abc"));
+
+        model.setFieldObservable(new ObservableField<String>("def"));
+
+        mBindingRule.executePending();
+        assertThat(binding.view2.getText().toString(), is("abc"));
+
+        model.notifyPropertyChanged(BR.fieldObservable);
+        mBindingRule.executePending();
+        assertThat(binding.view2.getText().toString(), is("def"));
+    }
+
+    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+    @Test
+    public void methodBindingChangeObservable() {
+        ViewModel model = new ViewModel();
+        model.getMethodObservable().set(30);
+        BindableObservablesBinding binding = mBindingRule.getBinding();
+        binding.setModel(model);
+        mBindingRule.executePending();
+        assertThat(binding.view3.getMaxLines(), is(30));
+
+        model.setMethodObservable(new ObservableInt(15));
+
+        mBindingRule.executePending();
+        assertThat(binding.view3.getMaxLines(), is(30));
+
+        model.notifyPropertyChanged(BR.methodObservable);
+        mBindingRule.executePending();
+        assertThat(binding.view3.getMaxLines(), is(15));
+    }
+}
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/BracketTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/BracketTest.java
index 136b7cc..a4cda6a 100644
--- a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/BracketTest.java
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/BracketTest.java
@@ -94,7 +94,7 @@
     @UiThreadTest
     public void testBracketObj() {
         mBinder.executePendingBindings();
-        assertEquals("Hello World", mBinder.indexObj.getText().toString());
+        assertEquals("Hello World", mBinder.indexObjView.getText().toString());
         assertEquals("Hello", mBinder.sparseArrayTextObj.getText().toString());
     }
 
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/CallbackTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/CallbackTest.java
new file mode 100644
index 0000000..ca08fc9
--- /dev/null
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/CallbackTest.java
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.testapp;
+
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
+import android.annotation.TargetApi;
+import android.databinding.testapp.databinding.CallbacksBinding;
+import android.databinding.testapp.vo.CallbackBindingObject;
+import android.databinding.testapp.vo.NotBindableVo;
+import android.os.Build;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.View;
+import android.widget.ArrayAdapter;
+
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.MatcherAssert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicInteger;
+
+@RunWith(AndroidJUnit4.class)
+public class CallbackTest {
+    @Rule
+    public DataBindingTestRule<CallbacksBinding> mBindingRule = new DataBindingTestRule<>(
+            R.layout.callbacks
+    );
+
+    CallbackBindingObject mObj;
+    NotBindableVo mOther;
+    CallbacksBinding mBinding;
+
+    @Before
+    public void setup() throws Throwable {
+        mBinding = mBindingRule.getBinding();
+        mObj = mock(CallbackBindingObject.class);
+        mOther = new NotBindableVo();
+        mBinding.setObj(mObj);
+        mBinding.setOtherObj(mOther);
+        mBindingRule.executePending();
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                verifyZeroInteractions(mObj);
+            }
+        });
+
+    }
+
+    @Test
+    public void testRegularClick() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinding.view1.performClick();
+                verify(mObj, times(1)).onClick();
+                verify(mObj, never()).onClick(any(View.class));
+                verify(mObj, never()).onClickWithParam(any(NotBindableVo.class));
+                verify(mObj, never()).onClickWithParam(any(View.class), any(NotBindableVo.class));
+            }
+        });
+    }
+
+    @Test
+    public void testClickWithCallbackArg() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinding.view2.performClick();
+                verify(mObj, never()).onClick();
+                verify(mObj, times(1)).onClick(mBinding.view2);
+                verify(mObj, never()).onClickWithParam(any(NotBindableVo.class));
+                verify(mObj, never()).onClickWithParam(any(View.class), any(NotBindableVo.class));
+            }
+        });
+    }
+
+    @Test
+    public void testClickWithAnotherVariableAsArg() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinding.view3.performClick();
+                verify(mObj, never()).onClick();
+                verify(mObj, never()).onClick(any(View.class));
+                verify(mObj, times(1)).onClickWithParam(eq(mOther));
+                verify(mObj, never()).onClickWithParam(any(View.class), any(NotBindableVo.class));
+            }
+        });
+    }
+
+    @Test
+    public void testClickWithViewAndAnotherVariableAsArgs() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinding.view4.performClick();
+                verify(mObj, never()).onClick();
+                verify(mObj, never()).onClick(any(View.class));
+                verify(mObj, never()).onClickWithParam(any(NotBindableVo.class));
+                verify(mObj, times(1)).onClickWithParam(mBinding.view4, mOther);
+            }
+        });
+    }
+
+    @Test
+    public void nullObjectInCallback() throws Throwable {
+        mBinding.setObj(null);
+        mBindingRule.executePending();
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinding.view1.performClick();
+                mBinding.view2.performClick();
+                mBinding.view3.performClick();
+                mBinding.view4.performClick();
+
+                MatcherAssert.assertThat(mBinding.view1.performLongClick(), CoreMatchers.is(false));
+                MatcherAssert.assertThat(mBinding.view2.performLongClick(), CoreMatchers.is(false));
+                MatcherAssert.assertThat(mBinding.view3.performLongClick(), CoreMatchers.is(false));
+                MatcherAssert.assertThat(mBinding.view4.performLongClick(), CoreMatchers.is(false));
+
+            }
+        });
+        verifyZeroInteractions(mObj);
+    }
+
+    // long click
+    @Test
+    public void testRegularLongClick() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                when(mObj.onLongClick()).thenReturn(true);
+                MatcherAssert.assertThat(mBinding.view1.performLongClick(), CoreMatchers.is(true));
+                verify(mObj, times(1)).onLongClick();
+                verify(mObj, never()).onLongClick(any(View.class));
+                verify(mObj, never()).onLongClickWithParam(any(NotBindableVo.class));
+                verify(mObj, never()).onLongClickWithParam(any(View.class), any(NotBindableVo
+                        .class));
+            }
+        });
+    }
+
+    @Test
+    public void testLongClickWithCallbackArg() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                when(mObj.onLongClick(mBinding.view2)).thenReturn(true);
+                MatcherAssert.assertThat(mBinding.view2.performLongClick(), CoreMatchers.is(true));
+                verify(mObj, never()).onLongClick();
+                verify(mObj, times(1)).onLongClick(mBinding.view2);
+                verify(mObj, never()).onLongClickWithParam(any(NotBindableVo.class));
+                verify(mObj, never()).onLongClickWithParam(any(View.class), any(NotBindableVo
+                        .class));
+            }
+        });
+    }
+
+    @Test
+    public void testLongClickWithAnotherVariableAsArg() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                when(mObj.onLongClickWithParam(mOther)).thenReturn(true);
+                MatcherAssert.assertThat(mBinding.view3.performLongClick(), CoreMatchers.is(true));
+                verify(mObj, never()).onLongClick();
+                verify(mObj, never()).onLongClick(any(View.class));
+                verify(mObj, times(1)).onLongClickWithParam(mOther);
+                verify(mObj, never()).onLongClickWithParam(any(View.class), any(NotBindableVo
+                        .class));
+            }
+        });
+    }
+
+    @Test
+    public void testLongClickWithViewAndAnotherVariableAsArgs() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                when(mObj.onLongClickWithParam(mBinding.view4, mOther)).thenReturn(true);
+                MatcherAssert.assertThat(mBinding.view4.performLongClick(), CoreMatchers.is(true));
+                verify(mObj, never()).onLongClick();
+                verify(mObj, never()).onLongClick(any(View.class));
+                verify(mObj, never()).onLongClickWithParam(any(NotBindableVo.class));
+                verify(mObj, times(1)).onLongClickWithParam(mBinding.view4, mOther);
+            }
+        });
+    }
+
+    @Test
+    public void testListViewOnScroll() throws Throwable {
+        final CallbackBindingObject obj2 = mock(CallbackBindingObject.class);
+        mBinding.setObj2(obj2);
+        mBindingRule.executePending();
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // this is going to trigger scroll
+                mBinding.listView.setAdapter(new ArrayAdapter<>(mBinding.listView.getContext(),
+                        android.R.layout.simple_list_item_1, Arrays.asList("a", "b")));
+            }
+        });
+        mBindingRule.runOnUiThread(new Runnable() {
+            @TargetApi(Build.VERSION_CODES.KITKAT)
+            @Override
+            public void run() {
+                // setting listener also calls the callback
+                verify(obj2).onScrolled();
+            }
+        });
+    }
+
+    @Test
+    public void testProgressChange() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinding.seekBar.setProgress(20);
+                verify(mObj, times(1)).onProgressChanged(mBinding.seekBar, 20, false);
+            }
+        });
+    }
+
+    @Test
+    public void testStaticCallViaClass() throws Throwable {
+        staticCall(mBinding.view5);
+    }
+
+    @Test
+    public void testStaticCallViaInstance() throws Throwable {
+        staticCall(mBinding.view6);
+    }
+
+    @Test
+    public void testVariableOverride() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinding.view8.performClick();
+                verify(mObj).onClick(mBinding.view8);
+            }
+        });
+    }
+
+    @Test
+    public void testArrayAccess() throws Throwable {
+        final CallbackBindingObject[] objects = new CallbackBindingObject[] {
+                mock(CallbackBindingObject.class),
+                mock(CallbackBindingObject.class),
+                mock(CallbackBindingObject.class),
+        };
+        mBinding.setObjArr(objects);
+        mBindingRule.executePending();
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                verifyZeroInteractions(objects);
+                mBinding.view7.performClick();
+                verify(objects[1]).onClick(mBinding.view7);
+                mBinding.view7.performLongClick();
+                verify(objects[2]).onLongClick(mBinding.view7);
+                verifyZeroInteractions(objects[0]);
+            }
+        });
+    }
+
+    @Test
+    public void testStaticVariableFullPackage() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinding.view9.performClick();
+                verify(mObj).setVisible(View.VISIBLE);
+            }
+        });
+    }
+
+    @Test
+    public void testStaticVariableImported() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinding.view10.performClick();
+                verify(mObj).setVisible(NotBindableVo.STATIC_VAL);
+            }
+        });
+    }
+
+    @Test
+    public void testTernary1() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinding.view11.setFocusable(false);
+                mBinding.view11.performClick();
+                verify(mObj).onNotFocusable();
+                verify(mObj, never()).onFocusable();
+            }
+        });
+    }
+
+    @Test
+    public void testTernary2() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinding.view11.setFocusable(true);
+                mBinding.view11.performClick();
+                verify(mObj).onFocusable();
+                verify(mObj, never()).onNotFocusable();
+            }
+        });
+    }
+
+    @Test
+    public void testTernary3() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinding.view11.setFocusable(false);
+                when(mObj.onFocusable()).thenReturn(true, false);
+                when(mObj.onNotFocusable()).thenReturn(false, true);
+                MatcherAssert.assertThat(mBinding.view11.performLongClick(), CoreMatchers.is(false));
+                MatcherAssert.assertThat(mBinding.view11.performLongClick(), CoreMatchers.is(true));
+                mBinding.view11.setFocusable(true);
+                MatcherAssert.assertThat(mBinding.view11.performLongClick(), CoreMatchers.is(true));
+                MatcherAssert.assertThat(mBinding.view11.performLongClick(), CoreMatchers.is(false));
+            }
+        });
+    }
+
+    @Test
+    public void testTernary4() throws Throwable {
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinding.view11.setFocusable(true);
+                mBinding.view11.performClick();
+                verify(mObj).onFocusable();
+                verify(mObj, never()).onNotFocusable();
+            }
+        });
+    }
+
+    private void staticCall(final View view) throws Throwable {
+        final AtomicInteger counter = NotBindableVo.sStaticCounter;
+        final int start = counter.get();
+        mBindingRule.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                view.performClick();
+                MatcherAssert.assertThat(counter.get(), CoreMatchers.is(start + 1));
+                MatcherAssert.assertThat(view.performLongClick(), CoreMatchers.is(true));
+                MatcherAssert.assertThat(counter.get(), CoreMatchers.is(start + 2));
+            }
+        });
+    }
+}
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/DataBindingTestRule.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/DataBindingTestRule.java
new file mode 100644
index 0000000..587897d
--- /dev/null
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/DataBindingTestRule.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.testapp;
+
+import android.databinding.DataBindingUtil;
+import android.databinding.ViewDataBinding;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ActivityTestRule;
+
+/**
+ * Convenience rule for tests that use data binding.
+ * @param <T> The type of the generated binding class
+ */
+public class DataBindingTestRule<T extends ViewDataBinding>
+        extends ActivityTestRule<TestActivity> {
+    final int mLayoutId;
+    private T mBinding;
+    public DataBindingTestRule(int layoutId) {
+        super(TestActivity.class);
+        mLayoutId = layoutId;
+    }
+
+    @Override
+    protected void afterActivityLaunched() {
+        super.afterActivityLaunched();
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                mBinding = DataBindingUtil.setContentView(getActivity(), mLayoutId);
+            }
+        });
+    }
+
+    public T getBinding() {
+        return mBinding;
+    }
+
+    public void executePending() {
+        try {
+            runOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    mBinding.executePendingBindings();
+                }
+            });
+        } catch (Throwable throwable) {
+            throw new RuntimeException("unexpected problem in execute pending", throwable);
+        }
+    }
+}
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/FindMethodTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/FindMethodTest.java
index a7799dc..234ec1d 100644
--- a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/FindMethodTest.java
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/FindMethodTest.java
@@ -123,4 +123,11 @@
         assertTrue(mBinder.textView27.getTag() instanceof Integer);
         assertEquals((Integer)1, mBinder.textView27.getTag());
     }
+
+    @UiThreadTest
+    public void testFindMethodBasedOnSecondParam() throws Throwable {
+        mBinder.executePendingBindings();
+        assertEquals("2", mBinder.textView28.getText().toString());
+        assertEquals("10", mBinder.textView29.getText().toString());
+    }
 }
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/LeakTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/LeakTest.java
index 8f63bcc..5d00b66 100644
--- a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/LeakTest.java
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/LeakTest.java
@@ -19,6 +19,7 @@
 import android.widget.FrameLayout;
 
 import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 
 public class LeakTest extends ActivityInstrumentationTestCase2<TestActivity> {
     WeakReference<LeakTestBinding> mWeakReference = new WeakReference<LeakTestBinding>(null);
@@ -63,8 +64,9 @@
             }
         });
         WeakReference<Object> canary = new WeakReference<Object>(new Object());
+        ArrayList<WeakReference<byte[]>> leak = new ArrayList<>();
         while (canary.get() != null) {
-            byte[] b = new byte[1024 * 1024];
+            leak.add(new WeakReference<byte[]>(new byte[100]));
             System.gc();
         }
         assertNull(mWeakReference.get());
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/ListenerWithDotTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/ListenerWithDotTest.java
new file mode 100644
index 0000000..67b244d
--- /dev/null
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/ListenerWithDotTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.databinding.testapp;
+
+import android.databinding.ViewStubProxy;
+import android.databinding.testapp.databinding.ListenersWithDotBinding;
+import android.databinding.testapp.vo.ListenerBindingObject;
+import android.databinding.testapp.vo.ListenerBindingObject.Inner;
+import android.test.UiThreadTest;
+import android.view.View;
+
+public class ListenerWithDotTest extends BaseDataBinderTest<ListenersWithDotBinding> {
+    private ListenerBindingObject mBindingObject;
+
+    public ListenerWithDotTest() {
+        super(ListenersWithDotBinding.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        mBindingObject = new ListenerBindingObject(getActivity());
+        super.setUp();
+        initBinder(new Runnable() {
+            @Override
+            public void run() {
+                mBinder.setObj(mBindingObject);
+            }
+        });
+        ListenerBindingObject.lastClick = 0;
+    }
+
+    @UiThreadTest
+    public void testInstanceClick() throws Throwable {
+        View view = mBinder.click1;
+        assertEquals(0, ListenerBindingObject.lastClick);
+        view.callOnClick();
+        assertEquals(1, ListenerBindingObject.lastClick);
+    }
+
+    @UiThreadTest
+    public void testStaticClick() throws Throwable {
+        View view = mBinder.click2;
+        assertEquals(0, ListenerBindingObject.lastClick);
+        view.callOnClick();
+        assertEquals(2, ListenerBindingObject.lastClick);
+    }
+
+    @UiThreadTest
+    public void testInstanceClickTwoArgs() throws Throwable {
+        View view = mBinder.click3;
+        assertEquals(0, ListenerBindingObject.lastClick);
+        view.callOnClick();
+        assertEquals(3, ListenerBindingObject.lastClick);
+        assertTrue(view.isClickable());
+        ListenerBindingObject.lastClick = 0;
+        mBindingObject.clickable.set(false);
+        mBinder.executePendingBindings();
+        assertFalse(view.isClickable());
+        mBindingObject.useOne.set(true);
+        mBinder.executePendingBindings();
+        assertFalse(view.isClickable());
+        mBindingObject.clickable.set(true);
+        mBinder.executePendingBindings();
+        view.callOnClick();
+        assertEquals(1, ListenerBindingObject.lastClick);
+    }
+
+    @UiThreadTest
+    public void testStaticClickTwoArgs() throws Throwable {
+        View view = mBinder.click4;
+        assertEquals(0, ListenerBindingObject.lastClick);
+        view.callOnClick();
+        assertEquals(4, ListenerBindingObject.lastClick);
+        assertTrue(view.isClickable());
+        ListenerBindingObject.lastClick = 0;
+        mBindingObject.clickable.set(false);
+        mBinder.executePendingBindings();
+        assertFalse(view.isClickable());
+        view.setClickable(true);
+        view.callOnClick();
+        assertEquals(4, ListenerBindingObject.lastClick);
+    }
+
+    @UiThreadTest
+    public void testClickExpression() throws Throwable {
+        View view = mBinder.click5;
+        assertEquals(0, ListenerBindingObject.lastClick);
+        view.callOnClick();
+        assertEquals(2, ListenerBindingObject.lastClick);
+        ListenerBindingObject.lastClick = 0;
+        mBindingObject.useOne.set(true);
+        mBinder.executePendingBindings();
+        view.callOnClick();
+        assertEquals(1, ListenerBindingObject.lastClick);
+    }
+
+    @UiThreadTest
+    public void testInflateListener() throws Throwable {
+        ViewStubProxy viewStubProxy = mBinder.viewStub;
+        assertFalse(viewStubProxy.isInflated());
+        assertFalse(mBindingObject.inflateCalled);
+        viewStubProxy.getViewStub().inflate();
+        assertTrue(mBindingObject.inflateCalled);
+        assertTrue(viewStubProxy.isInflated());
+    }
+
+    @UiThreadTest
+    public void testBaseObservableClick() throws Throwable {
+        View view = mBinder.click6;
+        Inner inner = new Inner();
+        mBinder.setObj2(inner);
+        mBinder.executePendingBindings();
+        assertFalse(inner.clicked);
+        view.callOnClick();
+        assertTrue(inner.clicked);
+    }
+}
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TextViewBindingAdapterTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TextViewBindingAdapterTest.java
index c6bc671..83dfe72 100644
--- a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TextViewBindingAdapterTest.java
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TextViewBindingAdapterTest.java
@@ -31,6 +31,7 @@
 import android.text.method.DigitsKeyListener;
 import android.text.method.KeyListener;
 import android.text.method.TextKeyListener;
+import android.widget.EditText;
 import android.widget.TextView;
 
 public class TextViewBindingAdapterTest
@@ -315,4 +316,14 @@
                 android.R.color.holo_blue_bright);
         assertEquals(expectedColor, textView.getCurrentTextColor());
     }
+
+    @UiThreadTest
+    public void testTwoWayText() throws Throwable {
+        EditText view = mBinder.twoWayText;
+        mBindingObject.setText("Hello");
+        mBinder.executePendingBindings();
+        assertEquals("Hello", view.getText().toString());
+        view.setText("World");
+        assertEquals("World", mBindingObject.getText());
+    }
 }
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TwoWayBindingAdapterTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TwoWayBindingAdapterTest.java
new file mode 100644
index 0000000..0a1b14d
--- /dev/null
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/TwoWayBindingAdapterTest.java
@@ -0,0 +1,813 @@
+/*
+ * 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 android.databinding.testapp;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.databinding.testapp.databinding.TwoWayBinding;
+import android.databinding.testapp.vo.TwoWayBindingObject;
+import android.os.SystemClock;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.style.BackgroundColorSpan;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.TabHost.TabSpec;
+
+import java.util.Calendar;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class TwoWayBindingAdapterTest extends BaseDataBinderTest<TwoWayBinding> {
+
+    TwoWayBindingObject mBindingObject;
+
+    public TwoWayBindingAdapterTest() {
+        super(TwoWayBinding.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        initBinder(new Runnable() {
+            @Override
+            public void run() {
+                Context context = getBinder().getRoot().getContext();
+                mBindingObject = new TwoWayBindingObject(context);
+                getBinder().setObj(mBindingObject);
+                getBinder().executePendingBindings();
+            }
+        });
+    }
+
+    public void testListViewSelectedItemPosition() throws Throwable {
+        makeVisible(mBinder.listView);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(0, mBindingObject.selectedItemPosition.get());
+                assertEquals(0, mBinder.listView.getSelectedItemPosition());
+                mBinder.listView.setSelection(1);
+            }
+        });
+        long timeout = SystemClock.uptimeMillis() + 500;
+        while (mBindingObject.selectedItemPosition.get() == 0 &&
+                SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(1, mBinder.listView.getSelectedItemPosition());
+                assertEquals(1, mBindingObject.selectedItemPosition.get());
+            }
+        });
+    }
+
+    private void clickView(final View view, float offsetX) throws Throwable {
+        final int[] xy = new int[2];
+        final int[] viewSize = new int[2];
+        do {
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    view.getLocationOnScreen(xy);
+                    viewSize[0] = view.getWidth();
+                    viewSize[1] = view.getHeight();
+                }
+            });
+        } while (xy[0] < 0 || xy[1] < 0);
+
+        final float x = xy[0] + offsetX;
+        final float y = xy[1] + (viewSize[1] / 2f);
+
+        Instrumentation inst = getInstrumentation();
+
+        long downTime = SystemClock.uptimeMillis();
+        long eventTime = SystemClock.uptimeMillis();
+
+        MotionEvent event = MotionEvent.obtain(downTime, eventTime,
+                MotionEvent.ACTION_DOWN, x, y, 0);
+        inst.sendPointerSync(event);
+        inst.waitForIdleSync();
+
+        eventTime = SystemClock.uptimeMillis();
+        final int touchSlop = ViewConfiguration.get(view.getContext()).getScaledTouchSlop();
+        event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
+                x + (touchSlop / 2.0f), y + (touchSlop / 2.0f), 0);
+        inst.sendPointerSync(event);
+        inst.waitForIdleSync();
+
+        eventTime = SystemClock.uptimeMillis();
+        event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
+        inst.sendPointerSync(event);
+        inst.waitForIdleSync();
+    }
+
+    private void clickChild(View view, float offsetX) throws Throwable {
+        View childView = view;
+        while (childView != null) {
+            childView.callOnClick();
+            if (childView instanceof ViewGroup) {
+                final ViewGroup viewGroup = (ViewGroup) childView;
+                if (viewGroup.getChildCount() > 0) {
+                    childView = viewGroup.getChildAt(0);
+                } else {
+                    childView = null;
+                }
+            } else {
+                clickView(childView, offsetX);
+                childView = null;
+            }
+        }
+    }
+
+    public void testCalendarViewDate() throws Throwable {
+        makeVisible(mBinder.calendarView);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertTrue(mBindingObject.date.get() != 0);
+                assertDatesMatch(mBindingObject.date.get(), mBinder.calendarView.getDate());
+            }
+        });
+        final long[] date = new long[2];
+        float offsetX = 0;
+        long timeout = SystemClock.uptimeMillis() + 1500;
+        do {
+            // Just randomly poke at the CalendarView to set the date
+            clickChild(mBinder.calendarView, offsetX);
+            offsetX += 48;
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    date[0] = mBinder.calendarView.getDate();
+                    if (date[1] == 0) {
+                        date[1] = date[0];
+                    }
+                }
+            });
+        } while (date[0] == date[1] && SystemClock.uptimeMillis() < timeout);
+
+        timeout = SystemClock.uptimeMillis() + 100;
+        while (mBindingObject.date.get() == 0 && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        assertDatesMatch(date[0], mBindingObject.date.get());
+    }
+
+    public void assertDatesMatch(long expectedTimeMillis, long testTimeMillis) {
+        Calendar expected = Calendar.getInstance();
+        expected.setTimeInMillis(expectedTimeMillis);
+        Calendar testValue = Calendar.getInstance();
+        testValue.setTimeInMillis(testTimeMillis);
+        assertEquals(expected.get(Calendar.YEAR), testValue.get(Calendar.YEAR));
+        assertEquals(expected.get(Calendar.MONTH), testValue.get(Calendar.MONTH));
+        assertEquals(expected.get(Calendar.DAY_OF_MONTH),
+                testValue.get(Calendar.DAY_OF_MONTH));
+    }
+
+    public void testCheckBoxChecked() throws Throwable {
+        makeVisible(mBinder.checkBox);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertFalse(mBindingObject.checked.get());
+                assertFalse(mBinder.checkBox.isChecked());
+                mBinder.checkBox.setChecked(true);
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (!mBindingObject.checked.get() && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertTrue(mBinder.checkBox.isChecked());
+                assertTrue(mBindingObject.checked.get());
+            }
+        });
+    }
+
+    private boolean focusOn(final View view) throws Throwable {
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                view.requestFocus();
+            }
+        });
+        long timeout = SystemClock.uptimeMillis() + 500;
+        final boolean[] focused = new boolean[1];
+        while (SystemClock.uptimeMillis() < timeout) {
+            runTestOnUiThread(new Runnable() {
+                @Override
+                public void run() {
+                    focused[0] = view.isFocused();
+                }
+            });
+            if (focused[0]) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void testNumberPickerNumber() throws Throwable {
+        makeVisible(mBinder.textView, mBinder.numberPicker);
+        assertTrue(focusOn(mBinder.textView));
+        final EditText[] pickerText = new EditText[1];
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(1, mBindingObject.number.get());
+                assertEquals(1, mBinder.numberPicker.getValue());
+                for (int i = 0; i < mBinder.numberPicker.getChildCount(); i++) {
+                    View view = mBinder.numberPicker.getChildAt(i);
+                    if (view instanceof EditText) {
+                        pickerText[0] = (EditText) view;
+                        break;
+                    }
+                }
+            }
+        });
+        assertNotNull(pickerText[0]);
+        assertTrue(focusOn(pickerText[0]));
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                pickerText[0].setText("10");
+            }
+        });
+        assertTrue(focusOn(mBinder.textView));
+
+        final long timeout = SystemClock.uptimeMillis() + 10;
+        while (mBindingObject.number.get() == 1 && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(10, mBinder.numberPicker.getValue());
+                assertEquals(10, mBindingObject.number.get());
+            }
+        });
+    }
+
+    public void testRatingBarRating() throws Throwable {
+        makeVisible(mBinder.ratingBar);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(1f, mBindingObject.rating.get());
+                assertEquals(1f, mBinder.ratingBar.getRating());
+                mBinder.ratingBar.setRating(2.5f);
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (mBindingObject.rating.get() == 1f && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(2.5f, mBinder.ratingBar.getRating());
+                assertEquals(2.5f, mBindingObject.rating.get());
+            }
+        });
+    }
+
+    public void testSeekBarProgress() throws Throwable {
+        makeVisible(mBinder.seekBar);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(1, mBindingObject.progress.get());
+                assertEquals(1, mBinder.seekBar.getProgress());
+                mBinder.seekBar.setProgress(30);
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (mBindingObject.progress.get() == 1 && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(30, mBinder.seekBar.getProgress());
+                assertEquals(30, mBindingObject.progress.get());
+            }
+        });
+    }
+
+    public void testTabHostCurrentTab() throws Throwable {
+        makeVisible(mBinder.tabhost);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinder.tabhost.setup();
+                TabSpec tab1 = mBinder.tabhost.newTabSpec("Tab1");
+                TabSpec tab2 = mBinder.tabhost.newTabSpec("Tab2");
+
+                tab1.setIndicator("tab1");
+                tab1.setContent(R.id.foo);
+                tab2.setIndicator("tab2");
+                tab2.setContent(R.id.bar);
+                mBinder.tabhost.addTab(tab1);
+                mBinder.tabhost.addTab(tab2);
+                mBinder.tabhost.setCurrentTab(1);
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (mBindingObject.currentTab.get() == 0 && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(1, mBinder.tabhost.getCurrentTab());
+                assertEquals(1, mBindingObject.currentTab.get());
+            }
+        });
+    }
+
+    public void testTextViewText() throws Throwable {
+        makeVisible(mBinder.textView);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(null, mBindingObject.text.get());
+                assertEquals("", mBinder.textView.getText().toString());
+                mBinder.textView.setText("Hello World");
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (mBindingObject.text.get().isEmpty() && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals("Hello World", mBinder.textView.getText().toString());
+                assertEquals("Hello World", mBindingObject.text.get());
+            }
+        });
+    }
+
+    public void testDatePicker() throws Throwable {
+        makeVisible(mBinder.datePicker);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(1972, mBindingObject.year.get());
+                assertEquals(9, mBindingObject.month.get());
+                assertEquals(21, mBindingObject.day.get());
+                assertEquals(1972, mBinder.datePicker.getYear());
+                assertEquals(9, mBinder.datePicker.getMonth());
+                assertEquals(21, mBinder.datePicker.getDayOfMonth());
+                mBinder.datePicker.updateDate(2003, 4, 17);
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (mBindingObject.year.get() == 1972 && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(2003, mBindingObject.year.get());
+                assertEquals(4, mBindingObject.month.get());
+                assertEquals(17, mBindingObject.day.get());
+            }
+        });
+    }
+
+    public void testExpressions1() throws Throwable {
+        makeVisible(mBinder.expressions1);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(1972, mBindingObject.year.get());
+                assertEquals(9, mBindingObject.month.get());
+                assertEquals(21, mBindingObject.day.get());
+                assertEquals(1972000, mBinder.expressions1.getYear());
+                assertEquals(2, mBinder.expressions1.getMonth());
+                assertEquals(22, mBinder.expressions1.getDayOfMonth());
+                mBinder.expressions1.updateDate(2003000, 3, 18);
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (mBindingObject.year.get() == 1972 && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(2003, mBindingObject.year.get());
+                assertEquals(8, mBindingObject.month.get());
+                assertEquals(17, mBindingObject.day.get());
+            }
+        });
+    }
+
+    public void testExpressions2() throws Throwable {
+        makeVisible(mBinder.expressions2);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(1972, mBindingObject.year.get());
+                assertEquals(9, mBindingObject.month.get());
+                assertEquals(21, mBindingObject.day.get());
+                assertEquals(1, mBinder.expressions2.getYear());
+                assertEquals(9, mBinder.expressions2.getMonth());
+                assertEquals(21, mBinder.expressions2.getDayOfMonth());
+                mBinder.expressions2.updateDate(2, 4, 17);
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (mBindingObject.year.get() == 1972 && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(2000, mBindingObject.year.get());
+                assertEquals(4, mBindingObject.month.get());
+                assertEquals(17, mBindingObject.day.get());
+            }
+        });
+    }
+
+    public void testExpressions3() throws Throwable {
+        makeVisible(mBinder.expressions3);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals((Integer)1, mBindingObject.list.get(1));
+                assertEquals((Integer)2, mBindingObject.map.get("two"));
+                assertEquals(2, mBindingObject.array.get()[1]);
+                assertEquals(1, mBinder.expressions3.getYear());
+                assertEquals(2, mBinder.expressions3.getMonth());
+                assertEquals(2, mBinder.expressions3.getDayOfMonth());
+                mBinder.expressions3.updateDate(2003, 4, 17);
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (mBindingObject.year.get() == 1972 && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals((Integer)2003, mBindingObject.list.get(1));
+                assertEquals((Integer)4, mBindingObject.map.get("two"));
+                assertEquals(17, mBindingObject.array.get()[1]);
+            }
+        });
+    }
+
+    public void testExpressions4() throws Throwable {
+        makeVisible(mBinder.expressions4);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(1972, mBindingObject.year.get());
+                assertEquals(9, mBindingObject.month.get());
+                assertEquals(21, mBindingObject.day.get());
+                assertEquals(50, mBinder.expressions4.getYear());
+                assertEquals(5, mBinder.expressions4.getMonth());
+                assertEquals(21, mBinder.expressions4.getDayOfMonth());
+                mBinder.expressions4.updateDate(49, 4, 17);
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (mBindingObject.year.get() == 1972 && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(2040, mBindingObject.year.get());
+                assertEquals(6, mBindingObject.month.get());
+                assertEquals(17, mBindingObject.day.get());
+            }
+        });
+    }
+
+    public void testChaining() throws Throwable {
+        makeVisible(mBinder.checkBox, mBinder.checkBox2);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertTrue(mBinder.checkBox2.isChecked());
+                mBindingObject.checked.set(true);
+                mBinder.executePendingBindings();
+                assertFalse(mBinder.checkBox2.isChecked());
+            }
+        });
+    }
+
+    public void testTwoWayChaining() throws Throwable {
+        makeVisible(mBinder.checkBox3, mBinder.checkBox4);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertFalse(mBinder.checkBox3.isChecked());
+                assertTrue(mBinder.checkBox4.isChecked());
+                mBinder.checkBox3.setChecked(true);
+                mBinder.executePendingBindings();
+                assertTrue(mBinder.checkBox3.isChecked());
+                assertFalse(mBinder.checkBox4.isChecked());
+            }
+        });
+    }
+
+    public void testIncludedTwoWay1() throws Throwable {
+        makeVisible(mBinder.included.editText1, mBinder.textView);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(null, mBindingObject.text.get());
+                assertEquals("", mBinder.textView.getText().toString());
+                assertEquals("", mBinder.included.editText1.getText().toString());
+                mBinder.included.editText1.setText("Hello World");
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (mBindingObject.text.get().isEmpty() && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals("Hello World", mBinder.included.editText1.getText().toString());
+                assertEquals("Hello World", mBinder.textView.getText().toString());
+                assertEquals("Hello World", mBindingObject.text.get());
+            }
+        });
+    }
+
+    public void testIncludedTwoWay2() throws Throwable {
+        makeVisible(mBinder.included.editText2, mBinder.textView);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(null, mBindingObject.text.get());
+                assertEquals("", mBinder.textView.getText().toString());
+                assertEquals("", mBinder.included.editText2.getText().toString());
+                mBinder.included.editText2.setText("Hello World");
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (mBindingObject.text.get().isEmpty() && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals("Hello World", mBinder.included.editText2.getText().toString());
+                assertEquals("Hello World", mBinder.textView.getText().toString());
+                assertEquals("Hello World", mBindingObject.text.get());
+            }
+        });
+    }
+
+    public void testNoEditableLoop() throws Throwable {
+        makeVisible(mBinder.editText1, mBinder.editText2);
+
+        final SpannableString text = new SpannableString("Hello World Also");
+        BackgroundColorSpan highlight = new BackgroundColorSpan(0xFFFFFF80);
+        text.setSpan(highlight, 0, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+
+        mBindingObject.textLatch = new CountDownLatch(2);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals("", mBinder.editText1.getText().toString());
+                assertEquals(0, mBindingObject.text1Changes);
+                assertEquals(0, mBindingObject.text2Changes);
+
+                // Change the text of one of the controls
+                mBinder.editText1.setText("Hello World");
+            }
+        });
+
+        assertTrue(mBindingObject.textLatch.await(500, TimeUnit.MILLISECONDS));
+        mBindingObject.textLatch = new CountDownLatch(2);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertNotNull(mBindingObject.editText.get());
+                assertEquals("Hello World", mBindingObject.editText.get().toString());
+                // They should both be set
+                assertEquals(1, mBindingObject.text1Changes);
+                assertEquals(1, mBindingObject.text2Changes);
+
+                // Edit the span, but the text remains the same.
+                mBinder.editText2.setText(text);
+            }
+        });
+
+        assertTrue(mBindingObject.textLatch.await(500, TimeUnit.MILLISECONDS));
+        mBindingObject.textLatch = new CountDownLatch(1);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // The one control should notify a change, but not the other.
+                assertEquals(2, mBindingObject.text1Changes);
+                assertEquals(2, mBindingObject.text2Changes);
+
+                // No more changes should occur
+                mBinder.executePendingBindings();
+            }
+        });
+
+        assertFalse(mBindingObject.textLatch.await(200, TimeUnit.MILLISECONDS));
+        mBindingObject.textLatch = new CountDownLatch(2);
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                // Nothing changed:
+                assertEquals(2, mBindingObject.text1Changes);
+                assertEquals(2, mBindingObject.text2Changes);
+
+                // Now try changing the value to the same thing. Because the
+                // value is Spannable, it will set it to the EditText
+                // and then get back a String in the onTextChanged.
+                mBindingObject.editText.set(text);
+            }
+        });
+
+        assertTrue(mBindingObject.textLatch.await(500, TimeUnit.MILLISECONDS));
+
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                assertEquals(3, mBindingObject.text1Changes);
+                assertEquals(3, mBindingObject.text2Changes);
+                assertEquals("Hello World Also", mBindingObject.editText.get());
+            }
+        });
+    }
+
+    public void testStringConversions() throws Throwable {
+        makeVisible(mBinder.convertBool, mBinder.convertByte, mBinder.convertShort,
+                mBinder.convertInt, mBinder.convertLong, mBinder.convertFloat,
+                mBinder.convertDouble, mBinder.convertChar);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinder.convertBool.setText("True");
+                mBinder.convertByte.setText("123");
+                mBinder.convertShort.setText("1234");
+                mBinder.convertInt.setText("12345");
+                mBinder.convertLong.setText("123456");
+                mBinder.convertFloat.setText("1.2345");
+                mBinder.convertDouble.setText("1.23456");
+                mBinder.convertChar.setText("a");
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (!mBindingObject.booleanField.get() && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+        getInstrumentation().waitForIdleSync();
+        assertTrue(mBindingObject.booleanField.get());
+        assertEquals(123, mBindingObject.byteField.get());
+        assertEquals(1234, mBindingObject.shortField.get());
+        assertEquals(12345, mBindingObject.intField.get());
+        assertEquals(123456, mBindingObject.longField.get());
+        assertEquals(1.2345f, mBindingObject.floatField.get(), 0.0001f);
+        assertEquals(1.23456, mBindingObject.doubleField.get(), 0.000001);
+        assertEquals('a', mBindingObject.charField.get());
+    }
+
+    public void testBadStringConversions() throws Throwable {
+        makeVisible(mBinder.convertBool, mBinder.convertByte, mBinder.convertShort,
+                mBinder.convertInt, mBinder.convertLong, mBinder.convertFloat,
+                mBinder.convertDouble, mBinder.convertChar);
+        mBindingObject.booleanField.set(true);
+        mBindingObject.charField.set('1');
+        mBindingObject.byteField.set((byte) 1);
+        mBindingObject.shortField.set((short) 12);
+        mBindingObject.intField.set(123);
+        mBindingObject.longField.set(1234);
+        mBindingObject.floatField.set(1.2345f);
+        mBindingObject.doubleField.set(1.23456);
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinder.executePendingBindings();
+                mBinder.convertBool.setText("foobar");
+                mBinder.convertByte.setText("fred");
+                mBinder.convertShort.setText("wilma");
+                mBinder.convertInt.setText("barney");
+                mBinder.convertLong.setText("betty");
+                mBinder.convertFloat.setText("pebbles");
+                mBinder.convertDouble.setText("bam-bam");
+                mBinder.convertChar.setText("");
+            }
+        });
+
+        final long timeout = SystemClock.uptimeMillis() + 500;
+        while (mBindingObject.booleanField.get() && SystemClock.uptimeMillis() < timeout) {
+            Thread.sleep(1);
+        }
+        getInstrumentation().waitForIdleSync();
+        assertFalse(mBindingObject.booleanField.get());
+        assertEquals(1, mBindingObject.byteField.get());
+        assertEquals(12, mBindingObject.shortField.get());
+        assertEquals(123, mBindingObject.intField.get());
+        assertEquals(1234, mBindingObject.longField.get());
+        assertEquals(1.2345f, mBindingObject.floatField.get(), 0.0001f);
+        assertEquals(1.23456, mBindingObject.doubleField.get(), 0.00001);
+        assertEquals('1', mBindingObject.charField.get());
+    }
+
+    private void makeVisible(final View... views) throws Throwable {
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                mBinder.calendarView.setVisibility(View.GONE);
+                mBinder.listView.setVisibility(View.GONE);
+                mBinder.checkBox.setVisibility(View.GONE);
+                mBinder.numberPicker.setVisibility(View.GONE);
+                mBinder.ratingBar.setVisibility(View.GONE);
+                mBinder.seekBar.setVisibility(View.GONE);
+                mBinder.tabhost.setVisibility(View.GONE);
+                mBinder.textView.setVisibility(View.GONE);
+                mBinder.timePicker.setVisibility(View.GONE);
+                mBinder.datePicker.setVisibility(View.GONE);
+                mBinder.expressions1.setVisibility(View.GONE);
+                mBinder.expressions2.setVisibility(View.GONE);
+                mBinder.expressions3.setVisibility(View.GONE);
+                mBinder.expressions4.setVisibility(View.GONE);
+                mBinder.checkBox2.setVisibility(View.GONE);
+                mBinder.checkBox3.setVisibility(View.GONE);
+                mBinder.checkBox4.setVisibility(View.GONE);
+                mBinder.editText1.setVisibility(View.GONE);
+                mBinder.editText2.setVisibility(View.GONE);
+                mBinder.included.editText1.setVisibility(View.GONE);
+                mBinder.included.editText2.setVisibility(View.GONE);
+                mBinder.convertBool.setVisibility(View.GONE);
+                mBinder.convertByte.setVisibility(View.GONE);
+                mBinder.convertShort.setVisibility(View.GONE);
+                mBinder.convertInt.setVisibility(View.GONE);
+                mBinder.convertLong.setVisibility(View.GONE);
+                mBinder.convertFloat.setVisibility(View.GONE);
+                mBinder.convertDouble.setVisibility(View.GONE);
+                mBinder.convertChar.setVisibility(View.GONE);
+                for (View view : views) {
+                    view.setVisibility(View.VISIBLE);
+                }
+            }
+        });
+        getInstrumentation().waitForIdleSync();
+    }
+}
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/multiconfig/LandscapeConfigTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/multiconfig/LandscapeConfigTest.java
index ddda269..e3fc74f 100644
--- a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/multiconfig/LandscapeConfigTest.java
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/multiconfig/LandscapeConfigTest.java
@@ -34,9 +34,15 @@
         super(MultiResLayoutBinding.class, ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
     }
 
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        initBinder();
+        getInstrumentation().waitForIdleSync();
+    }
+
     public void testSharedViewIdAndVariableInheritance()
             throws InterruptedException, NoSuchMethodException, NoSuchFieldException {
-        initBinder();
         assertEquals("MultiResLayoutBindingLandImpl", mBinder.getClass().getSimpleName());
         assertPublicField(TextView.class, "objectInLandTextView");
         assertPublicField(TextView.class, "objectInDefaultTextView");
@@ -54,7 +60,6 @@
 
     @UiThreadTest
     public void testSetVariable() throws Throwable {
-        initBinder();
         assertTrue(mBinder.setVariable(BR.objectInBoth, null));
         assertTrue(mBinder.setVariable(BR.objectInDefault, null));
         assertTrue(mBinder.setVariable(BR.objectInLand, null));
diff --git a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/multiconfig/PortraitConfigTest.java b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/multiconfig/PortraitConfigTest.java
index 6a259bb..bcc2c4c 100644
--- a/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/multiconfig/PortraitConfigTest.java
+++ b/integration-tests/TestApp/app/src/androidTestApi7/java/android/databinding/testapp/multiconfig/PortraitConfigTest.java
@@ -33,9 +33,15 @@
         super(MultiResLayoutBinding.class, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
     }
 
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        initBinder();
+        getInstrumentation().waitForIdleSync();
+    }
+
     public void testSharedViewIdAndVariableInheritance()
             throws InterruptedException, NoSuchMethodException, NoSuchFieldException {
-        initBinder();
         assertEquals("MultiResLayoutBindingImpl", mBinder.getClass().getSimpleName());
         assertPublicField(TextView.class, "objectInLandTextView");
         assertPublicField(TextView.class, "objectInDefaultTextView");
@@ -52,7 +58,6 @@
 
     @UiThreadTest
     public void testSetVariable() throws Throwable {
-        initBinder();
         assertTrue(mBinder.setVariable(BR.objectInBoth, null));
         assertTrue(mBinder.setVariable(BR.objectInDefault, null));
         assertFalse(mBinder.setVariable(BR.obj, null));
diff --git a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/adapter/CustomNamespaceAdapter.java b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/adapter/CustomNamespaceAdapter.java
index 9b8d8be..1888bb0 100644
--- a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/adapter/CustomNamespaceAdapter.java
+++ b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/adapter/CustomNamespaceAdapter.java
@@ -24,7 +24,7 @@
         view.setText(value);
     }
 
-    @BindingAdapter({"bind:set2"})
+    @BindingAdapter({"set2"})
     public static void setTwo(TextView view, String value) {
         view.setText(value);
     }
diff --git a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/CallbackBindingObject.java b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/CallbackBindingObject.java
new file mode 100644
index 0000000..8ff88e6
--- /dev/null
+++ b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/CallbackBindingObject.java
@@ -0,0 +1,70 @@
+/*
+ * 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 android.databinding.testapp.vo;
+
+import android.content.Context;
+import android.databinding.BaseObservable;
+import android.databinding.ObservableBoolean;
+import android.graphics.Outline;
+import android.media.MediaPlayer;
+import android.text.Editable;
+import android.view.ContextMenu;
+import android.view.DragEvent;
+import android.view.KeyEvent;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewStub;
+import android.view.WindowInsets;
+import android.view.animation.Animation;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.CalendarView;
+import android.widget.Chronometer;
+import android.widget.CompoundButton;
+import android.widget.ExpandableListView;
+import android.widget.NumberPicker;
+import android.widget.RadioGroup;
+import android.widget.RatingBar;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.TimePicker;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+public interface CallbackBindingObject {
+    void onClick();
+    void onClick(View view);
+    boolean onLongClick();
+    boolean onLongClick(View view);
+    boolean onClickWithParam(NotBindableVo other);
+    boolean onClickWithParam(View view, NotBindableVo other);
+    boolean onLongClickWithParam(NotBindableVo other);
+    boolean onLongClickWithParam(View view, NotBindableVo other);
+    void onScrolled();
+    void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser);
+
+    void setVisible(int visible);
+    boolean onFocusable();
+    boolean onNotFocusable();
+
+    void beforeTextChanged(CharSequence s, int start, int count, int after);
+
+    void onTextChanged(CharSequence s, int start, int before, int count);
+
+    void beforeTextChanged();
+    void onTextChanged();
+}
diff --git a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/FindMethodBindingObject.java b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/FindMethodBindingObject.java
index 515a341..452ddcf 100644
--- a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/FindMethodBindingObject.java
+++ b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/FindMethodBindingObject.java
@@ -16,7 +16,6 @@
 package android.databinding.testapp.vo;
 
 import android.databinding.BaseObservable;
-import android.databinding.Bindable;
 import android.databinding.ObservableField;
 import android.databinding.testapp.BR;
 import android.util.ArrayMap;
@@ -67,6 +66,18 @@
         return vals;
     }
 
+    public int argsClose(int i, String j) {
+        return i;
+    }
+
+    public float argsClose(int i, short j) {
+        return i;
+    }
+
+    public int argsClose(int i, int j) {
+        return j;
+    }
+
     public static class Foo {
         public final String bar = "hello world";
         public static final String baz = "hello world";
diff --git a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/NotBindableVo.java b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/NotBindableVo.java
index 64d1a48..cfb52eb 100644
--- a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/NotBindableVo.java
+++ b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/NotBindableVo.java
@@ -13,7 +13,12 @@
 
 package android.databinding.testapp.vo;
 
+import android.view.View;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
 public class NotBindableVo {
+    public static int STATIC_VAL = 101;
     private int mIntValue;
     private int mIntValueGetCount;
     private boolean mBoolValue;
@@ -22,6 +27,7 @@
     private int mStringValueGetCount;
     private final String mFinalString = "this has final content";
     public final int publicField = 3;
+    public static AtomicInteger sStaticCounter = new AtomicInteger();
 
     public NotBindableVo() {
     }
@@ -85,4 +91,9 @@
     public int getStringValueGetCount() {
         return mStringValueGetCount;
     }
+
+    public static boolean incStaticCounter() {
+        sStaticCounter.incrementAndGet();
+        return true;
+    }
 }
diff --git a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TextViewBindingObject.java b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TextViewBindingObject.java
index b1d04b6..f57638b 100644
--- a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TextViewBindingObject.java
+++ b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TextViewBindingObject.java
@@ -123,6 +123,9 @@
     @Bindable
     private float mTextSize = 10f;
 
+    @Bindable
+    private String mText;
+
     public TextView.BufferType getBufferType() {
         return mBufferType;
     }
@@ -252,6 +255,15 @@
         return mTextAllCaps;
     }
 
+    public String getText() {
+        return mText;
+    }
+
+    public void setText(String text) {
+        mText = text;
+        notifyPropertyChanged(BR.text);
+    }
+
     public void changeValues() {
         mAutoLink = Linkify.EMAIL_ADDRESSES;
         mDrawablePadding = 10;
diff --git a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TwoWayBindingObject.java b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TwoWayBindingObject.java
new file mode 100644
index 0000000..f3adbdd
--- /dev/null
+++ b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/TwoWayBindingObject.java
@@ -0,0 +1,91 @@
+/*
+ * 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 android.databinding.testapp.vo;
+
+import android.content.Context;
+import android.databinding.ObservableArrayList;
+import android.databinding.ObservableArrayMap;
+import android.databinding.ObservableBoolean;
+import android.databinding.ObservableByte;
+import android.databinding.ObservableChar;
+import android.databinding.ObservableDouble;
+import android.databinding.ObservableField;
+import android.databinding.ObservableFloat;
+import android.databinding.ObservableInt;
+import android.databinding.ObservableLong;
+import android.databinding.ObservableShort;
+import android.widget.ArrayAdapter;
+import android.widget.ListAdapter;
+
+import java.util.concurrent.CountDownLatch;
+
+public class TwoWayBindingObject {
+    private static final String[] VALUES = {
+            "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"
+    };
+    public final ListAdapter adapter;
+    public final ObservableInt selectedItemPosition = new ObservableInt();
+    public final ObservableLong date = new ObservableLong(System.currentTimeMillis());
+    public final ObservableBoolean checked = new ObservableBoolean();
+    public final ObservableInt number = new ObservableInt(1);
+    public final ObservableFloat rating = new ObservableFloat(1);
+    public final ObservableInt progress = new ObservableInt(1);
+    public final ObservableInt currentTab = new ObservableInt();
+    public final ObservableField<String> text = new ObservableField<>();
+    public final ObservableInt hour = new ObservableInt();
+    public final ObservableInt minute = new ObservableInt();
+    public final ObservableInt year = new ObservableInt(1972);
+    public final ObservableInt month = new ObservableInt(9);
+    public final ObservableInt day = new ObservableInt(21);
+    public final ObservableArrayList<Integer> list = new ObservableArrayList<>();
+    public final ObservableArrayMap<String, Integer> map = new ObservableArrayMap<>();
+    public final ObservableField<int[]> array = new ObservableField<>();
+    public final ObservableField<CharSequence> editText = new ObservableField<>();
+    public final ObservableBoolean booleanField = new ObservableBoolean();
+    public final ObservableByte byteField = new ObservableByte();
+    public final ObservableShort shortField = new ObservableShort();
+    public final ObservableInt intField = new ObservableInt();
+    public final ObservableLong longField = new ObservableLong();
+    public final ObservableFloat floatField = new ObservableFloat();
+    public final ObservableDouble doubleField = new ObservableDouble();
+    public final ObservableChar charField = new ObservableChar();
+    public int text1Changes;
+    public int text2Changes;
+    public CountDownLatch textLatch;
+
+    public TwoWayBindingObject(Context context) {
+        this.adapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, VALUES);
+        int[] arr = new int[10];
+        for (int i = 0; i < 10; i++) {
+            list.add(i);
+            arr[i] = i + 1;
+        }
+        array.set(arr);
+        for (int i = 0; i < VALUES.length; i++) {
+            map.put(VALUES[i], i + 1);
+        }
+    }
+
+    public void textChanged1(CharSequence s, int start, int before, int count) {
+        text1Changes++;
+        textLatch.countDown();
+    }
+
+    public void textChanged2(CharSequence s, int start, int before, int count) {
+        text2Changes++;
+        textLatch.countDown();
+    }
+}
diff --git a/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/ViewModel.java b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/ViewModel.java
new file mode 100644
index 0000000..2454fb9
--- /dev/null
+++ b/integration-tests/TestApp/app/src/main/java/android/databinding/testapp/vo/ViewModel.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.databinding.testapp.vo;
+
+import android.databinding.BaseObservable;
+import android.databinding.Bindable;
+import android.databinding.ObservableField;
+import android.databinding.ObservableInt;
+
+public class ViewModel extends BaseObservable {
+    @Bindable
+    public ObservableInt publicObservable = new ObservableInt();
+
+    @Bindable
+    private ObservableField<String> fieldObservable = new ObservableField<>();
+
+    private ObservableInt methodObservable = new ObservableInt();
+
+
+    public ObservableField<String> getFieldObservable() {
+        return fieldObservable;
+    }
+
+    @Bindable
+    public ObservableInt getMethodObservable() {
+        return methodObservable;
+    }
+
+    public void setFieldObservable(ObservableField<String> fieldObservable) {
+        this.fieldObservable = fieldObservable;
+    }
+
+    public void setMethodObservable(ObservableInt methodObservable) {
+        this.methodObservable = methodObservable;
+    }
+}
diff --git a/integration-tests/TestApp/app/src/main/res/layout/bindable_observables.xml b/integration-tests/TestApp/app/src/main/res/layout/bindable_observables.xml
new file mode 100644
index 0000000..c325a23
--- /dev/null
+++ b/integration-tests/TestApp/app/src/main/res/layout/bindable_observables.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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.
+  -->
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+    <data>
+        <variable name="model" type="android.databinding.testapp.vo.ViewModel"/>
+    </data>
+    <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="vertical">
+        <TextView android:id="@+id/view1" android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:maxLines="@{model.publicObservable}"/>
+        <TextView android:id="@+id/view2" android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:text="@{model.fieldObservable}"/>
+        <TextView android:id="@+id/view3" android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:maxLines="@{model.methodObservable}"/>
+
+    </FrameLayout>
+</layout>
diff --git a/integration-tests/TestApp/app/src/main/res/layout/bracket_test.xml b/integration-tests/TestApp/app/src/main/res/layout/bracket_test.xml
index e9a0e2f..04beb94 100644
--- a/integration-tests/TestApp/app/src/main/res/layout/bracket_test.xml
+++ b/integration-tests/TestApp/app/src/main/res/layout/bracket_test.xml
@@ -35,7 +35,7 @@
 
         <TextView android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
-                  android:id="@+id/indexObj"
+                  android:id="@+id/indexObjView"
                   android:text="@{array[indexObj]}"/>
 
         <TextView android:layout_width="wrap_content"
diff --git a/integration-tests/TestApp/app/src/main/res/layout/callbacks.xml b/integration-tests/TestApp/app/src/main/res/layout/callbacks.xml
new file mode 100644
index 0000000..f312ec6
--- /dev/null
+++ b/integration-tests/TestApp/app/src/main/res/layout/callbacks.xml
@@ -0,0 +1,109 @@
+<?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.
+  -->
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:app="http://schemas.android.com/apk/res-auto">
+    <data>
+        <import type="android.databinding.testapp.vo.NotBindableVo"/>
+        <variable name="otherObj" type="android.databinding.testapp.vo.NotBindableVo"/>
+        <variable name="obj" type="android.databinding.testapp.vo.CallbackBindingObject"/>
+        <variable name="obj2" type="android.databinding.testapp.vo.CallbackBindingObject"/>
+        <variable name="objArr" type="android.databinding.testapp.vo.CallbackBindingObject[]"/>
+    </data>
+    <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+        <View
+                android:id="@+id/view1"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="@{() -> obj.onClick()}"
+                android:onLongClick="@{() -> obj.onLongClick()}"
+                />
+        <View
+                android:id="@+id/view2"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="@{(v) -> obj.onClick(v)}"
+                android:onLongClick="@{(view) -> obj.onLongClick(view)}"
+        />
+
+        <View
+                android:id="@+id/view3"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="@{(v) -> obj.onClickWithParam(otherObj)}"
+                android:onLongClick="@{(view) -> obj.onLongClickWithParam(otherObj)}"
+        />
+
+        <View
+                android:id="@+id/view4"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="@{(v) -> obj.onClickWithParam(v, otherObj)}"
+                android:onLongClick="@{(view) -> obj.onLongClickWithParam(view, otherObj)}"
+        />
+
+        <!-- via adapter and also multiple params -->
+        <ListView
+                android:id="@+id/listView"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onScroll="@{() -> obj2.onScrolled()}"/>
+
+        <SeekBar
+                 android:id="@+id/seekBar"
+                 android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                 android:onProgressChanged="@{(seekBar, progress, fromUser) -> obj.onProgressChanged(seekBar, progress, fromUser)}"
+        />
+        <View
+                android:id="@+id/view5"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="@{(v) -> NotBindableVo.incStaticCounter()}"
+                android:onLongClick="@{(v) -> NotBindableVo.incStaticCounter()}"
+        />
+        <View
+                android:id="@+id/view6"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="@{(v) -> otherObj.incStaticCounter()}"
+                android:onLongClick="@{(v) -> otherObj.incStaticCounter()}"
+        />
+        <View android:layout_width="wrap_content" android:layout_height="wrap_content"
+              android:id="@+id/view7"
+              android:onClick="@{(v) -> objArr[1].onClick(v)}"
+              android:onLongClick="@{(view) -> objArr[2].onLongClick(view)}"/>
+
+        <!--variable override-->
+        <View android:layout_width="wrap_content" android:layout_height="match_parent"
+              android:id="@+id/view8"
+              android:onClick="@{(objArr) -> obj.onClick(objArr)}"/>
+
+        <View android:layout_width="wrap_content" android:layout_height="match_parent"
+              android:id="@+id/view9"
+              android:onClick="@{(v) -> obj.setVisible(android.view.View.VISIBLE)}"/>
+
+        <View android:layout_width="wrap_content" android:layout_height="match_parent"
+              android:id="@+id/view10"
+              android:onClick="@{(v) -> obj.setVisible(NotBindableVo.STATIC_VAL)}"/>
+
+        <View android:layout_width="wrap_content" android:layout_height="match_parent"
+              android:id="@+id/view11"
+              android:onClick="@{(v) -> v.focusable ? obj.onFocusable() : obj.onNotFocusable()}"
+              android:onLongClick="@{(v) -> v.focusable ? obj.onFocusable() : obj.onNotFocusable()}"/>
+    </LinearLayout>
+</layout>
\ No newline at end of file
diff --git a/integration-tests/TestApp/app/src/main/res/layout/conditional_binding.xml b/integration-tests/TestApp/app/src/main/res/layout/conditional_binding.xml
index 675c37c..3f6c64e 100644
--- a/integration-tests/TestApp/app/src/main/res/layout/conditional_binding.xml
+++ b/integration-tests/TestApp/app/src/main/res/layout/conditional_binding.xml
@@ -43,6 +43,6 @@
                 android:id="@+id/view1"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:onClick="@{cond1 ? obj4.clicked : null}"/>
+                android:onClick="@{cond1 ? obj4::clicked : null}"/>
     </LinearLayout>
 </layout>
\ No newline at end of file
diff --git a/integration-tests/TestApp/app/src/main/res/layout/find_method_test.xml b/integration-tests/TestApp/app/src/main/res/layout/find_method_test.xml
index 509517f..cc5a2c6 100644
--- a/integration-tests/TestApp/app/src/main/res/layout/find_method_test.xml
+++ b/integration-tests/TestApp/app/src/main/res/layout/find_method_test.xml
@@ -139,5 +139,15 @@
                 android:id="@+id/textView27"
                 android:layout_width="wrap_content" android:layout_height="wrap_content"
                 app:tag="@{1}"/>
+        <TextView
+                android:id="@+id/textView28"
+                android:layout_width="wrap_content" android:layout_height="wrap_content"
+                android:text="@{`` + ((Integer)obj.argsClose(1, 2))}"
+        />
+        <TextView
+                android:id="@+id/textView29"
+                android:layout_width="wrap_content" android:layout_height="wrap_content"
+                android:text="@{`` + ((Integer)obj.argsClose(10, `Hello World`))}"
+        />
     </LinearLayout>
 </layout>
\ No newline at end of file
diff --git a/integration-tests/TestApp/app/src/main/res/layout/listeners.xml b/integration-tests/TestApp/app/src/main/res/layout/listeners.xml
index 00a26ff..89572ac 100644
--- a/integration-tests/TestApp/app/src/main/res/layout/listeners.xml
+++ b/integration-tests/TestApp/app/src/main/res/layout/listeners.xml
@@ -26,289 +26,289 @@
         <ListView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:onMovedToScrapHeap="@{obj.onMovedToScrapHeap}"
-                android:onScroll="@{obj.onScroll}"
-                android:onScrollStateChanged="@{obj.onScrollStateChanged}"
-                android:onItemClick="@{obj.onItemClick}"
-                android:onItemLongClick="@{obj.onItemLongClick}"
-                android:onItemSelected="@{obj.onItemSelected}"
-                android:onNothingSelected="@{obj.onNothingSelected}"
+                android:onMovedToScrapHeap="@{obj::onMovedToScrapHeap}"
+                android:onScroll="@{obj::onScroll}"
+                android:onScrollStateChanged="@{obj::onScrollStateChanged}"
+                android:onItemClick="@{obj::onItemClick}"
+                android:onItemLongClick="@{obj::onItemLongClick}"
+                android:onItemSelected="@{obj::onItemSelected}"
+                android:onNothingSelected="@{obj::onNothingSelected}"
                 />
         <ListView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:onScroll="@{obj.onScroll}"
-                android:onItemSelected="@{obj.onItemSelected}"
+                android:onScroll="@{obj::onScroll}"
+                android:onItemSelected="@{obj::onItemSelected}"
                 />
         <ListView
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:onScrollStateChanged="@{obj.onScrollStateChanged}"
-                android:onNothingSelected="@{obj.onNothingSelected}"
+                android:onScrollStateChanged="@{obj::onScrollStateChanged}"
+                android:onNothingSelected="@{obj::onNothingSelected}"
                 />
         <ActionMenuView android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
-                        android:onMenuItemClick="@{obj.onMenuItemClick}"
+                        android:onMenuItemClick="@{obj::onMenuItemClick}"
                 />
         <AutoCompleteTextView android:layout_width="wrap_content"
                               android:layout_height="wrap_content"
-                              android:onDismiss="@{obj.onDismiss}"
-                              android:onItemClick="@{obj.onItemClick}"
-                              android:fixText="@{obj.fixText}"
-                              android:isValid="@{obj.isValid}"
-                              android:onItemSelected="@{obj.onItemSelected}"
-                              android:onNothingSelected="@{obj.onNothingSelected}"
+                              android:onDismiss="@{obj::onDismiss}"
+                              android:onItemClick="@{obj::onItemClick}"
+                              android:fixText="@{obj::fixText}"
+                              android:isValid="@{obj::isValid}"
+                              android:onItemSelected="@{obj::onItemSelected}"
+                              android:onNothingSelected="@{obj::onNothingSelected}"
                 />
         <AutoCompleteTextView android:layout_width="wrap_content"
                               android:layout_height="wrap_content"
-                              android:isValid="@{obj.isValid}"
-                              android:onItemSelected="@{obj.onItemSelected}"
+                              android:isValid="@{obj::isValid}"
+                              android:onItemSelected="@{obj::onItemSelected}"
                 />
         <AutoCompleteTextView android:layout_width="wrap_content"
                               android:layout_height="wrap_content"
-                              android:fixText="@{obj.fixText}"
-                              android:onNothingSelected="@{obj.onNothingSelected}"
+                              android:fixText="@{obj::fixText}"
+                              android:onNothingSelected="@{obj::onNothingSelected}"
                 />
         <CalendarView android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
-                      android:onSelectedDayChange="@{obj.onSelectedDayChange}"
+                      android:onSelectedDayChange="@{obj::onSelectedDayChange}"
                 />
         <Chronometer android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
-                     android:onChronometerTick="@{obj.onChronometerTick}"
+                     android:onChronometerTick="@{obj::onChronometerTick}"
                 />
         <CheckBox android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
-                  android:onCheckedChanged="@{obj.onCheckedChanged}"
+                  android:onCheckedChanged="@{obj::onCheckedChanged}"
                 />
         <ExpandableListView android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
-                            android:onChildClick="@{obj.onChildClick}"
-                            android:onGroupClick="@{obj.onGroupClick}"
-                            android:onGroupCollapse="@{obj.onGroupCollapse}"
-                            android:onGroupExpand="@{obj.onGroupExpand}"
-                            android:onItemClick="@{obj.onItemClick}"
+                            android:onChildClick="@{obj::onChildClick}"
+                            android:onGroupClick="@{obj::onGroupClick}"
+                            android:onGroupCollapse="@{obj::onGroupCollapse}"
+                            android:onGroupExpand="@{obj::onGroupExpand}"
+                            android:onItemClick="@{obj::onItemClick}"
                 />
         <NumberPicker android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
-                      android:format="@{obj.format}"
-                      android:onValueChange="@{obj.onValueChange}"
-                      android:onScrollStateChange="@{obj.onScrollStateChange}"
+                      android:format="@{obj::format}"
+                      android:onValueChange="@{obj::onValueChange}"
+                      android:onScrollStateChange="@{obj::onScrollStateChange}"
                 />
         <RadioGroup android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:onCheckedChanged="@{obj.onCheckedChanged}"
+                    android:onCheckedChanged="@{obj::onCheckedChanged}"
                 />
         <RatingBar android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
-                   android:onRatingChanged="@{obj.onRatingChanged}"
+                   android:onRatingChanged="@{obj::onRatingChanged}"
                 />
         <SearchView android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:onClose="@{obj.onClose}"
-                    android:onQueryTextChange="@{obj.onQueryTextChange}"
-                    android:onQueryTextSubmit="@{obj.onQueryTextSubmit}"
-                    android:onSuggestionClick="@{obj.onSuggestionClick}"
-                    android:onSuggestionSelect="@{obj.onSuggestionSelect}"
+                    android:onClose="@{obj::onClose}"
+                    android:onQueryTextChange="@{obj::onQueryTextChange}"
+                    android:onQueryTextSubmit="@{obj::onQueryTextSubmit}"
+                    android:onSuggestionClick="@{obj::onSuggestionClick}"
+                    android:onSuggestionSelect="@{obj::onSuggestionSelect}"
                 />
         <SearchView android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:onQueryTextSubmit="@{obj.onQueryTextSubmit}"
-                    android:onSuggestionClick="@{obj.onSuggestionClick}"
+                    android:onQueryTextSubmit="@{obj::onQueryTextSubmit}"
+                    android:onSuggestionClick="@{obj::onSuggestionClick}"
                 />
         <SearchView android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:onQueryTextChange="@{obj.onQueryTextChange}"
-                    android:onSuggestionClick="@{obj.onSuggestionClick}"
+                    android:onQueryTextChange="@{obj::onQueryTextChange}"
+                    android:onSuggestionClick="@{obj::onSuggestionClick}"
                 />
         <SeekBar android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
-                 android:onProgressChanged="@{obj.onProgressChanged}"
-                 android:onStartTrackingTouch="@{obj.onStartTrackingTouch}"
-                 android:onStopTrackingTouch="@{obj.onStopTrackingTouch}"
+                 android:onProgressChanged="@{obj::onProgressChanged}"
+                 android:onStartTrackingTouch="@{obj::onStartTrackingTouch}"
+                 android:onStopTrackingTouch="@{obj::onStopTrackingTouch}"
                 />
         <SeekBar android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
-                 android:onStartTrackingTouch="@{obj.onStartTrackingTouch}"
-                 android:onStopTrackingTouch="@{obj.onStopTrackingTouch}"
+                 android:onStartTrackingTouch="@{obj::onStartTrackingTouch}"
+                 android:onStopTrackingTouch="@{obj::onStopTrackingTouch}"
                 />
         <SeekBar android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
-                 android:onProgressChanged="@{obj.onProgressChanged}"
-                 android:onStopTrackingTouch="@{obj.onStopTrackingTouch}"
+                 android:onProgressChanged="@{obj::onProgressChanged}"
+                 android:onStopTrackingTouch="@{obj::onStopTrackingTouch}"
                 />
         <SeekBar android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
-                 android:onProgressChanged="@{obj.onProgressChanged}"
-                 android:onStartTrackingTouch="@{obj.onStartTrackingTouch}"
+                 android:onProgressChanged="@{obj::onProgressChanged}"
+                 android:onStartTrackingTouch="@{obj::onStartTrackingTouch}"
                 />
         <SeekBar android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
-                 android:onProgressChanged="@{obj.onProgressChanged}"
+                 android:onProgressChanged="@{obj::onProgressChanged}"
                 />
         <SeekBar android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
-                 android:onStartTrackingTouch="@{obj.onStartTrackingTouch}"
+                 android:onStartTrackingTouch="@{obj::onStartTrackingTouch}"
                 />
         <SeekBar android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
-                 android:onStopTrackingTouch="@{obj.onStopTrackingTouch}"
+                 android:onStopTrackingTouch="@{obj::onStopTrackingTouch}"
                 />
         <TabHost android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
-                 android:onTabChanged="@{obj.onTabChanged}"
+                 android:onTabChanged="@{obj::onTabChanged}"
                 />
         <TextView android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
-                  android:onEditorAction="@{obj.onEditorAction}"
-                  android:afterTextChanged="@{obj.afterTextChanged}"
-                  android:beforeTextChanged="@{obj.beforeTextChanged}"
-                  android:onTextChanged="@{obj.onTextChanged}"
+                  android:onEditorAction="@{obj::onEditorAction}"
+                  android:afterTextChanged="@{obj::afterTextChanged}"
+                  android:beforeTextChanged="@{obj::beforeTextChanged}"
+                  android:onTextChanged="@{obj::onTextChanged}"
                 />
         <TextView android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
-                  android:beforeTextChanged="@{obj.beforeTextChanged}"
-                  android:onTextChanged="@{obj.onTextChanged}"
+                  android:beforeTextChanged="@{obj::beforeTextChanged}"
+                  android:onTextChanged="@{obj::onTextChanged}"
                 />
         <TextView android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
-                  android:afterTextChanged="@{obj.afterTextChanged}"
-                  android:onTextChanged="@{obj.onTextChanged}"
+                  android:afterTextChanged="@{obj::afterTextChanged}"
+                  android:onTextChanged="@{obj::onTextChanged}"
                 />
         <TextView android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
-                  android:afterTextChanged="@{obj.afterTextChanged}"
-                  android:beforeTextChanged="@{obj.beforeTextChanged}"
+                  android:afterTextChanged="@{obj::afterTextChanged}"
+                  android:beforeTextChanged="@{obj::beforeTextChanged}"
                 />
         <TextView android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
-                  android:onTextChanged="@{obj.onTextChanged}"
+                  android:onTextChanged="@{obj::onTextChanged}"
                 />
         <TextView android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
-                  android:beforeTextChanged="@{obj.beforeTextChanged}"
+                  android:beforeTextChanged="@{obj::beforeTextChanged}"
                 />
         <TextView android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
-                  android:afterTextChanged="@{obj.afterTextChanged}"
+                  android:afterTextChanged="@{obj::afterTextChanged}"
                 />
         <TimePicker android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:onTimeChanged="@{obj.onTimeChanged}"
+                    android:onTimeChanged="@{obj::onTimeChanged}"
                 />
         <Toolbar android:layout_width="wrap_content"
                  android:layout_height="wrap_content"
-                 android:onMenuItemClick="@{obj.onMenuItemClick}"
-                 android:onNavigationClick="@{obj.onClick}"
+                 android:onMenuItemClick="@{obj::onMenuItemClick}"
+                 android:onNavigationClick="@{obj::onClick}"
                 />
         <VideoView android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
-                   android:onCompletion="@{obj.onCompletion}"
-                   android:onError="@{obj.onError}"
-                   android:onInfo="@{obj.onInfo}"
-                   android:onPrepared="@{obj.onPrepared}"
+                   android:onCompletion="@{obj::onCompletion}"
+                   android:onError="@{obj::onError}"
+                   android:onInfo="@{obj::onInfo}"
+                   android:onPrepared="@{obj::onPrepared}"
                 />
         <View android:layout_width="wrap_content"
               android:layout_height="wrap_content"
-              android:onApplyWindowInsets="@{obj.onApplyWindowInsets}"
-              android:onCreateContextMenu="@{obj.onCreateContextMenu}"
-              android:onDrag="@{obj.onDrag}"
-              android:onFocusChange="@{obj.onFocusChange}"
-              android:onGenericMotion="@{obj.onGenericMotion}"
-              android:onHover="@{obj.onHover}"
-              android:onKey="@{obj.onKey}"
-              android:onLongClick="@{obj.onLongClick}"
-              android:onClick="@{obj.onClick}"
-              android:onSystemUiVisibilityChange="@{obj.onSystemUiVisibilityChange}"
-              android:onTouch="@{obj.onTouch}"
-              android:getOutline="@{obj.getOutline}"
-              android:onViewAttachedToWindow="@{obj.onViewAttachedToWindow}"
-              android:onViewDetachedFromWindow="@{obj.onViewDetachedFromWindow}"
+              android:onApplyWindowInsets="@{obj::onApplyWindowInsets}"
+              android:onCreateContextMenu="@{obj::onCreateContextMenu}"
+              android:onDrag="@{obj::onDrag}"
+              android:onFocusChange="@{obj::onFocusChange}"
+              android:onGenericMotion="@{obj::onGenericMotion}"
+              android:onHover="@{obj::onHover}"
+              android:onKey="@{obj::onKey}"
+              android:onLongClick="@{obj::onLongClick}"
+              android:onClick="@{obj::onClick}"
+              android:onSystemUiVisibilityChange="@{obj::onSystemUiVisibilityChange}"
+              android:onTouch="@{obj::onTouch}"
+              android:getOutline="@{obj::getOutline}"
+              android:onViewAttachedToWindow="@{obj::onViewAttachedToWindow}"
+              android:onViewDetachedFromWindow="@{obj::onViewDetachedFromWindow}"
               android:clickable="@{true}"
               android:longClickable="@{true}"
                 />
         <View android:layout_width="wrap_content"
               android:layout_height="wrap_content"
-              android:onClick="@{obj.onClick}"
-              android:onLongClick="@{obj.onLongClick}"
-              android:onViewAttachedToWindow="@{obj.onViewAttachedToWindow}"
+              android:onClick="@{obj::onClick}"
+              android:onLongClick="@{obj::onLongClick}"
+              android:onViewAttachedToWindow="@{obj::onViewAttachedToWindow}"
                 />
         <View android:layout_width="wrap_content"
               android:layout_height="wrap_content"
-              android:onViewDetachedFromWindow="@{obj.onViewDetachedFromWindow}"
+              android:onViewDetachedFromWindow="@{obj::onViewDetachedFromWindow}"
                 />
         <FrameLayout android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
-                     android:onChildViewAdded="@{obj.onChildViewAdded}"
-                     android:onChildViewRemoved="@{obj.onChildViewRemoved}"
-                     android:onAnimationEnd="@{obj.onAnimationEnd}"
-                     android:onAnimationStart="@{obj.onAnimationStart}"
-                     android:onAnimationRepeat="@{obj.onAnimationRepeat}"
+                     android:onChildViewAdded="@{obj::onChildViewAdded}"
+                     android:onChildViewRemoved="@{obj::onChildViewRemoved}"
+                     android:onAnimationEnd="@{obj::onAnimationEnd}"
+                     android:onAnimationStart="@{obj::onAnimationStart}"
+                     android:onAnimationRepeat="@{obj::onAnimationRepeat}"
                 />
         <FrameLayout android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
-                     android:onChildViewRemoved="@{obj.onChildViewRemoved}"
-                     android:onAnimationStart="@{obj.onAnimationStart}"
-                     android:onAnimationRepeat="@{obj.onAnimationRepeat}"
+                     android:onChildViewRemoved="@{obj::onChildViewRemoved}"
+                     android:onAnimationStart="@{obj::onAnimationStart}"
+                     android:onAnimationRepeat="@{obj::onAnimationRepeat}"
                 />
         <FrameLayout android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
-                     android:onChildViewAdded="@{obj.onChildViewAdded}"
-                     android:onAnimationEnd="@{obj.onAnimationEnd}"
-                     android:onAnimationRepeat="@{obj.onAnimationRepeat}"
+                     android:onChildViewAdded="@{obj::onChildViewAdded}"
+                     android:onAnimationEnd="@{obj::onAnimationEnd}"
+                     android:onAnimationRepeat="@{obj::onAnimationRepeat}"
                 />
         <FrameLayout android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
-                     android:onAnimationEnd="@{obj.onAnimationEnd}"
-                     android:onAnimationStart="@{obj.onAnimationStart}"
+                     android:onAnimationEnd="@{obj::onAnimationEnd}"
+                     android:onAnimationStart="@{obj::onAnimationStart}"
                 />
         <FrameLayout android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
-                     android:onAnimationEnd="@{obj.onAnimationEnd}"
+                     android:onAnimationEnd="@{obj::onAnimationEnd}"
                 />
         <FrameLayout android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
-                     android:onAnimationStart="@{obj.onAnimationStart}"
+                     android:onAnimationStart="@{obj::onAnimationStart}"
                 />
         <FrameLayout android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
-                     android:onAnimationRepeat="@{obj.onAnimationRepeat}"
+                     android:onAnimationRepeat="@{obj::onAnimationRepeat}"
                 />
         <ViewStub android:layout_width="wrap_content"
                   android:layout_height="wrap_content"
                   android:id="@+id/viewStub"
-                  android:onInflate="@{obj.onInflate}"
+                  android:onInflate="@{obj::onInflate}"
                   android:layout="@layout/plain_layout"
                 />
         <ZoomControls android:layout_width="wrap_content"
                       android:layout_height="wrap_content"
-                      android:onZoomIn="@{obj.onClick}"
-                      android:onZoomOut="@{obj.onClick}"
+                      android:onZoomIn="@{obj::onClick}"
+                      android:onZoomOut="@{obj::onClick}"
                 />
         <View android:id="@+id/click1"
-              android:onClick="@{obj.onClick1}"
+              android:onClick="@{obj::onClick1}"
               android:layout_width="10dp"
               android:layout_height="10dp"
                 />
         <View android:id="@+id/click2"
-              android:onClick="@{ListenerBindingObject.onClick2}"
+              android:onClick="@{ListenerBindingObject::onClick2}"
               android:layout_width="10dp"
               android:layout_height="10dp"
                 />
         <View android:id="@+id/click3"
-              android:onClick="@{obj.useOne ? obj.onClick1 : obj.onClick3}"
+              android:onClick="@{obj.useOne ? obj::onClick1 : obj::onClick3}"
               android:clickable="@{obj.clickable}"
               android:layout_width="10dp"
               android:layout_height="10dp"
                 />
         <View android:id="@+id/click4"
-              android:onClick="@{ListenerBindingObject.onClick4}"
+              android:onClick="@{ListenerBindingObject::onClick4}"
               android:clickable="@{obj.clickable}"
               android:layout_width="10dp"
               android:layout_height="10dp"
                 />
         <View android:id="@+id/click5"
-              android:onClick="@{obj.useOne ? obj.onClick1 : ListenerBindingObject.onClick2}"
+              android:onClick="@{obj.useOne ? obj::onClick1 : ListenerBindingObject::onClick2}"
               android:layout_width="10dp"
               android:layout_height="10dp"
                 />
@@ -316,26 +316,26 @@
         <View android:id="@+id/listener1"
               android:layout_width="10dp"
               android:layout_height="10dp"
-              android:onFoo="@{obj.onFoo}"
-              android:onFoo2="@{obj.onFoo}"
+              android:onFoo="@{obj::onFoo}"
+              android:onFoo2="@{obj::onFoo}"
                 />
         <View android:id="@+id/listener2"
               android:layout_width="10dp"
               android:layout_height="10dp"
-              android:onBar1="@{obj.onBar}"
-              android:onBar2="@{obj.onBar}"
+              android:onBar1="@{obj::onBar}"
+              android:onBar2="@{obj::onBar}"
                 />
         <View android:id="@+id/click6"
               android:layout_width="10dp"
               android:layout_height="10dp"
-              android:onClick="@{obj2.onClick}"
+              android:onClick="@{obj2::onClick}"
                 />
         <View android:id="@+id/click7"
               android:layout_width="10dp"
               android:layout_height="10dp"
               app:fooId="@{1}"
               app:barId="@{2}"
-              app:runnable="@{obj.runnableRun}"
+              app:runnable="@{obj::runnableRun}"
                 />
     </LinearLayout>
 </layout>
\ No newline at end of file
diff --git a/integration-tests/TestApp/app/src/main/res/layout/listeners_with_dot.xml b/integration-tests/TestApp/app/src/main/res/layout/listeners_with_dot.xml
new file mode 100644
index 0000000..e9e6145
--- /dev/null
+++ b/integration-tests/TestApp/app/src/main/res/layout/listeners_with_dot.xml
@@ -0,0 +1,344 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2016 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.
+  -->
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:app="http://schemas.android.com/apk/res-auto">
+    <data>
+        <variable name="obj" type="android.databinding.testapp.vo.ListenerBindingObject"/>
+        <variable name="obj2" type="android.databinding.testapp.vo.ListenerBindingObject.Inner"/>
+        <import type="android.databinding.testapp.vo.ListenerBindingObject"/>
+    </data>
+    <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+        <ListView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onMovedToScrapHeap="@{obj.onMovedToScrapHeap}"
+                android:onScroll="@{obj.onScroll}"
+                android:onScrollStateChanged="@{obj.onScrollStateChanged}"
+                android:onItemClick="@{obj.onItemClick}"
+                android:onItemLongClick="@{obj.onItemLongClick}"
+                android:onItemSelected="@{obj.onItemSelected}"
+                android:onNothingSelected="@{obj.onNothingSelected}"
+                />
+        <ListView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onScroll="@{obj.onScroll}"
+                android:onItemSelected="@{obj.onItemSelected}"
+                />
+        <ListView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onScrollStateChanged="@{obj.onScrollStateChanged}"
+                android:onNothingSelected="@{obj.onNothingSelected}"
+                />
+        <ActionMenuView android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:onMenuItemClick="@{obj.onMenuItemClick}"
+                />
+        <AutoCompleteTextView android:layout_width="wrap_content"
+                              android:layout_height="wrap_content"
+                              android:onDismiss="@{obj.onDismiss}"
+                              android:onItemClick="@{obj.onItemClick}"
+                              android:fixText="@{obj.fixText}"
+                              android:isValid="@{obj.isValid}"
+                              android:onItemSelected="@{obj.onItemSelected}"
+                              android:onNothingSelected="@{obj.onNothingSelected}"
+                />
+        <AutoCompleteTextView android:layout_width="wrap_content"
+                              android:layout_height="wrap_content"
+                              android:isValid="@{obj.isValid}"
+                              android:onItemSelected="@{obj.onItemSelected}"
+                />
+        <AutoCompleteTextView android:layout_width="wrap_content"
+                              android:layout_height="wrap_content"
+                              android:fixText="@{obj.fixText}"
+                              android:onNothingSelected="@{obj.onNothingSelected}"
+                />
+        <CalendarView android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:onSelectedDayChange="@{obj.onSelectedDayChange}"
+                />
+        <Chronometer android:layout_width="wrap_content"
+                     android:layout_height="wrap_content"
+                     android:onChronometerTick="@{obj.onChronometerTick}"
+                />
+        <CheckBox android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:onCheckedChanged="@{obj.onCheckedChanged}"
+                />
+        <ExpandableListView android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:onChildClick="@{obj.onChildClick}"
+                            android:onGroupClick="@{obj.onGroupClick}"
+                            android:onGroupCollapse="@{obj.onGroupCollapse}"
+                            android:onGroupExpand="@{obj.onGroupExpand}"
+                            android:onItemClick="@{obj.onItemClick}"
+                />
+        <NumberPicker android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:format="@{obj.format}"
+                      android:onValueChange="@{obj.onValueChange}"
+                      android:onScrollStateChange="@{obj.onScrollStateChange}"
+                />
+        <RadioGroup android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:onCheckedChanged="@{obj.onCheckedChanged}"
+                />
+        <RatingBar android:layout_width="wrap_content"
+                   android:layout_height="wrap_content"
+                   android:onRatingChanged="@{obj.onRatingChanged}"
+                />
+        <SearchView android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:onClose="@{obj.onClose}"
+                    android:onQueryTextChange="@{obj.onQueryTextChange}"
+                    android:onQueryTextSubmit="@{obj.onQueryTextSubmit}"
+                    android:onSuggestionClick="@{obj.onSuggestionClick}"
+                    android:onSuggestionSelect="@{obj.onSuggestionSelect}"
+                />
+        <SearchView android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:onQueryTextSubmit="@{obj.onQueryTextSubmit}"
+                    android:onSuggestionClick="@{obj.onSuggestionClick}"
+                />
+        <SearchView android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:onQueryTextChange="@{obj.onQueryTextChange}"
+                    android:onSuggestionClick="@{obj.onSuggestionClick}"
+                />
+        <SeekBar android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                 android:onProgressChanged="@{obj.onProgressChanged}"
+                 android:onStartTrackingTouch="@{obj.onStartTrackingTouch}"
+                 android:onStopTrackingTouch="@{obj.onStopTrackingTouch}"
+                />
+        <SeekBar android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                 android:onStartTrackingTouch="@{obj.onStartTrackingTouch}"
+                 android:onStopTrackingTouch="@{obj.onStopTrackingTouch}"
+                />
+        <SeekBar android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                 android:onProgressChanged="@{obj.onProgressChanged}"
+                 android:onStopTrackingTouch="@{obj.onStopTrackingTouch}"
+                />
+        <SeekBar android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                 android:onProgressChanged="@{obj.onProgressChanged}"
+                 android:onStartTrackingTouch="@{obj.onStartTrackingTouch}"
+                />
+        <SeekBar android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                 android:onProgressChanged="@{obj.onProgressChanged}"
+                />
+        <SeekBar android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                 android:onStartTrackingTouch="@{obj.onStartTrackingTouch}"
+                />
+        <SeekBar android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                 android:onStopTrackingTouch="@{obj.onStopTrackingTouch}"
+                />
+        <TabHost android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                 android:onTabChanged="@{obj.onTabChanged}"
+                />
+        <TextView android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:onEditorAction="@{obj.onEditorAction}"
+                  android:afterTextChanged="@{obj.afterTextChanged}"
+                  android:beforeTextChanged="@{obj.beforeTextChanged}"
+                  android:onTextChanged="@{obj.onTextChanged}"
+                />
+        <TextView android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:beforeTextChanged="@{obj.beforeTextChanged}"
+                  android:onTextChanged="@{obj.onTextChanged}"
+                />
+        <TextView android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:afterTextChanged="@{obj.afterTextChanged}"
+                  android:onTextChanged="@{obj.onTextChanged}"
+                />
+        <TextView android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:afterTextChanged="@{obj.afterTextChanged}"
+                  android:beforeTextChanged="@{obj.beforeTextChanged}"
+                />
+        <TextView android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:onTextChanged="@{obj.onTextChanged}"
+                />
+        <TextView android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:beforeTextChanged="@{obj.beforeTextChanged}"
+                />
+        <TextView android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:afterTextChanged="@{obj.afterTextChanged}"
+                />
+        <TimePicker android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:onTimeChanged="@{obj.onTimeChanged}"
+                />
+        <Toolbar android:layout_width="wrap_content"
+                 android:layout_height="wrap_content"
+                 android:onMenuItemClick="@{obj.onMenuItemClick}"
+                 android:onNavigationClick="@{obj.onClick}"
+                />
+        <VideoView android:layout_width="wrap_content"
+                   android:layout_height="wrap_content"
+                   android:onCompletion="@{obj.onCompletion}"
+                   android:onError="@{obj.onError}"
+                   android:onInfo="@{obj.onInfo}"
+                   android:onPrepared="@{obj.onPrepared}"
+                />
+        <View android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:onApplyWindowInsets="@{obj.onApplyWindowInsets}"
+              android:onCreateContextMenu="@{obj.onCreateContextMenu}"
+              android:onDrag="@{obj.onDrag}"
+              android:onFocusChange="@{obj.onFocusChange}"
+              android:onGenericMotion="@{obj.onGenericMotion}"
+              android:onHover="@{obj.onHover}"
+              android:onKey="@{obj.onKey}"
+              android:onLongClick="@{obj.onLongClick}"
+              android:onClick="@{obj.onClick}"
+              android:onSystemUiVisibilityChange="@{obj.onSystemUiVisibilityChange}"
+              android:onTouch="@{obj.onTouch}"
+              android:getOutline="@{obj.getOutline}"
+              android:onViewAttachedToWindow="@{obj.onViewAttachedToWindow}"
+              android:onViewDetachedFromWindow="@{obj.onViewDetachedFromWindow}"
+              android:clickable="@{true}"
+              android:longClickable="@{true}"
+                />
+        <View android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:onClick="@{obj.onClick}"
+              android:onLongClick="@{obj.onLongClick}"
+              android:onViewAttachedToWindow="@{obj.onViewAttachedToWindow}"
+                />
+        <View android:layout_width="wrap_content"
+              android:layout_height="wrap_content"
+              android:onViewDetachedFromWindow="@{obj.onViewDetachedFromWindow}"
+                />
+        <FrameLayout android:layout_width="wrap_content"
+                     android:layout_height="wrap_content"
+                     android:onChildViewAdded="@{obj.onChildViewAdded}"
+                     android:onChildViewRemoved="@{obj.onChildViewRemoved}"
+                     android:onAnimationEnd="@{obj.onAnimationEnd}"
+                     android:onAnimationStart="@{obj.onAnimationStart}"
+                     android:onAnimationRepeat="@{obj.onAnimationRepeat}"
+                />
+        <FrameLayout android:layout_width="wrap_content"
+                     android:layout_height="wrap_content"
+                     android:onChildViewRemoved="@{obj.onChildViewRemoved}"
+                     android:onAnimationStart="@{obj.onAnimationStart}"
+                     android:onAnimationRepeat="@{obj.onAnimationRepeat}"
+                />
+        <FrameLayout android:layout_width="wrap_content"
+                     android:layout_height="wrap_content"
+                     android:onChildViewAdded="@{obj.onChildViewAdded}"
+                     android:onAnimationEnd="@{obj.onAnimationEnd}"
+                     android:onAnimationRepeat="@{obj.onAnimationRepeat}"
+                />
+        <FrameLayout android:layout_width="wrap_content"
+                     android:layout_height="wrap_content"
+                     android:onAnimationEnd="@{obj.onAnimationEnd}"
+                     android:onAnimationStart="@{obj.onAnimationStart}"
+                />
+        <FrameLayout android:layout_width="wrap_content"
+                     android:layout_height="wrap_content"
+                     android:onAnimationEnd="@{obj.onAnimationEnd}"
+                />
+        <FrameLayout android:layout_width="wrap_content"
+                     android:layout_height="wrap_content"
+                     android:onAnimationStart="@{obj.onAnimationStart}"
+                />
+        <FrameLayout android:layout_width="wrap_content"
+                     android:layout_height="wrap_content"
+                     android:onAnimationRepeat="@{obj.onAnimationRepeat}"
+                />
+        <ViewStub android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:id="@+id/viewStub"
+                  android:onInflate="@{obj.onInflate}"
+                  android:layout="@layout/plain_layout"
+                />
+        <ZoomControls android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:onZoomIn="@{obj.onClick}"
+                      android:onZoomOut="@{obj.onClick}"
+                />
+        <View android:id="@+id/click1"
+              android:onClick="@{obj.onClick1}"
+              android:layout_width="10dp"
+              android:layout_height="10dp"
+                />
+        <View android:id="@+id/click2"
+              android:onClick="@{ListenerBindingObject.onClick2}"
+              android:layout_width="10dp"
+              android:layout_height="10dp"
+                />
+        <View android:id="@+id/click3"
+              android:onClick="@{obj.useOne ? obj.onClick1 : obj.onClick3}"
+              android:clickable="@{obj.clickable}"
+              android:layout_width="10dp"
+              android:layout_height="10dp"
+                />
+        <View android:id="@+id/click4"
+              android:onClick="@{ListenerBindingObject.onClick4}"
+              android:clickable="@{obj.clickable}"
+              android:layout_width="10dp"
+              android:layout_height="10dp"
+                />
+        <View android:id="@+id/click5"
+              android:onClick="@{obj.useOne ? obj.onClick1 : ListenerBindingObject.onClick2}"
+              android:layout_width="10dp"
+              android:layout_height="10dp"
+                />
+
+        <View android:id="@+id/listener1"
+              android:layout_width="10dp"
+              android:layout_height="10dp"
+              android:onFoo="@{obj.onFoo}"
+              android:onFoo2="@{obj.onFoo}"
+                />
+        <View android:id="@+id/listener2"
+              android:layout_width="10dp"
+              android:layout_height="10dp"
+              android:onBar1="@{obj.onBar}"
+              android:onBar2="@{obj.onBar}"
+                />
+        <View android:id="@+id/click6"
+              android:layout_width="10dp"
+              android:layout_height="10dp"
+              android:onClick="@{obj2.onClick}"
+                />
+        <View android:id="@+id/click7"
+              android:layout_width="10dp"
+              android:layout_height="10dp"
+              app:fooId="@{1}"
+              app:barId="@{2}"
+              app:runnable="@{obj.runnableRun}"
+                />
+    </LinearLayout>
+</layout>
\ No newline at end of file
diff --git a/integration-tests/TestApp/app/src/main/res/layout/text_view_adapter_test.xml b/integration-tests/TestApp/app/src/main/res/layout/text_view_adapter_test.xml
index 43b11da..12aa6ed 100644
--- a/integration-tests/TestApp/app/src/main/res/layout/text_view_adapter_test.xml
+++ b/integration-tests/TestApp/app/src/main/res/layout/text_view_adapter_test.xml
@@ -87,6 +87,10 @@
         <TextView android:layout_width="match_parent" android:layout_height="match_parent"
                   android:id="@+id/textWithColor"
                   android:textColor="@{@android:color/holo_blue_bright}"
-        />
+                />
+        <EditText android:layout_width="match_parent" android:layout_height="match_parent"
+                  android:id="@+id/twoWayText"
+                  android:text="@={obj.text}"
+                />
     </LinearLayout>
-</layout>
\ No newline at end of file
+</layout>
diff --git a/integration-tests/TestApp/app/src/main/res/layout/two_way.xml b/integration-tests/TestApp/app/src/main/res/layout/two_way.xml
new file mode 100644
index 0000000..ad12d58
--- /dev/null
+++ b/integration-tests/TestApp/app/src/main/res/layout/two_way.xml
@@ -0,0 +1,223 @@
+<?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.
+  -->
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+    <data>
+        <variable name="obj" type="android.databinding.testapp.vo.TwoWayBindingObject"/>
+    </data>
+    <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+        <CalendarView
+                android:id="@+id/calendarView"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:date="@={obj.date}"
+        />
+        <ListView
+                android:id="@+id/listView"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:selectedItemPosition="@={obj.selectedItemPosition}"
+                android:adapter="@{obj.adapter}"
+        />
+        <CheckBox
+                android:id="@+id/checkBox"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:checked="@={obj.checked}"
+                android:text="Check Box"
+        />
+        <NumberPicker
+                android:id="@+id/numberPicker"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:value="@={obj.number}"
+                android:minValue="@{1}"
+                android:maxValue="@{100}"
+        />
+        <RatingBar
+                android:id="@+id/ratingBar"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:rating="@={obj.rating}"
+                android:numStars="5"
+        />
+        <SeekBar
+                android:id="@+id/seekBar"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:max="100"
+                android:progress="@={obj.progress}"
+        />
+        <TabHost
+                android:id="@android:id/tabhost"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:currentTab="@={obj.currentTab}">
+            <LinearLayout
+                    android:orientation="vertical"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent">
+                <TabWidget
+                        android:id="@android:id/tabs"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"/>
+                <FrameLayout
+                        android:id="@android:id/tabcontent"
+                        android:layout_width="match_parent"
+                        android:layout_height="match_parent">
+                    <View
+                            android:id="@+id/foo"
+                            android:layout_width="10dp"
+                            android:layout_height="10dp"/>
+                    <View
+                            android:id="@+id/bar"
+                            android:layout_width="10dp"
+                            android:layout_height="10dp"/>
+                </FrameLayout>
+            </LinearLayout>
+        </TabHost>
+        <EditText
+                android:id="@+id/textView"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@={obj.text}"
+        />
+        <TimePicker
+                android:id="@+id/timePicker"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:hour="@={obj.hour}"
+                android:minute="@={obj.minute}"
+        />
+        <DatePicker
+                android:id="@+id/datePicker"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:year="@={obj.year}"
+                android:month="@={obj.month}"
+                android:day="@={obj.day}"/>
+        <DatePicker
+                android:id="@+id/expressions1"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:year="@={obj.year * @integer/oneThousand}"
+                android:month="@={11 - obj.month}"
+                android:day="@={obj.day + 1}"/>
+        <DatePicker
+                android:id="@+id/expressions2"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:year="@={obj.year / @integer/oneThousand}"
+                android:month="@={@bool/alwaysTrue ? obj.month : obj.day}"
+                android:day="@={@bool/alwaysFalse ? obj.month : obj.day}"/>
+        <DatePicker
+                android:id="@+id/expressions3"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:year="@={obj.list[@integer/one]}"
+                android:month="@={obj.map[`two`]}"
+                android:day="@={obj.array[1]}"/>
+        <DatePicker
+                android:id="@+id/expressions4"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:year="@={(int)(100000f/obj.year)}"
+                android:month="@={1 + (obj.month / 2)}"
+                android:day="@={true ? obj.day : obj.month}"/>
+        <CheckBox
+                android:id="@+id/checkBox2"
+                android:checked="@{!checkBox.checked}"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+        <CheckBox
+                android:id="@+id/checkBox3"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+        <CheckBox
+                android:id="@+id/checkBox4"
+                android:checked="@{!checkBox3.checked}"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+        <include
+                android:id="@+id/included"
+                layout="@layout/two_way_included"
+                android:obj="@{obj}"
+                android:text="@={obj.text}"/>
+        <EditText
+                android:id="@+id/editText1"
+                android:text="@={obj.editText}"
+                android:bufferType="editable"
+                android:onTextChanged="@{obj::textChanged1}"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+        <EditText
+                android:id="@+id/editText2"
+                android:text="@={obj.editText}"
+                android:bufferType="editable"
+                android:onTextChanged="@{obj::textChanged2}"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+        <EditText
+                android:id="@+id/convertBool"
+                android:text="@={`` + obj.booleanField}"
+                android:inputType="number"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+        <EditText
+                android:id="@+id/convertByte"
+                android:text="@={`` + obj.byteField}"
+                android:inputType="number"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+        <EditText
+                android:id="@+id/convertShort"
+                android:text="@={`` + obj.shortField}"
+                android:inputType="number"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+        <EditText
+                android:id="@+id/convertInt"
+                android:text="@={`` + obj.intField}"
+                android:inputType="number"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+        <EditText
+                android:id="@+id/convertLong"
+                android:text="@={`` + obj.longField}"
+                android:inputType="number"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+        <EditText
+                android:id="@+id/convertFloat"
+                android:text="@={`` + obj.floatField}"
+                android:inputType="numberDecimal"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+        <EditText
+                android:id="@+id/convertDouble"
+                android:text="@={`` + obj.doubleField}"
+                android:inputType="numberDecimal"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+        <EditText
+                android:id="@+id/convertChar"
+                android:text="@={`` + obj.charField}"
+                android:inputType="number"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"/>
+    </LinearLayout>
+</layout>
diff --git a/integration-tests/TestApp/app/src/main/res/layout/two_way_included.xml b/integration-tests/TestApp/app/src/main/res/layout/two_way_included.xml
new file mode 100644
index 0000000..a1a02e0
--- /dev/null
+++ b/integration-tests/TestApp/app/src/main/res/layout/two_way_included.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+    <data>
+        <variable name="text" type="String"/>
+        <variable name="obj" type="android.databinding.testapp.vo.TwoWayBindingObject"/>
+    </data>
+    <LinearLayout
+            android:orientation="vertical"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+        <EditText
+                android:id="@+id/editText1"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@={text}"/>
+        <EditText
+                android:id="@+id/editText2"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@={obj.text}"/>
+    </LinearLayout>
+</layout>
\ No newline at end of file
diff --git a/integration-tests/TestApp/app/src/main/res/layout/view_stub.xml b/integration-tests/TestApp/app/src/main/res/layout/view_stub.xml
index 322c966..b6af0fa 100644
--- a/integration-tests/TestApp/app/src/main/res/layout/view_stub.xml
+++ b/integration-tests/TestApp/app/src/main/res/layout/view_stub.xml
@@ -12,11 +12,9 @@
             xmlns:bind="http://schemas.android.com/apk/res-auto">
         <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
                   android:text="@{firstName}"
-                  android:id="@+id/firstName"
                 />
         <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
                   android:text="@{lastName}"
-                  android:id="@+id/lastName"
                 />
 
         <ViewStub android:layout_width="match_parent" android:layout_height="match_parent"
diff --git a/integration-tests/TestApp/app/src/main/res/values/integers.xml b/integration-tests/TestApp/app/src/main/res/values/integers.xml
new file mode 100644
index 0000000..b56db93
--- /dev/null
+++ b/integration-tests/TestApp/app/src/main/res/values/integers.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <integer name="oneThousand">1000</integer>
+    <integer name="one">1</integer>
+</resources>
\ No newline at end of file
diff --git a/internal-prebuilts/com/android/databinding/localizemaven/1.1/localizemaven-1.1.jar b/internal-prebuilts/com/android/databinding/localizemaven/1.1/localizemaven-1.1.jar
index e003a04..56b9cc3 100644
--- a/internal-prebuilts/com/android/databinding/localizemaven/1.1/localizemaven-1.1.jar
+++ b/internal-prebuilts/com/android/databinding/localizemaven/1.1/localizemaven-1.1.jar
Binary files differ
diff --git a/internal-prebuilts/com/android/databinding/localizemaven/1.1/localizemaven-1.1.jar.md5 b/internal-prebuilts/com/android/databinding/localizemaven/1.1/localizemaven-1.1.jar.md5
index d93d95d..602f242 100644
--- a/internal-prebuilts/com/android/databinding/localizemaven/1.1/localizemaven-1.1.jar.md5
+++ b/internal-prebuilts/com/android/databinding/localizemaven/1.1/localizemaven-1.1.jar.md5
@@ -1 +1 @@
-4b81f88150cd2be1b1f6d886100af1c2
\ No newline at end of file
+655e10a4a34db4274d7731fccd675bad
\ No newline at end of file
diff --git a/internal-prebuilts/com/android/databinding/localizemaven/1.1/localizemaven-1.1.jar.sha1 b/internal-prebuilts/com/android/databinding/localizemaven/1.1/localizemaven-1.1.jar.sha1
index 77d5422..8cf3d00 100644
--- a/internal-prebuilts/com/android/databinding/localizemaven/1.1/localizemaven-1.1.jar.sha1
+++ b/internal-prebuilts/com/android/databinding/localizemaven/1.1/localizemaven-1.1.jar.sha1
@@ -1 +1 @@
-6e19c0ca82802428346c624673e66479089c6814
\ No newline at end of file
+eb55fbfc70996f9645de075086df68794d96e4dc
\ No newline at end of file
diff --git a/internal-prebuilts/com/android/databinding/localizemaven/maven-metadata.xml b/internal-prebuilts/com/android/databinding/localizemaven/maven-metadata.xml
index 4f263e9..cf7e9ce 100644
--- a/internal-prebuilts/com/android/databinding/localizemaven/maven-metadata.xml
+++ b/internal-prebuilts/com/android/databinding/localizemaven/maven-metadata.xml
@@ -2,11 +2,11 @@
 <metadata>
   <groupId>com.android.databinding</groupId>
   <artifactId>localizemaven</artifactId>
-  <version>1.1</version>
   <versioning>
+    <release>1.1</release>
     <versions>
       <version>1.1</version>
     </versions>
-    <lastUpdated>20151104222707</lastUpdated>
+    <lastUpdated>20160212192012</lastUpdated>
   </versioning>
 </metadata>
diff --git a/internal-prebuilts/com/android/databinding/localizemaven/maven-metadata.xml.md5 b/internal-prebuilts/com/android/databinding/localizemaven/maven-metadata.xml.md5
index accb9a0..4c02386 100644
--- a/internal-prebuilts/com/android/databinding/localizemaven/maven-metadata.xml.md5
+++ b/internal-prebuilts/com/android/databinding/localizemaven/maven-metadata.xml.md5
@@ -1 +1 @@
-71903e14023ca5e2adb851cf065715e7
\ No newline at end of file
+d6a9b7f884c713fa405cb4a3faf2c9fe
\ No newline at end of file
diff --git a/internal-prebuilts/com/android/databinding/localizemaven/maven-metadata.xml.sha1 b/internal-prebuilts/com/android/databinding/localizemaven/maven-metadata.xml.sha1
index c2964b1..b90a5d5 100644
--- a/internal-prebuilts/com/android/databinding/localizemaven/maven-metadata.xml.sha1
+++ b/internal-prebuilts/com/android/databinding/localizemaven/maven-metadata.xml.sha1
@@ -1 +1 @@
-f30fef09adcbc55cf74ad44c7607accc884d87f9
\ No newline at end of file
+f5afd3a9fd6308b1fe4fdfbf54356a7afa344c0f
\ No newline at end of file
diff --git a/propLoader.gradle b/propLoader.gradle
index 310d313..d3e65cd 100644
--- a/propLoader.gradle
+++ b/propLoader.gradle
@@ -14,9 +14,10 @@
 databindingProperties.androidGradlePluginRepoDir = "${root}/../../${databindingProperties.androidGradlePluginOutRepo}"
 databindingProperties.mavenRepoDir = "${databindingProperties.androidGradlePluginRepoDir}"
 databindingProperties.internalPrebuiltsRepoDir = "${root}/${databindingProperties.internalPrebuiltsRepoName}"
-databindingProperties.runProguard = project.hasProperty('runProguard') && project.getProperty('runProguard').equals("true")
 
-databindingProperties.inReleaseBuild = project.ext.hasProperty('release') && project.ext.release
+databindingProperties.inReleaseBuild = project.hasProperty('release') && project.ext.release == "true"
+
+databindingProperties.runProguard = (project.hasProperty('runProguard') && project.getProperty('runProguard').equals("true"))
 // load version from gradle build file
 apply from: "$root/../buildSrc/base/version.gradle"
 databindingProperties.androidPluginVersion=ext.buildVersion
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 68c76c9..bcdcdba 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
@@ -69,14 +69,6 @@
         mListeners.notifyChange(this, BR.selected);
     }
 
-    public void onSave(View v) {
-        if (selected == null) {
-            return;
-        }
-        selected.setName(dataBinder.selectedName.getText().toString());
-        selected.setLastName(dataBinder.selectedLastname.getText().toString());
-    }
-
     public void onUnselect (View v) {
         setSelected(null);
     }
diff --git a/samples/BindingDemo/app/src/main/res/layout/main_activity.xml b/samples/BindingDemo/app/src/main/res/layout/main_activity.xml
index c16a94f..e17f27a 100644
--- a/samples/BindingDemo/app/src/main/res/layout/main_activity.xml
+++ b/samples/BindingDemo/app/src/main/res/layout/main_activity.xml
@@ -93,7 +93,7 @@
                     android:layout_row="0"
                     android:background="@android:color/holo_blue_dark"
                     android:gravity="center"
-                    android:text="@{activity.selected.name}" />
+                    android:text="@={activity.selected.name}" />
 
                 <EditText
                     android:id="@+id/selected_lastname"
@@ -104,16 +104,7 @@
                     android:layout_row="1"
                     android:background="@android:color/holo_blue_bright"
                     android:gravity="center"
-                    android:text="@{activity.selected.lastName}" />
-                <Button
-                    android:id="@+id/edit_button"
-                    android:onClick="@{activity.onSave}"
-                    android:text='@{"Save changes to " + activity.selected.name}'
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_column="1"
-                    android:layout_gravity="right"
-                    android:layout_row="2"/>
+                    android:text="@={activity.selected.lastName}" />
 
                 <Button
                     android:id="@+id/delete_button"