[
  {
    "path": ".buildscript/deploy_snapshot.sh",
    "content": "#!/bin/bash\n#\n# Deploy a jar, source jar, and javadoc jar to Sonatype's snapshot repo.\n#\n# Adapted from https://coderwall.com/p/9b_lfq and\n# http://benlimmer.com/2013/12/26/automatically-publish-javadoc-to-gh-pages-with-travis-ci/\n\nSLUG=\"uber/artist\"\nJDK=\"oraclejdk8\"\nBRANCH=\"master\"\n\nset -e\n\nif [ \"$TRAVIS_REPO_SLUG\" != \"$SLUG\" ]; then\n  echo \"Skipping snapshot deployment: wrong repository. Expected '$SLUG' but was '$TRAVIS_REPO_SLUG'.\"\nelif [ \"$TRAVIS_JDK_VERSION\" != \"$JDK\" ]; then\n  echo \"Skipping snapshot deployment: wrong JDK. Expected '$JDK' but was '$TRAVIS_JDK_VERSION'.\"\nelif [ \"$TRAVIS_PULL_REQUEST\" != \"false\" ]; then\n  echo \"Skipping snapshot deployment: was pull request.\"\nelif [ \"$TRAVIS_BRANCH\" != \"$BRANCH\" ]; then\n  echo \"Skipping snapshot deployment: wrong branch. Expected '$BRANCH' but was '$TRAVIS_BRANCH'.\"\nelse\n  echo \"Deploying snapshot...\"\n  ./gradlew clean uploadArchives -Dorg.gradle.parallel=false\n  echo \"Snapshot deployed!\"\nfi\n"
  },
  {
    "path": ".editorconfig",
    "content": "[*.{kt,kts}]\n# possible values: number (e.g. 2), \"unset\" (makes ktlint ignore indentation completely)\nindent_size=2\ncontinuation_indent_size=4\ninsert_final_newline=true\n# possible values: number (e.g. 120) (package name, imports & comments are ignored), \"off\"\nmax_line_length=off\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "Thanks for using Artist. Before you create an issue, please consider the following points:\n\n  - [ ] If you think you found a bug, please include a code sample that reproduces the problem. A test case that reproduces the issue is preferred. A stack trace alone is ok but may not contain enough context for us to address the issue.\n\n  - [ ] Please include the library version number, including the minor and patch version, in the issue text.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "Thank you for contributing to Artist. Before pressing the \"Create Pull Request\" button, please provide the following:\n\n  - [ ] A description about what and why you are contributing, even if it's trivial.\n\n  - [ ] The issue number(s) or PR number(s) in the description if you are contributing in response to those.\n\n  - [ ] If applicable, unit tests.\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non: [push, pull_request]\n\njobs: \n  build:\n    name: JDK ${{ matrix.java_version }}\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        java_version: [8]\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n      - name: Install JDK ${{ matrix.java_version }}\n        uses: actions/setup-java@v2\n        with:\n          distribution: 'zulu'\n          java-version: ${{ matrix.java_version }}\n      - name: Install Android SDK\n        uses: malinskiy/action-android/install-sdk@release/0.1.1\n      - name: Gradle Wrapper Validation\n        uses: gradle/wrapper-validation-action@v1\n      - name: Configure Gradle\n        # Install Gradle Deps\n        run: ./gradlew help\n      - name: Build project\n        run: ./gradlew assemble --stacktrace\n      - name: Run tests\n        run: ./gradlew test --stacktrace\n      - name: Gradle Check\n        run: ./gradlew check --stacktrace\n      - name: Upload snapshot (main only)\n        run: ./gradlew uploadArchives -PSONATYPE_NEXUS_USERNAME=\"$SONATYPE_NEXUS_USERNAME\" -PSONATYPE_NEXUS_PASSWORD=\"$SONATYPE_NEXUS_PASSWORD\"\n        env:\n          SONATYPE_NEXUS_USERNAME: ${{ secrets.SonatypeUsername }}\n          SONATYPE_NEXUS_PASSWORD: ${{ secrets.SonatypePassword }}\n        if: success() && github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && matrix.java_version == '8'\n"
  },
  {
    "path": ".gitignore",
    "content": "###OSX###\n\n.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must ends with two \\r.\nIcon\n\n\n# Thumbnails\n._*\n\n# Files that might appear on external disk\n.Spotlight-V100\n.Trashes\n\n\n###Linux###\n\n*~\n\n# KDE directory preferences\n.directory\n\n\n###Android###\n\n# Built application files\n*.apk\n*.ap_\n\n# Files for ART and Dalvik VM\n*.dex\n\n# Java class files\n*.class\n\n# Generated files\nbin/\ngen/\n\n# Gradle files\n.gradle/\n.gradletasknamecache\nbuild/\n\n# Local configuration file (sdk path, etc)\nlocal.properties\n\n# Proguard folder generated by Eclipse\nproguard/\n\n# Lint\nlint-report.html\nlint-report_files/\nlint_result.txt\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.war\n*.ear\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n\n\n###IntelliJ###\n\n*.iml\n*.ipr\n*.iws\n.idea/\n\n\n###Eclipse###\n\n*.pydevproject\n.metadata\ntmp/\n*.tmp\n*.bak\n*.swp\n*~.nib\n.settings/\n.loadpath\n\n# External tool builders\n.externalToolBuilders/\n\n# Locally stored \"Eclipse launch configurations\"\n*.launch\n\n# CDT-specific\n.cproject\n\n# PDT-specific\n.buildpath\n\n# sbteclipse plugin\n.target\n\n# TeXlipse plugin\n.texlipse\n\n# kotlin\nannotations/\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "Changelog\n=========\nVersion 0.4.9\n-------------\n_2023-07-27_\n\n* Update version upstreaming unmerged fixes \n\nVersion 0.4.8\n-------------\n\n_2023-07-18_\n\n* Fixes Rx Kotlin nulls [issue](https://github.com/uber/artist/issues/49) \n\nVersion 0.4.7\n-------------\n\n_2021-02-06_\n\n* Add support for AndroidX\n\nVersion 0.4.6\n-------------\n\n_2021-02-08_\n\n\nVersion 0.4.5\n-------------\n\n_2018-12-19_\n\n* **Breaking change:** API classes renamed with \"Java\" prefixes. Class names and AutoService annotations will need to be updated\n* Added Kotlin-prefixed API classes modules for generating Kotlin views\n\n\nVersion 0.3.0\n-------------\n\n_2018-12-03_\n\n* **Breaking change:** Project migrated to [AndroidX](https://developer.android.com/jetpack/androidx/). See the [class and package mappings](https://developer.android.com/jetpack/androidx/migrate) for help migrating\n\nVersion 0.2.2\n-------------\n\n_2018-11-07_\n\n* **Note:** This is the final version that uses the non-AndroidX Support Library\n* Annotate underlying `setOnClickListener(listener)` method param as `@Nullable` to match AOSP\n* Dependency updates including using Support Library, Kotlin, RxJava, and RxBinding\n\nVersion 0.2.1\n-------------\n\n_2018-07-01_\n\n* Separated core artist functionality into a module\n\nVersion 0.2.0\n-------------\n\n_2018-04-23_\n\n* **Breaking change:** Removed `TraitProvider` in favor of annotating with `AutoService(Trait.class)`\n* `ViewStencilProvider` and `ArtistRxConfig` implementations can also be annotated with `AutoService`\n\nVersion 0.1.0\n-------------\n\n_2017-12-11_\n\n* Initial release\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment include:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at mobile-open-source@uber.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]\n\n[homepage]: http://contributor-covenant.org\n[version]: http://contributor-covenant.org/version/1/4/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Contributing to Uber's Android Template\n=======================\n\nUber welcomes contributions of all kinds and sizes. This includes everything from from simple bug reports to large features.\n\nWorkflow\n--------\n\nWe love GitHub issues!\n\nFor small feature requests, an issue first proposing it for discussion or demo implementation in a PR suffice.\n\nFor big features, please open an issue so that we can agree on the direction, and hopefully avoid investing a lot of time on a feature that might need reworking.\n\nSmall pull requests for things like typos, bug fixes, etc are always welcome.\n\nDOs and DON'Ts\n--------------\n\n* DO follow our [coding style](https://github.com/uber/java-code-styles) \n* DO include tests when adding new features. When fixing bugs, start with adding a test that highlights how the current behavior is broken.\n* DO keep the discussions focused. When a new or related topic comes up it's often better to create new issue than to side track the discussion.\n\n* DON'T submit PRs that alter licensing related files or headers. If you believe there's a problem with them, file an issue and we'll be happy to discuss it.\n\nGuiding Principles\n------------------\n\n* We allow anyone to participate in our projects. Tasks can be carried out by anyone that demonstrates the capability to complete them\n* Always be respectful of one another. Assume the best in others and act with empathy at all times\n* Collaborate closely with individuals maintaining the project or experienced users. Getting ideas out in the open and seeing a proposal before it's a pull request helps reduce redundancy and ensures we're all connected to the decision making process\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.md",
    "content": "# Artist [![Build Status](https://travis-ci.org/uber/artist.svg?branch=master)](https://travis-ci.org/uber/artist)\n\n\nAs Android apps grow, providing common features and consistent functionality across Views becomes challenging. Typically, this results in copy-pasting features across views, monolithic classes, or complicated inheritance trees. Artist is a highly-extensible platform for creating and maintaining an app’s base set of Android views.\n\n## Overview\n\nArtist is a Gradle plugin written in Kotlin that generates a base set of Android `View`s. Artist-generated views are created using a stencil and trait system. Each view type is declared with a single stencil, which is comprised of a set of traits. All of this comes together to create an easily maintainable system of stencils and traits.\n\n*Stencils*: A `Stencil` defines a View class to be generated. Each `Stencil` has some properties that can be configured and declares a set of traits they exhibit.\n\n*Traits*: A `Trait` defines the new functionality that should be added to a view. It is a hook into the `Stencil`’s codegen process that is called during each `Stencil`’s generation. It is responsible for generating the code that implements `Trait`'s functionality. This could be used to do things like add automatic view analytics to every view or add first-party support for RxBinding APIs (clicks, attach events, visibility changes, etc.) on all your views. \n\nA simple `Trait` that adds visibility helper methods would look like:\n\n```kotlin\n@AutoService(JavaTrait::class)\nclass VisibilityTrait : JavaTrait {\n  override fun generateFor(type: Builder, initMethod: MethodSpec.Builder, rClass: ClassName, baseType: String) {\n    arrayOf(\"visible\", \"invisible\", \"gone\")\n        .forEach { type.addMethod(createVisibilityConvenienceMethod(it)) }\n  }\n\n  private fun createVisibilityConvenienceMethod(type: String): MethodSpec {\n    return MethodSpec.methodBuilder(\"is${type.capitalize()}\")\n        .addModifiers(Modifier.PUBLIC)\n        .returns(TypeName.BOOLEAN)\n        .addStatement(\"return getVisibility() == \\$T.${type.toUpperCase()}\", TypeNames.Android.View)\n        .build()\n  }\n}\n```\n\nA simple `ViewStencil` to generate a `Switch` with visibility helper methods would look like:\n\n```kotlin\nclass SwitchStencil : JavaViewStencil(\n    extendedType = \"android.support.v7.widget.SwitchCompat\",\n    constructorCount = 3,\n    defaultAttrRes = \"switchStyle\",\n    addedTraits = VisibilityTrait::class.java) {\n  \n  override fun name() = \"MySwitch\"\n}\n```\n\nFinally leaving you with a generated view like this:\n\n```java\npublic class MySwitch extends SwitchCompat {\n  // Constructors\n  \n  // protected init method - provided in every stencil\n  \n  public boolean isVisible() {\n    return getVisibility() == View.VISIBLE;\n  }\n  \n  public boolean isGone() {\n    return getVisibility() == View.GONE;\n  }\n  \n  public boolean isInvisible() {\n    return getVisibility() == View.INVISIBLE;\n  }\n}\n```\n\nThis may look like a lot of boilerplate for simple helpers, but it scales quite well when you want to have these methods on _all_ your base views.\n\n## Motivation\n\n#### Common Façade\n\nEverything is behind the façade of commonly named classes, basically \"[YOUR_PREFIX]ViewName\". This allows you to push as much functionality as you want behind them whilst not changing the front facing entry point. Things we can push behind them include new functionality, other base classes, framework bug fixes, etc.\n\n#### Sane, simple maintainability\n\nThe stencil and trait system ensures that base views are defined in one place and that extra functionality is divided up into single-focus traits.\n\n#### Reactive Semantics\n\nArtist-generated views can have [RxBinding](https://github.com/JakeWharton/RxBinding) APIs as first class citizens in their public APIs. In a increasingly reactive world, this gracefully bridges common UI listener interactions to RxJava streams. This can optionally be brought in via the `artist-traits-rx` module.\n\n#### Intelligence\n\nArtist-generated views have deep internal knowledge of their internal state and interactions. This gives you flexibility to do a number of interesting, contextual actions under the hood.\n\n*Automatic Instrumentation*: Artist-generated views know when they're being attached, changed to visible, clicked, etc. This allows you to do automatic instrumentation of impressions and taps in views when they occur, provided the developer has provided an ID. You can also detect and signal a developer if an ID is missing where there should be one.\n\n*Accessibility*: This intelligence gives you enough insight into the state of the view hierarchy to make accessibility a first class citizen in the daily development cycle. Artist-generated views can intelligently infer if there are content description errors associated with them, and signal them to developers in the apps.\n\nFor more examples of things you can do with Artist, check out the [Recipes](https://github.com/uber/artist/wiki/Recipes) wiki page.\n\n## Usage\n\n#### Create the Provider module\n- Create a new plain Java/Kotlin module (non-Android)\n- Add Artist dependencies (API, Traits, Traits-Rx)\n\n#### Implement the Stencil Provider\n- Create a class that implements `JavaViewStencilProvider`\n- Annotate your class with `@AutoService(JavaViewStencilProvider::class)`\n\n#### Implement Custom Traits (Optional)\n- If you have custom traits, then create classes that implement `JavaTrait`\n- Annotate those classes with `@AutoService(JavaTrait::class)`\n\n#### Add Provider module to Plugin Classpath\n_Option #1_\n\nIf your provider module is in it's own project, then you can add the JAR to the buildscript classpath in your main project's root `build.gradle` like:\n\n```groovy\nbuildscript {\n  dependencies {\n    classpath <include for your jar>\n  }\n}\n```\n\n_Option #2_\n\nOtherwise, if your provider module is in your primary project, then in order for Artist to find the classes on the plugin classpath during code generation, we must leverage Gradle's `buildSrc`. We use this project within your project to build the classes that will be added to the plugin classpath. This will run before your primary project is built.\n\n- Create a dir at root of project named `buildSrc`\n- Navigate to `buildSrc` and add a relative symlink to the provider module `cd $PROJECT_ROOT/buildSrc; ln -s ../path/to/provider/module/root custom-artist-providers`\n- Create a `settings.gradle` in `buildSrc` and add `include :custom-artist-providers`\n- Update the `build.gradle` for the `buildSrc` project to ensure that the `custom-artist-providers` module is added the buildScript classpath so it is available to the Artist plugin:\n\n```groovy\nsubprojects { subproject ->\n    if (subproject.buildFile.exists()) {\n        repositories {\n            jcenter()\n            google()\n        }\n\n        rootProject.dependencies {\n            runtime project(path)\n        }\n    }\n    subproject.afterEvaluate {\n        // Disable useless tasks in buildSrc\n        if (subproject.plugins.hasPlugin(\"kotlin\")) {\n            subproject.tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {\n                kotlinOptions.suppressWarnings = true\n            }\n        }\n\n        subproject.tasks.findAll {\n            it.name.toLowerCase().contains(\"test\") ||\n                it.name.toLowerCase().contains(\"lint\") ||\n                it.name.toLowerCase().contains(\"checkstyle\") }.each {\n            it.enabled = false\n        }\n    }\n}\n```\n\n#### Use the Generated Views\nThe [generated views](https://github.com/uber/artist/tree/master/sample/demo/java) will be added to the library's source files. They can then be consumed as regular views. To add even more consistency, you can write a lint rule or ErrorProne check to ensure that all `View` subclasses use your Artist-generated views.\n\n## Further examples\n\nThe set of `JavaViewStencil`s that Artist should process are provided via the `JavaViewStencilProvider`. The [sample's ViewStencilProvider](https://github.com/uber/artist/blob/master/sample/providers/src/main/java/com/uber/artist/myproviders/SampleViewStencilProvider.java) would configure Artist to generate [these Views](https://github.com/uber/artist/tree/master/sample/library/build/generated/source/artist/release/com/uber/artist/mylibrary).\n\n## Download\n\nArtist Plugin [![Maven Central](https://img.shields.io/maven-central/v/com.uber.artist/artist.svg)](https://mvnrepository.com/artifact/com.uber.artist/artist)\n```gradle\nclasspath 'com.uber.artist:artist:0.4.9'\n```\n\nArtist API [![Maven Central](https://img.shields.io/maven-central/v/com.uber.artist/artist-api.svg)](https://mvnrepository.com/artifact/com.uber.artist/artist-api)\n```gradle\nclasspath 'com.uber.artist:artist-api:0.4.9'\n```\n\nArtist Traits [![Maven Central](https://img.shields.io/maven-central/v/com.uber.artist/artist-traits.svg)](https://mvnrepository.com/artifact/com.uber.artist/artist-traits)\n```gradle\nclasspath 'com.uber.artist:artist-traits:0.4.9'\n```\n\nArtist Rx Traits [![Maven Central](https://img.shields.io/maven-central/v/com.uber.artist/artist-traits-rx.svg)](https://mvnrepository.com/artifact/com.uber.artist/artist-traits-rx)\n```gradle\nclasspath 'com.uber.artist:artist-traits-rx:0.4.9'\n```\n\n## License\n\n```\nCopyright (C) 2017 Uber Technologies\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n"
  },
  {
    "path": "RELEASING.md",
    "content": "Releasing\n=========\n\n 1. Change the version in `gradle.properties` to a non-SNAPSHOT version.\n 2. Update the `CHANGELOG.md` for the impending release.\n 3. Update the `README.md` with the new version.\n 4. `git commit -am \"Prepare for release X.Y.Z.\"` (where X.Y.Z is the new version)\n 5. `git tag -a X.Y.Z -m \"Version X.Y.Z\"` (where X.Y.Z is the new version)\n 6. `./gradlew clean uploadArchives`\n 7. Update the `gradle.properties` to the next SNAPSHOT version.\n 8. `git commit -am \"Prepare next development version.\"`\n 9. `git push && git push --tags`\n 10. Visit [Sonatype Nexus](https://oss.sonatype.org/) and promote the artifact.\n"
  },
  {
    "path": "artist/build.gradle",
    "content": "apply plugin: \"org.jetbrains.kotlin.jvm\"\n\nsourceCompatibility = JavaVersion.VERSION_1_7\ntargetCompatibility = JavaVersion.VERSION_1_7\n\ndependencies {\n    compileOnly gradleApi()\n\n    implementation deps.build.androidPlugin\n    implementation deps.kotlin.stdLibJdk7\n    implementation project(\":artist-core\")\n}\n\nif (rootProject.projectDir.name != \"buildSrc\") {\n    apply from: rootProject.file('gradle/gradle-mvn-push.gradle')\n}\n"
  },
  {
    "path": "artist/gradle.properties",
    "content": "#\n# Copyright (C) 2017. Uber Technologies\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nPOM_NAME=artist\nPOM_ARTIFACT_ID=artist\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "artist/src/main/kotlin/com/uber/artist/ArtistExtension.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist\n\nclass ArtistExtension {\n\n  /**\n   * Optional override of the package name for the generated views. Defaults to variant.applicationId\n   */\n  var viewPackageName: String? = null\n\n  /**\n   * Optional override of the consuming module's package name. Defaults to variant.applicationId\n   */\n  var rPackageName: String? = null\n\n  /**\n   * Optional fully qualified class name for an interface that all generated views should be marked as implementing\n   */\n  var interfaceClassName: String? = null\n\n  /**\n   * Optional prefix to append to the beginning of each generated view's name.\n   */\n  var viewNamePrefix: String = \"\"\n\n  /**\n   * Optional setting to control whether the source is formatted with Google Java Format. Defaults to true.\n   */\n  var formatSource: Boolean = true\n\n  /**\n   * Optional setting to control whether the source is generated in Java or Kotlin. Defaults to false for Java.\n   */\n  var generateKotlin: Boolean = false\n}\n"
  },
  {
    "path": "artist/src/main/kotlin/com/uber/artist/ArtistPlugin.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.uber.artist\n\nimport com.android.build.gradle.AppExtension\nimport com.android.build.gradle.AppPlugin\nimport com.android.build.gradle.LibraryExtension\nimport com.android.build.gradle.LibraryPlugin\nimport com.android.build.gradle.api.BaseVariant\nimport com.uber.artist.internal.util.resolveVariantOutputDir\nimport org.gradle.api.DomainObjectSet\nimport org.gradle.api.Plugin\nimport org.gradle.api.Project\n\nclass ArtistPlugin : Plugin<Project> {\n\n  companion object {\n    private const val ARTIST = \"artist\"\n  }\n\n  private val artistExtension = ArtistExtension()\n\n  override fun apply(project: Project) {\n    project.extensions.add(ARTIST, artistExtension)\n    project.afterEvaluate {\n      project.plugins.all {\n        when (it) {\n          is AppPlugin -> with(project.extensions.getByType(AppExtension::class.java)) {\n            configureAndroid(project, applicationVariants)\n          }\n          is LibraryPlugin -> with(project.extensions.getByType(LibraryExtension::class.java)) {\n            configureAndroid(project, libraryVariants)\n          }\n        }\n      }\n    }\n  }\n\n  private fun <T : BaseVariant> configureAndroid(\n      project: Project,\n      variants: DomainObjectSet<T>) {\n    variants.all { variant ->\n      val outputDir = resolveVariantOutputDir(project, variant, ARTIST)\n      val artistTask = project.tasks.create(\n          \"generate${variant.name.capitalize()}Views\", ArtistTask::class.java)\n          .apply {\n            group = ARTIST\n            outputDirectory = outputDir\n            description = \"Generate ${variant.name} base views.\"\n            viewPackageName = artistExtension.viewPackageName ?: variant.applicationId\n            rPackageName = artistExtension.rPackageName ?: (artistExtension.viewPackageName ?: variant.applicationId)\n            superinterfaceClassName = artistExtension.interfaceClassName\n            viewNamePrefix = artistExtension.viewNamePrefix\n            formatSource = artistExtension.formatSource\n            generateKotlin = artistExtension.generateKotlin\n          }\n      artistTask.outputs.dir(outputDir)\n\n      if (artistExtension.generateKotlin) {\n        val kotlinCompileTask = project.tasks.findByName(\"compile${variant.name.capitalize()}Kotlin\")\n        if (kotlinCompileTask != null) {\n          kotlinCompileTask.dependsOn(artistTask)\n        }\n      }\n\n      variant.registerJavaGeneratingTask(artistTask, artistTask.outputDirectory)\n    }\n  }\n}\n"
  },
  {
    "path": "artist/src/main/kotlin/com/uber/artist/ArtistTask.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist\n\nimport org.gradle.api.DefaultTask\nimport org.gradle.api.tasks.Input\nimport org.gradle.api.tasks.TaskAction\nimport org.gradle.api.tasks.incremental.IncrementalTaskInputs\nimport java.io.File\n\nopen class ArtistTask : DefaultTask() {\n\n  @Input\n  lateinit var outputDirectory: File\n\n  @Input\n  lateinit var viewPackageName: String\n\n  @Input\n  lateinit var rPackageName: String\n\n  @Input\n  var superinterfaceClassName: String? = null\n\n  @Input\n  var viewNamePrefix: String = \"\"\n\n  @Input\n  var formatSource: Boolean = true\n\n  @Input\n  var generateKotlin: Boolean = false\n\n  @TaskAction\n  fun execute(inputs: IncrementalTaskInputs) {\n    generateViewsFor(\n        outputDirectory,\n        viewPackageName,\n        rPackageName,\n        superinterfaceClassName,\n        viewNamePrefix,\n        formatSource,\n        generateKotlin\n    )\n  }\n}\n"
  },
  {
    "path": "artist/src/main/kotlin/com/uber/artist/internal/util/Util.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.internal.util\n\nimport com.android.build.gradle.api.BaseVariant\nimport org.gradle.api.Project\nimport java.io.File\n\nfun resolveVariantOutputDir(project: Project, variant: BaseVariant, plugin: String): File = project.file(\n    \"${project.projectDir}/build/generated/source/$plugin/${variant.flavorName}/${variant.buildType.name}\".sanitize()\n)\n\nfun String.sanitize(): String = replace('/', File.separatorChar)\n"
  },
  {
    "path": "artist/src/main/resources/META-INF/gradle-plugins/com.uber.artist.properties",
    "content": "implementation-class=com.uber.artist.ArtistPlugin\n"
  },
  {
    "path": "artist-api/build.gradle",
    "content": "apply plugin: \"java-library\"\napply plugin: \"org.jetbrains.kotlin.jvm\"\n\nsourceCompatibility = JavaVersion.VERSION_1_7\ntargetCompatibility = JavaVersion.VERSION_1_7\n\ndependencies {\n    api deps.apt.javapoet\n    api deps.apt.kotlinPoet\n\n    implementation deps.kotlin.stdLibJdk7\n}\n\nif (rootProject.projectDir.name != \"buildSrc\") {\n    apply from: rootProject.file('gradle/gradle-mvn-push.gradle')\n}\n"
  },
  {
    "path": "artist-api/gradle.properties",
    "content": "#\n# Copyright (C) 2017. Uber Technologies\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nPOM_NAME=artist-api\nPOM_ARTIFACT_ID=artist-api\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/JavaTrait.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeSpec\n\n/**\n * A [JavaTrait] defines code that must be generated in order for a [View] to receive new functionality.\n * Each [JavaTrait] can be declared by multiple [ViewStencil]s, and generate otherwise duplicate code across all views\n * that exhibit them. Common examples include clicks, attach events, visibility changes, etc. They are a hook into the\n * [ViewStencil]’s code gen process that are called during each [ViewStencil]’s generation.\n */\ninterface JavaTrait : Trait<TypeSpec.Builder, MethodSpec.Builder, ClassName> {\n  override fun generateFor(type: TypeSpec.Builder, initMethod: MethodSpec.Builder, rClass: ClassName, sourceType: String)\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/JavaTraitService.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\nimport java.util.ServiceLoader\n\nclass JavaTraitService private constructor() : TraitService<JavaTrait> {\n\n  private val serviceLoader = ServiceLoader.load(JavaTrait::class.java)\n\n  /**\n   * Gets the [Trait] implementations loaded.\n   *\n   * @return The located [Trait]s.\n   */\n  override fun get(): Set<JavaTrait> {\n    val traits = LinkedHashSet<JavaTrait>()\n    serviceLoader.iterator()\n        .forEach { traits.add(it) }\n    return traits\n  }\n\n  companion object {\n    fun newInstance(): JavaTraitService {\n      return JavaTraitService()\n    }\n  }\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/JavaTypeNames.kt",
    "content": "@file:Suppress(\"PLATFORM_CLASS_MAPPED_TO_KOTLIN\")\n\n/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\nimport com.squareup.javapoet.ClassName\n\nclass JavaTypeNames {\n  class Android {\n    companion object {\n      val AccessibilityEvent: ClassName = ClassName.get(\"android.view.accessibility\", \"AccessibilityEvent\")\n      val AccessibilityNodeInfo: ClassName = ClassName.get(\"android.view.accessibility\", \"AccessibilityNodeInfo\")\n      val AttributeSet: ClassName = ClassName.get(\"android.util\", \"AttributeSet\")\n      val Canvas: ClassName = ClassName.get(\"android.graphics\", \"Canvas\")\n      val Context: ClassName = ClassName.get(\"android.content\", \"Context\")\n      val Drawable: ClassName = ClassName.get(\"android.graphics.drawable\", \"Drawable\")\n      val Gravity: ClassName = ClassName.get(\"android.view\", \"Gravity\")\n      val GravityCompat: ClassName = ClassName.get(\"androidx.core.view\", \"GravityCompat\")\n      val MenuItem: ClassName = ClassName.get(\"android.view\", \"MenuItem\")\n      val Rect: ClassName = ClassName.get(\"android.graphics\", \"Rect\")\n      val TabLayout: ClassName = ClassName.get(\"com.google.android.material.tabs\", \"TabLayout\")\n      val TabLayoutTab: ClassName = TabLayout.nestedClass(\"Tab\")\n      val TypedArray: ClassName = ClassName.get(\"android.content.res\", \"TypedArray\")\n      val View: ClassName = ClassName.get(\"android.view\", \"View\")\n      val MotionEvent: ClassName = ClassName.get(\"android.view\", \"MotionEvent\")\n    }\n  }\n\n  class Annotations {\n    companion object {\n      val AttrRes: ClassName = ClassName.get(\"androidx.annotation\", \"AttrRes\")\n      val CallSuper: ClassName = ClassName.get(\"androidx.annotation\", \"CallSuper\")\n      val IdRes: ClassName = ClassName.get(\"androidx.annotation\", \"IdRes\")\n      val Nullable: ClassName = ClassName.get(\"androidx.annotation\", \"Nullable\")\n      val StyleRes: ClassName = ClassName.get(\"androidx.annotation\", \"StyleRes\")\n      val TargetApi: ClassName = ClassName.get(\"android.annotation\", \"TargetApi\")\n      val VisibleForTesting: ClassName = ClassName.get(\"androidx.annotation\", \"VisibleForTesting\")\n    }\n  }\n\n  class Java {\n    companion object {\n      val Map: ClassName = ClassName.get(java.util.Map::class.java)\n      val String: ClassName = ClassName.get(java.lang.String::class.java)\n    }\n  }\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/JavaViewStencil.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.CodeBlock\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeSpec\n\nopen class JavaViewStencil(\n    extendedType: String,\n    constructorCount: Int = 4,\n    defaultAttrRes: String? = null,\n    vararg addedTraits: Class<out JavaTrait> = emptyArray()\n) : ViewStencil<TypeSpec.Builder, MethodSpec.Builder, ClassName, CodeBlock>(\n    extendedType, constructorCount, defaultAttrRes, addedTraits.toSet()\n) {\n\n  val sourceType = ClassName.get(\n      extendedType.substringBeforeLast('.'),\n      extendedType.split('.').last()\n  )\n\n  /**\n   * Hook for when attributes are being pulled out of the attribute set.\n   * Can safely assume the following values exist:\n   *   - context: Context\n   *   - attrs: AttributeSet\n   *   - defStyleAttr: int\n   *   - a: TypedArray\n   *\n   * Should *not* recycle `a`. Safe to assume `a` is null-checked before code would execute.\n   */\n  override fun attrsHook(type: TypeSpec.Builder, initMethod: MethodSpec.Builder): CodeBlock? = null\n\n  /**\n   * Hook for implementing the `init()` method.\n   */\n  override fun initMethodHook(type: TypeSpec.Builder, initMethod: MethodSpec.Builder) {}\n\n  /**\n   * Hook for the type builder implementation.\n   */\n  override fun typeHook(type: TypeSpec.Builder) {}\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/JavaViewStencilProvider.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\ninterface JavaViewStencilProvider : ViewStencilProvider<JavaViewStencil, JavaTrait> {\n\n  /**\n   * Provide a set of [ViewStencil]s to be used during code generation.\n   *\n   * @return The set of [ViewStencil]s.\n   */\n  override fun stencils(): Set<JavaViewStencil>\n\n  /**\n   * Provide a set of [Trait] classes that should be applied to all [ViewStencil]s.\n   *\n   * @return The set of [Trait] classes.\n   */\n  override fun globalTraits(): Set<Class<out JavaTrait>>\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/JavaViewStencilService.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\nimport java.util.ServiceLoader\n\nclass JavaViewStencilService private constructor() : ViewStencilService<JavaViewStencil, JavaTrait> {\n\n  private val serviceLoader = ServiceLoader.load(JavaViewStencilProvider::class.java)\n\n  /**\n   * Gets the [ViewStencil] implementations loaded.\n   *\n   * @return The located [ViewStencil]s.\n   */\n  override fun getStencils(): Set<JavaViewStencil> {\n    val stencils = LinkedHashSet<JavaViewStencil>()\n    serviceLoader.iterator()\n        .forEach { stencils.addAll(it.stencils()) }\n    return stencils\n  }\n\n  /**\n   * Gets the [Trait] implementations that should be applied to every [ViewStencil].\n   *\n   * @return The located global [Trait]s.\n   */\n  override fun getGlobalTraits(): Set<Class<out JavaTrait>> {\n    val globalTraits = LinkedHashSet<Class<out JavaTrait>>()\n    serviceLoader.iterator()\n        .forEach { globalTraits.addAll(it.globalTraits()) }\n    return globalTraits\n  }\n\n  companion object {\n    fun newInstance(): JavaViewStencilService {\n      return JavaViewStencilService()\n    }\n  }\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/KotlinTrait.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.FunSpec\nimport com.squareup.kotlinpoet.TypeSpec\n\n/**\n * A [KotlinTrait] defines code that must be generated in order for a [View] to receive new functionality.\n * Each [KotlinTrait] can be declared by multiple [ViewStencil]s, and generate otherwise duplicate code across all views\n * that exhibit them. Common examples include clicks, attach events, visibility changes, etc. They are a hook into the\n * [ViewStencil]’s code gen process that are called during each [ViewStencil]’s generation.\n */\ninterface KotlinTrait : Trait<TypeSpec.Builder, FunSpec.Builder, ClassName> {\n  override fun generateFor(type: TypeSpec.Builder, initMethod: FunSpec.Builder, rClass: ClassName, sourceType: String)\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/KotlinTraitService.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\nimport java.util.ServiceLoader\n\nclass KotlinTraitService private constructor() : TraitService<KotlinTrait> {\n\n  private val serviceLoader = ServiceLoader.load(KotlinTrait::class.java)\n\n  /**\n   * Gets the [Trait] implementations loaded.\n   *\n   * @return The located [Trait]s.\n   */\n  override fun get(): Set<KotlinTrait> {\n    val traits = LinkedHashSet<KotlinTrait>()\n    serviceLoader.iterator()\n        .forEach { traits.add(it) }\n    return traits\n  }\n\n  companion object {\n    fun newInstance(): KotlinTraitService {\n      return KotlinTraitService()\n    }\n  }\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/KotlinTypeNames.kt",
    "content": "@file:Suppress(\"PLATFORM_CLASS_MAPPED_TO_KOTLIN\")\n\n/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.asClassName\n\nclass KotlinTypeNames {\n  class Android {\n    companion object {\n      val AccessibilityEvent: ClassName = ClassName(\"android.view.accessibility\", \"AccessibilityEvent\")\n      val AccessibilityNodeInfo: ClassName = ClassName(\"android.view.accessibility\", \"AccessibilityNodeInfo\")\n      val AttributeSet: ClassName = ClassName(\"android.util\", \"AttributeSet\")\n      val Canvas: ClassName = ClassName(\"android.graphics\", \"Canvas\")\n      val Context: ClassName = ClassName(\"android.content\", \"Context\")\n      val Drawable: ClassName = ClassName(\"android.graphics.drawable\", \"Drawable\")\n      val Gravity: ClassName = ClassName(\"android.view\", \"Gravity\")\n      val GravityCompat: ClassName = ClassName(\"androidx.core.view\", \"GravityCompat\")\n      val MenuItem: ClassName = ClassName(\"android.view\", \"MenuItem\")\n      val Rect: ClassName = ClassName(\"android.graphics\", \"Rect\")\n      val TabLayout: ClassName = ClassName(\"com.google.android.material.tabs\", \"TabLayout\")\n      val TabLayoutTab: ClassName = TabLayout.nestedClass(\"Tab\")\n      val TypedArray: ClassName = ClassName(\"android.content.res\", \"TypedArray\")\n      val View: ClassName = ClassName(\"android.view\", \"View\")\n      val MotionEvent: ClassName = ClassName(\"android.view\", \"MotionEvent\")\n    }\n  }\n\n  class Annotations {\n    companion object {\n      val AttrRes: ClassName = ClassName(\"androidx.annotation\", \"AttrRes\")\n      val CallSuper: ClassName = ClassName(\"androidx.annotation\", \"CallSuper\")\n      val IdRes: ClassName = ClassName(\"androidx.annotation\", \"IdRes\")\n      val StyleRes: ClassName = ClassName(\"androidx.annotation\", \"StyleRes\")\n      val TargetApi: ClassName = ClassName(\"android.annotation\", \"TargetApi\")\n      val VisibleForTesting: ClassName = ClassName(\"androidx.annotation\", \"VisibleForTesting\")\n    }\n  }\n\n  class Java {\n    companion object {\n      val Map: ClassName = java.util.Map::class.asClassName()\n      val Object: ClassName = java.lang.Object::class.asClassName()\n      val String: ClassName = java.lang.String::class.asClassName()\n    }\n  }\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/KotlinViewStencil.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\nimport AliasTypeNames.Rx.Companion.rxExtensionFunctionToAlias\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.CodeBlock\nimport com.squareup.kotlinpoet.FunSpec\nimport com.squareup.kotlinpoet.TypeSpec\n\nopen class KotlinViewStencil(\n    extendedType: String,\n    constructorCount: Int = 4,\n    defaultAttrRes: String? = null,\n    vararg addedTraits: Class<out KotlinTrait> = emptyArray()\n) : ViewStencil<TypeSpec.Builder, FunSpec.Builder, ClassName, CodeBlock>(\n    extendedType, constructorCount, defaultAttrRes, addedTraits.toSet()\n) {\n\n  val sourceType = ClassName(\n      extendedType.substringBeforeLast('.'),\n      extendedType.split('.').last()\n  )\n\n  /**\n   * Hook for when attributes are being pulled out of the attribute set.\n   * Can safely assume the following values exist:\n   *   - context: Context\n   *   - attrs: AttributeSet\n   *   - defStyleAttr: int\n   *   - a: TypedArray\n   *\n   * Should *not* recycle `a`. Safe to assume `a` is null-checked before code would execute.\n   */\n  override fun attrsHook(type: TypeSpec.Builder, initMethod: FunSpec.Builder): CodeBlock? = null\n\n  /**\n   * Hook for implementing the `init()` method.\n   */\n  override fun initMethodHook(type: TypeSpec.Builder, initMethod: FunSpec.Builder) {}\n\n  /**\n   * Hook for the type builder implementation.\n   */\n  override fun typeHook(type: TypeSpec.Builder) {}\n\n  /**\n   * In an attempt to allow for newly created extension functions to co-exist alongside legacy\n   * code and not conflict in the naming, especially for the migration from rxbinding2 to\n   * rxbinding3, we provide an ability for stencils to provide their own aliases.\n   *\n   * This corresponds to the syntax import x as y where x is the extension function and y is the\n   * alias\n   */\n  fun extensionFunctionToAlias(): Map<AliasTypeNames.Rx.Companion.ExtensionFunctionAlias, String> {\n    return rxExtensionFunctionToAlias\n  }\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/KotlinViewStencilProvider.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\ninterface KotlinViewStencilProvider : ViewStencilProvider<KotlinViewStencil, KotlinTrait> {\n\n  /**\n   * Provide a set of [ViewStencil]s to be used during code generation.\n   *\n   * @return The set of [ViewStencil]s.\n   */\n  override fun stencils(): Set<KotlinViewStencil>\n\n  /**\n   * Provide a set of [Trait] classes that should be applied to all [ViewStencil]s.\n   *\n   * @return The set of [Trait] classes.\n   */\n  override fun globalTraits(): Set<Class<out KotlinTrait>>\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/KotlinViewStencilService.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\nimport java.util.ServiceLoader\n\nclass KotlinViewStencilService private constructor() : ViewStencilService<KotlinViewStencil, KotlinTrait> {\n\n  private val serviceLoader = ServiceLoader.load(KotlinViewStencilProvider::class.java)\n\n  /**\n   * Gets the [ViewStencil] implementations loaded.\n   *\n   * @return The located [ViewStencil]s.\n   */\n  override fun getStencils(): Set<KotlinViewStencil> {\n    val stencils = LinkedHashSet<KotlinViewStencil>()\n    serviceLoader.iterator()\n        .forEach { stencils.addAll(it.stencils()) }\n    return stencils\n  }\n\n  /**\n   * Gets the [Trait] implementations that should be applied to every [ViewStencil].\n   *\n   * @return The located global [Trait]s.\n   */\n  override fun getGlobalTraits(): Set<Class<out KotlinTrait>> {\n    val globalTraits = LinkedHashSet<Class<out KotlinTrait>>()\n    serviceLoader.iterator()\n        .forEach { globalTraits.addAll(it.globalTraits()) }\n    return globalTraits\n  }\n\n  companion object {\n    fun newInstance(): KotlinViewStencilService {\n      return KotlinViewStencilService()\n    }\n  }\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/Trait.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\n/**\n * A [Trait] defines code that must be generated in order for a [View] to receive new functionality.\n * Each [Trait] can be declared by multiple [ViewStencil]s, and generate otherwise duplicate code across all views\n * that exhibit them. Common examples include clicks, attach events, visibility changes, etc. They are a hook into the\n * [ViewStencil]’s code gen process that are called during each [ViewStencil]’s generation.\n */\ninterface Trait<OutputType, FunType, ClassType> {\n  fun generateFor(type: OutputType, initMethod: FunType, rClass: ClassType, sourceType: String)\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/TraitService.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\ninterface TraitService<TraitType> {\n\n  /**\n   * Gets the [Trait] implementations loaded.\n   *\n   * @return The located [Trait]s.\n   */\n  fun get(): Set<TraitType>\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/TypeNames.kt",
    "content": "@file:Suppress(\"PLATFORM_CLASS_MAPPED_TO_KOTLIN\")\n\n/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\nimport com.squareup.javapoet.ClassName\n\nclass TypeNames {\n  class Android {\n    companion object {\n      val AccessibilityEvent: ClassName = ClassName.get(\"android.view.accessibility\", \"AccessibilityEvent\")\n      val AccessibilityNodeInfo: ClassName = ClassName.get(\"android.view.accessibility\", \"AccessibilityNodeInfo\")\n      val AttributeSet: ClassName = ClassName.get(\"android.util\", \"AttributeSet\")\n      val Canvas: ClassName = ClassName.get(\"android.graphics\", \"Canvas\")\n      val Context: ClassName = ClassName.get(\"android.content\", \"Context\")\n      val Drawable: ClassName = ClassName.get(\"android.graphics.drawable\", \"Drawable\")\n      val Gravity: ClassName = ClassName.get(\"android.view\", \"Gravity\")\n      val GravityCompat: ClassName = ClassName.get(\"androidx.core.view\", \"GravityCompat\")\n      val MenuItem: ClassName = ClassName.get(\"android.view\", \"MenuItem\")\n      val Rect: ClassName = ClassName.get(\"android.graphics\", \"Rect\")\n      val TabLayout: ClassName = ClassName.get(\"com.google.android.material.tabs\", \"TabLayout\")\n      val TabLayoutTab: ClassName = TabLayout.nestedClass(\"Tab\")\n      val TypedArray: ClassName = ClassName.get(\"android.content.res\", \"TypedArray\")\n      val View: ClassName = ClassName.get(\"android.view\", \"View\")\n      val MotionEvent: ClassName = ClassName.get(\"android.view\", \"MotionEvent\")\n    }\n  }\n\n  class Annotations {\n    companion object {\n      val AttrRes: ClassName = ClassName.get(\"androidx.annotation\", \"AttrRes\")\n      val CallSuper: ClassName = ClassName.get(\"androidx.annotation\", \"CallSuper\")\n      val IdRes: ClassName = ClassName.get(\"androidx.annotation\", \"IdRes\")\n      val Nullable: ClassName = ClassName.get(\"androidx.annotation\", \"Nullable\")\n      val StyleRes: ClassName = ClassName.get(\"androidx.annotation\", \"StyleRes\")\n      val TargetApi: ClassName = ClassName.get(\"android.annotation\", \"TargetApi\")\n      val VisibleForTesting: ClassName = ClassName.get(\"androidx.annotation\", \"VisibleForTesting\")\n    }\n  }\n\n  class Java {\n    companion object {\n      val Map: ClassName = ClassName.get(java.util.Map::class.java)\n      val String: ClassName = ClassName.get(java.lang.String::class.java)\n    }\n  }\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/ViewStencil.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\nabstract class ViewStencil<OutputType, FunType, ClassName, CodeBlock>(\n    val extendedType: String,\n    val constructorCount: Int = 4,\n    val defaultAttrRes: String? = null,\n    protected val addedTraits: Set<Class<out Trait<*, *, *>>>\n) {\n\n  val globalTraits = mutableSetOf<Class<out Trait<*, *, *>>>()\n  var namePrefix: String = \"\"\n\n  open fun traits(): Set<Class<out Trait<*, *, *>>> = globalTraits.plus(addedTraits)\n\n  /**\n   * The name of the view class.\n   */\n  open fun name(): String {\n    val sourceName = extendedType.split('.').last()\n    return \"$namePrefix${sourceName.removePrefix(\"AppCompat\")}\"\n  }\n\n  /**\n   * Hook for when attributes are being pulled out of the attribute set.\n   * Can safely assume the following values exist:\n   *   - context: Context\n   *   - attrs: AttributeSet\n   *   - defStyleAttr: int\n   *   - a: TypedArray\n   *\n   * Should *not* recycle `a`. Safe to assume `a` is null-checked before code would execute.\n   */\n  abstract fun attrsHook(type: OutputType, initMethod: FunType): CodeBlock?\n\n  /**\n   * Hook for implementing the `init()` method.\n   */\n  abstract fun initMethodHook(type: OutputType, initMethod: FunType)\n\n  /**\n   * Hook for the type builder implementation.\n   */\n  abstract fun typeHook(type: OutputType)\n\n  fun setGlobalTraits(traits: Set<Class<out Trait<*, *, *>>>) {\n    globalTraits.addAll(traits)\n  }\n\n  fun setPrefix(namePrefix: String) {\n    this.namePrefix = namePrefix\n  }\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/ViewStencilProvider.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\ninterface ViewStencilProvider<ViewStencilType, TraitType> {\n\n  /**\n   * Provide a set of [ViewStencil]s to be used during code generation.\n   *\n   * @return The set of [ViewStencil]s.\n   */\n  fun stencils(): Set<ViewStencilType>\n\n  /**\n   * Provide a set of [Trait] classes that should be applied to all [ViewStencil]s.\n   *\n   * @return The set of [Trait] classes.\n   */\n  fun globalTraits(): Set<Class<out TraitType>>\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/ViewStencilService.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.api\n\ninterface ViewStencilService<ViewStencilType, TraitType> {\n\n  /**\n   * Gets the [ViewStencil] implementations loaded.\n   *\n   * @return The located [ViewStencil]s.\n   */\n  fun getStencils(): Set<ViewStencilType>\n\n  /**\n   * Gets the [Trait] implementations that should be applied to every [ViewStencil].\n   *\n   * @return The located global [Trait]s.\n   */\n  fun getGlobalTraits(): Set<Class<out TraitType>>\n}\n"
  },
  {
    "path": "artist-api/src/main/kotlin/com/uber/artist/api/alias/AliasTypeNames.kt",
    "content": "import com.squareup.kotlinpoet.ClassName\n\nclass AliasTypeNames {\n\n  open class Rx {\n    companion object {\n\n      val RecyclerViewScrollEvent = ClassName(\"com.jakewharton.rxbinding3.recyclerview\", \"RecyclerViewScrollEvent\")\n      val RxView = ClassName(\"com.jakewharton.rxbinding3.view\", \"RxView\")\n      val RxCompoundButton = ClassName(\"com.jakewharton.rxbinding3.widget\", \"RxCompoundButton\")\n      val RxNestedScrollView = ClassName(\"com.jakewharton.rxbinding3.core\", \"RxNestedScrollView\")\n      val RxRecyclerView = ClassName(\"com.jakewharton.rxbinding3.recyclerview\", \"RxRecyclerView\")\n      val RxSearchView = ClassName(\"com.jakewharton.rxbinding3.appcompat\", \"RxSearchView\")\n      val RxSeekBar = ClassName(\"com.jakewharton.rxbinding3.widget\", \"RxSeekBar\")\n      val SeekBarChangeEvent = ClassName(\"com.jakewharton.rxbinding3.widget\", \"SeekBarChangeEvent\")\n      val SeekBarProgressChangeEvent = ClassName(\"com.jakewharton.rxbinding3.widget\", \"SeekBarProgressChangeEvent\")\n      val SeekBarStartChangeEvent = ClassName(\"com.jakewharton.rxbinding3.widget\", \"SeekBarStartChangeEvent\")\n      val RxSwipeRefreshLayout = ClassName(\"com.jakewharton.rxbinding3.swiperefreshlayout\", \"RxSwipeRefreshLayout\")\n      val RxTabLayout = ClassName(\"com.jakewharton.rxbinding3.material\", \"RxTabLayout\")\n      val RxTextView = ClassName(\"com.jakewharton.rxbinding3.widget\", \"RxTextView\")\n      val RxToolbar = ClassName(\"com.jakewharton.rxbinding3.appcompat\", \"RxToolbar\")\n      val RxViewPager = ClassName(\"com.jakewharton.rxbinding3.viewpager\", \"RxViewPager\")\n      val RxViewAttachEvent = ClassName(\"com.jakewharton.rxbinding3.view\", \"ViewAttachEvent\")\n      val RxViewAttachAttachedEvent = ClassName(\"com.jakewharton.rxbinding3.view\", \"ViewAttachAttachedEvent\")\n      val RxViewAttachDetachedEvent = ClassName(\"com.jakewharton.rxbinding3.view\", \"ViewAttachDetachedEvent\")\n      val SearchViewQueryTextEvent = ClassName(\"com.jakewharton.rxbinding3.appcompat\", \"SearchViewQueryTextEvent\")\n      val ViewScrollChangeEvent = ClassName(\"com.jakewharton.rxbinding3.view\", \"ViewScrollChangeEvent\")\n\n      data class ExtensionFunctionAlias(\n          val className: ClassName,\n          val methodName: String\n      )\n\n      val list = listOf<ExtensionFunctionAlias>(\n          ExtensionFunctionAlias(RxToolbar, \"itemClicks\"),\n          ExtensionFunctionAlias(RxView, \"layoutChanges\"),\n          ExtensionFunctionAlias(RxView, \"clicks\"),\n          ExtensionFunctionAlias(RxView, \"attachEvents\"),\n          ExtensionFunctionAlias(RxView, \"longClicks\"),\n          ExtensionFunctionAlias(RxToolbar, \"navigationClicks\"),\n          ExtensionFunctionAlias(RxView, \"scrollChangeEvents\"),\n          ExtensionFunctionAlias(RxNestedScrollView, \"scrollChangeEvents\"),\n          ExtensionFunctionAlias(RxCompoundButton, \"checkedChanges\"),\n          ExtensionFunctionAlias(RxSwipeRefreshLayout, \"refreshes\"),\n          ExtensionFunctionAlias(RxSeekBar, \"changeEvents\"),\n          ExtensionFunctionAlias(RxTabLayout, \"selections\"),\n          ExtensionFunctionAlias(RxSearchView, \"queryTextChangeEvents\"),\n          ExtensionFunctionAlias(RxTabLayout, \"selections\"),\n          ExtensionFunctionAlias(RxRecyclerView, \"scrollEvents\"),\n          ExtensionFunctionAlias(RxTextView, \"textChanges\"),\n              ExtensionFunctionAlias(RxView, \"attachEvents\")\n      )\n\n      val rxExtensionFunctionToAlias = list.map { it to it.className.simpleName.toLowerCase() + \"_\" + it\n          .methodName.dropLast(4) }.toMap()\n    }\n  }\n}\n"
  },
  {
    "path": "artist-core/build.gradle",
    "content": "apply plugin: \"java-library\"\napply plugin: \"org.jetbrains.kotlin.jvm\"\n\nsourceCompatibility = JavaVersion.VERSION_1_7\ntargetCompatibility = JavaVersion.VERSION_1_7\n\ndependencies {\n    implementation deps.apt.javapoet\n    implementation deps.apt.kotlinPoet\n    implementation deps.build.googleJavaFormatter\n    implementation deps.kotlin.stdLibJdk7\n    implementation project(\":artist-api\")\n\n    // Dont need to run tests in buildSrc\n    if (rootProject.projectDir.name != \"buildSrc\") {\n        testImplementation deps.androidx.annotations\n        testImplementation deps.test.compileTesting\n        testImplementation deps.test.junit\n        testImplementation deps.test.robolectric\n        testImplementation deps.test.truth\n    }\n}\n\nif (rootProject.projectDir.name != \"buildSrc\") {\n    apply from: rootProject.file('gradle/gradle-mvn-push.gradle')\n}\n"
  },
  {
    "path": "artist-core/gradle.properties",
    "content": "#\n# Copyright (C) 2017. Uber Technologies\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nPOM_NAME=artist-core\nPOM_ARTIFACT_ID=artist-core\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "artist-core/src/main/kotlin/com/uber/artist/Artist.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist\n\nimport java.io.File\n\nfun generateViewsFor(\n    outputDir: File,\n    viewPackageName: String,\n    rPackageName: String,\n    superinterfaceClassName: String?,\n    viewNamePrefix: String,\n    formatSource: Boolean,\n    generateKotlin: Boolean = false) {\n  val artistCodeGenerator = if (generateKotlin) KotlinArtistCodeGenerator() else JavaArtistCodeGenerator()\n  artistCodeGenerator.generateViews(outputDir, viewPackageName, rPackageName, superinterfaceClassName, viewNamePrefix, formatSource)\n}\n"
  },
  {
    "path": "artist-core/src/main/kotlin/com/uber/artist/ArtistCodeGenerator.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist\n\nimport com.google.common.annotations.VisibleForTesting\nimport com.uber.artist.api.KotlinViewStencil\nimport com.uber.artist.api.Trait\nimport com.uber.artist.api.ViewStencil\nimport java.io.File\n\nabstract class ArtistCodeGenerator<\n    OutputFileType,\n    OutputType,\n    FunType,\n    ClassName,\n    CodeBlock,\n    ViewStencilType : ViewStencil<OutputType, FunType, ClassName, CodeBlock>,\n    TraitType : Trait<OutputType, FunType, ClassName>> {\n\n  abstract val viewStencils: Set<ViewStencilType>\n  abstract val traits: Set<TraitType>\n  abstract val globalTraits: Set<Class<out TraitType>>\n\n  fun generateViews(\n      outputDir: File,\n      viewPackageName: String,\n      rPackageName: String,\n      superinterfaceClassName: String?,\n      viewNamePrefix: String,\n      formatSource: Boolean\n  ) {\n    generateViewsForStencils(viewStencils, traits, globalTraits, outputDir, viewPackageName, rPackageName, superinterfaceClassName, viewNamePrefix, formatSource)\n  }\n\n  @VisibleForTesting\n  fun generateViewsForStencils(\n      viewStencils: Set<ViewStencilType>,\n      traits: Set<TraitType>,\n      globalTraits: Set<Class<out TraitType>>,\n      outputDir: File,\n      viewPackageName: String,\n      rPackageName: String,\n      superinterfaceClassName: String?,\n      viewNamePrefix: String,\n      formatSource: Boolean) {\n    val traitMap: Map<Class<out TraitType>, TraitType> = traits.associateBy { it.javaClass }\n\n    viewStencils.forEach {\n      it.setGlobalTraits(globalTraits)\n      it.setPrefix(viewNamePrefix)\n\n      val typeSpecBuilder = generateTypeSpecFor(it, rPackageName, traitMap, superinterfaceClassName)\n      val fileSpec = generateFileSpecFor(it, viewPackageName, typeSpecBuilder)\n      if (formatSource) {\n        writeFileWithFormatting(fileSpec, outputDir, typeSpecBuilder, viewPackageName)\n      } else {\n        writeFile(fileSpec, outputDir)\n      }\n    }\n  }\n\n  protected abstract fun generateFileSpecFor(stencil: ViewStencilType, viewPackageName: String, typeSpecBuilder: OutputType): OutputFileType\n\n  protected abstract fun generateTypeSpecFor(\n      stencil: ViewStencilType,\n      rPackageName: String,\n      traitMap: Map<Class<out TraitType>, TraitType>,\n      superinterfaceClassName: String?): OutputType\n\n  protected abstract fun createInitBuilderFor(stencil: ViewStencilType, type: OutputType): FunType\n\n  protected abstract fun generateConstructorsFor(stencil: ViewStencilType, type: OutputType, rClass: ClassName)\n\n  protected abstract fun superinterface(className: String): ClassName\n\n  protected abstract fun writeFile(fileSpec: OutputFileType, outputDir: File)\n\n  protected abstract fun writeFileWithFormatting(fileSpec: OutputFileType, outputDir: File, outputType: OutputType, viewPackageName: String)\n\n  protected fun superConstructorStatement(count: Int): String {\n    when (count) {\n      1 -> return \"super(context)\"\n      2 -> return \"super(context, attrs)\"\n      3 -> return \"super(context, attrs, defStyleAttr)\"\n      4 -> return \"super(context, attrs, defStyleAttr, defStyleRes)\"\n    }\n    throw IllegalArgumentException()\n  }\n\n  protected fun initStatement(count: Int): String {\n    when (count) {\n      1 -> return \"init(context, null, 0, 0)\"\n      2 -> return \"init(context, attrs, 0, 0)\"\n      3 -> return \"init(context, attrs, defStyleAttr, 0)\"\n      4 -> return \"init(context, attrs, defStyleAttr, defStyleRes)\"\n    }\n    throw IllegalArgumentException()\n  }\n}\n"
  },
  {
    "path": "artist-core/src/main/kotlin/com/uber/artist/FormattingFileWriter.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist\n\nimport java.io.File\n\nabstract class FormattingFileWriter<OutputFileType, OutputType> {\n\n  protected val packageSplitRegex = \"\\\\.\".toRegex()\n\n  /**\n   * A rough estimate of the average file size: 80 chars per line, 500 lines.\n   */\n  protected val defaultFileSize = 80 * 500\n\n  /**\n   * A file writer function that formats the code before writing out to the file system.\n   */\n  abstract fun writeWithFormattingTo(directory: File)\n}\n"
  },
  {
    "path": "artist-core/src/main/kotlin/com/uber/artist/JavaArtistCodeGenerator.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist\n\nimport com.squareup.javapoet.AnnotationSpec\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.CodeBlock\nimport com.squareup.javapoet.JavaFile\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.ParameterSpec\nimport com.squareup.javapoet.TypeSpec\nimport com.uber.artist.api.JavaTrait\nimport com.uber.artist.api.JavaTraitService\nimport com.uber.artist.api.JavaViewStencil\nimport com.uber.artist.api.JavaViewStencilService\nimport com.uber.artist.api.TypeNames\nimport java.io.File\nimport javax.lang.model.element.Modifier\n\nclass JavaArtistCodeGenerator : ArtistCodeGenerator<JavaFile, TypeSpec.Builder, MethodSpec.Builder, ClassName, CodeBlock, JavaViewStencil, JavaTrait>() {\n\n  override val viewStencils: Set<JavaViewStencil>\n    get() = JavaViewStencilService.newInstance().getStencils()\n\n  override val traits: Set<JavaTrait>\n    get() = JavaTraitService.newInstance().get()\n\n  override val globalTraits: Set<Class<out JavaTrait>>\n    get() = JavaViewStencilService.newInstance().getGlobalTraits()\n\n  override fun generateFileSpecFor(stencil: JavaViewStencil, viewPackageName: String, typeSpecBuilder: TypeSpec.Builder): JavaFile {\n    return JavaFile.builder(viewPackageName, typeSpecBuilder.build()).build()\n  }\n\n  override fun generateTypeSpecFor(\n      stencil: JavaViewStencil,\n      rPackageName: String,\n      traitMap: Map<Class<out JavaTrait>, JavaTrait>,\n      superinterfaceClassName: String?): TypeSpec.Builder {\n    val rClass = ClassName.get(rPackageName, \"R\")\n    val typeBuilder = TypeSpec.classBuilder(stencil.name())\n        .addModifiers(Modifier.PUBLIC)\n        .superclass(stencil.sourceType)\n\n    superinterfaceClassName?.let { typeBuilder.addSuperinterface(superinterface(superinterfaceClassName)) }\n\n    generateConstructorsFor(stencil, typeBuilder, rClass)\n    val initMethod = createInitBuilderFor(stencil, typeBuilder)\n\n    stencil.traits()\n        .map { traitName -> traitMap[traitName] }\n        .forEach { it?.generateFor(typeBuilder, initMethod, rClass, stencil.name()) }\n\n    typeBuilder.addMethod(initMethod.build())\n    stencil.typeHook(typeBuilder)\n    return typeBuilder\n  }\n\n  override fun createInitBuilderFor(\n      stencil: JavaViewStencil,\n      type: TypeSpec.Builder): MethodSpec.Builder {\n    val initMethod = MethodSpec.methodBuilder(\"init\")\n        .addAnnotation(TypeNames.Annotations.CallSuper)\n        .addModifiers(Modifier.PROTECTED)\n        .addParameter(ParameterSpec.builder(TypeNames.Android.Context, \"context\")\n            .build())\n        .addParameter(ParameterSpec.builder(TypeNames.Android.AttributeSet, \"attrs\")\n            .addAnnotation(TypeNames.Annotations.Nullable)\n            .build())\n        .addParameter(ParameterSpec.builder(ClassName.INT, \"defStyleAttr\")\n            .addAnnotation(TypeNames.Annotations.AttrRes)\n            .build())\n        .addParameter(ParameterSpec.builder(ClassName.INT, \"defStyleRes\")\n            .addAnnotation(TypeNames.Annotations.StyleRes)\n            .build())\n\n    stencil.initMethodHook(type, initMethod)\n\n    return initMethod\n  }\n\n  override fun generateConstructorsFor(stencil: JavaViewStencil, type: TypeSpec.Builder, rClass: ClassName) {\n    val count = stencil.constructorCount\n    for (i in 1..count) {\n      when (i) {\n        1 -> // Context constructor\n          type.addMethod(MethodSpec.constructorBuilder()\n              .addModifiers(Modifier.PUBLIC)\n              .addParameter(ParameterSpec.builder(TypeNames.Android.Context, \"context\")\n                  .build())\n              .addCode(constructorBlock(stencil, rClass, count, i))\n              .build())\n        2 -> // Context, AttributeSet constructor\n          type.addMethod(MethodSpec.constructorBuilder()\n              .addModifiers(Modifier.PUBLIC)\n              .addParameter(ParameterSpec.builder(TypeNames.Android.Context, \"context\")\n                  .build())\n              .addParameter(ParameterSpec.builder(TypeNames.Android.AttributeSet, \"attrs\")\n                  .addAnnotation(TypeNames.Annotations.Nullable)\n                  .build())\n              .addCode(constructorBlock(stencil, rClass, count, i))\n              .build())\n        3 -> // Context, AttributeSet, defStyleAttr constructor\n          type.addMethod(MethodSpec.constructorBuilder()\n              .addModifiers(Modifier.PUBLIC)\n              .addParameter(ParameterSpec.builder(TypeNames.Android.Context, \"context\")\n                  .build())\n              .addParameter(ParameterSpec.builder(TypeNames.Android.AttributeSet, \"attrs\")\n                  .addAnnotation(TypeNames.Annotations.Nullable)\n                  .build())\n              .addParameter(ParameterSpec.builder(ClassName.INT, \"defStyleAttr\")\n                  .addAnnotation(TypeNames.Annotations.AttrRes)\n                  .build())\n              .addCode(constructorBlock(stencil, rClass, count, i))\n              .build())\n        4 -> // Context, AttributeSet, defStyleAttr, defStyleRes constructor\n          type.addMethod(MethodSpec.constructorBuilder()\n              .addModifiers(Modifier.PUBLIC)\n              .addParameter(ParameterSpec.builder(TypeNames.Android.Context, \"context\")\n                  .build())\n              .addParameter(ParameterSpec.builder(TypeNames.Android.AttributeSet, \"attrs\")\n                  .addAnnotation(TypeNames.Annotations.Nullable)\n                  .build())\n              .addParameter(ParameterSpec.builder(ClassName.INT, \"defStyleAttr\")\n                  .addAnnotation(TypeNames.Annotations.AttrRes)\n                  .build())\n              .addParameter(ParameterSpec.builder(ClassName.INT, \"defStyleRes\")\n                  .addAnnotation(TypeNames.Annotations.StyleRes)\n                  .build())\n              .addAnnotation(AnnotationSpec.builder(TypeNames.Annotations.TargetApi)\n                  .addMember(\"value\", \"\\$T.\\$L.\\$L\",\n                      ClassName.get(\"android.os\", \"Build\"),\n                      \"VERSION_CODES\",\n                      \"LOLLIPOP\")\n                  .build())\n              .addCode(constructorBlock(stencil, rClass, count, i))\n              .build())\n      }\n    }\n  }\n\n  private fun constructorBlock(stencil: JavaViewStencil, rClass: ClassName, total: Int, currentIndex: Int): CodeBlock {\n    val builder = CodeBlock.builder()\n    if (currentIndex == total || currentIndex == 3) {\n      builder.addStatement(superConstructorStatement(currentIndex))\n      builder.addStatement(initStatement(currentIndex))\n    } else {\n      builder.add(fallthroughConstructorStatement(stencil, rClass, currentIndex))\n    }\n    return builder.build()\n  }\n\n  private fun fallthroughConstructorStatement(stencil: JavaViewStencil, rClass: ClassName, count: Int): CodeBlock {\n    when (count) {\n      1 -> return CodeBlock.of(\"this(context, null);\\n\")\n      2 -> {\n        return if (stencil.defaultAttrRes != null) {\n          if ((stencil.defaultAttrRes as String).startsWith(prefix = \"android.R\")) {\n            CodeBlock.of(\"this(context, attrs, ${stencil.defaultAttrRes});\\n\")\n          } else {\n            CodeBlock.of(\"this(context, attrs, \\$T.attr.${stencil.defaultAttrRes});\\n\", rClass)\n          }\n        } else {\n          CodeBlock.of(\"this(context, attrs, 0);\\n\")\n        }\n      }\n      3 -> return CodeBlock.of(\"this(context, attrs, defStyleAttr, 0);\\n\")\n    }\n    throw IllegalArgumentException(count.toString())\n  }\n\n  override fun superinterface(className: String): ClassName {\n    val packageName = className.substring(0, className.lastIndexOf('.'))\n    val simpleName = className.substring(className.lastIndexOf('.') + 1)\n    return ClassName.get(packageName, simpleName)\n  }\n\n  override fun writeFile(fileSpec: JavaFile, outputDir: File) {\n    fileSpec.writeTo(outputDir)\n  }\n\n  override fun writeFileWithFormatting(fileSpec: JavaFile, outputDir: File, outputType: TypeSpec.Builder, packageName: String) {\n    JavaFormattingFileWriter(fileSpec, outputType, packageName).writeWithFormattingTo(outputDir)\n  }\n}\n"
  },
  {
    "path": "artist-core/src/main/kotlin/com/uber/artist/JavaFormattingFileWriter.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist\n\nimport com.google.common.base.Preconditions.checkArgument\nimport com.google.common.io.CharSink\nimport com.google.common.io.CharSource\nimport com.google.googlejavaformat.java.Formatter\nimport com.google.googlejavaformat.java.FormatterException\nimport com.squareup.javapoet.JavaFile\nimport com.squareup.javapoet.TypeSpec\nimport java.io.File\nimport java.io.IOException\nimport java.io.OutputStreamWriter\nimport java.io.Writer\nimport java.nio.charset.StandardCharsets.UTF_8\nimport java.nio.file.Files\n\nclass JavaFormattingFileWriter(val outputFile: JavaFile, val typeSpecBuilder: TypeSpec.Builder, val packageName: String) : FormattingFileWriter<JavaFile, TypeSpec.Builder>() {\n\n  private val formatter: Formatter = Formatter()\n\n  /**\n   * A file writer function that formats the code before writing out to the file system.\n   */\n  override fun writeWithFormattingTo(directory: File) {\n    val directoryPath = directory.toPath()\n    checkArgument(Files.notExists(directoryPath) || Files.isDirectory(directoryPath),\n        \"path %s exists but is not a directoryPath.\", directoryPath)\n    var outputDirectory = directoryPath\n    if (!packageName.isEmpty()) {\n      for (packageComponent in packageName.split(packageSplitRegex)\n          .filter { !it.isEmpty() }.toTypedArray()) {\n        outputDirectory = outputDirectory.resolve(packageComponent)\n      }\n      Files.createDirectories(outputDirectory)\n    }\n\n    val typeSpec = typeSpecBuilder.build()\n    val outputPath = outputDirectory.resolve(typeSpec.name + \".java\")\n    try {\n      OutputStreamWriter(Files.newOutputStream(outputPath), UTF_8).use { writer ->\n        val stringBuilder = StringBuilder(defaultFileSize)\n        outputFile.writeTo(stringBuilder)\n        formatter.formatSource(\n            CharSource.wrap(stringBuilder),\n            object : CharSink() {\n              @Throws(IOException::class)\n              override fun openStream(): Writer {\n                return writer\n              }\n            })\n      }\n    } catch (e: FormatterException) {\n      throw IOException(\"Error formatting \" + outputPath.fileName.toString(), e)\n    }\n  }\n}\n"
  },
  {
    "path": "artist-core/src/main/kotlin/com/uber/artist/KotlinArtistCodeGenerator.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist\n\nimport AliasTypeNames.Rx.Companion.rxExtensionFunctionToAlias\nimport com.squareup.kotlinpoet.AnnotationSpec\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.CodeBlock\nimport com.squareup.kotlinpoet.FileSpec\nimport com.squareup.kotlinpoet.FunSpec\nimport com.squareup.kotlinpoet.INT\nimport com.squareup.kotlinpoet.KModifier\nimport com.squareup.kotlinpoet.ParameterSpec\nimport com.squareup.kotlinpoet.TypeSpec\nimport com.uber.artist.api.KotlinTrait\nimport com.uber.artist.api.KotlinTraitService\nimport com.uber.artist.api.KotlinTypeNames\nimport com.uber.artist.api.KotlinViewStencil\nimport com.uber.artist.api.KotlinViewStencilService\nimport java.io.File\n\nclass KotlinArtistCodeGenerator : ArtistCodeGenerator<FileSpec, TypeSpec.Builder, FunSpec.Builder, ClassName, CodeBlock, KotlinViewStencil, KotlinTrait>() {\n\n  override val viewStencils: Set<KotlinViewStencil>\n    get() = KotlinViewStencilService.newInstance().getStencils()\n\n  override val traits: Set<KotlinTrait>\n    get() = KotlinTraitService.newInstance().get()\n\n  override val globalTraits: Set<Class<out KotlinTrait>>\n    get() = KotlinViewStencilService.newInstance().getGlobalTraits()\n\n  override fun generateFileSpecFor(stencil: KotlinViewStencil, viewPackageName: String,\n                                   typeSpecBuilder: TypeSpec.Builder): FileSpec {\n    val typeSpec = typeSpecBuilder.build()\n    var builder = FileSpec.builder(viewPackageName, typeSpec.name\n        ?: throw IllegalStateException(\"No name for type: $typeSpec\"))\n\n    for ((extensionFunctionAlias, alias) in stencil.extensionFunctionToAlias()) {\n      builder = builder.addAliasedImport(extensionFunctionAlias.toClassName(), \"\", alias)\n    }\n    return builder.addType(typeSpec).build()\n  }\n\n  fun AliasTypeNames.Rx.Companion.ExtensionFunctionAlias.toClassName(): ClassName {\n    return ClassName(this.className.packageName, this.methodName)\n  }\n\n  override fun generateTypeSpecFor(stencil: KotlinViewStencil, rPackageName: String, traitMap: Map<Class<out KotlinTrait>, KotlinTrait>, superinterfaceClassName: String?): TypeSpec.Builder {\n    val rClass = ClassName(rPackageName, \"R\")\n    val typeBuilder = TypeSpec.classBuilder(stencil.name())\n        .addModifiers(KModifier.OPEN)\n        .superclass(stencil.sourceType)\n\n    superinterfaceClassName?.let { typeBuilder.addSuperinterface(superinterface(superinterfaceClassName)) }\n\n    generateConstructorsFor(stencil, typeBuilder, rClass)\n    val initMethod = createInitBuilderFor(stencil, typeBuilder)\n\n    stencil.traits()\n        .map { traitName -> traitMap[traitName] }\n        .forEach { it?.generateFor(typeBuilder, initMethod, rClass, stencil.name()) }\n\n    typeBuilder.addFunction(initMethod.build())\n    stencil.typeHook(typeBuilder)\n    return typeBuilder\n  }\n\n  override fun createInitBuilderFor(stencil: KotlinViewStencil, type: TypeSpec.Builder): FunSpec.Builder {\n    return FunSpec.builder(\"init\")\n        .addAnnotation(KotlinTypeNames.Annotations.CallSuper)\n        .addModifiers(KModifier.PROTECTED, KModifier.OPEN)\n        .addParameter(ParameterSpec.builder(\"context\", KotlinTypeNames.Android.Context)\n            .build())\n        .addParameter(ParameterSpec.builder(\"attrs\", KotlinTypeNames.Android.AttributeSet.copy(nullable = true))\n            .build())\n        .addParameter(ParameterSpec.builder(\"defStyleAttr\", INT)\n            .addAnnotation(KotlinTypeNames.Annotations.AttrRes)\n            .build())\n        .addParameter(ParameterSpec.builder(\"defStyleRes\", INT)\n            .addAnnotation(KotlinTypeNames.Annotations.StyleRes)\n            .build())\n        .also {\n          stencil.initMethodHook(type, it)\n        }\n  }\n\n  override fun generateConstructorsFor(stencil: KotlinViewStencil, type: TypeSpec.Builder, rClass: ClassName) {\n    val paramContext = ParameterSpec.builder(\"context\", KotlinTypeNames.Android.Context)\n        .build()\n    val paramAttrs = ParameterSpec.builder(\"attrs\", KotlinTypeNames.Android.AttributeSet.copy(nullable = true))\n        .defaultValue(\"null\")\n        .build()\n    val paramDefStyleAttr = ParameterSpec.builder(\"defStyleAttr\", INT)\n        .addAnnotation(KotlinTypeNames.Annotations.AttrRes)\n        .defaultValue(stencil.defaultAttrRes?.let {\n          if (\".\" in it) {\n            CodeBlock.of(it)\n          } else {\n            CodeBlock.of(\"%T.attr.$it\", rClass)\n          }\n        } ?: CodeBlock.of(\"0\")\n        )\n        .build()\n    val paramDefStyleRes = ParameterSpec.builder(\"defStyleRes\", INT)\n        .addAnnotation(KotlinTypeNames.Annotations.StyleRes)\n        .defaultValue(\"0\")\n        .build()\n\n    val params = listOf(paramContext, paramAttrs, paramDefStyleAttr, paramDefStyleRes)\n    val superConstructorArgs = listOf(\"context\", \"attrs\", \"defStyleAttr\", \"defStyleRes\")\n\n    val ctorOverloadsCount = stencil.constructorCount.coerceAtMost(3)\n    val overloadsConstructor = FunSpec.constructorBuilder()\n        .addAnnotation(JvmOverloads::class)\n        .addParameters(params.subList(0, ctorOverloadsCount))\n        .callSuperConstructor(*superConstructorArgs.subList(0, ctorOverloadsCount).toTypedArray())\n        .addStatement(initStatement(ctorOverloadsCount))\n        .build()\n\n    val targetApiConstructor = FunSpec.constructorBuilder()\n        .addAnnotation(AnnotationSpec.builder(KotlinTypeNames.Annotations.TargetApi)\n            .addMember(\"%T.VERSION_CODES.LOLLIPOP\", ClassName(\"android.os\", \"Build\"))\n            .build())\n        .addParameters(params)\n        .callSuperConstructor(*superConstructorArgs.toTypedArray())\n        .addStatement(initStatement(4))\n        .build()\n\n    type\n        .addFunction(overloadsConstructor)\n        .apply {\n          if (stencil.constructorCount > 3) addFunction(targetApiConstructor)\n        }\n  }\n\n  override fun superinterface(className: String) = ClassName(\n      className.substringBeforeLast('.'),\n      className.substringAfterLast('.')\n  )\n\n  override fun writeFile(fileSpec: FileSpec, outputDir: File) {\n    fileSpec.writeTo(outputDir)\n  }\n\n  override fun writeFileWithFormatting(fileSpec: FileSpec, outputDir: File, outputType: TypeSpec.Builder, packageName: String) {\n    fileSpec.writeTo(outputDir)\n  }\n}\n"
  },
  {
    "path": "artist-core/src/test/kotlin/com/uber/artist/ArtistTest.kt",
    "content": "package com.uber.artist\n\nimport com.google.common.io.Files\nimport com.google.common.truth.Truth.assertAbout\nimport com.google.common.truth.Truth.assertThat\nimport com.google.common.truth.Truth.assertWithMessage\nimport com.google.testing.compile.JavaFileObjects.forSourceString\nimport com.google.testing.compile.JavaSourceSubjectFactory.javaSource\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeSpec\nimport com.uber.artist.api.JavaTrait\nimport com.uber.artist.api.JavaViewStencil\nimport org.junit.Test\nimport javax.lang.model.element.Modifier\n\nclass ArtistTest {\n\n    companion object {\n        const val TEST_PACKAGE_NAME = \"foo.bar\"\n        val TRAITS = setOf(TestTrait())\n\n        const val IMAGE_VIEW_SOURCE_NO_TRAITS = \"\"\"package foo.bar;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.widget.ImageView;\nimport androidx.annotation.AttrRes;\nimport androidx.annotation.CallSuper;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StyleRes;\n\npublic class MyImageView extends ImageView {\n  public MyImageView(Context context) {\n    this(context, null);\n  }\n\n  public MyImageView(Context context, @Nullable AttributeSet attrs) {\n    this(context, attrs, 0);\n  }\n\n  public MyImageView(Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {\n    super(context, attrs, defStyleAttr);\n    init(context, attrs, defStyleAttr, 0);\n  }\n\n  @CallSuper\n  protected void init(\n      Context context,\n      @Nullable AttributeSet attrs,\n      @AttrRes int defStyleAttr,\n      @StyleRes int defStyleRes) {}\n}\n\"\"\"\n\n        val IMAGE_VIEW_WITH_TEST_TRAIT = \"\"\"package foo.bar;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.widget.ImageView;\nimport androidx.annotation.AttrRes;\nimport androidx.annotation.CallSuper;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StyleRes;\nimport java.lang.String;\n\npublic class MyImageView extends ImageView {\n  public MyImageView(Context context) {\n    this(context, null);\n  }\n\n  public MyImageView(Context context, @Nullable AttributeSet attrs) {\n    this(context, attrs, 0);\n  }\n\n  public MyImageView(Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {\n    super(context, attrs, defStyleAttr);\n    init(context, attrs, defStyleAttr, 0);\n  }\n\n  public String testMethod() {\n    return \"foo\";\n  }\n\n  @CallSuper\n  protected void init(\n      Context context,\n      @Nullable AttributeSet attrs,\n      @AttrRes int defStyleAttr,\n      @StyleRes int defStyleRes) {}\n}\n\"\"\"\n    }\n\n    @Test\n    fun testArtist_withNoTraits_shouldGenerateViews() {\n        val outputDir = Files.createTempDir()\n        val stencils: Set<JavaViewStencil> = setOf(\n                JavaViewStencil(\"android.widget.Button\", 3),\n                JavaViewStencil(\"android.widget.ImageView\", 3),\n                JavaViewStencil(\"android.widget.TextView\", 3))\n\n        JavaArtistCodeGenerator().generateViewsForStencils(stencils, TRAITS, emptySet(), outputDir, TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, null, \"My\", true)\n\n        val viewOutputDir = outputDir.resolve(TEST_PACKAGE_NAME.replace('.', '/'))\n        val viewNames = viewOutputDir.listFiles()\n                .map { it.name }\n                .toList()\n        assertThat(viewNames).containsExactly(\"MyButton.java\", \"MyImageView.java\", \"MyTextView.java\")\n    }\n\n    @Test\n    fun testArtist_withNoTraits_shouldGenerateExpectedSource() {\n        val outputDir = Files.createTempDir()\n        val stencils: Set<JavaViewStencil> = setOf(\n                JavaViewStencil(\"android.widget.ImageView\", 3))\n\n        JavaArtistCodeGenerator().generateViewsForStencils(stencils, TRAITS, emptySet(), outputDir, TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, null, \"My\", true)\n\n        val viewOutputDir = outputDir.resolve(TEST_PACKAGE_NAME.replace('.', '/'))\n        assertWithMessage(\"$viewOutputDir does not exist\").that(viewOutputDir.exists()).isTrue()\n\n        val generatedFileName = viewOutputDir.listFiles().first()\n        val generatedViewContent = generatedFileName.readText()\n        assertAbout(javaSource())\n                .that(forSourceString(\"$TEST_PACKAGE_NAME.MyImageView\", generatedViewContent))\n                .compilesWithoutError()\n\n        assertWithMessage(\"$generatedFileName did not match expected file content\")\n                .that(generatedViewContent)\n                .isEqualTo(IMAGE_VIEW_SOURCE_NO_TRAITS)\n    }\n\n    @Test\n    fun testArtist_withAddedTrait_shouldGenerateExpectedSource() {\n        val outputDir = Files.createTempDir()\n        val stencils: Set<JavaViewStencil> = setOf(\n                JavaViewStencil(\"android.widget.ImageView\", 3, addedTraits = *arrayOf(TestTrait::class.java)))\n\n        JavaArtistCodeGenerator().generateViewsForStencils(stencils, TRAITS, emptySet(), outputDir, TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, null, \"My\", true)\n\n        val viewOutputDir = outputDir.resolve(TEST_PACKAGE_NAME.replace('.', '/'))\n        assertWithMessage(\"$viewOutputDir does not exist\").that(viewOutputDir.exists()).isTrue()\n\n        val generatedFileName = viewOutputDir.listFiles().first()\n        val generatedViewContent = generatedFileName.readText()\n        assertAbout(javaSource())\n                .that(forSourceString(\"$TEST_PACKAGE_NAME.MyImageView\", generatedViewContent))\n                .compilesWithoutError()\n\n        assertWithMessage(\"$generatedFileName did not match expected file content\")\n                .that(generatedViewContent)\n                .isEqualTo(IMAGE_VIEW_WITH_TEST_TRAIT)\n    }\n\n    @Test\n    fun testArtist_withGlobalTrait_shouldGenerateExpectedSource() {\n        val outputDir = Files.createTempDir()\n        val globalTraits: Set<Class<out JavaTrait>> = setOf(TestTrait::class.java)\n        val stencils: Set<JavaViewStencil> = setOf(\n                JavaViewStencil(\"android.widget.ImageView\", 3))\n\n        JavaArtistCodeGenerator().generateViewsForStencils(stencils, TRAITS, globalTraits, outputDir, TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, null, \"My\", true)\n\n        val viewOutputDir = outputDir.resolve(TEST_PACKAGE_NAME.replace('.', '/'))\n        assertWithMessage(\"$viewOutputDir does not exist\").that(viewOutputDir.exists()).isTrue()\n\n        val generatedFileName = viewOutputDir.listFiles().first()\n        val generatedViewContent = generatedFileName.readText()\n        assertAbout(javaSource())\n                .that(forSourceString(\"$TEST_PACKAGE_NAME.MyImageView\", generatedViewContent))\n                .compilesWithoutError()\n\n        assertWithMessage(\"$generatedFileName did not match expected file content\")\n                .that(generatedViewContent)\n                .isEqualTo(IMAGE_VIEW_WITH_TEST_TRAIT)\n    }\n\n    class TestTrait : JavaTrait {\n        override fun generateFor(type: TypeSpec.Builder, initMethod: MethodSpec.Builder, rClass: ClassName, sourceType: String) {\n            type.addMethod(MethodSpec.methodBuilder(\"testMethod\")\n                    .addModifiers(Modifier.PUBLIC)\n                    .returns(ClassName.get(String::class.java))\n                    .addStatement(\"return \\$S\", \"foo\")\n                    .build())\n        }\n    }\n}\n"
  },
  {
    "path": "artist-traits/build.gradle",
    "content": "apply plugin: \"java-library\"\napply plugin: \"org.jetbrains.kotlin.jvm\"\napply plugin: \"org.jetbrains.kotlin.kapt\"\n\nsourceCompatibility = JavaVersion.VERSION_1_7\ntargetCompatibility = JavaVersion.VERSION_1_7\n\ndependencies {\n    kapt deps.apt.autoService\n    compileOnly deps.apt.autoService\n\n    api project(\":artist-api\")\n\n    implementation deps.kotlin.stdLibJdk7\n}\n\nif (rootProject.projectDir.name != \"buildSrc\") {\n    apply from: rootProject.file('gradle/gradle-mvn-push.gradle')\n}\n"
  },
  {
    "path": "artist-traits/gradle.properties",
    "content": "#\n# Copyright (C) 2017. Uber Technologies\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nPOM_NAME=artist-traits\nPOM_ARTIFACT_ID=artist-traits\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "artist-traits/src/main/kotlin/com/uber/artist/traits/JavaForegroundTrait.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits\n\nimport com.google.auto.service.AutoService\nimport com.squareup.javapoet.AnnotationSpec\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.FieldSpec\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeName\nimport com.squareup.javapoet.TypeSpec\nimport com.uber.artist.api.JavaTrait\nimport com.uber.artist.api.Trait\nimport com.uber.artist.api.TypeNames\nimport javax.lang.model.element.Modifier\n\n/**\n * This [Trait] ports [FrameLayout]'s foreground functionality to other views. In order to use this, the module that\n * applies that [Artist] plugin must declare the ForegroundView styleable in res/values/attrs_foreground_view.xml.\n *\n * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n * <resources>\n *   <declare-styleable name=\"ForegroundView\">\n *     <attr name=\"android:foreground\"/>\n *     <attr name=\"android:foregroundGravity\"/>\n *     <attr name=\"foregroundInsidePadding\"/>\n *   </declare-styleable>\n * </resources>\n */\n@AutoService(JavaTrait::class)\nclass JavaForegroundTrait : JavaTrait {\n  override fun generateFor(\n      type: TypeSpec.Builder,\n      initMethod: MethodSpec.Builder,\n      rClass: ClassName,\n      sourceType: String) {\n\n    val isLayout = sourceType.endsWith(\"Layout\")\n\n    // The field\n    type.addField(TypeNames.Android.Drawable, \"foreground\", Modifier.PRIVATE)\n\n    if (isLayout) {\n      type.addField(FieldSpec.builder(TypeNames.Android.Rect, \"selfBounds\", Modifier.PRIVATE, Modifier.FINAL)\n          .initializer(\"new \\$T()\", TypeNames.Android.Rect)\n          .build())\n      type.addField(FieldSpec.builder(TypeNames.Android.Rect, \"overlayBounds\", Modifier.PRIVATE, Modifier.FINAL)\n          .initializer(\"new \\$T()\", TypeNames.Android.Rect)\n          .build())\n      type.addField(FieldSpec.builder(TypeName.BOOLEAN, \"foregroundInPadding\", Modifier.PRIVATE)\n          .initializer(\"true\")\n          .build())\n      type.addField(FieldSpec.builder(TypeName.BOOLEAN, \"foregroundBoundsChanged\", Modifier.PRIVATE)\n          .initializer(\"false\")\n          .build())\n      type.addField(FieldSpec.builder(TypeName.INT, \"foregroundGravity\", Modifier.PRIVATE)\n          .initializer(\"\\$T.FILL\", TypeNames.Android.Gravity)\n          .build())\n    }\n\n    // Pull out the value\n    initMethod.addStatement(\n        \"\\$T foregroundTA = context.obtainStyledAttributes(attrs, \\$T.styleable.ForegroundView)\",\n        TypeNames.Android.TypedArray,\n        rClass)\n    initMethod.addStatement(\n        \"final \\$T localForeground = foregroundTA.getDrawable(\\$T.styleable.ForegroundView_android_foreground)\",\n        TypeNames.Android.Drawable,\n        rClass)\n\n    initMethod.beginControlFlow(\"if (localForeground != null)\")\n    initMethod.addCode(\"//noinspection AndroidLintNewApi\\n\")\n    initMethod.addStatement(\"setForeground(localForeground)\")\n    initMethod.endControlFlow()\n\n    if (isLayout) {\n      initMethod.addStatement(\n          \"foregroundGravity = foregroundTA.getInt(\\$T.styleable.ForegroundView_android_foregroundGravity, \" +\n              \"foregroundGravity)\", rClass)\n      initMethod.addStatement(\n          \"foregroundInPadding = foregroundTA.getBoolean(\" +\n              \"\\$T.styleable.ForegroundView_foregroundInsidePadding, \" +\n              \"true)\", rClass)\n    }\n\n    initMethod.addStatement(\"foregroundTA.recycle()\")\n\n    val onSizeChangedMethod = MethodSpec.methodBuilder(\"onSizeChanged\")\n        .addAnnotation(Override::class.java)\n        .addModifiers(Modifier.PROTECTED)\n        .addParameter(TypeName.INT, \"w\")\n        .addParameter(TypeName.INT, \"h\")\n        .addParameter(TypeName.INT, \"oldw\")\n        .addParameter(TypeName.INT, \"oldh\")\n        .addStatement(\"super.onSizeChanged(w, h, oldw, oldh)\")\n\n    if (isLayout) {\n      onSizeChangedMethod.addStatement(\"foregroundBoundsChanged = true\")\n    } else {\n      onSizeChangedMethod.beginControlFlow(\"if (foreground != null)\")\n          .addStatement(\"foreground.setBounds(0, 0, w, h)\")\n          .endControlFlow()\n    }\n\n    type.addMethod(onSizeChangedMethod.build())\n\n    if (sourceType.endsWith(\"ImageView\")) {\n      type.addMethod(MethodSpec.methodBuilder(\"hasOverlappingRendering\")\n          .addAnnotation(Override::class.java)\n          .addModifiers(Modifier.PUBLIC)\n          .returns(TypeName.BOOLEAN)\n          .addStatement(\"return false\")\n          .build())\n    }\n\n    if (isLayout) {\n      type.addMethod(MethodSpec.methodBuilder(\"getForegroundGravity\")\n          .addJavadoc(\"\"\"Describes how the foreground is positioned.\n\n    @return foreground gravity.\n    @see #setForegroundGravity(int)\n    \"\"\")\n          .addAnnotation(AnnotationSpec.builder(SuppressWarnings::class.java).addMember(\"value\", \"\\$S\", \"MissingOverride\").build())\n          .addModifiers(Modifier.PUBLIC)\n          .returns(TypeName.INT)\n          .addStatement(\"return foregroundGravity\")\n          .build())\n\n      type.addMethod(MethodSpec.methodBuilder(\"setForegroundGravity\")\n          .addJavadoc(\"\"\"Describes how the foreground is positioned. Defaults to START and TOP.\n\n    @param foregroundGravity See {@link android.view.Gravity}\n    @see #getForegroundGravity()\n    \"\"\")\n          .addAnnotation(AnnotationSpec.builder(SuppressWarnings::class.java).addMember(\"value\", \"\\$S\", \"MissingOverride\").build())\n          .addModifiers(Modifier.PUBLIC)\n          .addParameter(TypeName.INT, \"foregroundGravity\")\n          .beginControlFlow(\"if (this.foregroundGravity != foregroundGravity)\")\n          .beginControlFlow(\"if ((foregroundGravity & \\$T.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0)\",\n              TypeNames.Android.Gravity)\n          .addStatement(\"foregroundGravity |= \\$T.START\", TypeNames.Android.GravityCompat)\n          .endControlFlow()\n          .beginControlFlow(\"if ((foregroundGravity & \\$T.VERTICAL_GRAVITY_MASK) == 0)\",\n              TypeNames.Android.Gravity)\n          .addStatement(\"foregroundGravity |= \\$T.TOP\", TypeNames.Android.Gravity)\n          .endControlFlow()\n          .addStatement(\"this.foregroundGravity = foregroundGravity\")\n          .beginControlFlow(\"if (this.foregroundGravity == \\$T.FILL && foreground != null)\",\n              TypeNames.Android.Gravity)\n          .addStatement(\"\\$T padding = new \\$T()\", TypeNames.Android.Rect, TypeNames.Android.Rect)\n          .addStatement(\"foreground.getPadding(padding)\")\n          .endControlFlow()\n          .addStatement(\"requestLayout()\")\n          .endControlFlow()\n          .build())\n    }\n\n    type.addMethod(MethodSpec.methodBuilder(\"verifyDrawable\")\n        .addAnnotation(Override::class.java)\n        .addModifiers(Modifier.PROTECTED)\n        .returns(TypeName.BOOLEAN)\n        .addParameter(TypeNames.Android.Drawable, \"who\")\n        .addStatement(\"return super.verifyDrawable(who) || (who == foreground)\")\n        .build())\n\n    type.addMethod(MethodSpec.methodBuilder(\"jumpDrawablesToCurrentState\")\n        .addAnnotation(Override::class.java)\n        .addModifiers(Modifier.PUBLIC)\n        .addStatement(\"super.jumpDrawablesToCurrentState()\")\n        .beginControlFlow(\"if (foreground != null)\")\n        .addStatement(\"foreground.jumpToCurrentState()\")\n        .endControlFlow()\n        .build())\n\n    type.addMethod(MethodSpec.methodBuilder(\"drawableStateChanged\")\n        .addAnnotation(Override::class.java)\n        .addModifiers(Modifier.PROTECTED)\n        .addStatement(\"super.drawableStateChanged()\")\n        .beginControlFlow(\"if (foreground != null && foreground.isStateful())\")\n        .addStatement(\"foreground.setState(getDrawableState())\")\n        .endControlFlow()\n        .build())\n\n    type.addMethod(MethodSpec.methodBuilder(\"getForeground\")\n        .addJavadoc(\"\"\"Returns the drawable used as the foreground of this view. The\n    foreground drawable, if non-null, is always drawn on top of the children.\n\n    @return A Drawable or null if no foreground was set.\n    \"\"\")\n        .addAnnotation(AnnotationSpec.builder(SuppressWarnings::class.java).addMember(\"value\", \"\\$S\", \"MissingOverride\").build())\n        .addModifiers(Modifier.PUBLIC)\n        .returns(TypeNames.Android.Drawable)\n        .addStatement(\"return foreground\")\n        .build())\n\n    val setForegroundMethod = MethodSpec.methodBuilder(\"setForeground\")\n        .addJavadoc(\"\"\"Supply a Drawable that is to be rendered on top of all of the child\n    views in this layout.  Any padding in the Drawable will be taken\n    into account by ensuring that the children are inset to be placed\n    inside of the padding area.\n\n    @param drawable The Drawable to be drawn on top of the children.\n    \"\"\")\n        .addAnnotation(AnnotationSpec.builder(SuppressWarnings::class.java).addMember(\"value\", \"\\$S\", \"MissingOverride\").build())\n        .addAnnotation(AnnotationSpec.builder(ClassName.get(\"android.annotation\", \"SuppressLint\"))\n            .addMember(\"value\", \"\\\"NewApi\\\"\")\n            .build())\n        .addModifiers(Modifier.PUBLIC)\n        .addParameter(TypeNames.Android.Drawable, \"drawable\")\n        .beginControlFlow(\"if (foreground != drawable)\")\n        .beginControlFlow(\"if (foreground != null)\")\n        .addStatement(\"foreground.setCallback(null)\")\n        .addStatement(\"unscheduleDrawable(foreground)\")\n        .endControlFlow()\n        .addStatement(\"foreground = drawable\")\n        .beginControlFlow(\"if (drawable != null)\")\n\n    if (!isLayout) {\n      setForegroundMethod.addStatement(\"foreground.setBounds(0, 0, getWidth(), getHeight())\")\n    }\n\n    setForegroundMethod.addStatement(\"setWillNotDraw(false)\")\n        .addStatement(\"drawable.setCallback(this)\")\n        .beginControlFlow(\"if (drawable.isStateful())\")\n        .addStatement(\"drawable.setState(getDrawableState())\")\n        .endControlFlow()\n\n    if (isLayout) {\n      setForegroundMethod.beginControlFlow(\"if (foregroundGravity == \\$T.FILL)\", TypeNames.Android.Gravity)\n      setForegroundMethod.addStatement(\"\\$T padding = new \\$T()\", TypeNames.Android.Rect, TypeNames.Android.Rect)\n      setForegroundMethod.addStatement(\"drawable.getPadding(padding)\")\n      setForegroundMethod.endControlFlow()\n    }\n\n    setForegroundMethod.nextControlFlow(\"else\")\n        .addStatement(\"setWillNotDraw(true)\")\n        .endControlFlow()\n\n    if (isLayout) {\n      setForegroundMethod.addStatement(\"requestLayout()\")\n    }\n    setForegroundMethod.addStatement(\"invalidate()\")\n        .endControlFlow()\n\n    type.addMethod(setForegroundMethod.build())\n\n    if (isLayout) {\n      type.addMethod(MethodSpec.methodBuilder(\"onLayout\")\n          .addAnnotation(Override::class.java)\n          .addModifiers(Modifier.PROTECTED)\n          .addParameter(TypeName.BOOLEAN, \"changed\")\n          .addParameter(TypeName.INT, \"left\")\n          .addParameter(TypeName.INT, \"top\")\n          .addParameter(TypeName.INT, \"right\")\n          .addParameter(TypeName.INT, \"bottom\")\n          .addStatement(\"super.onLayout(changed, left, top, right, bottom)\")\n          .beginControlFlow(\"if (changed)\")\n          .addStatement(\"foregroundBoundsChanged = true\")\n          .endControlFlow()\n          .build())\n    }\n\n    val drawMethod = MethodSpec.methodBuilder(\"draw\")\n        .addAnnotation(Override::class.java)\n        .addModifiers(Modifier.PUBLIC)\n        .addParameter(TypeNames.Android.Canvas, \"canvas\")\n        .addStatement(\"super.draw(canvas)\")\n        .beginControlFlow(\"if (foreground != null)\")\n\n    if (isLayout) {\n      drawMethod.addStatement(\"final \\$T localForeground = foreground\", TypeNames.Android.Drawable)\n          .beginControlFlow(\"if (foregroundBoundsChanged)\")\n          .addStatement(\"foregroundBoundsChanged = false\")\n          .addStatement(\"final \\$T localSelfBounds = selfBounds\", TypeNames.Android.Rect)\n          .addStatement(\"final \\$T localOverlayBounds = overlayBounds\", TypeNames.Android.Rect)\n          .addStatement(\"final int w = getRight() - getLeft()\")\n          .addStatement(\"final int h = getBottom() - getTop()\")\n          .beginControlFlow(\"if (foregroundInPadding)\")\n          .addStatement(\"localSelfBounds.set(0, 0, w, h)\")\n          .nextControlFlow(\"else\")\n          .addStatement(\"localSelfBounds.set(getPaddingLeft(), getPaddingTop(), w - getPaddingRight(), h - \" +\n              \"getPaddingBottom())\")\n          .endControlFlow()\n          .addStatement(\"\\$T.apply(foregroundGravity, localForeground.getIntrinsicWidth(), localForeground\" +\n              \".getIntrinsicHeight(), localSelfBounds, localOverlayBounds)\", TypeNames.Android.Gravity)\n          .addStatement(\"localForeground.setBounds(localOverlayBounds)\")\n          .endControlFlow()\n          .addStatement(\"localForeground.draw(canvas)\")\n    } else {\n      drawMethod.addStatement(\"foreground.draw(canvas)\")\n    }\n    drawMethod.endControlFlow()\n    type.addMethod(drawMethod.build())\n\n    type.addMethod(MethodSpec.methodBuilder(\"drawableHotspotChanged\")\n        .addAnnotation(AnnotationSpec.builder(TypeNames.Annotations.TargetApi)\n            .addMember(\"value\", \"\\$L\", \"android.os.Build.VERSION_CODES.LOLLIPOP\")\n            .build())\n        .addAnnotation(Override::class.java)\n        .addModifiers(Modifier.PUBLIC)\n        .addParameter(TypeName.FLOAT, \"x\")\n        .addParameter(TypeName.FLOAT, \"y\")\n        .addStatement(\"super.drawableHotspotChanged(x, y)\")\n        .beginControlFlow(\"if (foreground != null)\")\n        .addStatement(\"foreground.setHotspot(x, y)\")\n        .endControlFlow()\n        .build())\n  }\n}\n"
  },
  {
    "path": "artist-traits/src/main/kotlin/com/uber/artist/traits/JavaSuppressNullabilityInitializerTrait.kt",
    "content": "package com.uber.artist.traits\n\nimport com.google.auto.service.AutoService\nimport com.squareup.javapoet.AnnotationSpec\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeSpec.Builder\nimport com.uber.artist.api.JavaTrait\n\n@AutoService(JavaTrait::class)\nclass JavaSuppressNullabilityInitializerTrait : JavaTrait {\n  override fun generateFor(\n      type: Builder,\n      initMethod: MethodSpec.Builder,\n      rClass: ClassName,\n      sourceType: String) {\n\n    initMethod.addAnnotation(AnnotationSpec.builder(SuppressWarnings::class.java)\n        .addMember(\"value\", \"\\$S\", \"CheckNullabilityTypes\")\n        .build())\n  }\n}\n\n"
  },
  {
    "path": "artist-traits/src/main/kotlin/com/uber/artist/traits/JavaVisibilityTrait.kt",
    "content": "package com.uber.artist.traits\n\nimport com.google.auto.service.AutoService\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeName\nimport com.squareup.javapoet.TypeSpec.Builder\nimport com.uber.artist.api.JavaTrait\nimport com.uber.artist.api.TypeNames\nimport javax.lang.model.element.Modifier\n\n@AutoService(JavaTrait::class)\nclass JavaVisibilityTrait : JavaTrait {\n  override fun generateFor(\n      type: Builder,\n      initMethod: MethodSpec.Builder,\n      rClass: ClassName,\n      sourceType: String) {\n\n    // Visibility convenience methods\n    arrayOf(\"visible\", \"invisible\", \"gone\")\n        .forEach { type.addMethod(createVisibilityConvenienceMethod(it)) }\n  }\n\n  private fun createVisibilityConvenienceMethod(type: String): MethodSpec {\n    return MethodSpec.methodBuilder(\"is${type.capitalize()}\")\n        .addModifiers(Modifier.PUBLIC)\n        .returns(TypeName.BOOLEAN)\n        .addStatement(\"return getVisibility() == \\$T.${type.toUpperCase()}\", TypeNames.Android.View)\n        .build()\n  }\n}\n"
  },
  {
    "path": "artist-traits/src/main/kotlin/com/uber/artist/traits/KotlinForegroundTrait.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits\n\nimport com.google.auto.service.AutoService\nimport com.squareup.kotlinpoet.AnnotationSpec\nimport com.squareup.kotlinpoet.BOOLEAN\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.FLOAT\nimport com.squareup.kotlinpoet.FunSpec\nimport com.squareup.kotlinpoet.INT\nimport com.squareup.kotlinpoet.KModifier\nimport com.squareup.kotlinpoet.PropertySpec\nimport com.squareup.kotlinpoet.TypeSpec\nimport com.uber.artist.api.KotlinTrait\nimport com.uber.artist.api.KotlinTypeNames\nimport com.uber.artist.api.Trait\n\n/**\n * This [Trait] ports [FrameLayout]'s foreground functionality to other views. In order to use this, the module that\n * applies that [Artist] plugin must declare the ForegroundView styleable in res/values/attrs_foreground_view.xml.\n *\n * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n * <resources>\n *   <declare-styleable name=\"ForegroundView\">\n *     <attr name=\"android:foreground\"/>\n *     <attr name=\"android:foregroundGravity\"/>\n *     <attr name=\"foregroundInsidePadding\"/>\n *   </declare-styleable>\n * </resources>\n */\n@AutoService(KotlinTrait::class)\nclass KotlinForegroundTrait : KotlinTrait {\n  override fun generateFor(\n      type: TypeSpec.Builder,\n      initMethod: FunSpec.Builder,\n      rClass: ClassName,\n      sourceType: String) {\n\n    val isLayout = sourceType.endsWith(\"Layout\")\n\n    // The field\n    type.addProperty(PropertySpec.builder(\"foreground\", KotlinTypeNames.Android.Drawable.copy(nullable = true), KModifier.PRIVATE)\n        .initializer(\"null\")\n        .mutable()\n        .build())\n\n    if (isLayout) {\n      type.addProperty(PropertySpec.builder(\"selfBounds\", KotlinTypeNames.Android.Rect, KModifier.PRIVATE, KModifier.FINAL)\n          .initializer(\"%T()\", KotlinTypeNames.Android.Rect)\n          .build())\n      type.addProperty(PropertySpec.builder(\"overlayBounds\", KotlinTypeNames.Android.Rect, KModifier.PRIVATE, KModifier.FINAL)\n          .initializer(\"%T()\", KotlinTypeNames.Android.Rect)\n          .build())\n      type.addProperty(PropertySpec.builder(\"foregroundInPadding\", BOOLEAN, KModifier.PRIVATE)\n          .initializer(\"true\")\n          .mutable()\n          .build())\n      type.addProperty(PropertySpec.builder(\"foregroundBoundsChanged\", BOOLEAN, KModifier.PRIVATE)\n          .initializer(\"false\")\n          .mutable()\n          .build())\n      type.addProperty(PropertySpec.builder(\"foregroundGravity\", INT, KModifier.PRIVATE)\n          .initializer(\"%T.FILL\", KotlinTypeNames.Android.Gravity)\n          .mutable()\n          .build())\n    }\n\n    // Pull out the value\n    initMethod.apply {\n      addStatement(\"val foregroundTA = context.obtainStyledAttributes(attrs, %T.styleable.ForegroundView)\", rClass)\n      beginControlFlow(\"foregroundTA.getDrawable(%T.styleable.ForegroundView_android_foreground)?.let\", rClass)\n      addCode(\"//noinspection AndroidLintNewApi\\n\")\n      addStatement(\"setForeground(it)\")\n      endControlFlow()\n\n      if (isLayout) {\n        addStatement(\n            \"foregroundGravity = foregroundTA.getInt(%T.styleable.ForegroundView_android_foregroundGravity, foregroundGravity)\", rClass)\n        addStatement(\n            \"foregroundInPadding = foregroundTA.getBoolean(%T.styleable.ForegroundView_foregroundInsidePadding, true)\", rClass)\n      }\n\n      addStatement(\"foregroundTA.recycle()\")\n    }\n\n    val onSizeChangedMethod = FunSpec.builder(\"onSizeChanged\")\n        .addModifiers(KModifier.PROTECTED, KModifier.OPEN, KModifier.OVERRIDE)\n        .addParameter(\"w\", INT)\n        .addParameter(\"h\", INT)\n        .addParameter(\"oldw\", INT)\n        .addParameter(\"oldh\", INT)\n        .addStatement(\"super.onSizeChanged(w, h, oldw, oldh)\")\n\n    if (isLayout) {\n      onSizeChangedMethod.addStatement(\"foregroundBoundsChanged = true\")\n    } else {\n      onSizeChangedMethod.addStatement(\"foreground?.setBounds(0, 0, w, h)\")\n    }\n\n    type.addFunction(onSizeChangedMethod.build())\n\n    if (sourceType.endsWith(\"ImageView\")) {\n      type.addFunction(FunSpec.builder(\"hasOverlappingRendering\")\n          .addModifiers(KModifier.OPEN, KModifier.OVERRIDE)\n          .returns(BOOLEAN)\n          .addStatement(\"return false\")\n          .build())\n    }\n\n    if (isLayout) {\n      type.addFunction(FunSpec.builder(\"getForegroundGravity\")\n          .addKdoc(\"\"\"Describes how the foreground is positioned.\n\n    @return foreground gravity.\n    @see #setForegroundGravity(int)\n    \"\"\")\n          .addAnnotation(AnnotationSpec.builder(SuppressWarnings::class.java).addMember(\"%S\", \"MissingOverride\").build())\n          .addModifiers(KModifier.OPEN, KModifier.OVERRIDE)\n          .returns(INT)\n          .addStatement(\"return foregroundGravity\")\n          .build())\n\n      type.addFunction(FunSpec.builder(\"setForegroundGravity\")\n          .addKdoc(\"\"\"Describes how the foreground is positioned. Defaults to START and TOP.\n\n    @param foregroundGravity See {@link android.view.Gravity}\n    @see #getForegroundGravity()\n    \"\"\")\n          .addAnnotation(AnnotationSpec.builder(SuppressWarnings::class.java).addMember(\"%S\", \"MissingOverride\").build())\n          .addModifiers(KModifier.OPEN, KModifier.OVERRIDE)\n          .addParameter(\"foregroundGravity\", INT)\n          .beginControlFlow(\"if (this.foregroundGravity != foregroundGravity)\")\n          .beginControlFlow(\"if ((foregroundGravity and %T.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0)\",\n              KotlinTypeNames.Android.Gravity)\n          .addStatement(\"this.foregroundGravity = foregroundGravity.or(%T.START)\", KotlinTypeNames.Android.GravityCompat)\n          .endControlFlow()\n          .beginControlFlow(\"if ((foregroundGravity and %T.VERTICAL_GRAVITY_MASK) == 0)\",\n              KotlinTypeNames.Android.Gravity)\n          .addStatement(\"this.foregroundGravity = foregroundGravity.or(%T.TOP)\", KotlinTypeNames.Android.Gravity)\n          .endControlFlow()\n          .beginControlFlow(\"if (this.foregroundGravity == %T.FILL && foreground != null)\",\n              KotlinTypeNames.Android.Gravity)\n          .addStatement(\"val padding = %T()\", KotlinTypeNames.Android.Rect)\n          .addStatement(\"foreground?.getPadding(padding)\")\n          .endControlFlow()\n          .addStatement(\"requestLayout()\")\n          .endControlFlow()\n          .build())\n    }\n\n    type.addFunction(FunSpec.builder(\"verifyDrawable\")\n        .addModifiers(KModifier.PROTECTED, KModifier.OPEN, KModifier.OVERRIDE)\n        .returns(BOOLEAN)\n        .addParameter(\"who\", KotlinTypeNames.Android.Drawable)\n        .addStatement(\"return super.verifyDrawable(who) || (who == foreground)\")\n        .build())\n\n    type.addFunction(FunSpec.builder(\"jumpDrawablesToCurrentState\")\n        .addModifiers(KModifier.OPEN, KModifier.OVERRIDE)\n        .addStatement(\"super.jumpDrawablesToCurrentState()\")\n        .addStatement(\"foreground?.jumpToCurrentState()\")\n        .build())\n\n    type.addFunction(FunSpec.builder(\"drawableStateChanged\")\n        .addModifiers(KModifier.PROTECTED, KModifier.OPEN, KModifier.OVERRIDE)\n        .addStatement(\"super.drawableStateChanged()\")\n        .beginControlFlow(\"if (foreground?.isStateful() ?: false)\")\n        .addStatement(\"foreground?.setState(getDrawableState())\")\n        .endControlFlow()\n        .build())\n\n    type.addFunction(FunSpec.builder(\"getForeground\")\n        .addKdoc(\"\"\"Returns the drawable used as the foreground of this view. The\n    foreground drawable, if non-null, is always drawn on top of the children.\n\n    @return A Drawable or null if no foreground was set.\n    \"\"\")\n        .addAnnotation(AnnotationSpec.builder(SuppressWarnings::class.java).addMember(\"%S\", \"MissingOverride\").build())\n        .addModifiers(KModifier.OPEN, KModifier.OVERRIDE)\n        .returns(KotlinTypeNames.Android.Drawable.copy(nullable = true))\n        .addStatement(\"return foreground\")\n        .build())\n\n    val setForegroundMethod = FunSpec.builder(\"setForeground\")\n        .addKdoc(\"\"\"Supply a Drawable that is to be rendered on top of all of the child\n    views in this layout.  Any padding in the Drawable will be taken\n    into account by ensuring that the children are inset to be placed\n    inside of the padding area.\n\n    @param drawable The Drawable to be drawn on top of the children.\n    \"\"\")\n        .addAnnotation(AnnotationSpec.builder(SuppressWarnings::class.java).addMember(\"%S\", \"MissingOverride\").build())\n        .addAnnotation(AnnotationSpec.builder(ClassName(\"android.annotation\", \"SuppressLint\"))\n            .addMember(\"%S\", \"NewApi\")\n            .build())\n        .addModifiers(KModifier.OPEN, KModifier.OVERRIDE)\n        .addParameter(\"drawable\", KotlinTypeNames.Android.Drawable.copy(nullable = true))\n        .beginControlFlow(\"if (foreground != drawable)\")\n        .beginControlFlow(\"if (foreground != null)\")\n        .addStatement(\"foreground?.setCallback(null)\")\n        .addStatement(\"unscheduleDrawable(foreground)\")\n        .endControlFlow()\n        .addStatement(\"foreground = drawable\")\n        .beginControlFlow(\"if (drawable != null)\")\n\n    if (!isLayout) {\n      setForegroundMethod.addStatement(\"foreground?.setBounds(0, 0, getWidth(), getHeight())\")\n    }\n\n    setForegroundMethod.addStatement(\"setWillNotDraw(false)\")\n        .addStatement(\"drawable.setCallback(this)\")\n        .beginControlFlow(\"if (drawable.isStateful())\")\n        .addStatement(\"drawable.setState(getDrawableState())\")\n        .endControlFlow()\n\n    if (isLayout) {\n      setForegroundMethod.beginControlFlow(\"if (foregroundGravity == %T.FILL)\", KotlinTypeNames.Android.Gravity)\n      setForegroundMethod.addStatement(\"val padding = %T()\", KotlinTypeNames.Android.Rect)\n      setForegroundMethod.addStatement(\"drawable.getPadding(padding)\")\n      setForegroundMethod.endControlFlow()\n    }\n\n    setForegroundMethod.nextControlFlow(\"else\")\n        .addStatement(\"setWillNotDraw(true)\")\n        .endControlFlow()\n\n    if (isLayout) {\n      setForegroundMethod.addStatement(\"requestLayout()\")\n    }\n    setForegroundMethod.addStatement(\"invalidate()\")\n        .endControlFlow()\n\n    type.addFunction(setForegroundMethod.build())\n\n    if (isLayout) {\n      type.addFunction(FunSpec.builder(\"onLayout\")\n          .addModifiers(KModifier.PROTECTED, KModifier.OPEN, KModifier.OVERRIDE)\n          .addParameter(\"changed\", BOOLEAN)\n          .addParameter(\"left\", INT)\n          .addParameter(\"top\", INT)\n          .addParameter(\"right\", INT)\n          .addParameter(\"bottom\", INT)\n          .addStatement(\"super.onLayout(changed, left, top, right, bottom)\")\n          .beginControlFlow(\"if (changed)\")\n          .addStatement(\"foregroundBoundsChanged = true\")\n          .endControlFlow()\n          .build())\n    }\n\n    val drawMethod = FunSpec.builder(\"draw\")\n        .addModifiers(KModifier.OPEN, KModifier.OVERRIDE)\n        .addParameter(\"canvas\", KotlinTypeNames.Android.Canvas)\n        .addStatement(\"super.draw(canvas)\")\n\n    if (isLayout) {\n      drawMethod\n          .beginControlFlow(\"foreground?.let\")\n          .addStatement(\"val localForeground = it\")\n          .beginControlFlow(\"if (foregroundBoundsChanged)\")\n          .addStatement(\"foregroundBoundsChanged = false\")\n          .addStatement(\"val localSelfBounds: %T = selfBounds\", KotlinTypeNames.Android.Rect)\n          .addStatement(\"val localOverlayBounds: %T = overlayBounds\", KotlinTypeNames.Android.Rect)\n          .addStatement(\"val w: Int = getRight() - getLeft()\")\n          .addStatement(\"val h: Int = getBottom() - getTop()\")\n          .beginControlFlow(\"if (foregroundInPadding)\")\n          .addStatement(\"localSelfBounds.set(0, 0, w, h)\")\n          .nextControlFlow(\"else\")\n          .addStatement(\"localSelfBounds.set(getPaddingLeft(), getPaddingTop(), w - getPaddingRight(), h - \" +\n              \"getPaddingBottom())\")\n          .endControlFlow()\n          .addStatement(\"%T.apply(foregroundGravity, localForeground.getIntrinsicWidth(), localForeground\" +\n              \".getIntrinsicHeight(), localSelfBounds, localOverlayBounds)\", KotlinTypeNames.Android.Gravity)\n          .addStatement(\"localForeground.setBounds(localOverlayBounds)\")\n          .endControlFlow()\n          .addStatement(\"localForeground.draw(canvas)\")\n          .endControlFlow()\n    } else {\n      drawMethod.addStatement(\"foreground?.draw(canvas)\")\n    }\n    type.addFunction(drawMethod.build())\n\n    type.addFunction(FunSpec.builder(\"drawableHotspotChanged\")\n        .addAnnotation(AnnotationSpec.builder(KotlinTypeNames.Annotations.TargetApi)\n            .addMember(\"%T.VERSION_CODES.LOLLIPOP\", ClassName(\"android.os\", \"Build\"))\n            .build())\n        .addModifiers(KModifier.OPEN, KModifier.OVERRIDE)\n        .addParameter(\"x\", FLOAT)\n        .addParameter(\"y\", FLOAT)\n        .addStatement(\"super.drawableHotspotChanged(x, y)\")\n        .addStatement(\"foreground?.setHotspot(x, y)\")\n        .build())\n  }\n}\n"
  },
  {
    "path": "artist-traits/src/main/kotlin/com/uber/artist/traits/KotlinSuppressNullabilityInitializerTrait.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits\n\nimport com.google.auto.service.AutoService\nimport com.squareup.kotlinpoet.AnnotationSpec\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.FunSpec\nimport com.squareup.kotlinpoet.TypeSpec\nimport com.uber.artist.api.KotlinTrait\n\n@AutoService(KotlinTrait::class)\nclass KotlinSuppressNullabilityInitializerTrait : KotlinTrait {\n  override fun generateFor(\n      type: TypeSpec.Builder,\n      initMethod: FunSpec.Builder,\n      rClass: ClassName,\n      sourceType: String) {\n\n    initMethod.addAnnotation(AnnotationSpec.builder(SuppressWarnings::class.java)\n        .addMember(\"%S\", \"CheckNullabilityTypes\")\n        .build())\n  }\n}\n"
  },
  {
    "path": "artist-traits/src/main/kotlin/com/uber/artist/traits/KotlinVisibilityTrait.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits\n\nimport com.google.auto.service.AutoService\nimport com.squareup.kotlinpoet.BOOLEAN\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.FunSpec\nimport com.squareup.kotlinpoet.KModifier\nimport com.squareup.kotlinpoet.TypeSpec\nimport com.uber.artist.api.KotlinTrait\nimport com.uber.artist.api.KotlinTypeNames\n\n@AutoService(KotlinTrait::class)\nclass KotlinVisibilityTrait : KotlinTrait {\n  override fun generateFor(\n      type: TypeSpec.Builder,\n      initMethod: FunSpec.Builder,\n      rClass: ClassName,\n      sourceType: String) {\n\n    // Visibility convenience methods\n    arrayOf(\"visible\", \"invisible\", \"gone\")\n        .forEach { type.addFunction(createVisibilityConvenienceMethod(it)) }\n  }\n\n  private fun createVisibilityConvenienceMethod(type: String): FunSpec {\n    return FunSpec.builder(\"is${type.capitalize()}\")\n        .addModifiers(KModifier.OPEN)\n        .returns(BOOLEAN)\n        .addStatement(\"return getVisibility() == %T.${type.toUpperCase()}\", KotlinTypeNames.Android.View)\n        .build()\n  }\n}\n"
  },
  {
    "path": "artist-traits-rx/build.gradle",
    "content": "apply plugin: \"java-library\"\napply plugin: \"org.jetbrains.kotlin.jvm\"\napply plugin: \"org.jetbrains.kotlin.kapt\"\n\nsourceCompatibility = JavaVersion.VERSION_1_7\ntargetCompatibility = JavaVersion.VERSION_1_7\n\ndependencies {\n    kapt deps.apt.autoService\n    compileOnly deps.apt.autoService\n\n    // Also requires RxBinding be on the classpath. Since it is an AAR, we can't include it here.\n    api deps.apt.javapoet\n    api deps.external.rxjava2\n    api deps.external.rxrelay2\n    api project(\":artist-api\")\n\n    implementation deps.kotlin.stdLibJdk7\n}\n\nif (rootProject.projectDir.name != \"buildSrc\") {\n    apply from: rootProject.file('gradle/gradle-mvn-push.gradle')\n}\n"
  },
  {
    "path": "artist-traits-rx/gradle.properties",
    "content": "#\n# Copyright (C) 2017. Uber Technologies\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#    http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\nPOM_NAME=artist-traits-rx\nPOM_ARTIFACT_ID=artist-traits-rx\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/JavaApiHelper.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx\n\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.CodeBlock\nimport com.squareup.javapoet.FieldSpec\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.ParameterSpec\nimport com.squareup.javapoet.ParameterizedTypeName\nimport com.squareup.javapoet.TypeName\nimport com.squareup.javapoet.TypeSpec\nimport com.uber.artist.api.TypeNames\nimport com.uber.artist.traits.rx.config.JavaArtistRxConfigService\nimport javax.lang.model.element.Modifier\n\ndata class JavaRxBindingInfo(\n    val className: ClassName,\n    val methodName: String,\n    val methodDoc: String\n)\n\ndata class JavaSettableApi(\n    val rxBindingInfo: JavaRxBindingInfo,\n    val listenerType: TypeName,\n    val listenerMethod: String,\n    val observableType: TypeName,\n    val listenerImpl: MethodSpec.Builder,\n    val isStateful: Boolean = false,\n    val relayInitializer: CodeBlock? = null,\n    val setterCaveats: String? = null,\n    val isUViewOverride: Boolean = false,\n    val setListenerMethodAnnotations: List<ClassName> = emptyList())\n\ndata class JavaAdditiveApi(\n    val rxBindingInfo: JavaRxBindingInfo,\n    val observableType: TypeName,\n    val isUViewOverride: Boolean = false\n)\n\nprivate fun TypeName.irrelevantIfObject(): TypeName {\n  val artistRxConfig = JavaArtistRxConfigService.newInstance().getArtistRxConfig()\n  return if (this == TypeName.OBJECT.box()) artistRxConfig.rxBindingSignalEventTypeName() else this\n}\n\nfun addRxBindingApiForAdditive(type: TypeSpec.Builder, api: JavaAdditiveApi) {\n  val artistRxConfig = JavaArtistRxConfigService.newInstance().getArtistRxConfig()\n  type.addMethod(MethodSpec.methodBuilder(api.rxBindingInfo.methodName)\n      .addJavadoc(\"${api.rxBindingInfo.methodDoc}\\n\")\n      .apply {\n        if (api.isUViewOverride) {\n          addAnnotation(Override::class.java)\n        }\n      }\n      .addModifiers(Modifier.PUBLIC)\n      .returns(ParameterizedTypeName.get(JavaRxTypeNames.Rx.Observable, api.observableType.irrelevantIfObject()))\n      .addCode(CodeBlock.builder()\n          .add(\"return \\$T.${api.rxBindingInfo.methodName}(this)\", api.rxBindingInfo.className)\n          .apply {\n            if (api.observableType == TypeName.OBJECT.box()) {\n              artistRxConfig.processRxBindingSignalEvent(this)\n            }\n            if (api.rxBindingInfo.methodName != \"attachEvents\") {\n              // Safe to call, otherwise it'd be a recursive stack overflow\n              artistRxConfig.processRxBindingStream(this, api.observableType.irrelevantIfObject())\n            }\n            add(\";\")\n          }\n          .build())\n      .build())\n}\n\nfun addRxBindingApiForSettable(type: TypeSpec.Builder, api: JavaSettableApi, isDebug: Boolean = true) {\n  val artistRxConfig = JavaArtistRxConfigService.newInstance().getArtistRxConfig()\n  val rxBindingClassName = api.rxBindingInfo.className\n  val rxBindingMethod = api.rxBindingInfo.methodName\n  val rxBindingMethodDoc = api.rxBindingInfo.methodDoc\n  val isInitting = \"${api.rxBindingInfo.methodName}IsInitting\"\n  val disposable = \"${api.rxBindingInfo.methodName}Disposable\"\n\n  // clicksInitting\n  type.addField(TypeName.BOOLEAN, isInitting, Modifier.PRIVATE)\n\n  // internal relay\n  type.addField(\n      FieldSpec.builder(ParameterizedTypeName.get(if (api.isStateful) JavaRxTypeNames.Rx.BehaviorRelay else JavaRxTypeNames.Rx.PublishRelay,\n          api.observableType.irrelevantIfObject()),\n          rxBindingMethod,\n          Modifier.PRIVATE)\n          .addAnnotation(TypeNames.Annotations.Nullable).build())\n\n  type.addField(FieldSpec.builder(JavaRxTypeNames.Rx.Disposable, disposable, Modifier.PRIVATE).addAnnotation(TypeNames.Annotations.Nullable).build())\n\n  val consumer = TypeSpec.anonymousClassBuilder(\"\")\n      .addSuperinterface(ParameterizedTypeName.get(JavaRxTypeNames.Rx.Consumer, api.observableType.irrelevantIfObject()))\n      .addMethod(api.listenerImpl.addAnnotation(Override::class.java).build())\n      .build()\n\n  // Overridden and deprecated setOnClickListener method\n  type.addMethod(MethodSpec.methodBuilder(api.listenerMethod)\n      .addJavadoc(StringBuilder().apply {\n        if (api.setterCaveats != null) {\n          append(api.setterCaveats)\n          append(\"\\n\\n\")\n        }\n      }.append(\"@deprecated Use {@link #$rxBindingMethod()}\\n\").toString())\n      .addModifiers(Modifier.PUBLIC, Modifier.FINAL)\n      .addAnnotation(Override::class.java)\n      .addAnnotation(java.lang.Deprecated::class.java)\n      .addParameter(\n          ParameterSpec.builder(api.listenerType, \"l\", Modifier.FINAL).apply {\n            api.setListenerMethodAnnotations.forEach {\n              addAnnotation(it)\n            }\n          }.build()\n      )\n      .beginControlFlow(\"if ($isInitting)\")\n      .addStatement(\"$isInitting = false\")\n      .addStatement(\"super.${api.listenerMethod}(l)\")\n      .nextControlFlow(\"else\")\n      .beginControlFlow(\"if ($disposable != null)\")\n      .addStatement(\"$disposable.dispose()\")\n      .addStatement(\"$disposable = null\")\n      .endControlFlow()\n      .beginControlFlow(\"if (l != null)\")\n      .addCode(CodeBlock.builder()\n          .add(\"$disposable = $rxBindingMethod()\")\n          .add(\".subscribe(\\$L);\", consumer)\n          .build())\n      .endControlFlow()\n      .endControlFlow()\n      .build())\n\n  type.addMethod(MethodSpec.methodBuilder(rxBindingMethod)\n      .addJavadoc(rxBindingMethodDoc)\n      .apply {\n        if (api.isUViewOverride) {\n          addAnnotation(Override::class.java)\n        }\n      }\n      .addModifiers(Modifier.PUBLIC)\n      .returns(ParameterizedTypeName.get(JavaRxTypeNames.Rx.Observable, api.observableType.irrelevantIfObject()))\n      .beginControlFlow(\"if ($rxBindingMethod == null)\")\n      .addStatement(\"$isInitting = true\")\n      .apply {\n        if (api.relayInitializer != null) {\n          addCode(\"$rxBindingMethod = \", JavaRxTypeNames.Rx.BehaviorRelay)\n          addCode(api.relayInitializer)\n          addCode(\";\\n\")\n        } else {\n          addStatement(\"$rxBindingMethod = \\$T.create()\",\n              if (api.isStateful) JavaRxTypeNames.Rx.BehaviorRelay else JavaRxTypeNames.Rx.PublishRelay)\n        }\n      }\n      .addCode(CodeBlock.builder()\n          .add(\"\\$T.$rxBindingMethod(this)\", rxBindingClassName)\n          .apply {\n            if (api.observableType == TypeName.OBJECT.box()) {\n              artistRxConfig.processRxBindingSignalEvent(this)\n            }\n            if (rxBindingMethod.contains(\"click\", true)) {\n              artistRxConfig.processTap(this)\n            }\n          }\n          .addStatement(\"\\n\\t.subscribe($rxBindingMethod)\")\n          .build())\n      .endControlFlow()\n      .addCode(CodeBlock.builder()\n          .add(\"return $rxBindingMethod.hide()\")\n          .apply { artistRxConfig.processRxBindingStream(this, api.observableType.irrelevantIfObject()) }\n          .add(\";\")\n          .build())\n      .build())\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/JavaCheckableTrait.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx\n\nimport com.google.auto.service.AutoService\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.CodeBlock\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.ParameterizedTypeName\nimport com.squareup.javapoet.TypeName\nimport com.squareup.javapoet.TypeSpec\nimport com.uber.artist.api.JavaTrait\nimport com.uber.artist.api.TypeNames\nimport javax.lang.model.element.Modifier\n\n@AutoService(JavaTrait::class)\nclass JavaCheckableTrait : JavaTrait {\n  override fun generateFor(\n      type: TypeSpec.Builder,\n      initMethod: MethodSpec.Builder,\n      rClass: ClassName,\n      baseType: String) {\n\n    val isTextView = baseType.endsWith(\"TextView\")\n\n    if (isTextView) {\n      type.addField(\n          ParameterizedTypeName.get(JavaRxTypeNames.Rx.BehaviorRelay, TypeName.BOOLEAN.box()), \"checkedChanges\",\n          Modifier.PRIVATE)\n      type.addMethod(MethodSpec.methodBuilder(\"ensureCheckedChanges\")\n          .addModifiers(Modifier.PRIVATE)\n          .beginControlFlow(\"if (checkedChanges == null)\")\n          .addStatement(\"checkedChanges = \\$T.create()\", JavaRxTypeNames.Rx.BehaviorRelay)\n          .endControlFlow()\n          .build())\n      type.addMethod(MethodSpec.methodBuilder(\"checkedChanges\")\n          .addJavadoc(\"\"\"@return an observable of booleans representing the checked state of this view.\n    \"\"\")\n          .addModifiers(Modifier.PUBLIC)\n          .returns(ParameterizedTypeName.get(JavaRxTypeNames.Rx.Observable, TypeName.BOOLEAN.box()))\n          .addStatement(\"ensureCheckedChanges()\")\n          .addStatement(\"return checkedChanges.hide()\")\n          .build())\n      type.addMethod(MethodSpec.methodBuilder(\"setChecked\")\n          .addModifiers(Modifier.PUBLIC)\n          .addAnnotation(Override::class.java)\n          .addParameter(TypeName.BOOLEAN, \"val\")\n          .addStatement(\"super.setChecked(val)\")\n          .addStatement(\"ensureCheckedChanges()\")\n          .addStatement(\"checkedChanges.accept(val)\")\n          .build())\n    } else {\n      addRxBindingApiForSettable(type, JavaSettableApi(\n          JavaRxBindingInfo(JavaRxTypeNames.Rx.RxCompoundButton,\n              \"checkedChanges\",\n              \"\"\"@return an observable of booleans representing the checked state of this view.\n    \"\"\"),\n          ClassName.bestGuess(\"OnCheckedChangeListener\"),\n          \"setOnCheckedChangeListener\",\n          TypeName.BOOLEAN.box(),\n          MethodSpec.methodBuilder(\"accept\")\n              .addModifiers(Modifier.PUBLIC)\n              .addParameter(TypeName.BOOLEAN.box(), \"isChecked\")\n              .addStatement(\"l.onCheckedChanged($baseType.this, isChecked)\"),\n          true,\n          CodeBlock.of(\"\\$T.createDefault(isChecked())\", JavaRxTypeNames.Rx.BehaviorRelay),\n          setListenerMethodAnnotations = listOf(TypeNames.Annotations.Nullable)\n      ))\n    }\n  }\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/JavaRxTypeNames.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx\n\nimport com.squareup.javapoet.ClassName\n\nclass JavaRxTypeNames {\n  class Rx {\n    companion object {\n      // Rx\n      val Consumer = ClassName.get(io.reactivex.functions.Consumer::class.java)\n      val Disposable = ClassName.get(io.reactivex.disposables.Disposable::class.java)\n      val Function = ClassName.get(io.reactivex.functions.Function::class.java)\n      val Observable = ClassName.get(io.reactivex.Observable::class.java)\n\n      // RxRelay\n      val BehaviorRelay = ClassName.get(com.jakewharton.rxrelay2.BehaviorRelay::class.java)\n      val PublishRelay = ClassName.get(com.jakewharton.rxrelay2.PublishRelay::class.java)\n\n      // RxBinding\n      val RecyclerViewScrollEvent = ClassName.get(\"com.jakewharton.rxbinding3.recyclerview\", \"RecyclerViewScrollEvent\")\n      val RxView = ClassName.get(\"com.jakewharton.rxbinding3.view\", \"RxView\")\n      val RxCompoundButton = ClassName.get(\"com.jakewharton.rxbinding3.widget\", \"RxCompoundButton\")\n      val RxNestedScrollView = ClassName.get(\"com.jakewharton.rxbinding3.core\", \"RxNestedScrollView\")\n      val RxRecyclerView = ClassName.get(\"com.jakewharton.rxbinding3.recyclerview\", \"RxRecyclerView\")\n      val RxSearchView = ClassName.get(\"com.jakewharton.rxbinding3.appcompat\", \"RxSearchView\")\n      val RxSeekBar = ClassName.get(\"com.jakewharton.rxbinding3.widget\", \"RxSeekBar\")\n      val SeekBarChangeEvent = ClassName.get(\"com.jakewharton.rxbinding3.widget\", \"SeekBarChangeEvent\")\n      val SeekBarProgressChangeEvent = ClassName.get(\"com.jakewharton.rxbinding3.widget\", \"SeekBarProgressChangeEvent\")\n      val SeekBarStartChangeEvent = ClassName.get(\"com.jakewharton.rxbinding3.widget\", \"SeekBarStartChangeEvent\")\n      val RxSwipeRefreshLayout = ClassName.get(\"com.jakewharton.rxbinding3.swiperefreshlayout\", \"RxSwipeRefreshLayout\")\n      val RxTabLayout = ClassName.get(\"com.jakewharton.rxbinding3.material\", \"RxTabLayout\")\n      val RxTextView = ClassName.get(\"com.jakewharton.rxbinding3.widget\", \"RxTextView\")\n      val RxToolbar = ClassName.get(\"com.jakewharton.rxbinding3.widget\", \"RxToolbar\")\n      val RxViewPager = ClassName.get(\"com.jakewharton.rxbinding3.viewpager\", \"RxViewPager\")\n      val RxViewAttachEvent = ClassName.get(\"com.jakewharton.rxbinding3.view\", \"ViewAttachEvent\")\n      val RxViewAttachAttachedEvent = ClassName.get(\"com.jakewharton.rxbinding3.view\", \"ViewAttachAttachedEvent\")\n      val RxViewAttachDetachedEvent = ClassName.get(\"com.jakewharton.rxbinding3.view\", \"ViewAttachDetachedEvent\")\n      val SearchViewQueryTextEvent = ClassName.get(\"com.jakewharton.rxbinding3.appcompat\", \"SearchViewQueryTextEvent\")\n      val ViewScrollChangeEvent = ClassName.get(\"com.jakewharton.rxbinding3.view\", \"ViewScrollChangeEvent\")\n    }\n  }\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/JavaScrollableTrait.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx\n\nimport com.google.auto.service.AutoService\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeSpec\nimport com.uber.artist.api.JavaTrait\nimport javax.lang.model.element.Modifier\n\n@AutoService(JavaTrait::class)\nclass JavaScrollableTrait : JavaTrait {\n  override fun generateFor(\n      type: TypeSpec.Builder,\n      initMethod: MethodSpec.Builder,\n      rClass: ClassName,\n      sourceType: String) {\n\n    // ScrollView overrides\n    if (sourceType.contains(\"ScrollView\")) {\n      addRxBindingApiForSettable(type, JavaSettableApi(\n          JavaRxBindingInfo(JavaRxTypeNames.Rx.RxNestedScrollView,\n              \"scrollChangeEvents\",\n              \"\"\"@return an observable of scroll-change events for this NestedScrollView.\n    \"\"\"),\n          ClassName.bestGuess(\"OnScrollChangeListener\"),\n          \"setOnScrollChangeListener\",\n          JavaRxTypeNames.Rx.ViewScrollChangeEvent,\n          MethodSpec.methodBuilder(\"accept\")\n              .addModifiers(Modifier.PUBLIC)\n              .addParameter(JavaRxTypeNames.Rx.ViewScrollChangeEvent, \"event\")\n              .addStatement(\"l.onScrollChange($sourceType.this, event.getScrollX(), event\" +\n                  \".getScrollY\" +\n                  \"(), event.getOldScrollX(), event.getOldScrollY())\")))\n    }\n\n    // RecyclerView overrides\n    if (sourceType.contains(\"RecyclerView\")) {\n      addRxBindingApiForAdditive(type, JavaAdditiveApi(\n          JavaRxBindingInfo(JavaRxTypeNames.Rx.RxRecyclerView,\n              \"scrollEvents\",\n              \"@return an observable of scroll events on this RecyclerView\"),\n          JavaRxTypeNames.Rx.RecyclerViewScrollEvent))\n    }\n  }\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/JavaTextInputTrait.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx\n\nimport com.google.auto.service.AutoService\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeSpec\nimport com.uber.artist.api.JavaTrait\n\n@AutoService(JavaTrait::class)\nclass JavaTextInputTrait : JavaTrait {\n  override fun generateFor(\n      type: TypeSpec.Builder,\n      initMethod: MethodSpec.Builder,\n      rClass: ClassName,\n      sourceType: String) {\n\n    // TextChanges\n    addRxBindingApiForAdditive(type, JavaAdditiveApi(\n        JavaRxBindingInfo(JavaRxTypeNames.Rx.RxTextView,\n            \"textChanges\",\n            \"\"\"@return an observable of character sequences for text changes on this TextView.\"\"\"),\n        ClassName.get(CharSequence::class.java)))\n  }\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/JavaViewTrait.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx\n\nimport com.google.auto.service.AutoService\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeName\nimport com.squareup.javapoet.TypeSpec\nimport com.uber.artist.api.JavaTrait\nimport com.uber.artist.api.TypeNames\nimport com.uber.artist.traits.rx.config.JavaArtistRxConfigService\nimport javax.lang.model.element.Modifier\n\n@AutoService(JavaTrait::class)\nopen class JavaViewTrait : JavaTrait {\n  private val artistRxConfig by lazy { JavaArtistRxConfigService.newInstance().getArtistRxConfig() }\n\n  override fun generateFor(\n      type: TypeSpec.Builder,\n      initMethod: MethodSpec.Builder,\n      rClass: ClassName,\n      sourceType: String) {\n\n    clicks(type, sourceType)\n    longClicks(type, sourceType)\n    layoutChanges(type)\n  }\n\n  open fun clicks(type: TypeSpec.Builder, sourceType: String) {\n    addRxBindingApiForSettable(type, JavaSettableApi(\n        JavaRxBindingInfo(JavaRxTypeNames.Rx.RxView,\n            \"clicks\",\n            \"\"\"@return an Observable of click events. The emitted value is unspecified and should only be used as notification.\n    \"\"\"),\n        ClassName.bestGuess(\"OnClickListener\"),\n        \"setOnClickListener\",\n        TypeName.OBJECT.box(),\n        MethodSpec.methodBuilder(\"accept\")\n            .addModifiers(Modifier.PUBLIC)\n            .addParameter(artistRxConfig.rxBindingSignalEventTypeName(), \"ignored\")\n            .addStatement(\"l.onClick($sourceType.this)\"),\n        setListenerMethodAnnotations = listOf(TypeNames.Annotations.Nullable)\n    ))\n  }\n\n  open fun longClicks(type: TypeSpec.Builder, sourceType: String) {\n    addRxBindingApiForSettable(type, JavaSettableApi(\n        JavaRxBindingInfo(JavaRxTypeNames.Rx.RxView,\n            \"longClicks\",\n            \"\"\"@return an Observable of longclick events. The emitted value is unspecified and should only be used as notification.\n    \"\"\"),\n        ClassName.bestGuess(\"OnLongClickListener\"),\n        \"setOnLongClickListener\",\n        TypeName.OBJECT.box(),\n        MethodSpec.methodBuilder(\"accept\")\n            .addModifiers(Modifier.PUBLIC)\n            .addParameter(artistRxConfig.rxBindingSignalEventTypeName(), \"ignored\")\n            .addStatement(\"l.onLongClick($sourceType.this)\"),\n        setListenerMethodAnnotations = listOf(TypeNames.Annotations.Nullable)\n    ))\n  }\n\n  open fun layoutChanges(type: TypeSpec.Builder) {\n    // Attach state changes observable\n    addRxBindingApiForAdditive(type, JavaAdditiveApi(\n        JavaRxBindingInfo(\n            JavaRxTypeNames.Rx.RxView,\n            \"layoutChanges\",\n            \"@return an observable which emits on layout changes. The emitted value is \" +\n                \"unspecified and should only be used as notification.\"),\n        TypeName.OBJECT.box()))\n  }\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/KotlinApiHelper.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx\n\nimport AliasTypeNames.Rx.Companion.rxExtensionFunctionToAlias\nimport com.squareup.kotlinpoet.AnnotationSpec\nimport com.squareup.kotlinpoet.BOOLEAN\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.CodeBlock\nimport com.squareup.kotlinpoet.FunSpec\nimport com.squareup.kotlinpoet.KModifier\nimport com.squareup.kotlinpoet.ParameterSpec\nimport com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy\nimport com.squareup.kotlinpoet.PropertySpec\nimport com.squareup.kotlinpoet.TypeName\nimport com.squareup.kotlinpoet.TypeSpec\nimport com.squareup.kotlinpoet.asClassName\nimport com.uber.artist.api.KotlinTypeNames\nimport com.uber.artist.traits.rx.config.KotlinArtistRxConfigService\n\ndata class KotlinRxBindingInfo(\n    val className: ClassName,\n    val methodName: String,\n    val methodDoc: String\n)\n\nfun KotlinRxBindingInfo.getRxAlias(): String? {\n  val rxBindingClassName = className\n  val rxBindingMethod = methodName\n  val alias_keys = rxExtensionFunctionToAlias.filter {\n    it.key.methodName == rxBindingMethod && it.key\n        .className == rxBindingClassName\n  }.keys.toList()\n\n  val rx_alias = if (alias_keys.size > 0) {\n    rxExtensionFunctionToAlias[alias_keys[0]]\n  } else {\n    null\n  }\n  return rx_alias\n}\n\ndata class KotlinSettableApi(\n    val rxBindingInfo: KotlinRxBindingInfo,\n    val listenerType: TypeName,\n    val listenerMethod: String,\n    val observableType: TypeName,\n    val listenerImpl: FunSpec.Builder,\n    val isStateful: Boolean = false,\n    val relayInitializer: CodeBlock? = null,\n    val setterCaveats: String? = null,\n    val isUViewOverride: Boolean = false,\n    val setListenerMethodAnnotations: List<ClassName> = emptyList())\n\ndata class KotlinAdditiveApi(\n    val rxBindingInfo: KotlinRxBindingInfo,\n    val observableType: TypeName,\n    val isUViewOverride: Boolean = false\n)\n\nprivate fun TypeName.irrelevantIfObject(): TypeName {\n  val artistRxConfig = KotlinArtistRxConfigService.newInstance().getArtistRxConfig()\n  return if (this == KotlinTypeNames.Java.Object) artistRxConfig.rxBindingSignalEventTypeName() else this\n}\n\nfun addRxBindingApiForAdditive(type: TypeSpec.Builder, api: KotlinAdditiveApi) {\n  val artistRxConfig = KotlinArtistRxConfigService.newInstance().getArtistRxConfig()\n  val rx_alias = api.rxBindingInfo.getRxAlias()\n  type.addFunction(FunSpec.builder(api.rxBindingInfo.methodName)\n      .addKdoc(\"${api.rxBindingInfo.methodDoc}\\n\")\n      .apply {\n        if (api.isUViewOverride) {\n          addModifiers(KModifier.OVERRIDE)\n        }\n      }\n      .addModifiers(KModifier.OPEN)\n      .returns(KotlinRxTypeNames.Rx.Observable.parameterizedBy(api.observableType.irrelevantIfObject()))\n      .addCode(CodeBlock.builder()\n          .apply {\n            if (rx_alias != null) {\n              add(\"return ${rx_alias}()\")\n            } else {\n              add(\"return ${api.rxBindingInfo.methodName}()\")\n            }\n          }\n          .apply {\n            if (api.observableType == KotlinTypeNames.Java.Object) {\n              artistRxConfig.processRxBindingSignalEvent(this)\n            }\n            if (api.rxBindingInfo.methodName != \"attachEvents\") {\n              // Safe to call, otherwise it'd be a recursive stack overflow\n              artistRxConfig.processRxBindingStream(this, api.observableType.irrelevantIfObject())\n            }\n          }\n          .add(\"\\n\")\n          .build())\n      .build())\n}\n\nfun addRxBindingApiForSettable(type: TypeSpec.Builder, api: KotlinSettableApi, isDebug: Boolean = true) {\n  val artistRxConfig = KotlinArtistRxConfigService.newInstance().getArtistRxConfig()\n  val rxBindingClassName = api.rxBindingInfo.className\n  val rxBindingMethod = api.rxBindingInfo.methodName\n  val rxBindingMethodDoc = api.rxBindingInfo.methodDoc\n  val isInitting = \"${api.rxBindingInfo.methodName}IsInitting\"\n  val disposable = \"${api.rxBindingInfo.methodName}Disposable\"\n\n  val rx_alias = api.rxBindingInfo.getRxAlias()\n\n  // clicksInitting\n  type.addProperty(PropertySpec.builder(isInitting, BOOLEAN, KModifier.PRIVATE)\n      .mutable()\n      .initializer(\"false\")\n      .build())\n\n  // internal relay\n  val internalRelayTypeName = if (api.isStateful) KotlinRxTypeNames.Rx.BehaviorRelay else KotlinRxTypeNames.Rx.PublishRelay\n  type.addProperty(\n      PropertySpec.builder(rxBindingMethod, internalRelayTypeName.parameterizedBy(api.observableType.irrelevantIfObject()).copy(nullable = true),\n          KModifier.PRIVATE)\n          .mutable()\n          .initializer(\"null\")\n          .build())\n\n  type.addProperty(PropertySpec.builder(disposable, KotlinRxTypeNames.Rx.Disposable.copy(nullable = true), KModifier.PRIVATE)\n      .mutable()\n      .initializer(\"null\")\n      .build())\n\n  val consumer = TypeSpec.anonymousClassBuilder()\n      .addSuperinterface(KotlinRxTypeNames.Rx.Consumer.parameterizedBy(api.observableType.irrelevantIfObject()))\n      .addFunction(api.listenerImpl.addModifiers(KModifier.OVERRIDE).build())\n      .build()\n\n  // Overridden and deprecated setOnClickListener method\n  type.addFunction(FunSpec.builder(api.listenerMethod)\n      .addKdoc(StringBuilder().apply {\n        if (api.setterCaveats != null) {\n          append(api.setterCaveats)\n          append(\"\\n\\n\")\n        }\n      }.append(\"@deprecated Use [$rxBindingMethod]\\n\").toString())\n      .addModifiers(KModifier.FINAL, KModifier.OVERRIDE)\n      .addAnnotation(AnnotationSpec.builder(Deprecated::class.java)\n          .addMember(\"message = %S\", \"Use $rxBindingMethod()\")\n          .addMember(\"replaceWith = %T(%S)\", ReplaceWith::class.asClassName(), \"$rxBindingMethod()\")\n          .addMember(\"level = %T.ERROR\", DeprecationLevel::class.asClassName())\n          .build())\n      .addParameter(\n          ParameterSpec.builder(\"l\", api.listenerType.copy(nullable = true)).apply {\n            api.setListenerMethodAnnotations.forEach {\n              addAnnotation(it)\n            }\n          }.build()\n      )\n      .beginControlFlow(\"if ($isInitting)\")\n      .addStatement(\"$isInitting = false\")\n      .addStatement(\"super.${api.listenerMethod}(l)\")\n      .nextControlFlow(\"else\")\n      .addStatement(\"$disposable?.dispose()\")\n      .addStatement(\"$disposable = null\")\n      .beginControlFlow(\"if (l != null)\")\n      .addCode(CodeBlock.builder()\n          .add(\"$disposable = $rxBindingMethod()\")\n          .add(\".subscribe($consumer)\\n\")\n          .build())\n      .endControlFlow()\n      .endControlFlow()\n      .build())\n\n  type.addFunction(FunSpec.builder(rxBindingMethod)\n      .addKdoc(rxBindingMethodDoc)\n      .apply {\n        if (api.isUViewOverride) {\n          addModifiers(KModifier.OVERRIDE)\n        }\n      }\n      .addModifiers(KModifier.OPEN)\n      .returns(KotlinRxTypeNames.Rx.Observable.parameterizedBy(api.observableType.irrelevantIfObject()))\n      .beginControlFlow(\"if ($rxBindingMethod == null)\")\n      .addStatement(\"$isInitting = true\")\n      .apply {\n        if (api.relayInitializer != null) {\n          addCode(\"$rxBindingMethod = \", KotlinRxTypeNames.Rx.BehaviorRelay)\n          addCode(api.relayInitializer)\n        } else {\n          addStatement(\"$rxBindingMethod = %T.create()\",\n              if (api.isStateful) KotlinRxTypeNames.Rx.BehaviorRelay else KotlinRxTypeNames.Rx.PublishRelay)\n        }\n      }\n      .addCode(CodeBlock.builder()\n          .apply {\n            add(\"$rxBindingMethod?.let {\\n\")\n          }\n          .apply {\n            if (rx_alias != null) {\n              add(\"$rx_alias()\")\n            } else {\n              add(\"%T.$rxBindingMethod(this)\", rxBindingClassName)\n            }\n          }\n          .apply {\n            if (api.observableType == KotlinTypeNames.Java.Object) {\n              artistRxConfig.processRxBindingSignalEvent(this)\n            }\n            if (rxBindingMethod.contains(\"click\", true)) {\n              artistRxConfig.processTap(this)\n            }\n          }\n          .addStatement(\".subscribe(it)\")\n          .addStatement(\" }\\n\")\n          .build())\n      .endControlFlow()\n      .addCode(CodeBlock.builder()\n          .add(\"return $rxBindingMethod?.hide()?\")\n          .apply { artistRxConfig.processRxBindingStream(this, api.observableType.irrelevantIfObject()) }\n          .add(\" ?: Observable.empty()\")\n          .build())\n      .build())\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/KotlinCheckableTrait.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx\n\nimport com.google.auto.service.AutoService\nimport com.squareup.kotlinpoet.BOOLEAN\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.CodeBlock\nimport com.squareup.kotlinpoet.FunSpec\nimport com.squareup.kotlinpoet.KModifier\nimport com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy\nimport com.squareup.kotlinpoet.PropertySpec\nimport com.squareup.kotlinpoet.TypeSpec\nimport com.uber.artist.api.KotlinTrait\n\n@AutoService(KotlinTrait::class)\nclass KotlinCheckableTrait : KotlinTrait {\n  override fun generateFor(\n      type: TypeSpec.Builder,\n      initMethod: FunSpec.Builder,\n      rClass: ClassName,\n      baseType: String) {\n\n    val isTextView = baseType.endsWith(\"TextView\")\n\n    if (isTextView) {\n      type.addProperty(PropertySpec.builder(\n          \"checkedChanges\",\n          KotlinRxTypeNames.Rx.BehaviorRelay.parameterizedBy(BOOLEAN).copy(nullable = true),\n          KModifier.PRIVATE)\n          .mutable()\n          .initializer(\"null\")\n          .build())\n      type.addFunction(FunSpec.builder(\"ensureCheckedChanges\")\n          .addModifiers(KModifier.PRIVATE)\n          .beginControlFlow(\"if (checkedChanges == null)\")\n          .addStatement(\"checkedChanges = %T.create()\", KotlinRxTypeNames.Rx.BehaviorRelay)\n          .endControlFlow()\n          .build())\n      type.addFunction(FunSpec.builder(\"checkedChanges\")\n          .addKdoc(\"\"\"@return an observable of booleans representing the checked state of this view.\n    \"\"\")\n          .addModifiers(KModifier.OPEN)\n          .returns(KotlinRxTypeNames.Rx.Observable.parameterizedBy(BOOLEAN))\n          .addStatement(\"ensureCheckedChanges()\")\n          .addStatement(\"return checkedChanges!!.hide()\")\n          .build())\n      type.addFunction(FunSpec.builder(\"setChecked\")\n          .addModifiers(KModifier.OPEN, KModifier.OVERRIDE)\n          .addParameter(\"value\", BOOLEAN)\n          .addStatement(\"super.setChecked(value)\")\n          .addStatement(\"ensureCheckedChanges()\")\n          .addStatement(\"checkedChanges!!.accept(value)\")\n          .build())\n    } else {\n      addRxBindingApiForSettable(type, KotlinSettableApi(\n          KotlinRxBindingInfo(KotlinRxTypeNames.Rx.RxCompoundButton,\n              \"checkedChanges\",\n              \"\"\"@return an observable of booleans representing the checked state of this view.\n    \"\"\"),\n          ClassName.bestGuess(\"android.widget.CompoundButton.OnCheckedChangeListener\"),\n          \"setOnCheckedChangeListener\",\n          BOOLEAN,\n          FunSpec.builder(\"accept\")\n              .addParameter(\"isChecked\", BOOLEAN)\n              .addStatement(\"l.onCheckedChanged(this@$baseType, isChecked)\"),\n          true,\n          CodeBlock.of(\"%T.createDefault(isChecked())\\n\", KotlinRxTypeNames.Rx.BehaviorRelay)\n      ))\n    }\n  }\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/KotlinRxTypeNames.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx\n\nimport com.jakewharton.rxrelay2.BehaviorRelay\nimport com.jakewharton.rxrelay2.PublishRelay\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.asClassName\nimport io.reactivex.Observable\nimport io.reactivex.disposables.Disposable\nimport io.reactivex.functions.Consumer\nimport io.reactivex.functions.Function\n\nclass KotlinRxTypeNames {\n  class Rx {\n    companion object {\n      // Rx\n      val Consumer = Consumer::class.asClassName()\n      val Disposable = Disposable::class.asClassName()\n      val Function = Function::class.asClassName()\n      val Observable = Observable::class.asClassName()\n\n      // RxRelay\n      val BehaviorRelay = BehaviorRelay::class.asClassName()\n      val PublishRelay = PublishRelay::class.asClassName()\n\n      // As a consequence of RxBinding2 migrating to RxBinding3 and replacing its static calls\n      // with equivalent extension functions, its important that we do not interrupt any existing\n      // code that was created with RxBinding2 in mind, namely the function names. This can mean\n      // that function names share the same name as the extension function which is being used in\n      // lieu of the original static function.\n\n      //Ideally, we would come up with a better way of listing these classes so as to keep this DRY.\n\n      // RxBinding\n      val RecyclerViewScrollEvent = AliasTypeNames.Rx.RecyclerViewScrollEvent\n      val RxView = AliasTypeNames.Rx.RxView\n      val RxCompoundButton = AliasTypeNames.Rx.RxCompoundButton\n      val RxNestedScrollView = AliasTypeNames.Rx.RxNestedScrollView\n      val RxRecyclerView = AliasTypeNames.Rx.RxRecyclerView\n      val RxSearchView = AliasTypeNames.Rx.RxSearchView\n      val RxSeekBar =  AliasTypeNames.Rx.RxSeekBar\n      val SeekBarChangeEvent =  AliasTypeNames.Rx.SeekBarChangeEvent\n      val SeekBarProgressChangeEvent =  AliasTypeNames.Rx.SeekBarProgressChangeEvent\n      val SeekBarStartChangeEvent =  AliasTypeNames.Rx.SeekBarStartChangeEvent\n      val RxSwipeRefreshLayout = AliasTypeNames.Rx.RxSwipeRefreshLayout\n      val RxTabLayout = AliasTypeNames.Rx.RxTabLayout\n      val RxTextView = AliasTypeNames.Rx.RxTextView\n      val RxToolbar = AliasTypeNames.Rx.RxToolbar\n      val RxViewPager = AliasTypeNames.Rx.RxViewPager\n      val RxViewAttachEvent = AliasTypeNames.Rx.RxViewAttachEvent\n      val RxViewAttachAttachedEvent = AliasTypeNames.Rx.RxViewAttachAttachedEvent\n      val RxViewAttachDetachedEvent = AliasTypeNames.Rx.RxViewAttachDetachedEvent\n      val SearchViewQueryTextEvent = AliasTypeNames.Rx.SearchViewQueryTextEvent\n      val ViewScrollChangeEvent = AliasTypeNames.Rx.ViewScrollChangeEvent\n    }\n  }\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/KotlinScrollableTrait.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx\n\nimport com.google.auto.service.AutoService\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.FunSpec\nimport com.squareup.kotlinpoet.TypeSpec\nimport com.uber.artist.api.KotlinTrait\n\n@AutoService(KotlinTrait::class)\nclass KotlinScrollableTrait : KotlinTrait {\n  override fun generateFor(\n      type: TypeSpec.Builder,\n      initMethod: FunSpec.Builder,\n      rClass: ClassName,\n      sourceType: String) {\n\n    // ScrollView overrides\n    if (sourceType.contains(\"ScrollView\")) {\n      addRxBindingApiForSettable(type, KotlinSettableApi(\n          KotlinRxBindingInfo(KotlinRxTypeNames.Rx.RxNestedScrollView,\n              \"scrollChangeEvents\",\n              \"\"\"@return an observable of scroll-change events for this NestedScrollView.\n    \"\"\"),\n          ClassName.bestGuess(\"androidx.core.widget.NestedScrollView.OnScrollChangeListener\"),\n          \"setOnScrollChangeListener\",\n          KotlinRxTypeNames.Rx.ViewScrollChangeEvent,\n          FunSpec.builder(\"accept\")\n              .addParameter(\"event\", KotlinRxTypeNames.Rx.ViewScrollChangeEvent)\n              .addStatement(\"l.onScrollChange(this@$sourceType, event.scrollX, event.scrollY, event.oldScrollX, event.oldScrollY)\")))\n    }\n\n    // RecyclerView overrides\n    if (sourceType.contains(\"RecyclerView\")) {\n      addRxBindingApiForAdditive(type, KotlinAdditiveApi(\n          KotlinRxBindingInfo(KotlinRxTypeNames.Rx.RxRecyclerView,\n              \"scrollEvents\",\n              \"@return an observable of scroll events on this RecyclerView\"),\n          KotlinRxTypeNames.Rx.RecyclerViewScrollEvent))\n    }\n  }\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/KotlinTextInputTrait.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx\n\nimport com.google.auto.service.AutoService\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.FunSpec\nimport com.squareup.kotlinpoet.TypeSpec\nimport com.squareup.kotlinpoet.asClassName\nimport com.uber.artist.api.KotlinTrait\n\n@AutoService(KotlinTrait::class)\nclass KotlinTextInputTrait : KotlinTrait {\n  override fun generateFor(\n      type: TypeSpec.Builder,\n      initMethod: FunSpec.Builder,\n      rClass: ClassName,\n      sourceType: String) {\n\n    // TextChanges\n    addRxBindingApiForAdditive(type, KotlinAdditiveApi(\n        KotlinRxBindingInfo(KotlinRxTypeNames.Rx.RxTextView,\n            \"textChanges\",\n            \"\"\"@return an observable of character sequences for text changes on this TextView.\"\"\"),\n        CharSequence::class.asClassName()))\n  }\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/KotlinViewTrait.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx\n\nimport com.google.auto.service.AutoService\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.FunSpec\nimport com.squareup.kotlinpoet.TypeSpec\nimport com.uber.artist.api.KotlinTrait\nimport com.uber.artist.api.KotlinTypeNames\nimport com.uber.artist.traits.rx.config.KotlinArtistRxConfigService\n\n@AutoService(KotlinTrait::class)\nopen class KotlinViewTrait : KotlinTrait {\n  private val artistRxConfig by lazy { KotlinArtistRxConfigService.newInstance().getArtistRxConfig() }\n\n  override fun generateFor(\n      type: TypeSpec.Builder,\n      initMethod: FunSpec.Builder,\n      rClass: ClassName,\n      sourceType: String) {\n\n    clicks(type, sourceType)\n    longClicks(type, sourceType)\n    layoutChanges(type)\n  }\n\n  open fun clicks(type: TypeSpec.Builder, sourceType: String) {\n    addRxBindingApiForSettable(type, KotlinSettableApi(\n        KotlinRxBindingInfo(KotlinRxTypeNames.Rx.RxView,\n            \"clicks\",\n            \"\"\"@return an Observable of click events. The emitted value is unspecified and should only be used as notification.\n    \"\"\"),\n        ClassName.bestGuess(\"android.view.View.OnClickListener\"),\n        \"setOnClickListener\",\n        KotlinTypeNames.Java.Object,\n        FunSpec.builder(\"accept\")\n            .addParameter(\"ignored\", artistRxConfig.rxBindingSignalEventTypeName())\n            .addStatement(\"l.onClick(this@$sourceType)\")\n    ))\n  }\n\n  open fun longClicks(type: TypeSpec.Builder, sourceType: String) {\n    addRxBindingApiForSettable(type, KotlinSettableApi(\n        KotlinRxBindingInfo(KotlinRxTypeNames.Rx.RxView,\n            \"longClicks\",\n            \"\"\"@return an Observable of longclick events. The emitted value is unspecified and should only be used as notification.\n    \"\"\"),\n        ClassName.bestGuess(\"android.view.View.OnLongClickListener\"),\n        \"setOnLongClickListener\",\n        KotlinTypeNames.Java.Object,\n        FunSpec.builder(\"accept\")\n            .addParameter(\"ignored\", artistRxConfig.rxBindingSignalEventTypeName())\n            .addStatement(\"l.onLongClick(this@$sourceType)\")\n    ))\n  }\n\n  open fun layoutChanges(type: TypeSpec.Builder) {\n    // Attach state changes observable\n    addRxBindingApiForAdditive(type, KotlinAdditiveApi(\n        KotlinRxBindingInfo(\n            KotlinRxTypeNames.Rx.RxView,\n            \"layoutChanges\",\n            \"@return an observable which emits on layout changes. The emitted value is \" +\n                \"unspecified and should only be used as notification.\"),\n        KotlinTypeNames.Java.Object))\n  }\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/config/ArtistRxConfig.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx.config\n\n/**\n * This configuration object describes various plugin points for rx-based traits.\n */\ninterface ArtistRxConfig<CodeBlockType, TypeNameType> {\n\n  /**\n   * Plugin point for generating additional code to invoke when a view has been tapped.\n   */\n  fun processTap(codeBlockBuilder: CodeBlockType) {}\n\n  /**\n   * Plugin point for generating additional code to invoke when a view has attached to the window.\n   */\n  fun processImpression(codeBlockBuilder: CodeBlockType) {}\n\n  /**\n   * Plugin point for generating additional code to invoke when a view has changed visibility.\n   */\n  fun processVisibilityChanges(codeBlockBuilder: CodeBlockType) {}\n\n  /**\n   * Plugin point for generating additional code to modify an RxBinding stream.\n   */\n  fun processRxBindingStream(codeBlockBuilder: CodeBlockType, streamTypeName: TypeNameType) {}\n\n  /**\n   * Plugin point for generating additional code to modify an RxBinding stream which notifies that something occurred.\n   * This can be used along with rxBindingSignalEventTypeName() to map signal events to a different type.\n   */\n  fun processRxBindingSignalEvent(codeBlockBuilder: CodeBlockType) {}\n\n  /**\n   * This defines the type to be used for RxBinding event signals. It can be changed if processRxBindingSignalEvent()\n   * has been overridden to map the signal events to a new type. The default type is Object.\n   */\n  fun rxBindingSignalEventTypeName(): TypeNameType\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/config/ArtistRxConfigService.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx.config\n\ninterface ArtistRxConfigService<ArtistRxConfig> {\n\n  /**\n   * Gets the optionally overridden [ArtistRxConfig] implementation or the default.\n   *\n   * @return The located [ArtistRxConfig] or a default config if not provided.\n   */\n  fun getArtistRxConfig(): ArtistRxConfig\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/config/JavaArtistRxConfig.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx.config\n\nimport com.squareup.javapoet.CodeBlock\nimport com.squareup.javapoet.TypeName\n\n/**\n * This configuration object describes various plugin points for rx-based traits.\n */\nabstract class JavaArtistRxConfig : ArtistRxConfig<CodeBlock.Builder, TypeName> {\n\n  /**\n   * Plugin point for generating additional code to invoke when a view has been tapped.\n   */\n  override fun processTap(codeBlockBuilder: CodeBlock.Builder) {}\n\n  /**\n   * Plugin point for generating additional code to invoke when a view has attached to the window.\n   */\n  override fun processImpression(codeBlockBuilder: CodeBlock.Builder) {}\n\n  /**\n   * Plugin point for generating additional code to invoke when a view has changed visibility.\n   */\n  override fun processVisibilityChanges(codeBlockBuilder: CodeBlock.Builder) {}\n\n  /**\n   * Plugin point for generating additional code to modify an RxBinding stream.\n   */\n  override fun processRxBindingStream(codeBlockBuilder: CodeBlock.Builder, streamTypeName: TypeName) {}\n\n  /**\n   * Plugin point for generating additional code to modify an RxBinding stream which notifies that something occurred.\n   * This can be used along with rxBindingSignalEventTypeName() to map signal events to a different type.\n   */\n  override fun processRxBindingSignalEvent(codeBlockBuilder: CodeBlock.Builder) {}\n\n  /**\n   * This defines the type to be used for RxBinding event signals. It can be changed if processRxBindingSignalEvent()\n   * has been overridden to map the signal events to a new type. The default type is Object.\n   */\n  override fun rxBindingSignalEventTypeName(): TypeName = TypeName.OBJECT\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/config/JavaArtistRxConfigService.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx.config\n\nimport java.util.ServiceLoader\n\nclass JavaArtistRxConfigService private constructor() : ArtistRxConfigService<JavaArtistRxConfig> {\n\n  private val serviceLoader = ServiceLoader.load(JavaArtistRxConfig::class.java)\n\n  /**\n   * Gets the optionally overridden [ArtistRxConfig] implementation or the default.\n   *\n   * @return The located [ArtistRxConfig] or a default config if not provided.\n   */\n  override fun getArtistRxConfig(): JavaArtistRxConfig = serviceLoader.asIterable().firstOrNull() ?: DEFAULT_CONFIG\n\n  companion object {\n    private val DEFAULT_CONFIG: JavaArtistRxConfig = JavaDefaultArtistRxConfig()\n\n    fun newInstance(): JavaArtistRxConfigService = JavaArtistRxConfigService()\n  }\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/config/JavaDefaultArtistRxConfig.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx.config\n\nclass JavaDefaultArtistRxConfig : JavaArtistRxConfig()\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/config/KotlinArtistRxConfig.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx.config\n\nimport com.squareup.kotlinpoet.CodeBlock\nimport com.squareup.kotlinpoet.TypeName\nimport com.squareup.kotlinpoet.UNIT\n\n/**\n * This configuration object describes various plugin points for rx-based traits.\n */\nabstract class KotlinArtistRxConfig : ArtistRxConfig<CodeBlock.Builder, TypeName> {\n\n  /**\n   * Plugin point for generating additional code to invoke when a view has been tapped.\n   */\n  override fun processTap(codeBlockBuilder: CodeBlock.Builder) {}\n\n  /**\n   * Plugin point for generating additional code to invoke when a view has attached to the window.\n   */\n  override fun processImpression(codeBlockBuilder: CodeBlock.Builder) {}\n\n  /**\n   * Plugin point for generating additional code to invoke when a view has changed visibility.\n   */\n  override fun processVisibilityChanges(codeBlockBuilder: CodeBlock.Builder) {}\n\n  /**\n   * Plugin point for generating additional code to modify an RxBinding stream.\n   */\n  override fun processRxBindingStream(codeBlockBuilder: CodeBlock.Builder, streamTypeName: TypeName) {}\n\n  /**\n   * Plugin point for generating additional code to modify an RxBinding stream which notifies that something occurred.\n   * This can be used along with rxBindingSignalEventTypeName() to map signal events to a different type.\n   */\n  override fun processRxBindingSignalEvent(codeBlockBuilder: CodeBlock.Builder) {}\n\n  /**\n   * This defines the type to be used for RxBinding event signals. It can be changed if processRxBindingSignalEvent()\n   * has been overridden to map the signal events to a new type. The default type is Object.\n   */\n  override fun rxBindingSignalEventTypeName(): TypeName = UNIT\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/config/KotlinArtistRxConfigService.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx.config\n\nimport java.util.ServiceLoader\n\nclass KotlinArtistRxConfigService private constructor() : ArtistRxConfigService<KotlinArtistRxConfig> {\n\n  private val serviceLoader = ServiceLoader.load(KotlinArtistRxConfig::class.java)\n\n  /**\n   * Gets the optionally overridden [ArtistRxConfig] implementation or the default.\n   *\n   * @return The located [ArtistRxConfig] or a default config if not provided.\n   */\n  override fun getArtistRxConfig(): KotlinArtistRxConfig = serviceLoader.asIterable().firstOrNull() ?: DEFAULT_CONFIG\n\n  companion object {\n    private val DEFAULT_CONFIG: KotlinArtistRxConfig = KotlinDefaultArtistRxConfig()\n\n    fun newInstance(): KotlinArtistRxConfigService = KotlinArtistRxConfigService()\n  }\n}\n"
  },
  {
    "path": "artist-traits-rx/src/main/kotlin/com/uber/artist/traits/rx/config/KotlinDefaultArtistRxConfig.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.traits.rx.config\n\nclass KotlinDefaultArtistRxConfig : KotlinArtistRxConfig()\n"
  },
  {
    "path": "build.gradle",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nbuildscript {\n    apply from: project.file('gradle/dependencies.gradle')\n\n    repositories {\n        google()\n        jcenter()\n        maven { url deps.build.gradlePluginsUrl }\n    }\n\n    dependencies {\n        classpath deps.build.androidPlugin\n        classpath deps.kotlin.gradlePlugin\n    }\n}\n\napply from: project.file('gradle/dependencies.gradle')\nsubprojects {\n    buildscript {\n        repositories {\n            google()\n            jcenter()\n        }\n    }\n\n    repositories {\n        google()\n        jcenter()\n        maven { url deps.build.gradlePluginsUrl }\n    }\n\n    apply plugin: 'checkstyle'\n\n    checkstyle { -> rootProject\n        configFile rootProject.file('config/checkstyle/checkstyle.xml')\n    }\n}\n\ntask wrapper(type: Wrapper) {\n    gradleVersion = '4.7'\n    distributionUrl = \"https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip\"\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n\napply from: 'gradle/dependencies.gradle'\n"
  },
  {
    "path": "buildSrc/build.gradle",
    "content": "buildscript {\n    apply from: project.rootProject.file(\"../gradle/dependencies.gradle\")\n\n    repositories {\n        google()\n        jcenter()\n        maven { url deps.build.gradlePluginsUrl }\n    }\n\n    dependencies {\n        classpath deps.build.androidPlugin\n        classpath deps.kotlin.gradlePlugin\n    }\n}\n\napply from: project.rootProject.file(\"../gradle/dependencies.gradle\")\nrepositories {\n    google()\n    jcenter()\n}\n\nsubprojects { subproject ->\n    if (subproject.buildFile.exists()) {\n        apply from: project.rootProject.file(\"../gradle/dependencies.gradle\")\n        repositories {\n            google()\n            jcenter()\n        }\n\n        rootProject.dependencies {\n            runtime project(path)\n        }\n    }\n    subproject.afterEvaluate {\n        // Disable useless tasks in buildSrc\n        if (subproject.plugins.hasPlugin(\"kotlin\")) {\n            subproject.tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {\n                kotlinOptions.suppressWarnings = true\n            }\n        }\n\n        subproject.tasks.findAll {\n            it.name.toLowerCase().contains(\"test\") ||\n                it.name.toLowerCase().contains(\"lint\") ||\n                it.name.toLowerCase().contains(\"checkstyle\") }.each {\n            it.enabled = false\n        }\n    }\n}\n"
  },
  {
    "path": "buildSrc/settings.gradle",
    "content": "// These are not needed if consuming the Artist plugin from Maven Central instead of the local copy from this repo\ninclude ':artist'\ninclude ':artist-api'\ninclude ':artist-core'\ninclude ':artist-traits'\ninclude ':artist-traits-rx'\n\ninclude ':sample:providers'\ninclude ':sample:providers-kotlin'\n"
  },
  {
    "path": "config/checkstyle/checkstyle-suppressions.xml",
    "content": "<?xml version=\"1.0\"?>\n\n<!DOCTYPE suppressions PUBLIC\n    \"-//Puppy Crawl//DTD Suppressions 1.1//EN\"\n    \"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd\">\n\n<suppressions>\n    <suppress checks=\"JavadocType\" files=\"[\\\\/]test[\\\\/]\" />\n    <suppress checks=\"JavadocMethod\" files=\"[\\\\/]test[\\\\/]\" />\n</suppressions>\n"
  },
  {
    "path": "config/checkstyle/checkstyle-test.xml",
    "content": "<?xml version=\"1.0\"?>\n<!DOCTYPE module PUBLIC\n    \"-//Puppy Crawl//DTD Check Configuration 1.2//EN\"\n    \"http://www.puppycrawl.com/dtds/configuration_1_2.dtd\">\n\n<module name=\"Checker\">\n    <property name=\"charset\" value=\"UTF-8\"/>\n\n    <!-- Javadoc Comments                                          -->\n    <!-- See http://checkstyle.sourceforge.net/config_javadoc.html -->\n    <!--module name=\"JavadocPackage\"/-->\n\n\n    <!-- Miscellaneous                                          -->\n    <!-- See http://checkstyle.sourceforge.net/config_misc.html -->\n    <module name=\"NewlineAtEndOfFile\"/>\n    <!--module name=\"Translation\"/-->\n    <!--module name=\"UniqueProperties\"/-->\n\n\n    <!-- Size Violations                                         -->\n    <!-- See http://checkstyle.sourceforge.net/config_sizes.html -->\n    <module name=\"FileLength\">\n        <property name=\"max\" value=\"5500\"/>\n    </module>\n\n\n    <!-- Whitespace                                          -->\n    <!-- See http://checkstyle.sf.net/config_whitespace.html -->\n    <module name=\"FileTabCharacter\">\n        <property name=\"eachLine\" value=\"true\"/>\n    </module>\n\n\n    <!-- Tree Walker                                                  -->\n    <!-- See http://checkstyle.sourceforge.net/config.html#TreeWalker -->\n    <module name=\"TreeWalker\">\n\n        <!-- Annotations                                                  -->\n        <!-- See http://checkstyle.sourceforge.net/config_annotation.html -->\n        <!--module name=\"AnnotationUseStyle\"/-->\n        <!--module name=\"MissingDeprecated\"/-->\n        <module name=\"MissingOverride\"/>\n        <module name=\"PackageAnnotation\"/>\n        <!--module name=\"SuppressWarnings\"/-->\n        <!--module name=\"SuppressWarningsHolder\"/-->\n        <module name=\"AnnotationLocation\">\n            <property name=\"tokens\" value=\"CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF\"/>\n            <property name=\"allowSamelineMultipleAnnotations\" value=\"false\"/>\n            <property name=\"allowSamelineSingleParameterlessAnnotation\" value=\"false\"/>\n            <property name=\"allowSamelineParameterizedAnnotation\" value=\"false\"/>\n        </module>\n        <module name=\"AnnotationLocation\">\n            <property name=\"tokens\" value=\"VARIABLE_DEF\"/>\n            <property name=\"allowSamelineMultipleAnnotations\" value=\"true\"/>\n            <property name=\"allowSamelineSingleParameterlessAnnotation\" value=\"true\"/>\n            <property name=\"allowSamelineParameterizedAnnotation\" value=\"true\"/>\n        </module>\n\n\n        <!-- Blocks Checks                                            -->\n        <!-- See http://checkstyle.sourceforge.net/config_blocks.html -->\n        <module name=\"EmptyBlock\">\n            <property name=\"tokens\" value=\"LITERAL_WHILE,LITERAL_TRY,LITERAL_FINALLY,LITERAL_DO,LITERAL_IF,LITERAL_ELSE,LITERAL_FOR,INSTANCE_INIT,STATIC_INIT,LITERAL_SWITCH\"/>\n        </module>\n        <!--module name=\"EmptyCatchBlock\"/-->\n        <module name=\"LeftCurly\">\n            <property name=\"maxLineLength\" value=\"120\"/>\n        </module>\n        <module name=\"NeedBraces\"/>\n        <module name=\"RightCurly\"/>\n        <module name=\"AvoidNestedBlocks\"/>\n\n\n        <!-- Class Design                                             -->\n        <!-- See http://checkstyle.sourceforge.net/config_design.html -->\n        <!--module name=\"VisibilityModifier\"/-->\n        <!--module name=\"FinalClass\"/-->\n        <module name=\"InterfaceIsType\"/>\n        <module name=\"HideUtilityClassConstructor\"/>\n        <!--module name=\"DesignForExtension\"/-->\n        <!--module name=\"MutableException\"/-->\n        <!--module name=\"ThrowsCount\"/-->\n        <module name=\"InnerTypeLast\"/>\n        <module name=\"OneTopLevelClass\"/>\n\n\n        <!-- Coding                                                   -->\n        <!-- See http://checkstyle.sourceforge.net/config_coding.html -->\n        <!--module name=\"ArrayTrailingComma\"/-->\n        <!--module name=\"AvoidInlineConditionals\"/-->\n        <module name=\"CovariantEquals\"/>\n        <module name=\"EmptyStatement\"/>\n        <!--module name=\"EqualsAvoidNull\"/-->\n        <module name=\"EqualsHashCode\"/>\n        <!--module name=\"FinalLocalVariable\"/-->\n        <!--module name=\"HiddenField\"/-->\n        <module name=\"IllegalInstantiation\"/>\n        <!--module name=\"IllegalToken\"/-->\n        <!--module name=\"IllegalTokenText\"/-->\n        <module name=\"InnerAssignment\"/>\n        <!--module name=\"MagicNumber\"/-->\n        <!--module name=\"MissingSwitchDefault\"/-->\n        <!--module name=\"ModifiedControlVariable\"/-->\n        <module name=\"SimplifyBooleanExpression\"/>\n        <module name=\"SimplifyBooleanReturn\"/>\n        <module name=\"StringLiteralEquality\"/>\n        <!--module name=\"NestedForDepth\"/-->\n        <!--module name=\"NestedIfDepth\"/-->\n        <!--module name=\"NestedTryDepth\"/-->\n        <module name=\"NoClone\"/>\n        <module name=\"NoFinalizer\"/>\n        <module name=\"SuperClone\"/>\n        <!--module name=\"SuperFinalize\"/-->\n        <!--module name=\"IllegalCatch\"/-->\n        <!--module name=\"IllegalThrows\"/-->\n        <module name=\"PackageDeclaration\"/>\n        <!--module name=\"ReturnCount\"/-->\n        <!--module name=\"IllegalType\"/-->\n        <module name=\"DeclarationOrder\"/>\n        <!--module name=\"ParameterAssignment\"/-->\n        <!--module name=\"ExplicitInitialization\"/-->\n        <module name=\"DefaultComesLast\"/>\n        <!--module name=\"MissingCtor\"/-->\n        <module name=\"FallThrough\"/>\n        <!--module name=\"MultipleStringLiterals\"/-->\n        <module name=\"MultipleVariableDeclarations\"/>\n        <!--module name=\"RequireThis\"/-->\n        <!--module name=\"UnnecessaryParentheses\"/-->\n        <module name=\"OneStatementPerLine\"/>\n        <!--module name=\"VariableDeclarationUsageDistance\"/-->\n        <!--module name=\"OverloadMethodsDeclarationOrder\"/-->\n\n\n        <!-- Headers                                                  -->\n        <!-- See http://checkstyle.sourceforge.net/config_header.html -->\n        <!--module name=\"Header\"/-->\n        <!--module name=\"RegexpHeader\"/-->\n\n\n        <!-- Imports                                                   -->\n        <!-- See http://checkstyle.sourceforge.net/config_imports.html -->\n        <module name=\"AvoidStarImport\"/>\n        <!--module name=\"AvoidStaticImport\"/-->\n        <module name=\"IllegalImport\"/>\n        <module name=\"RedundantImport\"/>\n        <module name=\"UnusedImports\">\n            <property name=\"processJavadoc\" value=\"true\"/>\n        </module>\n        <!--module name=\"ImportOrder\"/-->\n        <!--module name=\"ImportControl\"/-->\n        <!--module name=\"CustomImportOrder\"/-->\n\n\n        <!-- Javadoc Comments                                          -->\n        <!-- See http://checkstyle.sourceforge.net/config_javadoc.html -->\n        <!--module name=\"JavadocType\"/-->\n        <!--module name=\"JavadocMethod\">\n            <property name=\"scope\" value=\"public\"/>\n        </module-->\n        <!--module name=\"JavadocVariable\"/-->\n        <!--module name=\"JavadocStyle\"/-->\n        <!--module name=\"WriteTag\"/-->\n        <!--module name=\"NonEmptyAtclauseDescription\"/-->\n        <!--module name=\"JavadocTagContinuationIndentation\"/-->\n        <!--module name=\"SummaryJavadoc\"/-->\n        <!--module name=\"AtclauseOrder\"/-->\n        <!--module name=\"JavadocParagraph\"/-->\n        <!--module name=\"SingleLineJavadoc\"/-->\n\n\n        <!-- Metrics                                               -->\n        <!-- http://checkstyle.sourceforge.net/config_metrics.html -->\n        <!--module name=\"BooleanExpressionComplexity\"/-->\n        <!--module name=\"ClassDataAbstractionCoupling\"/-->\n        <!--module name=\"ClassFanOutComplexity\"/-->\n        <!--module name=\"CyclomaticComplexity\"/-->\n        <!--module name=\"NPathComplexity\"/-->\n        <!--module name=\"JavaNCSS\"/-->\n\n\n        <!-- Miscellaneous                                          -->\n        <!-- See http://checkstyle.sourceforge.net/config_misc.html -->\n        <module name=\"TodoComment\">\n            <property name=\"format\" value=\"\\bTODO\\b.*\"/>\n        </module>\n        <module name=\"TodoComment\">\n            <property name=\"format\" value=\"\\btodo\\b.*\"/>\n        </module>\n        <module name=\"TodoComment\">\n            <property name=\"format\" value=\"\\bFIXME\\b.*\"/>\n        </module>\n        <module name=\"TodoComment\">\n            <property name=\"format\" value=\"\\bfixme\\b.*\"/>\n        </module>\n        <!--module name=\"CommentsIndentation\"/-->\n        <!--module name=\"UncommentedMain\"/-->\n        <module name=\"UpperEll\"/>\n        <module name=\"ArrayTypeStyle\"/>\n        <!--module name=\"FinalParameters\"/-->\n        <!--module name=\"DescendantToken\"/-->\n        <module name=\"Indentation\">\n            <property name=\"lineWrappingIndentation\" value=\"0\"/>\n            <property name=\"arrayInitIndent\" value=\"8\"/>\n        </module>\n        <module name=\"TrailingComment\"/>\n        <module name=\"OuterTypeFilename\"/>\n        <!--module name=\"UniqueProperties\"/-->\n        <!--module name=\"AvoidEscapedUnicodeCharacters\"/-->\n\n\n        <!-- Modifiers                                                  -->\n        <!-- See http://checkstyle.sourceforge.net/config_modifier.html -->\n        <module name=\"ModifierOrder\"/>\n        <module name=\"RedundantModifier\">\n            <property name=\"severity\" value=\"ignore\"/>\n        </module>\n\n\n        <!-- Naming Conventions                                       -->\n        <!-- See http://checkstyle.sourceforge.net/config_naming.html -->\n        <!--module name=\"AbstractClassName\"/-->\n        <module name=\"ClassTypeParameterName\"/>\n        <module name=\"ConstantName\"/>\n        <module name=\"LocalFinalVariableName\"/>\n        <module name=\"LocalVariableName\"/>\n        <module name=\"MemberName\">\n            <property name=\"applyToPublic\" value=\"true\"/>\n            <property name=\"applyToPackage\" value=\"true\"/>\n            <property name=\"applyToProtected\" value=\"false\"/>\n            <property name=\"applyToPrivate\" value=\"false\"/>\n            <property name=\"format\" value=\"^[a-z][a-zA-Z0-9]*$\"/>\n        </module>\n        <module name=\"MethodName\">\n            <property name=\"format\" value=\"^[a-z_][a-zA-Z0-9_]*$\"/>\n        </module>\n        <module name=\"MethodTypeParameterName\"/>\n        <module name=\"InterfaceTypeParameterName\"/>\n        <module name=\"PackageName\"/>\n        <module name=\"ParameterName\"/>\n        <!--module name=\"StaticVariableName\"/-->\n        <module name=\"TypeName\"/>\n        <!--module name=\"AbbreviationAsWordInName\"/-->\n\n\n        <!-- Regexp                                               -->\n        <!-- http://checkstyle.sourceforge.net/config_regexp.html -->\n        <!--module name=\"Regexp\"/-->\n        <!--module name=\"RegexpSingleLineJava\"-->\n\n\n        <!-- Size Violations                                         -->\n        <!-- See http://checkstyle.sourceforge.net/config_sizes.html -->\n        <!--module name=\"ExecutableStatementCount\"/-->\n        <module name=\"LineLength\">\n            <property name=\"max\" value=\"120\"/>\n            <property name=\"ignorePattern\" value=\"^(package|import) .+?;$\"/>\n        </module>\n        <!--module name=\"MethodLength\"/-->\n        <!--module name=\"AnonInnerLength\"/-->\n        <!--module name=\"ParameterNumber\"/-->\n        <!--module name=\"OuterTypeNumber\"/-->\n        <!--module name=\"MethodCount\"/-->\n\n\n        <!-- Whitespace                                                   -->\n        <!-- See http://checkstyle.sourceforge.net/config_whitespace.html -->\n        <module name=\"GenericWhitespace\"/>\n        <module name=\"EmptyForInitializerPad\"/>\n        <module name=\"EmptyForIteratorPad\"/>\n        <module name=\"MethodParamPad\"/>\n        <module name=\"NoWhitespaceAfter\">\n            <property name=\"tokens\" value=\"BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS\"/>\n        </module>\n        <module name=\"NoWhitespaceBefore\"/>\n        <module name=\"OperatorWrap\"/>\n        <module name=\"ParenPad\"/>\n        <module name=\"TypecastParenPad\"/>\n        <module name=\"WhitespaceAfter\"/>\n        <module name=\"WhitespaceAround\"/>\n        <module name=\"NoLineWrap\"/>\n        <!--module name=\"EmptyLineSeparator\"/-->\n        <!--module name=\"SeparatorWrap\"/-->\n    </module>\n\n\n    <!-- Regexp                                               -->\n    <!-- http://checkstyle.sourceforge.net/config_regexp.html -->\n    <module name=\"RegexpSingleline\">\n        <property name=\"format\" value=\"\\s+$\"/>\n        <property name=\"message\" value=\"Line has trailing spaces.\"/>\n    </module>\n    <module name=\"RegexpMultiline\">\n        <property name=\"format\" value=\"\\n\\n\\n\"/>\n        <property name=\"message\" value=\"Double blank lines.\"/>\n    </module>\n\n    <module name=\"SuppressionFilter\">\n        <property name=\"file\" value=\"config/checkstyle/checkstyle-suppressions.xml\"/>\n    </module>\n</module>\n"
  },
  {
    "path": "config/checkstyle/checkstyle.xml",
    "content": "<?xml version=\"1.0\"?>\n<!DOCTYPE module PUBLIC\n    \"-//Puppy Crawl//DTD Check Configuration 1.2//EN\"\n    \"http://www.puppycrawl.com/dtds/configuration_1_2.dtd\">\n\n<module name=\"Checker\">\n    <property name=\"charset\" value=\"UTF-8\"/>\n\n    <!-- Javadoc Comments                                          -->\n    <!-- See http://checkstyle.sourceforge.net/config_javadoc.html -->\n    <!--module name=\"JavadocPackage\"/-->\n\n\n    <!-- Miscellaneous                                          -->\n    <!-- See http://checkstyle.sourceforge.net/config_misc.html -->\n    <module name=\"NewlineAtEndOfFile\"/>\n    <!--module name=\"Translation\"/-->\n    <!--module name=\"UniqueProperties\"/-->\n\n\n    <!-- Size Violations                                         -->\n    <!-- See http://checkstyle.sourceforge.net/config_sizes.html -->\n    <module name=\"FileLength\">\n        <property name=\"max\" value=\"1500\"/>\n    </module>\n\n\n    <!-- Whitespace                                          -->\n    <!-- See http://checkstyle.sf.net/config_whitespace.html -->\n    <module name=\"FileTabCharacter\">\n        <property name=\"eachLine\" value=\"true\"/>\n    </module>\n\n\n    <!-- Tree Walker                                                  -->\n    <!-- See http://checkstyle.sourceforge.net/config.html#TreeWalker -->\n    <module name=\"TreeWalker\">\n\n        <!-- Annotations                                                  -->\n        <!-- See http://checkstyle.sourceforge.net/config_annotation.html -->\n        <!--module name=\"AnnotationUseStyle\"/-->\n        <!--module name=\"MissingDeprecated\"/-->\n        <module name=\"MissingOverride\"/>\n        <module name=\"PackageAnnotation\"/>\n        <!--module name=\"SuppressWarnings\"/-->\n        <!--module name=\"SuppressWarningsHolder\"/-->\n        <module name=\"AnnotationLocation\">\n            <property name=\"tokens\" value=\"CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF\"/>\n            <property name=\"allowSamelineMultipleAnnotations\" value=\"false\"/>\n            <property name=\"allowSamelineSingleParameterlessAnnotation\" value=\"false\"/>\n            <property name=\"allowSamelineParameterizedAnnotation\" value=\"false\"/>\n        </module>\n        <module name=\"AnnotationLocation\">\n            <property name=\"tokens\" value=\"VARIABLE_DEF\"/>\n            <property name=\"allowSamelineMultipleAnnotations\" value=\"true\"/>\n            <property name=\"allowSamelineSingleParameterlessAnnotation\" value=\"true\"/>\n            <property name=\"allowSamelineParameterizedAnnotation\" value=\"true\"/>\n        </module>\n\n\n        <!-- Blocks Checks                                            -->\n        <!-- See http://checkstyle.sourceforge.net/config_blocks.html -->\n        <module name=\"EmptyBlock\">\n            <property name=\"tokens\" value=\"LITERAL_WHILE,LITERAL_TRY,LITERAL_FINALLY,LITERAL_DO,LITERAL_IF,LITERAL_ELSE,LITERAL_FOR,INSTANCE_INIT,STATIC_INIT,LITERAL_SWITCH\"/>\n        </module>\n        <!--module name=\"EmptyCatchBlock\"/-->\n        <module name=\"LeftCurly\">\n            <property name=\"maxLineLength\" value=\"120\"/>\n        </module>\n        <module name=\"NeedBraces\"/>\n        <module name=\"RightCurly\"/>\n        <module name=\"AvoidNestedBlocks\"/>\n\n\n        <!-- Class Design                                             -->\n        <!-- See http://checkstyle.sourceforge.net/config_design.html -->\n        <!--module name=\"VisibilityModifier\"/-->\n        <!--module name=\"FinalClass\"/-->\n        <module name=\"InterfaceIsType\"/>\n        <module name=\"HideUtilityClassConstructor\"/>\n        <!--module name=\"DesignForExtension\"/-->\n        <!--module name=\"MutableException\"/-->\n        <!--module name=\"ThrowsCount\"/-->\n        <module name=\"InnerTypeLast\"/>\n        <module name=\"OneTopLevelClass\"/>\n\n\n        <!-- Coding                                                   -->\n        <!-- See http://checkstyle.sourceforge.net/config_coding.html -->\n        <!--module name=\"ArrayTrailingComma\"/-->\n        <!--module name=\"AvoidInlineConditionals\"/-->\n        <module name=\"CovariantEquals\"/>\n        <module name=\"EmptyStatement\"/>\n        <!--module name=\"EqualsAvoidNull\"/-->\n        <module name=\"EqualsHashCode\"/>\n        <!--module name=\"FinalLocalVariable\"/-->\n        <!--module name=\"HiddenField\"/-->\n        <module name=\"IllegalInstantiation\"/>\n        <!--module name=\"IllegalToken\"/-->\n        <!--module name=\"IllegalTokenText\"/-->\n        <module name=\"InnerAssignment\"/>\n        <!--module name=\"MagicNumber\"/-->\n        <!--module name=\"MissingSwitchDefault\"/-->\n        <!--module name=\"ModifiedControlVariable\"/-->\n        <module name=\"SimplifyBooleanExpression\"/>\n        <module name=\"SimplifyBooleanReturn\"/>\n        <module name=\"StringLiteralEquality\"/>\n        <!--module name=\"NestedForDepth\"/-->\n        <!--module name=\"NestedIfDepth\"/-->\n        <!--module name=\"NestedTryDepth\"/-->\n        <module name=\"NoClone\"/>\n        <module name=\"NoFinalizer\"/>\n        <module name=\"SuperClone\"/>\n        <!--module name=\"SuperFinalize\"/-->\n        <!--module name=\"IllegalCatch\"/-->\n        <!--module name=\"IllegalThrows\"/-->\n        <module name=\"PackageDeclaration\"/>\n        <!--module name=\"ReturnCount\"/-->\n        <!--module name=\"IllegalType\"/-->\n        <module name=\"DeclarationOrder\"/>\n        <!--module name=\"ParameterAssignment\"/-->\n        <!--module name=\"ExplicitInitialization\"/-->\n        <module name=\"DefaultComesLast\"/>\n        <!--module name=\"MissingCtor\"/-->\n        <module name=\"FallThrough\"/>\n        <!--module name=\"MultipleStringLiterals\"/-->\n        <module name=\"MultipleVariableDeclarations\"/>\n        <!--module name=\"RequireThis\"/-->\n        <!--module name=\"UnnecessaryParentheses\"/-->\n        <module name=\"OneStatementPerLine\"/>\n        <!--module name=\"VariableDeclarationUsageDistance\"/-->\n        <module name=\"OverloadMethodsDeclarationOrder\"/>\n\n\n        <!-- Headers                                                  -->\n        <!-- See http://checkstyle.sourceforge.net/config_header.html -->\n        <!--module name=\"Header\"/-->\n        <!--module name=\"RegexpHeader\"/-->\n\n\n        <!-- Imports                                                   -->\n        <!-- See http://checkstyle.sourceforge.net/config_imports.html -->\n        <module name=\"AvoidStarImport\"/>\n        <!--module name=\"AvoidStaticImport\"/-->\n        <module name=\"IllegalImport\"/>\n        <module name=\"RedundantImport\"/>\n        <module name=\"UnusedImports\">\n            <property name=\"processJavadoc\" value=\"true\"/>\n        </module>\n        <!--module name=\"ImportOrder\"/-->\n        <!--module name=\"ImportControl\"/-->\n        <!--module name=\"CustomImportOrder\"/-->\n\n\n        <!-- Javadoc Comments                                          -->\n        <!-- See http://checkstyle.sourceforge.net/config_javadoc.html -->\n        <module name=\"JavadocType\">\n            <property name=\"scope\" value=\"public\"/>\n        </module>\n        <module name=\"JavadocMethod\">\n            <property name=\"scope\" value=\"public\"/>\n            <property name=\"tokens\" value=\"METHOD_DEF\" /> <!-- Constructors don't always need Javadoc -->\n        </module>\n        <!--module name=\"JavadocVariable\"/-->\n        <!--module name=\"JavadocStyle\"/-->\n        <!--module name=\"WriteTag\"/-->\n        <!--module name=\"NonEmptyAtclauseDescription\"/-->\n        <!--module name=\"JavadocTagContinuationIndentation\"/-->\n        <!--module name=\"SummaryJavadoc\"/-->\n        <!--module name=\"AtclauseOrder\"/-->\n        <!--module name=\"JavadocParagraph\"/-->\n        <!--module name=\"SingleLineJavadoc\"/-->\n\n\n        <!-- Metrics                                               -->\n        <!-- http://checkstyle.sourceforge.net/config_metrics.html -->\n        <!--module name=\"BooleanExpressionComplexity\"/-->\n        <!--module name=\"ClassDataAbstractionCoupling\"/-->\n        <!--module name=\"ClassFanOutComplexity\"/-->\n        <!--module name=\"CyclomaticComplexity\"/-->\n        <!--module name=\"NPathComplexity\"/-->\n        <!--module name=\"JavaNCSS\"/-->\n\n\n        <!-- Miscellaneous                                          -->\n        <!-- See http://checkstyle.sourceforge.net/config_misc.html -->\n        <module name=\"TodoComment\">\n            <property name=\"format\" value=\"\\bTODO\\b.*\"/>\n        </module>\n        <module name=\"TodoComment\">\n            <property name=\"format\" value=\"\\btodo\\b.*\"/>\n        </module>\n        <module name=\"TodoComment\">\n            <property name=\"format\" value=\"\\bFIXME\\b.*\"/>\n        </module>\n        <module name=\"TodoComment\">\n            <property name=\"format\" value=\"\\bfixme\\b.*\"/>\n        </module>\n        <!--module name=\"CommentsIndentation\"/-->\n        <!--module name=\"UncommentedMain\"/-->\n        <module name=\"UpperEll\"/>\n        <module name=\"ArrayTypeStyle\"/>\n        <!--module name=\"FinalParameters\"/-->\n        <!--module name=\"DescendantToken\"/-->\n        <module name=\"Indentation\">\n            <property name=\"basicOffset\" value=\"2\"/>\n            <property name=\"caseIndent\" value=\"2\"/>\n        </module>\n        <module name=\"TrailingComment\"/>\n        <module name=\"OuterTypeFilename\"/>\n        <!--module name=\"UniqueProperties\"/-->\n        <!--module name=\"AvoidEscapedUnicodeCharacters\"/-->\n\n\n        <!-- Modifiers                                                  -->\n        <!-- See http://checkstyle.sourceforge.net/config_modifier.html -->\n        <module name=\"ModifierOrder\"/>\n        <module name=\"RedundantModifier\">\n            <property name=\"severity\" value=\"ignore\"/>\n        </module>\n\n\n        <!-- Naming Conventions                                       -->\n        <!-- See http://checkstyle.sourceforge.net/config_naming.html -->\n        <!--module name=\"AbstractClassName\"/-->\n        <module name=\"ClassTypeParameterName\">\n            <property name=\"format\" value=\"([A-Z][a-z]*T)|[A-Z]\"/>\n        </module>\n        <module name=\"ConstantName\"/>\n        <module name=\"LocalFinalVariableName\"/>\n        <module name=\"LocalVariableName\"/>\n        <module name=\"MemberName\">\n            <property name=\"applyToPublic\" value=\"true\"/>\n            <property name=\"applyToPackage\" value=\"true\"/>\n            <property name=\"applyToProtected\" value=\"false\"/>\n            <property name=\"applyToPrivate\" value=\"false\"/>\n            <property name=\"format\" value=\"^[a-z][a-zA-Z0-9]*$\"/>\n        </module>\n        <module name=\"MethodName\"/>\n        <module name=\"MethodTypeParameterName\">\n            <property name=\"format\" value=\"([A-Z][a-z]*T)|[A-Z]\"/>\n        </module>\n        <module name=\"InterfaceTypeParameterName\">\n            <property name=\"format\" value=\"([A-Z][a-z]*T)|[A-Z]\"/>\n        </module>\n        <module name=\"PackageName\"/>\n        <module name=\"ParameterName\"/>\n        <module name=\"StaticVariableName\"/>\n        <module name=\"TypeName\"/>\n        <!--module name=\"AbbreviationAsWordInName\"/-->\n\n\n        <!-- Regexp                                               -->\n        <!-- http://checkstyle.sourceforge.net/config_regexp.html -->\n        <!--module name=\"Regexp\"/-->\n        <!--module name=\"RegexpSingleLineJava\"-->\n\n\n        <!-- Size Violations                                         -->\n        <!-- See http://checkstyle.sourceforge.net/config_sizes.html -->\n        <!--module name=\"ExecutableStatementCount\"/-->\n        <module name=\"LineLength\">\n            <property name=\"max\" value=\"120\"/>\n            <property name=\"ignorePattern\" value=\"^(package|import) .+?;$\"/>\n        </module>\n        <module name=\"MethodLength\">\n            <property name=\"max\" value=\"250\"/>\n        </module>\n        <!--module name=\"AnonInnerLength\"/-->\n        <!--module name=\"ParameterNumber\"/-->\n        <!--module name=\"OuterTypeNumber\"/-->\n        <!--module name=\"MethodCount\"/-->\n\n\n        <!-- Whitespace                                                   -->\n        <!-- See http://checkstyle.sourceforge.net/config_whitespace.html -->\n        <module name=\"GenericWhitespace\"/>\n        <module name=\"EmptyForInitializerPad\"/>\n        <module name=\"EmptyForIteratorPad\"/>\n        <module name=\"MethodParamPad\"/>\n        <module name=\"NoWhitespaceAfter\">\n            <property name=\"tokens\" value=\"BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS\"/>\n        </module>\n        <module name=\"NoWhitespaceBefore\"/>\n        <module name=\"OperatorWrap\"/>\n        <module name=\"ParenPad\"/>\n        <module name=\"TypecastParenPad\"/>\n        <module name=\"WhitespaceAfter\"/>\n        <module name=\"WhitespaceAround\"/>\n        <module name=\"NoLineWrap\"/>\n        <!--module name=\"EmptyLineSeparator\"/-->\n        <!--module name=\"SeparatorWrap\"/-->\n    </module>\n\n\n    <!-- Regexp                                               -->\n    <!-- http://checkstyle.sourceforge.net/config_regexp.html -->\n    <module name=\"RegexpSingleline\">\n        <property name=\"format\" value=\"\\s+$\"/>\n        <property name=\"message\" value=\"Line has trailing spaces.\"/>\n    </module>\n\n    <module name=\"RegexpMultiline\">\n        <property name=\"format\" value=\"\\n\\n\\n\"/>\n        <property name=\"message\" value=\"Double blank lines.\"/>\n    </module>\n\n    <module name=\"SuppressionFilter\">\n        <property name=\"file\" value=\"config/checkstyle/checkstyle-suppressions.xml\"/>\n    </module>\n</module>\n"
  },
  {
    "path": "config/lint/lint.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<lint>\n    <issue id=\"AppCompatCustomView\" severity=\"ignore\" />\n    <issue id=\"GoogleAppIndexingWarning\" severity=\"ignore\" />\n    <issue id=\"GradleCompatible\" severity=\"ignore\" />\n    <issue id=\"IconLauncherFormat\" severity=\"ignore\" />\n</lint>\n"
  },
  {
    "path": "gradle/dependencies.gradle",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\ndef versions = [\n        kotlin   : \"1.3.0\",\n        rxBinding: \"3.1.0\"\n]\n\ndef androidx = [\n        annotations: \"androidx.annotation:annotation:1.0.0\",\n        appcompat  : \"androidx.appcompat:appcompat:1.0.2\"\n]\n\ndef apt = [\n        autoService: \"com.google.auto.service:auto-service:1.0-rc4\",\n        javapoet   : \"com.squareup:javapoet:1.9.0\",\n        kotlinPoet : \"com.squareup:kotlinpoet:1.0.1\"\n]\n\ndef build = [\n        androidPlugin      : \"com.android.tools.build:gradle:3.2.0\",\n        buildToolsVersion  : \"28.0.3\",\n        compileSdkVersion  : 28,\n        ci                 : 'true' == System.getenv('CI'),\n        googleJavaFormatter: \"com.google.googlejavaformat:google-java-format:1.4\",\n        gradleAptPlugin    : \"net.ltgt.gradle:gradle-apt-plugin:0.15\",\n        gradlePluginsUrl   : \"https://plugins.gradle.org/m2/\",\n        minSdkVersion      : 16,\n        targetSdkVersion   : 28\n]\n\ndef external = [\n        rxbinding            : \"com.jakewharton.rxbinding3:rxbinding-core:${versions.rxBinding}\",\n        rxbindingAppCompat   : \"com.jakewharton.rxbinding3:rxbinding-appcompat:${versions.rxBinding}\",\n        rxbindingRecyclerView: \"com.jakewharton.rxbinding3:rxbinding-recyclerview:${versions.rxBinding}\",\n        rxjava2              : \"io.reactivex.rxjava2:rxjava:2.2.3\",\n        rxrelay2             : \"com.jakewharton.rxrelay2:rxrelay:2.1.0\",\n]\n\ndef kotlin = [\n        gradlePlugin: \"org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}\",\n        stdLibJdk7  : \"org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}\"\n]\n\ndef test = [\n        compileTesting: \"com.google.testing.compile:compile-testing:0.15\",\n        junit         : 'junit:junit:4.12',\n        robolectric   : \"org.robolectric:android-all:8.1.0-robolectric-4402310\",\n        truth         : \"com.google.truth:truth:0.42\"\n]\n\next.deps = [\n        \"androidx\": androidx,\n        \"apt\"     : apt,\n        \"build\"   : build,\n        \"external\": external,\n        \"kotlin\"  : kotlin,\n        \"test\"    : test,\n        \"versions\": versions\n]\n\n"
  },
  {
    "path": "gradle/gradle-mvn-push.gradle",
    "content": "/*\n * Copyright (C) Chris Banes\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\napply plugin: 'maven'\napply plugin: 'signing'\n\nversion = VERSION_NAME\ngroup = GROUP\n\ndef isReleaseBuild() {\n  return VERSION_NAME.contains(\"SNAPSHOT\") == false\n}\n\ndef getReleaseRepositoryUrl() {\n  return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL\n          : \"https://oss.sonatype.org/service/local/staging/deploy/maven2/\"\n}\n\ndef getSnapshotRepositoryUrl() {\n  return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL\n          : \"https://oss.sonatype.org/content/repositories/snapshots/\"\n}\n\ndef getRepositoryUsername() {\n  return hasProperty('SONATYPE_NEXUS_USERNAME') ? SONATYPE_NEXUS_USERNAME : \"\"\n}\n\ndef getRepositoryPassword() {\n  return hasProperty('SONATYPE_NEXUS_PASSWORD') ? SONATYPE_NEXUS_PASSWORD : \"\"\n}\n\nafterEvaluate { project ->\n  uploadArchives {\n    repositories {\n      mavenDeployer {\n        beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }\n\n        pom.groupId = GROUP\n        pom.artifactId = POM_ARTIFACT_ID\n        pom.version = VERSION_NAME\n\n        repository(url: getReleaseRepositoryUrl()) {\n          authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())\n        }\n        snapshotRepository(url: getSnapshotRepositoryUrl()) {\n          authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())\n        }\n\n        pom.project {\n          name POM_NAME\n          packaging POM_PACKAGING\n          description POM_DESCRIPTION\n          url POM_URL\n\n          scm {\n            url POM_SCM_URL\n            connection POM_SCM_CONNECTION\n            developerConnection POM_SCM_DEV_CONNECTION\n          }\n\n          licenses {\n            license {\n              name POM_LICENCE_NAME\n              url POM_LICENCE_URL\n              distribution POM_LICENCE_DIST\n            }\n          }\n\n          developers {\n            developer {\n              id POM_DEVELOPER_ID\n              name POM_DEVELOPER_NAME\n            }\n          }\n        }\n      }\n    }\n  }\n\n  signing {\n    required { isReleaseBuild() && gradle.taskGraph.hasTask(\"uploadArchives\") }\n    sign configurations.archives\n  }\n\n  if (project.getPlugins().hasPlugin('com.android.application') ||\n          project.getPlugins().hasPlugin('com.android.library')) {\n    task install(type: Upload, dependsOn: assemble) {\n      repositories.mavenInstaller {\n        configuration = configurations.archives\n\n        pom.groupId = GROUP\n        pom.artifactId = POM_ARTIFACT_ID\n        pom.version = VERSION_NAME\n\n        pom.project {\n          name POM_NAME\n          packaging POM_PACKAGING\n          description POM_DESCRIPTION\n          url POM_URL\n\n          scm {\n            url POM_SCM_URL\n            connection POM_SCM_CONNECTION\n            developerConnection POM_SCM_DEV_CONNECTION\n          }\n\n          licenses {\n            license {\n              name POM_LICENCE_NAME\n              url POM_LICENCE_URL\n              distribution POM_LICENCE_DIST\n            }\n          }\n\n          developers {\n            developer {\n              id POM_DEVELOPER_ID\n              name POM_DEVELOPER_NAME\n            }\n          }\n        }\n      }\n    }\n\n    task androidJavadocs(type: Javadoc) {\n      if (!project.plugins.hasPlugin('kotlin-android')) {\n        source = android.sourceSets.main.java.srcDirs\n      }\n      classpath += project.files(android.getBootClasspath().join(File.pathSeparator))\n      exclude '**/internal/*'\n\n      if (JavaVersion.current().isJava8Compatible()) {\n        options.addStringOption('Xdoclint:none', '-quiet')\n      }\n    }\n\n    task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {\n      classifier = 'javadoc'\n      from androidJavadocs.destinationDir\n    }\n\n    task androidSourcesJar(type: Jar) {\n      classifier = 'sources'\n      from android.sourceSets.main.java.sourceFiles\n    }\n  } else {\n    install {\n      repositories.mavenInstaller {\n        pom.groupId = GROUP\n        pom.artifactId = POM_ARTIFACT_ID\n        pom.version = VERSION_NAME\n\n        pom.project {\n          name POM_NAME\n          packaging POM_PACKAGING\n          description POM_DESCRIPTION\n          url POM_URL\n\n          scm {\n            url POM_SCM_URL\n            connection POM_SCM_CONNECTION\n            developerConnection POM_SCM_DEV_CONNECTION\n          }\n\n          licenses {\n            license {\n              name POM_LICENCE_NAME\n              url POM_LICENCE_URL\n              distribution POM_LICENCE_DIST\n            }\n          }\n\n          developers {\n            developer {\n              id POM_DEVELOPER_ID\n              name POM_DEVELOPER_NAME\n            }\n          }\n        }\n      }\n    }\n\n    task sourcesJar(type: Jar, dependsOn: classes) {\n      classifier = 'sources'\n      from sourceSets.main.allSource\n    }\n\n    task javadocJar(type: Jar, dependsOn: javadoc) {\n      classifier = 'javadoc'\n      from javadoc.destinationDir\n    }\n  }\n\n  if (JavaVersion.current().isJava8Compatible()) {\n    allprojects {\n      tasks.withType(Javadoc) {\n        options.addStringOption('Xdoclint:none', '-quiet')\n      }\n    }\n  }\n\n  artifacts {\n    if (project.getPlugins().hasPlugin('com.android.application') ||\n            project.getPlugins().hasPlugin('com.android.library')) {\n      archives androidSourcesJar\n      archives androidJavadocsJar\n    } else {\n      archives sourcesJar\n      archives javadocJar\n    }\n  }\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-4.7-all.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true\n\nGROUP=com.uber.artist\nVERSION_NAME=0.4.10-SNAPSHOT\nPOM_DESCRIPTION=A Gradle plugin that generates a base set of Views\nPOM_URL=https://github.com/uber/artist/\nPOM_SCM_URL=https://github.com/uber/artist/\nPOM_SCM_CONNECTION=scm:git:git://github.com/uber/artist.git\nPOM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/uber/artist.git\nPOM_LICENCE_NAME=The Apache Software License, Version 2.0\nPOM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt\nPOM_LICENCE_DIST=repo\nPOM_DEVELOPER_ID=uber\nPOM_DEVELOPER_NAME=Uber Technologies\n\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=$(save \"$@\")\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\n# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong\nif [ \"$(uname)\" = \"Darwin\" ] && [ \"$HOME\" = \"$PWD\" ]; then\n  cd \"$(dirname \"$0\")\"\nfi\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "sample/app/build.gradle",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\napply plugin: 'com.android.application'\napply plugin: \"org.jetbrains.kotlin.android\"\n\nandroid {\n    compileSdkVersion deps.build.compileSdkVersion\n    buildToolsVersion deps.build.buildToolsVersion\n\n    defaultConfig {\n        applicationId \"com.uber.artist.myapplication\"\n        minSdkVersion deps.build.minSdkVersion\n        targetSdkVersion deps.build.targetSdkVersion\n        versionCode 1\n        versionName \"1.0\"\n    }\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n    // Setup a simple lint config for an android app/library.\n    lintOptions {\n        abortOnError true\n        lintConfig rootProject.file('config/lint/lint.xml')\n    }\n}\n\n// This is required to run checkstyle on an android app/library.\ntask checkstyle(type: Checkstyle) {\n   source 'src'\n   include '**/*.java'\n   exclude '**/gen/**'\n\n   classpath = files()\n}\ncheck.dependsOn 'checkstyle'\n\ndependencies {\n    api project(\":sample:library\")\n    api deps.androidx.annotations\n}\n"
  },
  {
    "path": "sample/app/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.uber.artist.myapplication\">\n\n    <application\n        android:allowBackup=\"false\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:roundIcon=\"@mipmap/ic_launcher_round\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity android:name=\".MainActivity\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "sample/app/src/main/java/com/uber/artist/myapplication/MainActivity.kt",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.myapplication\n\nimport android.annotation.SuppressLint\nimport android.os.Bundle\nimport android.widget.Toast\n\nimport com.uber.artist.mylibrary.MyButton\nimport com.uber.artist.mylibrary.MyEditText\nimport com.uber.artist.mylibrary.MyImageView\nimport com.uber.artist.mylibrary.MyNestedScrollView\nimport com.uber.artist.mylibrary.MySwitch\nimport com.uber.artist.mylibrary.MyTextView\n\nimport java.util.concurrent.TimeUnit\n\nimport androidx.appcompat.app.AppCompatActivity\nimport io.reactivex.android.schedulers.AndroidSchedulers\n\nimport android.widget.Toast.LENGTH_SHORT\n\n/**\n * Sample activity.\n */\nclass MainActivity : AppCompatActivity() {\n\n  private val button by lazy { findViewById<MyButton>(R.id.button) }\n  private val editText by lazy { findViewById<MyEditText>(R.id.edittext) }\n  private val imageView by lazy { findViewById<MyImageView>(R.id.image) }\n  private val scrollView by lazy { findViewById<MyNestedScrollView>(R.id.scrollView) }\n  private val textView by lazy { findViewById<MyTextView>(R.id.text) }\n  private val toggle by lazy { findViewById<MySwitch>(R.id.toggle) }\n\n  override fun onCreate(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n    setContentView(R.layout.activity_main)\n    demoArtistViewUsage()\n  }\n\n  @SuppressLint(\"CheckResult\")\n  private fun demoArtistViewUsage() {\n    textView.sampleMethodFromCustomTrait()\n\n    button.clicks()\n        .observeOn(AndroidSchedulers.mainThread())\n        .subscribe { toast(\"Click from MyButton's clicks() stream!\") }\n\n    editText.textChanges()\n        .skip(1)\n        .debounce(200, TimeUnit.MILLISECONDS)\n        .observeOn(AndroidSchedulers.mainThread())\n        .subscribe { charSequence: CharSequence ->\n          toast(\"MyEditText's textChanges() stream sent: $charSequence\")\n        }\n\n    scrollView.scrollChangeEvents()\n        .debounce(200, TimeUnit.MILLISECONDS)\n        .observeOn(AndroidSchedulers.mainThread())\n        .subscribe { toast(\"Scroll from MyScrollView's debounced scrollEvents() stream\") }\n\n    toggle.checkedChanges()\n        .observeOn(AndroidSchedulers.mainThread())\n        .subscribe { isChecked: Boolean ->\n          toast(\"MySwitch's checkedChanges() stream sent: $isChecked\")\n        }\n  }\n\n  private fun toast(msg: CharSequence) = Toast.makeText(this, msg, LENGTH_SHORT).show()\n}\n"
  },
  {
    "path": "sample/app/src/main/res/drawable/divider.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (C) 2017. Uber Technologies\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~    http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  android:shape=\"rectangle\">\n  <solid android:color=\"@android:color/transparent\" />\n  <size\n    android:width=\"1dp\"\n    android:height=\"@dimen/element_spacing\" />\n</shape>\n"
  },
  {
    "path": "sample/app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\n  ~ Copyright (C) 2017. Uber Technologies\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"License\");\n  ~ you may not use this file except in compliance with the License.\n  ~ You may obtain a copy of the License at\n  ~\n  ~    http://www.apache.org/licenses/LICENSE-2.0\n  ~\n  ~ Unless required by applicable law or agreed to in writing, software\n  ~ distributed under the License is distributed on an \"AS IS\" BASIS,\n  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n  ~ See the License for the specific language governing permissions and\n  ~ limitations under the License.\n  -->\n<com.uber.artist.mylibrary.MyNestedScrollView\n  xmlns:android=\"http://schemas.android.com/apk/res/android\"\n  xmlns:tools=\"http://schemas.android.com/tools\"\n  android:id=\"@+id/scrollView\"\n  android:layout_width=\"match_parent\"\n  android:layout_height=\"match_parent\">\n\n  <com.uber.artist.mylibrary.MyLinearLayout\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:divider=\"@drawable/divider\"\n    android:orientation=\"vertical\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    android:showDividers=\"middle\"\n    tools:context=\".MainActivity\">\n\n    <com.uber.artist.mylibrary.MyTextView\n      android:id=\"@+id/text\"\n      android:layout_width=\"wrap_content\"\n      android:layout_height=\"wrap_content\"\n      android:foregroundGravity=\"center\"\n      android:text=\"This is a generated MyTextView\" />\n\n    <com.uber.artist.mylibrary.MyEditText\n      android:id=\"@+id/edittext\"\n      android:layout_width=\"wrap_content\"\n      android:layout_height=\"wrap_content\"\n      android:foregroundGravity=\"center\"\n      android:hint=\"This is a generated MyEditText\" />\n\n    <com.uber.artist.mylibrary.MyButton\n      android:id=\"@+id/button\"\n      android:layout_width=\"wrap_content\"\n      android:layout_height=\"wrap_content\"\n      android:foregroundGravity=\"center\"\n      android:text=\"Generated MyButton\" />\n\n    <com.uber.artist.mylibrary.MySwitch\n      android:id=\"@+id/toggle\"\n      android:layout_width=\"wrap_content\"\n      android:layout_height=\"wrap_content\" />\n\n    <com.uber.artist.mylibrary.MyImageView\n      android:id=\"@+id/image\"\n      android:layout_width=\"64dp\"\n      android:layout_height=\"64dp\"\n      android:src=\"@mipmap/ic_launcher\" />\n\n    <!-- image with large margin so we scroll -->\n    <com.uber.artist.mylibrary.MyImageView\n      android:id=\"@+id/otherImage\"\n      android:layout_width=\"64dp\"\n      android:layout_height=\"64dp\"\n      android:layout_marginTop=\"512dp\"\n      android:src=\"@mipmap/ic_launcher\" />\n\n  </com.uber.artist.mylibrary.MyLinearLayout>\n\n</com.uber.artist.mylibrary.MyNestedScrollView>\n"
  },
  {
    "path": "sample/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@color/ic_launcher_background\"/>\n    <foreground android:drawable=\"@mipmap/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "sample/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<adaptive-icon xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <background android:drawable=\"@color/ic_launcher_background\"/>\n    <foreground android:drawable=\"@mipmap/ic_launcher_foreground\"/>\n</adaptive-icon>"
  },
  {
    "path": "sample/app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n</resources>\n"
  },
  {
    "path": "sample/app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n    <dimen name=\"element_spacing\">16dp</dimen>\n</resources>\n"
  },
  {
    "path": "sample/app/src/main/res/values/ic_launcher_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"ic_launcher_background\">#333333</color>\n</resources>"
  },
  {
    "path": "sample/app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Artist Sample</string>\n</resources>\n"
  },
  {
    "path": "sample/app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar\">\n        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n</resources>\n"
  },
  {
    "path": "sample/demo/java/MyButton.java",
    "content": "package com.uber.artist.mylibrary;\n\nimport android.annotation.SuppressLint;\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Canvas;\nimport android.graphics.drawable.Drawable;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport androidx.annotation.AttrRes;\nimport androidx.annotation.CallSuper;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StyleRes;\nimport androidx.appcompat.widget.AppCompatButton;\nimport com.jakewharton.rxbinding3.view.RxView;\nimport com.jakewharton.rxrelay2.PublishRelay;\nimport io.reactivex.Observable;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.functions.Consumer;\nimport java.lang.Deprecated;\nimport java.lang.Override;\nimport java.lang.SuppressWarnings;\n\npublic class MyButton extends AppCompatButton implements MyView {\n  private Drawable foreground;\n\n  private boolean clicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> clicks;\n\n  @Nullable private Disposable clicksDisposable;\n\n  private boolean longClicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> longClicks;\n\n  @Nullable private Disposable longClicksDisposable;\n\n  public MyButton(Context context) {\n    this(context, null);\n  }\n\n  public MyButton(Context context, @Nullable AttributeSet attrs) {\n    this(context, attrs, R.attr.buttonStyle);\n  }\n\n  public MyButton(Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {\n    super(context, attrs, defStyleAttr);\n    init(context, attrs, defStyleAttr, 0);\n  }\n\n  public View sampleMethodFromCustomTrait() {\n    return this;\n  }\n\n  public boolean isVisible() {\n    return getVisibility() == View.VISIBLE;\n  }\n\n  public boolean isInvisible() {\n    return getVisibility() == View.INVISIBLE;\n  }\n\n  public boolean isGone() {\n    return getVisibility() == View.GONE;\n  }\n\n  @Override\n  protected void onSizeChanged(int w, int h, int oldw, int oldh) {\n    super.onSizeChanged(w, h, oldw, oldh);\n    if (foreground != null) {\n      foreground.setBounds(0, 0, w, h);\n    }\n  }\n\n  @Override\n  protected boolean verifyDrawable(Drawable who) {\n    return super.verifyDrawable(who) || (who == foreground);\n  }\n\n  @Override\n  public void jumpDrawablesToCurrentState() {\n    super.jumpDrawablesToCurrentState();\n    if (foreground != null) {\n      foreground.jumpToCurrentState();\n    }\n  }\n\n  @Override\n  protected void drawableStateChanged() {\n    super.drawableStateChanged();\n    if (foreground != null && foreground.isStateful()) {\n      foreground.setState(getDrawableState());\n    }\n  }\n\n  /**\n   * Returns the drawable used as the foreground of this view. The foreground drawable, if non-null,\n   * is always drawn on top of the children.\n   *\n   * @return A Drawable or null if no foreground was set.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  public Drawable getForeground() {\n    return foreground;\n  }\n\n  /**\n   * Supply a Drawable that is to be rendered on top of all of the child views in this layout. Any\n   * padding in the Drawable will be taken into account by ensuring that the children are inset to\n   * be placed inside of the padding area.\n   *\n   * @param drawable The Drawable to be drawn on top of the children.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  @SuppressLint(\"NewApi\")\n  public void setForeground(Drawable drawable) {\n    if (foreground != drawable) {\n      if (foreground != null) {\n        foreground.setCallback(null);\n        unscheduleDrawable(foreground);\n      }\n      foreground = drawable;\n      if (drawable != null) {\n        foreground.setBounds(0, 0, getWidth(), getHeight());\n        setWillNotDraw(false);\n        drawable.setCallback(this);\n        if (drawable.isStateful()) {\n          drawable.setState(getDrawableState());\n        }\n      } else {\n        setWillNotDraw(true);\n      }\n      invalidate();\n    }\n  }\n\n  @Override\n  public void draw(Canvas canvas) {\n    super.draw(canvas);\n    if (foreground != null) {\n      foreground.draw(canvas);\n    }\n  }\n\n  @TargetApi(android.os.Build.VERSION_CODES.LOLLIPOP)\n  @Override\n  public void drawableHotspotChanged(float x, float y) {\n    super.drawableHotspotChanged(x, y);\n    if (foreground != null) {\n      foreground.setHotspot(x, y);\n    }\n  }\n\n  /** @deprecated Use {@link #clicks()} */\n  @Override\n  @Deprecated\n  public final void setOnClickListener(@Nullable final OnClickListener l) {\n    if (clicksIsInitting) {\n      clicksIsInitting = false;\n      super.setOnClickListener(l);\n    } else {\n      if (clicksDisposable != null) {\n        clicksDisposable.dispose();\n        clicksDisposable = null;\n      }\n      if (l != null) {\n        clicksDisposable =\n            clicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onClick(MyButton.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of click events. The emitted value is unspecified and should only be used\n   *     as notification.\n   */\n  public Observable<Signal> clicks() {\n    if (clicks == null) {\n      clicksIsInitting = true;\n      clicks = PublishRelay.create();\n      RxView.clicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(clicks);\n    }\n    return clicks.hide();\n  }\n\n  /** @deprecated Use {@link #longClicks()} */\n  @Override\n  @Deprecated\n  public final void setOnLongClickListener(@Nullable final OnLongClickListener l) {\n    if (longClicksIsInitting) {\n      longClicksIsInitting = false;\n      super.setOnLongClickListener(l);\n    } else {\n      if (longClicksDisposable != null) {\n        longClicksDisposable.dispose();\n        longClicksDisposable = null;\n      }\n      if (l != null) {\n        longClicksDisposable =\n            longClicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onLongClick(MyButton.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of longclick events. The emitted value is unspecified and should only be\n   *     used as notification.\n   */\n  public Observable<Signal> longClicks() {\n    if (longClicks == null) {\n      longClicksIsInitting = true;\n      longClicks = PublishRelay.create();\n      RxView.longClicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(longClicks);\n    }\n    return longClicks.hide();\n  }\n\n  /**\n   * @return an observable which emits on layout changes. The emitted value is unspecified and\n   *     should only be used as notification.\n   */\n  public Observable<Signal> layoutChanges() {\n    return RxView.layoutChanges(this).map(MyUtils.createRxBindingSignalMapper());\n  }\n\n  @CallSuper\n  protected void init(\n      Context context,\n      @Nullable AttributeSet attrs,\n      @AttrRes int defStyleAttr,\n      @StyleRes int defStyleRes) {\n    TypedArray foregroundTA = context.obtainStyledAttributes(attrs, R.styleable.ForegroundView);\n    final Drawable localForeground =\n        foregroundTA.getDrawable(R.styleable.ForegroundView_android_foreground);\n    if (localForeground != null) {\n      // noinspection AndroidLintNewApi\n      setForeground(localForeground);\n    }\n    foregroundTA.recycle();\n  }\n}\n"
  },
  {
    "path": "sample/demo/java/MyEditText.java",
    "content": "package com.uber.artist.mylibrary;\n\nimport android.annotation.SuppressLint;\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Canvas;\nimport android.graphics.drawable.Drawable;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport androidx.annotation.AttrRes;\nimport androidx.annotation.CallSuper;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StyleRes;\nimport androidx.appcompat.widget.AppCompatEditText;\nimport com.jakewharton.rxbinding3.view.RxView;\nimport com.jakewharton.rxbinding3.widget.RxTextView;\nimport com.jakewharton.rxrelay2.PublishRelay;\nimport io.reactivex.Observable;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.functions.Consumer;\nimport java.lang.CharSequence;\nimport java.lang.Deprecated;\nimport java.lang.Override;\nimport java.lang.SuppressWarnings;\n\npublic class MyEditText extends AppCompatEditText implements MyView {\n  private Drawable foreground;\n\n  private boolean clicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> clicks;\n\n  @Nullable private Disposable clicksDisposable;\n\n  private boolean longClicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> longClicks;\n\n  @Nullable private Disposable longClicksDisposable;\n\n  public MyEditText(Context context) {\n    this(context, null);\n  }\n\n  public MyEditText(Context context, @Nullable AttributeSet attrs) {\n    this(context, attrs, android.R.attr.editTextStyle);\n  }\n\n  public MyEditText(Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {\n    super(context, attrs, defStyleAttr);\n    init(context, attrs, defStyleAttr, 0);\n  }\n\n  public View sampleMethodFromCustomTrait() {\n    return this;\n  }\n\n  public boolean isVisible() {\n    return getVisibility() == View.VISIBLE;\n  }\n\n  public boolean isInvisible() {\n    return getVisibility() == View.INVISIBLE;\n  }\n\n  public boolean isGone() {\n    return getVisibility() == View.GONE;\n  }\n\n  @Override\n  protected void onSizeChanged(int w, int h, int oldw, int oldh) {\n    super.onSizeChanged(w, h, oldw, oldh);\n    if (foreground != null) {\n      foreground.setBounds(0, 0, w, h);\n    }\n  }\n\n  @Override\n  protected boolean verifyDrawable(Drawable who) {\n    return super.verifyDrawable(who) || (who == foreground);\n  }\n\n  @Override\n  public void jumpDrawablesToCurrentState() {\n    super.jumpDrawablesToCurrentState();\n    if (foreground != null) {\n      foreground.jumpToCurrentState();\n    }\n  }\n\n  @Override\n  protected void drawableStateChanged() {\n    super.drawableStateChanged();\n    if (foreground != null && foreground.isStateful()) {\n      foreground.setState(getDrawableState());\n    }\n  }\n\n  /**\n   * Returns the drawable used as the foreground of this view. The foreground drawable, if non-null,\n   * is always drawn on top of the children.\n   *\n   * @return A Drawable or null if no foreground was set.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  public Drawable getForeground() {\n    return foreground;\n  }\n\n  /**\n   * Supply a Drawable that is to be rendered on top of all of the child views in this layout. Any\n   * padding in the Drawable will be taken into account by ensuring that the children are inset to\n   * be placed inside of the padding area.\n   *\n   * @param drawable The Drawable to be drawn on top of the children.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  @SuppressLint(\"NewApi\")\n  public void setForeground(Drawable drawable) {\n    if (foreground != drawable) {\n      if (foreground != null) {\n        foreground.setCallback(null);\n        unscheduleDrawable(foreground);\n      }\n      foreground = drawable;\n      if (drawable != null) {\n        foreground.setBounds(0, 0, getWidth(), getHeight());\n        setWillNotDraw(false);\n        drawable.setCallback(this);\n        if (drawable.isStateful()) {\n          drawable.setState(getDrawableState());\n        }\n      } else {\n        setWillNotDraw(true);\n      }\n      invalidate();\n    }\n  }\n\n  @Override\n  public void draw(Canvas canvas) {\n    super.draw(canvas);\n    if (foreground != null) {\n      foreground.draw(canvas);\n    }\n  }\n\n  @TargetApi(android.os.Build.VERSION_CODES.LOLLIPOP)\n  @Override\n  public void drawableHotspotChanged(float x, float y) {\n    super.drawableHotspotChanged(x, y);\n    if (foreground != null) {\n      foreground.setHotspot(x, y);\n    }\n  }\n\n  /** @deprecated Use {@link #clicks()} */\n  @Override\n  @Deprecated\n  public final void setOnClickListener(@Nullable final OnClickListener l) {\n    if (clicksIsInitting) {\n      clicksIsInitting = false;\n      super.setOnClickListener(l);\n    } else {\n      if (clicksDisposable != null) {\n        clicksDisposable.dispose();\n        clicksDisposable = null;\n      }\n      if (l != null) {\n        clicksDisposable =\n            clicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onClick(MyEditText.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of click events. The emitted value is unspecified and should only be used\n   *     as notification.\n   */\n  public Observable<Signal> clicks() {\n    if (clicks == null) {\n      clicksIsInitting = true;\n      clicks = PublishRelay.create();\n      RxView.clicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(clicks);\n    }\n    return clicks.hide();\n  }\n\n  /** @deprecated Use {@link #longClicks()} */\n  @Override\n  @Deprecated\n  public final void setOnLongClickListener(@Nullable final OnLongClickListener l) {\n    if (longClicksIsInitting) {\n      longClicksIsInitting = false;\n      super.setOnLongClickListener(l);\n    } else {\n      if (longClicksDisposable != null) {\n        longClicksDisposable.dispose();\n        longClicksDisposable = null;\n      }\n      if (l != null) {\n        longClicksDisposable =\n            longClicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onLongClick(MyEditText.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of longclick events. The emitted value is unspecified and should only be\n   *     used as notification.\n   */\n  public Observable<Signal> longClicks() {\n    if (longClicks == null) {\n      longClicksIsInitting = true;\n      longClicks = PublishRelay.create();\n      RxView.longClicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(longClicks);\n    }\n    return longClicks.hide();\n  }\n\n  /**\n   * @return an observable which emits on layout changes. The emitted value is unspecified and\n   *     should only be used as notification.\n   */\n  public Observable<Signal> layoutChanges() {\n    return RxView.layoutChanges(this).map(MyUtils.createRxBindingSignalMapper());\n  }\n\n  /** @return an observable of character sequences for text changes on this TextView. */\n  public Observable<CharSequence> textChanges() {\n    return RxTextView.textChanges(this);\n  }\n\n  @CallSuper\n  protected void init(\n      Context context,\n      @Nullable AttributeSet attrs,\n      @AttrRes int defStyleAttr,\n      @StyleRes int defStyleRes) {\n    TypedArray foregroundTA = context.obtainStyledAttributes(attrs, R.styleable.ForegroundView);\n    final Drawable localForeground =\n        foregroundTA.getDrawable(R.styleable.ForegroundView_android_foreground);\n    if (localForeground != null) {\n      // noinspection AndroidLintNewApi\n      setForeground(localForeground);\n    }\n    foregroundTA.recycle();\n  }\n}\n"
  },
  {
    "path": "sample/demo/java/MyImageView.java",
    "content": "package com.uber.artist.mylibrary;\n\nimport android.annotation.SuppressLint;\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Canvas;\nimport android.graphics.drawable.Drawable;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport androidx.annotation.AttrRes;\nimport androidx.annotation.CallSuper;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StyleRes;\nimport androidx.appcompat.widget.AppCompatImageView;\nimport com.jakewharton.rxbinding3.view.RxView;\nimport com.jakewharton.rxrelay2.PublishRelay;\nimport io.reactivex.Observable;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.functions.Consumer;\nimport java.lang.Deprecated;\nimport java.lang.Override;\nimport java.lang.SuppressWarnings;\n\npublic class MyImageView extends AppCompatImageView implements MyView {\n  private Drawable foreground;\n\n  private boolean clicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> clicks;\n\n  @Nullable private Disposable clicksDisposable;\n\n  private boolean longClicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> longClicks;\n\n  @Nullable private Disposable longClicksDisposable;\n\n  public MyImageView(Context context) {\n    this(context, null);\n  }\n\n  public MyImageView(Context context, @Nullable AttributeSet attrs) {\n    this(context, attrs, 0);\n  }\n\n  public MyImageView(Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {\n    super(context, attrs, defStyleAttr);\n    init(context, attrs, defStyleAttr, 0);\n  }\n\n  public View sampleMethodFromCustomTrait() {\n    return this;\n  }\n\n  public boolean isVisible() {\n    return getVisibility() == View.VISIBLE;\n  }\n\n  public boolean isInvisible() {\n    return getVisibility() == View.INVISIBLE;\n  }\n\n  public boolean isGone() {\n    return getVisibility() == View.GONE;\n  }\n\n  @Override\n  protected void onSizeChanged(int w, int h, int oldw, int oldh) {\n    super.onSizeChanged(w, h, oldw, oldh);\n    if (foreground != null) {\n      foreground.setBounds(0, 0, w, h);\n    }\n  }\n\n  @Override\n  public boolean hasOverlappingRendering() {\n    return false;\n  }\n\n  @Override\n  protected boolean verifyDrawable(Drawable who) {\n    return super.verifyDrawable(who) || (who == foreground);\n  }\n\n  @Override\n  public void jumpDrawablesToCurrentState() {\n    super.jumpDrawablesToCurrentState();\n    if (foreground != null) {\n      foreground.jumpToCurrentState();\n    }\n  }\n\n  @Override\n  protected void drawableStateChanged() {\n    super.drawableStateChanged();\n    if (foreground != null && foreground.isStateful()) {\n      foreground.setState(getDrawableState());\n    }\n  }\n\n  /**\n   * Returns the drawable used as the foreground of this view. The foreground drawable, if non-null,\n   * is always drawn on top of the children.\n   *\n   * @return A Drawable or null if no foreground was set.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  public Drawable getForeground() {\n    return foreground;\n  }\n\n  /**\n   * Supply a Drawable that is to be rendered on top of all of the child views in this layout. Any\n   * padding in the Drawable will be taken into account by ensuring that the children are inset to\n   * be placed inside of the padding area.\n   *\n   * @param drawable The Drawable to be drawn on top of the children.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  @SuppressLint(\"NewApi\")\n  public void setForeground(Drawable drawable) {\n    if (foreground != drawable) {\n      if (foreground != null) {\n        foreground.setCallback(null);\n        unscheduleDrawable(foreground);\n      }\n      foreground = drawable;\n      if (drawable != null) {\n        foreground.setBounds(0, 0, getWidth(), getHeight());\n        setWillNotDraw(false);\n        drawable.setCallback(this);\n        if (drawable.isStateful()) {\n          drawable.setState(getDrawableState());\n        }\n      } else {\n        setWillNotDraw(true);\n      }\n      invalidate();\n    }\n  }\n\n  @Override\n  public void draw(Canvas canvas) {\n    super.draw(canvas);\n    if (foreground != null) {\n      foreground.draw(canvas);\n    }\n  }\n\n  @TargetApi(android.os.Build.VERSION_CODES.LOLLIPOP)\n  @Override\n  public void drawableHotspotChanged(float x, float y) {\n    super.drawableHotspotChanged(x, y);\n    if (foreground != null) {\n      foreground.setHotspot(x, y);\n    }\n  }\n\n  /** @deprecated Use {@link #clicks()} */\n  @Override\n  @Deprecated\n  public final void setOnClickListener(@Nullable final OnClickListener l) {\n    if (clicksIsInitting) {\n      clicksIsInitting = false;\n      super.setOnClickListener(l);\n    } else {\n      if (clicksDisposable != null) {\n        clicksDisposable.dispose();\n        clicksDisposable = null;\n      }\n      if (l != null) {\n        clicksDisposable =\n            clicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onClick(MyImageView.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of click events. The emitted value is unspecified and should only be used\n   *     as notification.\n   */\n  public Observable<Signal> clicks() {\n    if (clicks == null) {\n      clicksIsInitting = true;\n      clicks = PublishRelay.create();\n      RxView.clicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(clicks);\n    }\n    return clicks.hide();\n  }\n\n  /** @deprecated Use {@link #longClicks()} */\n  @Override\n  @Deprecated\n  public final void setOnLongClickListener(@Nullable final OnLongClickListener l) {\n    if (longClicksIsInitting) {\n      longClicksIsInitting = false;\n      super.setOnLongClickListener(l);\n    } else {\n      if (longClicksDisposable != null) {\n        longClicksDisposable.dispose();\n        longClicksDisposable = null;\n      }\n      if (l != null) {\n        longClicksDisposable =\n            longClicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onLongClick(MyImageView.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of longclick events. The emitted value is unspecified and should only be\n   *     used as notification.\n   */\n  public Observable<Signal> longClicks() {\n    if (longClicks == null) {\n      longClicksIsInitting = true;\n      longClicks = PublishRelay.create();\n      RxView.longClicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(longClicks);\n    }\n    return longClicks.hide();\n  }\n\n  /**\n   * @return an observable which emits on layout changes. The emitted value is unspecified and\n   *     should only be used as notification.\n   */\n  public Observable<Signal> layoutChanges() {\n    return RxView.layoutChanges(this).map(MyUtils.createRxBindingSignalMapper());\n  }\n\n  @CallSuper\n  protected void init(\n      Context context,\n      @Nullable AttributeSet attrs,\n      @AttrRes int defStyleAttr,\n      @StyleRes int defStyleRes) {\n    TypedArray foregroundTA = context.obtainStyledAttributes(attrs, R.styleable.ForegroundView);\n    final Drawable localForeground =\n        foregroundTA.getDrawable(R.styleable.ForegroundView_android_foreground);\n    if (localForeground != null) {\n      // noinspection AndroidLintNewApi\n      setForeground(localForeground);\n    }\n    foregroundTA.recycle();\n  }\n}\n"
  },
  {
    "path": "sample/demo/java/MyLinearLayout.java",
    "content": "package com.uber.artist.mylibrary;\n\nimport android.annotation.SuppressLint;\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Canvas;\nimport android.graphics.Rect;\nimport android.graphics.drawable.Drawable;\nimport android.util.AttributeSet;\nimport android.view.Gravity;\nimport android.view.View;\nimport android.widget.LinearLayout;\nimport androidx.annotation.AttrRes;\nimport androidx.annotation.CallSuper;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StyleRes;\nimport androidx.core.view.GravityCompat;\nimport com.jakewharton.rxbinding3.view.RxView;\nimport com.jakewharton.rxrelay2.PublishRelay;\nimport io.reactivex.Observable;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.functions.Consumer;\nimport java.lang.Deprecated;\nimport java.lang.Override;\nimport java.lang.SuppressWarnings;\n\npublic class MyLinearLayout extends LinearLayout implements MyView {\n  private Drawable foreground;\n\n  private final Rect selfBounds = new Rect();\n\n  private final Rect overlayBounds = new Rect();\n\n  private boolean foregroundInPadding = true;\n\n  private boolean foregroundBoundsChanged = false;\n\n  private int foregroundGravity = Gravity.FILL;\n\n  private boolean clicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> clicks;\n\n  @Nullable private Disposable clicksDisposable;\n\n  private boolean longClicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> longClicks;\n\n  @Nullable private Disposable longClicksDisposable;\n\n  public MyLinearLayout(Context context) {\n    this(context, null);\n  }\n\n  public MyLinearLayout(Context context, @Nullable AttributeSet attrs) {\n    this(context, attrs, 0);\n  }\n\n  public MyLinearLayout(Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {\n    super(context, attrs, defStyleAttr);\n    init(context, attrs, defStyleAttr, 0);\n  }\n\n  public View sampleMethodFromCustomTrait() {\n    return this;\n  }\n\n  public boolean isVisible() {\n    return getVisibility() == View.VISIBLE;\n  }\n\n  public boolean isInvisible() {\n    return getVisibility() == View.INVISIBLE;\n  }\n\n  public boolean isGone() {\n    return getVisibility() == View.GONE;\n  }\n\n  @Override\n  protected void onSizeChanged(int w, int h, int oldw, int oldh) {\n    super.onSizeChanged(w, h, oldw, oldh);\n    foregroundBoundsChanged = true;\n  }\n\n  /**\n   * Describes how the foreground is positioned.\n   *\n   * @return foreground gravity.\n   * @see #setForegroundGravity(int)\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  public int getForegroundGravity() {\n    return foregroundGravity;\n  }\n\n  /**\n   * Describes how the foreground is positioned. Defaults to START and TOP.\n   *\n   * @param foregroundGravity See {@link android.view.Gravity}\n   * @see #getForegroundGravity()\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  public void setForegroundGravity(int foregroundGravity) {\n    if (this.foregroundGravity != foregroundGravity) {\n      if ((foregroundGravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {\n        foregroundGravity |= GravityCompat.START;\n      }\n      if ((foregroundGravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {\n        foregroundGravity |= Gravity.TOP;\n      }\n      this.foregroundGravity = foregroundGravity;\n      if (this.foregroundGravity == Gravity.FILL && foreground != null) {\n        Rect padding = new Rect();\n        foreground.getPadding(padding);\n      }\n      requestLayout();\n    }\n  }\n\n  @Override\n  protected boolean verifyDrawable(Drawable who) {\n    return super.verifyDrawable(who) || (who == foreground);\n  }\n\n  @Override\n  public void jumpDrawablesToCurrentState() {\n    super.jumpDrawablesToCurrentState();\n    if (foreground != null) {\n      foreground.jumpToCurrentState();\n    }\n  }\n\n  @Override\n  protected void drawableStateChanged() {\n    super.drawableStateChanged();\n    if (foreground != null && foreground.isStateful()) {\n      foreground.setState(getDrawableState());\n    }\n  }\n\n  /**\n   * Returns the drawable used as the foreground of this view. The foreground drawable, if non-null,\n   * is always drawn on top of the children.\n   *\n   * @return A Drawable or null if no foreground was set.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  public Drawable getForeground() {\n    return foreground;\n  }\n\n  /**\n   * Supply a Drawable that is to be rendered on top of all of the child views in this layout. Any\n   * padding in the Drawable will be taken into account by ensuring that the children are inset to\n   * be placed inside of the padding area.\n   *\n   * @param drawable The Drawable to be drawn on top of the children.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  @SuppressLint(\"NewApi\")\n  public void setForeground(Drawable drawable) {\n    if (foreground != drawable) {\n      if (foreground != null) {\n        foreground.setCallback(null);\n        unscheduleDrawable(foreground);\n      }\n      foreground = drawable;\n      if (drawable != null) {\n        setWillNotDraw(false);\n        drawable.setCallback(this);\n        if (drawable.isStateful()) {\n          drawable.setState(getDrawableState());\n        }\n        if (foregroundGravity == Gravity.FILL) {\n          Rect padding = new Rect();\n          drawable.getPadding(padding);\n        }\n      } else {\n        setWillNotDraw(true);\n      }\n      requestLayout();\n      invalidate();\n    }\n  }\n\n  @Override\n  protected void onLayout(boolean changed, int left, int top, int right, int bottom) {\n    super.onLayout(changed, left, top, right, bottom);\n    if (changed) {\n      foregroundBoundsChanged = true;\n    }\n  }\n\n  @Override\n  public void draw(Canvas canvas) {\n    super.draw(canvas);\n    if (foreground != null) {\n      final Drawable localForeground = foreground;\n      if (foregroundBoundsChanged) {\n        foregroundBoundsChanged = false;\n        final Rect localSelfBounds = selfBounds;\n        final Rect localOverlayBounds = overlayBounds;\n        final int w = getRight() - getLeft();\n        final int h = getBottom() - getTop();\n        if (foregroundInPadding) {\n          localSelfBounds.set(0, 0, w, h);\n        } else {\n          localSelfBounds.set(\n              getPaddingLeft(), getPaddingTop(), w - getPaddingRight(), h - getPaddingBottom());\n        }\n        Gravity.apply(\n            foregroundGravity,\n            localForeground.getIntrinsicWidth(),\n            localForeground.getIntrinsicHeight(),\n            localSelfBounds,\n            localOverlayBounds);\n        localForeground.setBounds(localOverlayBounds);\n      }\n      localForeground.draw(canvas);\n    }\n  }\n\n  @TargetApi(android.os.Build.VERSION_CODES.LOLLIPOP)\n  @Override\n  public void drawableHotspotChanged(float x, float y) {\n    super.drawableHotspotChanged(x, y);\n    if (foreground != null) {\n      foreground.setHotspot(x, y);\n    }\n  }\n\n  /** @deprecated Use {@link #clicks()} */\n  @Override\n  @Deprecated\n  public final void setOnClickListener(@Nullable final OnClickListener l) {\n    if (clicksIsInitting) {\n      clicksIsInitting = false;\n      super.setOnClickListener(l);\n    } else {\n      if (clicksDisposable != null) {\n        clicksDisposable.dispose();\n        clicksDisposable = null;\n      }\n      if (l != null) {\n        clicksDisposable =\n            clicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onClick(MyLinearLayout.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of click events. The emitted value is unspecified and should only be used\n   *     as notification.\n   */\n  public Observable<Signal> clicks() {\n    if (clicks == null) {\n      clicksIsInitting = true;\n      clicks = PublishRelay.create();\n      RxView.clicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(clicks);\n    }\n    return clicks.hide();\n  }\n\n  /** @deprecated Use {@link #longClicks()} */\n  @Override\n  @Deprecated\n  public final void setOnLongClickListener(@Nullable final OnLongClickListener l) {\n    if (longClicksIsInitting) {\n      longClicksIsInitting = false;\n      super.setOnLongClickListener(l);\n    } else {\n      if (longClicksDisposable != null) {\n        longClicksDisposable.dispose();\n        longClicksDisposable = null;\n      }\n      if (l != null) {\n        longClicksDisposable =\n            longClicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onLongClick(MyLinearLayout.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of longclick events. The emitted value is unspecified and should only be\n   *     used as notification.\n   */\n  public Observable<Signal> longClicks() {\n    if (longClicks == null) {\n      longClicksIsInitting = true;\n      longClicks = PublishRelay.create();\n      RxView.longClicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(longClicks);\n    }\n    return longClicks.hide();\n  }\n\n  /**\n   * @return an observable which emits on layout changes. The emitted value is unspecified and\n   *     should only be used as notification.\n   */\n  public Observable<Signal> layoutChanges() {\n    return RxView.layoutChanges(this).map(MyUtils.createRxBindingSignalMapper());\n  }\n\n  @CallSuper\n  protected void init(\n      Context context,\n      @Nullable AttributeSet attrs,\n      @AttrRes int defStyleAttr,\n      @StyleRes int defStyleRes) {\n    TypedArray foregroundTA = context.obtainStyledAttributes(attrs, R.styleable.ForegroundView);\n    final Drawable localForeground =\n        foregroundTA.getDrawable(R.styleable.ForegroundView_android_foreground);\n    if (localForeground != null) {\n      // noinspection AndroidLintNewApi\n      setForeground(localForeground);\n    }\n    foregroundGravity =\n        foregroundTA.getInt(\n            R.styleable.ForegroundView_android_foregroundGravity, foregroundGravity);\n    foregroundInPadding =\n        foregroundTA.getBoolean(R.styleable.ForegroundView_foregroundInsidePadding, true);\n    foregroundTA.recycle();\n  }\n}\n"
  },
  {
    "path": "sample/demo/java/MyNestedScrollView.java",
    "content": "package com.uber.artist.mylibrary;\n\nimport android.annotation.SuppressLint;\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Canvas;\nimport android.graphics.drawable.Drawable;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport androidx.annotation.AttrRes;\nimport androidx.annotation.CallSuper;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StyleRes;\nimport androidx.core.widget.NestedScrollView;\nimport com.jakewharton.rxbinding3.core.RxNestedScrollView;\nimport com.jakewharton.rxbinding3.view.RxView;\nimport com.jakewharton.rxbinding3.view.ViewScrollChangeEvent;\nimport com.jakewharton.rxrelay2.PublishRelay;\nimport io.reactivex.Observable;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.functions.Consumer;\nimport java.lang.Deprecated;\nimport java.lang.Override;\nimport java.lang.SuppressWarnings;\n\npublic class MyNestedScrollView extends NestedScrollView implements MyView {\n  private Drawable foreground;\n\n  private boolean clicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> clicks;\n\n  @Nullable private Disposable clicksDisposable;\n\n  private boolean longClicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> longClicks;\n\n  @Nullable private Disposable longClicksDisposable;\n\n  private boolean scrollChangeEventsIsInitting;\n\n  @Nullable private PublishRelay<ViewScrollChangeEvent> scrollChangeEvents;\n\n  @Nullable private Disposable scrollChangeEventsDisposable;\n\n  public MyNestedScrollView(Context context) {\n    this(context, null);\n  }\n\n  public MyNestedScrollView(Context context, @Nullable AttributeSet attrs) {\n    this(context, attrs, 0);\n  }\n\n  public MyNestedScrollView(\n      Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {\n    super(context, attrs, defStyleAttr);\n    init(context, attrs, defStyleAttr, 0);\n  }\n\n  public View sampleMethodFromCustomTrait() {\n    return this;\n  }\n\n  public boolean isVisible() {\n    return getVisibility() == View.VISIBLE;\n  }\n\n  public boolean isInvisible() {\n    return getVisibility() == View.INVISIBLE;\n  }\n\n  public boolean isGone() {\n    return getVisibility() == View.GONE;\n  }\n\n  @Override\n  protected void onSizeChanged(int w, int h, int oldw, int oldh) {\n    super.onSizeChanged(w, h, oldw, oldh);\n    if (foreground != null) {\n      foreground.setBounds(0, 0, w, h);\n    }\n  }\n\n  @Override\n  protected boolean verifyDrawable(Drawable who) {\n    return super.verifyDrawable(who) || (who == foreground);\n  }\n\n  @Override\n  public void jumpDrawablesToCurrentState() {\n    super.jumpDrawablesToCurrentState();\n    if (foreground != null) {\n      foreground.jumpToCurrentState();\n    }\n  }\n\n  @Override\n  protected void drawableStateChanged() {\n    super.drawableStateChanged();\n    if (foreground != null && foreground.isStateful()) {\n      foreground.setState(getDrawableState());\n    }\n  }\n\n  /**\n   * Returns the drawable used as the foreground of this view. The foreground drawable, if non-null,\n   * is always drawn on top of the children.\n   *\n   * @return A Drawable or null if no foreground was set.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  public Drawable getForeground() {\n    return foreground;\n  }\n\n  /**\n   * Supply a Drawable that is to be rendered on top of all of the child views in this layout. Any\n   * padding in the Drawable will be taken into account by ensuring that the children are inset to\n   * be placed inside of the padding area.\n   *\n   * @param drawable The Drawable to be drawn on top of the children.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  @SuppressLint(\"NewApi\")\n  public void setForeground(Drawable drawable) {\n    if (foreground != drawable) {\n      if (foreground != null) {\n        foreground.setCallback(null);\n        unscheduleDrawable(foreground);\n      }\n      foreground = drawable;\n      if (drawable != null) {\n        foreground.setBounds(0, 0, getWidth(), getHeight());\n        setWillNotDraw(false);\n        drawable.setCallback(this);\n        if (drawable.isStateful()) {\n          drawable.setState(getDrawableState());\n        }\n      } else {\n        setWillNotDraw(true);\n      }\n      invalidate();\n    }\n  }\n\n  @Override\n  public void draw(Canvas canvas) {\n    super.draw(canvas);\n    if (foreground != null) {\n      foreground.draw(canvas);\n    }\n  }\n\n  @TargetApi(android.os.Build.VERSION_CODES.LOLLIPOP)\n  @Override\n  public void drawableHotspotChanged(float x, float y) {\n    super.drawableHotspotChanged(x, y);\n    if (foreground != null) {\n      foreground.setHotspot(x, y);\n    }\n  }\n\n  /** @deprecated Use {@link #clicks()} */\n  @Override\n  @Deprecated\n  public final void setOnClickListener(@Nullable final OnClickListener l) {\n    if (clicksIsInitting) {\n      clicksIsInitting = false;\n      super.setOnClickListener(l);\n    } else {\n      if (clicksDisposable != null) {\n        clicksDisposable.dispose();\n        clicksDisposable = null;\n      }\n      if (l != null) {\n        clicksDisposable =\n            clicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onClick(MyNestedScrollView.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of click events. The emitted value is unspecified and should only be used\n   *     as notification.\n   */\n  public Observable<Signal> clicks() {\n    if (clicks == null) {\n      clicksIsInitting = true;\n      clicks = PublishRelay.create();\n      RxView.clicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(clicks);\n    }\n    return clicks.hide();\n  }\n\n  /** @deprecated Use {@link #longClicks()} */\n  @Override\n  @Deprecated\n  public final void setOnLongClickListener(@Nullable final OnLongClickListener l) {\n    if (longClicksIsInitting) {\n      longClicksIsInitting = false;\n      super.setOnLongClickListener(l);\n    } else {\n      if (longClicksDisposable != null) {\n        longClicksDisposable.dispose();\n        longClicksDisposable = null;\n      }\n      if (l != null) {\n        longClicksDisposable =\n            longClicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onLongClick(MyNestedScrollView.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of longclick events. The emitted value is unspecified and should only be\n   *     used as notification.\n   */\n  public Observable<Signal> longClicks() {\n    if (longClicks == null) {\n      longClicksIsInitting = true;\n      longClicks = PublishRelay.create();\n      RxView.longClicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(longClicks);\n    }\n    return longClicks.hide();\n  }\n\n  /**\n   * @return an observable which emits on layout changes. The emitted value is unspecified and\n   *     should only be used as notification.\n   */\n  public Observable<Signal> layoutChanges() {\n    return RxView.layoutChanges(this).map(MyUtils.createRxBindingSignalMapper());\n  }\n\n  /** @deprecated Use {@link #scrollChangeEvents()} */\n  @Override\n  @Deprecated\n  public final void setOnScrollChangeListener(final OnScrollChangeListener l) {\n    if (scrollChangeEventsIsInitting) {\n      scrollChangeEventsIsInitting = false;\n      super.setOnScrollChangeListener(l);\n    } else {\n      if (scrollChangeEventsDisposable != null) {\n        scrollChangeEventsDisposable.dispose();\n        scrollChangeEventsDisposable = null;\n      }\n      if (l != null) {\n        scrollChangeEventsDisposable =\n            scrollChangeEvents()\n                .subscribe(\n                    new Consumer<ViewScrollChangeEvent>() {\n                      @Override\n                      public void accept(ViewScrollChangeEvent event) {\n                        l.onScrollChange(\n                            MyNestedScrollView.this,\n                            event.scrollX(),\n                            event.scrollY(),\n                            event.oldScrollX(),\n                            event.oldScrollY());\n                      }\n                    });\n      }\n    }\n  }\n\n  /** @return an observable of scroll-change events for this NestedScrollView. */\n  public Observable<ViewScrollChangeEvent> scrollChangeEvents() {\n    if (scrollChangeEvents == null) {\n      scrollChangeEventsIsInitting = true;\n      scrollChangeEvents = PublishRelay.create();\n      RxNestedScrollView.scrollChangeEvents(this).subscribe(scrollChangeEvents);\n    }\n    return scrollChangeEvents.hide();\n  }\n\n  @CallSuper\n  protected void init(\n      Context context,\n      @Nullable AttributeSet attrs,\n      @AttrRes int defStyleAttr,\n      @StyleRes int defStyleRes) {\n    TypedArray foregroundTA = context.obtainStyledAttributes(attrs, R.styleable.ForegroundView);\n    final Drawable localForeground =\n        foregroundTA.getDrawable(R.styleable.ForegroundView_android_foreground);\n    if (localForeground != null) {\n      // noinspection AndroidLintNewApi\n      setForeground(localForeground);\n    }\n    foregroundTA.recycle();\n  }\n}\n"
  },
  {
    "path": "sample/demo/java/MySwitch.java",
    "content": "package com.uber.artist.mylibrary;\n\nimport android.annotation.SuppressLint;\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Canvas;\nimport android.graphics.drawable.Drawable;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport androidx.annotation.AttrRes;\nimport androidx.annotation.CallSuper;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StyleRes;\nimport androidx.appcompat.widget.SwitchCompat;\nimport com.jakewharton.rxbinding3.view.RxView;\nimport com.jakewharton.rxbinding3.widget.RxCompoundButton;\nimport com.jakewharton.rxrelay2.BehaviorRelay;\nimport com.jakewharton.rxrelay2.PublishRelay;\nimport io.reactivex.Observable;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.functions.Consumer;\nimport java.lang.Boolean;\nimport java.lang.Deprecated;\nimport java.lang.Override;\nimport java.lang.SuppressWarnings;\n\npublic class MySwitch extends SwitchCompat implements MyView {\n  private Drawable foreground;\n\n  private boolean clicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> clicks;\n\n  @Nullable private Disposable clicksDisposable;\n\n  private boolean longClicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> longClicks;\n\n  @Nullable private Disposable longClicksDisposable;\n\n  private boolean checkedChangesIsInitting;\n\n  @Nullable private BehaviorRelay<Boolean> checkedChanges;\n\n  @Nullable private Disposable checkedChangesDisposable;\n\n  public MySwitch(Context context) {\n    this(context, null);\n  }\n\n  public MySwitch(Context context, @Nullable AttributeSet attrs) {\n    this(context, attrs, R.attr.switchStyle);\n  }\n\n  public MySwitch(Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {\n    super(context, attrs, defStyleAttr);\n    init(context, attrs, defStyleAttr, 0);\n  }\n\n  public View sampleMethodFromCustomTrait() {\n    return this;\n  }\n\n  public boolean isVisible() {\n    return getVisibility() == View.VISIBLE;\n  }\n\n  public boolean isInvisible() {\n    return getVisibility() == View.INVISIBLE;\n  }\n\n  public boolean isGone() {\n    return getVisibility() == View.GONE;\n  }\n\n  @Override\n  protected void onSizeChanged(int w, int h, int oldw, int oldh) {\n    super.onSizeChanged(w, h, oldw, oldh);\n    if (foreground != null) {\n      foreground.setBounds(0, 0, w, h);\n    }\n  }\n\n  @Override\n  protected boolean verifyDrawable(Drawable who) {\n    return super.verifyDrawable(who) || (who == foreground);\n  }\n\n  @Override\n  public void jumpDrawablesToCurrentState() {\n    super.jumpDrawablesToCurrentState();\n    if (foreground != null) {\n      foreground.jumpToCurrentState();\n    }\n  }\n\n  @Override\n  protected void drawableStateChanged() {\n    super.drawableStateChanged();\n    if (foreground != null && foreground.isStateful()) {\n      foreground.setState(getDrawableState());\n    }\n  }\n\n  /**\n   * Returns the drawable used as the foreground of this view. The foreground drawable, if non-null,\n   * is always drawn on top of the children.\n   *\n   * @return A Drawable or null if no foreground was set.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  public Drawable getForeground() {\n    return foreground;\n  }\n\n  /**\n   * Supply a Drawable that is to be rendered on top of all of the child views in this layout. Any\n   * padding in the Drawable will be taken into account by ensuring that the children are inset to\n   * be placed inside of the padding area.\n   *\n   * @param drawable The Drawable to be drawn on top of the children.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  @SuppressLint(\"NewApi\")\n  public void setForeground(Drawable drawable) {\n    if (foreground != drawable) {\n      if (foreground != null) {\n        foreground.setCallback(null);\n        unscheduleDrawable(foreground);\n      }\n      foreground = drawable;\n      if (drawable != null) {\n        foreground.setBounds(0, 0, getWidth(), getHeight());\n        setWillNotDraw(false);\n        drawable.setCallback(this);\n        if (drawable.isStateful()) {\n          drawable.setState(getDrawableState());\n        }\n      } else {\n        setWillNotDraw(true);\n      }\n      invalidate();\n    }\n  }\n\n  @Override\n  public void draw(Canvas canvas) {\n    super.draw(canvas);\n    if (foreground != null) {\n      foreground.draw(canvas);\n    }\n  }\n\n  @TargetApi(android.os.Build.VERSION_CODES.LOLLIPOP)\n  @Override\n  public void drawableHotspotChanged(float x, float y) {\n    super.drawableHotspotChanged(x, y);\n    if (foreground != null) {\n      foreground.setHotspot(x, y);\n    }\n  }\n\n  /** @deprecated Use {@link #clicks()} */\n  @Override\n  @Deprecated\n  public final void setOnClickListener(@Nullable final OnClickListener l) {\n    if (clicksIsInitting) {\n      clicksIsInitting = false;\n      super.setOnClickListener(l);\n    } else {\n      if (clicksDisposable != null) {\n        clicksDisposable.dispose();\n        clicksDisposable = null;\n      }\n      if (l != null) {\n        clicksDisposable =\n            clicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onClick(MySwitch.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of click events. The emitted value is unspecified and should only be used\n   *     as notification.\n   */\n  public Observable<Signal> clicks() {\n    if (clicks == null) {\n      clicksIsInitting = true;\n      clicks = PublishRelay.create();\n      RxView.clicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(clicks);\n    }\n    return clicks.hide();\n  }\n\n  /** @deprecated Use {@link #longClicks()} */\n  @Override\n  @Deprecated\n  public final void setOnLongClickListener(@Nullable final OnLongClickListener l) {\n    if (longClicksIsInitting) {\n      longClicksIsInitting = false;\n      super.setOnLongClickListener(l);\n    } else {\n      if (longClicksDisposable != null) {\n        longClicksDisposable.dispose();\n        longClicksDisposable = null;\n      }\n      if (l != null) {\n        longClicksDisposable =\n            longClicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onLongClick(MySwitch.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of longclick events. The emitted value is unspecified and should only be\n   *     used as notification.\n   */\n  public Observable<Signal> longClicks() {\n    if (longClicks == null) {\n      longClicksIsInitting = true;\n      longClicks = PublishRelay.create();\n      RxView.longClicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(longClicks);\n    }\n    return longClicks.hide();\n  }\n\n  /**\n   * @return an observable which emits on layout changes. The emitted value is unspecified and\n   *     should only be used as notification.\n   */\n  public Observable<Signal> layoutChanges() {\n    return RxView.layoutChanges(this).map(MyUtils.createRxBindingSignalMapper());\n  }\n\n  /** @deprecated Use {@link #checkedChanges()} */\n  @Override\n  @Deprecated\n  public final void setOnCheckedChangeListener(@Nullable final OnCheckedChangeListener l) {\n    if (checkedChangesIsInitting) {\n      checkedChangesIsInitting = false;\n      super.setOnCheckedChangeListener(l);\n    } else {\n      if (checkedChangesDisposable != null) {\n        checkedChangesDisposable.dispose();\n        checkedChangesDisposable = null;\n      }\n      if (l != null) {\n        checkedChangesDisposable =\n            checkedChanges()\n                .subscribe(\n                    new Consumer<Boolean>() {\n                      @Override\n                      public void accept(Boolean isChecked) {\n                        l.onCheckedChanged(MySwitch.this, isChecked);\n                      }\n                    });\n      }\n    }\n  }\n\n  /** @return an observable of booleans representing the checked state of this view. */\n  public Observable<Boolean> checkedChanges() {\n    if (checkedChanges == null) {\n      checkedChangesIsInitting = true;\n      checkedChanges = BehaviorRelay.createDefault(isChecked());\n      RxCompoundButton.checkedChanges(this).subscribe(checkedChanges);\n    }\n    return checkedChanges.hide();\n  }\n\n  @CallSuper\n  protected void init(\n      Context context,\n      @Nullable AttributeSet attrs,\n      @AttrRes int defStyleAttr,\n      @StyleRes int defStyleRes) {\n    TypedArray foregroundTA = context.obtainStyledAttributes(attrs, R.styleable.ForegroundView);\n    final Drawable localForeground =\n        foregroundTA.getDrawable(R.styleable.ForegroundView_android_foreground);\n    if (localForeground != null) {\n      // noinspection AndroidLintNewApi\n      setForeground(localForeground);\n    }\n    foregroundTA.recycle();\n  }\n}\n"
  },
  {
    "path": "sample/demo/java/MyTextView.java",
    "content": "package com.uber.artist.mylibrary;\n\nimport android.annotation.SuppressLint;\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.Canvas;\nimport android.graphics.drawable.Drawable;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport android.widget.TextView;\nimport androidx.annotation.AttrRes;\nimport androidx.annotation.CallSuper;\nimport androidx.annotation.Nullable;\nimport androidx.annotation.StyleRes;\nimport com.jakewharton.rxbinding3.view.RxView;\nimport com.jakewharton.rxrelay2.PublishRelay;\nimport io.reactivex.Observable;\nimport io.reactivex.disposables.Disposable;\nimport io.reactivex.functions.Consumer;\nimport java.lang.Deprecated;\nimport java.lang.Override;\nimport java.lang.SuppressWarnings;\n\npublic class MyTextView extends TextView implements MyView {\n  private Drawable foreground;\n\n  private boolean clicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> clicks;\n\n  @Nullable private Disposable clicksDisposable;\n\n  private boolean longClicksIsInitting;\n\n  @Nullable private PublishRelay<Signal> longClicks;\n\n  @Nullable private Disposable longClicksDisposable;\n\n  public MyTextView(Context context) {\n    this(context, null);\n  }\n\n  public MyTextView(Context context, @Nullable AttributeSet attrs) {\n    this(context, attrs, android.R.attr.textViewStyle);\n  }\n\n  public MyTextView(Context context, @Nullable AttributeSet attrs, @AttrRes int defStyleAttr) {\n    super(context, attrs, defStyleAttr);\n    init(context, attrs, defStyleAttr, 0);\n  }\n\n  public View sampleMethodFromCustomTrait() {\n    return this;\n  }\n\n  public boolean isVisible() {\n    return getVisibility() == View.VISIBLE;\n  }\n\n  public boolean isInvisible() {\n    return getVisibility() == View.INVISIBLE;\n  }\n\n  public boolean isGone() {\n    return getVisibility() == View.GONE;\n  }\n\n  @Override\n  protected void onSizeChanged(int w, int h, int oldw, int oldh) {\n    super.onSizeChanged(w, h, oldw, oldh);\n    if (foreground != null) {\n      foreground.setBounds(0, 0, w, h);\n    }\n  }\n\n  @Override\n  protected boolean verifyDrawable(Drawable who) {\n    return super.verifyDrawable(who) || (who == foreground);\n  }\n\n  @Override\n  public void jumpDrawablesToCurrentState() {\n    super.jumpDrawablesToCurrentState();\n    if (foreground != null) {\n      foreground.jumpToCurrentState();\n    }\n  }\n\n  @Override\n  protected void drawableStateChanged() {\n    super.drawableStateChanged();\n    if (foreground != null && foreground.isStateful()) {\n      foreground.setState(getDrawableState());\n    }\n  }\n\n  /**\n   * Returns the drawable used as the foreground of this view. The foreground drawable, if non-null,\n   * is always drawn on top of the children.\n   *\n   * @return A Drawable or null if no foreground was set.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  public Drawable getForeground() {\n    return foreground;\n  }\n\n  /**\n   * Supply a Drawable that is to be rendered on top of all of the child views in this layout. Any\n   * padding in the Drawable will be taken into account by ensuring that the children are inset to\n   * be placed inside of the padding area.\n   *\n   * @param drawable The Drawable to be drawn on top of the children.\n   */\n  @SuppressWarnings(\"MissingOverride\")\n  @SuppressLint(\"NewApi\")\n  public void setForeground(Drawable drawable) {\n    if (foreground != drawable) {\n      if (foreground != null) {\n        foreground.setCallback(null);\n        unscheduleDrawable(foreground);\n      }\n      foreground = drawable;\n      if (drawable != null) {\n        foreground.setBounds(0, 0, getWidth(), getHeight());\n        setWillNotDraw(false);\n        drawable.setCallback(this);\n        if (drawable.isStateful()) {\n          drawable.setState(getDrawableState());\n        }\n      } else {\n        setWillNotDraw(true);\n      }\n      invalidate();\n    }\n  }\n\n  @Override\n  public void draw(Canvas canvas) {\n    super.draw(canvas);\n    if (foreground != null) {\n      foreground.draw(canvas);\n    }\n  }\n\n  @TargetApi(android.os.Build.VERSION_CODES.LOLLIPOP)\n  @Override\n  public void drawableHotspotChanged(float x, float y) {\n    super.drawableHotspotChanged(x, y);\n    if (foreground != null) {\n      foreground.setHotspot(x, y);\n    }\n  }\n\n  /** @deprecated Use {@link #clicks()} */\n  @Override\n  @Deprecated\n  public final void setOnClickListener(@Nullable final OnClickListener l) {\n    if (clicksIsInitting) {\n      clicksIsInitting = false;\n      super.setOnClickListener(l);\n    } else {\n      if (clicksDisposable != null) {\n        clicksDisposable.dispose();\n        clicksDisposable = null;\n      }\n      if (l != null) {\n        clicksDisposable =\n            clicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onClick(MyTextView.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of click events. The emitted value is unspecified and should only be used\n   *     as notification.\n   */\n  public Observable<Signal> clicks() {\n    if (clicks == null) {\n      clicksIsInitting = true;\n      clicks = PublishRelay.create();\n      RxView.clicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(clicks);\n    }\n    return clicks.hide();\n  }\n\n  /** @deprecated Use {@link #longClicks()} */\n  @Override\n  @Deprecated\n  public final void setOnLongClickListener(@Nullable final OnLongClickListener l) {\n    if (longClicksIsInitting) {\n      longClicksIsInitting = false;\n      super.setOnLongClickListener(l);\n    } else {\n      if (longClicksDisposable != null) {\n        longClicksDisposable.dispose();\n        longClicksDisposable = null;\n      }\n      if (l != null) {\n        longClicksDisposable =\n            longClicks()\n                .subscribe(\n                    new Consumer<Signal>() {\n                      @Override\n                      public void accept(Signal ignored) {\n                        l.onLongClick(MyTextView.this);\n                      }\n                    });\n      }\n    }\n  }\n\n  /**\n   * @return an Observable of longclick events. The emitted value is unspecified and should only be\n   *     used as notification.\n   */\n  public Observable<Signal> longClicks() {\n    if (longClicks == null) {\n      longClicksIsInitting = true;\n      longClicks = PublishRelay.create();\n      RxView.longClicks(this)\n          .map(MyUtils.createRxBindingSignalMapper())\n          .doOnNext(MyUtils.createTapProcessor())\n          .subscribe(longClicks);\n    }\n    return longClicks.hide();\n  }\n\n  /**\n   * @return an observable which emits on layout changes. The emitted value is unspecified and\n   *     should only be used as notification.\n   */\n  public Observable<Signal> layoutChanges() {\n    return RxView.layoutChanges(this).map(MyUtils.createRxBindingSignalMapper());\n  }\n\n  @CallSuper\n  protected void init(\n      Context context,\n      @Nullable AttributeSet attrs,\n      @AttrRes int defStyleAttr,\n      @StyleRes int defStyleRes) {\n    TypedArray foregroundTA = context.obtainStyledAttributes(attrs, R.styleable.ForegroundView);\n    final Drawable localForeground =\n        foregroundTA.getDrawable(R.styleable.ForegroundView_android_foreground);\n    if (localForeground != null) {\n      // noinspection AndroidLintNewApi\n      setForeground(localForeground);\n    }\n    foregroundTA.recycle();\n  }\n}\n"
  },
  {
    "path": "sample/library/build.gradle",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\napply plugin: 'com.android.library'\napply plugin: \"org.jetbrains.kotlin.android\"\nif (project.rootProject.name != 'buildSrc') {\n    apply plugin: 'com.uber.artist'\n}\n\nandroid {\n    compileSdkVersion deps.build.compileSdkVersion\n    buildToolsVersion deps.build.buildToolsVersion\n\n    defaultConfig {\n        minSdkVersion deps.build.minSdkVersion\n        targetSdkVersion deps.build.targetSdkVersion\n    }\n\n    compileOptions {\n        sourceCompatibility JavaVersion.VERSION_1_8\n        targetCompatibility JavaVersion.VERSION_1_8\n    }\n\n    // Setup a simple lint config for an android app/library.\n    lintOptions {\n        abortOnError false\n        lintConfig rootProject.file('config/lint/lint.xml')\n    }\n}\n\n// This is required to run checkstyle on an android app/library.\ntask checkstyle(type: Checkstyle) {\n    source 'src'\n    include '**/*.java'\n    exclude '**/gen/**'\n\n    classpath = files()\n}\ncheck.dependsOn 'checkstyle'\n\ndependencies {\n    api deps.androidx.appcompat\n    api deps.kotlin.stdLibJdk7\n    api deps.external.rxbinding\n    api deps.external.rxbindingAppCompat\n    api deps.external.rxbindingRecyclerView\n    api deps.external.rxjava2\n    api deps.external.rxrelay2\n}\n\nif (project.rootProject.name != 'buildSrc') {\n    artist {\n        interfaceClassName = \"com.uber.artist.mylibrary.MyView\"\n        viewNamePrefix = \"My\"\n        generateKotlin = false\n    }\n}\n"
  },
  {
    "path": "sample/library/src/main/AndroidManifest.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.uber.artist.mylibrary\"/>\n"
  },
  {
    "path": "sample/library/src/main/java/com/uber/artist/mylibrary/MyUtils.java",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.mylibrary;\n\nimport android.util.Log;\n\nimport io.reactivex.functions.Consumer;\nimport io.reactivex.functions.Function;\n\n/**\n * Various utilities used during code generation.\n */\npublic final class MyUtils {\n\n  private MyUtils() {\n  }\n\n  /**\n   * A static factory method that creates the Consumer that processes the tap. In this case we\n   * write a message in LogCat.\n   *\n   * @return The processor consumer.\n   */\n  public static Consumer<Object> createTapProcessor() {\n    return new Consumer<Object>() {\n      @Override\n      public void accept(Object o) {\n        Log.d(\"Artist\", \"Tapped a MyView\");\n      }\n    };\n  }\n\n  /**\n   * A static factory method that creates the Function that maps RxBinding signals to another type.\n   * In this case we map them to our instance of Signal.\n   *\n   * @return The mapper function.\n   */\n  public static Function<Object, Signal> createRxBindingSignalMapper() {\n    return new Function<Object, Signal>() {\n      @Override\n      public Signal apply(Object o) throws Exception {\n        return Signal.INSTANCE;\n      }\n    };\n  }\n}\n"
  },
  {
    "path": "sample/library/src/main/java/com/uber/artist/mylibrary/MyView.java",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.mylibrary;\n\n/**\n * A common interface amongst all of the Artist-generated View types.\n */\npublic interface MyView {\n\n}\n"
  },
  {
    "path": "sample/library/src/main/java/com/uber/artist/mylibrary/Signal.java",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.mylibrary;\n\n/**\n * Enum useful for Rx streams that are just notifications with no actual values.\n */\npublic enum Signal {\n  INSTANCE;\n\n  @Override\n  public String toString() {\n    return \"██████\";\n  }\n}\n"
  },
  {
    "path": "sample/library/src/main/res/values/attrs_foreground_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n  <declare-styleable name=\"ForegroundView\">\n    <attr name=\"android:foreground\"/>\n    <attr name=\"android:foregroundGravity\"/>\n    <attr name=\"foregroundInsidePadding\"/>\n  </declare-styleable>\n</resources>\n"
  },
  {
    "path": "sample/library/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">My Application</string>\n</resources>\n"
  },
  {
    "path": "sample/providers/build.gradle",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nbuildscript {\n    repositories {\n        maven { url deps.build.gradlePluginsUrl }\n    }\n\n    dependencies {\n        classpath deps.build.gradleAptPlugin\n    }\n}\n\napply plugin: 'java-library'\napply plugin: 'net.ltgt.apt'\n\nsourceCompatibility = JavaVersion.VERSION_1_7\ntargetCompatibility = JavaVersion.VERSION_1_7\n\ndependencies {\n    annotationProcessor deps.apt.autoService\n    compileOnly deps.apt.autoService\n\n    implementation deps.androidx.annotations\n    implementation project(\":artist-api\")\n    implementation project(\":artist-traits\")\n    implementation project(\":artist-traits-rx\")\n}\n"
  },
  {
    "path": "sample/providers/src/main/java/com/uber/artist/myproviders/JavaSampleRxConfig.java",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.myproviders;\n\nimport com.google.auto.service.AutoService;\nimport com.squareup.javapoet.CodeBlock;\nimport com.squareup.javapoet.TypeName;\nimport com.uber.artist.traits.rx.config.JavaArtistRxConfig;\n\nimport androidx.annotation.NonNull;\n\n/**\n * Sample Artist RxTrait Config.\n */\n@AutoService(JavaArtistRxConfig.class)\npublic class JavaSampleRxConfig extends JavaArtistRxConfig {\n\n  @Override\n  public void processTap(CodeBlock.Builder codeBlockBuilder) {\n    super.processTap(codeBlockBuilder);\n    codeBlockBuilder.add(\".doOnNext($T.createTapProcessor())\", JavaSampleTypeNames.MY_UTILS);\n  }\n\n  @Override\n  public void processRxBindingSignalEvent(@NonNull CodeBlock.Builder codeBlockBuilder) {\n    super.processRxBindingSignalEvent(codeBlockBuilder);\n    codeBlockBuilder.add(\".map($T.createRxBindingSignalMapper())\", JavaSampleTypeNames.MY_UTILS);\n  }\n\n  @Override\n  public TypeName rxBindingSignalEventTypeName() {\n    return JavaSampleTypeNames.SIGNAL;\n  }\n}\n"
  },
  {
    "path": "sample/providers/src/main/java/com/uber/artist/myproviders/JavaSampleTypeNames.java",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.myproviders;\n\nimport com.squareup.javapoet.ClassName;\n\n/**\n * Sample TypeNames.\n */\npublic final class JavaSampleTypeNames {\n\n  public static final ClassName MY_UTILS = ClassName.get(\"com.uber.artist.mylibrary\", \"MyUtils\");\n  public static final ClassName SIGNAL = ClassName.get(\"com.uber.artist.mylibrary\", \"Signal\");\n  public static final ClassName VIEW = ClassName.get(\"android.view\", \"View\");\n\n  private JavaSampleTypeNames() {\n  }\n}\n"
  },
  {
    "path": "sample/providers/src/main/java/com/uber/artist/myproviders/JavaSampleViewStencilProvider.java",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.myproviders;\n\nimport com.google.auto.service.AutoService;\nimport com.uber.artist.api.JavaTrait;\nimport com.uber.artist.api.JavaViewStencil;\nimport com.uber.artist.api.JavaViewStencilProvider;\nimport com.uber.artist.myproviders.trait.JavaSampleTrait;\nimport com.uber.artist.traits.JavaForegroundTrait;\nimport com.uber.artist.traits.JavaVisibilityTrait;\nimport com.uber.artist.traits.rx.JavaCheckableTrait;\nimport com.uber.artist.traits.rx.JavaScrollableTrait;\nimport com.uber.artist.traits.rx.JavaTextInputTrait;\nimport com.uber.artist.traits.rx.JavaViewTrait;\n\nimport java.util.Arrays;\nimport java.util.LinkedHashSet;\nimport java.util.Set;\n\n/**\n * Sample ViewStencil provider.\n */\n@AutoService(JavaViewStencilProvider.class)\npublic class JavaSampleViewStencilProvider implements JavaViewStencilProvider {\n\n  @Override\n  public Set<JavaViewStencil> stencils() {\n    return new LinkedHashSet<>(Arrays.asList(\n        new JavaViewStencil(\"androidx.appcompat.widget.AppCompatButton\", 3, \"buttonStyle\"),\n        new JavaViewStencil(\"androidx.appcompat.widget.AppCompatEditText\", 3,\n            \"android.R.attr.editTextStyle\", JavaTextInputTrait.class),\n        new JavaViewStencil(\"android.widget.LinearLayout\", 3, null),\n        new JavaViewStencil(\"androidx.appcompat.widget.AppCompatImageView\", 3, null),\n        new JavaViewStencil(\"androidx.core.widget.NestedScrollView\", 3, null,\n            JavaScrollableTrait.class),\n        new JavaViewStencil(\"android.widget.TextView\", 3, \"android.R.attr.textViewStyle\"),\n        new SwitchStencil()\n    ));\n  }\n\n  @Override\n  public Set<Class<? extends JavaTrait>> globalTraits() {\n    return new LinkedHashSet<>(Arrays.asList(\n        JavaSampleTrait.class,\n        JavaVisibilityTrait.class,\n        JavaForegroundTrait.class,\n        JavaViewTrait.class\n    ));\n  }\n\n  private static class SwitchStencil extends JavaViewStencil {\n\n    public SwitchStencil() {\n      super(\"androidx.appcompat.widget.SwitchCompat\", 3, \"switchStyle\", JavaCheckableTrait.class);\n    }\n\n    @Override\n    public String name() {\n      return \"MySwitch\";\n    }\n  }\n}\n"
  },
  {
    "path": "sample/providers/src/main/java/com/uber/artist/myproviders/trait/JavaSampleTrait.java",
    "content": "/*\n * Copyright (C) 2017. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.uber.artist.myproviders.trait;\n\nimport com.google.auto.service.AutoService;\nimport com.squareup.javapoet.ClassName;\nimport com.squareup.javapoet.MethodSpec;\nimport com.squareup.javapoet.TypeSpec;\nimport com.uber.artist.api.JavaTrait;\nimport com.uber.artist.myproviders.JavaSampleTypeNames;\n\nimport javax.lang.model.element.Modifier;\n\n/**\n * A somewhat arbitrary example of a custom Trait.\n */\n@AutoService(JavaTrait.class)\npublic class JavaSampleTrait implements JavaTrait {\n\n  @Override\n  public void generateFor(TypeSpec.Builder type, MethodSpec.Builder initMethod, ClassName rClass,\n      String sourceType) {\n\n    type.addMethod(MethodSpec.methodBuilder(\"sampleMethodFromCustomTrait\")\n        .addModifiers(Modifier.PUBLIC)\n        .returns(JavaSampleTypeNames.VIEW)\n        .addStatement(\"return this\")\n        .build()\n    );\n  }\n}\n"
  },
  {
    "path": "sample/providers-kotlin/build.gradle",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\napply plugin: \"org.jetbrains.kotlin.jvm\"\napply plugin: \"org.jetbrains.kotlin.kapt\"\n\nsourceCompatibility = JavaVersion.VERSION_1_7\ntargetCompatibility = JavaVersion.VERSION_1_7\n\ndependencies {\n    kapt deps.apt.autoService\n    compileOnly deps.apt.autoService\n\n    implementation deps.androidx.annotations\n    implementation project(\":artist-api\")\n    implementation project(\":artist-traits\")\n    implementation project(\":artist-traits-rx\")\n}\n"
  },
  {
    "path": "sample/providers-kotlin/src/main/kotlin/com/uber/artist/myproviders/KotlinSampleRxConfig.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.myproviders\n\nimport com.google.auto.service.AutoService\nimport com.squareup.kotlinpoet.CodeBlock\nimport com.squareup.kotlinpoet.TypeName\nimport com.uber.artist.traits.rx.config.KotlinArtistRxConfig\n\n/**\n * Sample Artist RxTrait Config.\n */\n@AutoService(KotlinArtistRxConfig::class)\nclass KotlinSampleRxConfig : KotlinArtistRxConfig() {\n\n  override fun processTap(codeBlockBuilder: CodeBlock.Builder) {\n    super.processTap(codeBlockBuilder)\n    codeBlockBuilder.add(\".doOnNext(%T.createTapProcessor())\", KotlinSampleTypeNames.MY_UTILS)\n  }\n\n  override fun processRxBindingSignalEvent(codeBlockBuilder: CodeBlock.Builder) {\n    super.processRxBindingSignalEvent(codeBlockBuilder)\n    codeBlockBuilder.add(\".map(%T.createRxBindingSignalMapper())\", KotlinSampleTypeNames.MY_UTILS)\n  }\n\n  override fun rxBindingSignalEventTypeName(): TypeName {\n    return KotlinSampleTypeNames.SIGNAL\n  }\n}\n"
  },
  {
    "path": "sample/providers-kotlin/src/main/kotlin/com/uber/artist/myproviders/KotlinSampleTypeNames.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.myproviders\n\nimport com.squareup.kotlinpoet.ClassName\n\n/**\n * Sample TypeNames.\n */\nobject KotlinSampleTypeNames {\n  val MY_UTILS = ClassName(\"com.uber.artist.mylibrary\", \"MyUtils\")\n  val SIGNAL = ClassName(\"com.uber.artist.mylibrary\", \"Signal\")\n  val VIEW = ClassName(\"android.view\", \"View\")\n}\n"
  },
  {
    "path": "sample/providers-kotlin/src/main/kotlin/com/uber/artist/myproviders/KotlinSampleViewStencilProvider.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\npackage com.uber.artist.myproviders\n\nimport com.google.auto.service.AutoService\nimport com.uber.artist.api.KotlinTrait\nimport com.uber.artist.api.KotlinViewStencil\nimport com.uber.artist.api.KotlinViewStencilProvider\nimport com.uber.artist.myproviders.trait.KotlinSampleTrait\nimport com.uber.artist.traits.KotlinForegroundTrait\nimport com.uber.artist.traits.KotlinSuppressNullabilityInitializerTrait\nimport com.uber.artist.traits.KotlinVisibilityTrait\nimport com.uber.artist.traits.rx.KotlinCheckableTrait\nimport com.uber.artist.traits.rx.KotlinScrollableTrait\nimport com.uber.artist.traits.rx.KotlinTextInputTrait\nimport com.uber.artist.traits.rx.KotlinViewTrait\n\n/**\n * Sample ViewStencil provider.\n */\n@AutoService(KotlinViewStencilProvider::class)\nclass KotlinSampleViewStencilProvider : KotlinViewStencilProvider {\n\n  override fun stencils(): Set<KotlinViewStencil> {\n    return linkedSetOf(\n        KotlinViewStencil(\"androidx.appcompat.widget.AppCompatButton\", 3, \"buttonStyle\"),\n        KotlinViewStencil(\"androidx.appcompat.widget.AppCompatEditText\", 3,\n            \"android.R.attr.editTextStyle\", KotlinTextInputTrait::class.java),\n        KotlinViewStencil(\"android.widget.LinearLayout\", 4, null),\n        KotlinViewStencil(\"androidx.appcompat.widget.AppCompatImageView\", 3, null),\n        KotlinViewStencil(\"androidx.core.widget.NestedScrollView\", 3, null, KotlinScrollableTrait::class.java),\n        KotlinViewStencil(\"android.widget.TextView\", 3, \"android.R.attr.textViewStyle\"),\n        SwitchStencil()\n    )\n  }\n\n  override fun globalTraits(): Set<Class<out KotlinTrait>> = setOf(\n      KotlinSampleTrait::class.java,\n      KotlinVisibilityTrait::class.java,\n      KotlinForegroundTrait::class.java,\n      KotlinSuppressNullabilityInitializerTrait::class.java,\n      KotlinViewTrait::class.java\n  )\n\n  private class SwitchStencil : KotlinViewStencil(\"androidx.appcompat.widget.SwitchCompat\", 3, \"switchStyle\", KotlinCheckableTrait::class.java) {\n\n    override fun name(): String {\n      return \"MySwitch\"\n    }\n  }\n}\n"
  },
  {
    "path": "sample/providers-kotlin/src/main/kotlin/com/uber/artist/myproviders/trait/KotlinSampleTrait.kt",
    "content": "/*\n * Copyright (C) 2018. Uber Technologies\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *    http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n */\n\npackage com.uber.artist.myproviders.trait\n\nimport com.google.auto.service.AutoService\nimport com.squareup.kotlinpoet.ClassName\nimport com.squareup.kotlinpoet.FunSpec\nimport com.squareup.kotlinpoet.KModifier\nimport com.squareup.kotlinpoet.TypeSpec\nimport com.uber.artist.api.KotlinTrait\nimport com.uber.artist.myproviders.KotlinSampleTypeNames\n\n/**\n * A somewhat arbitrary example of a custom Trait.\n */\n@AutoService(KotlinTrait::class)\nclass KotlinSampleTrait : KotlinTrait {\n\n  override fun generateFor(type: TypeSpec.Builder, initMethod: FunSpec.Builder, rClass: ClassName, sourceType: String) {\n    type.addFunction(FunSpec.builder(\"sampleMethodFromCustomTrait\")\n        .addModifiers(KModifier.PUBLIC)\n        .returns(KotlinSampleTypeNames.VIEW)\n        .addStatement(\"return this\")\n        .build())\n  }\n}\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':artist'\ninclude ':artist-api'\ninclude ':artist-core'\ninclude ':artist-traits'\ninclude ':artist-traits-rx'\ninclude ':sample:app'\ninclude ':sample:library'\ninclude ':sample:providers'\ninclude ':sample:providers-kotlin'\n"
  }
]