Full Code of JakeWharton/butterknife for AI

master fcdebedf3276 cached
232 files
674.9 KB
174.3k tokens
913 symbols
1 requests
Download .txt
Showing preview only (745K chars total). Download the full file or copy to clipboard to get everything.
Repository: JakeWharton/butterknife
Branch: master
Commit: fcdebedf3276
Files: 232
Total size: 674.9 KB

Directory structure:
gitextract_9jjk0dbd/

├── .buildscript/
│   └── deploy_snapshot.sh
├── .github/
│   └── workflows/
│       └── gradle-wrapper-validation.yml
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── RELEASING.md
├── build.gradle
├── butterknife/
│   ├── build.gradle
│   ├── gradle.properties
│   ├── proguard-rules.txt
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── butterknife/
│       │           └── ButterKnifeTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── butterknife/
│                   ├── ButterKnife.java
│                   └── package-info.java
├── butterknife-annotations/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       └── main/
│           └── java/
│               └── butterknife/
│                   ├── BindAnim.java
│                   ├── BindArray.java
│                   ├── BindBitmap.java
│                   ├── BindBool.java
│                   ├── BindColor.java
│                   ├── BindDimen.java
│                   ├── BindDrawable.java
│                   ├── BindFloat.java
│                   ├── BindFont.java
│                   ├── BindInt.java
│                   ├── BindString.java
│                   ├── BindView.java
│                   ├── BindViews.java
│                   ├── OnCheckedChanged.java
│                   ├── OnClick.java
│                   ├── OnEditorAction.java
│                   ├── OnFocusChange.java
│                   ├── OnItemClick.java
│                   ├── OnItemLongClick.java
│                   ├── OnItemSelected.java
│                   ├── OnLongClick.java
│                   ├── OnPageChange.java
│                   ├── OnTextChanged.java
│                   ├── OnTouch.java
│                   ├── Optional.java
│                   └── internal/
│                       ├── Constants.java
│                       ├── ListenerClass.java
│                       └── ListenerMethod.java
├── butterknife-compiler/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── butterknife/
│       │           └── compiler/
│       │               ├── BindingSet.java
│       │               ├── ButterKnifeProcessor.java
│       │               ├── FieldAnimationBinding.java
│       │               ├── FieldCollectionViewBinding.java
│       │               ├── FieldDrawableBinding.java
│       │               ├── FieldResourceBinding.java
│       │               ├── FieldTypefaceBinding.java
│       │               ├── FieldViewBinding.java
│       │               ├── Id.java
│       │               ├── MemberViewBinding.java
│       │               ├── MethodViewBinding.java
│       │               ├── Parameter.java
│       │               ├── ResourceBinding.java
│       │               └── ViewBinding.java
│       └── test/
│           └── java/
│               └── butterknife/
│                   └── compiler/
│                       └── BindingSetTest.java
├── butterknife-gradle-plugin/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── butterknife/
│       │   │       └── plugin/
│       │   │           ├── ButterKnifePlugin.kt
│       │   │           ├── FinalRClassBuilder.kt
│       │   │           ├── R2Generator.kt
│       │   │           └── ResourceSymbolListReader.kt
│       │   └── resources/
│       │       └── META-INF/
│       │           └── gradle-plugins/
│       │               └── com.jakewharton.butterknife.properties
│       └── test/
│           ├── AndroidManifest.xml
│           ├── build.gradle
│           ├── fixtures/
│           │   └── suffix_parsed_properly/
│           │       └── src/
│           │           └── main/
│           │               ├── java/
│           │               │   └── butterknife/
│           │               │       └── test/
│           │               │           └── ButteryActivity.java
│           │               └── res/
│           │                   └── layout/
│           │                       └── activity_layout.xml
│           ├── java/
│           │   └── butterknife/
│           │       └── plugin/
│           │           ├── AndroidHome.kt
│           │           ├── BuildFilesRule.kt
│           │           ├── FinalRClassBuilderTest.kt
│           │           └── FixturesTest.kt
│           └── resources/
│               └── fixtures/
│                   ├── R.txt
│                   └── R2.java
├── butterknife-integration-test/
│   ├── build.gradle
│   └── src/
│       ├── androidTest/
│       │   ├── font_licenses.txt
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── example/
│       │   │           └── butterknife/
│       │   │               ├── functional/
│       │   │               │   ├── BindAnimTest.java
│       │   │               │   ├── BindArrayTest.java
│       │   │               │   ├── BindBitmapTest.java
│       │   │               │   ├── BindBoolTest.java
│       │   │               │   ├── BindColorTest.java
│       │   │               │   ├── BindDimenTest.java
│       │   │               │   ├── BindDrawableTest.java
│       │   │               │   ├── BindFloatTest.java
│       │   │               │   ├── BindFontTest.java
│       │   │               │   ├── BindIntTest.java
│       │   │               │   ├── BindStringTest.java
│       │   │               │   ├── BindViewTest.java
│       │   │               │   ├── BindViewsTest.java
│       │   │               │   ├── OnCheckedChangedTest.java
│       │   │               │   ├── OnClickTest.java
│       │   │               │   ├── OnItemClickTest.java
│       │   │               │   ├── OnItemLongClickTest.java
│       │   │               │   ├── OnItemSelectedTest.java
│       │   │               │   ├── OnLongClickTest.java
│       │   │               │   ├── OnTouchTest.java
│       │   │               │   └── ViewTree.java
│       │   │               ├── library/
│       │   │               │   ├── SimpleActivityTest.java
│       │   │               │   └── SimpleAdapterTest.java
│       │   │               └── unbinder/
│       │   │                   └── UnbinderTest.java
│       │   ├── proguard.pro
│       │   └── res/
│       │       ├── color/
│       │       │   └── colors.xml
│       │       ├── drawable/
│       │       │   └── circle.xml
│       │       └── values/
│       │           └── values.xml
│       ├── androidTestReflect/
│       │   └── java/
│       │       └── com/
│       │           └── example/
│       │               └── butterknife/
│       │                   └── functional/
│       │                       ├── BindAnimFailureTest.java
│       │                       ├── BindArrayFailureTest.java
│       │                       ├── BindBitmapFailureTest.java
│       │                       ├── BindBoolFailureTest.java
│       │                       ├── BindColorFailureTest.java
│       │                       ├── BindDimenFailureTest.java
│       │                       ├── BindDrawableFailureTest.java
│       │                       ├── BindFloatFailureTest.java
│       │                       ├── BindFontFailureTest.java
│       │                       ├── BindIntFailureTest.java
│       │                       ├── BindStringFailureTest.java
│       │                       ├── BindViewFailureTest.java
│       │                       └── BindViewsFailureTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── com/
│           │       └── example/
│           │           └── butterknife/
│           │               ├── SimpleApp.java
│           │               ├── library/
│           │               │   ├── SimpleActivity.java
│           │               │   └── SimpleAdapter.java
│           │               └── unbinder/
│           │                   ├── A.java
│           │                   ├── B.java
│           │                   ├── C.java
│           │                   ├── D.java
│           │                   ├── E.java
│           │                   ├── F.java
│           │                   ├── G.java
│           │                   └── H.java
│           ├── proguard.pro
│           └── res/
│               ├── layout/
│               │   ├── simple_activity.xml
│               │   └── simple_list_item.xml
│               └── values/
│                   └── strings.xml
├── butterknife-lint/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── butterknife/
│       │           └── lint/
│       │               ├── InvalidR2UsageDetector.java
│       │               └── LintRegistry.java
│       └── test/
│           └── java/
│               └── butterknife/
│                   └── lint/
│                       ├── InvalidR2UsageDetectorTest.java
│                       └── LintRegistryTest.java
├── butterknife-reflect/
│   ├── README.md
│   ├── build.gradle
│   ├── gradle.properties
│   ├── proguard-rules.txt
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── butterknife/
│                   ├── ButterKnife.java
│                   ├── CompositeUnbinder.java
│                   ├── EmptyTextWatcher.java
│                   ├── FieldUnbinder.java
│                   └── ListenerUnbinder.java
├── butterknife-runtime/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── butterknife/
│       │           ├── ViewCollectionsTest.java
│       │           └── internal/
│       │               └── UtilsTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   └── java/
│       │       └── butterknife/
│       │           ├── Action.java
│       │           ├── Setter.java
│       │           ├── Unbinder.java
│       │           ├── ViewCollections.java
│       │           └── internal/
│       │               ├── DebouncingOnClickListener.java
│       │               ├── ImmutableList.java
│       │               └── Utils.java
│       └── test/
│           └── java/
│               └── butterknife/
│                   ├── BindAnimTest.java
│                   ├── BindArrayTest.java
│                   ├── BindBitmapTest.java
│                   ├── BindBoolTest.java
│                   ├── BindColorTest.java
│                   ├── BindDimenTest.java
│                   ├── BindDrawableTest.java
│                   ├── BindFloatTest.java
│                   ├── BindFontTest.java
│                   ├── BindIntTest.java
│                   ├── BindStringTest.java
│                   ├── BindViewTest.java
│                   ├── BindViewsTest.java
│                   ├── ClasspathParentBindTest.java
│                   ├── ExtendActivityTest.java
│                   ├── ExtendDialogTest.java
│                   ├── ExtendViewTest.java
│                   ├── OnClickTest.java
│                   ├── OnEditorActionTest.java
│                   ├── OnFocusChangeTest.java
│                   ├── OnItemClickTest.java
│                   ├── OnItemLongClickTest.java
│                   ├── OnItemSelectedTest.java
│                   ├── OnPageChangeTest.java
│                   ├── OnTextChangedTest.java
│                   ├── OnTouchTest.java
│                   ├── RClassTest.java
│                   ├── TestGeneratingProcessor.java
│                   ├── TestStubs.java
│                   ├── UnbinderTest.java
│                   └── UtilsTest.java
├── checkstyle.xml
├── deploy_website.sh
├── gradle/
│   ├── gradle-mvn-push.gradle
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── sample/
│   ├── app/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           └── java/
│   │               └── com/
│   │                   └── example/
│   │                       └── butterknife/
│   │                           ├── SimpleApp.java
│   │                           └── unbinder/
│   │                               ├── A.java
│   │                               ├── B.java
│   │                               ├── C.java
│   │                               ├── D.java
│   │                               ├── E.java
│   │                               ├── F.java
│   │                               ├── G.java
│   │                               └── H.java
│   └── library/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── butterknife/
│               │               └── library/
│               │                   ├── SimpleActivity.java
│               │                   └── SimpleAdapter.java
│               └── res/
│                   ├── layout/
│                   │   ├── simple_activity.xml
│                   │   └── simple_list_item.xml
│                   └── values/
│                       └── strings.xml
├── settings.gradle
└── website/
    ├── ide-eclipse.html
    ├── ide-idea.html
    ├── index.html
    └── static/
        ├── app.css
        ├── butter_android.psd
        ├── logo.psd
        ├── prettify.css
        └── prettify.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .buildscript/deploy_snapshot.sh
================================================
#!/bin/bash
#
# Deploy a jar, source jar, and javadoc jar to Sonatype's snapshot repo.
#
# Adapted from https://coderwall.com/p/9b_lfq and
# http://benlimmer.com/2013/12/26/automatically-publish-javadoc-to-gh-pages-with-travis-ci/

SLUG="JakeWharton/butterknife"
JDK="oraclejdk8"
BRANCH="master"

set -e

if [ "$TRAVIS_REPO_SLUG" != "$SLUG" ]; then
  echo "Skipping snapshot deployment: wrong repository. Expected '$SLUG' but was '$TRAVIS_REPO_SLUG'."
elif [ "$TRAVIS_JDK_VERSION" != "$JDK" ]; then
  echo "Skipping snapshot deployment: wrong JDK. Expected '$JDK' but was '$TRAVIS_JDK_VERSION'."
elif [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
  echo "Skipping snapshot deployment: was pull request."
elif [ "$TRAVIS_BRANCH" != "$BRANCH" ]; then
  echo "Skipping snapshot deployment: wrong branch. Expected '$BRANCH' but was '$TRAVIS_BRANCH'."
else
  echo "Deploying snapshot..."
  ./gradlew uploadArchives
  echo "Snapshot deployed!"
fi


================================================
FILE: .github/workflows/gradle-wrapper-validation.yml
================================================
name: "Validate Gradle Wrapper"
on: [push, pull_request]

jobs:
  validation:
    name: "Validation"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: gradle/wrapper-validation-action@v1


================================================
FILE: .gitignore
================================================
bin
gen
out
lib

.idea
*.iml
classes

obj

.DS_Store

# Gradle
.gradle
jniLibs
build
local.properties
reports


================================================
FILE: .travis.yml
================================================
language: android

jdk:
  - oraclejdk8

before_install:
  # Install SDK license so Android Gradle plugin can install deps.
  - mkdir "$ANDROID_HOME/licenses" || true
  - echo "d56f5187479451eabf01fb78af6dfcb131a6481e" > "$ANDROID_HOME/licenses/android-sdk-license"
  - echo "24333f8a63b6825ea9c5514f83c2829b004d1fee" >> "$ANDROID_HOME/licenses/android-sdk-license"
  # Install the rest of tools (e.g., avdmanager)
  - sdkmanager tools
  # Install the system image
  - sdkmanager "system-images;android-18;default;armeabi-v7a"
  # Create and start emulator for the script. Meant to race the install task.
  - echo no | avdmanager create avd --force -n test -k "system-images;android-18;default;armeabi-v7a"
  - $ANDROID_HOME/emulator/emulator -avd test -no-audio -no-window &

install: ./gradlew clean assemble assembleAndroidTest --stacktrace

before_script:
  - android-wait-for-emulator
  - adb shell input keyevent 82

script: ./gradlew check connectedCheck --stacktrace

after_success:
  - .buildscript/deploy_snapshot.sh

env:
  global:
    - secure: "ESbreW4FNMPQhV1zbFb9iBvhFWFbVHecaig3Si3+4nrJCMn9x4nqB18ZcU+Aviw67WQNcuSH4I0Hl08uknl+kzE/xKEfPLmu28bptXRCSued49aL11i2aQmRj5nqP2yxkinhtRGOQxzIo56NmFt7sIcEXODM3D5a6q7s9tlvPfw="
    - secure: "JWEeqx0CWBqAkjcREHUg3Ei8wxqp59HZag8EidSLwmekgPJQwipwuEeXMZyPCGJCP+4ijUirtS/hRApi37BW0LYdt+XR7dI1TSZ0HFLTLqSPfWfsUcjmGpmoqVUv8FLVhC+KA42YeEhqkEaCUW92gJeAyK8swxDqGHAPT/sfKRA="

branches:
  except:
    - gh-pages

notifications:
  email: false

sudo: false

before_cache:
  - rm -f  $HOME/.gradle/caches/modules-2/modules-2.lock
  - rm -fr $HOME/.gradle/caches/*/plugin-resolution/

cache:
  directories:
    - $HOME/.gradle/caches/
    - $HOME/.gradle/wrapper/
    - $HOME/.android/build-cache


================================================
FILE: CHANGELOG.md
================================================
Change Log
==========

Version 10.2.3 *(2020-08-12)*
-----------------------------

Heads up: Development on this tool is winding down as [view binding](https://developer.android.com/topic/libraries/view-binding) is stable in AS/AGP 3.6+.

 * Fix: Support receiving `MotionEvent` in an `@OnTouch` callback when using 'butterknife-reflect'.


Version 10.2.2 *(2020-08-03)*
-----------------------------

Heads up: Development on this tool is winding down as [view binding](https://developer.android.com/topic/libraries/view-binding) is stable in AS/AGP 3.6+.

 * Fix: Views detached while processing click callbacks will no longer disable future clicks on other views.


Version 10.2.1 *(2019-12-19)*
-----------------------------

Heads up: Development on this tool is winding down as [view binding](https://developer.android.com/topic/libraries/view-binding) will be stable in AS/AGP 3.6.

 * New: Make R2-generating Gradle task cacheable by default.
 * Fix: R2 classes now generate their own unique values for entries. This ensures that the annotation processor
   can always do a reverse mapping from ID back to name and type. In AGP 3.6.0, the `R.txt` symbol table that was
   previously used as a source for values now uses 0 for every entry which required this change.
 * Fix: Lint check for R2 values now properly handles static imports for entries.


Version 10.2.0 *(2019-09-12)*
-----------------------------

 * New: Support incremental annotation processing.
 * Fix: Detect generated superclass bindings across compilation units.
 * Fix: Avoid deprecated APIs from the Android Gradle plugin. As a result, the new minimum supported version
   of the Android Gradle plugin is 3.3.


Version 10.1.0 *(2019-02-13)*
-----------------------------

 * New: Listeners which require return values (e.g., long click) can now be bound to methods returning `void`.
   The default value of `true` will be returned in this case.
 * New: Add support for `@OnTextChanged` and `@OnPageChange` to reflection backend.
 * Remove enforcement of required views in the reflection backend. Most `@Nullable` annotations do not have
   runtime retention so they can't be checked at runtime with reflection. Instead of forcing everyone to find
   a new annotation, this enforcement is now dropped. While this might lead to nulls in otherwise required
   view bindings, they'll either be unused or quickly cause a `NullPointerException`.


Version 10.0.0 *(2019-01-03)*
-----------------------------

 * Equivalent to 9.0.0 but only supports AndroidX-enabled builds.
 * Removed APIs deprecated in 9.0.0.


Version 9.0.0 *(2019-01-03)*
----------------------------

 * New: Support for AndroidX. Requires `android.useAndroidX=true` in `gradle.properties` to generate
   AndroidX code.

 * New: A `butterknife-runtime` artifact has been extracted from `butterknife` which contains the APIs
   required for the generated code but does not contain the code to reflectively look up the generated
   code. This allows you to reference the generated code directly such that R8/ProGuard optimization can
   rename both the generated code and your classes. `ButterKnife.bind` and the consumer R8/ProGuard rules
   remain in the old `butterknife` artifact.
 
 * New: Experimental `butterknife-reflect` artifact eliminates the need to run the annotation
   processor for IDE builds. This artifact is binary compatible with `butterknife` so it can be interchanged
   depending on how your build is being invoked. See [its README](butterknife-reflect/README.md) for more
   information. Currently about 90% of functionality is covered. File bugs for anything that does not work.

   Note: This artifact requires Java 8. There's no good reason for this except to push the ecosystem to
   having this be a default. As of AGP 3.2 there is no reason not to do this.

 * New: Lint checks have been ported to UAST and now work on Kotlin code.
 
 * Helpers such as `apply` have been deprecated on `ButterKnife` and are now available on the `ViewCollections` class.

 * Add support for Android Gradle plugin 3.3 and newer where `R` is no longer generated as Java source. This
   has a side-effect of removing support for Android Gradle plugin 3.0.x (and older).
 * Use Java 8 bytecode for all artifacts as announced in RC1 release notes.
 * Fix: Allow `@BindFont` to work prior to API 26 using `ResourcesCompat`.
 * Fix: Update Android Gradle plugin to 3.1 or newer to fix binary incompatibilities.
 * Fix: Correct generated resource annotation names when running Turkish locale.
 * Fix: Use the application ID instead of the resource package for generating `R2`.
 * Cache the fact that a class hierarchy has no remaining bindings to prevent traversing the hierarchy
   multiple times.
 * Deprecated methods from 8.x have been removed.


Version 9.0.0-rc3 *(2018-12-20)*
--------------------------------

 * Fix: Correct generated resource annotation names when running Turkish locale.
 * Cache the fact that a class hierarchy has no remaining bindings to prevent traversing the hierarchy
   multiple times.


Version 9.0.0-rc2 *(2018-11-19)*
--------------------------------

 * Add support for Android Gradle plugin 3.3 and newer where `R` is no longer generated as Java source. This
   has a side-effect of removing support for Android Gradle plugin 3.0.x (and older).
 * Use Java 8 bytecode for all artifacts as announced in RC1 release notes.


Version 9.0.0-rc1 *(2018-10-10)*
--------------------------------

 * New: Support for AndroidX. Requires `android.useAndroidX=true` in `gradle.properties` to generate
   AndroidX code.

 * New: A `butterknife-runtime` artifact has been extracted from `butterknife` which contains the APIs
   required for the generated code but does not contain the code to reflectively look up the generated
   code. This allows you to reference the generated code directly such that R8/ProGuard optimization can
   rename both the generated code and your classes. `ButterKnife.bind` and the consumer R8/ProGuard rules
   remain in the old `butterknife` artifact.
 
 * New: Experimental `butterknife-reflect` artifact eliminates the need to run the annotation
   processor for IDE builds. This artifact is binary compatible with `butterknife` so it can be interchanged
   depending on how your build is being invoked. See [its README](butterknife-reflect/README.md) for more
   information. Currently about 90% of functionality is covered. File bugs for anything that does not work.

   Note: This artifact requires Java 8. There's no good reason for this except to push the ecosystem to
   having this be a default. As of AGP 3.2 there is no reason not to do this.

 * New: Lint checks have been ported to UAST and now work on Kotlin code.

 * Fix: Allow `@BindFont` to work prior to API 26 using `ResourcesCompat`.
 * Fix: Update Android Gradle plugin to 3.1 or newer to fix binary incompatibilities.
 * Fix: Use the application ID instead of the resource package for generating `R2`.
 * Deprecated methods from 8.x have been removed.

Note: The next release candidate will switch all artifacts to require Java 8 bytecode which will force
your applications to enable Java 8 bytecode. As of AGP 3.2 there is no cost to this, and there is no
reason to have it set any lower.


Version 8.8.1 *(2017-08-09)*
----------------------------

 * Fix: Properly emit casts for single-bound view subtypes when `butterknife.debuggable` is set to `false`.


Version 8.8.0 *(2017-08-04)*
----------------------------

 * New: Processor option `butterknife.debuggable` controls whether debug information is generated. When
   specified as `false`, checks for required views being non-null are elided and casts are no longer guarded
   with user-friendly error messages. This reduces the amount of generated code for release builds at the
   expense of less friendly exceptions when something breaks.
 * Deprecate the `findById` methods. Compile against API 26 and use the normal `findViewById` for the same
   functionality.
 * Fix: Correct `@BindFont` code generation on pre-API 26 builds to pass a `Context` (not a `Resources`) to
   `ResourceCompat`.


Version 8.7.0 *(2017-07-07)*
----------------------------

 * New: `@BindFont` annotation binds `Typeface` instances with an optional style. Requires support libraries
   26.0.0-beta1 or newer.
 * New: `@BindAnim` annotation binds `Animation` instances.
 * New: Generate `R2` constants for animation, layout, menu, plurals, styles, and styleables.
 * Fix: Properly catch and re-throw type cast exceptions when method binding arguments do not match.


Version 8.6.0 *(2017-05-16)*
----------------------------

 * Plugin was ported to Kotlin and updated to support future Android Gradle plugin versions.
 * Fix: Properly handle multiple library modules using Butter Knife and defining the same ID.
 * Fix: Use the same classloader of the binding target to load the generated view binding class.


Version 8.5.1 *(2017-01-24)*
----------------------------

 * Fix: Tweak bundled ProGuard rules to only retain the two-argument constructor accessed via reflection.


Version 8.5.0 *(2017-01-23)*
----------------------------

 * Emit `@SuppressLint` when using `@OnTouch` to avoid a lint warning.
 * Migrate lint checks from Lombok AST to JetBrains PSI.
 * Annotations are no longer claimed by the processor.
 * Based on the minimum SDK version (as specified by `butterknife.minSdk` until http://b.android.com/187527 is
   released) the generated code now changes to use newer APIs when available.
 * Generated classes now include single-argument overloads for `View`, `Activity`, and `Dialog` subclasses.
 * Generated classes are no longer generic.
 * Minimum supported SDK is now 9.


Version 8.4.0 *(2016-08-26)*
----------------------------

 * New: `@BindFloat` annotation for dimensions whose format is of type 'float'. See the annotation for more
   information.
 * Generated constructors are now annotated with `@UiThread` and non-final, base classes `unbind()` methods
   are annotated with `@CallSuper`.


Version 8.3.0 *(2016-08-23)*
----------------------------

 * New: Support for Jack compiler in application projects.
 * Fix: Generate ~20% less code and ~40% less methods.
 * Fix: Allow `@BindView` to reference types which are generated by other annotation processors.
 * Experimental: The generated view binding class can now be used directly. This allows ProGuard shrinking,
   optimization, and obfuscation to work without any rules being needed. For a class `Test`, the binding
   class will be named `Test_ViewBinding`. Calling its constructor will bind the instance passed in, and
   the create object is also the implementation of `Unbinder` that can be used to unbind the views.
   Note: The API of this generated code is subject to backwards-incompatible changes until v9.0.


Version 8.2.1 *(2016-07-11)*
----------------------------

 * Fix: Do not emit `android.R` imports in generated code.
 * Fix: Ensure the processor does not crash when scanning for `R` classes. This can occur when used in a
   Kotlin project.


Version 8.2.0 *(2016-07-10)*
----------------------------

 * New: Support for library projects. Requires application of a Butter Knife Gradle plugin. See README for
   details.
 * New: Generated code now emits `R` references instead of raw integer IDs.
 * Fix: `@OnPageChange` listener binding now uses the 'add'/'remove' methods on `ViewPager` instead of 'set'.


Version 8.1.0 *(2016-06-14)*
----------------------------

 * New: Change the structure of generated view binders to optimize for performance and generated code. This
   should result in faster binding (not that it's slow) and a reduction of methods.
 * Fix: Call the correct method on `TextView` to unbind `@OnTextChanged` uses.
 * Fix: Properly handle package names which contain uppercase letters.


Version 8.0.1 *(2016-04-27)*
----------------------------

 * Fix: ProGuard rules now prevent obfuscation of only types which reference ButterKnife annotations.
 * Eliminate some of the generated machinery when referenced from `final` types.


Version 8.0.0 *(2016-04-25)*
----------------------------

 *  `@Bind` becomes `@BindView` and `@BindViews` (one view and multiple views, respectively).
 *  Calls to `bind` now return an `Unbinder` instance which can be used to `null` references. This replaces
    the `unbind` API and adds support for being able to clear listeners.
 *  New: `@BindArray` binds `String`, `CharSequence`, and `int` arrays and `TypeArray` to fields.
 *  New: `@BindBitmap` binds `Bitmap` instances from resources to fields.
 *  `@BindDrawable` now supports a `tint` field which accepts a theme attribute.
 *  The runtime and compiler are now split into two artifacts.

    ```groovy
    compile 'com.jakewharton:butterknife:8.0.0'
    apt 'com.jakewharton:butterknife-compiler:8.0.0'
    ```
 *  New: `apply` overloads which accept a single view and arrays of views.
 *  ProGuard rules now ship inside of the library and are included automatically.
 *  `@Optional` annotation is back to mark methods as being optional.


Version 7.0.1 *(2015-06-30)*
----------------------------

 * Fix: Correct `ClassCastException` which occurred when `@Nullable` array bindings had missing views.


Version 7.0.0 *(2015-06-27)*
----------------------------

 * `@Bind` replaces `@InjectView` and `@InjectViews`.
 * `ButterKnife.bind` and `ButterKnife.unbind` replaces `ButterKnife.inject` and `ButterKnife.reset`, respectively.
 * `@Optional` has been removed. Use `@Nullable` from the 'support-annotations' library, or any other annotation
   named "Nullable".
 * New: Resource binding annotations!
   * `@BindBool` binds an `R.bool` ID to a `boolean` field.
   * `@BindColor` binds an `R.color` ID to an `int` or `ColorStateList` field.
   * `@BindDimen` binds an `R.dimen` ID to an `int` (for pixel size) or `float` (for exact value) field.
   * `@BindDrawable` binds an `R.drawable` ID to a `Drawable` field.
   * `@BindInt` binds an `R.int` ID to an `int` field.
   * `@BindString` binds an `R.string` ID to a `String` field.
 * Fix: Missing views will be filtered out from list and array bindings.
 * Note: If you are using Proguard, the generated class name has changed from being suffixed with `$$ViewInjector`
   to `$$ViewBinder`.


Version 6.1.0 *(2015-01-29)*
----------------------------

 * New: Support for injecting interface types everywhere that views were previously supported (e.g., `Checkable`).
 * Eliminate reflection-based method invocation for injection and resetting. This makes performance slightly faster
   (although if you are worried about the performance of Butter Knife you have other problems). The only reflection
   in the library is a single `Class.forName` lookup for each type.


Version 6.0.0 *(2014-10-27)*
----------------------------

 * New: Listeners can bind to the root view being injected by omitting a view ID on the annotation.
 * New: Exceptions thrown from missing views now include the human-readable ID name (e.g., 'button1').
 * Specifying multiple fields binding to the same ID is now considered an error.
 * `findById` overload for view lookup on `Dialog` instances.
 * Experimental: Click listeners are now globally debounced per frame. This means that only a single click
   will be processed per frame preventing race conditions due to queued input events.
 * Experimental: Multiple methods can bind to the same listener provided that listener's callback method
   does not require a return value.


Version 5.1.2 *(2014-08-01)*
----------------------------

 * Report an error if the annotations are on a class inside the `android.*` or `java.*`
   package. Since we ignore these packages in the runtime, injection would never work.


Version 5.1.1 *(2014-06-19)*
----------------------------

 * Fix: Correct rare `ClassCastException` when unwinding an `InvocationTargetException`.


Version 5.1.0 *(2014-05-20)*
----------------------------

 * New listener!
   * `View`: `@OnTouch`.
 * Fix: `@Optional` now correctly works for `@InjectViews` fields.
 * Fix: Correct erasure problem which may have prevented the processor from running in Eclipse.


Version 5.0.1 *(2014-05-04)*
----------------------------

 * New: Support `Dialog` as injection source.
 * Fix: Unwrap `InvocationTargetException` causes for more helpful exceptions.


Version 5.0.0 *(2014-04-21)*
----------------------------

 * New: `@InjectViews` annotation groups multiple IDs into a `List` or array.
 * New: `ButterKnife.apply` method applies an `Action`, `Setter`, or Android `Property` to views in
   a list.
 * New listeners!
   * `ViewPager`: `@OnPageChange`.
   * `AdapterView`: `@OnItemSelected`.
   * `TextView`: `@OnTextChanged`.
 * New: Multi-method listener support. Specify a `callback` argument to choose which method the
   binding is for. *(See `@OnItemSelected` for an example)*
 * Fix: Support for generic types which are declared with an upper-bound.
 * Fix: Use less sophisticated method injection inspection in the annotation processor. The previous
   method caused problems with some Eclipse configurations.


Version 4.0.1 *(2013-11-25)*
----------------------------

 * Fix: Correct a problem preventing the annotation processor to access Android types when certain
   `javac` configurations were used to build.


Version 4.0.0 *(2013-11-25)*
----------------------------

`Views` class is now named `ButterKnife`

 * New listeners!
   * `View`: `@OnLongClick` and `@OnFocusChanged`.
   * `TextView`: `@OnEditorAction`.
   * `AdapterView`: `@OnItemClick` and `@OnItemLongClick`.
   * `CompoundButton`: `@OnCheckedChanged`.
 * New: Views are now only checked to be `null` once if at least one of the fields and/or methods
   lack the `@Optional` annotation.
 * Fix: Do no emit redundant casts to `View` for methods.


Version 3.0.1 *(2013-11-12)*
----------------------------

 * Fix: Do not emit redundant casts to `View`.


Version 3.0.0 *(2013-09-10)*
----------------------------

 * New: Injections are now required. An exception will be thrown if a view is
   not found. Add `@Optional` annotation to suppress this verification.


Version 2.0.1 *(2013-07-18)*
----------------------------

 * New: Control debug logging via `Views.setDebug`.


Version 2.0.0 *(2013-07-16)*
----------------------------

 * New: `@OnClick` annotation for binding click listeners to methods!


Version 1.4.0 *(2013-06-03)*
----------------------------

 * New: `Views.reset` for settings injections back to `null` in a fragment's
   `onDestroyView` callback.
 * Fix: Support parent class injection when the parent class has generics.


Version 1.3.2 *(2013-04-27)*
----------------------------

 * Multiple injections of the same view ID only require a single find call.
 * Fix: Ensure injection happens on classes who do not have any injections but
   their superclasses do.


Version 1.3.1 *(2013-04-12)*
----------------------------

 * Fix: Parent class inflater resolution now generates correct code.


Version 1.3.0 *(2013-03-26)*
----------------------------

 * New: Injection on objects that have zero `@InjectView`-annotated fields will
   no longer throw an exception.


Version 1.2.2 *(2013-03-11)*
----------------------------

 * Fix: Prevent annotations on private classes.


Version 1.2.1 *(2013-03-11)*
----------------------------

 * Fix: Correct generated code for parent class inflation.
 * Fix: Allow injection on `protected`-scoped fields.


Version 1.2.0 *(2013-05-07)*
----------------------------

 * Support injection on any object using an Activity as the view root.
 * Support injection on views for their children.
 * Fix: Annotation errors now appear on the affected field in IDEs.


Version 1.1.1 *(2013-05-06)*
----------------------------

 * Fix: Verify that the target type extends from `View`.
 * Fix: Correct package name resolution in Eclipse 4.2


Version 1.1.0 *(2013-03-05)*
----------------------------

 * Perform injection on any object by passing a view root.
 * Fix: Correct naming of static inner-class injection points.
 * Fix: Enforce `findById` can only be used with child classes of `View`.


Version 1.0.0 *(2013-03-05)*
----------------------------

Initial release.


================================================
FILE: LICENSE.txt
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   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.


================================================
FILE: README.md
================================================
Butter Knife
============

**Attention**: This tool is now deprecated. Please switch to
[view binding](https://developer.android.com/topic/libraries/view-binding).
Existing versions will continue to work, obviously, but only critical bug fixes for integration
with AGP will be considered. Feature development and general bug fixes have stopped.

![Logo](website/static/logo.png)

Field and method binding for Android views which uses annotation processing to generate boilerplate
code for you.

 * Eliminate `findViewById` calls by using `@BindView` on fields.
 * Group multiple views in a list or array. Operate on all of them at once with actions,
   setters, or properties.
 * Eliminate anonymous inner-classes for listeners by annotating methods with `@OnClick` and others.
 * Eliminate resource lookups by using resource annotations on fields.

```java
class ExampleActivity extends Activity {
  @BindView(R.id.user) EditText username;
  @BindView(R.id.pass) EditText password;

  @BindString(R.string.login_error) String loginErrorMessage;

  @OnClick(R.id.submit) void submit() {
    // TODO call server...
  }

  @Override public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.simple_activity);
    ButterKnife.bind(this);
    // TODO Use fields...
  }
}
```

For documentation and additional information see [the website][3].

__Remember: A butter knife is like a [dagger][1], only infinitely less sharp.__



Download
--------

```groovy
android {
  ...
  // Butterknife requires Java 8.
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

dependencies {
  implementation 'com.jakewharton:butterknife:10.2.3'
  annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.3'
}
```

If you are using Kotlin, replace `annotationProcessor` with `kapt`.

Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap].



Library projects
--------------------

To use Butter Knife in a library, add the plugin to your `buildscript`:

```groovy
buildscript {
  repositories {
    mavenCentral()
    google()
  }
  dependencies {
    classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3'
  }
}
```

and then apply it in your module:

```groovy
apply plugin: 'com.android.library'
apply plugin: 'com.jakewharton.butterknife'
```

Now make sure you use `R2` instead of `R` inside all Butter Knife annotations.

```java
class ExampleActivity extends Activity {
  @BindView(R2.id.user) EditText username;
  @BindView(R2.id.pass) EditText password;
...
}
```



License
-------

    Copyright 2013 Jake Wharton

    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.



 [1]: https://dagger.dev/
 [2]: https://search.maven.org/remote_content?g=com.jakewharton&a=butterknife&v=LATEST
 [3]: http://jakewharton.github.com/butterknife/
 [snap]: https://oss.sonatype.org/content/repositories/snapshots/


================================================
FILE: RELEASING.md
================================================
Releasing
========

 1. Change the version in `gradle.properties` to a non-SNAPSHOT version.
 2. Update the `CHANGELOG.md` for the impending release.
 3. Update the `README.md` with the new version.
 4. `git commit -am "Prepare for release X.Y.Z."` (where X.Y.Z is the new version)
 5. `./gradlew clean uploadArchives`.
 6. Visit [Sonatype Nexus](https://oss.sonatype.org/) and promote the artifact.
 7. `git tag -a X.Y.X -m "Version X.Y.Z"` (where X.Y.Z is the new version)
 8. Update the `gradle.properties` to the next SNAPSHOT version.
 9. `git commit -am "Prepare next development version."`
 10. `git push && git push --tags`
 11. Update the two sample modules to point to the newly released version.

If step 5 or 6 fails, drop the Sonatype repo, fix the problem, commit, and start again at step 5.


================================================
FILE: build.gradle
================================================
apply plugin: 'com.github.ben-manes.versions'

buildscript {
  ext.versions = [
      'minSdk': 14,
      'compileSdk': 28,

      'androidTools': '26.2.0',
      'kotlin': '1.2.71',
      'incap' : '0.2',

      'release': '8.8.1',
  ]

  ext.deps = [
      android: [
          'runtime': 'com.google.android:android:4.1.1.4',
          'gradlePlugin': "com.android.tools.build:gradle:3.3.0",
      ],
      'androidx': [
          'core': "androidx.core:core:1.0.0",
          'viewpager': "androidx.viewpager:viewpager:1.0.0",
          'annotations': "androidx.annotation:annotation:1.0.0",
          'test': [
              'runner': 'androidx.test:runner:1.1.0',
              'rules': 'androidx.test:rules:1.1.0',
          ],
      ],
      'lint': [
          'core': "com.android.tools.lint:lint:${versions.androidTools}",
          'api': "com.android.tools.lint:lint-api:${versions.androidTools}",
          'checks': "com.android.tools.lint:lint-checks:${versions.androidTools}",
          'tests': "com.android.tools.lint:lint-tests:${versions.androidTools}",
      ],
      javapoet: 'com.squareup:javapoet:1.10.0',
      junit: 'junit:junit:4.12',
      truth: 'com.google.truth:truth:0.42',
      compiletesting: 'com.google.testing.compile:compile-testing:0.15',
      'auto': [
          'service': 'com.google.auto.service:auto-service:1.0-rc4',
          'common': 'com.google.auto:auto-common:0.10',
      ],
      'guava': 'com.google.guava:guava:24.0-jre',
      'release': [
          'runtime': "com.jakewharton:butterknife:${versions.release}",
          'compiler': "com.jakewharton:butterknife-compiler:${versions.release}"
      ],
      'kotlin': [
          'stdLibJdk8': "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}",
      ],
      'incap': [
          'runtime': "net.ltgt.gradle.incap:incap:${versions.incap}",
          'processor': "net.ltgt.gradle.incap:incap-processor:${versions.incap}",
      ]
  ]

  repositories {
    mavenCentral()
    google()
    jcenter()
    gradlePluginPortal()
  }

  dependencies {
    classpath 'com.android.tools.build:gradle:3.2.0'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
    classpath 'com.github.ben-manes:gradle-versions-plugin:0.17.0'
    classpath 'net.ltgt.gradle:gradle-errorprone-plugin:0.0.16'
  }
}

subprojects { project ->
  group = GROUP
  version = VERSION_NAME

  repositories {
    mavenCentral()
    google()
    jcenter()
  }

  apply plugin: 'net.ltgt.errorprone'

  dependencies {
    errorprone 'com.google.errorprone:error_prone_core:2.3.1'
  }

  // TODO figure out why this causes codegen to fail in android tests.
  //def nullaway = dependencies.create('com.uber.nullaway:nullaway:0.5.5')
  //configurations.all { Configuration configuration ->
  //  if (configuration.name.endsWith('nnotationProcessor')) {
  //    configuration.dependencies.add(nullaway)
  //  }
  //}
  //
  //tasks.withType(JavaCompile) {
  //  options.compilerArgs += [
  //      '-Xep:NullAway:ERROR',
  //      '-XepOpt:NullAway:AnnotatedPackages=butterknife',
  //  ]
  //}

  if (!project.name.equals('butterknife-gradle-plugin')) {
    apply plugin: 'checkstyle'

    task checkstyle(type: Checkstyle) {
      configFile rootProject.file('checkstyle.xml')
      source 'src/main/java'
      ignoreFailures false
      showViolations true
      include '**/*.java'

      classpath = files()
    }

    afterEvaluate {
      if (project.tasks.findByName('check')) {
        check.dependsOn('checkstyle')
      }
    }
  }
}


================================================
FILE: butterknife/build.gradle
================================================
apply plugin: 'com.android.library'

android {
  compileSdkVersion versions.compileSdk

  defaultConfig {
    minSdkVersion versions.minSdk

    consumerProguardFiles 'proguard-rules.txt'

    testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
  }

  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }

  lintOptions {
    textReport true
    textOutput 'stdout'
    // We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks.
    checkReleaseBuilds false
  }

  // TODO replace with https://issuetracker.google.com/issues/72050365 once released.
  libraryVariants.all {
    it.generateBuildConfig.enabled = false
  }
}

dependencies {
  api project(':butterknife-runtime')

  androidTestImplementation deps.junit
  androidTestImplementation deps.truth
  androidTestImplementation deps.androidx.test.runner
  androidTestAnnotationProcessor project(':butterknife-compiler')
}

apply from: rootProject.file('gradle/gradle-mvn-push.gradle')


================================================
FILE: butterknife/gradle.properties
================================================
POM_ARTIFACT_ID=butterknife
POM_NAME=Butterknife
POM_PACKAGING=aar


================================================
FILE: butterknife/proguard-rules.txt
================================================
# Retain generated class which implement Unbinder.
-keep public class * implements butterknife.Unbinder { public <init>(**, android.view.View); }

# Prevent obfuscation of types which use ButterKnife annotations since the simple name
# is used to reflectively look up the generated ViewBinding.
-keep class butterknife.*
-keepclasseswithmembernames class * { @butterknife.* <methods>; }
-keepclasseswithmembernames class * { @butterknife.* <fields>; }


================================================
FILE: butterknife/src/androidTest/java/butterknife/ButterKnifeTest.java
================================================
package butterknife;

import android.content.Context;
import android.view.View;
import androidx.test.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static com.google.common.truth.Truth.assertThat;

public class ButterKnifeTest {
  private final Context context = InstrumentationRegistry.getContext();

  @Before @After // Clear out cache of binders before and after each test.
  public void resetViewsCache() {
    ButterKnife.BINDINGS.clear();
  }

  @Test public void zeroBindingsBindDoesNotThrowExceptionAndCaches() {
    class Example {
    }

    Example example = new Example();
    View view = new View(context);
    assertThat(ButterKnife.BINDINGS).isEmpty();
    assertThat(ButterKnife.bind(example, view)).isSameAs(Unbinder.EMPTY);
    assertThat(ButterKnife.BINDINGS).containsEntry(Example.class, null);
  }

  @Test public void bindingKnownPackagesIsNoOp() {
    View view = new View(context);
    ButterKnife.bind(view);
    assertThat(ButterKnife.BINDINGS).isEmpty();
    ButterKnife.bind(new Object(), view);
    assertThat(ButterKnife.BINDINGS).isEmpty();
  }
}


================================================
FILE: butterknife/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="butterknife"/>


================================================
FILE: butterknife/src/main/java/butterknife/ButterKnife.java
================================================
package butterknife;

import android.app.Activity;
import android.app.Dialog;
import android.util.Log;
import android.view.View;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import androidx.annotation.VisibleForTesting;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Field and method binding for Android views. Use this class to simplify finding views and
 * attaching listeners by binding them with annotations.
 * <p>
 * Finding views from your activity is as easy as:
 * <pre><code>
 * public class ExampleActivity extends Activity {
 *   {@literal @}BindView(R.id.title) EditText titleView;
 *   {@literal @}BindView(R.id.subtitle) EditText subtitleView;
 *
 *   {@literal @}Override protected void onCreate(Bundle savedInstanceState) {
 *     super.onCreate(savedInstanceState);
 *     setContentView(R.layout.example_activity);
 *     ButterKnife.bind(this);
 *   }
 * }
 * </code></pre>
 * Binding can be performed directly on an {@linkplain #bind(Activity) activity}, a
 * {@linkplain #bind(View) view}, or a {@linkplain #bind(Dialog) dialog}. Alternate objects to
 * bind can be specified along with an {@linkplain #bind(Object, Activity) activity},
 * {@linkplain #bind(Object, View) view}, or
 * {@linkplain #bind(Object, android.app.Dialog) dialog}.
 * <p>
 * Group multiple views together into a {@link List} or array.
 * <pre><code>
 * {@literal @}BindView({R.id.first_name, R.id.middle_name, R.id.last_name})
 * List<EditText> nameViews;
 * </code></pre>
 * <p>
 * To bind listeners to your views you can annotate your methods:
 * <pre><code>
 * {@literal @}OnClick(R.id.submit) void onSubmit() {
 *   // React to button click.
 * }
 * </code></pre>
 * Any number of parameters from the listener may be used on the method.
 * <pre><code>
 * {@literal @}OnItemClick(R.id.tweet_list) void onTweetClicked(int position) {
 *   // React to tweet click.
 * }
 * </code></pre>
 * <p>
 * Be default, views are required to be present in the layout for both field and method bindings.
 * If a view is optional add a {@code @Nullable} annotation for fields (such as the one in the
 * <a href="http://tools.android.com/tech-docs/support-annotations">support-annotations</a> library)
 * or the {@code @Optional} annotation for methods.
 * <pre><code>
 * {@literal @}Nullable @BindView(R.id.title) TextView subtitleView;
 * </code></pre>
 * Resources can also be bound to fields to simplify programmatically working with views:
 * <pre><code>
 * {@literal @}BindBool(R.bool.is_tablet) boolean isTablet;
 * {@literal @}BindInt(R.integer.columns) int columns;
 * {@literal @}BindColor(R.color.error_red) int errorRed;
 * </code></pre>
 */
public final class ButterKnife {
  private ButterKnife() {
    throw new AssertionError("No instances.");
  }

  private static final String TAG = "ButterKnife";
  private static boolean debug = false;

  @VisibleForTesting
  static final Map<Class<?>, Constructor<? extends Unbinder>> BINDINGS = new LinkedHashMap<>();

  /** Control whether debug logging is enabled. */
  public static void setDebug(boolean debug) {
    ButterKnife.debug = debug;
  }

  /**
   * BindView annotated fields and methods in the specified {@link Activity}. The current content
   * view is used as the view root.
   *
   * @param target Target activity for view binding.
   */
  @NonNull @UiThread
  public static Unbinder bind(@NonNull Activity target) {
    View sourceView = target.getWindow().getDecorView();
    return bind(target, sourceView);
  }

  /**
   * BindView annotated fields and methods in the specified {@link View}. The view and its children
   * are used as the view root.
   *
   * @param target Target view for view binding.
   */
  @NonNull @UiThread
  public static Unbinder bind(@NonNull View target) {
    return bind(target, target);
  }

  /**
   * BindView annotated fields and methods in the specified {@link Dialog}. The current content
   * view is used as the view root.
   *
   * @param target Target dialog for view binding.
   */
  @NonNull @UiThread
  public static Unbinder bind(@NonNull Dialog target) {
    View sourceView = target.getWindow().getDecorView();
    return bind(target, sourceView);
  }

  /**
   * BindView annotated fields and methods in the specified {@code target} using the {@code source}
   * {@link Activity} as the view root.
   *
   * @param target Target class for view binding.
   * @param source Activity on which IDs will be looked up.
   */
  @NonNull @UiThread
  public static Unbinder bind(@NonNull Object target, @NonNull Activity source) {
    View sourceView = source.getWindow().getDecorView();
    return bind(target, sourceView);
  }

  /**
   * BindView annotated fields and methods in the specified {@code target} using the {@code source}
   * {@link Dialog} as the view root.
   *
   * @param target Target class for view binding.
   * @param source Dialog on which IDs will be looked up.
   */
  @NonNull @UiThread
  public static Unbinder bind(@NonNull Object target, @NonNull Dialog source) {
    View sourceView = source.getWindow().getDecorView();
    return bind(target, sourceView);
  }

  /**
   * BindView annotated fields and methods in the specified {@code target} using the {@code source}
   * {@link View} as the view root.
   *
   * @param target Target class for view binding.
   * @param source View root on which IDs will be looked up.
   */
  @NonNull @UiThread
  public static Unbinder bind(@NonNull Object target, @NonNull View source) {
    Class<?> targetClass = target.getClass();
    if (debug) Log.d(TAG, "Looking up binding for " + targetClass.getName());
    Constructor<? extends Unbinder> constructor = findBindingConstructorForClass(targetClass);

    if (constructor == null) {
      return Unbinder.EMPTY;
    }

    //noinspection TryWithIdenticalCatches Resolves to API 19+ only type.
    try {
      return constructor.newInstance(target, source);
    } catch (IllegalAccessException e) {
      throw new RuntimeException("Unable to invoke " + constructor, e);
    } catch (InstantiationException e) {
      throw new RuntimeException("Unable to invoke " + constructor, e);
    } catch (InvocationTargetException e) {
      Throwable cause = e.getCause();
      if (cause instanceof RuntimeException) {
        throw (RuntimeException) cause;
      }
      if (cause instanceof Error) {
        throw (Error) cause;
      }
      throw new RuntimeException("Unable to create binding instance.", cause);
    }
  }

  @Nullable @CheckResult @UiThread
  private static Constructor<? extends Unbinder> findBindingConstructorForClass(Class<?> cls) {
    Constructor<? extends Unbinder> bindingCtor = BINDINGS.get(cls);
    if (bindingCtor != null || BINDINGS.containsKey(cls)) {
      if (debug) Log.d(TAG, "HIT: Cached in binding map.");
      return bindingCtor;
    }
    String clsName = cls.getName();
    if (clsName.startsWith("android.") || clsName.startsWith("java.")
        || clsName.startsWith("androidx.")) {
      if (debug) Log.d(TAG, "MISS: Reached framework class. Abandoning search.");
      return null;
    }
    try {
      Class<?> bindingClass = cls.getClassLoader().loadClass(clsName + "_ViewBinding");
      //noinspection unchecked
      bindingCtor = (Constructor<? extends Unbinder>) bindingClass.getConstructor(cls, View.class);
      if (debug) Log.d(TAG, "HIT: Loaded binding class and constructor.");
    } catch (ClassNotFoundException e) {
      if (debug) Log.d(TAG, "Not found. Trying superclass " + cls.getSuperclass().getName());
      bindingCtor = findBindingConstructorForClass(cls.getSuperclass());
    } catch (NoSuchMethodException e) {
      throw new RuntimeException("Unable to find binding constructor for " + clsName, e);
    }
    BINDINGS.put(cls, bindingCtor);
    return bindingCtor;
  }
}


================================================
FILE: butterknife/src/main/java/butterknife/package-info.java
================================================
/**
 * Field and method binding for Android views which uses annotation processing to generate
 * boilerplate code for you.
 * <p>
 * <ul>
 * <li>Eliminate {@link android.view.View#findViewById findViewById} calls by using
 * {@link butterknife.BindView @BindView} on fields.</li>
 * <li>Group multiple views in a {@linkplain java.util.List list} or array.
 * <li>Eliminate anonymous inner-classes for listeners by annotating methods with
 * {@link butterknife.OnClick @OnClick} and others.</li>
 * <li>Eliminate resource lookups by using resource annotations on fields.</li>
 * </ul>
 */
package butterknife;


================================================
FILE: butterknife-annotations/build.gradle
================================================
apply plugin: 'java-library'
apply plugin: 'checkstyle'

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8

checkstyle {
  configFile rootProject.file('checkstyle.xml')
  showViolations true
}

dependencies {
  compileOnly deps.android.runtime
  api deps.androidx.annotations
}

apply from: rootProject.file('gradle/gradle-mvn-push.gradle')


================================================
FILE: butterknife-annotations/gradle.properties
================================================
POM_NAME=Butterknife Annotations
POM_ARTIFACT_ID=butterknife-annotations
POM_PACKAGING=jar


================================================
FILE: butterknife-annotations/src/main/java/butterknife/BindAnim.java
================================================
package butterknife;

import androidx.annotation.AnimRes;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a field to the specified animation resource ID.
 * <pre><code>
 * {@literal @}BindAnim(R.anim.fade_in) Animation fadeIn;
 * </code></pre>
 */
@Target(FIELD)
@Retention(RUNTIME)
public @interface BindAnim {
  /** Animation resource ID to which the field will be bound. */
  @AnimRes int value();
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/BindArray.java
================================================
package butterknife;

import androidx.annotation.ArrayRes;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a field to the specified array resource ID. The type of array will be inferred from the
 * annotated element.
 *
 * String array:
 * <pre><code>
 * {@literal @}BindArray(R.array.countries) String[] countries;
 * </code></pre>
 *
 * Int array:
 * <pre><code>
 * {@literal @}BindArray(R.array.phones) int[] phones;
 * </code></pre>
 *
 * Text array:
 * <pre><code>
 * {@literal @}BindArray(R.array.options) CharSequence[] options;
 * </code></pre>
 *
 * {@link android.content.res.TypedArray}:
 * <pre><code>
 * {@literal @}BindArray(R.array.icons) TypedArray icons;
 * </code></pre>
 */
@Retention(RUNTIME) @Target(FIELD)
public @interface BindArray {
  /** Array resource ID to which the field will be bound. */
  @ArrayRes int value();
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/BindBitmap.java
================================================
package butterknife;

import android.graphics.Bitmap;
import androidx.annotation.DrawableRes;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a field to a {@link Bitmap} from the specified drawable resource ID.
 * <pre><code>
 * {@literal @}BindBitmap(R.drawable.logo) Bitmap logo;
 * </code></pre>
 */
@Target(FIELD)
@Retention(RUNTIME)
public @interface BindBitmap {
  /** Drawable resource ID from which the {@link Bitmap} will be created. */
  @DrawableRes int value();
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/BindBool.java
================================================
package butterknife;

import androidx.annotation.BoolRes;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a field to the specified boolean resource ID.
 * <pre><code>
 * {@literal @}BindBool(R.bool.is_tablet) boolean isTablet;
 * </code></pre>
 */
@Target(FIELD)
@Retention(RUNTIME)
public @interface BindBool {
  /** Boolean resource ID to which the field will be bound. */
  @BoolRes int value();
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/BindColor.java
================================================
package butterknife;

import androidx.annotation.ColorRes;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a field to the specified color resource ID. Type can be {@code int} or
 * {@link android.content.res.ColorStateList}.
 * <pre><code>
 * {@literal @}BindColor(R.color.background_green) int green;
 * {@literal @}BindColor(R.color.background_green_selector) ColorStateList greenSelector;
 * </code></pre>
 */
@Target(FIELD)
@Retention(RUNTIME)
public @interface BindColor {
  /** Color resource ID to which the field will be bound. */
  @ColorRes int value();
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/BindDimen.java
================================================
package butterknife;

import androidx.annotation.DimenRes;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a field to the specified dimension resource ID. Type can be {@code int} for pixel size or
 * {@code float} for exact amount.
 * <pre><code>
 * {@literal @}BindDimen(R.dimen.horizontal_gap) int gapPx;
 * {@literal @}BindDimen(R.dimen.horizontal_gap) float gap;
 * </code></pre>
 */
@Target(FIELD)
@Retention(RUNTIME)
public @interface BindDimen {
  /** Dimension resource ID to which the field will be bound. */
  @DimenRes int value();
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/BindDrawable.java
================================================
package butterknife;

import androidx.annotation.AttrRes;
import androidx.annotation.DrawableRes;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static butterknife.internal.Constants.NO_RES_ID;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a field to the specified drawable resource ID.
 * <pre><code>
 * {@literal @}BindDrawable(R.drawable.placeholder)
 * Drawable placeholder;
 * {@literal @}BindDrawable(value = R.drawable.placeholder, tint = R.attr.colorAccent)
 * Drawable tintedPlaceholder;
 * </code></pre>
 */
@Target(FIELD)
@Retention(RUNTIME)
public @interface BindDrawable {
  /** Drawable resource ID to which the field will be bound. */
  @DrawableRes int value();

  /** Color attribute resource ID that is used to tint the drawable. */
  @AttrRes int tint() default NO_RES_ID;
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/BindFloat.java
================================================
package butterknife;

import androidx.annotation.DimenRes;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a field to the specified dimension resource ID whose type is explicitly defined as float.
 * <p>
 * This is different than simply reading a normal dimension as a float value which
 * {@link BindDimen @BindDimen} supports. The resource must be defined as a float like
 * {@code <item name="whatever" format="float" type="dimen">1.1</item>}.
 * <pre><code>
 * {@literal @}BindFloat(R.dimen.image_ratio) float imageRatio;
 * </code></pre>
 */
@Target(FIELD)
@Retention(RUNTIME)
public @interface BindFloat {
  /** Float resource ID to which the field will be bound. */
  @DimenRes int value();
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/BindFont.java
================================================
package butterknife;

import android.graphics.Typeface;
import androidx.annotation.FontRes;
import androidx.annotation.IntDef;
import androidx.annotation.RestrictTo;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static androidx.annotation.RestrictTo.Scope.LIBRARY;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a field to the specified font resource ID.
 * <pre><code>
 * {@literal @}BindFont(R.font.comic_sans) Typeface comicSans;
 * </code></pre>
 */
@Target(FIELD)
@Retention(RUNTIME)
public @interface BindFont {
  /** Font resource ID to which the field will be bound. */
  @FontRes int value();

  @TypefaceStyle int style() default Typeface.NORMAL;

  @IntDef({
      Typeface.NORMAL,
      Typeface.BOLD,
      Typeface.ITALIC,
      Typeface.BOLD_ITALIC
  })
  @RestrictTo(LIBRARY)
  @interface TypefaceStyle {
  }
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/BindInt.java
================================================
package butterknife;

import androidx.annotation.IntegerRes;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a field to the specified integer resource ID.
 * <pre><code>
 * {@literal @}BindInt(R.int.columns) int columns;
 * </code></pre>
 */
@Target(FIELD)
@Retention(RUNTIME)
public @interface BindInt {
  /** Integer resource ID to which the field will be bound. */
  @IntegerRes int value();
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/BindString.java
================================================
package butterknife;

import androidx.annotation.StringRes;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a field to the specified string resource ID.
 * <pre><code>
 * {@literal @}BindString(R.string.username_error) String usernameErrorText;
 * </code></pre>
 */
@Retention(RUNTIME) @Target(FIELD)
public @interface BindString {
  /** String resource ID to which the field will be bound. */
  @StringRes int value();
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/BindView.java
================================================
package butterknife;

import androidx.annotation.IdRes;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a field to the view for the specified ID. The view will automatically be cast to the field
 * type.
 * <pre><code>
 * {@literal @}BindView(R.id.title) TextView title;
 * </code></pre>
 */
@Retention(RUNTIME) @Target(FIELD)
public @interface BindView {
  /** View ID to which the field will be bound. */
  @IdRes int value();
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/BindViews.java
================================================
package butterknife;

import androidx.annotation.IdRes;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a field to the view for the specified ID. The view will automatically be cast to the field
 * type.
 * <pre><code>
 * {@literal @}BindViews({ R.id.title, R.id.subtitle })
 * List&lt;TextView&gt; titles;
 * </code></pre>
 */
@Retention(RUNTIME) @Target(FIELD)
public @interface BindViews {
  /** View IDs to which the field will be bound. */
  @IdRes int[] value();
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/OnCheckedChanged.java
================================================
package butterknife;

import android.view.View;
import androidx.annotation.IdRes;
import butterknife.internal.ListenerClass;
import butterknife.internal.ListenerMethod;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static android.widget.CompoundButton.OnCheckedChangeListener;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a method to an {@link OnCheckedChangeListener OnCheckedChangeListener} on the view for
 * each ID specified.
 * <pre><code>
 * {@literal @}OnCheckedChanged(R.id.example) void onChecked(boolean checked) {
 *   Toast.makeText(this, checked ? "Checked!" : "Unchecked!", Toast.LENGTH_SHORT).show();
 * }
 * </code></pre>
 * Any number of parameters from
 * {@link OnCheckedChangeListener#onCheckedChanged(android.widget.CompoundButton, boolean)
 * onCheckedChanged} may be used on the method.
 *
 * @see OnCheckedChangeListener
 */
@Target(METHOD)
@Retention(RUNTIME)
@ListenerClass(
    targetType = "android.widget.CompoundButton",
    setter = "setOnCheckedChangeListener",
    type = "android.widget.CompoundButton.OnCheckedChangeListener",
    method = @ListenerMethod(
        name = "onCheckedChanged",
        parameters = {
            "android.widget.CompoundButton",
            "boolean"
        }
    )
)
public @interface OnCheckedChanged {
  /** View IDs to which the method will be bound. */
  @IdRes int[] value() default { View.NO_ID };
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/OnClick.java
================================================
package butterknife;

import android.view.View;
import androidx.annotation.IdRes;
import butterknife.internal.ListenerClass;
import butterknife.internal.ListenerMethod;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static android.view.View.OnClickListener;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a method to an {@link OnClickListener OnClickListener} on the view for each ID specified.
 * <pre><code>
 * {@literal @}OnClick(R.id.example) void onClick() {
 *   Toast.makeText(this, "Clicked!", Toast.LENGTH_SHORT).show();
 * }
 * </code></pre>
 * Any number of parameters from
 * {@link OnClickListener#onClick(android.view.View) onClick} may be used on the
 * method.
 *
 * @see OnClickListener
 */
@Target(METHOD)
@Retention(RUNTIME)
@ListenerClass(
    targetType = "android.view.View",
    setter = "setOnClickListener",
    type = "butterknife.internal.DebouncingOnClickListener",
    method = @ListenerMethod(
        name = "doClick",
        parameters = "android.view.View"
    )
)
public @interface OnClick {
  /** View IDs to which the method will be bound. */
  @IdRes int[] value() default { View.NO_ID };
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/OnEditorAction.java
================================================
package butterknife;

import android.view.View;
import androidx.annotation.IdRes;
import butterknife.internal.ListenerClass;
import butterknife.internal.ListenerMethod;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static android.widget.TextView.OnEditorActionListener;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a method to an {@link OnEditorActionListener OnEditorActionListener} on the view for each
 * ID specified.
 * <pre><code>
 * {@literal @}OnEditorAction(R.id.example) boolean onEditorAction(KeyEvent key) {
 *   Toast.makeText(this, "Pressed: " + key, Toast.LENGTH_SHORT).show();
 *   return true;
 * }
 * </code></pre>
 * Any number of parameters from
 * {@link OnEditorActionListener#onEditorAction(android.widget.TextView, int, android.view.KeyEvent)
 * onEditorAction} may be used on the method.
 * <p>
 * If the return type of the method is {@code void}, true will be returned from the listener.
 *
 * @see OnEditorActionListener
 */
@Target(METHOD)
@Retention(RUNTIME)
@ListenerClass(
    targetType = "android.widget.TextView",
    setter = "setOnEditorActionListener",
    type = "android.widget.TextView.OnEditorActionListener",
    method = @ListenerMethod(
        name = "onEditorAction",
        parameters = {
            "android.widget.TextView",
            "int",
            "android.view.KeyEvent"
        },
        returnType = "boolean",
        defaultReturn = "true"
    )
)
public @interface OnEditorAction {
  /** View IDs to which the method will be bound. */
  @IdRes int[] value() default { View.NO_ID };
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/OnFocusChange.java
================================================
package butterknife;

import android.view.View;
import androidx.annotation.IdRes;
import butterknife.internal.ListenerClass;
import butterknife.internal.ListenerMethod;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static android.view.View.OnFocusChangeListener;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a method to an {@link OnFocusChangeListener OnFocusChangeListener} on the view for each ID
 * specified.
 * <pre><code>
 * {@literal @}OnFocusChange(R.id.example) void onFocusChanged(boolean focused) {
 *   Toast.makeText(this, focused ? "Gained focus" : "Lost focus", Toast.LENGTH_SHORT).show();
 * }
 * </code></pre>
 * Any number of parameters from {@link OnFocusChangeListener#onFocusChange(android.view.View,
 * boolean) onFocusChange} may be used on the method.
 *
 * @see OnFocusChangeListener
 */
@Target(METHOD)
@Retention(RUNTIME)
@ListenerClass(
    targetType = "android.view.View",
    setter = "setOnFocusChangeListener",
    type = "android.view.View.OnFocusChangeListener",
    method = @ListenerMethod(
        name = "onFocusChange",
        parameters = {
            "android.view.View",
            "boolean"
        }
    )
)
public @interface OnFocusChange {
  /** View IDs to which the method will be bound. */
  @IdRes int[] value() default { View.NO_ID };
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/OnItemClick.java
================================================
package butterknife;

import android.view.View;
import androidx.annotation.IdRes;
import butterknife.internal.ListenerClass;
import butterknife.internal.ListenerMethod;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static android.widget.AdapterView.OnItemClickListener;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a method to an {@link OnItemClickListener OnItemClickListener} on the view for each ID
 * specified.
 * <pre><code>
 * {@literal @}OnItemClick(R.id.example_list) void onItemClick(int position) {
 *   Toast.makeText(this, "Clicked position " + position + "!", Toast.LENGTH_SHORT).show();
 * }
 * </code></pre>
 * Any number of parameters from {@link OnItemClickListener#onItemClick(android.widget.AdapterView,
 * android.view.View, int, long) onItemClick} may be used on the method.
 *
 * @see OnItemClickListener
 */
@Target(METHOD)
@Retention(RUNTIME)
@ListenerClass(
    targetType = "android.widget.AdapterView<?>",
    setter = "setOnItemClickListener",
    type = "android.widget.AdapterView.OnItemClickListener",
    method = @ListenerMethod(
        name = "onItemClick",
        parameters = {
            "android.widget.AdapterView<?>",
            "android.view.View",
            "int",
            "long"
        }
    )
)
public @interface OnItemClick {
  /** View IDs to which the method will be bound. */
  @IdRes int[] value() default { View.NO_ID };
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/OnItemLongClick.java
================================================
package butterknife;

import android.view.View;
import androidx.annotation.IdRes;
import butterknife.internal.ListenerClass;
import butterknife.internal.ListenerMethod;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static android.widget.AdapterView.OnItemLongClickListener;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a method to an {@link OnItemLongClickListener OnItemLongClickListener} on the view for each
 * ID specified.
 * <pre><code>
 * {@literal @}OnItemLongClick(R.id.example_list) boolean onItemLongClick(int position) {
 *   Toast.makeText(this, "Long clicked position " + position + "!", Toast.LENGTH_SHORT).show();
 *   return true;
 * }
 * </code></pre>
 * Any number of parameters from
 * {@link OnItemLongClickListener#onItemLongClick(android.widget.AdapterView, android.view.View,
 * int, long) onItemLongClick} may be used on the method.
 * <p>
 * If the return type of the method is {@code void}, true will be returned from the listener.
 *
 * @see OnItemLongClickListener
 */
@Target(METHOD)
@Retention(RUNTIME)
@ListenerClass(
    targetType = "android.widget.AdapterView<?>",
    setter = "setOnItemLongClickListener",
    type = "android.widget.AdapterView.OnItemLongClickListener",
    method = @ListenerMethod(
        name = "onItemLongClick",
        parameters = {
            "android.widget.AdapterView<?>",
            "android.view.View",
            "int",
            "long"
        },
        returnType = "boolean",
        defaultReturn = "true"
    )
)
public @interface OnItemLongClick {
  /** View IDs to which the method will be bound. */
  @IdRes int[] value() default { View.NO_ID };
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/OnItemSelected.java
================================================
package butterknife;

import android.view.View;
import androidx.annotation.IdRes;
import butterknife.internal.ListenerClass;
import butterknife.internal.ListenerMethod;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static android.widget.AdapterView.OnItemSelectedListener;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.CLASS;

/**
 * Bind a method to an {@link OnItemSelectedListener OnItemSelectedListener} on the view for each
 * ID specified.
 * <pre><code>
 * {@literal @}OnItemSelected(R.id.example_list) void onItemSelected(int position) {
 *   Toast.makeText(this, "Selected position " + position + "!", Toast.LENGTH_SHORT).show();
 * }
 * </code></pre>
 * Any number of parameters from
 * {@link OnItemSelectedListener#onItemSelected(android.widget.AdapterView, android.view.View, int,
 * long) onItemSelected} may be used on the method.
 * <p>
 * To bind to methods other than {@code onItemSelected}, specify a different {@code callback}.
 * <pre><code>
 * {@literal @}OnItemSelected(value = R.id.example_list, callback = NOTHING_SELECTED)
 * void onNothingSelected() {
 *   Toast.makeText(this, "Nothing selected!", Toast.LENGTH_SHORT).show();
 * }
 * </code></pre>
 *
 * @see OnItemSelectedListener
 */
@Target(METHOD)
@Retention(CLASS)
@ListenerClass(
    targetType = "android.widget.AdapterView<?>",
    setter = "setOnItemSelectedListener",
    type = "android.widget.AdapterView.OnItemSelectedListener",
    callbacks = OnItemSelected.Callback.class
)
public @interface OnItemSelected {
  /** View IDs to which the method will be bound. */
  @IdRes int[] value() default { View.NO_ID };

  /** Listener callback to which the method will be bound. */
  Callback callback() default Callback.ITEM_SELECTED;

  /** {@link OnItemSelectedListener} callback methods. */
  enum Callback {
    /**
     * {@link OnItemSelectedListener#onItemSelected(android.widget.AdapterView, android.view.View,
     * int, long)}
     */
    @ListenerMethod(
        name = "onItemSelected",
        parameters = {
            "android.widget.AdapterView<?>",
            "android.view.View",
            "int",
            "long"
        }
    )
    ITEM_SELECTED,

    /** {@link OnItemSelectedListener#onNothingSelected(android.widget.AdapterView)} */
    @ListenerMethod(
        name = "onNothingSelected",
        parameters = "android.widget.AdapterView<?>"
    )
    NOTHING_SELECTED
  }
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/OnLongClick.java
================================================
package butterknife;

import android.view.View;
import androidx.annotation.IdRes;
import butterknife.internal.ListenerClass;
import butterknife.internal.ListenerMethod;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static android.view.View.OnLongClickListener;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a method to an {@link OnLongClickListener OnLongClickListener} on the view for each ID
 * specified.
 * <pre><code>
 * {@literal @}OnLongClick(R.id.example) boolean onLongClick() {
 *   Toast.makeText(this, "Long clicked!", Toast.LENGTH_SHORT).show();
 *   return true;
 * }
 * </code></pre>
 * Any number of parameters from {@link OnLongClickListener#onLongClick(android.view.View)} may be
 * used on the method.
 * <p>
 * If the return type of the method is {@code void}, true will be returned from the listener.
 *
 * @see OnLongClickListener
 */
@Target(METHOD)
@Retention(RUNTIME)
@ListenerClass(
    targetType = "android.view.View",
    setter = "setOnLongClickListener",
    type = "android.view.View.OnLongClickListener",
    method = @ListenerMethod(
        name = "onLongClick",
        parameters = {
            "android.view.View"
        },
        returnType = "boolean",
        defaultReturn = "true"
    )
)
public @interface OnLongClick {
  /** View IDs to which the method will be bound. */
  @IdRes int[] value() default { View.NO_ID };
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/OnPageChange.java
================================================
package butterknife;

import android.view.View;
import androidx.annotation.IdRes;
import butterknife.internal.ListenerClass;
import butterknife.internal.ListenerMethod;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a method to an {@code OnPageChangeListener} on the view for each ID specified.
 * <pre><code>
 * {@literal @}OnPageChange(R.id.example_pager) void onPageSelected(int position) {
 *   Toast.makeText(this, "Selected " + position + "!", Toast.LENGTH_SHORT).show();
 * }
 * </code></pre>
 * Any number of parameters from {@code onPageSelected} may be used on the method.
 * <p>
 * To bind to methods other than {@code onPageSelected}, specify a different {@code callback}.
 * <pre><code>
 * {@literal @}OnPageChange(value = R.id.example_pager, callback = PAGE_SCROLL_STATE_CHANGED)
 * void onPageStateChanged(int state) {
 *   Toast.makeText(this, "State changed: " + state + "!", Toast.LENGTH_SHORT).show();
 * }
 * </code></pre>
 */
@Target(METHOD)
@Retention(RUNTIME)
@ListenerClass(
    targetType = "androidx.viewpager.widget.ViewPager",
    setter = "addOnPageChangeListener",
    remover = "removeOnPageChangeListener",
    type = "androidx.viewpager.widget.ViewPager.OnPageChangeListener",
    callbacks = OnPageChange.Callback.class
)
public @interface OnPageChange {
  /** View IDs to which the method will be bound. */
  @IdRes int[] value() default { View.NO_ID };

  /** Listener callback to which the method will be bound. */
  Callback callback() default Callback.PAGE_SELECTED;

  /** {@code ViewPager.OnPageChangeListener} callback methods. */
  enum Callback {
    /** {@code onPageSelected(int)} */
    @ListenerMethod(
        name = "onPageSelected",
        parameters = "int"
    )
    PAGE_SELECTED,

    /** {@code onPageScrolled(int, float, int)} */
    @ListenerMethod(
        name = "onPageScrolled",
        parameters = {
            "int",
            "float",
            "int"
        }
    )
    PAGE_SCROLLED,

    /** {@code onPageScrollStateChanged(int)} */
    @ListenerMethod(
        name = "onPageScrollStateChanged",
        parameters = "int"
    )
    PAGE_SCROLL_STATE_CHANGED,
  }
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/OnTextChanged.java
================================================
package butterknife;

import android.text.TextWatcher;
import android.view.View;
import androidx.annotation.IdRes;
import butterknife.internal.ListenerClass;
import butterknife.internal.ListenerMethod;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a method to a {@link TextWatcher TextWatcher} on the view for each ID specified.
 * <pre><code>
 * {@literal @}OnTextChanged(R.id.example) void onTextChanged(CharSequence text) {
 *   Toast.makeText(this, "Text changed: " + text, Toast.LENGTH_SHORT).show();
 * }
 * </code></pre>
 * Any number of parameters from {@link TextWatcher#onTextChanged(CharSequence, int, int, int)
 * onTextChanged} may be used on the method.
 * <p>
 * To bind to methods other than {@code onTextChanged}, specify a different {@code callback}.
 * <pre><code>
 * {@literal @}OnTextChanged(value = R.id.example, callback = BEFORE_TEXT_CHANGED)
 * void onBeforeTextChanged(CharSequence text) {
 *   Toast.makeText(this, "Before text changed: " + text, Toast.LENGTH_SHORT).show();
 * }
 * </code></pre>
 *
 * @see TextWatcher
 */
@Target(METHOD)
@Retention(RUNTIME)
@ListenerClass(
    targetType = "android.widget.TextView",
    setter = "addTextChangedListener",
    remover = "removeTextChangedListener",
    type = "android.text.TextWatcher",
    callbacks = OnTextChanged.Callback.class
)
public @interface OnTextChanged {
  /** View IDs to which the method will be bound. */
  @IdRes int[] value() default { View.NO_ID };

  /** Listener callback to which the method will be bound. */
  Callback callback() default Callback.TEXT_CHANGED;

  /** {@link TextWatcher} callback methods. */
  enum Callback {
    /** {@link TextWatcher#onTextChanged(CharSequence, int, int, int)} */
    @ListenerMethod(
        name = "onTextChanged",
        parameters = {
            "java.lang.CharSequence",
            "int",
            "int",
            "int"
        }
    )
    TEXT_CHANGED,

    /** {@link TextWatcher#beforeTextChanged(CharSequence, int, int, int)} */
    @ListenerMethod(
        name = "beforeTextChanged",
        parameters = {
            "java.lang.CharSequence",
            "int",
            "int",
            "int"
        }
    )
    BEFORE_TEXT_CHANGED,

    /** {@link TextWatcher#afterTextChanged(android.text.Editable)} */
    @ListenerMethod(
        name = "afterTextChanged",
        parameters = "android.text.Editable"
    )
    AFTER_TEXT_CHANGED,
  }
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/OnTouch.java
================================================
package butterknife;

import android.view.View;
import androidx.annotation.IdRes;
import butterknife.internal.ListenerClass;
import butterknife.internal.ListenerMethod;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static android.view.View.OnTouchListener;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Bind a method to an {@link OnTouchListener OnTouchListener} on the view for each ID specified.
 * <pre><code>
 * {@literal @}OnTouch(R.id.example) boolean onTouch() {
 *   Toast.makeText(this, "Touched!", Toast.LENGTH_SHORT).show();
 *   return false;
 * }
 * </code></pre>
 * Any number of parameters from
 * {@link OnTouchListener#onTouch(android.view.View, android.view.MotionEvent) onTouch} may be used
 * on the method.
 * <p>
 * If the return type of the method is {@code void}, true will be returned from the listener.
 *
 * @see OnTouchListener
 */
@Target(METHOD)
@Retention(RUNTIME)
@ListenerClass(
    targetType = "android.view.View",
    setter = "setOnTouchListener",
    type = "android.view.View.OnTouchListener",
    method = @ListenerMethod(
        name = "onTouch",
        parameters = {
            "android.view.View",
            "android.view.MotionEvent"
        },
        returnType = "boolean",
        defaultReturn = "true"
    )
)
public @interface OnTouch {
  /** View IDs to which the method will be bound. */
  @IdRes int[] value() default { View.NO_ID };
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/Optional.java
================================================
package butterknife;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Denote that the view specified by the injection is not required to be present.
 * <pre><code>
 * {@literal @}Optional @OnClick(R.id.subtitle) void onSubtitleClick() {}
 * </code></pre>
 */
@Target(METHOD)
@Retention(RUNTIME)
public @interface Optional {
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/internal/Constants.java
================================================
package butterknife.internal;

public class Constants {

  private Constants() { }

  public static final int NO_RES_ID = -1;
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/internal/ListenerClass.java
================================================
package butterknife.internal;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Retention(RUNTIME) @Target(ANNOTATION_TYPE)
public @interface ListenerClass {
  String targetType();

  /** Name of the setter method on the {@linkplain #targetType() target type} for the listener. */
  String setter();

  /**
   * Name of the method on the {@linkplain #targetType() target type} to remove the listener. If
   * empty {@link #setter()} will be used by default.
   */
  String remover() default "";

  /** Fully-qualified class name of the listener type. */
  String type();

  /** Enum which declares the listener callback methods. Mutually exclusive to {@link #method()}. */
  Class<? extends Enum<?>> callbacks() default NONE.class;

  /**
   * Method data for single-method listener callbacks. Mutually exclusive with {@link #callbacks()}
   * and an error to specify more than one value.
   */
  ListenerMethod[] method() default { };

  /** Default value for {@link #callbacks()}. */
  enum NONE { }
}


================================================
FILE: butterknife-annotations/src/main/java/butterknife/internal/ListenerMethod.java
================================================
package butterknife.internal;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Retention(RUNTIME) @Target(FIELD)
public @interface ListenerMethod {
  /** Name of the listener method for which this annotation applies. */
  String name();

  /** List of method parameters. If the type is not a primitive it must be fully-qualified. */
  String[] parameters() default { };

  /** Primitive or fully-qualified return type of the listener method. May also be {@code void}. */
  String returnType() default "void";

  /** If {@link #returnType()} is not {@code void} this value is returned when no binding exists. */
  String defaultReturn() default "null";
}


================================================
FILE: butterknife-compiler/build.gradle
================================================
apply plugin: 'java-library'
apply plugin: 'checkstyle'

sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8

dependencies {
  implementation project(':butterknife-annotations')
  implementation deps.auto.common
  implementation deps.guava
  api deps.javapoet
  compileOnly deps.auto.service
  compileOnly files(org.gradle.internal.jvm.Jvm.current().getToolsJar())

  api deps.incap.runtime
  compileOnly deps.incap.processor

  testImplementation deps.junit
  testImplementation deps.truth
}

checkstyle {
  configFile rootProject.file('checkstyle.xml')
  showViolations true
  //Remove this when tests are less verbose, i.e. using JavaPoet
  sourceSets = [sourceSets.main]
}

apply from: rootProject.file('gradle/gradle-mvn-push.gradle')


================================================
FILE: butterknife-compiler/gradle.properties
================================================
POM_NAME=Butterknife Compiler
POM_ARTIFACT_ID=butterknife-compiler
POM_PACKAGING=jar


================================================
FILE: butterknife-compiler/src/main/java/butterknife/compiler/BindingSet.java
================================================
package butterknife.compiler;

import butterknife.OnTouch;
import butterknife.internal.ListenerClass;
import butterknife.internal.ListenerMethod;
import com.google.common.collect.ImmutableList;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import com.squareup.javapoet.WildcardTypeName;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;

import static butterknife.compiler.ButterKnifeProcessor.ACTIVITY_TYPE;
import static butterknife.compiler.ButterKnifeProcessor.DIALOG_TYPE;
import static butterknife.compiler.ButterKnifeProcessor.VIEW_TYPE;
import static butterknife.compiler.ButterKnifeProcessor.isSubtypeOfType;
import static com.google.auto.common.MoreElements.getPackage;
import static java.util.Collections.singletonList;
import static java.util.Objects.requireNonNull;
import static javax.lang.model.element.Modifier.FINAL;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.PUBLIC;

/** A set of all the bindings requested by a single type. */
final class BindingSet implements BindingInformationProvider {
  static final ClassName UTILS = ClassName.get("butterknife.internal", "Utils");
  private static final ClassName VIEW = ClassName.get("android.view", "View");
  private static final ClassName CONTEXT = ClassName.get("android.content", "Context");
  private static final ClassName RESOURCES = ClassName.get("android.content.res", "Resources");
  private static final ClassName UI_THREAD =
      ClassName.get("androidx.annotation", "UiThread");
  private static final ClassName CALL_SUPER =
      ClassName.get("androidx.annotation", "CallSuper");
  private static final ClassName SUPPRESS_LINT =
      ClassName.get("android.annotation", "SuppressLint");
  private static final ClassName UNBINDER = ClassName.get("butterknife", "Unbinder");
  static final ClassName BITMAP_FACTORY = ClassName.get("android.graphics", "BitmapFactory");
  static final ClassName CONTEXT_COMPAT =
      ClassName.get("androidx.core.content", "ContextCompat");
  static final ClassName ANIMATION_UTILS =
          ClassName.get("android.view.animation", "AnimationUtils");

  private final TypeName targetTypeName;
  private final ClassName bindingClassName;
  private final TypeElement enclosingElement;
  private final boolean isFinal;
  private final boolean isView;
  private final boolean isActivity;
  private final boolean isDialog;
  private final ImmutableList<ViewBinding> viewBindings;
  private final ImmutableList<FieldCollectionViewBinding> collectionBindings;
  private final ImmutableList<ResourceBinding> resourceBindings;
  private final @Nullable BindingInformationProvider parentBinding;

  private BindingSet(
      TypeName targetTypeName, ClassName bindingClassName, TypeElement enclosingElement,
      boolean isFinal, boolean isView, boolean isActivity, boolean isDialog,
      ImmutableList<ViewBinding> viewBindings,
      ImmutableList<FieldCollectionViewBinding> collectionBindings,
      ImmutableList<ResourceBinding> resourceBindings,
      @Nullable BindingInformationProvider parentBinding) {
    this.isFinal = isFinal;
    this.targetTypeName = targetTypeName;
    this.bindingClassName = bindingClassName;
    this.enclosingElement = enclosingElement;
    this.isView = isView;
    this.isActivity = isActivity;
    this.isDialog = isDialog;
    this.viewBindings = viewBindings;
    this.collectionBindings = collectionBindings;
    this.resourceBindings = resourceBindings;
    this.parentBinding = parentBinding;
  }

  @Override
  public ClassName getBindingClassName() {
    return bindingClassName;
  }

  JavaFile brewJava(int sdk, boolean debuggable) {
    TypeSpec bindingConfiguration = createType(sdk, debuggable);
    return JavaFile.builder(bindingClassName.packageName(), bindingConfiguration)
        .addFileComment("Generated code from Butter Knife. Do not modify!")
        .build();
  }

  private TypeSpec createType(int sdk, boolean debuggable) {
    TypeSpec.Builder result = TypeSpec.classBuilder(bindingClassName.simpleName())
        .addModifiers(PUBLIC)
        .addOriginatingElement(enclosingElement);
    if (isFinal) {
      result.addModifiers(FINAL);
    }

    if (parentBinding != null) {
      result.superclass(parentBinding.getBindingClassName());
    } else {
      result.addSuperinterface(UNBINDER);
    }

    if (hasTargetField()) {
      result.addField(targetTypeName, "target", PRIVATE);
    }

    if (isView) {
      result.addMethod(createBindingConstructorForView());
    } else if (isActivity) {
      result.addMethod(createBindingConstructorForActivity());
    } else if (isDialog) {
      result.addMethod(createBindingConstructorForDialog());
    }
    if (!constructorNeedsView()) {
      // Add a delegating constructor with a target type + view signature for reflective use.
      result.addMethod(createBindingViewDelegateConstructor());
    }
    result.addMethod(createBindingConstructor(sdk, debuggable));

    if (hasViewBindings() || parentBinding == null) {
      result.addMethod(createBindingUnbindMethod(result));
    }

    return result.build();
  }

  private MethodSpec createBindingViewDelegateConstructor() {
    return MethodSpec.constructorBuilder()
        .addJavadoc("@deprecated Use {@link #$T($T, $T)} for direct creation.\n    "
                + "Only present for runtime invocation through {@code ButterKnife.bind()}.\n",
            bindingClassName, targetTypeName, CONTEXT)
        .addAnnotation(Deprecated.class)
        .addAnnotation(UI_THREAD)
        .addModifiers(PUBLIC)
        .addParameter(targetTypeName, "target")
        .addParameter(VIEW, "source")
        .addStatement(("this(target, source.getContext())"))
        .build();
  }

  private MethodSpec createBindingConstructorForView() {
    MethodSpec.Builder builder = MethodSpec.constructorBuilder()
        .addAnnotation(UI_THREAD)
        .addModifiers(PUBLIC)
        .addParameter(targetTypeName, "target");
    if (constructorNeedsView()) {
      builder.addStatement("this(target, target)");
    } else {
      builder.addStatement("this(target, target.getContext())");
    }
    return builder.build();
  }

  private MethodSpec createBindingConstructorForActivity() {
    MethodSpec.Builder builder = MethodSpec.constructorBuilder()
        .addAnnotation(UI_THREAD)
        .addModifiers(PUBLIC)
        .addParameter(targetTypeName, "target");
    if (constructorNeedsView()) {
      builder.addStatement("this(target, target.getWindow().getDecorView())");
    } else {
      builder.addStatement("this(target, target)");
    }
    return builder.build();
  }

  private MethodSpec createBindingConstructorForDialog() {
    MethodSpec.Builder builder = MethodSpec.constructorBuilder()
        .addAnnotation(UI_THREAD)
        .addModifiers(PUBLIC)
        .addParameter(targetTypeName, "target");
    if (constructorNeedsView()) {
      builder.addStatement("this(target, target.getWindow().getDecorView())");
    } else {
      builder.addStatement("this(target, target.getContext())");
    }
    return builder.build();
  }

  private MethodSpec createBindingConstructor(int sdk, boolean debuggable) {
    MethodSpec.Builder constructor = MethodSpec.constructorBuilder()
        .addAnnotation(UI_THREAD)
        .addModifiers(PUBLIC);

    if (hasMethodBindings()) {
      constructor.addParameter(targetTypeName, "target", FINAL);
    } else {
      constructor.addParameter(targetTypeName, "target");
    }

    if (constructorNeedsView()) {
      constructor.addParameter(VIEW, "source");
    } else {
      constructor.addParameter(CONTEXT, "context");
    }

    if (hasUnqualifiedResourceBindings()) {
      // Aapt can change IDs out from underneath us, just suppress since all will work at runtime.
      constructor.addAnnotation(AnnotationSpec.builder(SuppressWarnings.class)
          .addMember("value", "$S", "ResourceType")
          .build());
    }

    if (hasOnTouchMethodBindings()) {
      constructor.addAnnotation(AnnotationSpec.builder(SUPPRESS_LINT)
          .addMember("value", "$S", "ClickableViewAccessibility")
          .build());
    }

    if (parentBinding != null) {
      if (parentBinding.constructorNeedsView()) {
        constructor.addStatement("super(target, source)");
      } else if (constructorNeedsView()) {
        constructor.addStatement("super(target, source.getContext())");
      } else {
        constructor.addStatement("super(target, context)");
      }
      constructor.addCode("\n");
    }
    if (hasTargetField()) {
      constructor.addStatement("this.target = target");
      constructor.addCode("\n");
    }

    if (hasViewBindings()) {
      if (hasViewLocal()) {
        // Local variable in which all views will be temporarily stored.
        constructor.addStatement("$T view", VIEW);
      }
      for (ViewBinding binding : viewBindings) {
        addViewBinding(constructor, binding, debuggable);
      }
      for (FieldCollectionViewBinding binding : collectionBindings) {
        constructor.addStatement("$L", binding.render(debuggable));
      }

      if (!resourceBindings.isEmpty()) {
        constructor.addCode("\n");
      }
    }

    if (!resourceBindings.isEmpty()) {
      if (constructorNeedsView()) {
        constructor.addStatement("$T context = source.getContext()", CONTEXT);
      }
      if (hasResourceBindingsNeedingResource(sdk)) {
        constructor.addStatement("$T res = context.getResources()", RESOURCES);
      }
      for (ResourceBinding binding : resourceBindings) {
        constructor.addStatement("$L", binding.render(sdk));
      }
    }

    return constructor.build();
  }

  private MethodSpec createBindingUnbindMethod(TypeSpec.Builder bindingClass) {
    MethodSpec.Builder result = MethodSpec.methodBuilder("unbind")
        .addAnnotation(Override.class)
        .addModifiers(PUBLIC);
    if (!isFinal && parentBinding == null) {
      result.addAnnotation(CALL_SUPER);
    }

    if (hasTargetField()) {
      if (hasFieldBindings()) {
        result.addStatement("$T target = this.target", targetTypeName);
      }
      result.addStatement("if (target == null) throw new $T($S)", IllegalStateException.class,
          "Bindings already cleared.");
      result.addStatement("$N = null", hasFieldBindings() ? "this.target" : "target");
      result.addCode("\n");
      for (ViewBinding binding : viewBindings) {
        if (binding.getFieldBinding() != null) {
          result.addStatement("target.$L = null", binding.getFieldBinding().getName());
        }
      }
      for (FieldCollectionViewBinding binding : collectionBindings) {
        result.addStatement("target.$L = null", binding.name);
      }
    }

    if (hasMethodBindings()) {
      result.addCode("\n");
      for (ViewBinding binding : viewBindings) {
        addFieldAndUnbindStatement(bindingClass, result, binding);
      }
    }

    if (parentBinding != null) {
      result.addCode("\n");
      result.addStatement("super.unbind()");
    }
    return result.build();
  }

  private void addFieldAndUnbindStatement(TypeSpec.Builder result, MethodSpec.Builder unbindMethod,
      ViewBinding bindings) {
    // Only add fields to the binding if there are method bindings.
    Map<ListenerClass, Map<ListenerMethod, Set<MethodViewBinding>>> classMethodBindings =
        bindings.getMethodBindings();
    if (classMethodBindings.isEmpty()) {
      return;
    }

    String fieldName =
        bindings.isBoundToRoot()
            ? "viewSource"
            : "view" + Integer.toHexString(bindings.getId().value);
    result.addField(VIEW, fieldName, PRIVATE);

    // We only need to emit the null check if there are zero required bindings.
    boolean needsNullChecked = bindings.getRequiredBindings().isEmpty();
    if (needsNullChecked) {
      unbindMethod.beginControlFlow("if ($N != null)", fieldName);
    }

    for (ListenerClass listenerClass : classMethodBindings.keySet()) {
      // We need to keep a reference to the listener
      // in case we need to unbind it via a remove method.
      boolean requiresRemoval = !"".equals(listenerClass.remover());
      String listenerField = "null";
      if (requiresRemoval) {
        TypeName listenerClassName = bestGuess(listenerClass.type());
        listenerField = fieldName + ((ClassName) listenerClassName).simpleName();
        result.addField(listenerClassName, listenerField, PRIVATE);
      }

      String targetType = listenerClass.targetType();
      if (!VIEW_TYPE.equals(targetType)) {
        unbindMethod.addStatement("(($T) $N).$N($N)", bestGuess(targetType),
            fieldName, removerOrSetter(listenerClass, requiresRemoval), listenerField);
      } else {
        unbindMethod.addStatement("$N.$N($N)", fieldName,
            removerOrSetter(listenerClass, requiresRemoval), listenerField);
      }

      if (requiresRemoval) {
        unbindMethod.addStatement("$N = null", listenerField);
      }
    }

    unbindMethod.addStatement("$N = null", fieldName);

    if (needsNullChecked) {
      unbindMethod.endControlFlow();
    }
  }

  private String removerOrSetter(ListenerClass listenerClass, boolean requiresRemoval) {
    return requiresRemoval
        ? listenerClass.remover()
        : listenerClass.setter();
  }

  private void addViewBinding(MethodSpec.Builder result, ViewBinding binding, boolean debuggable) {
    if (binding.isSingleFieldBinding()) {
      // Optimize the common case where there's a single binding directly to a field.
      FieldViewBinding fieldBinding = requireNonNull(binding.getFieldBinding());
      CodeBlock.Builder builder = CodeBlock.builder()
          .add("target.$L = ", fieldBinding.getName());

      boolean requiresCast = requiresCast(fieldBinding.getType());
      if (!debuggable || (!requiresCast && !fieldBinding.isRequired())) {
        if (requiresCast) {
          builder.add("($T) ", fieldBinding.getType());
        }
        builder.add("source.findViewById($L)", binding.getId().code);
      } else {
        builder.add("$T.find", UTILS);
        builder.add(fieldBinding.isRequired() ? "RequiredView" : "OptionalView");
        if (requiresCast) {
          builder.add("AsType");
        }
        builder.add("(source, $L", binding.getId().code);
        if (fieldBinding.isRequired() || requiresCast) {
          builder.add(", $S", asHumanDescription(singletonList(fieldBinding)));
        }
        if (requiresCast) {
          builder.add(", $T.class", fieldBinding.getRawType());
        }
        builder.add(")");
      }
      result.addStatement("$L", builder.build());
      return;
    }

    List<MemberViewBinding> requiredBindings = binding.getRequiredBindings();
    if (!debuggable || requiredBindings.isEmpty()) {
      result.addStatement("view = source.findViewById($L)", binding.getId().code);
    } else if (!binding.isBoundToRoot()) {
      result.addStatement("view = $T.findRequiredView(source, $L, $S)", UTILS,
          binding.getId().code, asHumanDescription(requiredBindings));
    }

    addFieldBinding(result, binding, debuggable);
    addMethodBindings(result, binding, debuggable);
  }

  private void addFieldBinding(MethodSpec.Builder result, ViewBinding binding, boolean debuggable) {
    FieldViewBinding fieldBinding = binding.getFieldBinding();
    if (fieldBinding != null) {
      if (requiresCast(fieldBinding.getType())) {
        if (debuggable) {
          result.addStatement("target.$L = $T.castView(view, $L, $S, $T.class)",
              fieldBinding.getName(), UTILS, binding.getId().code,
              asHumanDescription(singletonList(fieldBinding)), fieldBinding.getRawType());
        } else {
          result.addStatement("target.$L = ($T) view", fieldBinding.getName(),
              fieldBinding.getType());
        }
      } else {
        result.addStatement("target.$L = view", fieldBinding.getName());
      }
    }
  }

  private void addMethodBindings(MethodSpec.Builder result, ViewBinding binding,
      boolean debuggable) {
    Map<ListenerClass, Map<ListenerMethod, Set<MethodViewBinding>>> classMethodBindings =
        binding.getMethodBindings();
    if (classMethodBindings.isEmpty()) {
      return;
    }

    // We only need to emit the null check if there are zero required bindings.
    boolean needsNullChecked = binding.getRequiredBindings().isEmpty();
    if (needsNullChecked) {
      result.beginControlFlow("if (view != null)");
    }

    // Add the view reference to the binding.
    String fieldName = "viewSource";
    String bindName = "source";
    if (!binding.isBoundToRoot()) {
      fieldName = "view" + Integer.toHexString(binding.getId().value);
      bindName = "view";
    }
    result.addStatement("$L = $N", fieldName, bindName);

    for (Map.Entry<ListenerClass, Map<ListenerMethod, Set<MethodViewBinding>>> e
        : classMethodBindings.entrySet()) {
      ListenerClass listener = e.getKey();
      Map<ListenerMethod, Set<MethodViewBinding>> methodBindings = e.getValue();

      TypeSpec.Builder callback = TypeSpec.anonymousClassBuilder("")
          .superclass(ClassName.bestGuess(listener.type()));

      for (ListenerMethod method : getListenerMethods(listener)) {
        MethodSpec.Builder callbackMethod = MethodSpec.methodBuilder(method.name())
            .addAnnotation(Override.class)
            .addModifiers(PUBLIC)
            .returns(bestGuess(method.returnType()));
        String[] parameterTypes = method.parameters();
        for (int i = 0, count = parameterTypes.length; i < count; i++) {
          callbackMethod.addParameter(bestGuess(parameterTypes[i]), "p" + i);
        }

        boolean hasReturnValue = false;
        CodeBlock.Builder builder = CodeBlock.builder();
        Set<MethodViewBinding> methodViewBindings = methodBindings.get(method);
        if (methodViewBindings != null) {
          for (MethodViewBinding methodBinding : methodViewBindings) {
            if (methodBinding.hasReturnValue()) {
              hasReturnValue = true;
              builder.add("return "); // TODO what about multiple methods?
            }
            builder.add("target.$L(", methodBinding.getName());
            List<Parameter> parameters = methodBinding.getParameters();
            String[] listenerParameters = method.parameters();
            for (int i = 0, count = parameters.size(); i < count; i++) {
              if (i > 0) {
                builder.add(", ");
              }

              Parameter parameter = parameters.get(i);
              int listenerPosition = parameter.getListenerPosition();

              if (parameter.requiresCast(listenerParameters[listenerPosition])) {
                if (debuggable) {
                  builder.add("$T.castParam(p$L, $S, $L, $S, $L, $T.class)", UTILS,
                      listenerPosition, method.name(), listenerPosition, methodBinding.getName(), i,
                      parameter.getType());
                } else {
                  builder.add("($T) p$L", parameter.getType(), listenerPosition);
                }
              } else {
                builder.add("p$L", listenerPosition);
              }
            }
            builder.add(");\n");
          }
        }

        if (!"void".equals(method.returnType()) && !hasReturnValue) {
          builder.add("return $L;\n", method.defaultReturn());
        }

        callbackMethod.addCode(builder.build());
        callback.addMethod(callbackMethod.build());
      }

      boolean requiresRemoval = listener.remover().length() != 0;
      String listenerField = null;
      if (requiresRemoval) {
        TypeName listenerClassName = bestGuess(listener.type());
        listenerField = fieldName + ((ClassName) listenerClassName).simpleName();
        result.addStatement("$L = $L", listenerField, callback.build());
      }

      String targetType = listener.targetType();
      if (!VIEW_TYPE.equals(targetType)) {
        result.addStatement("(($T) $N).$L($L)", bestGuess(targetType), bindName,
            listener.setter(), requiresRemoval ? listenerField : callback.build());
      } else {
        result.addStatement("$N.$L($L)", bindName, listener.setter(),
            requiresRemoval ? listenerField : callback.build());
      }
    }

    if (needsNullChecked) {
      result.endControlFlow();
    }
  }

  private static List<ListenerMethod> getListenerMethods(ListenerClass listener) {
    if (listener.method().length == 1) {
      return Arrays.asList(listener.method());
    }

    try {
      List<ListenerMethod> methods = new ArrayList<>();
      Class<? extends Enum<?>> callbacks = listener.callbacks();
      for (Enum<?> callbackMethod : callbacks.getEnumConstants()) {
        Field callbackField = callbacks.getField(callbackMethod.name());
        ListenerMethod method = callbackField.getAnnotation(ListenerMethod.class);
        if (method == null) {
          throw new IllegalStateException(String.format("@%s's %s.%s missing @%s annotation.",
              callbacks.getEnclosingClass().getSimpleName(), callbacks.getSimpleName(),
              callbackMethod.name(), ListenerMethod.class.getSimpleName()));
        }
        methods.add(method);
      }
      return methods;
    } catch (NoSuchFieldException e) {
      throw new AssertionError(e);
    }
  }

  static String asHumanDescription(Collection<? extends MemberViewBinding> bindings) {
    Iterator<? extends MemberViewBinding> iterator = bindings.iterator();
    switch (bindings.size()) {
      case 1:
        return iterator.next().getDescription();
      case 2:
        return iterator.next().getDescription() + " and " + iterator.next().getDescription();
      default:
        StringBuilder builder = new StringBuilder();
        for (int i = 0, count = bindings.size(); i < count; i++) {
          if (i != 0) {
            builder.append(", ");
          }
          if (i == count - 1) {
            builder.append("and ");
          }
          builder.append(iterator.next().getDescription());
        }
        return builder.toString();
    }
  }

  private static TypeName bestGuess(String type) {
    switch (type) {
      case "void": return TypeName.VOID;
      case "boolean": return TypeName.BOOLEAN;
      case "byte": return TypeName.BYTE;
      case "char": return TypeName.CHAR;
      case "double": return TypeName.DOUBLE;
      case "float": return TypeName.FLOAT;
      case "int": return TypeName.INT;
      case "long": return TypeName.LONG;
      case "short": return TypeName.SHORT;
      default:
        int left = type.indexOf('<');
        if (left != -1) {
          ClassName typeClassName = ClassName.bestGuess(type.substring(0, left));
          List<TypeName> typeArguments = new ArrayList<>();
          do {
            typeArguments.add(WildcardTypeName.subtypeOf(Object.class));
            left = type.indexOf('<', left + 1);
          } while (left != -1);
          return ParameterizedTypeName.get(typeClassName,
              typeArguments.toArray(new TypeName[typeArguments.size()]));
        }
        return ClassName.bestGuess(type);
    }
  }

  /** True when this type's bindings require a view hierarchy. */
  private boolean hasViewBindings() {
    return !viewBindings.isEmpty() || !collectionBindings.isEmpty();
  }

  /** True when this type's bindings use raw integer values instead of {@code R} references. */
  private boolean hasUnqualifiedResourceBindings() {
    for (ResourceBinding binding : resourceBindings) {
      if (!binding.id().qualifed) {
        return true;
      }
    }
    return false;
  }

  /** True when this type's bindings use Resource directly instead of Context. */
  private boolean hasResourceBindingsNeedingResource(int sdk) {
    for (ResourceBinding binding : resourceBindings) {
      if (binding.requiresResources(sdk)) {
        return true;
      }
    }
    return false;
  }

  private boolean hasMethodBindings() {
    for (ViewBinding bindings : viewBindings) {
      if (!bindings.getMethodBindings().isEmpty()) {
        return true;
      }
    }
    return false;
  }

  private boolean hasOnTouchMethodBindings() {
    for (ViewBinding bindings : viewBindings) {
      if (bindings.getMethodBindings()
          .containsKey(OnTouch.class.getAnnotation(ListenerClass.class))) {
        return true;
      }
    }
    return false;
  }

  private boolean hasFieldBindings() {
    for (ViewBinding bindings : viewBindings) {
      if (bindings.getFieldBinding() != null) {
        return true;
      }
    }
    return !collectionBindings.isEmpty();
  }

  private boolean hasTargetField() {
    return hasFieldBindings() || hasMethodBindings();
  }

  private boolean hasViewLocal() {
    for (ViewBinding bindings : viewBindings) {
      if (bindings.requiresLocal()) {
        return true;
      }
    }
    return false;
  }

  /** True if this binding requires a view. Otherwise only a context is needed. */
  @Override
  public boolean constructorNeedsView() {
    return hasViewBindings() //
        || (parentBinding != null && parentBinding.constructorNeedsView());
  }

  static boolean requiresCast(TypeName type) {
    return !VIEW_TYPE.equals(type.toString());
  }

  @Override public String toString() {
    return bindingClassName.toString();
  }

  static Builder newBuilder(TypeElement enclosingElement) {
    TypeMirror typeMirror = enclosingElement.asType();

    boolean isView = isSubtypeOfType(typeMirror, VIEW_TYPE);
    boolean isActivity = isSubtypeOfType(typeMirror, ACTIVITY_TYPE);
    boolean isDialog = isSubtypeOfType(typeMirror, DIALOG_TYPE);

    TypeName targetType = TypeName.get(typeMirror);
    if (targetType instanceof ParameterizedTypeName) {
      targetType = ((ParameterizedTypeName) targetType).rawType;
    }

    ClassName bindingClassName = getBindingClassName(enclosingElement);

    boolean isFinal = enclosingElement.getModifiers().contains(Modifier.FINAL);
    return new Builder(targetType, bindingClassName, enclosingElement, isFinal, isView, isActivity,
        isDialog);
  }

  static ClassName getBindingClassName(TypeElement typeElement) {
    String packageName = getPackage(typeElement).getQualifiedName().toString();
    String className = typeElement.getQualifiedName().toString().substring(
            packageName.length() + 1).replace('.', '$');
    return ClassName.get(packageName, className + "_ViewBinding");
  }

  static final class Builder {
    private final TypeName targetTypeName;
    private final ClassName bindingClassName;
    private final TypeElement enclosingElement;
    private final boolean isFinal;
    private final boolean isView;
    private final boolean isActivity;
    private final boolean isDialog;

    private @Nullable BindingInformationProvider parentBinding;

    private final Map<Id, ViewBinding.Builder> viewIdMap = new LinkedHashMap<>();
    private final ImmutableList.Builder<FieldCollectionViewBinding> collectionBindings =
        ImmutableList.builder();
    private final ImmutableList.Builder<ResourceBinding> resourceBindings = ImmutableList.builder();

    private Builder(
        TypeName targetTypeName, ClassName bindingClassName, TypeElement enclosingElement,
        boolean isFinal, boolean isView, boolean isActivity, boolean isDialog) {
      this.targetTypeName = targetTypeName;
      this.bindingClassName = bindingClassName;
      this.enclosingElement = enclosingElement;
      this.isFinal = isFinal;
      this.isView = isView;
      this.isActivity = isActivity;
      this.isDialog = isDialog;
    }

    void addField(Id id, FieldViewBinding binding) {
      getOrCreateViewBindings(id).setFieldBinding(binding);
    }

    void addFieldCollection(FieldCollectionViewBinding binding) {
      collectionBindings.add(binding);
    }

    boolean addMethod(
        Id id,
        ListenerClass listener,
        ListenerMethod method,
        MethodViewBinding binding) {
      ViewBinding.Builder viewBinding = getOrCreateViewBindings(id);
      if (viewBinding.hasMethodBinding(listener, method) && !"void".equals(method.returnType())) {
        return false;
      }
      viewBinding.addMethodBinding(listener, method, binding);
      return true;
    }

    void addResource(ResourceBinding binding) {
      resourceBindings.add(binding);
    }

    void setParent(BindingInformationProvider parent) {
      this.parentBinding = parent;
    }

    @Nullable String findExistingBindingName(Id id) {
      ViewBinding.Builder builder = viewIdMap.get(id);
      if (builder == null) {
        return null;
      }
      FieldViewBinding fieldBinding = builder.fieldBinding;
      if (fieldBinding == null) {
        return null;
      }
      return fieldBinding.getName();
    }

    private ViewBinding.Builder getOrCreateViewBindings(Id id) {
      ViewBinding.Builder viewId = viewIdMap.get(id);
      if (viewId == null) {
        viewId = new ViewBinding.Builder(id);
        viewIdMap.put(id, viewId);
      }
      return viewId;
    }

    BindingSet build() {
      ImmutableList.Builder<ViewBinding> viewBindings = ImmutableList.builder();
      for (ViewBinding.Builder builder : viewIdMap.values()) {
        viewBindings.add(builder.build());
      }
      return new BindingSet(targetTypeName, bindingClassName, enclosingElement, isFinal, isView,
          isActivity, isDialog, viewBindings.build(), collectionBindings.build(),
          resourceBindings.build(), parentBinding);
    }
  }
}

interface BindingInformationProvider {
  boolean constructorNeedsView();
  ClassName getBindingClassName();
}

final class ClasspathBindingSet implements BindingInformationProvider {
  private boolean constructorNeedsView;
  private ClassName className;

  ClasspathBindingSet(boolean constructorNeedsView, TypeElement classElement) {
    this.constructorNeedsView = constructorNeedsView;
    this.className = BindingSet.getBindingClassName(classElement);
  }

  @Override
  public ClassName getBindingClassName() {
    return className;
  }

  @Override
  public boolean constructorNeedsView() {
    return constructorNeedsView;
  }
}


================================================
FILE: butterknife-compiler/src/main/java/butterknife/compiler/ButterKnifeProcessor.java
================================================
package butterknife.compiler;

import butterknife.BindAnim;
import butterknife.BindArray;
import butterknife.BindBitmap;
import butterknife.BindBool;
import butterknife.BindColor;
import butterknife.BindDimen;
import butterknife.BindDrawable;
import butterknife.BindFloat;
import butterknife.BindFont;
import butterknife.BindInt;
import butterknife.BindString;
import butterknife.BindView;
import butterknife.BindViews;
import butterknife.OnCheckedChanged;
import butterknife.OnClick;
import butterknife.OnEditorAction;
import butterknife.OnFocusChange;
import butterknife.OnItemClick;
import butterknife.OnItemLongClick;
import butterknife.OnItemSelected;
import butterknife.OnLongClick;
import butterknife.OnPageChange;
import butterknife.OnTextChanged;
import butterknife.OnTouch;
import butterknife.Optional;
import butterknife.compiler.FieldTypefaceBinding.TypefaceStyles;
import butterknife.internal.ListenerClass;
import butterknife.internal.ListenerMethod;
import com.google.auto.common.SuperficialValidation;
import com.google.auto.service.AutoService;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.TypeName;
import com.sun.source.util.Trees;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeScanner;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic.Kind;
import net.ltgt.gradle.incap.IncrementalAnnotationProcessor;
import net.ltgt.gradle.incap.IncrementalAnnotationProcessorType;

import static butterknife.internal.Constants.NO_RES_ID;
import static java.util.Objects.requireNonNull;
import static javax.lang.model.element.ElementKind.CLASS;
import static javax.lang.model.element.ElementKind.INTERFACE;
import static javax.lang.model.element.ElementKind.METHOD;
import static javax.lang.model.element.Modifier.PRIVATE;
import static javax.lang.model.element.Modifier.STATIC;

@AutoService(Processor.class)
@IncrementalAnnotationProcessor(IncrementalAnnotationProcessorType.DYNAMIC)
@SuppressWarnings("NullAway") // TODO fix all these...
public final class ButterKnifeProcessor extends AbstractProcessor {
  // TODO remove when http://b.android.com/187527 is released.
  private static final String OPTION_SDK_INT = "butterknife.minSdk";
  private static final String OPTION_DEBUGGABLE = "butterknife.debuggable";
  static final Id NO_ID = new Id(NO_RES_ID);
  static final String VIEW_TYPE = "android.view.View";
  static final String ACTIVITY_TYPE = "android.app.Activity";
  static final String DIALOG_TYPE = "android.app.Dialog";
  private static final String COLOR_STATE_LIST_TYPE = "android.content.res.ColorStateList";
  private static final String BITMAP_TYPE = "android.graphics.Bitmap";
  private static final String ANIMATION_TYPE = "android.view.animation.Animation";
  private static final String DRAWABLE_TYPE = "android.graphics.drawable.Drawable";
  private static final String TYPED_ARRAY_TYPE = "android.content.res.TypedArray";
  private static final String TYPEFACE_TYPE = "android.graphics.Typeface";
  private static final String NULLABLE_ANNOTATION_NAME = "Nullable";
  private static final String STRING_TYPE = "java.lang.String";
  private static final String LIST_TYPE = List.class.getCanonicalName();
  private static final List<Class<? extends Annotation>> LISTENERS = Arrays.asList(//
      OnCheckedChanged.class, //
      OnClick.class, //
      OnEditorAction.class, //
      OnFocusChange.class, //
      OnItemClick.class, //
      OnItemLongClick.class, //
      OnItemSelected.class, //
      OnLongClick.class, //
      OnPageChange.class, //
      OnTextChanged.class, //
      OnTouch.class //
  );

  private Types typeUtils;
  private Filer filer;
  private @Nullable Trees trees;

  private int sdk = 1;
  private boolean debuggable = true;

  private final RScanner rScanner = new RScanner();

  @Override public synchronized void init(ProcessingEnvironment env) {
    super.init(env);

    String sdk = env.getOptions().get(OPTION_SDK_INT);
    if (sdk != null) {
      try {
        this.sdk = Integer.parseInt(sdk);
      } catch (NumberFormatException e) {
        env.getMessager()
            .printMessage(Kind.WARNING, "Unable to parse supplied minSdk option '"
                + sdk
                + "'. Falling back to API 1 support.");
      }
    }

    debuggable = !"false".equals(env.getOptions().get(OPTION_DEBUGGABLE));

    typeUtils = env.getTypeUtils();
    filer = env.getFiler();
    try {
      trees = Trees.instance(processingEnv);
    } catch (IllegalArgumentException ignored) {
      try {
        // Get original ProcessingEnvironment from Gradle-wrapped one or KAPT-wrapped one.
        for (Field field : processingEnv.getClass().getDeclaredFields()) {
          if (field.getName().equals("delegate") || field.getName().equals("processingEnv")) {
            field.setAccessible(true);
            ProcessingEnvironment javacEnv = (ProcessingEnvironment) field.get(processingEnv);
            trees = Trees.instance(javacEnv);
            break;
          }
        }
      } catch (Throwable ignored2) {
      }
    }
  }

  @Override public Set<String> getSupportedOptions() {
    ImmutableSet.Builder<String> builder = ImmutableSet.builder();
    builder.add(OPTION_SDK_INT, OPTION_DEBUGGABLE);
    if (trees != null) {
      builder.add(IncrementalAnnotationProcessorType.ISOLATING.getProcessorOption());
    }
    return builder.build();
  }

  @Override public Set<String> getSupportedAnnotationTypes() {
    Set<String> types = new LinkedHashSet<>();
    for (Class<? extends Annotation> annotation : getSupportedAnnotations()) {
      types.add(annotation.getCanonicalName());
    }
    return types;
  }

  private Set<Class<? extends Annotation>> getSupportedAnnotations() {
    Set<Class<? extends Annotation>> annotations = new LinkedHashSet<>();

    annotations.add(BindAnim.class);
    annotations.add(BindArray.class);
    annotations.add(BindBitmap.class);
    annotations.add(BindBool.class);
    annotations.add(BindColor.class);
    annotations.add(BindDimen.class);
    annotations.add(BindDrawable.class);
    annotations.add(BindFloat.class);
    annotations.add(BindFont.class);
    annotations.add(BindInt.class);
    annotations.add(BindString.class);
    annotations.add(BindView.class);
    annotations.add(BindViews.class);
    annotations.addAll(LISTENERS);

    return annotations;
  }

  @Override public boolean process(Set<? extends TypeElement> elements, RoundEnvironment env) {
    Map<TypeElement, BindingSet> bindingMap = findAndParseTargets(env);

    for (Map.Entry<TypeElement, BindingSet> entry : bindingMap.entrySet()) {
      TypeElement typeElement = entry.getKey();
      BindingSet binding = entry.getValue();

      JavaFile javaFile = binding.brewJava(sdk, debuggable);
      try {
        javaFile.writeTo(filer);
      } catch (IOException e) {
        error(typeElement, "Unable to write binding for type %s: %s", typeElement, e.getMessage());
      }
    }

    return false;
  }

  private Map<TypeElement, BindingSet> findAndParseTargets(RoundEnvironment env) {
    Map<TypeElement, BindingSet.Builder> builderMap = new LinkedHashMap<>();
    Set<TypeElement> erasedTargetNames = new LinkedHashSet<>();

    // Process each @BindAnim element.
    for (Element element : env.getElementsAnnotatedWith(BindAnim.class)) {
      if (!SuperficialValidation.validateElement(element)) continue;
      try {
        parseResourceAnimation(element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        logParsingError(element, BindAnim.class, e);
      }
    }

    // Process each @BindArray element.
    for (Element element : env.getElementsAnnotatedWith(BindArray.class)) {
      if (!SuperficialValidation.validateElement(element)) continue;
      try {
        parseResourceArray(element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        logParsingError(element, BindArray.class, e);
      }
    }

    // Process each @BindBitmap element.
    for (Element element : env.getElementsAnnotatedWith(BindBitmap.class)) {
      if (!SuperficialValidation.validateElement(element)) continue;
      try {
        parseResourceBitmap(element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        logParsingError(element, BindBitmap.class, e);
      }
    }

    // Process each @BindBool element.
    for (Element element : env.getElementsAnnotatedWith(BindBool.class)) {
      if (!SuperficialValidation.validateElement(element)) continue;
      try {
        parseResourceBool(element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        logParsingError(element, BindBool.class, e);
      }
    }

    // Process each @BindColor element.
    for (Element element : env.getElementsAnnotatedWith(BindColor.class)) {
      if (!SuperficialValidation.validateElement(element)) continue;
      try {
        parseResourceColor(element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        logParsingError(element, BindColor.class, e);
      }
    }

    // Process each @BindDimen element.
    for (Element element : env.getElementsAnnotatedWith(BindDimen.class)) {
      if (!SuperficialValidation.validateElement(element)) continue;
      try {
        parseResourceDimen(element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        logParsingError(element, BindDimen.class, e);
      }
    }

    // Process each @BindDrawable element.
    for (Element element : env.getElementsAnnotatedWith(BindDrawable.class)) {
      if (!SuperficialValidation.validateElement(element)) continue;
      try {
        parseResourceDrawable(element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        logParsingError(element, BindDrawable.class, e);
      }
    }

    // Process each @BindFloat element.
    for (Element element : env.getElementsAnnotatedWith(BindFloat.class)) {
      if (!SuperficialValidation.validateElement(element)) continue;
      try {
        parseResourceFloat(element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        logParsingError(element, BindFloat.class, e);
      }
    }

    // Process each @BindFont element.
    for (Element element : env.getElementsAnnotatedWith(BindFont.class)) {
      if (!SuperficialValidation.validateElement(element)) continue;
      try {
        parseResourceFont(element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        logParsingError(element, BindFont.class, e);
      }
    }

    // Process each @BindInt element.
    for (Element element : env.getElementsAnnotatedWith(BindInt.class)) {
      if (!SuperficialValidation.validateElement(element)) continue;
      try {
        parseResourceInt(element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        logParsingError(element, BindInt.class, e);
      }
    }

    // Process each @BindString element.
    for (Element element : env.getElementsAnnotatedWith(BindString.class)) {
      if (!SuperficialValidation.validateElement(element)) continue;
      try {
        parseResourceString(element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        logParsingError(element, BindString.class, e);
      }
    }

    // Process each @BindView element.
    for (Element element : env.getElementsAnnotatedWith(BindView.class)) {
      // we don't SuperficialValidation.validateElement(element)
      // so that an unresolved View type can be generated by later processing rounds
      try {
        parseBindView(element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        logParsingError(element, BindView.class, e);
      }
    }

    // Process each @BindViews element.
    for (Element element : env.getElementsAnnotatedWith(BindViews.class)) {
      // we don't SuperficialValidation.validateElement(element)
      // so that an unresolved View type can be generated by later processing rounds
      try {
        parseBindViews(element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        logParsingError(element, BindViews.class, e);
      }
    }

    // Process each annotation that corresponds to a listener.
    for (Class<? extends Annotation> listener : LISTENERS) {
      findAndParseListener(env, listener, builderMap, erasedTargetNames);
    }

    Map<TypeElement, ClasspathBindingSet> classpathBindings =
        findAllSupertypeBindings(builderMap, erasedTargetNames);

    // Associate superclass binders with their subclass binders. This is a queue-based tree walk
    // which starts at the roots (superclasses) and walks to the leafs (subclasses).
    Deque<Map.Entry<TypeElement, BindingSet.Builder>> entries =
        new ArrayDeque<>(builderMap.entrySet());
    Map<TypeElement, BindingSet> bindingMap = new LinkedHashMap<>();
    while (!entries.isEmpty()) {
      Map.Entry<TypeElement, BindingSet.Builder> entry = entries.removeFirst();

      TypeElement type = entry.getKey();
      BindingSet.Builder builder = entry.getValue();

      TypeElement parentType = findParentType(type, erasedTargetNames, classpathBindings.keySet());
      if (parentType == null) {
        bindingMap.put(type, builder.build());
      } else {
        BindingInformationProvider parentBinding = bindingMap.get(parentType);
        if (parentBinding == null) {
          parentBinding = classpathBindings.get(parentType);
        }
        if (parentBinding != null) {
          builder.setParent(parentBinding);
          bindingMap.put(type, builder.build());
        } else {
          // Has a superclass binding but we haven't built it yet. Re-enqueue for later.
          entries.addLast(entry);
        }
      }
    }

    return bindingMap;
  }

  private void logParsingError(Element element, Class<? extends Annotation> annotation,
      Exception e) {
    StringWriter stackTrace = new StringWriter();
    e.printStackTrace(new PrintWriter(stackTrace));
    error(element, "Unable to parse @%s binding.\n\n%s", annotation.getSimpleName(), stackTrace);
  }

  private boolean isInaccessibleViaGeneratedCode(Class<? extends Annotation> annotationClass,
      String targetThing, Element element) {
    boolean hasError = false;
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Verify field or method modifiers.
    Set<Modifier> modifiers = element.getModifiers();
    if (modifiers.contains(PRIVATE) || modifiers.contains(STATIC)) {
      error(element, "@%s %s must not be private or static. (%s.%s)",
          annotationClass.getSimpleName(), targetThing, enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    // Verify containing type.
    if (enclosingElement.getKind() != CLASS) {
      error(enclosingElement, "@%s %s may only be contained in classes. (%s.%s)",
          annotationClass.getSimpleName(), targetThing, enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    // Verify containing class visibility is not private.
    if (enclosingElement.getModifiers().contains(PRIVATE)) {
      error(enclosingElement, "@%s %s may not be contained in private classes. (%s.%s)",
          annotationClass.getSimpleName(), targetThing, enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    return hasError;
  }

  private boolean isBindingInWrongPackage(Class<? extends Annotation> annotationClass,
      Element element) {
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
    String qualifiedName = enclosingElement.getQualifiedName().toString();

    if (qualifiedName.startsWith("android.")) {
      error(element, "@%s-annotated class incorrectly in Android framework package. (%s)",
          annotationClass.getSimpleName(), qualifiedName);
      return true;
    }
    if (qualifiedName.startsWith("java.")) {
      error(element, "@%s-annotated class incorrectly in Java framework package. (%s)",
          annotationClass.getSimpleName(), qualifiedName);
      return true;
    }

    return false;
  }

  private void parseBindView(Element element, Map<TypeElement, BindingSet.Builder> builderMap,
      Set<TypeElement> erasedTargetNames) {
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Start by verifying common generated code restrictions.
    boolean hasError = isInaccessibleViaGeneratedCode(BindView.class, "fields", element)
        || isBindingInWrongPackage(BindView.class, element);

    // Verify that the target type extends from View.
    TypeMirror elementType = element.asType();
    if (elementType.getKind() == TypeKind.TYPEVAR) {
      TypeVariable typeVariable = (TypeVariable) elementType;
      elementType = typeVariable.getUpperBound();
    }
    Name qualifiedName = enclosingElement.getQualifiedName();
    Name simpleName = element.getSimpleName();
    if (!isSubtypeOfType(elementType, VIEW_TYPE) && !isInterface(elementType)) {
      if (elementType.getKind() == TypeKind.ERROR) {
        note(element, "@%s field with unresolved type (%s) "
                + "must elsewhere be generated as a View or interface. (%s.%s)",
            BindView.class.getSimpleName(), elementType, qualifiedName, simpleName);
      } else {
        error(element, "@%s fields must extend from View or be an interface. (%s.%s)",
            BindView.class.getSimpleName(), qualifiedName, simpleName);
        hasError = true;
      }
    }

    if (hasError) {
      return;
    }

    // Assemble information on the field.
    int id = element.getAnnotation(BindView.class).value();
    BindingSet.Builder builder = builderMap.get(enclosingElement);
    Id resourceId = elementToId(element, BindView.class, id);
    if (builder != null) {
      String existingBindingName = builder.findExistingBindingName(resourceId);
      if (existingBindingName != null) {
        error(element, "Attempt to use @%s for an already bound ID %d on '%s'. (%s.%s)",
            BindView.class.getSimpleName(), id, existingBindingName,
            enclosingElement.getQualifiedName(), element.getSimpleName());
        return;
      }
    } else {
      builder = getOrCreateBindingBuilder(builderMap, enclosingElement);
    }

    String name = simpleName.toString();
    TypeName type = TypeName.get(elementType);
    boolean required = isFieldRequired(element);

    builder.addField(resourceId, new FieldViewBinding(name, type, required));

    // Add the type-erased version to the valid binding targets set.
    erasedTargetNames.add(enclosingElement);
  }

  private void parseBindViews(Element element, Map<TypeElement, BindingSet.Builder> builderMap,
      Set<TypeElement> erasedTargetNames) {
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Start by verifying common generated code restrictions.
    boolean hasError = isInaccessibleViaGeneratedCode(BindViews.class, "fields", element)
        || isBindingInWrongPackage(BindViews.class, element);

    // Verify that the type is a List or an array.
    TypeMirror elementType = element.asType();
    String erasedType = doubleErasure(elementType);
    TypeMirror viewType = null;
    FieldCollectionViewBinding.Kind kind = null;
    if (elementType.getKind() == TypeKind.ARRAY) {
      ArrayType arrayType = (ArrayType) elementType;
      viewType = arrayType.getComponentType();
      kind = FieldCollectionViewBinding.Kind.ARRAY;
    } else if (LIST_TYPE.equals(erasedType)) {
      DeclaredType declaredType = (DeclaredType) elementType;
      List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
      if (typeArguments.size() != 1) {
        error(element, "@%s List must have a generic component. (%s.%s)",
            BindViews.class.getSimpleName(), enclosingElement.getQualifiedName(),
            element.getSimpleName());
        hasError = true;
      } else {
        viewType = typeArguments.get(0);
      }
      kind = FieldCollectionViewBinding.Kind.LIST;
    } else {
      error(element, "@%s must be a List or array. (%s.%s)", BindViews.class.getSimpleName(),
          enclosingElement.getQualifiedName(), element.getSimpleName());
      hasError = true;
    }
    if (viewType != null && viewType.getKind() == TypeKind.TYPEVAR) {
      TypeVariable typeVariable = (TypeVariable) viewType;
      viewType = typeVariable.getUpperBound();
    }

    // Verify that the target type extends from View.
    if (viewType != null && !isSubtypeOfType(viewType, VIEW_TYPE) && !isInterface(viewType)) {
      if (viewType.getKind() == TypeKind.ERROR) {
        note(element, "@%s List or array with unresolved type (%s) "
                + "must elsewhere be generated as a View or interface. (%s.%s)",
            BindViews.class.getSimpleName(), viewType, enclosingElement.getQualifiedName(),
            element.getSimpleName());
      } else {
        error(element, "@%s List or array type must extend from View or be an interface. (%s.%s)",
            BindViews.class.getSimpleName(), enclosingElement.getQualifiedName(),
            element.getSimpleName());
        hasError = true;
      }
    }

    // Assemble information on the field.
    String name = element.getSimpleName().toString();
    int[] ids = element.getAnnotation(BindViews.class).value();
    if (ids.length == 0) {
      error(element, "@%s must specify at least one ID. (%s.%s)", BindViews.class.getSimpleName(),
          enclosingElement.getQualifiedName(), element.getSimpleName());
      hasError = true;
    }

    Integer duplicateId = findDuplicate(ids);
    if (duplicateId != null) {
      error(element, "@%s annotation contains duplicate ID %d. (%s.%s)",
          BindViews.class.getSimpleName(), duplicateId, enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    if (hasError) {
      return;
    }

    TypeName type = TypeName.get(requireNonNull(viewType));
    boolean required = isFieldRequired(element);

    BindingSet.Builder builder = getOrCreateBindingBuilder(builderMap, enclosingElement);
    builder.addFieldCollection(new FieldCollectionViewBinding(name, type, requireNonNull(kind),
        new ArrayList<>(elementToIds(element, BindViews.class, ids).values()), required));

    erasedTargetNames.add(enclosingElement);
  }

  private void parseResourceAnimation(Element element,
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> erasedTargetNames) {
    boolean hasError = false;
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Verify that the target type is Animation.
    if (!ANIMATION_TYPE.equals(element.asType().toString())) {
      error(element, "@%s field type must be 'Animation'. (%s.%s)",
          BindAnim.class.getSimpleName(), enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    // Verify common generated code restrictions.
    hasError |= isInaccessibleViaGeneratedCode(BindAnim.class, "fields", element);
    hasError |= isBindingInWrongPackage(BindAnim.class, element);

    if (hasError) {
      return;
    }

    // Assemble information on the field.
    String name = element.getSimpleName().toString();
    int id = element.getAnnotation(BindAnim.class).value();
    Id resourceId = elementToId(element, BindAnim.class, id);

    BindingSet.Builder builder = getOrCreateBindingBuilder(builderMap, enclosingElement);
    builder.addResource(new FieldAnimationBinding(resourceId, name));

    erasedTargetNames.add(enclosingElement);
  }

  private void parseResourceBool(Element element,
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> erasedTargetNames) {
    boolean hasError = false;
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Verify that the target type is bool.
    if (element.asType().getKind() != TypeKind.BOOLEAN) {
      error(element, "@%s field type must be 'boolean'. (%s.%s)",
          BindBool.class.getSimpleName(), enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    // Verify common generated code restrictions.
    hasError |= isInaccessibleViaGeneratedCode(BindBool.class, "fields", element);
    hasError |= isBindingInWrongPackage(BindBool.class, element);

    if (hasError) {
      return;
    }

    // Assemble information on the field.
    String name = element.getSimpleName().toString();
    int id = element.getAnnotation(BindBool.class).value();
    Id resourceId = elementToId(element, BindBool.class, id);
    BindingSet.Builder builder = getOrCreateBindingBuilder(builderMap, enclosingElement);
    builder.addResource(
        new FieldResourceBinding(resourceId, name, FieldResourceBinding.Type.BOOL));

    erasedTargetNames.add(enclosingElement);
  }

  private void parseResourceColor(Element element,
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> erasedTargetNames) {
    boolean hasError = false;
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Verify that the target type is int or ColorStateList.
    boolean isColorStateList = false;
    TypeMirror elementType = element.asType();
    if (COLOR_STATE_LIST_TYPE.equals(elementType.toString())) {
      isColorStateList = true;
    } else if (elementType.getKind() != TypeKind.INT) {
      error(element, "@%s field type must be 'int' or 'ColorStateList'. (%s.%s)",
          BindColor.class.getSimpleName(), enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    // Verify common generated code restrictions.
    hasError |= isInaccessibleViaGeneratedCode(BindColor.class, "fields", element);
    hasError |= isBindingInWrongPackage(BindColor.class, element);

    if (hasError) {
      return;
    }

    // Assemble information on the field.
    String name = element.getSimpleName().toString();
    int id = element.getAnnotation(BindColor.class).value();
    Id resourceId = elementToId(element, BindColor.class, id);
    BindingSet.Builder builder = getOrCreateBindingBuilder(builderMap, enclosingElement);

    FieldResourceBinding.Type colorStateList = FieldResourceBinding.Type.COLOR_STATE_LIST;
    FieldResourceBinding.Type color = FieldResourceBinding.Type.COLOR;
    builder.addResource(new FieldResourceBinding(
        resourceId,
        name,
        isColorStateList ? colorStateList : color));

    erasedTargetNames.add(enclosingElement);
  }

  private void parseResourceDimen(Element element,
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> erasedTargetNames) {
    boolean hasError = false;
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Verify that the target type is int or ColorStateList.
    boolean isInt = false;
    TypeMirror elementType = element.asType();
    if (elementType.getKind() == TypeKind.INT) {
      isInt = true;
    } else if (elementType.getKind() != TypeKind.FLOAT) {
      error(element, "@%s field type must be 'int' or 'float'. (%s.%s)",
          BindDimen.class.getSimpleName(), enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    // Verify common generated code restrictions.
    hasError |= isInaccessibleViaGeneratedCode(BindDimen.class, "fields", element);
    hasError |= isBindingInWrongPackage(BindDimen.class, element);

    if (hasError) {
      return;
    }

    // Assemble information on the field.
    String name = element.getSimpleName().toString();
    int id = element.getAnnotation(BindDimen.class).value();
    Id resourceId = elementToId(element, BindDimen.class, id);
    BindingSet.Builder builder = getOrCreateBindingBuilder(builderMap, enclosingElement);
    builder.addResource(new FieldResourceBinding(resourceId, name,
        isInt ? FieldResourceBinding.Type.DIMEN_AS_INT : FieldResourceBinding.Type.DIMEN_AS_FLOAT));

    erasedTargetNames.add(enclosingElement);
  }

  private void parseResourceBitmap(Element element,
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> erasedTargetNames) {
    boolean hasError = false;
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Verify that the target type is Bitmap.
    if (!BITMAP_TYPE.equals(element.asType().toString())) {
      error(element, "@%s field type must be 'Bitmap'. (%s.%s)",
          BindBitmap.class.getSimpleName(), enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    // Verify common generated code restrictions.
    hasError |= isInaccessibleViaGeneratedCode(BindBitmap.class, "fields", element);
    hasError |= isBindingInWrongPackage(BindBitmap.class, element);

    if (hasError) {
      return;
    }

    // Assemble information on the field.
    String name = element.getSimpleName().toString();
    int id = element.getAnnotation(BindBitmap.class).value();
    Id resourceId = elementToId(element, BindBitmap.class, id);
    BindingSet.Builder builder = getOrCreateBindingBuilder(builderMap, enclosingElement);
    builder.addResource(
        new FieldResourceBinding(resourceId, name, FieldResourceBinding.Type.BITMAP));

    erasedTargetNames.add(enclosingElement);
  }

  private void parseResourceDrawable(Element element,
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> erasedTargetNames) {
    boolean hasError = false;
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Verify that the target type is Drawable.
    if (!DRAWABLE_TYPE.equals(element.asType().toString())) {
      error(element, "@%s field type must be 'Drawable'. (%s.%s)",
          BindDrawable.class.getSimpleName(), enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    // Verify common generated code restrictions.
    hasError |= isInaccessibleViaGeneratedCode(BindDrawable.class, "fields", element);
    hasError |= isBindingInWrongPackage(BindDrawable.class, element);

    if (hasError) {
      return;
    }

    // Assemble information on the field.
    String name = element.getSimpleName().toString();
    int id = element.getAnnotation(BindDrawable.class).value();
    int tint = element.getAnnotation(BindDrawable.class).tint();
    Map<Integer, Id> resourceIds = elementToIds(element, BindDrawable.class, new int[] {id, tint});

    BindingSet.Builder builder = getOrCreateBindingBuilder(builderMap, enclosingElement);
    builder.addResource(new FieldDrawableBinding(resourceIds.get(id), name, resourceIds.get(tint)));

    erasedTargetNames.add(enclosingElement);
  }

  private void parseResourceFloat(Element element,
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> erasedTargetNames) {
    boolean hasError = false;
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Verify that the target type is float.
    if (element.asType().getKind() != TypeKind.FLOAT) {
      error(element, "@%s field type must be 'float'. (%s.%s)",
          BindFloat.class.getSimpleName(), enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    // Verify common generated code restrictions.
    hasError |= isInaccessibleViaGeneratedCode(BindFloat.class, "fields", element);
    hasError |= isBindingInWrongPackage(BindFloat.class, element);

    if (hasError) {
      return;
    }

    // Assemble information on the field.
    String name = element.getSimpleName().toString();
    int id = element.getAnnotation(BindFloat.class).value();
    Id resourceId = elementToId(element, BindFloat.class, id);
    BindingSet.Builder builder = getOrCreateBindingBuilder(builderMap, enclosingElement);
    builder.addResource(
        new FieldResourceBinding(resourceId, name, FieldResourceBinding.Type.FLOAT));

    erasedTargetNames.add(enclosingElement);
  }

  private void parseResourceFont(Element element,
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> erasedTargetNames) {
    boolean hasError = false;
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Verify that the target type is a Typeface.
    if (!TYPEFACE_TYPE.equals(element.asType().toString())) {
      error(element, "@%s field type must be 'Typeface'. (%s.%s)",
          BindFont.class.getSimpleName(), enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    // Verify common generated code restrictions.
    hasError |= isInaccessibleViaGeneratedCode(BindFont.class, "fields", element);
    hasError |= isBindingInWrongPackage(BindFont.class, element);

    // Assemble information on the field.
    String name = element.getSimpleName().toString();
    BindFont bindFont = element.getAnnotation(BindFont.class);

    int styleValue = bindFont.style();
    TypefaceStyles style = TypefaceStyles.fromValue(styleValue);
    if (style == null) {
      error(element, "@%s style must be NORMAL, BOLD, ITALIC, or BOLD_ITALIC. (%s.%s)",
          BindFont.class.getSimpleName(), enclosingElement.getQualifiedName(), name);
      hasError = true;
    }

    if (hasError) {
      return;
    }

    BindingSet.Builder builder = getOrCreateBindingBuilder(builderMap, enclosingElement);
    Id resourceId = elementToId(element, BindFont.class, bindFont.value());
    builder.addResource(new FieldTypefaceBinding(resourceId, name, style));

    erasedTargetNames.add(enclosingElement);
  }

  private void parseResourceInt(Element element,
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> erasedTargetNames) {
    boolean hasError = false;
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Verify that the target type is int.
    if (element.asType().getKind() != TypeKind.INT) {
      error(element, "@%s field type must be 'int'. (%s.%s)", BindInt.class.getSimpleName(),
          enclosingElement.getQualifiedName(), element.getSimpleName());
      hasError = true;
    }

    // Verify common generated code restrictions.
    hasError |= isInaccessibleViaGeneratedCode(BindInt.class, "fields", element);
    hasError |= isBindingInWrongPackage(BindInt.class, element);

    if (hasError) {
      return;
    }

    // Assemble information on the field.
    String name = element.getSimpleName().toString();
    int id = element.getAnnotation(BindInt.class).value();
    Id resourceId = elementToId(element, BindInt.class, id);
    BindingSet.Builder builder = getOrCreateBindingBuilder(builderMap, enclosingElement);
    builder.addResource(
        new FieldResourceBinding(resourceId, name, FieldResourceBinding.Type.INT));

    erasedTargetNames.add(enclosingElement);
  }

  private void parseResourceString(Element element,
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> erasedTargetNames) {
    boolean hasError = false;
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Verify that the target type is String.
    if (!STRING_TYPE.equals(element.asType().toString())) {
      error(element, "@%s field type must be 'String'. (%s.%s)",
          BindString.class.getSimpleName(), enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    // Verify common generated code restrictions.
    hasError |= isInaccessibleViaGeneratedCode(BindString.class, "fields", element);
    hasError |= isBindingInWrongPackage(BindString.class, element);

    if (hasError) {
      return;
    }

    // Assemble information on the field.
    String name = element.getSimpleName().toString();
    int id = element.getAnnotation(BindString.class).value();
    Id resourceId = elementToId(element, BindString.class, id);
    BindingSet.Builder builder = getOrCreateBindingBuilder(builderMap, enclosingElement);
    builder.addResource(
        new FieldResourceBinding(resourceId, name, FieldResourceBinding.Type.STRING));

    erasedTargetNames.add(enclosingElement);
  }

  private void parseResourceArray(Element element,
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> erasedTargetNames) {
    boolean hasError = false;
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Verify that the target type is supported.
    FieldResourceBinding.Type type = getArrayResourceMethodName(element);
    if (type == null) {
      error(element,
          "@%s field type must be one of: String[], int[], CharSequence[], %s. (%s.%s)",
          BindArray.class.getSimpleName(), TYPED_ARRAY_TYPE, enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    // Verify common generated code restrictions.
    hasError |= isInaccessibleViaGeneratedCode(BindArray.class, "fields", element);
    hasError |= isBindingInWrongPackage(BindArray.class, element);

    if (hasError) {
      return;
    }

    // Assemble information on the field.
    String name = element.getSimpleName().toString();
    int id = element.getAnnotation(BindArray.class).value();
    Id resourceId = elementToId(element, BindArray.class, id);
    BindingSet.Builder builder = getOrCreateBindingBuilder(builderMap, enclosingElement);
    builder.addResource(new FieldResourceBinding(resourceId, name, requireNonNull(type)));

    erasedTargetNames.add(enclosingElement);
  }

  /**
   * Returns a method name from the {@code android.content.res.Resources} class for array resource
   * binding, null if the element type is not supported.
   */
  private static @Nullable FieldResourceBinding.Type getArrayResourceMethodName(Element element) {
    TypeMirror typeMirror = element.asType();
    if (TYPED_ARRAY_TYPE.equals(typeMirror.toString())) {
      return FieldResourceBinding.Type.TYPED_ARRAY;
    }
    if (TypeKind.ARRAY.equals(typeMirror.getKind())) {
      ArrayType arrayType = (ArrayType) typeMirror;
      String componentType = arrayType.getComponentType().toString();
      if (STRING_TYPE.equals(componentType)) {
        return FieldResourceBinding.Type.STRING_ARRAY;
      } else if ("int".equals(componentType)) {
        return FieldResourceBinding.Type.INT_ARRAY;
      } else if ("java.lang.CharSequence".equals(componentType)) {
        return FieldResourceBinding.Type.TEXT_ARRAY;
      }
    }
    return null;
  }

  /** Returns the first duplicate element inside an array, null if there are no duplicates. */
  private static @Nullable Integer findDuplicate(int[] array) {
    Set<Integer> seenElements = new LinkedHashSet<>();

    for (int element : array) {
      if (!seenElements.add(element)) {
        return element;
      }
    }

    return null;
  }

  /** Uses both {@link Types#erasure} and string manipulation to strip any generic types. */
  private String doubleErasure(TypeMirror elementType) {
    String name = typeUtils.erasure(elementType).toString();
    int typeParamStart = name.indexOf('<');
    if (typeParamStart != -1) {
      name = name.substring(0, typeParamStart);
    }
    return name;
  }

  private void findAndParseListener(RoundEnvironment env,
      Class<? extends Annotation> annotationClass,
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> erasedTargetNames) {
    for (Element element : env.getElementsAnnotatedWith(annotationClass)) {
      if (!SuperficialValidation.validateElement(element)) continue;
      try {
        parseListenerAnnotation(annotationClass, element, builderMap, erasedTargetNames);
      } catch (Exception e) {
        StringWriter stackTrace = new StringWriter();
        e.printStackTrace(new PrintWriter(stackTrace));

        error(element, "Unable to generate view binder for @%s.\n\n%s",
            annotationClass.getSimpleName(), stackTrace.toString());
      }
    }
  }

  private void parseListenerAnnotation(Class<? extends Annotation> annotationClass, Element element,
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> erasedTargetNames)
      throws Exception {
    // This should be guarded by the annotation's @Target but it's worth a check for safe casting.
    if (!(element instanceof ExecutableElement) || element.getKind() != METHOD) {
      throw new IllegalStateException(
          String.format("@%s annotation must be on a method.", annotationClass.getSimpleName()));
    }

    ExecutableElement executableElement = (ExecutableElement) element;
    TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();

    // Assemble information on the method.
    Annotation annotation = element.getAnnotation(annotationClass);
    Method annotationValue = annotationClass.getDeclaredMethod("value");
    if (annotationValue.getReturnType() != int[].class) {
      throw new IllegalStateException(
          String.format("@%s annotation value() type not int[].", annotationClass));
    }

    int[] ids = (int[]) annotationValue.invoke(annotation);
    String name = executableElement.getSimpleName().toString();
    boolean required = isListenerRequired(executableElement);

    // Verify that the method and its containing class are accessible via generated code.
    boolean hasError = isInaccessibleViaGeneratedCode(annotationClass, "methods", element);
    hasError |= isBindingInWrongPackage(annotationClass, element);

    Integer duplicateId = findDuplicate(ids);
    if (duplicateId != null) {
      error(element, "@%s annotation for method contains duplicate ID %d. (%s.%s)",
          annotationClass.getSimpleName(), duplicateId, enclosingElement.getQualifiedName(),
          element.getSimpleName());
      hasError = true;
    }

    ListenerClass listener = annotationClass.getAnnotation(ListenerClass.class);
    if (listener == null) {
      throw new IllegalStateException(
          String.format("No @%s defined on @%s.", ListenerClass.class.getSimpleName(),
              annotationClass.getSimpleName()));
    }

    for (int id : ids) {
      if (id == NO_ID.value) {
        if (ids.length == 1) {
          if (!required) {
            error(element, "ID-free binding must not be annotated with @Optional. (%s.%s)",
                enclosingElement.getQualifiedName(), element.getSimpleName());
            hasError = true;
          }
        } else {
          error(element, "@%s annotation contains invalid ID %d. (%s.%s)",
              annotationClass.getSimpleName(), id, enclosingElement.getQualifiedName(),
              element.getSimpleName());
          hasError = true;
        }
      }
    }

    ListenerMethod method;
    ListenerMethod[] methods = listener.method();
    if (methods.length > 1) {
      throw new IllegalStateException(String.format("Multiple listener methods specified on @%s.",
          annotationClass.getSimpleName()));
    } else if (methods.length == 1) {
      if (listener.callbacks() != ListenerClass.NONE.class) {
        throw new IllegalStateException(
            String.format("Both method() and callback() defined on @%s.",
                annotationClass.getSimpleName()));
      }
      method = methods[0];
    } else {
      Method annotationCallback = annotationClass.getDeclaredMethod("callback");
      Enum<?> callback = (Enum<?>) annotationCallback.invoke(annotation);
      Field callbackField = callback.getDeclaringClass().getField(callback.name());
      method = callbackField.getAnnotation(ListenerMethod.class);
      if (method == null) {
        throw new IllegalStateException(
            String.format("No @%s defined on @%s's %s.%s.", ListenerMethod.class.getSimpleName(),
                annotationClass.getSimpleName(), callback.getDeclaringClass().getSimpleName(),
                callback.name()));
      }
    }

    // Verify that the method has equal to or less than the number of parameters as the listener.
    List<? extends VariableElement> methodParameters = executableElement.getParameters();
    if (methodParameters.size() > method.parameters().length) {
      error(element, "@%s methods can have at most %s parameter(s). (%s.%s)",
          annotationClass.getSimpleName(), method.parameters().length,
          enclosingElement.getQualifiedName(), element.getSimpleName());
      hasError = true;
    }

    // Verify method return type matches the listener.
    TypeMirror returnType = executableElement.getReturnType();
    if (returnType instanceof TypeVariable) {
      TypeVariable typeVariable = (TypeVariable) returnType;
      returnType = typeVariable.getUpperBound();
    }
    String returnTypeString = returnType.toString();
    boolean hasReturnValue = !"void".equals(returnTypeString);
    if (!returnTypeString.equals(method.returnType()) && hasReturnValue) {
      error(element, "@%s methods must have a '%s' return type. (%s.%s)",
          annotationClass.getSimpleName(), method.returnType(),
          enclosingElement.getQualifiedName(), element.getSimpleName());
      hasError = true;
    }

    if (hasError) {
      return;
    }

    Parameter[] parameters = Parameter.NONE;
    if (!methodParameters.isEmpty()) {
      parameters = new Parameter[methodParameters.size()];
      BitSet methodParameterUsed = new BitSet(methodParameters.size());
      String[] parameterTypes = method.parameters();
      for (int i = 0; i < methodParameters.size(); i++) {
        VariableElement methodParameter = methodParameters.get(i);
        TypeMirror methodParameterType = methodParameter.asType();
        if (methodParameterType instanceof TypeVariable) {
          TypeVariable typeVariable = (TypeVariable) methodParameterType;
          methodParameterType = typeVariable.getUpperBound();
        }

        for (int j = 0; j < parameterTypes.length; j++) {
          if (methodParameterUsed.get(j)) {
            continue;
          }
          if ((isSubtypeOfType(methodParameterType, parameterTypes[j])
              && isSubtypeOfType(methodParameterType, VIEW_TYPE))
              || isTypeEqual(methodParameterType, parameterTypes[j])
              || isInterface(methodParameterType)) {
            parameters[i] = new Parameter(j, TypeName.get(methodParameterType));
            methodParameterUsed.set(j);
            break;
          }
        }
        if (parameters[i] == null) {
          StringBuilder builder = new StringBuilder();
          builder.append("Unable to match @")
              .append(annotationClass.getSimpleName())
              .append(" method arguments. (")
              .append(enclosingElement.getQualifiedName())
              .append('.')
              .append(element.getSimpleName())
              .append(')');
          for (int j = 0; j < parameters.length; j++) {
            Parameter parameter = parameters[j];
            builder.append("\n\n  Parameter #")
                .append(j + 1)
                .append(": ")
                .append(methodParameters.get(j).asType().toString())
                .append("\n    ");
            if (parameter == null) {
              builder.append("did not match any listener parameters");
            } else {
              builder.append("matched listener parameter #")
                  .append(parameter.getListenerPosition() + 1)
                  .append(": ")
                  .append(parameter.getType());
            }
          }
          builder.append("\n\nMethods may have up to ")
              .append(method.parameters().length)
              .append(" parameter(s):\n");
          for (String parameterType : method.parameters()) {
            builder.append("\n  ").append(parameterType);
          }
          builder.append(
              "\n\nThese may be listed in any order but will be searched for from top to bottom.");
          error(executableElement, builder.toString());
          return;
        }
      }
    }

    MethodViewBinding binding =
        new MethodViewBinding(name, Arrays.asList(parameters), required, hasReturnValue);
    BindingSet.Builder builder = getOrCreateBindingBuilder(builderMap, enclosingElement);
    Map<Integer, Id> resourceIds = elementToIds(element, annotationClass, ids);

    for (Map.Entry<Integer, Id> entry : resourceIds.entrySet()) {
      if (!builder.addMethod(entry.getValue(), listener, method, binding)) {
        error(element, "Multiple listener methods with return value specified for ID %d. (%s.%s)",
            entry.getKey(), enclosingElement.getQualifiedName(), element.getSimpleName());
        return;
      }
    }

    // Add the type-erased version to the valid binding targets set.
    erasedTargetNames.add(enclosingElement);
  }

  private boolean isInterface(TypeMirror typeMirror) {
    return typeMirror instanceof DeclaredType
        && ((DeclaredType) typeMirror).asElement().getKind() == INTERFACE;
  }

  static boolean isSubtypeOfType(TypeMirror typeMirror, String otherType) {
    if (isTypeEqual(typeMirror, otherType)) {
      return true;
    }
    if (typeMirror.getKind() != TypeKind.DECLARED) {
      return false;
    }
    DeclaredType declaredType = (DeclaredType) typeMirror;
    List<? extends TypeMirror> typeArguments = declaredType.getTypeArguments();
    if (typeArguments.size() > 0) {
      StringBuilder typeString = new StringBuilder(declaredType.asElement().toString());
      typeString.append('<');
      for (int i = 0; i < typeArguments.size(); i++) {
        if (i > 0) {
          typeString.append(',');
        }
        typeString.append('?');
      }
      typeString.append('>');
      if (typeString.toString().equals(otherType)) {
        return true;
      }
    }
    Element element = declaredType.asElement();
    if (!(element instanceof TypeElement)) {
      return false;
    }
    TypeElement typeElement = (TypeElement) element;
    TypeMirror superType = typeElement.getSuperclass();
    if (isSubtypeOfType(superType, otherType)) {
      return true;
    }
    for (TypeMirror interfaceType : typeElement.getInterfaces()) {
      if (isSubtypeOfType(interfaceType, otherType)) {
        return true;
      }
    }
    return false;
  }

  private static boolean isTypeEqual(TypeMirror typeMirror, String otherType) {
    return otherType.equals(typeMirror.toString());
  }

  private BindingSet.Builder getOrCreateBindingBuilder(
      Map<TypeElement, BindingSet.Builder> builderMap, TypeElement enclosingElement) {
    BindingSet.Builder builder = builderMap.get(enclosingElement);
    if (builder == null) {
      builder = BindingSet.newBuilder(enclosingElement);
      builderMap.put(enclosingElement, builder);
    }
    return builder;
  }

  /** Finds the parent binder type in the supplied sets, if any. */
  private @Nullable TypeElement findParentType(
      TypeElement typeElement, Set<TypeElement> parents, Set<TypeElement> classpathParents) {
    while (true) {
      typeElement = getSuperClass(typeElement);
      if (typeElement == null || parents.contains(typeElement)
          || classpathParents.contains(typeElement)) {
        return typeElement;
      }
    }
  }

  private Map<TypeElement, ClasspathBindingSet> findAllSupertypeBindings(
      Map<TypeElement, BindingSet.Builder> builderMap, Set<TypeElement> processedInThisRound) {
    Map<TypeElement, ClasspathBindingSet> classpathBindings = new HashMap<>();

    Set<Class<? extends Annotation>> supportedAnnotations = getSupportedAnnotations();
    Set<Class<? extends Annotation>> requireViewInConstructor =
        ImmutableSet.<Class<? extends Annotation>>builder()
            .addAll(LISTENERS).add(BindView.class).add(BindViews.class).build();
    supportedAnnotations.removeAll(requireViewInConstructor);

    for (TypeElement typeElement : builderMap.keySet()) {
      // Make sure to process superclass before subclass. This is because if there is a class that
      // requires a View in the constructor, all subclasses need it as well.
      Deque<TypeElement> superClasses = new ArrayDeque<>();
      TypeElement superClass = getSuperClass(typeElement);
      while (superClass != null && !processedInThisRound.contains(superClass)
          && !classpathBindings.containsKey(superClass)) {
        superClasses.addFirst(superClass);
        superClass = getSuperClass(superClass);
      }

      boolean parentHasConstructorWithView = false;
      while (!superClasses.isEmpty()) {
        TypeElement superclass = superClasses.removeFirst();
        ClasspathBindingSet classpathBinding =
            findBindingInfoForType(superclass, requireViewInConstructor, supportedAnnotations,
                parentHasConstructorWithView);
        if (classpathBinding != null) {
          parentHasConstructorWithView |= classpathBinding.constructorNeedsView();
          classpathBindings.put(superclass, classpathBinding);
        }
      }
    }
    return ImmutableMap.copyOf(classpathBindings);
  }

  private @Nullable ClasspathBindingSet findBindingInfoForType(
      TypeElement typeElement, Set<Class<? extends Annotation>> requireConstructorWithView,
      Set<Class<? extends Annotation>> otherAnnotations, boolean needsConstructorWithView) {
    boolean foundSupportedAnnotation = false;
    for (Element enclosedElement : typeElement.getEnclosedElements()) {
      for (Class<? extends Annotation> bindViewAnnotation : requireConstructorWithView) {
        if (enclosedElement.getAnnotation(bindViewAnnotation) != null) {
          return new ClasspathBindingSet(true, typeElement);
        }
      }
      for (Class<? extends Annotation> supportedAnnotation : otherAnnotations) {
        if (enclosedElement.getAnnotation(supportedAnnotation) != null) {
          if (needsConstructorWithView) {
            return new ClasspathBindingSet(true, typeElement);
          }
          foundSupportedAnnotation = true;
        }
      }
    }
    if (foundSupportedAnnotation) {
      return new ClasspathBindingSet(false, typeElement);
    } else {
      return null;
    }
  }

  private @Nullable TypeElement getSuperClass(TypeElement typeElement) {
    TypeMirror type = typeElement.getSuperclass();
    if (type.getKind() == TypeKind.NONE) {
      return null;
    }
    return (TypeElement) ((DeclaredType) type).asElement();
  }

  @Override public SourceVersion getSupportedSourceVersion() {
    return SourceVersion.latestSupported();
  }

  private void error(Element element, String message, Object... args) {
    printMessage(Kind.ERROR, element, message, args);
  }

  private void note(Element element, String message, Object... args) {
    printMessage(Kind.NOTE, element, message, args);
  }

  private void printMessage(Kind kind, Element element, String message, Object[] args) {
    if (args.length > 0) {
      message = String.format(message, args);
    }

    processingEnv.getMessager().printMessage(kind, message, element);
  }

  private Id elementToId(Element element, Class<? extends Annotation> annotation, int value) {
    JCTree tree = (JCTree) trees.getTree(element, getMirror(element, annotation));
    if (tree != null) { // tree can be null if the references are compiled types and not source
      rScanner.reset();
      tree.accept(rScanner);
      if (!rScanner.resourceIds.isEmpty()) {
        return rScanner.resourceIds.values().iterator().next();
      }
    }
    return new Id(value);
  }

  private Map<Integer, Id> elementToIds(Element element, Class<? extends Annotation> annotation,
      int[] values) {
    Map<Integer, Id> resourceIds = new LinkedHashMap<>();
    JCTree tree = (JCTree) trees.getTree(element, getMirror(element, annotation));
    if (tree != null) { // tree can be null if the references are compiled types and not source
      rScanner.reset();
      tree.accept(rScanner);
      resourceIds = rScanner.resourceIds;
    }

    // Every value looked up should have an Id
    for (int value : values) {
      resourceIds.putIfAbsent(value, new Id(value));
    }
    return resourceIds;
  }

  private static boolean hasAnnotationWithName(Element element, String simpleName) {
    for (AnnotationMirror mirror : element.getAnnotationMirrors()) {
      String annotationName = mirror.getAnnotationType().asElement().getSimpleName().toString();
      if (simpleName.equals(annotationName)) {
        return true;
      }
    }
    return false;
  }

  private static boolean isFieldRequired(Element element) {
    return !hasAnnotationWithName(element, NULLABLE_ANNOTATION_NAME);
  }

  private static boolean isListenerRequired(ExecutableElement element) {
    return element.getAnnotation(Optional.class) == null;
  }

  private static @Nullable AnnotationMirror getMirror(Element element,
      Class<? extends Annotation> annotation) {
    for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
      if (annotationMirror.getAnnotationType().toString().equals(annotation.getCanonicalName())) {
        return annotationMirror;
      }
    }
    return null;
  }

  private static class RScanner extends TreeScanner {
    Map<Integer, Id> resourceIds = new LinkedHashMap<>();

    @Override
    public void visitIdent(JCTree.JCIdent jcIdent) {
      super.visitIdent(jcIdent);
      Symbol symbol = jcIdent.sym;
      if (symbol.type instanceof Type.JCPrimitiveType) {
        Id id = parseId(symbol);
        if (id != null) {
          resourceIds.put(id.value, id);
        }
      }
    }

    @Override public void visitSelect(JCTree.JCFieldAccess jcFieldAccess) {
      Symbol symbol = jcFieldAccess.sym;
      Id id = parseId(symbol);
      if (id != null) {
        resourceIds.put(id.value, id);
      }
    }

    @Nullable
    private Id parseId(Symbol symbol) {
      Id id = null;
      if (symbol.getEnclosingElement() != null
          && symbol.getEnclosingElement().getEnclosingElement() != null
          && symbol.getEnclosingElement().getEnclosingElement().enclClass() != null) {
        try {
          int value = (Integer) requireNonNull(((Symbol.VarSymbol) symbol).getConstantValue());
          id = new Id(value, symbol);
        } catch (Exception ignored) { }
      }
      return id;
    }

    @Override public void visitLiteral(JCTree.JCLiteral jcLiteral) {
      try {
        int value = (Integer) jcLiteral.value;
        resourceIds.put(value, new Id(value));
      } catch (Exception ignored) { }
    }

    void reset() {
      resourceIds.clear();
    }
  }
}


================================================
FILE: butterknife-compiler/src/main/java/butterknife/compiler/FieldAnimationBinding.java
================================================
package butterknife.compiler;

import com.squareup.javapoet.CodeBlock;

import static butterknife.compiler.BindingSet.ANIMATION_UTILS;

final class FieldAnimationBinding implements ResourceBinding {
  private final Id id;
  private final String name;

  FieldAnimationBinding(Id id, String name) {
    this.id = id;
    this.name = name;
  }

  @Override public Id id() {
    return id;
  }

  @Override public boolean requiresResources(int sdk) {
    return false;
  }

  @Override public CodeBlock render(int sdk) {
    return CodeBlock.of("target.$L = $T.loadAnimation(context, $L)", name, ANIMATION_UTILS,
            id.code);
  }
}


================================================
FILE: butterknife-compiler/src/main/java/butterknife/compiler/FieldCollectionViewBinding.java
================================================
package butterknife.compiler;

import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import java.util.List;

import static butterknife.compiler.BindingSet.UTILS;
import static butterknife.compiler.BindingSet.requiresCast;

final class FieldCollectionViewBinding {
  enum Kind {
    ARRAY("arrayFilteringNull"),
    LIST("listFilteringNull");

    final String factoryName;

    Kind(String factoryName) {
      this.factoryName = factoryName;
    }
  }

  final String name;
  private final TypeName type;
  private final Kind kind;
  private final boolean required;
  private final List<Id> ids;

  FieldCollectionViewBinding(String name, TypeName type, Kind kind, List<Id> ids,
      boolean required) {
    this.name = name;
    this.type = type;
    this.kind = kind;
    this.ids = ids;
    this.required = required;
  }

  CodeBlock render(boolean debuggable) {
    CodeBlock.Builder builder = CodeBlock.builder()
        .add("target.$L = $T.$L(", name, UTILS, kind.factoryName);
    for (int i = 0; i < ids.size(); i++) {
      if (i > 0) {
        builder.add(", ");
      }
      builder.add("\n");

      Id id = ids.get(i);
      boolean requiresCast = requiresCast(type);
      if (!debuggable) {
        if (requiresCast) {
          builder.add("($T) ", type);
        }
        builder.add("source.findViewById($L)", id.code);
      } else if (!requiresCast && !required) {
        builder.add("source.findViewById($L)", id.code);
      } else {
        builder.add("$T.find", UTILS);
        builder.add(required ? "RequiredView" : "OptionalView");
        if (requiresCast) {
          builder.add("AsType");
        }
        builder.add("(source, $L, \"field '$L'\"", id.code, name);
        if (requiresCast) {
          TypeName rawType = type;
          if (rawType instanceof ParameterizedTypeName) {
            rawType = ((ParameterizedTypeName) rawType).rawType;
          }
          builder.add(", $T.class", rawType);
        }
        builder.add(")");
      }
    }
    return builder.add(")").build();
  }
}


================================================
FILE: butterknife-compiler/src/main/java/butterknife/compiler/FieldDrawableBinding.java
================================================
package butterknife.compiler;

import com.squareup.javapoet.CodeBlock;

import static butterknife.compiler.BindingSet.CONTEXT_COMPAT;
import static butterknife.compiler.BindingSet.UTILS;
import static butterknife.internal.Constants.NO_RES_ID;

final class FieldDrawableBinding implements ResourceBinding {
  private final Id id;
  private final String name;
  private final Id tintAttributeId;

  FieldDrawableBinding(Id id, String name, Id tintAttributeId) {
    this.id = id;
    this.name = name;
    this.tintAttributeId = tintAttributeId;
  }

  @Override public Id id() {
    return id;
  }

  @Override public boolean requiresResources(int sdk) {
    return false;
  }

  @Override public CodeBlock render(int sdk) {
    if (tintAttributeId.value != NO_RES_ID) {
      return CodeBlock.of("target.$L = $T.getTintedDrawable(context, $L, $L)", name, UTILS, id.code,
          tintAttributeId.code);
    }
    if (sdk >= 21) {
      return CodeBlock.of("target.$L = context.getDrawable($L)", name, id.code);
    }
    return CodeBlock.of("target.$L = $T.getDrawable(context, $L)", name, CONTEXT_COMPAT, id.code);
  }
}


================================================
FILE: butterknife-compiler/src/main/java/butterknife/compiler/FieldResourceBinding.java
================================================
package butterknife.compiler;

import androidx.annotation.Nullable;
import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.Immutable;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

final class FieldResourceBinding implements ResourceBinding {
  enum Type {
    BITMAP(new ResourceMethod(BindingSet.BITMAP_FACTORY, "decodeResource", true, 1)),
    BOOL("getBoolean"),
    COLOR(new ResourceMethod(BindingSet.CONTEXT_COMPAT, "getColor", false, 1),
        new ResourceMethod(null, "getColor", false, 23)),
    COLOR_STATE_LIST(new ResourceMethod(BindingSet.CONTEXT_COMPAT,
        "getColorStateList", false, 1),
        new ResourceMethod(null, "getColorStateList", false, 23)),
    DIMEN_AS_INT("getDimensionPixelSize"),
    DIMEN_AS_FLOAT("getDimension"),
    FLOAT(new ResourceMethod(BindingSet.UTILS, "getFloat", false, 1)),
    INT("getInteger"),
    INT_ARRAY("getIntArray"),
    STRING("getString"),
    STRING_ARRAY("getStringArray"),
    TEXT_ARRAY("getTextArray"),
    TYPED_ARRAY("obtainTypedArray");

    private final ImmutableList<ResourceMethod> methods;

    Type(ResourceMethod... methods) {
      List<ResourceMethod> methodList = new ArrayList<>(methods.length);
      Collections.addAll(methodList, methods);
      Collections.sort(methodList);
      Collections.reverse(methodList);
      this.methods = ImmutableList.copyOf(methodList);
    }

    Type(String methodName) {
      methods = ImmutableList.of(new ResourceMethod(null, methodName, true, 1));
    }

    ResourceMethod methodForSdk(int sdk) {
      for (ResourceMethod method : methods) {
        if (method.sdk <= sdk) {
          return method;
        }
      }
      throw new AssertionError();
    }
  }

  @Immutable
  static final class ResourceMethod implements Comparable<ResourceMethod> {
    @SuppressWarnings("Immutable")
    final @Nullable ClassName typeName;
    final String name;
    final boolean requiresResources;
    final int sdk;

    ResourceMethod(@Nullable ClassName typeName, String name, boolean requiresResources, int sdk) {
      this.typeName = typeName;
      this.name = name;
      this.requiresResources = requiresResources;
      this.sdk = sdk;
    }

    @Override public int compareTo(ResourceMethod other) {
      return Integer.compare(sdk, other.sdk);
    }
  }

  private final Id id;
  private final String name;
  private final Type type;

  FieldResourceBinding(Id id, String name, Type type) {
    this.id = id;
    this.name = name;
    this.type = type;
  }

  @Override public Id id() {
    return id;
  }

  @Override public boolean requiresResources(int sdk) {
    return type.methodForSdk(sdk).requiresResources;
  }

  @Override public CodeBlock render(int sdk) {
    ResourceMethod method = type.methodForSdk(sdk);
    if (method.typeName == null) {
      if (method.requiresResources) {
        return CodeBlock.of("target.$L = res.$L($L)", name, method.name, id.code);
      }
      return CodeBlock.of("target.$L = context.$L($L)", name, method.name, id.code);
    }
    if (method.requiresResources) {
      return CodeBlock.of("target.$L = $T.$L(res, $L)", name, method.typeName, method.name,
          id.code);
    }
    return CodeBlock.of("target.$L = $T.$L(context, $L)", name, method.typeName, method.name,
        id.code);
  }
}


================================================
FILE: butterknife-compiler/src/main/java/butterknife/compiler/FieldTypefaceBinding.java
================================================
package butterknife.compiler;

import androidx.annotation.Nullable;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;

final class FieldTypefaceBinding implements ResourceBinding {
  private static final ClassName RESOURCES_COMPAT =
      ClassName.get("androidx.core.content.res", "ResourcesCompat");
  private static final ClassName TYPEFACE = ClassName.get("android.graphics", "Typeface");

  /** Keep in sync with {@link android.graphics.Typeface} constants. */
  enum TypefaceStyles {
    NORMAL(0),
    BOLD(1),
    ITALIC(2),
    BOLD_ITALIC(3);

    final int value;

    TypefaceStyles(int value) {
      this.value = value;
    }

    @Nullable static TypefaceStyles fromValue(int value) {
      for (TypefaceStyles style : values()) {
        if (style.value == value) {
          return style;
        }
      }
      return null;
    }
  }

  private final Id id;
  private final String name;
  private final TypefaceStyles style;

  FieldTypefaceBinding(Id id, String name, TypefaceStyles style) {
    this.id = id;
    this.name = name;
    this.style = style;
  }

  @Override public Id id() {
    return id;
  }

  @Override public boolean requiresResources(int sdk) {
    return sdk >= 26;
  }

  @Override public CodeBlock render(int sdk) {
    CodeBlock typeface = sdk >= 26
        ? CodeBlock.of("res.getFont($L)", id.code)
        : CodeBlock.of("$T.getFont(context, $L)", RESOURCES_COMPAT, id.code);
    if (style != TypefaceStyles.NORMAL) {
      typeface = CodeBlock.of("$1T.create($2L, $1T.$3L)", TYPEFACE, typeface, style);
    }
    return CodeBlock.of("target.$L = $L", name, typeface);
  }
}


================================================
FILE: butterknife-compiler/src/main/java/butterknife/compiler/FieldViewBinding.java
================================================
package butterknife.compiler;

import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;

final class FieldViewBinding implements MemberViewBinding {
  private final String name;
  private final TypeName type;
  private final boolean required;

  FieldViewBinding(String name, TypeName type, boolean required) {
    this.name = name;
    this.type = type;
    this.required = required;
  }

  public String getName() {
    return name;
  }

  public TypeName getType() {
    return type;
  }

  public ClassName getRawType() {
    if (type instanceof ParameterizedTypeName) {
      return ((ParameterizedTypeName) type).rawType;
    }
    return (ClassName) type;
  }

  @Override public String getDescription() {
    return "field '" + name + "'";
  }

  public boolean isRequired() {
    return required;
  }
}


================================================
FILE: butterknife-compiler/src/main/java/butterknife/compiler/Id.java
================================================
package butterknife.compiler;

import androidx.annotation.Nullable;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.sun.tools.javac.code.Symbol;

/**
 * Represents an ID of an Android resource.
 */
final class Id {
  private static final ClassName ANDROID_R = ClassName.get("android", "R");
  private static final String R = "R";

  final int value;
  final CodeBlock code;
  final boolean qualifed;

  Id(int value) {
    this(value, null);
  }

  Id(int value, @Nullable Symbol rSymbol) {
    this.value = value;
    if (rSymbol != null) {
      ClassName className = ClassName.get(rSymbol.packge().getQualifiedName().toString(), R,
          rSymbol.enclClass().name.toString());
      String resourceName = rSymbol.name.toString();

      this.code = className.topLevelClassName().equals(ANDROID_R)
        ? CodeBlock.of("$L.$N", className, resourceName)
        : CodeBlock.of("$T.$N", className, resourceName);
      this.qualifed = true;
    } else {
      this.code = CodeBlock.of("$L", value);
      this.qualifed = false;
    }
  }

  @Override public boolean equals(Object o) {
    return o instanceof Id && value == ((Id) o).value;
  }

  @Override public int hashCode() {
    return value;
  }

  @Override public String toString() {
    throw new UnsupportedOperationException("Please use value or code explicitly");
  }
}


================================================
FILE: butterknife-compiler/src/main/java/butterknife/compiler/MemberViewBinding.java
================================================
package butterknife.compiler;

/** A field or method view binding. */
interface MemberViewBinding {
  /** A description of the binding in human readable form (e.g., "field 'foo'"). */
  String getDescription();
}


================================================
FILE: butterknife-compiler/src/main/java/butterknife/compiler/MethodViewBinding.java
================================================
package butterknife.compiler;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

final class MethodViewBinding implements MemberViewBinding {
  private final String name;
  private final List<Parameter> parameters;
  private final boolean required;
  private final boolean hasReturnValue;

  MethodViewBinding(String name, List<Parameter> parameters, boolean required,
      boolean hasReturnValue) {
    this.name = name;
    this.parameters = Collections.unmodifiableList(new ArrayList<>(parameters));
    this.required = required;
    this.hasReturnValue = hasReturnValue;
  }

  public String getName() {
    return name;
  }

  public List<Parameter> getParameters() {
    return parameters;
  }

  @Override public String getDescription() {
    return "method '" + name + "'";
  }

  public boolean isRequired() {
    return required;
  }

  public boolean hasReturnValue() {
    return hasReturnValue;
  }
}


================================================
FILE: butterknife-compiler/src/main/java/butterknife/compiler/Parameter.java
================================================
package butterknife.compiler;

import com.squareup.javapoet.TypeName;

/** Represents a parameter type and its position in the listener method. */
final class Parameter {
  static final Parameter[] NONE = new Parameter[0];

  private final int listenerPosition;
  private final TypeName type;

  Parameter(int listenerPosition, TypeName type) {
    this.listenerPosition = listenerPosition;
    this.type = type;
  }

  int getListenerPosition() {
    return listenerPosition;
  }

  TypeName getType() {
    return type;
  }

  public boolean requiresCast(String toType) {
    return !type.toString().equals(toType);
  }
}


================================================
FILE: butterknife-compiler/src/main/java/butterknife/compiler/Resourc
Download .txt
gitextract_9jjk0dbd/

├── .buildscript/
│   └── deploy_snapshot.sh
├── .github/
│   └── workflows/
│       └── gradle-wrapper-validation.yml
├── .gitignore
├── .travis.yml
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── RELEASING.md
├── build.gradle
├── butterknife/
│   ├── build.gradle
│   ├── gradle.properties
│   ├── proguard-rules.txt
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── butterknife/
│       │           └── ButterKnifeTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── butterknife/
│                   ├── ButterKnife.java
│                   └── package-info.java
├── butterknife-annotations/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       └── main/
│           └── java/
│               └── butterknife/
│                   ├── BindAnim.java
│                   ├── BindArray.java
│                   ├── BindBitmap.java
│                   ├── BindBool.java
│                   ├── BindColor.java
│                   ├── BindDimen.java
│                   ├── BindDrawable.java
│                   ├── BindFloat.java
│                   ├── BindFont.java
│                   ├── BindInt.java
│                   ├── BindString.java
│                   ├── BindView.java
│                   ├── BindViews.java
│                   ├── OnCheckedChanged.java
│                   ├── OnClick.java
│                   ├── OnEditorAction.java
│                   ├── OnFocusChange.java
│                   ├── OnItemClick.java
│                   ├── OnItemLongClick.java
│                   ├── OnItemSelected.java
│                   ├── OnLongClick.java
│                   ├── OnPageChange.java
│                   ├── OnTextChanged.java
│                   ├── OnTouch.java
│                   ├── Optional.java
│                   └── internal/
│                       ├── Constants.java
│                       ├── ListenerClass.java
│                       └── ListenerMethod.java
├── butterknife-compiler/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── butterknife/
│       │           └── compiler/
│       │               ├── BindingSet.java
│       │               ├── ButterKnifeProcessor.java
│       │               ├── FieldAnimationBinding.java
│       │               ├── FieldCollectionViewBinding.java
│       │               ├── FieldDrawableBinding.java
│       │               ├── FieldResourceBinding.java
│       │               ├── FieldTypefaceBinding.java
│       │               ├── FieldViewBinding.java
│       │               ├── Id.java
│       │               ├── MemberViewBinding.java
│       │               ├── MethodViewBinding.java
│       │               ├── Parameter.java
│       │               ├── ResourceBinding.java
│       │               └── ViewBinding.java
│       └── test/
│           └── java/
│               └── butterknife/
│                   └── compiler/
│                       └── BindingSetTest.java
├── butterknife-gradle-plugin/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── butterknife/
│       │   │       └── plugin/
│       │   │           ├── ButterKnifePlugin.kt
│       │   │           ├── FinalRClassBuilder.kt
│       │   │           ├── R2Generator.kt
│       │   │           └── ResourceSymbolListReader.kt
│       │   └── resources/
│       │       └── META-INF/
│       │           └── gradle-plugins/
│       │               └── com.jakewharton.butterknife.properties
│       └── test/
│           ├── AndroidManifest.xml
│           ├── build.gradle
│           ├── fixtures/
│           │   └── suffix_parsed_properly/
│           │       └── src/
│           │           └── main/
│           │               ├── java/
│           │               │   └── butterknife/
│           │               │       └── test/
│           │               │           └── ButteryActivity.java
│           │               └── res/
│           │                   └── layout/
│           │                       └── activity_layout.xml
│           ├── java/
│           │   └── butterknife/
│           │       └── plugin/
│           │           ├── AndroidHome.kt
│           │           ├── BuildFilesRule.kt
│           │           ├── FinalRClassBuilderTest.kt
│           │           └── FixturesTest.kt
│           └── resources/
│               └── fixtures/
│                   ├── R.txt
│                   └── R2.java
├── butterknife-integration-test/
│   ├── build.gradle
│   └── src/
│       ├── androidTest/
│       │   ├── font_licenses.txt
│       │   ├── java/
│       │   │   └── com/
│       │   │       └── example/
│       │   │           └── butterknife/
│       │   │               ├── functional/
│       │   │               │   ├── BindAnimTest.java
│       │   │               │   ├── BindArrayTest.java
│       │   │               │   ├── BindBitmapTest.java
│       │   │               │   ├── BindBoolTest.java
│       │   │               │   ├── BindColorTest.java
│       │   │               │   ├── BindDimenTest.java
│       │   │               │   ├── BindDrawableTest.java
│       │   │               │   ├── BindFloatTest.java
│       │   │               │   ├── BindFontTest.java
│       │   │               │   ├── BindIntTest.java
│       │   │               │   ├── BindStringTest.java
│       │   │               │   ├── BindViewTest.java
│       │   │               │   ├── BindViewsTest.java
│       │   │               │   ├── OnCheckedChangedTest.java
│       │   │               │   ├── OnClickTest.java
│       │   │               │   ├── OnItemClickTest.java
│       │   │               │   ├── OnItemLongClickTest.java
│       │   │               │   ├── OnItemSelectedTest.java
│       │   │               │   ├── OnLongClickTest.java
│       │   │               │   ├── OnTouchTest.java
│       │   │               │   └── ViewTree.java
│       │   │               ├── library/
│       │   │               │   ├── SimpleActivityTest.java
│       │   │               │   └── SimpleAdapterTest.java
│       │   │               └── unbinder/
│       │   │                   └── UnbinderTest.java
│       │   ├── proguard.pro
│       │   └── res/
│       │       ├── color/
│       │       │   └── colors.xml
│       │       ├── drawable/
│       │       │   └── circle.xml
│       │       └── values/
│       │           └── values.xml
│       ├── androidTestReflect/
│       │   └── java/
│       │       └── com/
│       │           └── example/
│       │               └── butterknife/
│       │                   └── functional/
│       │                       ├── BindAnimFailureTest.java
│       │                       ├── BindArrayFailureTest.java
│       │                       ├── BindBitmapFailureTest.java
│       │                       ├── BindBoolFailureTest.java
│       │                       ├── BindColorFailureTest.java
│       │                       ├── BindDimenFailureTest.java
│       │                       ├── BindDrawableFailureTest.java
│       │                       ├── BindFloatFailureTest.java
│       │                       ├── BindFontFailureTest.java
│       │                       ├── BindIntFailureTest.java
│       │                       ├── BindStringFailureTest.java
│       │                       ├── BindViewFailureTest.java
│       │                       └── BindViewsFailureTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── com/
│           │       └── example/
│           │           └── butterknife/
│           │               ├── SimpleApp.java
│           │               ├── library/
│           │               │   ├── SimpleActivity.java
│           │               │   └── SimpleAdapter.java
│           │               └── unbinder/
│           │                   ├── A.java
│           │                   ├── B.java
│           │                   ├── C.java
│           │                   ├── D.java
│           │                   ├── E.java
│           │                   ├── F.java
│           │                   ├── G.java
│           │                   └── H.java
│           ├── proguard.pro
│           └── res/
│               ├── layout/
│               │   ├── simple_activity.xml
│               │   └── simple_list_item.xml
│               └── values/
│                   └── strings.xml
├── butterknife-lint/
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── java/
│       │       └── butterknife/
│       │           └── lint/
│       │               ├── InvalidR2UsageDetector.java
│       │               └── LintRegistry.java
│       └── test/
│           └── java/
│               └── butterknife/
│                   └── lint/
│                       ├── InvalidR2UsageDetectorTest.java
│                       └── LintRegistryTest.java
├── butterknife-reflect/
│   ├── README.md
│   ├── build.gradle
│   ├── gradle.properties
│   ├── proguard-rules.txt
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── java/
│               └── butterknife/
│                   ├── ButterKnife.java
│                   ├── CompositeUnbinder.java
│                   ├── EmptyTextWatcher.java
│                   ├── FieldUnbinder.java
│                   └── ListenerUnbinder.java
├── butterknife-runtime/
│   ├── build.gradle
│   ├── gradle.properties
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── butterknife/
│       │           ├── ViewCollectionsTest.java
│       │           └── internal/
│       │               └── UtilsTest.java
│       ├── main/
│       │   ├── AndroidManifest.xml
│       │   └── java/
│       │       └── butterknife/
│       │           ├── Action.java
│       │           ├── Setter.java
│       │           ├── Unbinder.java
│       │           ├── ViewCollections.java
│       │           └── internal/
│       │               ├── DebouncingOnClickListener.java
│       │               ├── ImmutableList.java
│       │               └── Utils.java
│       └── test/
│           └── java/
│               └── butterknife/
│                   ├── BindAnimTest.java
│                   ├── BindArrayTest.java
│                   ├── BindBitmapTest.java
│                   ├── BindBoolTest.java
│                   ├── BindColorTest.java
│                   ├── BindDimenTest.java
│                   ├── BindDrawableTest.java
│                   ├── BindFloatTest.java
│                   ├── BindFontTest.java
│                   ├── BindIntTest.java
│                   ├── BindStringTest.java
│                   ├── BindViewTest.java
│                   ├── BindViewsTest.java
│                   ├── ClasspathParentBindTest.java
│                   ├── ExtendActivityTest.java
│                   ├── ExtendDialogTest.java
│                   ├── ExtendViewTest.java
│                   ├── OnClickTest.java
│                   ├── OnEditorActionTest.java
│                   ├── OnFocusChangeTest.java
│                   ├── OnItemClickTest.java
│                   ├── OnItemLongClickTest.java
│                   ├── OnItemSelectedTest.java
│                   ├── OnPageChangeTest.java
│                   ├── OnTextChangedTest.java
│                   ├── OnTouchTest.java
│                   ├── RClassTest.java
│                   ├── TestGeneratingProcessor.java
│                   ├── TestStubs.java
│                   ├── UnbinderTest.java
│                   └── UtilsTest.java
├── checkstyle.xml
├── deploy_website.sh
├── gradle/
│   ├── gradle-mvn-push.gradle
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── sample/
│   ├── app/
│   │   ├── build.gradle
│   │   └── src/
│   │       └── main/
│   │           ├── AndroidManifest.xml
│   │           └── java/
│   │               └── com/
│   │                   └── example/
│   │                       └── butterknife/
│   │                           ├── SimpleApp.java
│   │                           └── unbinder/
│   │                               ├── A.java
│   │                               ├── B.java
│   │                               ├── C.java
│   │                               ├── D.java
│   │                               ├── E.java
│   │                               ├── F.java
│   │                               ├── G.java
│   │                               └── H.java
│   └── library/
│       ├── build.gradle
│       └── src/
│           └── main/
│               ├── AndroidManifest.xml
│               ├── java/
│               │   └── com/
│               │       └── example/
│               │           └── butterknife/
│               │               └── library/
│               │                   ├── SimpleActivity.java
│               │                   └── SimpleAdapter.java
│               └── res/
│                   ├── layout/
│                   │   ├── simple_activity.xml
│                   │   └── simple_list_item.xml
│                   └── values/
│                       └── strings.xml
├── settings.gradle
└── website/
    ├── ide-eclipse.html
    ├── ide-idea.html
    ├── index.html
    └── static/
        ├── app.css
        ├── butter_android.psd
        ├── logo.psd
        ├── prettify.css
        └── prettify.js
Download .txt
SYMBOL INDEX (913 symbols across 133 files)

FILE: butterknife-annotations/src/main/java/butterknife/OnItemSelected.java
  type Callback (line 52) | enum Callback {

FILE: butterknife-annotations/src/main/java/butterknife/OnPageChange.java
  type Callback (line 47) | enum Callback {

FILE: butterknife-annotations/src/main/java/butterknife/OnTextChanged.java
  type Callback (line 51) | enum Callback {

FILE: butterknife-annotations/src/main/java/butterknife/internal/Constants.java
  class Constants (line 3) | public class Constants {
    method Constants (line 5) | private Constants() { }

FILE: butterknife-annotations/src/main/java/butterknife/internal/ListenerClass.java
  type NONE (line 35) | enum NONE { }

FILE: butterknife-compiler/src/main/java/butterknife/compiler/BindingSet.java
  class BindingSet (line 42) | final class BindingSet implements BindingInformationProvider {
    method BindingSet (line 72) | private BindingSet(
    method getBindingClassName (line 92) | @Override
    method brewJava (line 97) | JavaFile brewJava(int sdk, boolean debuggable) {
    method createType (line 104) | private TypeSpec createType(int sdk, boolean debuggable) {
    method createBindingViewDelegateConstructor (line 142) | private MethodSpec createBindingViewDelegateConstructor() {
    method createBindingConstructorForView (line 156) | private MethodSpec createBindingConstructorForView() {
    method createBindingConstructorForActivity (line 169) | private MethodSpec createBindingConstructorForActivity() {
    method createBindingConstructorForDialog (line 182) | private MethodSpec createBindingConstructorForDialog() {
    method createBindingConstructor (line 195) | private MethodSpec createBindingConstructor(int sdk, boolean debuggabl...
    method createBindingUnbindMethod (line 272) | private MethodSpec createBindingUnbindMethod(TypeSpec.Builder bindingC...
    method addFieldAndUnbindStatement (line 312) | private void addFieldAndUnbindStatement(TypeSpec.Builder result, Metho...
    method removerOrSetter (line 365) | private String removerOrSetter(ListenerClass listenerClass, boolean re...
    method addViewBinding (line 371) | private void addViewBinding(MethodSpec.Builder result, ViewBinding bin...
    method addFieldBinding (line 415) | private void addFieldBinding(MethodSpec.Builder result, ViewBinding bi...
    method addMethodBindings (line 433) | private void addMethodBindings(MethodSpec.Builder result, ViewBinding ...
    method getListenerMethods (line 541) | private static List<ListenerMethod> getListenerMethods(ListenerClass l...
    method asHumanDescription (line 565) | static String asHumanDescription(Collection<? extends MemberViewBindin...
    method bestGuess (line 587) | private static TypeName bestGuess(String type) {
    method hasViewBindings (line 615) | private boolean hasViewBindings() {
    method hasUnqualifiedResourceBindings (line 620) | private boolean hasUnqualifiedResourceBindings() {
    method hasResourceBindingsNeedingResource (line 630) | private boolean hasResourceBindingsNeedingResource(int sdk) {
    method hasMethodBindings (line 639) | private boolean hasMethodBindings() {
    method hasOnTouchMethodBindings (line 648) | private boolean hasOnTouchMethodBindings() {
    method hasFieldBindings (line 658) | private boolean hasFieldBindings() {
    method hasTargetField (line 667) | private boolean hasTargetField() {
    method hasViewLocal (line 671) | private boolean hasViewLocal() {
    method constructorNeedsView (line 681) | @Override
    method requiresCast (line 687) | static boolean requiresCast(TypeName type) {
    method toString (line 691) | @Override public String toString() {
    method newBuilder (line 695) | static Builder newBuilder(TypeElement enclosingElement) {
    method getBindingClassName (line 714) | static ClassName getBindingClassName(TypeElement typeElement) {
    class Builder (line 721) | static final class Builder {
      method Builder (line 737) | private Builder(
      method addField (line 749) | void addField(Id id, FieldViewBinding binding) {
      method addFieldCollection (line 753) | void addFieldCollection(FieldCollectionViewBinding binding) {
      method addMethod (line 757) | boolean addMethod(
      method addResource (line 770) | void addResource(ResourceBinding binding) {
      method setParent (line 774) | void setParent(BindingInformationProvider parent) {
      method findExistingBindingName (line 778) | @Nullable String findExistingBindingName(Id id) {
      method getOrCreateViewBindings (line 790) | private ViewBinding.Builder getOrCreateViewBindings(Id id) {
      method build (line 799) | BindingSet build() {
  type BindingInformationProvider (line 811) | interface BindingInformationProvider {
    method constructorNeedsView (line 812) | boolean constructorNeedsView();
    method getBindingClassName (line 813) | ClassName getBindingClassName();
  class ClasspathBindingSet (line 816) | final class ClasspathBindingSet implements BindingInformationProvider {
    method ClasspathBindingSet (line 820) | ClasspathBindingSet(boolean constructorNeedsView, TypeElement classEle...
    method getBindingClassName (line 825) | @Override
    method constructorNeedsView (line 830) | @Override

FILE: butterknife-compiler/src/main/java/butterknife/compiler/ButterKnifeProcessor.java
  class ButterKnifeProcessor (line 91) | @AutoService(Processor.class)
    method init (line 134) | @Override public synchronized void init(ProcessingEnvironment env) {
    method getSupportedOptions (line 171) | @Override public Set<String> getSupportedOptions() {
    method getSupportedAnnotationTypes (line 180) | @Override public Set<String> getSupportedAnnotationTypes() {
    method getSupportedAnnotations (line 188) | private Set<Class<? extends Annotation>> getSupportedAnnotations() {
    method process (line 209) | @Override public boolean process(Set<? extends TypeElement> elements, ...
    method findAndParseTargets (line 227) | private Map<TypeElement, BindingSet> findAndParseTargets(RoundEnvironm...
    method logParsingError (line 403) | private void logParsingError(Element element, Class<? extends Annotati...
    method isInaccessibleViaGeneratedCode (line 410) | private boolean isInaccessibleViaGeneratedCode(Class<? extends Annotat...
    method isBindingInWrongPackage (line 443) | private boolean isBindingInWrongPackage(Class<? extends Annotation> an...
    method parseBindView (line 462) | private void parseBindView(Element element, Map<TypeElement, BindingSe...
    method parseBindViews (line 520) | private void parseBindViews(Element element, Map<TypeElement, BindingS...
    method parseResourceAnimation (line 605) | private void parseResourceAnimation(Element element,
    method parseResourceBool (line 637) | private void parseResourceBool(Element element,
    method parseResourceColor (line 669) | private void parseResourceColor(Element element,
    method parseResourceDimen (line 710) | private void parseResourceDimen(Element element,
    method parseResourceBitmap (line 746) | private void parseResourceBitmap(Element element,
    method parseResourceDrawable (line 778) | private void parseResourceDrawable(Element element,
    method parseResourceFloat (line 811) | private void parseResourceFloat(Element element,
    method parseResourceFont (line 843) | private void parseResourceFont(Element element,
    method parseResourceInt (line 883) | private void parseResourceInt(Element element,
    method parseResourceString (line 914) | private void parseResourceString(Element element,
    method parseResourceArray (line 946) | private void parseResourceArray(Element element,
    method getArrayResourceMethodName (line 983) | private static @Nullable FieldResourceBinding.Type getArrayResourceMet...
    method findDuplicate (line 1003) | private static @Nullable Integer findDuplicate(int[] array) {
    method doubleErasure (line 1016) | private String doubleErasure(TypeMirror elementType) {
    method findAndParseListener (line 1025) | private void findAndParseListener(RoundEnvironment env,
    method parseListenerAnnotation (line 1042) | private void parseListenerAnnotation(Class<? extends Annotation> annot...
    method isInterface (line 1237) | private boolean isInterface(TypeMirror typeMirror) {
    method isSubtypeOfType (line 1242) | static boolean isSubtypeOfType(TypeMirror typeMirror, String otherType) {
    method isTypeEqual (line 1282) | private static boolean isTypeEqual(TypeMirror typeMirror, String other...
    method getOrCreateBindingBuilder (line 1286) | private BindingSet.Builder getOrCreateBindingBuilder(
    method findParentType (line 1297) | private @Nullable TypeElement findParentType(
    method findAllSupertypeBindings (line 1308) | private Map<TypeElement, ClasspathBindingSet> findAllSupertypeBindings(
    method findBindingInfoForType (line 1344) | private @Nullable ClasspathBindingSet findBindingInfoForType(
    method getSuperClass (line 1370) | private @Nullable TypeElement getSuperClass(TypeElement typeElement) {
    method getSupportedSourceVersion (line 1378) | @Override public SourceVersion getSupportedSourceVersion() {
    method error (line 1382) | private void error(Element element, String message, Object... args) {
    method note (line 1386) | private void note(Element element, String message, Object... args) {
    method printMessage (line 1390) | private void printMessage(Kind kind, Element element, String message, ...
    method elementToId (line 1398) | private Id elementToId(Element element, Class<? extends Annotation> an...
    method elementToIds (line 1410) | private Map<Integer, Id> elementToIds(Element element, Class<? extends...
    method hasAnnotationWithName (line 1427) | private static boolean hasAnnotationWithName(Element element, String s...
    method isFieldRequired (line 1437) | private static boolean isFieldRequired(Element element) {
    method isListenerRequired (line 1441) | private static boolean isListenerRequired(ExecutableElement element) {
    method getMirror (line 1445) | private static @Nullable AnnotationMirror getMirror(Element element,
    class RScanner (line 1455) | private static class RScanner extends TreeScanner {
      method visitIdent (line 1458) | @Override
      method visitSelect (line 1470) | @Override public void visitSelect(JCTree.JCFieldAccess jcFieldAccess) {
      method parseId (line 1478) | @Nullable
      method visitLiteral (line 1492) | @Override public void visitLiteral(JCTree.JCLiteral jcLiteral) {
      method reset (line 1499) | void reset() {

FILE: butterknife-compiler/src/main/java/butterknife/compiler/FieldAnimationBinding.java
  class FieldAnimationBinding (line 7) | final class FieldAnimationBinding implements ResourceBinding {
    method FieldAnimationBinding (line 11) | FieldAnimationBinding(Id id, String name) {
    method id (line 16) | @Override public Id id() {
    method requiresResources (line 20) | @Override public boolean requiresResources(int sdk) {
    method render (line 24) | @Override public CodeBlock render(int sdk) {

FILE: butterknife-compiler/src/main/java/butterknife/compiler/FieldCollectionViewBinding.java
  class FieldCollectionViewBinding (line 11) | final class FieldCollectionViewBinding {
    type Kind (line 12) | enum Kind {
      method Kind (line 18) | Kind(String factoryName) {
    method FieldCollectionViewBinding (line 29) | FieldCollectionViewBinding(String name, TypeName type, Kind kind, List...
    method render (line 38) | CodeBlock render(boolean debuggable) {

FILE: butterknife-compiler/src/main/java/butterknife/compiler/FieldDrawableBinding.java
  class FieldDrawableBinding (line 9) | final class FieldDrawableBinding implements ResourceBinding {
    method FieldDrawableBinding (line 14) | FieldDrawableBinding(Id id, String name, Id tintAttributeId) {
    method id (line 20) | @Override public Id id() {
    method requiresResources (line 24) | @Override public boolean requiresResources(int sdk) {
    method render (line 28) | @Override public CodeBlock render(int sdk) {

FILE: butterknife-compiler/src/main/java/butterknife/compiler/FieldResourceBinding.java
  class FieldResourceBinding (line 12) | final class FieldResourceBinding implements ResourceBinding {
    type Type (line 13) | enum Type {
      method Type (line 33) | Type(ResourceMethod... methods) {
      method Type (line 41) | Type(String methodName) {
      method methodForSdk (line 45) | ResourceMethod methodForSdk(int sdk) {
    class ResourceMethod (line 55) | @Immutable
      method ResourceMethod (line 63) | ResourceMethod(@Nullable ClassName typeName, String name, boolean re...
      method compareTo (line 70) | @Override public int compareTo(ResourceMethod other) {
    method FieldResourceBinding (line 79) | FieldResourceBinding(Id id, String name, Type type) {
    method id (line 85) | @Override public Id id() {
    method requiresResources (line 89) | @Override public boolean requiresResources(int sdk) {
    method render (line 93) | @Override public CodeBlock render(int sdk) {

FILE: butterknife-compiler/src/main/java/butterknife/compiler/FieldTypefaceBinding.java
  class FieldTypefaceBinding (line 7) | final class FieldTypefaceBinding implements ResourceBinding {
    type TypefaceStyles (line 13) | enum TypefaceStyles {
      method TypefaceStyles (line 21) | TypefaceStyles(int value) {
      method fromValue (line 25) | @Nullable static TypefaceStyles fromValue(int value) {
    method FieldTypefaceBinding (line 39) | FieldTypefaceBinding(Id id, String name, TypefaceStyles style) {
    method id (line 45) | @Override public Id id() {
    method requiresResources (line 49) | @Override public boolean requiresResources(int sdk) {
    method render (line 53) | @Override public CodeBlock render(int sdk) {

FILE: butterknife-compiler/src/main/java/butterknife/compiler/FieldViewBinding.java
  class FieldViewBinding (line 7) | final class FieldViewBinding implements MemberViewBinding {
    method FieldViewBinding (line 12) | FieldViewBinding(String name, TypeName type, boolean required) {
    method getName (line 18) | public String getName() {
    method getType (line 22) | public TypeName getType() {
    method getRawType (line 26) | public ClassName getRawType() {
    method getDescription (line 33) | @Override public String getDescription() {
    method isRequired (line 37) | public boolean isRequired() {

FILE: butterknife-compiler/src/main/java/butterknife/compiler/Id.java
  class Id (line 11) | final class Id {
    method Id (line 19) | Id(int value) {
    method Id (line 23) | Id(int value, @Nullable Symbol rSymbol) {
    method equals (line 40) | @Override public boolean equals(Object o) {
    method hashCode (line 44) | @Override public int hashCode() {
    method toString (line 48) | @Override public String toString() {

FILE: butterknife-compiler/src/main/java/butterknife/compiler/MemberViewBinding.java
  type MemberViewBinding (line 4) | interface MemberViewBinding {
    method getDescription (line 6) | String getDescription();

FILE: butterknife-compiler/src/main/java/butterknife/compiler/MethodViewBinding.java
  class MethodViewBinding (line 7) | final class MethodViewBinding implements MemberViewBinding {
    method MethodViewBinding (line 13) | MethodViewBinding(String name, List<Parameter> parameters, boolean req...
    method getName (line 21) | public String getName() {
    method getParameters (line 25) | public List<Parameter> getParameters() {
    method getDescription (line 29) | @Override public String getDescription() {
    method isRequired (line 33) | public boolean isRequired() {
    method hasReturnValue (line 37) | public boolean hasReturnValue() {

FILE: butterknife-compiler/src/main/java/butterknife/compiler/Parameter.java
  class Parameter (line 6) | final class Parameter {
    method Parameter (line 12) | Parameter(int listenerPosition, TypeName type) {
    method getListenerPosition (line 17) | int getListenerPosition() {
    method getType (line 21) | TypeName getType() {
    method requiresCast (line 25) | public boolean requiresCast(String toType) {

FILE: butterknife-compiler/src/main/java/butterknife/compiler/ResourceBinding.java
  type ResourceBinding (line 5) | interface ResourceBinding {
    method id (line 6) | Id id();
    method requiresResources (line 9) | boolean requiresResources(int sdk);
    method render (line 11) | CodeBlock render(int sdk);

FILE: butterknife-compiler/src/main/java/butterknife/compiler/ViewBinding.java
  class ViewBinding (line 13) | final class ViewBinding {
    method ViewBinding (line 18) | ViewBinding(Id id, Map<ListenerClass, Map<ListenerMethod, Set<MethodVi...
    method getId (line 25) | public Id getId() {
    method getFieldBinding (line 29) | public @Nullable FieldViewBinding getFieldBinding() {
    method getMethodBindings (line 33) | public Map<ListenerClass, Map<ListenerMethod, Set<MethodViewBinding>>>...
    method getRequiredBindings (line 37) | public List<MemberViewBinding> getRequiredBindings() {
    method isSingleFieldBinding (line 54) | public boolean isSingleFieldBinding() {
    method requiresLocal (line 58) | public boolean requiresLocal() {
    method isBoundToRoot (line 68) | public boolean isBoundToRoot() {
    class Builder (line 72) | public static final class Builder {
      method Builder (line 79) | Builder(Id id) {
      method hasMethodBinding (line 83) | public boolean hasMethodBinding(ListenerClass listener, ListenerMeth...
      method addMethodBinding (line 88) | public void addMethodBinding(ListenerClass listener, ListenerMethod ...
      method setFieldBinding (line 105) | public void setFieldBinding(FieldViewBinding fieldBinding) {
      method build (line 112) | public ViewBinding build() {

FILE: butterknife-compiler/src/test/java/butterknife/compiler/BindingSetTest.java
  class BindingSetTest (line 10) | public class BindingSetTest {
    method humanDescriptionJoinWorks (line 11) | @Test public void humanDescriptionJoinWorks() {
    class TestViewBinding (line 26) | private static class TestViewBinding implements MemberViewBinding {
      method TestViewBinding (line 29) | private TestViewBinding(String description) {
      method getDescription (line 33) | @Override public String getDescription() {

FILE: butterknife-gradle-plugin/src/test/fixtures/suffix_parsed_properly/src/main/java/butterknife/test/ButteryActivity.java
  class ButteryActivity (line 11) | class ButteryActivity extends Activity {
    method onCreate (line 15) | @Override protected void onCreate(Bundle savedInstanceState) {

FILE: butterknife-gradle-plugin/src/test/resources/fixtures/R2.java
  class R2 (line 20) | public final class R2 {
    class anim (line 21) | public static final class anim {
    class array (line 26) | public static final class array {
    class attr (line 31) | public static final class attr {
    class bool (line 36) | public static final class bool {
    class color (line 41) | public static final class color {
    class dimen (line 46) | public static final class dimen {
    class drawable (line 51) | public static final class drawable {
    class id (line 56) | public static final class id {
    class integer (line 61) | public static final class integer {
    class layout (line 66) | public static final class layout {
    class menu (line 71) | public static final class menu {
    class plurals (line 76) | public static final class plurals {
    class string (line 81) | public static final class string {
    class style (line 86) | public static final class style {
    class styleable (line 91) | public static final class styleable {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindAnimTest.java
  class BindAnimTest (line 12) | public final class BindAnimTest {
    class Target (line 15) | static class Target {
    method anim (line 19) | @Test public void anim() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindArrayTest.java
  class BindArrayTest (line 14) | public final class BindArrayTest {
    class StringArrayTarget (line 18) | static class StringArrayTarget {
    method asStringArray (line 22) | @Test public void asStringArray() {
    class IntArrayTarget (line 33) | static class IntArrayTarget {
    method asIntArray (line 37) | @Test public void asIntArray() {
    class CharSequenceArrayTarget (line 48) | static class CharSequenceArrayTarget {
    method asCharSequenceArray (line 52) | @Test public void asCharSequenceArray() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindBitmapTest.java
  class BindBitmapTest (line 16) | public final class BindBitmapTest {
    class Target (line 20) | static class Target {
    method asBitmap (line 24) | @Test public void asBitmap() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindBoolTest.java
  class BindBoolTest (line 14) | public final class BindBoolTest {
    class Target (line 18) | static class Target {
    method asBoolean (line 22) | @Test public void asBoolean() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindColorTest.java
  class BindColorTest (line 15) | public final class BindColorTest {
    class IntTarget (line 19) | static class IntTarget {
    method asInt (line 23) | @Test public void asInt() {
    class ColorStateListTarget (line 34) | static class ColorStateListTarget {
    method asColorStateList (line 38) | @Test public void asColorStateList() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindDimenTest.java
  class BindDimenTest (line 14) | public final class BindDimenTest {
    class IntTarget (line 18) | static class IntTarget {
    method asInt (line 22) | @Test public void asInt() {
    class FloatTarget (line 33) | static class FloatTarget {
    method asFloat (line 37) | @Test public void asFloat() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindDrawableTest.java
  class BindDrawableTest (line 15) | public final class BindDrawableTest {
    class Target (line 19) | static class Target {
    method asDrawable (line 23) | @Test public void asDrawable() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindFloatTest.java
  class BindFloatTest (line 15) | public final class BindFloatTest {
    class Target (line 19) | static class Target {
    method asFloat (line 23) | @Test public void asFloat() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindFontTest.java
  class BindFontTest (line 18) | @SdkSuppress(minSdkVersion = 24) // AndroidX problems on earlier versions
    class TargetTypeface (line 23) | static class TargetTypeface {
    method typeface (line 27) | @Test public void typeface() {
    class TargetStyle (line 38) | static class TargetStyle {
    method style (line 42) | @Test public void style() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindIntTest.java
  class BindIntTest (line 14) | public final class BindIntTest {
    class Target (line 18) | static class Target {
    method asInt (line 22) | @Test public void asInt() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindStringTest.java
  class BindStringTest (line 14) | public final class BindStringTest {
    class Target (line 18) | static class Target {
    method simpleInt (line 22) | @Test public void simpleInt() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindViewTest.java
  class BindViewTest (line 11) | public final class BindViewTest {
    class TargetView (line 12) | static class TargetView {
    method view (line 16) | @Test public void view() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindViewsTest.java
  class BindViewsTest (line 12) | public final class BindViewsTest {
    class TargetViewArray (line 13) | static class TargetViewArray {
    method array (line 17) | @Test public void array() {
    class TargetViewList (line 30) | static class TargetViewList {
    method list (line 34) | @Test public void list() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnCheckedChangedTest.java
  class OnCheckedChangedTest (line 22) | @SuppressWarnings("unused") // Used reflectively / by code gen.
    class Simple (line 24) | static final class Simple {
      method click (line 27) | @OnCheckedChanged(1) void click() {
    method simple (line 32) | @UiThreadTest
    class MultipleBindings (line 49) | static final class MultipleBindings {
      method click1 (line 52) | @OnCheckedChanged(1) void click1() {
      method clicks2 (line 56) | @OnCheckedChanged(1) void clicks2() {
    method multipleBindings (line 61) | @UiThreadTest
    class Visibilities (line 80) | static final class Visibilities {
      method publicClick (line 83) | @OnCheckedChanged(1) public void publicClick() {
      method packageClick (line 87) | @OnCheckedChanged(2) void packageClick() {
      method protectedClick (line 91) | @OnCheckedChanged(3) protected void protectedClick() {
    method visibilities (line 96) | @UiThreadTest
    class MultipleIds (line 117) | static final class MultipleIds {
      method click (line 120) | @OnCheckedChanged({1, 2}) void click() {
    method multipleIds (line 125) | @UiThreadTest
    class OptionalId (line 147) | static final class OptionalId {
      method click (line 150) | @Optional @OnCheckedChanged(1) public void click() {
    method optionalIdPresent (line 155) | @UiThreadTest
    method optionalIdAbsent (line 172) | @UiThreadTest
    class ArgumentCast (line 189) | static final class ArgumentCast {
      type MyInterface (line 190) | interface MyInterface {}
      method clickTextView (line 194) | @OnCheckedChanged(1) void clickTextView(CompoundButton view) {
      method clickButton (line 198) | @OnCheckedChanged(2) void clickButton(ToggleButton view) {
      method clickMyInterface (line 202) | @OnCheckedChanged(3) void clickMyInterface(MyInterface view) {
    method argumentCast (line 207) | @UiThreadTest

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnClickTest.java
  class OnClickTest (line 22) | @SuppressWarnings("unused") // Used reflectively / by code gen.
    class Simple (line 26) | static final class Simple {
      method click (line 29) | @OnClick(1) void click() {
    method simple (line 34) | @Test public void simple() {
    class MultipleBindings (line 54) | static final class MultipleBindings {
      method click1 (line 57) | @OnClick(1) void click1() {
      method clicks2 (line 61) | @OnClick(1) void clicks2() {
    method multipleBindings (line 66) | @Test public void multipleBindings() {
    class Visibilities (line 88) | static final class Visibilities {
      method publicClick (line 91) | @OnClick(1) public void publicClick() {
      method packageClick (line 95) | @OnClick(2) void packageClick() {
      method protectedClick (line 99) | @OnClick(3) protected void protectedClick() {
    method visibilities (line 104) | @Test public void visibilities() {
    class MultipleIds (line 130) | static final class MultipleIds {
      method click (line 133) | @OnClick({1, 2}) void click() {
    method multipleIds (line 138) | @Test public void multipleIds() {
    class OptionalId (line 165) | static final class OptionalId {
      method click (line 168) | @Optional @OnClick(1) public void click() {
    method optionalIdPresent (line 173) | @Test public void optionalIdPresent() {
    method optionalIdAbsent (line 193) | @Test public void optionalIdAbsent() {
    class ArgumentCast (line 213) | static final class ArgumentCast {
      type MyInterface (line 214) | interface MyInterface {}
      method clickView (line 218) | @OnClick(1) void clickView(View view) {
      method clickTextView (line 222) | @OnClick(2) void clickTextView(TextView view) {
      method clickButton (line 226) | @OnClick(3) void clickButton(Button view) {
      method clickMyInterface (line 230) | @OnClick(4) void clickMyInterface(MyInterface view) {
    method argumentCast (line 235) | @Test public void argumentCast() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnItemClickTest.java
  class OnItemClickTest (line 23) | @SuppressWarnings("unused") // Used reflectively / by code gen.
    class TestSpinner (line 25) | static class TestSpinner extends AbsSpinner {
      method TestSpinner (line 26) | public TestSpinner(Context context) {
      method performItemClick (line 31) | void performItemClick(int position) {
    class Simple (line 43) | static final class Simple {
      method itemClick (line 46) | @OnItemClick(1) void itemClick(int position) {
    method simple (line 51) | @UiThreadTest
    class MultipleBindings (line 69) | static final class MultipleBindings {
      method itemClick1 (line 73) | @OnItemClick(1) void itemClick1(int position) {
      method itemClick2 (line 77) | @OnItemClick(1) void itemClick2(int position) {
    method multipleBindings (line 82) | @UiThreadTest
    class Visibilities (line 105) | static final class Visibilities {
      method publicItemClick (line 108) | @OnItemClick(1) public void publicItemClick(int position) {
      method packageItemClick (line 112) | @OnItemClick(2) void packageItemClick(int position) {
      method protectedItemClick (line 116) | @OnItemClick(3) protected void protectedItemClick(int position) {
    method visibilities (line 121) | @UiThreadTest
    class MultipleIds (line 142) | static final class MultipleIds {
      method itemClick (line 145) | @OnItemClick({1, 2}) void itemClick(int position) {
    method multipleIds (line 150) | @UiThreadTest
    class OptionalId (line 173) | static final class OptionalId {
      method itemClick (line 176) | @Optional @OnItemClick(1) void itemClick(int position) {
    method optionalIdPresent (line 181) | @UiThreadTest
    method optionalIdAbsent (line 198) | @UiThreadTest
    class ArgumentCast (line 215) | static final class ArgumentCast {
      type MyInterface (line 216) | interface MyInterface {}
      method itemClickAdapterView (line 220) | @OnItemClick(1) void itemClickAdapterView(AdapterView<?> view) {
      method itemClickAbsSpinner (line 224) | @OnItemClick(2) void itemClickAbsSpinner(AbsSpinner view) {
      method itemClickMyInterface (line 228) | @OnItemClick(3) void itemClickMyInterface(ArgumentCast.MyInterface v...
    method argumentCast (line 233) | @UiThreadTest

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnItemLongClickTest.java
  class OnItemLongClickTest (line 23) | @SuppressWarnings("unused") // Used reflectively / by code gen.
    class TestSpinner (line 25) | static class TestSpinner extends AbsSpinner {
      method TestSpinner (line 26) | public TestSpinner(Context context) {
      method performItemLongClick (line 31) | boolean performItemLongClick(int position) {
    class Simple (line 43) | static final class Simple {
      method itemClick (line 47) | @OnItemLongClick(1) boolean itemClick(int position) {
    method simple (line 53) | @UiThreadTest
    class ReturnVoid (line 74) | static final class ReturnVoid {
      method itemLongClick (line 77) | @OnItemLongClick(1) void itemLongClick(int position) {
    method returnVoid (line 82) | @UiThreadTest
    class Visibilities (line 99) | static final class Visibilities {
      method publicItemLongClick (line 102) | @OnItemLongClick(1) public boolean publicItemLongClick(int position) {
      method packageItemLongClick (line 107) | @OnItemLongClick(2) boolean packageItemLongClick(int position) {
      method protectedItemLongClick (line 112) | @OnItemLongClick(3) protected boolean protectedItemLongClick(int pos...
    method visibilities (line 118) | @UiThreadTest
    class MultipleIds (line 139) | static final class MultipleIds {
      method itemLongClick (line 142) | @OnItemLongClick({1, 2}) boolean itemLongClick(int position) {
    method multipleIds (line 148) | @UiThreadTest
    class OptionalId (line 171) | static final class OptionalId {
      method itemLongClick (line 174) | @Optional @OnItemLongClick(1) boolean itemLongClick(int position) {
    method optionalIdPresent (line 180) | @UiThreadTest
    method optionalIdAbsent (line 197) | @UiThreadTest
    class ArgumentCast (line 214) | static final class ArgumentCast {
      type MyInterface (line 215) | interface MyInterface {}
      method itemLongClickAdapterView (line 219) | @OnItemLongClick(1) boolean itemLongClickAdapterView(AdapterView<?> ...
      method itemLongClickAbsSpinner (line 224) | @OnItemLongClick(2) boolean itemLongClickAbsSpinner(AbsSpinner view) {
      method itemLongClickMyInterface (line 229) | @OnItemLongClick(3) boolean itemLongClickMyInterface(ArgumentCast.My...
    method argumentCast (line 235) | @UiThreadTest

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnItemSelectedTest.java
  class OnItemSelectedTest (line 25) | @SuppressWarnings("unused") // Used by code gen.
    class TestSpinner (line 27) | static class TestSpinner extends AbsSpinner {
      method TestSpinner (line 28) | public TestSpinner(Context context) {
      method performSelection (line 33) | void performSelection(int position) {
      method clearSelection (line 44) | void clearSelection() {
    method ignoreIfReflect (line 52) | @Before public void ignoreIfReflect() {
    class Simple (line 56) | static final class Simple {
      method select (line 59) | @OnItemSelected(1) void select(int position) {
      method clear (line 63) | @OnItemSelected(value = 1, callback = NOTHING_SELECTED) void clear() {
    method simple (line 68) | @UiThreadTest
    class MultipleBindings (line 91) | static final class MultipleBindings {
      method select1 (line 95) | @OnItemSelected(1) void select1(int position) {
      method select2 (line 99) | @OnItemSelected(1) void select2(int position) {
      method clear1 (line 103) | @OnItemSelected(value = 1, callback = NOTHING_SELECTED) void clear1() {
      method clear2 (line 107) | @OnItemSelected(value = 1, callback = NOTHING_SELECTED) void clear2() {
    method multipleBindings (line 112) | @UiThreadTest
    class Visibilities (line 140) | static final class Visibilities {
      method publicSelect (line 143) | @OnItemSelected(1) public void publicSelect(int position) {
      method packageSelect (line 147) | @OnItemSelected(2) void packageSelect(int position) {
      method protectedSelect (line 151) | @OnItemSelected(3) protected void protectedSelect(int position) {
      method publicClear (line 155) | @OnItemSelected(value = 1, callback = NOTHING_SELECTED) public void ...
      method packageClear (line 159) | @OnItemSelected(value = 2, callback = NOTHING_SELECTED) void package...
      method protectedClear (line 163) | @OnItemSelected(value = 3, callback = NOTHING_SELECTED) protected vo...
    method visibilities (line 168) | @UiThreadTest
    class MultipleIdPermutation (line 198) | static final class MultipleIdPermutation {
      method select (line 201) | @OnItemSelected({1, 2}) void select(int position) {
      method clear (line 205) | @OnItemSelected(value = {1, 3}, callback = NOTHING_SELECTED) void cl...
    method multipleIdPermutation (line 210) | @UiThreadTest
    class OptionalId (line 255) | static final class OptionalId {
      method select (line 258) | @Optional @OnItemSelected(1) void select(int position) {
      method clear (line 262) | @Optional @OnItemSelected(value = 1, callback = NOTHING_SELECTED) vo...
    method optionalIdPresent (line 267) | @UiThreadTest
    method optionalIdAbsent (line 290) | @UiThreadTest
    class ArgumentCast (line 313) | static final class ArgumentCast {
      type MyInterface (line 314) | interface MyInterface {}
      method selectAdapterView (line 318) | @OnItemSelected(1) void selectAdapterView(AdapterView<?> view) {
      method selectAbsSpinner (line 322) | @OnItemSelected(2) void selectAbsSpinner(AbsSpinner view) {
      method selectMyInterface (line 326) | @OnItemSelected(3) void selectMyInterface(MyInterface view) {
      method clearAdapterView (line 330) | @OnItemSelected(value = 1, callback = NOTHING_SELECTED)
      method clearAbsSpinner (line 335) | @OnItemSelected(value = 2, callback = NOTHING_SELECTED)
      method clearMyInterface (line 340) | @OnItemSelected(value = 3, callback = NOTHING_SELECTED)
    method argumentCast (line 346) | @UiThreadTest

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnLongClickTest.java
  class OnLongClickTest (line 22) | @SuppressWarnings("unused") // Used reflectively / by code gen.
    class Simple (line 24) | static final class Simple {
      method click (line 28) | @OnLongClick(1) boolean click() {
    method simple (line 34) | @UiThreadTest
    class ReturnVoid (line 55) | static final class ReturnVoid {
      method click (line 58) | @OnLongClick(1) void click() {
    method returnVoid (line 63) | @UiThreadTest
    class Visibilities (line 80) | static final class Visibilities {
      method publicClick (line 83) | @OnLongClick(1) public boolean publicClick() {
      method packageClick (line 88) | @OnLongClick(2) boolean packageClick() {
      method protectedClick (line 93) | @OnLongClick(3) protected boolean protectedClick() {
    method visibilities (line 99) | @UiThreadTest
    class MultipleIds (line 120) | static final class MultipleIds {
      method click (line 123) | @OnLongClick({1, 2}) boolean click() {
    method multipleIds (line 129) | @UiThreadTest
    class OptionalId (line 151) | static final class OptionalId {
      method click (line 154) | @Optional @OnLongClick(1) public boolean click() {
    method optionalIdPresent (line 160) | @UiThreadTest
    method optionalIdAbsent (line 177) | @UiThreadTest
    class ArgumentCast (line 194) | static final class ArgumentCast {
      type MyInterface (line 195) | interface MyInterface {}
      method clickView (line 199) | @OnLongClick(1) boolean clickView(View view) {
      method clickTextView (line 204) | @OnLongClick(2) boolean clickTextView(TextView view) {
      method clickButton (line 209) | @OnLongClick(3) boolean clickButton(Button view) {
      method clickMyInterface (line 214) | @OnLongClick(4) boolean clickMyInterface(MyInterface view) {
    method argumentCast (line 220) | @UiThreadTest

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnTouchTest.java
  class OnTouchTest (line 23) | @SuppressWarnings("unused") // Used reflectively / by code gen.
    class Simple (line 25) | static final class Simple {
      method touch (line 29) | @OnTouch(1) boolean touch() {
    method simple (line 35) | @UiThreadTest
    class Arguments (line 56) | static final class Arguments {
      method touch (line 59) | @OnTouch(1) boolean touch(View v) {
      method touch (line 64) | @OnTouch(2) boolean touch(View v, MotionEvent event) {
    method arguments (line 70) | @UiThreadTest
    class ReturnVoid (line 91) | static final class ReturnVoid {
      method touch (line 94) | @OnTouch(1) void touch() {
    method returnVoid (line 99) | @UiThreadTest
    class Visibilities (line 116) | static final class Visibilities {
      method publicTouch (line 119) | @OnTouch(1) public boolean publicTouch() {
      method packageTouch (line 124) | @OnTouch(2) boolean packageTouch() {
      method protectedTouch (line 129) | @OnTouch(3) protected boolean protectedTouch() {
    method visibilities (line 135) | @UiThreadTest
    class MultipleIds (line 156) | static final class MultipleIds {
      method touch (line 159) | @OnTouch({1, 2}) boolean touch() {
    method multipleIds (line 165) | @UiThreadTest
    class OptionalId (line 187) | static final class OptionalId {
      method touch (line 190) | @Optional @OnTouch(1) public boolean touch() {
    method optionalIdPresent (line 196) | @UiThreadTest
    method optionalIdAbsent (line 213) | @UiThreadTest
    class ArgumentCast (line 230) | static final class ArgumentCast {
      type MyInterface (line 231) | interface MyInterface {}
      method touchView (line 235) | @OnTouch(1) boolean touchView(View view) {
      method touchTextView (line 240) | @OnTouch(2) boolean touchTextView(TextView view) {
      method touchButton (line 245) | @OnTouch(3) boolean touchButton(Button view) {
      method touchMyInterface (line 250) | @OnTouch(4) boolean touchMyInterface(ArgumentCast.MyInterface view) {
    method argumentCast (line 256) | @UiThreadTest
    method performTouch (line 295) | private static boolean performTouch(View view) {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/ViewTree.java
  class ViewTree (line 10) | final class ViewTree {
    method create (line 11) | static View create(int... ids) {
    method create (line 15) | static View create(Class<? extends View> cls, int... ids) {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/library/SimpleActivityTest.java
  class SimpleActivityTest (line 12) | public final class SimpleActivityTest {
    method verifyContentViewBinding (line 16) | @Test public void verifyContentViewBinding() {
    method verifySimpleActivityBound (line 25) | protected static void verifySimpleActivityBound(SimpleActivity activit...
    method verifySimpleActivityUnbound (line 33) | protected static void verifySimpleActivityUnbound(SimpleActivity activ...

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/library/SimpleAdapterTest.java
  class SimpleAdapterTest (line 12) | public class SimpleAdapterTest {
    method verifyViewHolderViews (line 13) | @Test public void verifyViewHolderViews() {

FILE: butterknife-integration-test/src/androidTest/java/com/example/butterknife/unbinder/UnbinderTest.java
  class UnbinderTest (line 14) | public final class UnbinderTest {
    method verifyContentViewBinding (line 17) | @Test public void verifyContentViewBinding() {
    method verifyHBound (line 39) | private void verifyHBound(H h) {
    method verifyHUnbound (line 45) | private void verifyHUnbound(H h) {

FILE: butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindAnimFailureTest.java
  class BindAnimFailureTest (line 11) | public final class BindAnimFailureTest {
    class Target (line 14) | static class Target {
    method typeMustBeAnimation (line 18) | @Test public void typeMustBeAnimation() {

FILE: butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindArrayFailureTest.java
  class BindArrayFailureTest (line 11) | public final class BindArrayFailureTest {
    class Target (line 14) | static class Target {
    method typeMustBeSupported (line 18) | @Test public void typeMustBeSupported() {

FILE: butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindBitmapFailureTest.java
  class BindBitmapFailureTest (line 11) | public final class BindBitmapFailureTest {
    class Target (line 14) | static class Target {
    method typeMustBeBitmap (line 18) | @Test public void typeMustBeBitmap() {

FILE: butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindBoolFailureTest.java
  class BindBoolFailureTest (line 11) | public final class BindBoolFailureTest {
    class Target (line 14) | static class Target {
    method typeMustBeBool (line 18) | @Test public void typeMustBeBool() {

FILE: butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindColorFailureTest.java
  class BindColorFailureTest (line 11) | public final class BindColorFailureTest {
    class Target (line 14) | static class Target {
    method typeMustBeIntOrColorStateList (line 18) | @Test public void typeMustBeIntOrColorStateList() {

FILE: butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindDimenFailureTest.java
  class BindDimenFailureTest (line 11) | public final class BindDimenFailureTest {
    class Target (line 14) | static class Target {
    method typeMustBeIntOrFloat (line 18) | @Test public void typeMustBeIntOrFloat() {

FILE: butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindDrawableFailureTest.java
  class BindDrawableFailureTest (line 11) | public final class BindDrawableFailureTest {
    class Target (line 14) | static class Target {
    method typeMustBeDrawable (line 18) | @Test public void typeMustBeDrawable() {

FILE: butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindFloatFailureTest.java
  class BindFloatFailureTest (line 11) | public final class BindFloatFailureTest {
    class Target (line 14) | static class Target {
    method typeMustBeFloat (line 18) | @Test public void typeMustBeFloat() {

FILE: butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindFontFailureTest.java
  class BindFontFailureTest (line 14) | public final class BindFontFailureTest {
    class TargetType (line 17) | static class TargetType {
    method typeMustBeTypeface (line 21) | @Test public void typeMustBeTypeface() {
    class TargetStyle (line 34) | static class TargetStyle {
    method styleMustBeValid (line 38) | @SdkSuppress(minSdkVersion = 24) // AndroidX problems on earlier versions

FILE: butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindIntFailureTest.java
  class BindIntFailureTest (line 11) | public final class BindIntFailureTest {
    class Target (line 14) | static class Target {
    method typeMustBeInt (line 18) | @Test public void typeMustBeInt() {

FILE: butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindStringFailureTest.java
  class BindStringFailureTest (line 11) | public final class BindStringFailureTest {
    class Target (line 14) | static class Target {
    method typeMustBeString (line 18) | @Test public void typeMustBeString() {

FILE: butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindViewFailureTest.java
  class BindViewFailureTest (line 11) | public final class BindViewFailureTest {
    class NotView (line 14) | static class NotView {
    method failsIfNotView (line 18) | @Test public void failsIfNotView() {

FILE: butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindViewsFailureTest.java
  class BindViewsFailureTest (line 13) | public final class BindViewsFailureTest {
    class NoIds (line 16) | static class NoIds {
    method failsIfNoIds (line 20) | @Test public void failsIfNoIds() {
    class NoGenericType (line 33) | static class NoGenericType {
    method failsIfNoGenericType (line 37) | @Test public void failsIfNoGenericType() {
    class BadCollection (line 50) | static class BadCollection {
    method failsIfUnsupportedCollection (line 54) | @Test public void failsIfUnsupportedCollection() {
    class ListNotView (line 67) | static class ListNotView {
    method failsIfGenericNotView (line 71) | @Test public void failsIfGenericNotView() {
    class ArrayNotView (line 84) | static class ArrayNotView {
    method failsIfArrayNotView (line 88) | @Test public void failsIfArrayNotView() {

FILE: butterknife-integration-test/src/main/java/com/example/butterknife/SimpleApp.java
  class SimpleApp (line 6) | public class SimpleApp extends Application {
    method onCreate (line 7) | @Override public void onCreate() {

FILE: butterknife-integration-test/src/main/java/com/example/butterknife/library/SimpleActivity.java
  class SimpleActivity (line 26) | public class SimpleActivity extends Activity {
    method sayHello (line 49) | @OnClick(R.id.hello) void sayHello() {
    method sayGetOffMe (line 54) | @OnLongClick(R.id.hello) boolean sayGetOffMe() {
    method onItemClick (line 59) | @OnItemClick(R.id.list_of_things) void onItemClick(int position) {
    method onCreate (line 63) | @Override protected void onCreate(Bundle savedInstanceState) {

FILE: butterknife-integration-test/src/main/java/com/example/butterknife/library/SimpleAdapter.java
  class SimpleAdapter (line 15) | public class SimpleAdapter extends BaseAdapter {
    method SimpleAdapter (line 20) | public SimpleAdapter(Context context) {
    method getCount (line 24) | @Override public int getCount() {
    method getItem (line 28) | @Override public String getItem(int position) {
    method getItemId (line 32) | @Override public long getItemId(int position) {
    method getView (line 36) | @Override public View getView(int position, View view, ViewGroup paren...
    class ViewHolder (line 55) | static final class ViewHolder {
      method ViewHolder (line 60) | ViewHolder(View view) {

FILE: butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/A.java
  class A (line 8) | public class A {
    method A (line 12) | public A(View view) {

FILE: butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/B.java
  class B (line 8) | public class B extends A {
    method B (line 12) | public B(View view) {

FILE: butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/C.java
  class C (line 9) | public class C extends B {
    method C (line 14) | public C(View view) {

FILE: butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/D.java
  class D (line 8) | public class D extends C {
    method D (line 12) | public D(View view) {

FILE: butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/E.java
  class E (line 8) | public class E extends C {
    method E (line 12) | public E(View view) {

FILE: butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/F.java
  class F (line 8) | public final class F extends D {
    method F (line 12) | public F(View view) {

FILE: butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/G.java
  class G (line 11) | public class G extends E {
    method G (line 16) | public G(View view) {
    method onClick (line 21) | @OnClick(android.R.id.content) public void onClick() {

FILE: butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/H.java
  class H (line 9) | public class H extends G {
    method H (line 14) | public H(View view) {

FILE: butterknife-lint/src/main/java/butterknife/lint/InvalidR2UsageDetector.java
  class InvalidR2UsageDetector (line 28) | public class InvalidR2UsageDetector extends Detector implements Detector...
    method getApplicableUastTypes (line 42) | @Override public List<Class<? extends UElement>> getApplicableUastType...
    method createUastHandler (line 46) | @Override public UElementHandler createUastHandler(final JavaContext c...
    class R2UsageVisitor (line 54) | private static class R2UsageVisitor extends AbstractUastVisitor {
      method R2UsageVisitor (line 57) | R2UsageVisitor(JavaContext context) {
      method visitAnnotation (line 61) | @Override public boolean visitAnnotation(UAnnotation annotation) {
      method visitQualifiedReferenceExpression (line 66) | @Override public boolean visitQualifiedReferenceExpression(UQualifie...
      method visitSimpleNameReferenceExpression (line 71) | @Override
      method detectR2 (line 77) | private static void detectR2(JavaContext context, UElement node) {
      method isR2Expression (line 95) | private static boolean isR2Expression(UElement node) {
      method endsWithAny (line 107) | private static boolean endsWithAny(String text, Set<String> possible...

FILE: butterknife-lint/src/main/java/butterknife/lint/LintRegistry.java
  class LintRegistry (line 12) | public class LintRegistry extends IssueRegistry {
    method getIssues (line 14) | @Override public List<Issue> getIssues() {
    method getApi (line 18) | @Override public int getApi() {

FILE: butterknife-lint/src/test/java/butterknife/lint/InvalidR2UsageDetectorTest.java
  class InvalidR2UsageDetectorTest (line 9) | public final class InvalidR2UsageDetectorTest {
    method noR2Usage (line 64) | @Test public void noR2Usage() {
    method usesR2InAnnotations (line 75) | @Test public void usesR2InAnnotations() {
    method usesR2OutsideAnnotations (line 93) | @Test public void usesR2OutsideAnnotations() {
    method usesR2WithSuppression (line 116) | @Test public void usesR2WithSuppression() {

FILE: butterknife-lint/src/test/java/butterknife/lint/LintRegistryTest.java
  class LintRegistryTest (line 7) | public final class LintRegistryTest {
    method issues (line 8) | @Test public void issues() {

FILE: butterknife-reflect/src/main/java/butterknife/ButterKnife.java
  class ButterKnife (line 49) | public final class ButterKnife {
    method ButterKnife (line 50) | private ButterKnife() {
    method setDebug (line 58) | public static void setDebug(boolean debug) {
    method bind (line 68) | @NonNull @UiThread
    method bind (line 80) | @NonNull @UiThread
    method bind (line 91) | @NonNull @UiThread
    method bind (line 104) | @NonNull @UiThread
    method bind (line 117) | @NonNull @UiThread
    method bind (line 130) | @NonNull @UiThread
    method parseBindView (line 240) | private static @Nullable Unbinder parseBindView(Object target, Field f...
    method parseBindViews (line 265) | private static @Nullable Unbinder parseBindViews(Object target, Field ...
    method parseBindAnim (line 336) | private static @Nullable Unbinder parseBindAnim(Object target, Field f...
    method parseBindArray (line 362) | private static @Nullable Unbinder parseBindArray(Object target, Field ...
    method parseBindBitmap (line 405) | private static @Nullable Unbinder parseBindBitmap(Object target, Field...
    method parseBindBool (line 431) | private static @Nullable Unbinder parseBindBool(Object target, Field f...
    method parseBindColor (line 457) | private static @Nullable Unbinder parseBindColor(Object target, Field ...
    method parseBindDimen (line 485) | private static @Nullable Unbinder parseBindDimen(Object target, Field ...
    method parseBindDrawable (line 513) | private static @Nullable Unbinder parseBindDrawable(Object target, Fie...
    method parseBindFloat (line 542) | private static @Nullable Unbinder parseBindFloat(Object target, Field ...
    method parseBindFont (line 568) | private static @Nullable Unbinder parseBindFont(Object target, Field f...
    method parseBindInt (line 612) | private static @Nullable Unbinder parseBindInt(Object target, Field fi...
    method parseBindString (line 638) | private static @Nullable Unbinder parseBindString(Object target, Field...
    method parseOnCheckedChanged (line 664) | private static @Nullable Unbinder parseOnCheckedChanged(final Object t...
    method parseOnClick (line 686) | private static @Nullable Unbinder parseOnClick(final Object target, fi...
    method parseOnEditorAction (line 706) | private static @Nullable Unbinder parseOnEditorAction(final Object tar...
    method parseOnFocusChange (line 732) | private static @Nullable Unbinder parseOnFocusChange(final Object targ...
    method parseOnItemClick (line 752) | private static @Nullable Unbinder parseOnItemClick(final Object target...
    method parseOnItemLongClick (line 774) | private static @Nullable Unbinder parseOnItemLongClick(final Object ta...
    method parseOnLongClick (line 801) | private static @Nullable Unbinder parseOnLongClick(final Object target...
    method parseOnPageChange (line 826) | private static @Nullable Unbinder parseOnPageChange(final Object targe...
    method parseOnTextChanged (line 881) | private static @Nullable Unbinder parseOnTextChanged(Object target, Me...
    method parseOnTouch (line 932) | private static @Nullable Unbinder parseOnTouch(final Object target, fi...
    method findViews (line 957) | @SuppressWarnings("unchecked")
    method validateMember (line 979) | private static <T extends AccessibleObject & Member> void validateMemb...
    method validateReturnType (line 993) | private static boolean validateReturnType(Method method, Class<?> expe...
    method isRequired (line 1012) | private static boolean isRequired(Method method) {
    method createArgumentTransformer (line 1016) | private static ArgumentTransformer createArgumentTransformer(Method me...
    method trySet (line 1118) | static void trySet(Field field, Object target, @Nullable Object value) {
    method tryInvoke (line 1126) | private static Object tryInvoke(Method method, Object target, Object.....
    type ArgumentTransformer (line 1184) | private interface ArgumentTransformer {
      method transform (line 1188) | @Override public Object[] transform(Object... arguments) {
      method toString (line 1192) | @Override public String toString() {
      method transform (line 1197) | @Override public Object[] transform(Object... arguments) {
      method toString (line 1201) | @Override public String toString() {
      method transform (line 1206) | Object[] transform(Object... arguments);

FILE: butterknife-reflect/src/main/java/butterknife/CompositeUnbinder.java
  class CompositeUnbinder (line 7) | final class CompositeUnbinder implements Unbinder {
    method CompositeUnbinder (line 10) | CompositeUnbinder(@NonNull List<Unbinder> unbinders) {
    method unbind (line 14) | @Override public void unbind() {

FILE: butterknife-reflect/src/main/java/butterknife/EmptyTextWatcher.java
  class EmptyTextWatcher (line 6) | class EmptyTextWatcher implements TextWatcher {
    method beforeTextChanged (line 7) | @Override public void beforeTextChanged(CharSequence s, int start, int...
    method onTextChanged (line 10) | @Override public void onTextChanged(CharSequence s, int start, int bef...
    method afterTextChanged (line 13) | @Override public void afterTextChanged(Editable s) {

FILE: butterknife-reflect/src/main/java/butterknife/FieldUnbinder.java
  class FieldUnbinder (line 7) | final class FieldUnbinder implements Unbinder {
    method FieldUnbinder (line 11) | FieldUnbinder(Object target, Field field) {
    method unbind (line 16) | @Override public void unbind() {

FILE: butterknife-reflect/src/main/java/butterknife/ListenerUnbinder.java
  class ListenerUnbinder (line 6) | final class ListenerUnbinder<V extends View, L> implements Unbinder {
    method ListenerUnbinder (line 11) | ListenerUnbinder(List<V> targets, Setter<V, L> setter) {
    method ListenerUnbinder (line 17) | ListenerUnbinder(List<V> targets, Setter<V, L> setter, L listener) {
    method unbind (line 23) | @Override public void unbind() {

FILE: butterknife-runtime/src/androidTest/java/butterknife/ViewCollectionsTest.java
  class ViewCollectionsTest (line 13) | public class ViewCollectionsTest {
    method get (line 16) | @Override public Boolean get(View view) {
    method set (line 20) | @Override public void set(View view, Boolean enabled) {
    method propertyAppliedToView (line 31) | @Test public void propertyAppliedToView() {
    method propertyAppliedToEveryViewInList (line 39) | @Test public void propertyAppliedToEveryViewInList() {
    method propertyAppliedToEveryViewInArray (line 55) | @Test public void propertyAppliedToEveryViewInArray() {
    method actionAppliedToView (line 71) | @Test public void actionAppliedToView() {
    method actionsAppliedToView (line 80) | @Test public void actionsAppliedToView() {
    method actionAppliedToEveryViewInList (line 90) | @Test public void actionAppliedToEveryViewInList() {
    method actionAppliedToEveryViewInArray (line 106) | @Test public void actionAppliedToEveryViewInArray() {
    method actionsAppliedToEveryViewInList (line 122) | @Test public void actionsAppliedToEveryViewInList() {
    method actionsAppliedToEveryViewInArray (line 144) | @Test public void actionsAppliedToEveryViewInArray() {
    method setterAppliedToView (line 166) | @Test public void setterAppliedToView() {
    method setterAppliedToEveryViewInList (line 175) | @Test public void setterAppliedToEveryViewInList() {
    method setterAppliedToEveryViewInArray (line 191) | @Test public void setterAppliedToEveryViewInArray() {

FILE: butterknife-runtime/src/androidTest/java/butterknife/internal/UtilsTest.java
  class UtilsTest (line 11) | public final class UtilsTest {
    method finderThrowsNiceError (line 12) | @Test public void finderThrowsNiceError() {
    method finderThrowsLessNiceErrorInEditMode (line 25) | @Test public void finderThrowsLessNiceErrorInEditMode() {
    class EditModeView (line 38) | static final class EditModeView extends View {
      method EditModeView (line 39) | EditModeView(Context context) {
      method isInEditMode (line 43) | @Override public boolean isInEditMode() {

FILE: butterknife-runtime/src/main/java/butterknife/Action.java
  type Action (line 8) | public interface Action<T extends View> {
    method apply (line 10) | @UiThread void apply(@NonNull T view, int index);

FILE: butterknife-runtime/src/main/java/butterknife/Setter.java
  type Setter (line 9) | public interface Setter<T extends View, V> {
    method set (line 11) | @UiThread void set(@NonNull T view, @Nullable V value, int index);

FILE: butterknife-runtime/src/main/java/butterknife/Unbinder.java
  type Unbinder (line 6) | public interface Unbinder {
    method unbind (line 7) | @UiThread void unbind();

FILE: butterknife-runtime/src/main/java/butterknife/ViewCollections.java
  class ViewCollections (line 11) | public final class ViewCollections {
    method run (line 13) | @UiThread
    method run (line 24) | @UiThread
    method run (line 35) | @UiThread
    method run (line 44) | @UiThread
    method run (line 52) | @UiThread
    method run (line 61) | @UiThread
    method set (line 67) | @UiThread
    method set (line 76) | @UiThread
    method set (line 85) | @UiThread
    method set (line 94) | @UiThread
    method set (line 106) | @UiThread
    method set (line 116) | @UiThread
    method ViewCollections (line 122) | private ViewCollections() {

FILE: butterknife-runtime/src/main/java/butterknife/internal/DebouncingOnClickListener.java
  class DebouncingOnClickListener (line 11) | public abstract class DebouncingOnClickListener implements View.OnClickL...
    method onClick (line 17) | @Override public final void onClick(View v) {
    method doClick (line 30) | public abstract void doClick(View v);

FILE: butterknife-runtime/src/main/java/butterknife/internal/ImmutableList.java
  class ImmutableList (line 10) | final class ImmutableList<T> extends AbstractList<T> implements RandomAc...
    method ImmutableList (line 13) | ImmutableList(T[] views) {
    method get (line 17) | @Override public T get(int index) {
    method size (line 21) | @Override public int size() {
    method contains (line 25) | @Override public boolean contains(Object o) {

FILE: butterknife-runtime/src/main/java/butterknife/internal/Utils.java
  class Utils (line 18) | @SuppressWarnings("WeakerAccess") // Used by generated code.
    method getTintedDrawable (line 22) | @UiThread // Implicit synchronization for use of shared resource VALUE.
    method getFloat (line 41) | @UiThread // Implicit synchronization for use of shared resource VALUE.
    method arrayFilteringNull (line 52) | @SafeVarargs
    method listFilteringNull (line 67) | @SafeVarargs
    method findOptionalViewAsType (line 72) | public static <T> T findOptionalViewAsType(View source, @IdRes int id,...
    method findRequiredView (line 78) | public static View findRequiredView(View source, @IdRes int id, String...
    method findRequiredViewAsType (line 94) | public static <T> T findRequiredViewAsType(View source, @IdRes int id,...
    method castView (line 100) | public static <T> T castView(View view, @IdRes int id, String who, Cla...
    method castParam (line 115) | public static <T> T castParam(Object value, String from, int fromPos, ...
    method getResourceEntryName (line 132) | private static String getResourceEntryName(View view, @IdRes int id) {
    method Utils (line 139) | private Utils() {

FILE: butterknife-runtime/src/test/java/butterknife/BindAnimTest.java
  class BindAnimTest (line 14) | public class BindAnimTest {
    method typeMustBeAnimation (line 15) | @Test public void typeMustBeAnimation() {

FILE: butterknife-runtime/src/test/java/butterknife/BindArrayTest.java
  class BindArrayTest (line 11) | public final class BindArrayTest {
    method typedArray (line 12) | @Test public void typedArray() throws Exception {
    method typeMustBeSupported (line 65) | @Test public void typeMustBeSupported() {

FILE: butterknife-runtime/src/test/java/butterknife/BindBitmapTest.java
  class BindBitmapTest (line 11) | public final class BindBitmapTest {
    method typeMustBeBitmap (line 12) | @Test public void typeMustBeBitmap() {

FILE: butterknife-runtime/src/test/java/butterknife/BindBoolTest.java
  class BindBoolTest (line 11) | public final class BindBoolTest {
    method typeMustBeBoolean (line 12) | @Test public void typeMustBeBoolean() {

FILE: butterknife-runtime/src/test/java/butterknife/BindColorTest.java
  class BindColorTest (line 11) | public final class BindColorTest {
    method simpleIntSdk23 (line 12) | @Test public void simpleIntSdk23() {
    method simpleColorStateListSdk23 (line 62) | @Test public void simpleColorStateListSdk23() {
    method typeMustBeIntOrColorStateList (line 113) | @Test public void typeMustBeIntOrColorStateList() {

FILE: butterknife-runtime/src/test/java/butterknife/BindDimenTest.java
  class BindDimenTest (line 11) | public final class BindDimenTest {
    method typeMustBeIntOrFloat (line 12) | @Test public void typeMustBeIntOrFloat() {

FILE: butterknife-runtime/src/test/java/butterknife/BindDrawableTest.java
  class BindDrawableTest (line 11) | public final class BindDrawableTest {
    method simpleSdk21 (line 12) | @Test public void simpleSdk21() {
    method withTint (line 63) | @Test public void withTint() {
    method typeMustBeDrawable (line 115) | @Test public void typeMustBeDrawable() {

FILE: butterknife-runtime/src/test/java/butterknife/BindFloatTest.java
  class BindFloatTest (line 11) | public final class BindFloatTest {
    method typeMustBeFloat (line 12) | @Test public void typeMustBeFloat() {

FILE: butterknife-runtime/src/test/java/butterknife/BindFontTest.java
  class BindFontTest (line 11) | public class BindFontTest {
    method simpleIntSdk26 (line 12) | @Test public void simpleIntSdk26() {
    method styleSdk26 (line 65) | @Test public void styleSdk26() {
    method typeMustBeTypeface (line 119) | @Test public void typeMustBeTypeface() {
    method styleMustBeValid (line 135) | @Test public void styleMustBeValid() {

FILE: butterknife-runtime/src/test/java/butterknife/BindIntTest.java
  class BindIntTest (line 11) | public final class BindIntTest {
    method typeMustBeInt (line 12) | @Test public void typeMustBeInt() {

FILE: butterknife-runtime/src/test/java/butterknife/BindStringTest.java
  class BindStringTest (line 11) | public final class BindStringTest {
    method typeMustBeString (line 12) | @Test public void typeMustBeString() {

FILE: butterknife-runtime/src/test/java/butterknife/BindViewTest.java
  class BindViewTest (line 15) | public class BindViewTest {
    method bindingViewNonDebuggable (line 16) | @Test public void bindingViewNonDebuggable() {
    method bindingViewSubclassNonDebuggable (line 60) | @Test public void bindingViewSubclassNonDebuggable() {
    method bindingGeneratedView (line 105) | @Test public void bindingGeneratedView() {
    method bindingViewFinalClass (line 140) | @Test public void bindingViewFinalClass() {
    method bindingViewFinalClassWithBaseClass (line 183) | @Test public void bindingViewFinalClassWithBaseClass() {
    method bindingViewUppercasePackageName (line 262) | @Test public void bindingViewUppercasePackageName() {
    method bindingInterface (line 307) | @Test public void bindingInterface() throws Exception {
    method genericType (line 353) | @Test public void genericType() {
    method oneFindPerId (line 402) | @Test public void oneFindPerId() {
    method oneFindPerIdWithCast (line 462) | @Test public void oneFindPerIdWithCast() {
    method fieldVisibility (line 523) | @Test public void fieldVisibility() {
    method nullable (line 541) | @Test public void nullable() {
    method superclass (line 586) | @Test public void superclass() {
    method genericSuperclass (line 672) | @Test public void genericSuperclass() {
    method failsInJavaPackage (line 760) | @Test public void failsInJavaPackage() {
    method failsInAndroidPackage (line 778) | @Test public void failsInAndroidPackage() {
    method failsIfInPrivateClass (line 796) | @Test public void failsIfInPrivateClass() {
    method failsIfNotView (line 816) | @Test public void failsIfNotView() {
    method failsIfInInterface (line 833) | @Test public void failsIfInInterface() {
    method failsIfPrivate (line 851) | @Test public void failsIfPrivate() {
    method failsIfStatic (line 868) | @Test public void failsIfStatic() {
    method duplicateBindingFails (line 885) | @Test public void duplicateBindingFails() throws Exception {
    method failsOptionalRootViewBinding (line 904) | @Test public void failsOptionalRootViewBinding() throws Exception {

FILE: butterknife-runtime/src/test/java/butterknife/BindViewsTest.java
  class BindViewsTest (line 15) | public class BindViewsTest {
    method bindingArrayWithGenerics (line 16) | @Test public void bindingArrayWithGenerics() {
    method bindingArrayWithCast (line 66) | @Test public void bindingArrayWithCast() {
    method bindingArrayNonDebuggable (line 115) | @Test public void bindingArrayNonDebuggable() {
    method bindingArrayWithCastNonDebuggable (line 163) | @Test public void bindingArrayWithCastNonDebuggable() {
    method bindingGeneratedView (line 212) | @Test public void bindingGeneratedView() {
    method bindingListOfInterface (line 248) | @Test public void bindingListOfInterface() {
    method bindingListWithGenerics (line 297) | @Test public void bindingListWithGenerics() {
    method nullableList (line 348) | @Test public void nullableList() {
    method failsIfNoIds (line 398) | @Test public void failsIfNoIds() {
    method failsIfNoGenericType (line 416) | @Test public void failsIfNoGenericType() {
    method failsIfUnsupportedCollection (line 433) | @Test public void failsIfUnsupportedCollection() {
    method failsIfGenericNotView (line 451) | @Test public void failsIfGenericNotView() {
    method failsIfArrayNotView (line 469) | @Test public void failsIfArrayNotView() {
    method failsIfContainsDuplicateIds (line 486) | @Test public void failsIfContainsDuplicateIds() throws Exception {
    method bindingArrayWithRScanner (line 504) | @Test public void bindingArrayWithRScanner() {
    method bindingArrayWithMixedRAndLiteral (line 552) | @Test public void bindingArrayWithMixedRAndLiteral() {

FILE: butterknife-runtime/src/test/java/butterknife/ClasspathParentBindTest.java
  class ClasspathParentBindTest (line 30) | public class ClasspathParentBindTest {
    method parentBindingInClasspath (line 34) | @Test
    method indirectViewRequiredInConstructor (line 102) | @Test
    method viewNotRequiredInConstructor (line 178) | @Test
    method compileSources (line 240) | private void compileSources(File classesOut, File sourcesOut, JavaFile...

FILE: butterknife-runtime/src/test/java/butterknife/ExtendActivityTest.java
  class ExtendActivityTest (line 11) | public class ExtendActivityTest {
    method onlyResources (line 12) | @Test public void onlyResources() {
    method views (line 70) | @Test public void views() {

FILE: butterknife-runtime/src/test/java/butterknife/ExtendDialogTest.java
  class ExtendDialogTest (line 11) | public class ExtendDialogTest {
    method onlyResources (line 12) | @Test public void onlyResources() {
    method views (line 73) | @Test public void views() {

FILE: butterknife-runtime/src/test/java/butterknife/ExtendViewTest.java
  class ExtendViewTest (line 11) | public class ExtendViewTest {
    method onlyResources (line 12) | @Test public void onlyResources() {
    method views (line 73) | @Test public void views() {

FILE: butterknife-runtime/src/test/java/butterknife/OnClickTest.java
  class OnClickTest (line 11) | public class OnClickTest {
    method findOnlyCalledOnce (line 12) | @Test public void findOnlyCalledOnce() {
    method methodCastsArgumentNonDebuggable (line 72) | @Test public void methodCastsArgumentNonDebuggable() {
    method optionalAndRequiredSkipsNullCheck (line 179) | @Test public void optionalAndRequiredSkipsNullCheck() {
    method failsInJavaPackage (line 240) | @Test public void failsInJavaPackage() {
    method failsInAndroidPackage (line 257) | @Test public void failsInAndroidPackage() {
    method failsIfHasReturnType (line 274) | @Test public void failsIfHasReturnType() {
    method failsIfPrivateMethod (line 292) | @Test public void failsIfPrivateMethod() {
    method failsIfStatic (line 310) | @Test public void failsIfStatic() {
    method failsIfParameterNotView (line 328) | @Test public void failsIfParameterNotView() {
    method failsIfMoreThanOneParameter (line 356) | @Test public void failsIfMoreThanOneParameter() {
    method failsIfInInterface (line 376) | @Test public void failsIfInInterface() {
    method failsIfHasDuplicateIds (line 394) | @Test public void failsIfHasDuplicateIds() {

FILE: butterknife-runtime/src/test/java/butterknife/OnEditorActionTest.java
  class OnEditorActionTest (line 11) | public class OnEditorActionTest {
    method editorAction (line 12) | @Test public void editorAction() {
    method defaultReturnValue (line 67) | @Test public void defaultReturnValue() {

FILE: butterknife-runtime/src/test/java/butterknife/OnFocusChangeTest.java
  class OnFocusChangeTest (line 11) | public class OnFocusChangeTest {
    method focusChange (line 12) | @Test public void focusChange() {

FILE: butterknife-runtime/src/test/java/butterknife/OnItemClickTest.java
  class OnItemClickTest (line 12) | public class OnItemClickTest {
    method onItemClickBinding (line 13) | @Test public void onItemClickBinding() {
    method onItemClickBindingWithParameters (line 67) | @Test public void onItemClickBindingWithParameters() {
    method onItemClickBindingWithParameterSubset (line 128) | @Test public void onItemClickBindingWithParameterSubset() {
    method onItemClickBindingWithParameterSubsetAndGenerics (line 188) | @Test public void onItemClickBindingWithParameterSubsetAndGenerics() {
    method onClickRootViewBinding (line 251) | @Test public void onClickRootViewBinding() {
    method onClickRootViewAnyTypeBinding (line 311) | @Test public void onClickRootViewAnyTypeBinding() {
    method failsWithInvalidId (line 362) | @Test public void failsWithInvalidId() {
    method failsWithInvalidParameterConfiguration (line 378) | @Test public void failsWithInvalidParameterConfiguration() {

FILE: butterknife-runtime/src/test/java/butterknife/OnItemLongClickTest.java
  class OnItemLongClickTest (line 11) | public class OnItemLongClickTest {
    method itemLongClick (line 12) | @Test public void itemLongClick() {
    method defaultReturnValue (line 66) | @Test public void defaultReturnValue() {

FILE: butterknife-runtime/src/test/java/butterknife/OnItemSelectedTest.java
  class OnItemSelectedTest (line 12) | public class OnItemSelectedTest {
    method defaultMethod (line 13) | @Test public void defaultMethod() {
    method nonDefaultMethod (line 70) | @Test public void nonDefaultMethod() {
    method allMethods (line 129) | @Test public void allMethods() {
    method multipleBindingPermutation (line 191) | @Test public void multipleBindingPermutation() {

FILE: butterknife-runtime/src/test/java/butterknife/OnPageChangeTest.java
  class OnPageChangeTest (line 13) | public class OnPageChangeTest {
    method pageChange (line 14) | @Test public void pageChange() {

FILE: butterknife-runtime/src/test/java/butterknife/OnTextChangedTest.java
  class OnTextChangedTest (line 11) | public class OnTextChangedTest {
    method textChanged (line 12) | @Test public void textChanged() {
    method textChangedWithParameter (line 78) | @Test public void textChangedWithParameter() {
    method textChangedWithParameters (line 144) | @Test public void textChangedWithParameters() {
    method textChangedWithWrongParameter (line 210) | @Test public void textChangedWithWrongParameter() {

FILE: butterknife-runtime/src/test/java/butterknife/OnTouchTest.java
  class OnTouchTest (line 11) | public class OnTouchTest {
    method touch (line 12) | @Test public void touch() {
    method defaultReturnValue (line 68) | @Test public void defaultReturnValue() {
    method failsMultipleListenersWithReturnValue (line 125) | @Test public void failsMultipleListenersWithReturnValue() {

FILE: butterknife-runtime/src/test/java/butterknife/RClassTest.java
  class RClassTest (line 12) | public class RClassTest {
    method library (line 80) | @Test public void library() {
    method issue779 (line 130) | @Test public void issue779() {
    method app (line 327) | @Test public void app() {
    method compiledRClass (line 377) | @Test public void compiledRClass() {

FILE: butterknife-runtime/src/test/java/butterknife/TestGeneratingProcessor.java
  class TestGeneratingProcessor (line 22) | public class TestGeneratingProcessor extends AbstractProcessor {
    method TestGeneratingProcessor (line 35) | TestGeneratingProcessor(String generatedClassName, String... source) {
    method getSupportedAnnotationTypes (line 40) | @Override
    method process (line 45) | @Override

FILE: butterknife-runtime/src/test/java/butterknife/TestStubs.java
  class TestStubs (line 6) | final class TestStubs {

FILE: butterknife-runtime/src/test/java/butterknife/UnbinderTest.java
  class UnbinderTest (line 13) | public class UnbinderTest {
    method multipleBindings (line 14) | @Test public void multipleBindings() {
    method unbindingThroughAbstractChild (line 86) | @Test public void unbindingThroughAbstractChild() {
    method fullIntegration (line 190) | @Test public void fullIntegration() {

FILE: butterknife-runtime/src/test/java/butterknife/UtilsTest.java
  class UtilsTest (line 11) | public final class UtilsTest {
    method listOfFiltersNull (line 12) | @Test public void listOfFiltersNull() {
    method arrayFilteringNullRemovesNulls (line 23) | @Test public void arrayFilteringNullRemovesNulls() {
    method arrayFilteringNullReturnsOriginalWhenNoNulls (line 33) | @Test public void arrayFilteringNullReturnsOriginalWhenNoNulls() {
    method testCastParam (line 41) | @Test public void testCastParam() {

FILE: butterknife/src/androidTest/java/butterknife/ButterKnifeTest.java
  class ButterKnifeTest (line 12) | public class ButterKnifeTest {
    method resetViewsCache (line 15) | @Before @After // Clear out cache of binders before and after each test.
    method zeroBindingsBindDoesNotThrowExceptionAndCaches (line 20) | @Test public void zeroBindingsBindDoesNotThrowExceptionAndCaches() {
    method bindingKnownPackagesIsNoOp (line 31) | @Test public void bindingKnownPackagesIsNoOp() {

FILE: butterknife/src/main/java/butterknife/ButterKnife.java
  class ButterKnife (line 74) | public final class ButterKnife {
    method ButterKnife (line 75) | private ButterKnife() {
    method setDebug (line 86) | public static void setDebug(boolean debug) {
    method bind (line 96) | @NonNull @UiThread
    method bind (line 108) | @NonNull @UiThread
    method bind (line 119) | @NonNull @UiThread
    method bind (line 132) | @NonNull @UiThread
    method bind (line 145) | @NonNull @UiThread
    method bind (line 158) | @NonNull @UiThread
    method findBindingConstructorForClass (line 187) | @Nullable @CheckResult @UiThread

FILE: sample/app/src/main/java/com/example/butterknife/SimpleApp.java
  class SimpleApp (line 6) | public class SimpleApp extends Application {
    method onCreate (line 7) | @Override public void onCreate() {

FILE: sample/app/src/main/java/com/example/butterknife/unbinder/A.java
  class A (line 9) | public class A {
    method A (line 13) | public A(View view) {

FILE: sample/app/src/main/java/com/example/butterknife/unbinder/B.java
  class B (line 9) | public class B extends A {
    method B (line 13) | public B(View view) {

FILE: sample/app/src/main/java/com/example/butterknife/unbinder/C.java
  class C (line 10) | public class C extends B {
    method C (line 15) | public C(View view) {

FILE: sample/app/src/main/java/com/example/butterknife/unbinder/D.java
  class D (line 9) | public class D extends C {
    method D (line 13) | public D(View view) {

FILE: sample/app/src/main/java/com/example/butterknife/unbinder/E.java
  class E (line 9) | public class E extends C {
    method E (line 13) | public E(View view) {

FILE: sample/app/src/main/java/com/example/butterknife/unbinder/F.java
  class F (line 9) | public final class F extends D {
    method F (line 13) | public F(View view) {

FILE: sample/app/src/main/java/com/example/butterknife/unbinder/G.java
  class G (line 11) | public class G extends E {
    method G (line 16) | public G(View view) {
    method onClick (line 21) | @OnClick(android.R.id.content) public void onClick() {

FILE: sample/app/src/main/java/com/example/butterknife/unbinder/H.java
  class H (line 10) | public class H extends G {
    method H (line 15) | public H(View view) {

FILE: sample/library/src/main/java/com/example/butterknife/library/SimpleActivity.java
  class SimpleActivity (line 23) | public class SimpleActivity extends Activity {
    method apply (line 25) | @Override public void apply(@NonNull View view, int index) {
    method sayHello (line 44) | @OnClick(R2.id.hello) void sayHello() {
    method sayGetOffMe (line 49) | @OnLongClick(R2.id.hello) boolean sayGetOffMe() {
    method onItemClick (line 54) | @OnItemClick(R2.id.list_of_things) void onItemClick(int position) {
    method onCreate (line 58) | @SuppressLint("SetTextI18n") //

FILE: sample/library/src/main/java/com/example/butterknife/library/SimpleAdapter.java
  class SimpleAdapter (line 13) | public class SimpleAdapter extends BaseAdapter {
    method SimpleAdapter (line 18) | public SimpleAdapter(Context context) {
    method getCount (line 22) | @Override public int getCount() {
    method getItem (line 26) | @Override public String getItem(int position) {
    method getItemId (line 30) | @Override public long getItemId(int position) {
    method getView (line 34) | @SuppressLint("SetTextI18n") //
    class ViewHolder (line 54) | static final class ViewHolder {
      method ViewHolder (line 59) | ViewHolder(View view) {

FILE: website/static/prettify.js
  function L (line 2) | function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var...
  function M (line 6) | function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.classN...
  function B (line 7) | function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}
  function x (line 7) | function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(...
  function u (line 9) | function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''...
  function D (line 12) | function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.clas...
  function k (line 15) | function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(...
  function C (line 15) | function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-m...
  function E (line 15) | function E(a){var m=
  function m (line 25) | function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Inf...
Condensed preview — 232 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (749K chars).
[
  {
    "path": ".buildscript/deploy_snapshot.sh",
    "chars": 939,
    "preview": "#!/bin/bash\n#\n# Deploy a jar, source jar, and javadoc jar to Sonatype's snapshot repo.\n#\n# Adapted from https://coderwal"
  },
  {
    "path": ".github/workflows/gradle-wrapper-validation.yml",
    "chars": 223,
    "preview": "name: \"Validate Gradle Wrapper\"\non: [push, pull_request]\n\njobs:\n  validation:\n    name: \"Validation\"\n    runs-on: ubuntu"
  },
  {
    "path": ".gitignore",
    "chars": 110,
    "preview": "bin\ngen\nout\nlib\n\n.idea\n*.iml\nclasses\n\nobj\n\n.DS_Store\n\n# Gradle\n.gradle\njniLibs\nbuild\nlocal.properties\nreports\n"
  },
  {
    "path": ".travis.yml",
    "chars": 1738,
    "preview": "language: android\n\njdk:\n  - oraclejdk8\n\nbefore_install:\n  # Install SDK license so Android Gradle plugin can install dep"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 20229,
    "preview": "Change Log\n==========\n\nVersion 10.2.3 *(2020-08-12)*\n-----------------------------\n\nHeads up: Development on this tool i"
  },
  {
    "path": "LICENSE.txt",
    "chars": 11358,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "README.md",
    "chars": 3477,
    "preview": "Butter Knife\n============\n\n**Attention**: This tool is now deprecated. Please switch to\n[view binding](https://developer"
  },
  {
    "path": "RELEASING.md",
    "chars": 806,
    "preview": "Releasing\n========\n\n 1. Change the version in `gradle.properties` to a non-SNAPSHOT version.\n 2. Update the `CHANGELOG.m"
  },
  {
    "path": "build.gradle",
    "chars": 3551,
    "preview": "apply plugin: 'com.github.ben-manes.versions'\n\nbuildscript {\n  ext.versions = [\n      'minSdk': 14,\n      'compileSdk': "
  },
  {
    "path": "butterknife/build.gradle",
    "chars": 1054,
    "preview": "apply plugin: 'com.android.library'\n\nandroid {\n  compileSdkVersion versions.compileSdk\n\n  defaultConfig {\n    minSdkVers"
  },
  {
    "path": "butterknife/gradle.properties",
    "chars": 67,
    "preview": "POM_ARTIFACT_ID=butterknife\nPOM_NAME=Butterknife\nPOM_PACKAGING=aar\n"
  },
  {
    "path": "butterknife/proguard-rules.txt",
    "chars": 452,
    "preview": "# Retain generated class which implement Unbinder.\n-keep public class * implements butterknife.Unbinder { public <init>("
  },
  {
    "path": "butterknife/src/androidTest/java/butterknife/ButterKnifeTest.java",
    "chars": 1136,
    "preview": "package butterknife;\n\nimport android.content.Context;\nimport android.view.View;\nimport androidx.test.InstrumentationRegi"
  },
  {
    "path": "butterknife/src/main/AndroidManifest.xml",
    "chars": 97,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"butterknife\"/>\n"
  },
  {
    "path": "butterknife/src/main/java/butterknife/ButterKnife.java",
    "chars": 8006,
    "preview": "package butterknife;\n\nimport android.app.Activity;\nimport android.app.Dialog;\nimport android.util.Log;\nimport android.vi"
  },
  {
    "path": "butterknife/src/main/java/butterknife/package-info.java",
    "chars": 610,
    "preview": "/**\n * Field and method binding for Android views which uses annotation processing to generate\n * boilerplate code for y"
  },
  {
    "path": "butterknife-annotations/build.gradle",
    "chars": 383,
    "preview": "apply plugin: 'java-library'\napply plugin: 'checkstyle'\n\nsourceCompatibility = JavaVersion.VERSION_1_8\ntargetCompatibili"
  },
  {
    "path": "butterknife-annotations/gradle.properties",
    "chars": 91,
    "preview": "POM_NAME=Butterknife Annotations\nPOM_ARTIFACT_ID=butterknife-annotations\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/BindAnim.java",
    "chars": 558,
    "preview": "package butterknife;\n\nimport androidx.annotation.AnimRes;\nimport java.lang.annotation.Retention;\nimport java.lang.annota"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/BindArray.java",
    "chars": 1001,
    "preview": "package butterknife;\n\nimport androidx.annotation.ArrayRes;\nimport java.lang.annotation.Retention;\nimport java.lang.annot"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/BindBitmap.java",
    "chars": 631,
    "preview": "package butterknife;\n\nimport android.graphics.Bitmap;\nimport androidx.annotation.DrawableRes;\nimport java.lang.annotatio"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/BindBool.java",
    "chars": 556,
    "preview": "package butterknife;\n\nimport androidx.annotation.BoolRes;\nimport java.lang.annotation.Retention;\nimport java.lang.annota"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/BindColor.java",
    "chars": 721,
    "preview": "package butterknife;\n\nimport androidx.annotation.ColorRes;\nimport java.lang.annotation.Retention;\nimport java.lang.annot"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/BindDimen.java",
    "chars": 700,
    "preview": "package butterknife;\n\nimport androidx.annotation.DimenRes;\nimport java.lang.annotation.Retention;\nimport java.lang.annot"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/BindDrawable.java",
    "chars": 911,
    "preview": "package butterknife;\n\nimport androidx.annotation.AttrRes;\nimport androidx.annotation.DrawableRes;\nimport java.lang.annot"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/BindFloat.java",
    "chars": 855,
    "preview": "package butterknife;\n\nimport androidx.annotation.DimenRes;\nimport java.lang.annotation.Retention;\nimport java.lang.annot"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/BindFont.java",
    "chars": 944,
    "preview": "package butterknife;\n\nimport android.graphics.Typeface;\nimport androidx.annotation.FontRes;\nimport androidx.annotation.I"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/BindInt.java",
    "chars": 552,
    "preview": "package butterknife;\n\nimport androidx.annotation.IntegerRes;\nimport java.lang.annotation.Retention;\nimport java.lang.ann"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/BindString.java",
    "chars": 577,
    "preview": "package butterknife;\n\nimport androidx.annotation.StringRes;\nimport java.lang.annotation.Retention;\nimport java.lang.anno"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/BindView.java",
    "chars": 586,
    "preview": "package butterknife;\n\nimport androidx.annotation.IdRes;\nimport java.lang.annotation.Retention;\nimport java.lang.annotati"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/BindViews.java",
    "chars": 626,
    "preview": "package butterknife;\n\nimport androidx.annotation.IdRes;\nimport java.lang.annotation.Retention;\nimport java.lang.annotati"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/OnCheckedChanged.java",
    "chars": 1495,
    "preview": "package butterknife;\n\nimport android.view.View;\nimport androidx.annotation.IdRes;\nimport butterknife.internal.ListenerCl"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/OnClick.java",
    "chars": 1246,
    "preview": "package butterknife;\n\nimport android.view.View;\nimport androidx.annotation.IdRes;\nimport butterknife.internal.ListenerCl"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/OnEditorAction.java",
    "chars": 1670,
    "preview": "package butterknife;\n\nimport android.view.View;\nimport androidx.annotation.IdRes;\nimport butterknife.internal.ListenerCl"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/OnFocusChange.java",
    "chars": 1412,
    "preview": "package butterknife;\n\nimport android.view.View;\nimport androidx.annotation.IdRes;\nimport butterknife.internal.ListenerCl"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/OnItemClick.java",
    "chars": 1505,
    "preview": "package butterknife;\n\nimport android.view.View;\nimport androidx.annotation.IdRes;\nimport butterknife.internal.ListenerCl"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/OnItemLongClick.java",
    "chars": 1751,
    "preview": "package butterknife;\n\nimport android.view.View;\nimport androidx.annotation.IdRes;\nimport butterknife.internal.ListenerCl"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/OnItemSelected.java",
    "chars": 2488,
    "preview": "package butterknife;\n\nimport android.view.View;\nimport androidx.annotation.IdRes;\nimport butterknife.internal.ListenerCl"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/OnLongClick.java",
    "chars": 1488,
    "preview": "package butterknife;\n\nimport android.view.View;\nimport androidx.annotation.IdRes;\nimport butterknife.internal.ListenerCl"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/OnPageChange.java",
    "chars": 2299,
    "preview": "package butterknife;\n\nimport android.view.View;\nimport androidx.annotation.IdRes;\nimport butterknife.internal.ListenerCl"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/OnTextChanged.java",
    "chars": 2570,
    "preview": "package butterknife;\n\nimport android.text.TextWatcher;\nimport android.view.View;\nimport androidx.annotation.IdRes;\nimpor"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/OnTouch.java",
    "chars": 1510,
    "preview": "package butterknife;\n\nimport android.view.View;\nimport androidx.annotation.IdRes;\nimport butterknife.internal.ListenerCl"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/Optional.java",
    "chars": 477,
    "preview": "package butterknife;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\nimport static java.lan"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/internal/Constants.java",
    "chars": 128,
    "preview": "package butterknife.internal;\n\npublic class Constants {\n\n  private Constants() { }\n\n  public static final int NO_RES_ID "
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/internal/ListenerClass.java",
    "chars": 1157,
    "preview": "package butterknife.internal;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\nimport static"
  },
  {
    "path": "butterknife-annotations/src/main/java/butterknife/internal/ListenerMethod.java",
    "chars": 798,
    "preview": "package butterknife.internal;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\nimport static"
  },
  {
    "path": "butterknife-compiler/build.gradle",
    "chars": 780,
    "preview": "apply plugin: 'java-library'\napply plugin: 'checkstyle'\n\nsourceCompatibility = JavaVersion.VERSION_1_8\ntargetCompatibili"
  },
  {
    "path": "butterknife-compiler/gradle.properties",
    "chars": 85,
    "preview": "POM_NAME=Butterknife Compiler\nPOM_ARTIFACT_ID=butterknife-compiler\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/BindingSet.java",
    "chars": 30710,
    "preview": "package butterknife.compiler;\n\nimport butterknife.OnTouch;\nimport butterknife.internal.ListenerClass;\nimport butterknife"
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/ButterKnifeProcessor.java",
    "chars": 59946,
    "preview": "package butterknife.compiler;\n\nimport butterknife.BindAnim;\nimport butterknife.BindArray;\nimport butterknife.BindBitmap;"
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/FieldAnimationBinding.java",
    "chars": 638,
    "preview": "package butterknife.compiler;\n\nimport com.squareup.javapoet.CodeBlock;\n\nimport static butterknife.compiler.BindingSet.AN"
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/FieldCollectionViewBinding.java",
    "chars": 2118,
    "preview": "package butterknife.compiler;\n\nimport com.squareup.javapoet.CodeBlock;\nimport com.squareup.javapoet.ParameterizedTypeNam"
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/FieldDrawableBinding.java",
    "chars": 1123,
    "preview": "package butterknife.compiler;\n\nimport com.squareup.javapoet.CodeBlock;\n\nimport static butterknife.compiler.BindingSet.CO"
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/FieldResourceBinding.java",
    "chars": 3429,
    "preview": "package butterknife.compiler;\n\nimport androidx.annotation.Nullable;\nimport com.google.common.collect.ImmutableList;\nimpo"
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/FieldTypefaceBinding.java",
    "chars": 1653,
    "preview": "package butterknife.compiler;\n\nimport androidx.annotation.Nullable;\nimport com.squareup.javapoet.ClassName;\nimport com.s"
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/FieldViewBinding.java",
    "chars": 886,
    "preview": "package butterknife.compiler;\n\nimport com.squareup.javapoet.ClassName;\nimport com.squareup.javapoet.ParameterizedTypeNam"
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/Id.java",
    "chars": 1381,
    "preview": "package butterknife.compiler;\n\nimport androidx.annotation.Nullable;\nimport com.squareup.javapoet.ClassName;\nimport com.s"
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/MemberViewBinding.java",
    "chars": 213,
    "preview": "package butterknife.compiler;\n\n/** A field or method view binding. */\ninterface MemberViewBinding {\n  /** A description "
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/MethodViewBinding.java",
    "chars": 947,
    "preview": "package butterknife.compiler;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\nfinal c"
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/Parameter.java",
    "chars": 624,
    "preview": "package butterknife.compiler;\n\nimport com.squareup.javapoet.TypeName;\n\n/** Represents a parameter type and its position "
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/ResourceBinding.java",
    "chars": 281,
    "preview": "package butterknife.compiler;\n\nimport com.squareup.javapoet.CodeBlock;\n\ninterface ResourceBinding {\n  Id id();\n\n  /** Tr"
  },
  {
    "path": "butterknife-compiler/src/main/java/butterknife/compiler/ViewBinding.java",
    "chars": 3377,
    "preview": "package butterknife.compiler;\n\nimport butterknife.internal.ListenerClass;\nimport butterknife.internal.ListenerMethod;\nim"
  },
  {
    "path": "butterknife-compiler/src/test/java/butterknife/compiler/BindingSetTest.java",
    "chars": 1153,
    "preview": "package butterknife.compiler;\n\nimport org.junit.Test;\n\nimport static butterknife.compiler.BindingSet.asHumanDescription;"
  },
  {
    "path": "butterknife-gradle-plugin/build.gradle",
    "chars": 787,
    "preview": "apply plugin: 'java-gradle-plugin'\napply plugin: 'kotlin'\n\nsourceCompatibility = JavaVersion.VERSION_1_8\ntargetCompatibi"
  },
  {
    "path": "butterknife-gradle-plugin/gradle.properties",
    "chars": 95,
    "preview": "POM_NAME=Butterknife Gradle Plugin\nPOM_ARTIFACT_ID=butterknife-gradle-plugin\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "butterknife-gradle-plugin/src/main/java/butterknife/plugin/ButterKnifePlugin.kt",
    "chars": 3760,
    "preview": "package butterknife.plugin\n\nimport com.android.build.gradle.AppExtension\nimport com.android.build.gradle.AppPlugin\nimpor"
  },
  {
    "path": "butterknife-gradle-plugin/src/main/java/butterknife/plugin/FinalRClassBuilder.kt",
    "chars": 2297,
    "preview": "package butterknife.plugin\n\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.CodeBlock\nimport com.squ"
  },
  {
    "path": "butterknife-gradle-plugin/src/main/java/butterknife/plugin/R2Generator.kt",
    "chars": 1120,
    "preview": "package butterknife.plugin\n\nimport org.gradle.api.DefaultTask\nimport org.gradle.api.file.FileCollection\nimport org.gradl"
  },
  {
    "path": "butterknife-gradle-plugin/src/main/java/butterknife/plugin/ResourceSymbolListReader.kt",
    "chars": 716,
    "preview": "package butterknife.plugin\n\nimport com.squareup.javapoet.CodeBlock\nimport java.io.File\n\ninternal class ResourceSymbolLis"
  },
  {
    "path": "butterknife-gradle-plugin/src/main/resources/META-INF/gradle-plugins/com.jakewharton.butterknife.properties",
    "chars": 58,
    "preview": "implementation-class=butterknife.plugin.ButterKnifePlugin\n"
  },
  {
    "path": "butterknife-gradle-plugin/src/test/AndroidManifest.xml",
    "chars": 46,
    "preview": "<manifest package=\"com.example.butterknife\"/>\n"
  },
  {
    "path": "butterknife-gradle-plugin/src/test/build.gradle",
    "chars": 1552,
    "preview": "plugins {\n    id 'com.android.application'\n    id 'com.jakewharton.butterknife'\n}\n\nrepositories {\n    google()\n    maven"
  },
  {
    "path": "butterknife-gradle-plugin/src/test/fixtures/suffix_parsed_properly/src/main/java/butterknife/test/ButteryActivity.java",
    "chars": 469,
    "preview": "package butterknife.test;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.widget.TextView;\nimport"
  },
  {
    "path": "butterknife-gradle-plugin/src/test/fixtures/suffix_parsed_properly/src/main/res/layout/activity_layout.xml",
    "chars": 524,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  xmlns:"
  },
  {
    "path": "butterknife-gradle-plugin/src/test/java/butterknife/plugin/AndroidHome.kt",
    "chars": 689,
    "preview": "package butterknife.plugin\n\nimport java.io.File\nimport java.util.Properties\n\n\ninternal fun androidHome(): String {\n    v"
  },
  {
    "path": "butterknife-gradle-plugin/src/test/java/butterknife/plugin/BuildFilesRule.kt",
    "chars": 1683,
    "preview": "package butterknife.plugin\n\nimport com.google.common.truth.Truth.assertThat\nimport org.junit.rules.TestRule\nimport org.j"
  },
  {
    "path": "butterknife-gradle-plugin/src/test/java/butterknife/plugin/FinalRClassBuilderTest.kt",
    "chars": 1061,
    "preview": "package butterknife.plugin\n\nimport com.google.common.truth.Truth.assertAbout\nimport com.google.testing.compile.JavaFileO"
  },
  {
    "path": "butterknife-gradle-plugin/src/test/java/butterknife/plugin/FixturesTest.kt",
    "chars": 1918,
    "preview": "package butterknife.plugin\n\nimport com.google.common.truth.Truth.assertThat\nimport org.gradle.testkit.runner.GradleRunne"
  },
  {
    "path": "butterknife-gradle-plugin/src/test/resources/fixtures/R.txt",
    "chars": 499,
    "preview": "int unsupported res 0x7f040000\nint anim res 0x7f040001\nint array res 0x7f040002\nint attr res 0x7f040003\nint bool res 0x7"
  },
  {
    "path": "butterknife-gradle-plugin/src/test/resources/fixtures/R2.java",
    "chars": 2165,
    "preview": "// Generated code from Butter Knife gradle plugin. Do not modify!\npackage com.butterknife.example;\n\nimport androidx.anno"
  },
  {
    "path": "butterknife-integration-test/build.gradle",
    "chars": 1668,
    "preview": "apply plugin: 'com.android.application'\n\nandroid {\n  compileSdkVersion versions.compileSdk\n\n  compileOptions {\n    sourc"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/font_licenses.txt",
    "chars": 4443,
    "preview": "Copyright 2006 The Inconsolata Project Authors\r\n\r\nThis Font Software is licensed under the SIL Open Font License, Versio"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindAnimTest.java",
    "chars": 674,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport android.view.animation.Animation;\nimport b"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindArrayTest.java",
    "chars": 1949,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.view.View;\nimport androidx.t"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindBitmapTest.java",
    "chars": 998,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.graphics.Bitmap;\nimport andr"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindBoolTest.java",
    "chars": 924,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.view.View;\nimport androidx.t"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindColorTest.java",
    "chars": 1475,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.content.res.ColorStateList;\n"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindDimenTest.java",
    "chars": 1400,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.view.View;\nimport androidx.t"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindDrawableTest.java",
    "chars": 1061,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.graphics.drawable.Drawable;\n"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindFloatTest.java",
    "chars": 1043,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.util.TypedValue;\nimport andr"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindFontTest.java",
    "chars": 1704,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.graphics.Typeface;\nimport an"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindIntTest.java",
    "chars": 909,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.view.View;\nimport androidx.t"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindStringTest.java",
    "chars": 904,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.view.View;\nimport androidx.t"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindViewTest.java",
    "chars": 665,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindView;\nimport butterknife.B"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/BindViewsTest.java",
    "chars": 1406,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindViews;\nimport butterknife."
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnCheckedChangedTest.java",
    "chars": 5851,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.view.View;\nimport android.vi"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnClickTest.java",
    "chars": 6788,
    "preview": "package com.example.butterknife.functional;\n\nimport android.app.Instrumentation;\nimport android.content.Context;\nimport "
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnItemClickTest.java",
    "chars": 7984,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.view.View;\nimport android.vi"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnItemLongClickTest.java",
    "chars": 8230,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.view.View;\nimport android.vi"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnItemSelectedTest.java",
    "chars": 11015,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.view.View;\nimport android.vi"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnLongClickTest.java",
    "chars": 6187,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.view.View;\nimport android.vi"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/OnTouchTest.java",
    "chars": 6998,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.view.MotionEvent;\nimport and"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/functional/ViewTree.java",
    "chars": 1146,
    "preview": "package com.example.butterknife.functional;\n\nimport android.content.Context;\nimport android.view.View;\nimport android.vi"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/library/SimpleActivityTest.java",
    "chars": 1438,
    "preview": "package com.example.butterknife.library;\n\nimport androidx.test.rule.ActivityTestRule;\nimport butterknife.ButterKnife;\nim"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/library/SimpleAdapterTest.java",
    "chars": 790,
    "preview": "package com.example.butterknife.library;\n\nimport android.content.Context;\nimport android.view.View;\nimport androidx.test"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/java/com/example/butterknife/unbinder/UnbinderTest.java",
    "chars": 1499,
    "preview": "package com.example.butterknife.unbinder;\n\nimport android.content.Context;\nimport android.view.View;\nimport android.widg"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/proguard.pro",
    "chars": 67,
    "preview": "-dontoptimize\n-dontobfuscate\n-dontshrink\n-dontnote **\n-dontwarn **\n"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/res/color/colors.xml",
    "chars": 286,
    "preview": "<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n  <item\n      android:color=\"#ffff0000\"\n      andr"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/res/drawable/circle.xml",
    "chars": 266,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android"
  },
  {
    "path": "butterknife-integration-test/src/androidTest/res/values/values.xml",
    "chars": 542,
    "preview": "<resources>\n  <bool name=\"just_true\">true</bool>\n  <color name=\"red\">#ffff0000</color>\n  <integer name=\"twelve\">12</inte"
  },
  {
    "path": "butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindAnimFailureTest.java",
    "chars": 788,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindAnim;\nimport butterknife.B"
  },
  {
    "path": "butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindArrayFailureTest.java",
    "chars": 872,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindArray;\nimport butterknife."
  },
  {
    "path": "butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindBitmapFailureTest.java",
    "chars": 792,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindBitmap;\nimport butterknife"
  },
  {
    "path": "butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindBoolFailureTest.java",
    "chars": 781,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindBool;\nimport butterknife.B"
  },
  {
    "path": "butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindColorFailureTest.java",
    "chars": 817,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindColor;\nimport butterknife."
  },
  {
    "path": "butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindDimenFailureTest.java",
    "chars": 799,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindDimen;\nimport butterknife."
  },
  {
    "path": "butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindDrawableFailureTest.java",
    "chars": 806,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindDrawable;\nimport butterkni"
  },
  {
    "path": "butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindFloatFailureTest.java",
    "chars": 785,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindFloat;\nimport butterknife."
  },
  {
    "path": "butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindFontFailureTest.java",
    "chars": 1523,
    "preview": "package com.example.butterknife.functional;\n\nimport android.graphics.Typeface;\nimport android.view.View;\nimport androidx"
  },
  {
    "path": "butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindIntFailureTest.java",
    "chars": 771,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindInt;\nimport butterknife.Bu"
  },
  {
    "path": "butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindStringFailureTest.java",
    "chars": 793,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindString;\nimport butterknife"
  },
  {
    "path": "butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindViewFailureTest.java",
    "chars": 804,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindView;\nimport butterknife.B"
  },
  {
    "path": "butterknife-integration-test/src/androidTestReflect/java/com/example/butterknife/functional/BindViewsFailureTest.java",
    "chars": 2810,
    "preview": "package com.example.butterknife.functional;\n\nimport android.view.View;\nimport butterknife.BindViews;\nimport butterknife."
  },
  {
    "path": "butterknife-integration-test/src/main/AndroidManifest.xml",
    "chars": 835,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:to"
  },
  {
    "path": "butterknife-integration-test/src/main/java/com/example/butterknife/SimpleApp.java",
    "chars": 254,
    "preview": "package com.example.butterknife;\n\nimport android.app.Application;\nimport butterknife.ButterKnife;\n\npublic class SimpleAp"
  },
  {
    "path": "butterknife-integration-test/src/main/java/com/example/butterknife/library/SimpleActivity.java",
    "chars": 2538,
    "preview": "package com.example.butterknife.library;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.view.Vie"
  },
  {
    "path": "butterknife-integration-test/src/main/java/com/example/butterknife/library/SimpleAdapter.java",
    "chars": 1848,
    "preview": "package com.example.butterknife.library;\n\nimport android.content.Context;\nimport android.view.LayoutInflater;\nimport and"
  },
  {
    "path": "butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/A.java",
    "chars": 314,
    "preview": "package com.example.butterknife.unbinder;\n\nimport android.view.View;\nimport androidx.annotation.ColorInt;\nimport butterk"
  },
  {
    "path": "butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/B.java",
    "chars": 341,
    "preview": "package com.example.butterknife.unbinder;\n\nimport android.view.View;\nimport androidx.annotation.ColorInt;\nimport butterk"
  },
  {
    "path": "butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/C.java",
    "chars": 430,
    "preview": "package com.example.butterknife.unbinder;\n\nimport android.view.View;\nimport androidx.annotation.ColorInt;\nimport butterk"
  },
  {
    "path": "butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/D.java",
    "chars": 346,
    "preview": "package com.example.butterknife.unbinder;\n\nimport android.view.View;\nimport androidx.annotation.ColorInt;\nimport butterk"
  },
  {
    "path": "butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/E.java",
    "chars": 360,
    "preview": "package com.example.butterknife.unbinder;\n\nimport android.view.View;\nimport androidx.annotation.ColorInt;\nimport butterk"
  },
  {
    "path": "butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/F.java",
    "chars": 368,
    "preview": "package com.example.butterknife.unbinder;\n\nimport android.view.View;\nimport androidx.annotation.ColorInt;\nimport butterk"
  },
  {
    "path": "butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/G.java",
    "chars": 541,
    "preview": "package com.example.butterknife.unbinder;\n\nimport android.view.View;\nimport androidx.annotation.ColorInt;\nimport butterk"
  },
  {
    "path": "butterknife-integration-test/src/main/java/com/example/butterknife/unbinder/H.java",
    "chars": 431,
    "preview": "package com.example.butterknife.unbinder;\n\nimport android.view.View;\nimport androidx.annotation.ColorInt;\nimport butterk"
  },
  {
    "path": "butterknife-integration-test/src/main/proguard.pro",
    "chars": 305,
    "preview": "-dontoptimize\n-dontobfuscate\n-dontnote **\n-dontwarn **\n\n# STUFF USED BY TESTS:\n\n-keep class butterknife.internal.Utils {"
  },
  {
    "path": "butterknife-integration-test/src/main/res/layout/simple_activity.xml",
    "chars": 1572,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        "
  },
  {
    "path": "butterknife-integration-test/src/main/res/layout/simple_list_item.xml",
    "chars": 830,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        "
  },
  {
    "path": "butterknife-integration-test/src/main/res/values/strings.xml",
    "chars": 300,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<resources>\n  <string name=\"app_name\">Butter Knife</string>\n  <string name=\"fiel"
  },
  {
    "path": "butterknife-lint/build.gradle",
    "chars": 638,
    "preview": "apply plugin: 'java-library'\napply plugin: 'checkstyle'\n\nsourceCompatibility = JavaVersion.VERSION_1_8\ntargetCompatibili"
  },
  {
    "path": "butterknife-lint/src/main/java/butterknife/lint/InvalidR2UsageDetector.java",
    "chars": 4318,
    "preview": "package butterknife.lint;\n\nimport com.android.tools.lint.client.api.UElementHandler;\nimport com.android.tools.lint.detec"
  },
  {
    "path": "butterknife-lint/src/main/java/butterknife/lint/LintRegistry.java",
    "chars": 559,
    "preview": "package butterknife.lint;\n\nimport com.android.tools.lint.client.api.IssueRegistry;\nimport com.android.tools.lint.detecto"
  },
  {
    "path": "butterknife-lint/src/test/java/butterknife/lint/InvalidR2UsageDetectorTest.java",
    "chars": 4399,
    "preview": "package butterknife.lint;\n\nimport com.android.tools.lint.checks.infrastructure.TestFile;\nimport org.junit.Test;\n\nimport "
  },
  {
    "path": "butterknife-lint/src/test/java/butterknife/lint/LintRegistryTest.java",
    "chars": 270,
    "preview": "package butterknife.lint;\n\nimport org.junit.Test;\n\nimport static com.google.common.truth.Truth.assertThat;\n\npublic final"
  },
  {
    "path": "butterknife-reflect/README.md",
    "chars": 2106,
    "preview": "ButterKnife Reflect\n===================\n\nThe `butterknife-reflect` artifact is an API-compatible replacement for `butter"
  },
  {
    "path": "butterknife-reflect/build.gradle",
    "chars": 812,
    "preview": "apply plugin: 'com.android.library'\n\nandroid {\n  compileSdkVersion versions.compileSdk\n\n  defaultConfig {\n    minSdkVers"
  },
  {
    "path": "butterknife-reflect/gradle.properties",
    "chars": 83,
    "preview": "POM_ARTIFACT_ID=butterknife-reflect\nPOM_NAME=ButterKnife Reflect\nPOM_PACKAGING=aar\n"
  },
  {
    "path": "butterknife-reflect/proguard-rules.txt",
    "chars": 111,
    "preview": "-keepclassmembers class * { @butterknife.* <methods>; }\n-keepclassmembers class * { @butterknife.* <fields>; }\n"
  },
  {
    "path": "butterknife-reflect/src/main/AndroidManifest.xml",
    "chars": 42,
    "preview": "<manifest package=\"butterknife.reflect\"/>\n"
  },
  {
    "path": "butterknife-reflect/src/main/java/butterknife/ButterKnife.java",
    "chars": 43033,
    "preview": "package butterknife;\n\nimport android.app.Activity;\nimport android.app.Dialog;\nimport android.content.Context;\nimport and"
  },
  {
    "path": "butterknife-reflect/src/main/java/butterknife/CompositeUnbinder.java",
    "chars": 551,
    "preview": "package butterknife;\n\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport java.util.List;\n\nf"
  },
  {
    "path": "butterknife-reflect/src/main/java/butterknife/EmptyTextWatcher.java",
    "chars": 388,
    "preview": "package butterknife;\n\nimport android.text.Editable;\nimport android.text.TextWatcher;\n\nclass EmptyTextWatcher implements "
  },
  {
    "path": "butterknife-reflect/src/main/java/butterknife/FieldUnbinder.java",
    "chars": 386,
    "preview": "package butterknife;\n\nimport java.lang.reflect.Field;\n\nimport static butterknife.ButterKnife.trySet;\n\nfinal class FieldU"
  },
  {
    "path": "butterknife-reflect/src/main/java/butterknife/ListenerUnbinder.java",
    "chars": 638,
    "preview": "package butterknife;\n\nimport android.view.View;\nimport java.util.List;\n\nfinal class ListenerUnbinder<V extends View, L> "
  },
  {
    "path": "butterknife-runtime/build.gradle",
    "chars": 1936,
    "preview": "apply plugin: 'com.android.library'\n\nandroid {\n  compileSdkVersion versions.compileSdk\n\n  defaultConfig {\n    minSdkVers"
  },
  {
    "path": "butterknife-runtime/gradle.properties",
    "chars": 83,
    "preview": "POM_ARTIFACT_ID=butterknife-runtime\nPOM_NAME=ButterKnife Runtime\nPOM_PACKAGING=aar\n"
  },
  {
    "path": "butterknife-runtime/src/androidTest/java/butterknife/ViewCollectionsTest.java",
    "chars": 7028,
    "preview": "package butterknife;\n\nimport android.content.Context;\nimport android.util.Property;\nimport android.view.View;\nimport and"
  },
  {
    "path": "butterknife-runtime/src/androidTest/java/butterknife/internal/UtilsTest.java",
    "chars": 1552,
    "preview": "package butterknife.internal;\n\nimport android.content.Context;\nimport android.view.View;\nimport androidx.test.Instrument"
  },
  {
    "path": "butterknife-runtime/src/main/AndroidManifest.xml",
    "chars": 105,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"butterknife.runtime\"/>\n"
  },
  {
    "path": "butterknife-runtime/src/main/java/butterknife/Action.java",
    "chars": 360,
    "preview": "package butterknife;\n\nimport android.view.View;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.UiThread;"
  },
  {
    "path": "butterknife-runtime/src/main/java/butterknife/Setter.java",
    "chars": 424,
    "preview": "package butterknife;\n\nimport android.view.View;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;"
  },
  {
    "path": "butterknife-runtime/src/main/java/butterknife/Unbinder.java",
    "chars": 212,
    "preview": "package butterknife;\n\nimport androidx.annotation.UiThread;\n\n/** An unbinder contract that will unbind views when called."
  },
  {
    "path": "butterknife-runtime/src/main/java/butterknife/ViewCollections.java",
    "chars": 4173,
    "preview": "package butterknife;\n\nimport android.util.Property;\nimport android.view.View;\nimport androidx.annotation.NonNull;\nimport"
  },
  {
    "path": "butterknife-runtime/src/main/java/butterknife/internal/DebouncingOnClickListener.java",
    "chars": 946,
    "preview": "package butterknife.internal;\n\nimport android.os.Handler;\nimport android.os.Looper;\nimport android.view.View;\n\n/**\n * A "
  },
  {
    "path": "butterknife-runtime/src/main/java/butterknife/internal/ImmutableList.java",
    "chars": 689,
    "preview": "package butterknife.internal;\n\nimport java.util.AbstractList;\nimport java.util.RandomAccess;\n\n/**\n * An immutable list o"
  },
  {
    "path": "butterknife-runtime/src/main/java/butterknife/internal/Utils.java",
    "chars": 4567,
    "preview": "package butterknife.internal;\n\nimport android.content.Context;\nimport android.content.res.Resources;\nimport android.grap"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/BindAnimTest.java",
    "chars": 884,
    "preview": "package butterknife;\n\nimport com.google.testing.compile.JavaFileObjects;\n\nimport org.junit.Test;\n\nimport javax.tools.Jav"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/BindArrayTest.java",
    "chars": 3093,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/BindBitmapTest.java",
    "chars": 889,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/BindBoolTest.java",
    "chars": 883,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/BindColorTest.java",
    "chars": 4898,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/BindDimenTest.java",
    "chars": 897,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/BindDrawableTest.java",
    "chars": 4986,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/BindFloatTest.java",
    "chars": 883,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/BindFontTest.java",
    "chars": 5827,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/BindIntTest.java",
    "chars": 871,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/BindStringTest.java",
    "chars": 890,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/BindViewTest.java",
    "chars": 35680,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.common.collect.ImmutableList;\n"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/BindViewsTest.java",
    "chars": 23902,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\n\nimport com.google.common.collect.ImmutableList;"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/ClasspathParentBindTest.java",
    "chars": 10165,
    "preview": "package butterknife;\n\nimport com.google.common.collect.ImmutableList;\nimport com.google.testing.compile.JavaFileObjects;"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/ExtendActivityTest.java",
    "chars": 4573,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/ExtendDialogTest.java",
    "chars": 4748,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/ExtendViewTest.java",
    "chars": 4675,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/OnClickTest.java",
    "chars": 15272,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/OnEditorActionTest.java",
    "chars": 4809,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/OnFocusChangeTest.java",
    "chars": 2404,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/OnItemClickTest.java",
    "chars": 16721,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/OnItemLongClickTest.java",
    "chars": 4793,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/OnItemSelectedTest.java",
    "chars": 11840,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/OnPageChangeTest.java",
    "chars": 3090,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/OnTextChangedTest.java",
    "chars": 9521,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/OnTouchTest.java",
    "chars": 5429,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/RClassTest.java",
    "chars": 16648,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/TestGeneratingProcessor.java",
    "chars": 1883,
    "preview": "package butterknife;\n\nimport com.google.common.base.Joiner;\nimport com.google.common.collect.ImmutableSet;\nimport com.go"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/TestStubs.java",
    "chars": 1082,
    "preview": "package butterknife;\n\nimport com.google.testing.compile.JavaFileObjects;\nimport javax.tools.JavaFileObject;\n\nfinal class"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/UnbinderTest.java",
    "chars": 21939,
    "preview": "package butterknife;\n\nimport butterknife.compiler.ButterKnifeProcessor;\nimport com.google.testing.compile.JavaFileObject"
  },
  {
    "path": "butterknife-runtime/src/test/java/butterknife/UtilsTest.java",
    "chars": 2424,
    "preview": "package butterknife;\n\nimport butterknife.internal.Utils;\nimport org.junit.Test;\n\nimport static butterknife.internal.Util"
  },
  {
    "path": "checkstyle.xml",
    "chars": 5132,
    "preview": "<?xml version=\"1.0\"?>\n<!DOCTYPE module PUBLIC\n    \"-//Puppy Crawl//DTD Check Configuration 1.3//EN\"\n    \"http://checksty"
  },
  {
    "path": "deploy_website.sh",
    "chars": 931,
    "preview": "#!/bin/bash\n\nset -ex\n\nREPO=\"https://github.com/JakeWharton/butterknife.git\"\nGROUP_ID=\"com.jakewharton\"\nARTIFACT_ID=\"butt"
  },
  {
    "path": "gradle/gradle-mvn-push.gradle",
    "chars": 4452,
    "preview": "/*\n * Copyright 2013 Chris Banes\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not us"
  }
]

// ... and 32 more files (download for full content)

About this extraction

This page contains the full source code of the JakeWharton/butterknife GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 232 files (674.9 KB), approximately 174.3k tokens, and a symbol index with 913 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!