[
  {
    "path": ".editorconfig",
    "content": "[*.{kt,kts}]\ndisabled_rules=import-ordering"
  },
  {
    "path": ".github/stale.yml",
    "content": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 30\n# Number of days of inactivity before a stale issue is closed\ndaysUntilClose: 7\n# Issues with these labels will never be considered stale\nexemptLabels:\n  - bug\n  - enhancement\n  - help wanted\n# Label to use when marking an issue as stale\nstaleLabel: wontfix\n# Comment to post when marking an issue as stale. Set to `false` to disable\nmarkComment: >\n  This issue has been automatically marked as stale because it has not had\n  recent activity. It will be closed if no further activity occurs. Thank you\n  for your contributions.\n# Comment to post when closing a stale issue. Set to `false` to disable\ncloseComment: false\n"
  },
  {
    "path": ".github/workflows/android.yml",
    "content": "name: Build Magnet\n\non:\n  push:\n    branches: [ master ]\n  pull_request:\n    branches: [ master ]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    steps:\n    - uses: actions/checkout@v3\n    - name: set up JDK 11\n      uses: actions/setup-java@v3\n      with:\n        java-version: '11'\n        distribution: 'temurin'\n        cache: gradle\n\n    - name: Grant execute permission for gradlew\n      run: chmod +x gradlew\n    - name: Build with Gradle\n      run: ./gradlew build\n"
  },
  {
    "path": ".gitignore",
    "content": "out/\nbuild/\ncaptures/\nclasses/\nreports/\n\nlibrary/.idea/\n\n.idea/\n.gradle/\n.navigation/\n\n*.iml\n.DS_Store\n\nlocal.properties"
  },
  {
    "path": ".project",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<projectDescription>\n\t<name>magnet</name>\n\t<comment>Project magnet created by Buildship.</comment>\n\t<projects>\n\t</projects>\n\t<buildSpec>\n\t\t<buildCommand>\n\t\t\t<name>org.eclipse.buildship.core.gradleprojectbuilder</name>\n\t\t\t<arguments>\n\t\t\t</arguments>\n\t\t</buildCommand>\n\t</buildSpec>\n\t<natures>\n\t\t<nature>org.eclipse.buildship.core.gradleprojectnature</nature>\n\t</natures>\n\t<filteredResources>\n\t\t<filter>\n\t\t\t<id>1626289350744</id>\n\t\t\t<name></name>\n\t\t\t<type>30</type>\n\t\t\t<matcher>\n\t\t\t\t<id>org.eclipse.core.resources.regexFilterMatcher</id>\n\t\t\t\t<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>\n\t\t\t</matcher>\n\t\t</filter>\n\t</filteredResources>\n</projectDescription>\n"
  },
  {
    "path": ".settings/org.eclipse.buildship.core.prefs",
    "content": "arguments=\nauto.sync=false\nbuild.scans.enabled=false\nconnection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)\nconnection.project.dir=\neclipse.preferences.version=1\ngradle.user.home=\njava.home=/Library/Java/JavaVirtualMachines/jdk-11.jdk/Contents/Home\njvm.arguments=\noffline.mode=false\noverride.workspace.settings=true\nshow.console.view=true\nshow.executions.view=true\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n## 3.8 (release) - 2023.03.27\n\n- Same as 3.8 (snapshot) \n\n## 3.8 (snapshot) - 2023.01.20\n\n- Bump versions:\n  - Kotlin 1.8.0\n  - Kotlin Metadata JVM 0.6.0\n\n## 3.7 (release) - 2023.01.20\n\n- Same as 3.7 (snapshot)  \n\n## 3.7 (snapshot) - 2022.08.13\n\n- Bump versions:\n  - Kotlin 1.7.10\n  - Android Gradle Plugin (AGP) 7.2.0\n  - Stetho 1.6.0\n  - Kotlin Metadata JVM 0.5.0\n\n## 3.6 (release) - 2022.08.13\n\n- Migrate to Kotlin 1.6.21, Java 11 and AGP 7.0.4.\n- Add `Scope.isDisposed()` method.\n- Remove `magnetx-app-leakcannary`. The extension is not needed anymore because the library has a\n  built-in ability to autostart.\n- Fixed stetho extension\n\n## 3.6-rc3 - 2022.05.13\n\n- Fixed stetho extension\n\nFinal release version. Same as 3.6-rc3\n\n## 3.6-rc1 (Renierit) - 2022.04.30\n\n- Migrate to Kotlin 1.6.21, Java 11 and AGP 7.0.4.\n- Add `Scope.isDisposed()` method.\n- Remove `magnetx-app-leakcannary`. The extension is not needed anymore because the library has a\n  built-in ability to autostart.\n\n## 3.5 (Pyrrhotite) - 2021.07.14\n\n- Migrate to Kotlin 1.5.0\n"
  },
  {
    "path": "LICENSE",
    "content": "                                 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 2018 Sergej Shafarenka, www.halfbit.de\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": "[![Kotlin version badge](https://img.shields.io/badge/kotlin-1.8.0-blue.svg)](http://kotlinlang.org/)\n[![Maven Central](http://img.shields.io/maven-central/v/de.halfbit/magnet.svg)](http://search.maven.org/#search%7Cga%7C1%7Cg%3A%22de.halfbit%22%20a%3A%22magnet%22)\n![maintenance-status](https://img.shields.io/badge/maintenance-as--is-yellow.svg)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0)\n\n‼️ 27.01.2023: This project is not actively developed anymore ‼️\n\n# 🧲 Magnet\n\nMagnet is a concise, scope tree based Dependency Injection (DI) library designed for highly modular Android applications. It consists of two parts: an annotation processor (Kotlin) and a reflection free runtime library (Java + Kotlin).\n\n# Design\n\nMagnet defines and opetates on two core concepts: `Scopes` and `Instances`.\n\n<img height=\"400\" src=\"https://github.com/beworker/magnet/blob/master/documentation/images/readme-diagram.png\" />\n\n`Scope` is a container for instances. Scopes can be combined into a hierarchical tree by referencing parent scopes. The most top scope of the tree hierarchy, which has no parent scope, is called the root scope.\n\n`Instance` is a concrete occurrence of an injected type. Instances can be allocated in scopes (scoped instances) or outside of scopes (unscoped instances).\n\n# The Dependency Rule\n\nScopes depend on each other using the strong dependency rule - *scope dependency can only point towards its parent scope*. The dependency direction between two scopes enforces the direction of dependencies between instances allocated in those scopes. Instances allocated in a parent scope can know nothing about instances allocated in its child scopes. This simple design rule helps preventing memory leaks and allows safe disposal of child scopes and garbage collecting instances allocated there.\n\n# Getting Started\n\nIn the example below we will compose a very naive `MediaPlayer` which loads media using a `MediaLoader` and then plays the media.\n\n```kotlin\nfun main() {\n   val rootScope = MagnetScope.createRootScope()\n   val playerScope = rootScope.createSubscope {\n      bind(Uri.parse(\"https://my-media-file\"))\n   }\n   \n   // mark 1\n   val mediaPlayer = playerScope.getSingle<MediaPlayer>()\n   mediaPlayer.playWhenReady()\n   \n   // mark 2\n   Thread.sleep(5000)\n   playerScope.dispose()\n   \n   // mark 3\n}\n\n// MediaPlayer.kt\ninterface MediaPlayer {\n   fun playWhenReady()\n}\n\n@Instance(type = MediaPlayer::class, disposer = \"dispose\")\ninternal class DefaultMediaPlayer(\n   private val assetId: Uri,\n   private val mediaLoader: MediaLoader\n) : MediaPlayer {\n   override fun playWhenReady() { ... }\n   fun dispose() { ... }\n}\n\n// MediaLoader.kt\ninterface MediaLoader {\n   fun load(mediaUri: Uri): Single<Media>\n}\n\n@Instance(type = MediaLoader::class)\ninternal class DefaultMediaLoader() : MediaLoader {\n   override fun load(mediaUri: Uri): Single<Media> { ... }\n}\n```\n\nThe diagram below shows how Magnet manages the scope hierarchy when different marks of the main function are reached.\n\nAt `Mark 1`, two scopes are created and the `Uri` instance gets bound into the `playerScope`.\n\n<img width=\"450\" src=\"https://github.com/beworker/magnet/blob/master/documentation/images/readme-mark1.png\" />\n\nAt `Mark 2`, `mediaPlayer` and `mediaLoader` instances get allocated in respective scopes. `mediaPlayer` is allocated in the `playerScope` because one of its dependencies, the `Uri`,  is located in `playerScope`. Magnet cannot move `mediaPlayer` up to the `rootScope` because this would break the dependency rule described above. `mediaLoader` has no dependencies, that's why it is allocated in the `rootScope`. This instance allocation logic is specific to Magnet DI and is called auto-scoping. See developer documentation for more detail.\n\n<img width=\"450\" src=\"https://github.com/beworker/magnet/blob/master/documentation/images/readme-mark2.png\" />\n\nAt `Mark 3`, the `playerScope` gets disposed and all its instances are garbage collected.\n\n<img width=\"450\" src=\"https://github.com/beworker/magnet/blob/master/documentation/images/readme-mark3.png\" />\n\nFor more information refer to Magnet documentation.\n\n# Documentation\n\n1. [Developer Guide](https://www.halfbit.de/magnet/developer-guide/)\n2. [Dependency auto-scoping](https://github.com/beworker/magnet/wiki/Dependency-auto-scoping)\n3. [Scope Inspection](https://github.com/beworker/magnet/wiki/Scope-Inspection)\n4. [How to Inject Android ViewModels](https://github.com/beworker/magnet/issues/69#issuecomment-468033997)\n5. [Blog: Magnet - an alternative to Dagger](https://www.thomaskeller.biz/blog/2019/10/09/magnet-an-alternative-to-dagger/)\n6. [Co2Monitor sample app](https://github.com/beworker/co2monitor/tree/master/android-client)\n7. [Another sample app](https://github.com/beworker/g1)\n\n# Features\n\n- Minimalistic API\n- Auto-scoping of instances\n- Hierarchical, disposable scopes\n- Kotlin friendly annotation\n- Injection into Kotlin constructors with default arguments\n- Injection from binary libraries\n- Dependency inversion\n- No direct references to Magnet generated code\n- No reflection for injection, apt generated factory classes\n- Extensible - some `magnetx` extensions are available\n- Customizable - custom factories and instance selectors\n\n# Why Magnet?\n\nMagnet was crafted with simplicity and development speed in mind. It lets developers spend less time on DI configuration and do more other stuff, also more mistakes when used inattentively. Magnet motivates you writing highly modular apps because it makes DI so simple. It can even inject instances from the libraries added in build scripts without necessity to adapt source code. Magnet could be interesting for those, who needs an easy to configure and simple DI with more runtime control.\n\n# Why not Magnet?\n\nIf compile time consistency validation is your highest priority, I recommend using awesome [Dagger2](https://github.com/google/dagger) instead. You will spend slightly more time on DI configuration but Dagger2 lets you keep it highly consistent and error prone (in most cases) very early in the development cycle - at compile time.\n\nPeace ✌️ and have fun.\n\n# Gradle\n\nKotlin\n\n```gradle\nrepositories {\n   mavenCentral()\n}\ndependencies {\n   api 'de.halfbit:magnet-kotlin:<version>'\n   kapt 'de.halfbit:magnet-processor:<version>'\n}\n```\n\nJava\n\n```gradle\nrepositories {\n   mavenCentral()\n}\ndependencies {\n   api 'de.halfbit:magnet:<version>'\n   annotationProcessor 'de.halfbit:magnet-processor:<version>'\n}\n```\n\n# Compatibility\n\n| Kotlin Version | Magnet Version | \n|----------------|----------------|\n| 1.8.x          | 3.8            |\n| 1.7.x          | 3.7            |\n| 1.6.x          | 3.6            |\n| 1.5.x          | 3.5            |\n| 1.4.x          | 3.4            |\n| 1.3.x          | 3.4            |\n\n# Proguard & R8\n\n```\n-keep class magnet.internal.MagnetIndexer { *; }\n```\n\n# Build from Sources\n\n1. Set JAVA_HOME variable to JDK 11.\n2. Import project into Android Studio.\n3. Set Gradle → Gradle Settings... → Gradle JDK to JDK 11.\n4. To build the project run `./gradlew build`\n5. To release the project run `./gradlew publish`\n\n# Maven repository configurations\n\n| Repository | Configuration                                                              |\n|------------|----------------------------------------------------------------------------|\n| Central    | mavenCentral()                                                             |\n| Snapshot   | maven { url = \"https://oss.sonatype.org/content/repositories/snapshots/\" } |\n| Local      | mavenLocal()                                                               |\n\n# License\n\n```\nCopyright 2018-2023 Sergej Shafarenka, www.halfbit.de\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": "build.gradle",
    "content": "buildscript {\n    ext.kotlin_version = '1.8.0'\n\n    repositories {\n        mavenCentral()\n        maven { url 'https://maven.google.com' }\n    }\n\n    dependencies {\n        classpath \"com.android.tools.build:gradle:7.2.0\"\n        classpath \"com.vanniktech:gradle-maven-publish-plugin:0.19.0\"\n        classpath \"org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version\"\n    }\n}\n\nallprojects {\n    repositories {\n        mavenCentral()\n    }\n\n    configurations {\n        all {\n            resolutionStrategy {\n                force deps.kotlinjdk\n            }\n        }\n    }\n}\n\next {\n    javaVersion = JavaVersion.VERSION_11\n}\n\next.deps = [:]\n\n// open source\next.deps.kotlinjdk = \"org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version\"\next.deps.javapoet = 'com.squareup:javapoet:1.13.0'\next.deps.android = 'com.google.android:android:4.1.1.4'\next.deps.rxandroid = 'io.reactivex.rxjava2:rxandroid:2.1.1'\next.deps.rx3android = 'io.reactivex.rxjava3:rxandroid:3.0.0'\next.deps.stetho = 'com.facebook.stetho:stetho:1.6.0'\next.deps.kotlinMetadata = 'org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.6.0'\next.deps.annotations = 'org.jetbrains:annotations:16.0.1'\n\n// testing\next.deps.junit = 'junit:junit:4.12'\next.deps.jsr305 = 'com.google.code.findbugs:jsr305:3.0.2'\next.deps.mockito = 'org.mockito:mockito-core:4.5.1'\next.deps.mockitoKotlin = 'org.mockito.kotlin:mockito-kotlin:4.0.0'\next.deps.truth = 'com.google.truth:truth:1.1.3'\next.deps.compileTesting = 'com.google.testing.compile:compile-testing:0.21.0'\n"
  },
  {
    "path": "documentation/diagrams/design.graphml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<graphml xmlns=\"http://graphml.graphdrawing.org/xmlns\" xmlns:java=\"http://www.yworks.com/xml/yfiles-common/1.0/java\" xmlns:sys=\"http://www.yworks.com/xml/yfiles-common/markup/primitives/2.0\" xmlns:x=\"http://www.yworks.com/xml/yfiles-common/markup/2.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:y=\"http://www.yworks.com/xml/graphml\" xmlns:yed=\"http://www.yworks.com/xml/yed/3\" xsi:schemaLocation=\"http://graphml.graphdrawing.org/xmlns http://www.yworks.com/xml/schema/graphml/1.1/ygraphml.xsd\">\n  <!--Created by yEd 3.18.0.2-->\n  <key attr.name=\"Description\" attr.type=\"string\" for=\"graph\" id=\"d0\"/>\n  <key for=\"port\" id=\"d1\" yfiles.type=\"portgraphics\"/>\n  <key for=\"port\" id=\"d2\" yfiles.type=\"portgeometry\"/>\n  <key for=\"port\" id=\"d3\" yfiles.type=\"portuserdata\"/>\n  <key attr.name=\"url\" attr.type=\"string\" for=\"node\" id=\"d4\"/>\n  <key attr.name=\"description\" attr.type=\"string\" for=\"node\" id=\"d5\"/>\n  <key for=\"node\" id=\"d6\" yfiles.type=\"nodegraphics\"/>\n  <key for=\"graphml\" id=\"d7\" yfiles.type=\"resources\"/>\n  <key attr.name=\"url\" attr.type=\"string\" for=\"edge\" id=\"d8\"/>\n  <key attr.name=\"description\" attr.type=\"string\" for=\"edge\" id=\"d9\"/>\n  <key for=\"edge\" id=\"d10\" yfiles.type=\"edgegraphics\"/>\n  <graph edgedefault=\"directed\" id=\"G\">\n    <data key=\"d0\"/>\n    <node id=\"n0\">\n      <data key=\"d4\"/>\n      <data key=\"d6\">\n        <y:UMLClassNode>\n          <y:Geometry height=\"42.83889883347422\" width=\"121.96157027354172\" x=\"299.8019242940941\" y=\"328.709202259597\"/>\n          <y:Fill color=\"#FFCC00\" transparent=\"false\"/>\n          <y:BorderStyle hasColor=\"false\" type=\"line\" width=\"1.0\"/>\n          <y:NodeLabel alignment=\"center\" autoSizePolicy=\"content\" fontFamily=\"Dialog\" fontSize=\"13\" fontStyle=\"bold\" hasBackgroundColor=\"false\" hasLineColor=\"false\" height=\"19.310546875\" horizontalTextPosition=\"center\" iconTextGap=\"4\" modelName=\"custom\" textColor=\"#000000\" verticalTextPosition=\"bottom\" visible=\"true\" width=\"42.87939453125\" x=\"39.54108787114586\" y=\"3.0\">Scope<y:LabelModel>\n              <y:SmartNodeLabelModel distance=\"4.0\"/>\n            </y:LabelModel>\n            <y:ModelParameter>\n              <y:SmartNodeLabelModelParameter labelRatioX=\"0.0\" labelRatioY=\"0.0\" nodeRatioX=\"0.0\" nodeRatioY=\"0.0\" offsetX=\"0.0\" offsetY=\"0.0\" upX=\"0.0\" upY=\"-1.0\"/>\n            </y:ModelParameter>\n          </y:NodeLabel>\n          <y:UML clipContent=\"true\" constraint=\"\" hasDetailsColor=\"false\" omitDetails=\"false\" stereotype=\"\" use3DEffect=\"false\">\n            <y:AttributeLabel/>\n            <y:MethodLabel/>\n          </y:UML>\n        </y:UMLClassNode>\n      </data>\n    </node>\n    <node id=\"n1\">\n      <data key=\"d4\"/>\n      <data key=\"d6\">\n        <y:UMLClassNode>\n          <y:Geometry height=\"42.83889883347422\" width=\"121.96157027354172\" x=\"514.2481436779401\" y=\"328.709202259597\"/>\n          <y:Fill color=\"#FFCC00\" transparent=\"false\"/>\n          <y:BorderStyle hasColor=\"false\" type=\"line\" width=\"1.0\"/>\n          <y:NodeLabel alignment=\"center\" autoSizePolicy=\"content\" fontFamily=\"Dialog\" fontSize=\"13\" fontStyle=\"bold\" hasBackgroundColor=\"false\" hasLineColor=\"false\" height=\"19.310546875\" horizontalTextPosition=\"center\" iconTextGap=\"4\" modelName=\"custom\" textColor=\"#000000\" verticalTextPosition=\"bottom\" visible=\"true\" width=\"60.18310546875\" x=\"30.889232402395862\" y=\"3.0\">Instance<y:LabelModel>\n              <y:SmartNodeLabelModel distance=\"4.0\"/>\n            </y:LabelModel>\n            <y:ModelParameter>\n              <y:SmartNodeLabelModelParameter labelRatioX=\"0.0\" labelRatioY=\"-0.5\" nodeRatioX=\"4.440892098500626E-16\" nodeRatioY=\"-0.42997018873753573\" offsetX=\"0.0\" offsetY=\"0.0\" upX=\"0.0\" upY=\"-1.0\"/>\n            </y:ModelParameter>\n          </y:NodeLabel>\n          <y:UML clipContent=\"true\" constraint=\"\" hasDetailsColor=\"false\" omitDetails=\"false\" stereotype=\"\" use3DEffect=\"false\">\n            <y:AttributeLabel/>\n            <y:MethodLabel/>\n          </y:UML>\n        </y:UMLClassNode>\n      </data>\n    </node>\n    <edge id=\"e0\" source=\"n0\" target=\"n0\">\n      <data key=\"d8\"/>\n      <data key=\"d10\">\n        <y:PolyLineEdge>\n          <y:Path sx=\"0.0\" sy=\"0.0\" tx=\"0.0\" ty=\"0.0\">\n            <y:Point x=\"360.78270943086494\" y=\"287.44899181474153\"/>\n          </y:Path>\n          <y:LineStyle color=\"#000000\" type=\"line\" width=\"1.0\"/>\n          <y:Arrows source=\"none\" target=\"plain\"/>\n          <y:EdgeLabel alignment=\"center\" configuration=\"AutoFlippingLabel\" distance=\"2.0\" fontFamily=\"Dialog\" fontSize=\"12\" fontStyle=\"plain\" hasBackgroundColor=\"false\" hasLineColor=\"false\" height=\"18.1328125\" horizontalTextPosition=\"center\" iconTextGap=\"4\" modelName=\"custom\" preferredPlacement=\"anywhere\" ratio=\"0.5\" textColor=\"#000000\" verticalTextPosition=\"bottom\" visible=\"true\" width=\"60.7890625\" x=\"-60.70566875261699\" y=\"-64.50409416775955\">&lt;parent&gt;<y:LabelModel>\n              <y:SmartEdgeLabelModel autoRotationEnabled=\"false\" defaultAngle=\"0.0\" defaultDistance=\"10.0\"/>\n            </y:LabelModel>\n            <y:ModelParameter>\n              <y:SmartEdgeLabelModelParameter angle=\"6.283185307179586\" distance=\"0.5943657323100519\" distanceToCenter=\"true\" position=\"right\" ratio=\"-14.193472945391704\" segment=\"-1\"/>\n            </y:ModelParameter>\n            <y:PreferredPlacementDescriptor angle=\"0.0\" angleOffsetOnRightSide=\"0\" angleReference=\"absolute\" angleRotationOnRightSide=\"co\" distance=\"-1.0\" frozen=\"true\" placement=\"anywhere\" side=\"anywhere\" sideReference=\"relative_to_edge_flow\"/>\n          </y:EdgeLabel>\n          <y:EdgeLabel alignment=\"center\" configuration=\"AutoFlippingLabel\" distance=\"2.0\" fontFamily=\"Dialog\" fontSize=\"12\" fontStyle=\"plain\" hasBackgroundColor=\"false\" hasLineColor=\"false\" hasText=\"false\" height=\"4.0\" horizontalTextPosition=\"center\" iconTextGap=\"4\" modelName=\"custom\" preferredPlacement=\"anywhere\" ratio=\"0.5\" textColor=\"#000000\" verticalTextPosition=\"bottom\" visible=\"true\" width=\"4.0\" x=\"-1.7167717703069343\" y=\"-26.1141097499401\">\n            <y:LabelModel>\n              <y:SmartEdgeLabelModel autoRotationEnabled=\"false\" defaultAngle=\"0.0\" defaultDistance=\"10.0\"/>\n            </y:LabelModel>\n            <y:ModelParameter>\n              <y:SmartEdgeLabelModelParameter angle=\"0.0\" distance=\"30.0\" distanceToCenter=\"true\" position=\"right\" ratio=\"0.5\" segment=\"0\"/>\n            </y:ModelParameter>\n            <y:PreferredPlacementDescriptor angle=\"0.0\" angleOffsetOnRightSide=\"0\" angleReference=\"absolute\" angleRotationOnRightSide=\"co\" distance=\"-1.0\" frozen=\"true\" placement=\"anywhere\" side=\"anywhere\" sideReference=\"relative_to_edge_flow\"/>\n          </y:EdgeLabel>\n          <y:BendStyle smoothed=\"false\"/>\n        </y:PolyLineEdge>\n      </data>\n    </edge>\n    <edge id=\"e1\" source=\"n0\" target=\"n1\">\n      <data key=\"d8\"/>\n      <data key=\"d10\">\n        <y:PolyLineEdge>\n          <y:Path sx=\"0.0\" sy=\"0.0\" tx=\"0.0\" ty=\"0.0\"/>\n          <y:LineStyle color=\"#000000\" type=\"line\" width=\"1.0\"/>\n          <y:Arrows source=\"white_diamond\" target=\"plain\"/>\n          <y:BendStyle smoothed=\"false\"/>\n        </y:PolyLineEdge>\n      </data>\n    </edge>\n    <edge id=\"e2\" source=\"n1\" target=\"n1\">\n      <data key=\"d8\"/>\n      <data key=\"d10\">\n        <y:PolyLineEdge>\n          <y:Path sx=\"0.0\" sy=\"0.0\" tx=\"0.0\" ty=\"12.878338588469717\">\n            <y:Point x=\"565.7917197218228\" y=\"291.627427387127\"/>\n          </y:Path>\n          <y:LineStyle color=\"#000000\" type=\"line\" width=\"1.0\"/>\n          <y:Arrows source=\"none\" target=\"plain\"/>\n          <y:EdgeLabel alignment=\"center\" configuration=\"AutoFlippingLabel\" distance=\"2.0\" fontFamily=\"Dialog\" fontSize=\"12\" fontStyle=\"plain\" hasBackgroundColor=\"false\" hasLineColor=\"false\" height=\"18.1328125\" horizontalTextPosition=\"center\" iconTextGap=\"4\" modelName=\"custom\" preferredPlacement=\"anywhere\" ratio=\"0.5\" textColor=\"#000000\" verticalTextPosition=\"bottom\" visible=\"true\" width=\"103.10546875\" x=\"-77.45654384302611\" y=\"-61.57494978959795\">&lt;dependencies&gt;<y:LabelModel>\n              <y:SmartEdgeLabelModel autoRotationEnabled=\"false\" defaultAngle=\"0.0\" defaultDistance=\"10.0\"/>\n            </y:LabelModel>\n            <y:ModelParameter>\n              <y:SmartEdgeLabelModelParameter angle=\"6.283185307179586\" distance=\"9.279785258782196\" distanceToCenter=\"true\" position=\"left\" ratio=\"-14.325195439906148\" segment=\"-1\"/>\n            </y:ModelParameter>\n            <y:PreferredPlacementDescriptor angle=\"0.0\" angleOffsetOnRightSide=\"0\" angleReference=\"absolute\" angleRotationOnRightSide=\"co\" distance=\"-1.0\" frozen=\"true\" placement=\"anywhere\" side=\"anywhere\" sideReference=\"relative_to_edge_flow\"/>\n          </y:EdgeLabel>\n          <y:BendStyle smoothed=\"false\"/>\n        </y:PolyLineEdge>\n      </data>\n    </edge>\n  </graph>\n  <data key=\"d7\">\n    <y:Resources/>\n  </data>\n</graphml>\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Wed Dec 18 22:04:35 CET 2019\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.5.1-bin.zip\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStorePath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\n"
  },
  {
    "path": "gradle.properties",
    "content": "org.gradle.jvmargs=-Xmx1536m\nandroid.useAndroidX=true\n\nGROUP=de.halfbit\nVERSION_NAME=3.8\nVERSION_CODE=0\n\nPOM_DESCRIPTION=Dependency injection library for Android\nPOM_URL=https://github.com/sergejsha/magnet/\nPOM_INCEPTION_YEAR=2018\n\nPOM_SCM_URL=https://github.com/sergejsha/magnet/\nPOM_SCM_CONNECTION=scm:git:git://github.com/sergejsha/magnet.git\nPOM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/sergejsha/magnet.git\n\nPOM_LICENSE_NAME=The Apache Software License, Version 2.0\nPOM_LICENSE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt\nPOM_LICENSE_DIST=repo\n\nPOM_DEVELOPER_ID=sergejsha\nPOM_DEVELOPER_NAME=Sergej Shafarenka\nPOM_DEVELOPER_URL=https://github.com/sergejsha/\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": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windows variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "magnet/build.gradle",
    "content": "plugins {\n    id 'java-library'\n    id 'com.vanniktech.maven.publish'\n}\n\nsourceCompatibility = javaVersion\ntargetCompatibility = javaVersion\n\ndependencies {\n    compileOnly deps.annotations\n\n    testImplementation deps.junit\n    testImplementation deps.mockito\n    testImplementation deps.truth\n    testCompileOnly deps.annotations\n}\n"
  },
  {
    "path": "magnet/gradle.properties",
    "content": "POM_NAME=Magnet Runtime Library\nPOM_ARTIFACT_ID=magnet\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "magnet/src/main/java/magnet/Classifier.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\nimport static java.lang.annotation.RetentionPolicy.CLASS;\n\n/**\n * Magnet can bind multiple instances of the same type into a scope. Use classifier\n * with a unique value to differentiate between those instances.\n *\n * <pre>\n *      // bind instances\n *      scope.bind(Context.class, application, \"app-context\");\n *      scope.bind(Context.class, activity, \"activity-context\");\n *\n *      // get instances directly\n *      Context app = scope.getSingle(Context.class, \"app-context\");\n *      Context activity = scope.getSingle(Context.class, \"activity-context\");\n *\n *      // get instances via constructor injection\n *      &#64;Instance(type = MyImplementation.class)\n *      public MyImplementation(\n *          &#64;Classifier(\"app-context\") Context app,\n *          &#64;Classifier(\"activity-context\") Context activity,\n *      ) {\n *          ...\n *      }\n * </pre>\n */\n@Retention(CLASS)\n@Target({ElementType.PARAMETER, ElementType.METHOD})\npublic @interface Classifier {\n\n    String NONE = \"\";\n    String value();\n\n}"
  },
  {
    "path": "magnet/src/main/java/magnet/Factory.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet;\n\nimport org.jetbrains.annotations.NotNull;\n\n/** Custom factory to be used with {@link Instance#factory()}. */\npublic interface Factory<T> {\n\n    /** Implementation must return instance of give type without delegating the call to the given scope. */\n    @NotNull\n    T create(\n        @NotNull Scope scope,\n        @NotNull Class<T> type,\n        @NotNull String classifier,\n        @NotNull Scoping scoping,\n        @NotNull Instantiator<T> instantiator\n    );\n\n    /** Instantiator creates new instance of given type using {@code new} operator. */\n    interface Instantiator<T> {\n        @NotNull\n        T instantiate(Scope scope);\n    }\n\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/Instance.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet;\n\nimport static java.lang.annotation.RetentionPolicy.CLASS;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\n/**\n * Magnet instantiates classes marked with this annotation automatically. Annotated\n * classes must have a single, none private constructor. Constructor is allowed to have\n * parameters which are dependencies for this instance. Magnet checks constructor\n * parameters and tries to resolve corresponding dependencies by looking into accessible\n * scopes. If no suitable instances were found in scopes, Magnet searches for\n * {@code Instance}-annotated classes and tried to instantiate them. If constructor's\n * dependencies cannot be fulfilled, Magnet will fail at runtime with corresponding\n * error message.\n *\n * <p>\n * In the example below we declare two dependent types and instantiate them in scope.\n *\n * <pre>\n *     &#64;Instance(type=TypeA.class)\n *     class TypeA {\n *         TypeA() {}\n *     }\n *\n *     &#64;Instance(type=TypeB.class)\n *     class TypeB {\n *         final TypeA typeA;\n *         TypeB(@NonNull TypeA dependency) {\n *             typeA = dependency;\n *         }\n *     }\n *\n *     ...\n *\n *     // get instance of typeB\n *     TypeB typeB = scope.getSingle(TypeB.class);\n *\n *     // typeA has been provided by Magnet\n *     typeB.typeA != null\n *\n * </pre>\n *\n * <p>\n * <b>Nullability.</b> Magnet is capable of detecting whether dependency can or cannot be null.\n * If a constructor's parameter is annotated as nullable and Magnet cannot provide instance of\n * parameter's type, then <code>null</code> is provided instead.\n *\n * <p>\n * <b>Classification.</b> Same interface can be implemented by many classes. Classifier is used\n * to differentiate between those implementations. See {@link Classifier} for more detail.\n *\n * <p>\n * <b>Scoping.</b> Magnet can bind created instances into scope for reuse. Instance can\n * specify whether and how its instances should be bound into the scope. See {@link Scoping}\n * for more detail.\n */\n@Retention(CLASS)\n@Target({ElementType.TYPE, ElementType.METHOD})\npublic @interface Instance {\n\n    /**\n     * Type to use when annotated instance gets registered in scope. Annotated class must\n     * actually implement this type.\n     */\n    Class<?> type() default void.class;\n\n    /**\n     * Multiple types to use when annotated instance gets registered in scope. Annotated\n     * class must actually implement all these types. Properties {@link #type()} and\n     * {@code #types()} are exclusively mutual and cannot be used together.\n     */\n    Class<?>[] types() default void.class;\n\n    /**\n     * Classifier to use when annotated instance gets registered in scope.\n     */\n    String classifier() default Classifier.NONE;\n\n    /**\n     * Scoping rule to be applied when instance of annotated class gets created.\n     */\n    Scoping scoping() default Scoping.TOPMOST;\n\n    /**\n     * Limit tag to be used with {@link Scoping#TOPMOST} algorithm. If a limit tag is\n     * preset then the instance will be placed at or below the scope having same limit\n     * tag applied to it. If multiple scopes have the same limit tag, then the closest scope\n     * to the scope where the instance gets requested is used.\n     */\n    String limitedTo() default \"\";\n\n    /**\n     * <b>Experimental.</b> Magnet will only create instance of the annotated class if\n     * this selector expression is true after evaluation. Magnet currently support single\n     * type of expression:\n     * <p>\n     * <code>android.api (comparison operator) (api version)</code>\n     * <p>\n     * For instance, the expression <code>android.api &gt;= 28</code> will only create\n     * annotated instance if Build.VERSION.SDK_INT &gt;= 28. For the other versions\n     * <code>null</code> is returned. Make sure to use optional injection to handle\n     * this case.\n     */\n    String selector() default SelectorFilter.DEFAULT_SELECTOR;\n\n    /**\n     * Custom factory to be used for creating instance instead of the generated one.\n     */\n    Class<? extends Factory> factory() default Factory.class;\n\n    /**\n     * Name of optional disposer method to be called, when whole scope gets disposed.\n     */\n    String disposer() default \"\";\n\n    /**\n     * Magnet ignores this annotation when this flag is set to <code>true</code>.\n     */\n    boolean disabled() default false;\n\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/Magnet.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet;\n\nimport magnet.internal.InternalFactory;\nimport org.jetbrains.annotations.NotNull;\n\npublic final class Magnet {\n\n    private Magnet() { }\n\n    public static @NotNull Scope createRootScope() {\n        return InternalFactory.createRootScope();\n    }\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/Registry.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\nimport static java.lang.annotation.RetentionPolicy.CLASS;\n\n/**\n * This marker annotation instructs Magnet to generate a registry indexing all\n * instances available in classpath. Index applies to sources as well as libraries.\n * Apply this annotation to any interface or class in your main application module.\n */\n@Retention(CLASS)\n@Target({ElementType.TYPE})\npublic @interface Registry {}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/Scope.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.List;\n\n/**\n * Scope is a container for objects which are stored there at runtime.\n *\n * <p>\n * <b>Binding.</b> Binding is the way of putting objects into the scope.\n *\n * <pre>\n * Scope root = Magnet.createScope()\n *                 .bind(app, Application.class)\n *                 .bind(String.class, \"#FF0000\", \"red-color\");\n * </pre>\n *\n * <p>\n * <b>Chaining.</b> Scopes can be chained using\n * parent-child relation, or rather a child-parent relation because\n * a child scope (aka subscope) holds a reference to its parent and not\n * the other way around.\n *\n * <pre>\n * Scope subscope = root.createSubscope()\n *                   .bind(activity, Context.class)\n *                   .bind(String.class, \"#F30303\", \"red-color\")\n *                   .bind(String.class, \"#00FF00\", \"green-color\");\n * </pre>\n *\n * <b>Provisioning.</b> Scope has multiple get-methods for providing\n * objects it stores. Magnet will look through the whole scope's chain up\n * to the root parent scope to provide an object. First found match gets\n * returned.\n *\n * <pre>\n * // object overwriting\n * String red = root.getSingle(String.class, \"red-color\"); // \"#FF0000\" (from root)\n * String red = subscope.getSingle(String.class, \"red-color\"); // \"#F30303\" (from subscope)\n *\n * // scope chaining\n * Application app = subscope.getSingle(Application.class); // app (from root)\n * Context context = subscope.getSingle(Context.class); // activity (from subscope)\n * String green = subscope.getSingle(String.class, \"green-color\"); // \"#00FF00\" (from subscope)\n *\n * // optional provisioning\n * String red = root.getOptional(String.class, \"red-color\"); \"#FF0000\" (from root)\n * String yellow = subscope.getSingle(String.class, \"yellow-color\"); // throws IllegalStateException\n * String yellow = subscope.getOptional(String.class, \"yellow-color\"); // null, optional was not found\n * </pre>\n *\n * <p>\n * <b>Automatic binding (injection).</b>\n * Magnet can instantiate {@link Instance}-annotated classes and bind their instances\n * into respective scopes automatically. If instantiated classes have dependencies, Magnet\n * will resolve those dependencies too. In this respect Magnet works as dependency injection\n * library.\n *\n * <p>In the example below Magnet will create instance of {@code toaster} by taking required\n * dependencies from the scopes.\n *\n * <pre>\n * &#64;Instance(type = Toaster.class)\n * class Toaster {\n *     Toaster(\n *         Application app,\n *         &#64;Classifier(\"red-color\") String red,\n *         &#64;Classifier(\"green-color\") String green\n *     ) { ... }\n *\n * Toaster toaster = subscope.getSingle(Toaster.class);\n * toaster != null\n * </pre>\n */\npublic interface Scope {\n\n    /** Returns an object from the scope or {@code null}, if object was not found. */\n    @Nullable <T> T getOptional(@NotNull Class<T> type);\n\n    /** Returns an object from the scope or {@code null}, if object was not found. */\n    @Nullable <T> T getOptional(@NotNull Class<T> type, @NotNull String classifier);\n\n    /** Returns an object from the scope or throws exception, if object was not found. */\n    @NotNull <T> T getSingle(@NotNull Class<T> type);\n\n    /** Returns an object from the scope or throws exception, if object was not found. */\n    @NotNull <T> T getSingle(@NotNull Class<T> type, @NotNull String classifier);\n\n    /** Returns a list of objects or empty list, if no objects were found. */\n    @NotNull <T> List<T> getMany(@NotNull Class<T> type);\n\n    /** Returns a list of objects or empty list, if no objects were found. */\n    @NotNull <T> List<T> getMany(@NotNull Class<T> type, @NotNull String classifier);\n\n    /** Binds given instance into this scope. */\n    @NotNull <T> Scope bind(@NotNull Class<T> type, @NotNull T instance);\n\n    /** Binds given instance into this scope. */\n    @NotNull <T> Scope bind(@NotNull Class<T> type, @NotNull T instance, @NotNull String classifier);\n\n    /** Sets given limits to this scope. */\n    @NotNull Scope limit(String... limits);\n\n    /** Creates a new child scope of this scope. */\n    @NotNull Scope createSubscope();\n\n    /** Disposes this and all children scopes. Notifies instances with {@link magnet.Instance#disposer()}. */\n    void dispose();\n\n    /** Returns `true` is the scope is disposed, or `false` otherwise. */\n    boolean isDisposed();\n\n    /** Visits all instances and child scopes of given depth (use {@code Integer.MAX_VALUE} for visiting all scopes). */\n    void accept(Visitor visitor, int depth);\n\n}"
  },
  {
    "path": "magnet/src/main/java/magnet/Scoping.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet;\n\n/**\n * Declares the way Magnet binds instances of &#64;Instance</code>-annotated\n * classes into scopes. See each separate setting for more detail.\n */\npublic enum Scoping {\n\n    /**\n     * Magnet will not bind created instance into any scope. This is equivalent\n     * to having a factory creating new instances each time when instance is\n     * requested.\n     *\n     * <p>\n     * In the example below, both instances {@code typeA} and {@code typeB} are\n     * <b>not</b> bound into the {@code scope}. Each new {@code scope.getSingle(TypeB.class)}\n     * call will return new instances of {@code typeA} and {@code typeB}.\n     *\n     * <pre>\n     *\n     * &#64;Instance(type = TypeA.class, scoping = Scoping.UNSCOPED)\n     * class TypeA {\n     *     TypeA() {}\n     * }\n     *\n     * &#64;Instance(type = TypeB.class, scoping = Scoping.UNSCOPED)\n     * class TypeB {\n     *     final TypeA typeA;\n     *     TypeB(@NonNull TypeA dependency) {\n     *         typeA = dependency;\n     *     }\n     * }\n     *\n     * ...\n     *\n     * Scope scope = Magnet.createScope();\n     *\n     * TypeB typeB = scope.getSingle(TypeB.class);\n     * TypeA typeA = typeB.typeA;\n     * TypeA typeA2 = scope.getSingle(TypeA.class);\n     * typeA !== typeA2 // different instances\n     *\n     * </pre>\n     */\n    UNSCOPED,\n\n    /**\n     * Magnet will bind created instance into the most top scope in the chain of scopes,\n     * where all dependencies for the created instance are still fulfilled.\n     *\n     * <p>\n     * Scopes in Magnet can build a chain of parent-child relations (see {@link Scope} for\n     * more detail). This option allows binding instances of annotated class into a one\n     * of parent scopes. Magnet goes up the scope chain and checks, whether all dependencies\n     * for the instance can still be satisfied in that scope. The most top reached scope\n     * with satisfied dependencies is the scope, into which the instance gets bound.\n     *\n     * <p>\n     * In the example below both instances {@code typeA} and {@code typeB} are bound into\n     * {@code root}.\n     *\n     * <pre>\n     *\n     * &#64;Instance(type = TypeA.class, scoping = Scoping.TOPMOST)\n     * class TypeA {\n     *     TypeA() {}\n     * }\n     *\n     * &#64;Instance(type = TypeB.class)\n     * class TypeB {\n     *     final TypeA typeA;\n     *     TypeB(@NonNull TypeA dependency) {\n     *         typeA = dependency;\n     *     }\n     * }\n     *\n     * ...\n     *\n     * Scope root = Magnet.createScope();\n     * Scope scope = root.createSubscope();\n     *\n     * TypeB typeB = scope.getSingle(TypeB.class);\n     * TypeA typeA = typeB.typeA;\n     * TypeA typeA2 = scope.getSingle(TypeA.class);\n     * typeA === typeA2 // same instance\n     *\n     * </pre>\n     *\n     * Explanation:\n     *\n     * <ul>\n     * <li>{@code TypeA} has no dependencies and thus it gets bound to {@code root};\n     * <li>{@code TypeB} depends on {@code TypeA} and because the instance of {@code TypeA}\n     * is available in {@code root}, and instance of {@code TypeB} can also be created\n     * in {@code root}.\n     * </ul>\n     *\n     * <p>\n     * In the example below we bind instance of {@code typeA} into {@code scope} and\n     * {@code typeB} instance gets bound into the {@code scope} too.\n     *\n     * <pre>\n     *\n     * &#64;Instance(type = TypeA.class, scoping = Scoping.TOPMOST)\n     * class TypeA {\n     *     TypeA() {}\n     * }\n     *\n     * &#64;Instance(type = TypeB.class, scoping = Scoping.TOPMOST)\n     * class TypeB {\n     *     final TypeA typeA;\n     *     TypeB(@NonNull TypeA dependency) {\n     *         typeA = dependency;\n     *     }\n     * }\n     *\n     * ...\n     *\n     * Scope root = Magnet.createScope();\n     * Scope scope = root.createSubscope().bind(TypeA.class, new TypeA());\n     *\n     * TypeB typeB = scope.getSingle(TypeB.class);\n     * TypeA typeA = typeB.typeA;\n     * TypeA typeA2 = scope.getSingle(TypeA.class);\n     * typeA === typeA2 // same instance\n     *\n     * </pre>\n     *\n     * Explanation:\n     *\n     * <ul>\n     * <li>{@code typeB} cannot be bound in a scope above its dependencies;\n     * <li>{@code typeA} is available in {@code scope}, thus the {@code scope} is the\n     * top most scope for dependent {@code typeB} too.\n     * </ul>\n     */\n    TOPMOST,\n\n    /**\n     * Magnet will bind created instance into the same scope, in which this instance\n     * has been created.\n     *\n     * <p>\n     * In the example below, both instances {@code typeA} and {@code typeB} are bound\n     * into {@code scope}. Each new {@code scope.getSingle(TypeB.class)} call on the\n     * same instance of {@code scope} will return same instances of {@code typeA} and\n     * {@code typeB}.\n     *\n     * <pre>\n     *\n     * &#64;Instance(type = TypeA.class, scoping = Scoping.DIRECT)\n     * class TypeA {\n     *     TypeA() {}\n     * }\n     *\n     * &#64;Instance(type = TypeB.class, scoping = Scoping.DIRECT)\n     * class TypeB {\n     *     final TypeA typeA;\n     *     TypeB(@NonNull TypeA dependency) {\n     *         typeA = dependency;\n     *     }\n     * }\n     *\n     * ...\n     *\n     * Scope root = Magnet.createScope();\n     * Scope scope = root.createSubscope();\n     *\n     * TypeB typeB = scope.getSingle(TypeB.class);\n     * TypeA typeA = typeB.typeA;\n     * TypeA typeA2 = scope.getSingle(TypeA.class);\n     * typeA === typeA2 // same instance\n     *\n     * </pre>\n     */\n    DIRECT\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/SelectorFilter.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet;\n\nimport org.jetbrains.annotations.NotNull;\n\n/** Selector handler for processing {@link Instance#selector()} value at runtime. */\npublic abstract class SelectorFilter {\n\n    public static final String DEFAULT_SELECTOR = \"\";\n    public abstract boolean filter(@NotNull String[] selector);\n\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/Visitor.java",
    "content": "package magnet;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\n/**\n * Implementation of this interface should be used with {@link magnet.Scope#accept(Visitor, int)}\n * for iterating though instances and subscopes of a scope. Scope visiting begins with iterating\n * through all instances and then through all subscopes.\n */\npublic interface Visitor {\n\n    /** Provision type. */\n    enum Provision {BOUND, INJECTED}\n\n    /** Visited instance. */\n    interface Instance {\n        @NotNull Scoping getScoping();\n        @NotNull String getClassifier();\n        @NotNull String getLimit();\n        @NotNull Class<?> getType();\n        @NotNull Object getValue();\n        @NotNull Provision getProvision();\n    }\n\n    /** Visited scope. */\n    interface Scope {\n        @Nullable String[] getLimits();\n    }\n\n    /**\n     * Called when new scope is entered.\n     *\n     * @param scope  entered scope.\n     * @param parent parent scope of the entered scope.\n     * @return <code>true</code> to visit instances of this scope, <code>false</code> to skip instances.\n     */\n    boolean onEnterScope(@NotNull Scope scope, @Nullable Scope parent);\n\n    /**\n     * Called when visiting new instance between {@link #onEnterScope(Scope, Scope)}\n     * and {@link #onExitScope(Scope)} calls.\n     *\n     * @param instance visited instance.\n     * @return <code>true</code> to visit the next instance in the scope or <code>false</code>\n     * to skip all other instances in this scope.\n     */\n    boolean onInstance(@NotNull Instance instance);\n\n    /**\n     * Called when previously entered scope is exited.\n     *\n     * @param scope exited scope.\n     */\n    void onExitScope(@NotNull Scope scope);\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/internal/FactoryFilter.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\n/* Subject to change. For internal use only. */\ninterface FactoryFilter {\n    boolean filter(InstanceFactory factory);\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/internal/Generated.java",
    "content": "package magnet.internal;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\nimport static java.lang.annotation.RetentionPolicy.CLASS;\n\n/** Subject to change. For internal use only. */\n@Retention(CLASS)\n@Target({ElementType.TYPE})\npublic @interface Generated {}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/internal/ImmutableArrayList.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport java.util.AbstractList;\n\n/* Subject to change. For internal use only. */\nclass ImmutableArrayList<E> extends AbstractList<E> {\n\n    private final E[] elements;\n\n    ImmutableArrayList(E[] elements) {\n        this.elements = elements;\n    }\n\n    @Override public E get(int i) {\n        if (i < 0 || i >= elements.length) {\n            throw new IndexOutOfBoundsException(\n                    String.format(\n                            \"Cannot find element with index %s, array length: %s\", i, elements.length));\n        }\n        return elements[i];\n    }\n\n    @Override public int size() {\n        return elements.length;\n    }\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/internal/Index.java",
    "content": "package magnet.internal;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.Target;\n\nimport static java.lang.annotation.RetentionPolicy.CLASS;\n\n/** Subject to change. For internal use only. */\n@Retention(CLASS)\n@Target({ElementType.TYPE})\npublic @interface Index {\n\n    Class factoryType();\n    Class factoryClass();\n    String instanceType();\n    String classifier();\n\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/internal/InstanceBucket.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\n\nimport magnet.Scoping;\nimport magnet.Visitor;\n\n/* Subject to change. For internal use only. */\n@SuppressWarnings(\"unchecked\")\nfinal class InstanceBucket<T> {\n\n    @NotNull private final OnInstanceListener listener;\n    @NotNull private InstanceBucket.Instance instance;\n    @NotNull private MagnetScope scope;\n\n    InstanceBucket(\n        @NotNull MagnetScope scope,\n        @Nullable InstanceFactory<T> factory,\n        @NotNull Class<T> objectType,\n        @NotNull T object,\n        @NotNull String classifier,\n        @NotNull OnInstanceListener listener\n    ) {\n        this.scope = scope;\n        this.listener = listener;\n        this.instance = createSingleInstance(factory, objectType, object, classifier);\n    }\n\n    @NotNull MagnetScope getScope() { return scope; }\n\n    @NotNull T getSingleInstance() {\n        if (instance instanceof InjectedInstance) {\n            return ((InjectedInstance<T>) instance).object;\n        } else if (instance instanceof BoundInstance) {\n            return ((BoundInstance<T>) instance).object;\n        }\n\n        MultiObjectInstance multiObjectInstance = (MultiObjectInstance) instance;\n        throw new IllegalStateException(\n            String.format(\n                \"Single instance requested, while many instances are stored: %s\",\n                multiObjectInstance.instances\n            )\n        );\n    }\n\n    @Nullable T getOptional(@Nullable Class<InstanceFactory<T>> factoryType) {\n        if (instance instanceof InjectedInstance) {\n            InjectedInstance<T> single = (InjectedInstance<T>) instance;\n            if (single.factory.getClass() == factoryType) {\n                return single.object;\n            }\n            return null;\n        } else if (instance instanceof BoundInstance) {\n            BoundInstance<T> single = (BoundInstance<T>) instance;\n            if (factoryType == null) {\n                return single.object;\n            }\n            return null;\n        }\n        return (T) ((MultiObjectInstance) instance).getOptional(factoryType);\n    }\n\n    @NotNull List<T> getMany() {\n        if (instance instanceof InjectedInstance) {\n            return Collections.singletonList(((InjectedInstance<T>) instance).object);\n        } else if (instance instanceof BoundInstance) {\n            return Collections.singletonList(((BoundInstance<T>) instance).object);\n        }\n        return ((MultiObjectInstance<T>) instance).getMany();\n    }\n\n    void registerObject(\n        @Nullable InstanceFactory<T> factory,\n        @NotNull Class<T> objectType,\n        @NotNull T object,\n        @NotNull String classifier\n    ) {\n        if (this.instance instanceof InstanceBucket.MultiObjectInstance) {\n            MultiObjectInstance<T> many = (MultiObjectInstance<T>) this.instance;\n            many.putSingle(createSingleInstance(factory, objectType, object, classifier));\n\n        } else {\n            MultiObjectInstance<T> many = new MultiObjectInstance<>((SingleObjectInstance<T>) this.instance);\n            many.putSingle(createSingleInstance(factory, objectType, object, classifier));\n            this.instance = many;\n        }\n    }\n\n    boolean hasInstanceWithFactory(@Nullable InstanceFactory<T> factory) {\n        return instance.hasObjectWithFactory(factory);\n    }\n\n    private @NotNull InstanceBucket.SingleObjectInstance<T> createSingleInstance(\n        @Nullable InstanceFactory<T> factory,\n        @NotNull Class<T> objectType,\n        @NotNull T object,\n        @NotNull String classifier\n    ) {\n        SingleObjectInstance single;\n        if (factory == null) {\n            single = new BoundInstance<>(objectType, object, classifier);\n        } else {\n            single = new InjectedInstance<>(factory, objectType, object, classifier);\n        }\n        listener.onInstanceCreated(single);\n        return single;\n    }\n\n    public boolean accept(Visitor visitor) {\n        if (instance instanceof SingleObjectInstance) {\n            return ((SingleObjectInstance) instance).accept(visitor);\n        } else {\n            return ((MultiObjectInstance) instance).accept(visitor);\n        }\n    }\n\n    interface Instance<T> {\n        boolean hasObjectWithFactory(@Nullable InstanceFactory<T> factory);\n    }\n\n    static abstract class SingleObjectInstance<T> implements Instance<T> {\n        final @NotNull Class<T> objectType;\n        final @NotNull T object;\n        final @NotNull String classifier;\n\n        SingleObjectInstance(\n            @NotNull Class<T> objectType,\n            @NotNull T object,\n            @NotNull String classifier\n        ) {\n            this.objectType = objectType;\n            this.object = object;\n            this.classifier = classifier;\n        }\n\n        public boolean accept(Visitor visitor) {\n            if (this instanceof InjectedInstance) {\n                return visitor.onInstance((InjectedInstance) this);\n            } else {\n                return visitor.onInstance((BoundInstance) this);\n            }\n        }\n    }\n\n    static class BoundInstance<T> extends SingleObjectInstance<T> implements Visitor.Instance {\n        BoundInstance(@NotNull Class<T> objectType, @NotNull T object, @NotNull String classifier) {\n            super(objectType, object, classifier);\n        }\n\n        @Override public boolean hasObjectWithFactory(@Nullable InstanceFactory<T> factory) {\n            return true;\n        }\n        @Override public @NotNull Scoping getScoping() { return Scoping.DIRECT; }\n        @Override public @NotNull String getClassifier() { return classifier; }\n        @Override public @NotNull String getLimit() { return \"\"; }\n        @Override public @NotNull Class<?> getType() { return objectType; }\n        @Override public @NotNull Object getValue() { return object; }\n        @Override public @NotNull Visitor.Provision getProvision() {\n            return Visitor.Provision.BOUND;\n        }\n    }\n\n    static class InjectedInstance<T> extends SingleObjectInstance<T> implements Visitor.Instance {\n        @NotNull final InstanceFactory<T> factory;\n\n        InjectedInstance(\n            @NotNull InstanceFactory<T> factory,\n            @NotNull Class<T> objectType,\n            @NotNull T object,\n            @NotNull String classifier\n        ) {\n            super(objectType, object, classifier);\n            this.factory = factory;\n        }\n\n        @Override public boolean hasObjectWithFactory(@Nullable InstanceFactory<T> factory) {\n            return factory == this.factory;\n        }\n        @Override public @NotNull Scoping getScoping() { return factory.getScoping(); }\n        @Override public @NotNull String getClassifier() { return classifier; }\n        @Override public @NotNull String getLimit() { return factory.getLimit(); }\n        @Override public @NotNull Class<?> getType() { return objectType; }\n        @Override public @NotNull Object getValue() { return object; }\n        @Override public @NotNull Visitor.Provision getProvision() {\n            return Visitor.Provision.INJECTED;\n        }\n    }\n\n    private static class MultiObjectInstance<T> implements Instance<T> {\n        private final @NotNull HashMap<Class<InstanceFactory<T>>, SingleObjectInstance<T>> instances;\n\n        MultiObjectInstance(@NotNull InstanceBucket.SingleObjectInstance<T> single) {\n            instances = new HashMap<>(8);\n            putSingle(single);\n        }\n\n        @NotNull List<T> getMany() {\n            List<T> result = new ArrayList<>(this.instances.size());\n            for (SingleObjectInstance<T> single : this.instances.values()) {\n                result.add(single.object);\n            }\n            return result;\n        }\n\n        @Nullable T getOptional(@Nullable Class<InstanceFactory<T>> factoryType) {\n            SingleObjectInstance<T> single = instances.get(factoryType);\n            if (single == null) return null;\n            return single.object;\n        }\n\n        void putSingle(@NotNull InstanceBucket.SingleObjectInstance<T> single) {\n            @Nullable final Class<InstanceFactory<T>> factoryType;\n            if (single instanceof InjectedInstance) {\n                factoryType = (Class<InstanceFactory<T>>) ((InjectedInstance) single).factory.getClass();\n            } else if (single instanceof BoundInstance) {\n                factoryType = null;\n            } else {\n                throw new IllegalStateException(\"Unsupported SingleObjectInstance type.\");\n            }\n            instances.put(factoryType, single);\n        }\n\n        @Override public boolean hasObjectWithFactory(@Nullable InstanceFactory<T> factory) {\n            return instances.containsKey(factory == null ? null : factory.getClass());\n        }\n\n        public boolean accept(Visitor visitor) {\n            Collection<SingleObjectInstance<T>> singleObjectInstances = instances.values();\n            boolean takeNext = true;\n            for (SingleObjectInstance<T> instance : singleObjectInstances) {\n                takeNext = instance.accept(visitor);\n                if (!takeNext) break;\n            }\n            return takeNext;\n        }\n    }\n\n    interface OnInstanceListener {\n        <T> void onInstanceCreated(SingleObjectInstance<T> instance);\n    }\n}"
  },
  {
    "path": "magnet/src/main/java/magnet/internal/InstanceFactory.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Scope;\nimport magnet.Scoping;\n\n/* Subject to change. For internal use only. */\npublic abstract class InstanceFactory<T> {\n\n    public abstract T create(Scope scope);\n    public Scoping getScoping() { return Scoping.TOPMOST; }\n    public String getLimit() { return \"\"; }\n    public Class[] getSiblingTypes() { return null; }\n    public String[] getSelector() { return null; }\n\n    public boolean isDisposable() { return false; }\n    public void dispose(T instance) {\n        throw new IllegalStateException(\n            String.format(\"Instance %s is not disposable\", instance)\n        );\n    }\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/internal/InstanceManager.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.List;\n\n/* Subject to change. For internal use only. */\ninterface InstanceManager {\n\n    <T> @Nullable InstanceFactory<T> getInstanceFactory(\n        Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType);\n\n    <T> @Nullable InstanceFactory<T> getFilteredInstanceFactory(\n        Class<T> type, String classifier, FactoryFilter factoryFilter);\n\n    <T> @NotNull List<InstanceFactory<T>> getManyInstanceFactories(\n        Class<T> type, String classifier, FactoryFilter factoryFilter);\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/internal/InternalFactory.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Scope;\nimport org.jetbrains.annotations.NotNull;\n\n/* Subject to change. For internal use only. */\npublic final class InternalFactory {\n\n    private static final InstanceManager INSTANCE_MANAGER = new MagnetInstanceManager();\n\n    private InternalFactory() {}\n\n    static @NotNull Scope createRootScope(@NotNull InstanceManager instanceManager) {\n        return new MagnetScope(null, instanceManager);\n    }\n\n    public static @NotNull Scope createRootScope() {\n        return new MagnetScope(null, INSTANCE_MANAGER);\n    }\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/internal/MagnetInstanceManager.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Registry;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.Map;\n\n/* Subject to change. For internal use only. */\n@SuppressWarnings(\"unchecked\") final class MagnetInstanceManager implements InstanceManager {\n\n    private InstanceFactory[] factories;\n    private Map<Class, Object> index;\n\n    MagnetInstanceManager() {\n        registerInstanceFactories();\n    }\n\n    private void registerInstanceFactories() {\n        try {\n            Class<?> magnetClass = Class.forName(\"magnet.internal.MagnetIndexer\");\n            Method registerFactories = magnetClass.getMethod(\"register\", MagnetInstanceManager.class);\n            registerFactories.invoke(magnetClass, this);\n        } catch (Exception e) {\n            System.err.println(\n                String.format(\n                    \"MagnetIndexer cannot be found. Add a @%s-annotated class to the application module.\",\n                    Registry.class\n                )\n            );\n        }\n    }\n\n    // called by generated index class\n    void register(InstanceFactory[] factories, Map<Class, Object> index) {\n        this.factories = factories;\n        this.index = index;\n    }\n\n    @Override\n    public <T> @Nullable InstanceFactory<T> getInstanceFactory(\n        Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType\n    ) {\n        Range range = getOptionalRange(instanceType, classifier);\n        if (range == null) return null;\n        if (range.getCount() == 1) return factories[range.getFrom()];\n\n        for (int index = range.getFrom(), afterLast = range.getFrom() + range.getCount(); index < afterLast; index++) {\n            InstanceFactory<T> candidate = factories[index];\n            if (candidate.getClass() == factoryType) {\n                return candidate;\n            }\n        }\n        return null;\n    }\n\n    @Override\n    public <T> @Nullable InstanceFactory<T> getFilteredInstanceFactory(\n        Class<T> type, String classifier, FactoryFilter factoryFilter\n    ) {\n        Range range = getOptionalRange(type, classifier);\n        if (range == null) {\n            return null;\n        }\n\n        if (range.getCount() == 1) {\n            InstanceFactory factory = factories[range.getFrom()];\n            if (factoryFilter.filter(factory)) {\n                return factory;\n            }\n            return null;\n        }\n\n        InstanceFactory<T> factory = null;\n        for (int index = range.getFrom(), afterLast = range.getFrom() + range.getCount(); index < afterLast; index++) {\n            InstanceFactory<T> candidate = factories[index];\n            if (factoryFilter.filter(candidate)) {\n                if (factory != null) {\n                    throw new IllegalStateException(\n                        String.format(\n                            \"Multiple implementations of type %s (classifier: %s) can be injected,\" +\n                                \" while single implementation is expected. Overloaded factories: %s, %s\",\n                            type, classifier, factory, candidate\n                        )\n                    );\n                }\n                factory = candidate;\n            }\n        }\n\n        return factory;\n    }\n\n    @Override\n    public <T> @NotNull List<InstanceFactory<T>> getManyInstanceFactories(\n        Class<T> type, String classifier, FactoryFilter factoryFilter\n    ) {\n        Object indexed = index.get(type);\n\n        if (indexed instanceof Range) {\n            Range range = (Range) indexed;\n            if (range.getClassifier().equals(classifier)) {\n                return factoriesFromRange(range, factoryFilter);\n            }\n            return Collections.emptyList();\n        }\n\n        if (indexed instanceof Map) {\n            Map<String, Range> ranges = (Map<String, Range>) indexed;\n            Range range = ranges.get(classifier);\n            if (range != null) {\n                return factoriesFromRange(range, factoryFilter);\n            }\n            return Collections.emptyList();\n        }\n\n        return Collections.emptyList();\n    }\n\n    private Range getOptionalRange(Class<?> type, String classifier) {\n        Object indexed = index.get(type);\n\n        if (indexed == null) {\n            return null;\n        }\n\n        if (indexed instanceof Range) {\n            Range range = (Range) indexed;\n            if (classifier.equals(range.getClassifier())) {\n                return (Range) indexed;\n            }\n            return null;\n        }\n\n        if (indexed instanceof Map) {\n            Map<String, Range> ranges = (Map<String, Range>) indexed;\n            return ranges.get(classifier);\n        }\n\n        throw new IllegalStateException(\n            String.format(\"Unsupported index type: %s\", indexed.getClass())\n        );\n    }\n\n    private <T> List<InstanceFactory<T>> factoriesFromRange(Range range, FactoryFilter factoryFilter) {\n        List<InstanceFactory<T>> filteredFactories = null;\n        for (int index = range.getFrom(), afterLast = range.getFrom() + range.getCount(); index < afterLast; index++) {\n            InstanceFactory<T> factory = factories[index];\n            if (factory.getSelector() != null) {\n                if (filteredFactories == null) {\n                    filteredFactories = new ArrayList<>(range.getCount());\n                }\n                if (factoryFilter.filter(factory)) {\n                    filteredFactories.add(factory);\n                }\n            }\n        }\n\n        if (filteredFactories != null) {\n            return filteredFactories;\n        }\n\n        InstanceFactory<T>[] factories = new InstanceFactory[range.getCount()];\n        System.arraycopy(this.factories, range.getFrom(), factories, 0, range.getCount());\n        return new ImmutableArrayList<>(factories);\n    }\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/internal/MagnetScope.java",
    "content": "/*\n * Copyright (C) 2018-2019 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.lang.ref.WeakReference;\nimport java.util.ArrayDeque;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport magnet.Classifier;\nimport magnet.Scope;\nimport magnet.Scoping;\nimport magnet.SelectorFilter;\nimport magnet.Visitor;\n\n/* Subject to change. For internal use only. */\nfinal class MagnetScope implements Scope, Visitor.Scope, FactoryFilter, InstanceBucket.OnInstanceListener {\n\n    private static final byte CARDINALITY_OPTIONAL = 0;\n    private static final byte CARDINALITY_SINGLE = 1;\n    private static final byte CARDINALITY_MANY = 2;\n\n    private final @Nullable MagnetScope parent;\n    private final @NotNull InstanceManager instanceManager;\n    private final int depth;\n\n    private @Nullable WeakScopeReference childrenScopes;\n    private @Nullable List<InstanceBucket.InjectedInstance> disposables;\n    private @Nullable String[] limits;\n    private boolean disposed = false;\n\n    final @NotNull Map<String, InstanceBucket> instanceBuckets;\n\n    @SuppressWarnings(\"AnonymousHasLambdaAlternative\")\n    private final @NotNull ThreadLocal<InstantiationContext> instantiationContext =\n        new ThreadLocal<InstantiationContext>() {\n            @Override protected InstantiationContext initialValue() {\n                return new InstantiationContext();\n            }\n        };\n\n    MagnetScope(@Nullable MagnetScope parent, @NotNull InstanceManager instanceManager) {\n        this.depth = parent == null ? 0 : parent.depth + 1;\n        this.parent = parent;\n        this.instanceManager = instanceManager;\n        this.instanceBuckets = new HashMap<>(32, 0.75f);\n    }\n\n    @Override\n    public <T> @Nullable T getOptional(@NotNull Class<T> type) {\n        checkNotDisposed();\n        InstanceFactory<T> factory = instanceManager\n            .getFilteredInstanceFactory(type, Classifier.NONE, this);\n        return findOrInjectOptional(type, Classifier.NONE, factory, CARDINALITY_OPTIONAL);\n    }\n\n    @Override\n    public <T> @Nullable T getOptional(@NotNull Class<T> type, @NotNull String classifier) {\n        checkNotDisposed();\n        InstanceFactory<T> factory = instanceManager\n            .getFilteredInstanceFactory(type, classifier, this);\n        return findOrInjectOptional(type, classifier, factory, CARDINALITY_OPTIONAL);\n    }\n\n    @Override\n    public <T> @NotNull T getSingle(@NotNull Class<T> type) {\n        return getSingle(type, Classifier.NONE);\n    }\n\n    @Override\n    public <T> @NotNull T getSingle(@NotNull Class<T> type, @NotNull String classifier) {\n        checkNotDisposed();\n        @Nullable InstanceFactory<T> factory = instanceManager\n            .getFilteredInstanceFactory(type, classifier, this);\n        T object = findOrInjectOptional(type, classifier, factory, CARDINALITY_SINGLE);\n        if (object == null) {\n            throw new IllegalStateException(\n                String.format(\n                    \"Instance of type '%s' (classifier: '%s') was not found in scopes.\",\n                    type.getName(), classifier\n                )\n            );\n        }\n        return object;\n    }\n\n    @Override\n    public <T> @NotNull List<T> getMany(@NotNull Class<T> type) {\n        checkNotDisposed();\n        return getManyObjects(type, Classifier.NONE);\n    }\n\n    @Override\n    public <T> @NotNull List<T> getMany(@NotNull Class<T> type, @NotNull String classifier) {\n        checkNotDisposed();\n        return getManyObjects(type, classifier);\n    }\n\n    @Override\n    public <T> @NotNull Scope bind(@NotNull Class<T> type, @NotNull T object) {\n        bind(type, object, Classifier.NONE);\n        return this;\n    }\n\n    @Override\n    public <T> @NotNull Scope bind(\n        @NotNull Class<T> type, @NotNull T object, @NotNull String classifier\n    ) {\n        checkNotDisposed();\n        final String key = key(type, classifier);\n        Object existing = instanceBuckets.put(\n            key,\n            new InstanceBucket<>(\n                /* scope = */ this,\n                /* factory = */ null,\n                /* instanceType = */ type,\n                /* instance = */ object,\n                /* classifier = */ classifier,\n                /* listener = */  this\n            )\n        );\n        if (existing != null) {\n            throw new IllegalStateException(\n                String.format(\n                    \"Instance of type %s already registered. Existing instance %s, new instance %s\",\n                    key, existing, object\n                )\n            );\n        }\n        return this;\n    }\n\n    @Override\n    public @NotNull Scope createSubscope() {\n        checkNotDisposed();\n\n        MagnetScope child = new MagnetScope(this, instanceManager);\n        childrenScopes = new WeakScopeReference(child, childrenScopes);\n\n        return child;\n    }\n\n    @Override\n    public @NotNull Scope limit(String... limits) {\n        if (this.limits != null) {\n            throw new IllegalStateException(\n                String.format(\n                    \"Cannot set limits to '%s' because they must only be applied once.\" +\n                        \" Current limits '%s'\", Arrays.toString(limits), Arrays.toString(this.limits))\n            );\n        }\n        for (String limit : limits) {\n            if (limit.length() == 0 || limit.equals(\"*\")) {\n                throw new IllegalStateException(\"Limit must not be empty or be a '*'\");\n            }\n        }\n        Arrays.sort(limits);\n        this.limits = limits;\n        return this;\n    }\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public void dispose() {\n        if (disposed) return;\n\n        WeakScopeReference weakScope = childrenScopes;\n        if (weakScope != null) {\n            do {\n                MagnetScope scope = weakScope.get();\n                if (scope != null) {\n                    scope.dispose();\n                }\n                weakScope = weakScope.next;\n            } while (weakScope != null);\n        }\n\n        if (disposables != null) {\n            for (int i = disposables.size(); i-- > 0; ) {\n                InstanceBucket.InjectedInstance single = disposables.get(i);\n                single.factory.dispose(single.object);\n            }\n        }\n\n        disposed = true;\n\n        if (parent != null) {\n            parent.onChildScopeDisposed(this);\n        }\n    }\n\n    @Override\n    public boolean isDisposed() {\n        return disposed;\n    }\n\n    private void onChildScopeDisposed(MagnetScope childScope) {\n        if (childrenScopes == null) return;\n        WeakScopeReference prevWeakScope = null;\n        WeakScopeReference weakScope = childrenScopes;\n        do {\n            MagnetScope scope = weakScope.get();\n            if (scope == childScope) {\n                if (prevWeakScope == null) {\n                    childrenScopes = weakScope.next;\n                } else {\n                    prevWeakScope.next = weakScope.next;\n                }\n                break;\n            }\n            prevWeakScope = weakScope;\n            weakScope = weakScope.next;\n        } while (weakScope != null);\n    }\n\n    @Override\n    public <T> void onInstanceCreated(InstanceBucket.SingleObjectInstance<T> instance) {\n        if (instance instanceof InstanceBucket.InjectedInstance) {\n            InstanceBucket.InjectedInstance injected = (InstanceBucket.InjectedInstance) instance;\n            if (injected.factory.isDisposable()) {\n                if (disposables == null) {\n                    disposables = new ArrayList<>(8);\n                }\n                disposables.add(injected);\n            }\n        }\n    }\n\n    private void checkNotDisposed() {\n        if (disposed) throw new IllegalStateException(\"Scope is already disposed.\");\n    }\n\n    @Override\n    public boolean filter(@NotNull InstanceFactory factory) {\n        String[] selector = factory.getSelector();\n        if (selector == null) {\n            return true;\n        }\n        SelectorFilter selectorFilter = getOptional(SelectorFilter.class, selector[0]);\n        if (selectorFilter == null) {\n            throw new IllegalStateException(\n                String.format(\n                    \"Factory %s requires selector '%s', which implementation is not available in the scope.\" +\n                        \" Make sure to add corresponding %s implementation to the classpath.\",\n                    factory, Arrays.toString(selector), SelectorFilter.class)\n            );\n        }\n        return selectorFilter.filter(selector);\n    }\n\n    private <T> @NotNull List<T> getManyObjects(Class<T> type, String classifier) {\n        List<InstanceFactory<T>> factories = instanceManager.getManyInstanceFactories(type, classifier, this);\n        if (factories.size() == 0) return Collections.emptyList();\n\n        List<T> objects = new ArrayList<>(factories.size());\n        for (InstanceFactory<T> factory : factories) {\n            T object = findOrInjectOptional(type, classifier, factory, CARDINALITY_MANY);\n            if (object != null) objects.add(object);\n        }\n        return objects;\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private <T> @Nullable T findOrInjectOptional(\n        @NotNull Class<T> objectType,\n        @NotNull String classifier,\n        @Nullable InstanceFactory<T> factory,\n        byte cardinality\n    ) {\n        @NotNull InstantiationContext instantiationContext = this.instantiationContext.get();\n        @NotNull String key = key(objectType, classifier);\n\n        InstanceBucket<T> deepInstanceBucket = findDeepInstanceBucket(key, factory);\n        if (factory == null) {\n            if (deepInstanceBucket == null) {\n                if (cardinality == CARDINALITY_SINGLE) {\n                    throw new IllegalStateException(\n                        String.format(\n                            \"Instance of type '%s' (classifier: '%s') was not found in scopes.\",\n                            objectType.getName(), classifier));\n                }\n                return null;\n            }\n            instantiationContext.onDependencyFound(deepInstanceBucket.getScope().depth, key);\n            return deepInstanceBucket.getSingleInstance();\n        }\n\n        boolean keepInScope = factory.getScoping() != Scoping.UNSCOPED;\n        if (keepInScope) {\n            if (deepInstanceBucket != null) {\n                boolean isSingleOrOptional = cardinality != CARDINALITY_MANY;\n\n                if (isSingleOrOptional) {\n                    instantiationContext.onDependencyFound(deepInstanceBucket.getScope().depth, key);\n                    return deepInstanceBucket.getSingleInstance();\n                }\n\n                T object = deepInstanceBucket.getOptional((Class<InstanceFactory<T>>) factory.getClass());\n                if (object != null) {\n                    instantiationContext.onDependencyFound(deepInstanceBucket.getScope().depth, key);\n                    return object;\n                }\n            }\n        }\n\n        instantiationContext.onBeginInstantiation(key);\n\n        T object = factory.create(this);\n\n        Instantiation instantiation = instantiationContext.onEndInstantiation();\n        int objectDepth = instantiation.dependencyDepth;\n        Scoping objectScoping = factory.getScoping();\n\n        @NotNull String objectLimit = factory.getLimit();\n        if (objectLimit.length() > 0) {\n            if (objectScoping == Scoping.TOPMOST) {\n                objectDepth = findTopMostLimitedObjectDepth(objectLimit, objectDepth);\n\n            } else if (objectScoping == Scoping.DIRECT) {\n                objectDepth = findDirectLimitedObjectDepth(\n                    objectLimit, objectDepth, object, objectType, classifier, instantiation\n                );\n            }\n\n            if (objectDepth < 0) throwLimitNotFound(object, objectType, classifier, objectLimit);\n\n        } else {\n            if (objectScoping == Scoping.DIRECT) objectDepth = this.depth;\n        }\n\n        instantiationContext.onDependencyFound(objectDepth, key);\n\n        if (keepInScope) {\n\n            boolean canRegisterAtDeepInstanceBucket = deepInstanceBucket != null\n                && deepInstanceBucket.getScope().depth == objectDepth;\n\n            if (canRegisterAtDeepInstanceBucket) {\n                deepInstanceBucket.registerObject(factory, objectType, object, classifier);\n\n            } else {\n                registerInstanceInScope(\n                    key,\n                    objectDepth,\n                    factory,\n                    objectType,\n                    object,\n                    classifier\n                );\n            }\n\n            Class[] siblingFactoryTypes = factory.getSiblingTypes();\n            if (siblingFactoryTypes != null) {\n                for (int i = 0, size = siblingFactoryTypes.length; i < size; i += 2) {\n                    Class siblingObjectType = siblingFactoryTypes[i];\n                    String siblingKey = key(siblingObjectType, classifier);\n                    InstanceFactory siblingFactory = instanceManager.getInstanceFactory(\n                        siblingObjectType, classifier, siblingFactoryTypes[i + 1]\n                    );\n                    registerInstanceInScope(\n                        siblingKey,\n                        objectDepth,\n                        siblingFactory,\n                        siblingObjectType,\n                        object,\n                        classifier\n                    );\n                }\n            }\n        }\n\n        return object;\n    }\n\n    private int findTopMostLimitedObjectDepth(String objectLimit, int objectDepth) {\n        @Nullable MagnetScope scope = this;\n        while (scope != null) {\n            if (objectDepth > scope.depth) {\n                return objectDepth;\n            } else if (scope.hasLimit(objectLimit)) {\n                return scope.depth;\n            }\n            scope = scope.parent;\n        }\n        return -1;\n    }\n\n    private <T> int findDirectLimitedObjectDepth(\n        String objectLimit, int objectDepth, T object, Class<T> objectType, String classifier,\n        Instantiation instantiation\n    ) {\n        @Nullable MagnetScope scope = this;\n        int limitingScopeDepth = -1;\n        while (scope != null) {\n            if (scope.hasLimit(objectLimit)) {\n                limitingScopeDepth = scope.depth;\n                break;\n            }\n            scope = scope.parent;\n        }\n\n        if (limitingScopeDepth > -1 && limitingScopeDepth < objectDepth) {\n            StringBuilder logDetails = new StringBuilder();\n            buildInstanceDetails(logDetails, object, objectType, classifier, objectLimit);\n\n            throw new IllegalStateException(\n                String.format(\n                    \"Cannot register instance in limiting scope [depth: %s] because its\" +\n                        \" dependency '%s' is located in non-reachable child scope [depth: %s].\\n%s\",\n                    limitingScopeDepth,\n                    instantiation.dependencyKey,\n                    instantiation.dependencyDepth,\n                    logDetails\n                )\n            );\n        }\n\n        return limitingScopeDepth;\n    }\n\n    private boolean hasLimit(@NotNull String limit) {\n        if (limit.length() == 0 || limits == null) {\n            return false;\n        }\n        return Arrays.binarySearch(limits, limit) > -1;\n    }\n\n    private <T> void registerInstanceInScope(\n        @NotNull String key,\n        int depth,\n        @Nullable InstanceFactory<T> factory,\n        @NotNull Class<T> objectType,\n        @NotNull T object,\n        @NotNull String classifier\n    ) {\n        if (this.depth == depth) {\n            @SuppressWarnings(\"unchecked\") final InstanceBucket<T> bucket = instanceBuckets.get(key);\n            if (bucket == null) {\n                instanceBuckets.put(\n                    key,\n                    new InstanceBucket<>(this, factory, objectType, object, classifier, this)\n                );\n            } else {\n                bucket.registerObject(factory, objectType, object, classifier);\n            }\n            return;\n        }\n        if (parent == null) {\n            throw new IllegalStateException(\n                String.format(\n                    \"Cannot register instance %s, factory: %s, depth: %s\",\n                    object, factory, depth\n                )\n            );\n        }\n        parent.registerInstanceInScope(key, depth, factory, objectType, object, classifier);\n    }\n\n    @Nullable\n    @SuppressWarnings(\"unchecked\")\n    private <T> InstanceBucket<T> findDeepInstanceBucket(\n        @NotNull String key, @Nullable InstanceFactory<T> factory\n    ) {\n        @Nullable InstanceBucket<T> bucket = (InstanceBucket<T>) instanceBuckets.get(key);\n        if (bucket != null && bucket.hasInstanceWithFactory(factory)) return bucket;\n        if (parent == null) return null;\n        return parent.findDeepInstanceBucket(key, factory);\n    }\n\n    @NotNull\n    static String key(Class<?> type, String classifier) {\n        if (classifier == null || classifier.length() == 0) {\n            return type.getName();\n        }\n        return classifier + \"@\" + type.getName();\n    }\n\n    @Override\n    public void accept(Visitor visitor, int depth) {\n        acceptAtLevel(0, visitor, depth);\n    }\n\n    private void acceptAtLevel(int level, Visitor visitor, int depth) {\n        if (disposed) return;\n\n        boolean visitScopes = true;\n        if (visitor.onEnterScope(this, parent)) {\n            Collection<InstanceBucket> buckets = this.instanceBuckets.values();\n            for (InstanceBucket bucket : buckets) {\n                if (!bucket.accept(visitor)) {\n                    visitScopes = false;\n                    break;\n                }\n            }\n        }\n\n        if (visitScopes && level < depth) {\n            WeakScopeReference scopeRef = this.childrenScopes;\n            while (scopeRef != null) {\n                MagnetScope scope = scopeRef.get();\n                if (scope != null) scope.acceptAtLevel(level + 1, visitor, depth);\n                scopeRef = scopeRef.next;\n            }\n        }\n\n        visitor.onExitScope(this);\n    }\n\n    @Override public @Nullable String[] getLimits() {\n        return limits;\n    }\n\n    private static <T> void buildInstanceDetails(\n        StringBuilder builder, T object, Class<T> objectType, String classifier, String objectLimit\n    ) {\n        builder\n            .append(\"Instance:\")\n            .append(\"\\n\\tobject : \").append(object)\n            .append(\"\\n\\ttype : \").append(objectType.getName());\n\n        if (classifier.length() > 0) {\n            builder\n                .append(\"\\n\\tclassifier: '\").append(classifier).append(\"'\");\n        }\n\n        builder\n            .append(\"\\n\\tlimit : '\").append(objectLimit).append(\"'\");\n    }\n\n    private <T> void throwLimitNotFound(T object, Class<T> objectType, String classifier, String objectLimit) {\n        StringBuilder logDetail = new StringBuilder();\n        buildInstanceDetails(logDetail, object, objectType, classifier, objectLimit);\n        logDetail.append(\" <- required limit\");\n\n        logDetail.append(\"\\n\\nSearched scopes:\\n\\t-> \");\n        @Nullable MagnetScope scope = this;\n        while (scope != null) {\n            String scopeName = scope.toString();\n            if (scope.limits != null) {\n                logDetail.append('(');\n                for (String limit : scope.limits) {\n                    logDetail.append(\"'\").append(limit).append(\"', \");\n                }\n                logDetail.setLength(logDetail.length() - 2);\n                logDetail.append(\") \").append(scope.toString());\n            } else logDetail.append(scopeName);\n            logDetail.append(\"\\n\\t-> \");\n            scope = scope.parent;\n        }\n        logDetail.setLength(logDetail.length() - 5);\n        logDetail.append(\" <root scope>\");\n\n        throw new IllegalStateException(\n            String.format(\n                \"Cannot register instance because no scope with limit '%s' has been found.\\n%s\",\n                objectLimit, logDetail\n            )\n        );\n    }\n\n    private final static class InstantiationContext {\n        private final ArrayDeque<Instantiation> instantiations = new ArrayDeque<>();\n        private Instantiation currentInstantiation;\n\n        void onBeginInstantiation(String key) {\n            if (currentInstantiation != null) {\n                instantiations.addFirst(currentInstantiation);\n            }\n            currentInstantiation = new Instantiation(key);\n            if (instantiations.contains(currentInstantiation)) {\n                throw createCircularDependencyException();\n            }\n        }\n\n        @NotNull Instantiation onEndInstantiation() {\n            Instantiation instantiation = currentInstantiation;\n            currentInstantiation = instantiations.isEmpty() ? null : instantiations.pollFirst();\n            return instantiation;\n        }\n\n        void onDependencyFound(int dependencyDepth, @NotNull String dependencyKey) {\n            if (currentInstantiation == null) return;\n            if (dependencyDepth > currentInstantiation.dependencyDepth) {\n                currentInstantiation.dependencyDepth = dependencyDepth;\n                currentInstantiation.dependencyKey = dependencyKey;\n            }\n        }\n\n        private IllegalStateException createCircularDependencyException() {\n\n            Instantiation[] objects = instantiations.toArray(new Instantiation[0]);\n            StringBuilder builder = new StringBuilder()\n                .append(\"Dependency injection failed because of unresolved circular dependency: \");\n            for (int i = objects.length; i-- > 0; ) {\n                builder.append(objects[i].key).append(\" -> \");\n            }\n            builder.append(currentInstantiation.key);\n\n            return new IllegalStateException(builder.toString());\n        }\n    }\n\n    private final static class Instantiation {\n        final String key;\n        int dependencyDepth;\n        @Nullable String dependencyKey;\n\n        Instantiation(String key) {\n            this.key = key;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n            if (this == o) return true;\n            if (o == null || getClass() != o.getClass()) return false;\n            Instantiation that = (Instantiation) o;\n            return key.equals(that.key);\n        }\n\n        @Override\n        public int hashCode() {\n            return key.hashCode();\n        }\n    }\n\n    private final static class WeakScopeReference extends WeakReference<MagnetScope> {\n        private @Nullable WeakScopeReference next;\n        WeakScopeReference(MagnetScope referent, @Nullable WeakScopeReference next) {\n            super(referent);\n            this.next = next;\n        }\n    }\n}\n"
  },
  {
    "path": "magnet/src/main/java/magnet/internal/Range.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\n/* Subject to change. For internal use only. */\nfinal class Range {\n\n    private final int from;\n    private final int count;\n    private final String classifier;\n\n    public Range(int from, int count, String classifier) {\n        this.from = from;\n        this.count = count;\n        this.classifier = classifier;\n    }\n\n    public int getFrom() {\n        return from;\n    }\n\n    public int getCount() {\n        return count;\n    }\n\n    public String getClassifier() {\n        return classifier;\n    }\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/FactoryFilter_MagnetInstanceManagerTest.java",
    "content": "package magnet.internal;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.MockitoJUnitRunner;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport magnet.Classifier;\n\n@RunWith(MockitoJUnitRunner.Silent.class)\npublic class FactoryFilter_MagnetInstanceManagerTest {\n\n    private MagnetInstanceManager instanceManager;\n\n    @Mock FactoryFilter factoryFilter;\n    @Mock InstanceFactory<Interface1> instanceFactory1;\n    @Mock InstanceFactory<Interface2> instanceFactory21;\n    @Mock InstanceFactory<Interface2> instanceFactory22;\n\n    @Before\n    public void before() {\n        instanceManager = new MagnetInstanceManager();\n        InstanceFactory[] factories = new InstanceFactory[]{\n            instanceFactory1,\n            instanceFactory21,\n            instanceFactory22,\n        };\n        Map<Class, Object> index = new HashMap<>();\n        index.put(Interface1.class, new Range(0, 1, Classifier.NONE));\n        index.put(Interface2.class, new Range(1, 2, Classifier.NONE));\n        instanceManager.register(factories, index);\n    }\n\n    @Test\n    public void getOptionalFactoryReturnsFactoryWhenFilterReturnsTrue() {\n        when(factoryFilter.filter(instanceFactory1)).thenReturn(true);\n        InstanceFactory<Interface1> factory = instanceManager\n            .getFilteredInstanceFactory(Interface1.class, Classifier.NONE, factoryFilter);\n        assertThat(factory).isSameInstanceAs(instanceFactory1);\n    }\n\n    @Test\n    public void getOptionalFactoryReturnsNullWhenFilterReturnsTrue() {\n        when(factoryFilter.filter(instanceFactory1)).thenReturn(false);\n        InstanceFactory<Interface1> factory = instanceManager\n            .getFilteredInstanceFactory(Interface1.class, Classifier.NONE, factoryFilter);\n        assertThat(factory).isNull();\n    }\n\n    @Test\n    public void getOptionalFactoryReturnsFactoryWhenOneOfFiltersReturnsTrue() {\n        when(factoryFilter.filter(instanceFactory21)).thenReturn(false);\n        when(factoryFilter.filter(instanceFactory22)).thenReturn(true);\n        InstanceFactory<Interface2> factory = instanceManager\n            .getFilteredInstanceFactory(Interface2.class, Classifier.NONE, factoryFilter);\n        assertThat(factory).isSameInstanceAs(instanceFactory22);\n    }\n\n    @Test\n    public void getOptionalFactoryReturnsNullWhenAllFiltersReturnFalse() {\n        when(factoryFilter.filter(instanceFactory21)).thenReturn(false);\n        when(factoryFilter.filter(instanceFactory22)).thenReturn(false);\n        InstanceFactory<Interface2> factory = instanceManager\n            .getFilteredInstanceFactory(Interface2.class, Classifier.NONE, factoryFilter);\n        assertThat(factory).isNull();\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void getOptionalFactoryFailsWhenMultipleFactoriesDetected() {\n        when(factoryFilter.filter(instanceFactory21)).thenReturn(true);\n        when(factoryFilter.filter(instanceFactory22)).thenReturn(true);\n        instanceManager.getFilteredInstanceFactory(Interface2.class, Classifier.NONE, factoryFilter);\n    }\n\n    @Test\n    public void getManyFactoriesReturnsEmptyListWhenAllFiltersReturnFalse() {\n        when(instanceFactory21.getSelector()).thenReturn(new String[]{\"test\"});\n        when(instanceFactory22.getSelector()).thenReturn(new String[]{\"test\"});\n        when(factoryFilter.filter(instanceFactory21)).thenReturn(false);\n        when(factoryFilter.filter(instanceFactory22)).thenReturn(false);\n\n        List<InstanceFactory<Interface2>> factories = instanceManager\n            .getManyInstanceFactories(Interface2.class, Classifier.NONE, factoryFilter);\n\n        assertThat(factories).isNotNull();\n        assertThat(factories).isEmpty();\n    }\n\n    @Test\n    public void getManyFactoriesReturnsSingleFactoryWhenSingleFilterReturnsTrue() {\n        when(instanceFactory21.getSelector()).thenReturn(new String[]{\"test\"});\n        when(instanceFactory22.getSelector()).thenReturn(new String[]{\"test\"});\n        when(factoryFilter.filter(instanceFactory21)).thenReturn(false);\n        when(factoryFilter.filter(instanceFactory22)).thenReturn(true);\n\n        List<InstanceFactory<Interface2>> factories = instanceManager\n            .getManyInstanceFactories(Interface2.class, Classifier.NONE, factoryFilter);\n\n        assertThat(factories).isNotNull();\n        assertThat(factories).hasSize(1);\n        assertThat(factories.get(0)).isSameInstanceAs(instanceFactory22);\n    }\n\n    @Test\n    public void getManyFactoriesReturnsAllFactoriesWhenAllFiltersReturnTrue() {\n        when(instanceFactory21.getSelector()).thenReturn(new String[]{\"test\"});\n        when(instanceFactory22.getSelector()).thenReturn(new String[]{\"test\"});\n        when(factoryFilter.filter(instanceFactory21)).thenReturn(true);\n        when(factoryFilter.filter(instanceFactory22)).thenReturn(true);\n\n        List<InstanceFactory<Interface2>> factories = instanceManager\n            .getManyInstanceFactories(Interface2.class, Classifier.NONE, factoryFilter);\n\n        assertThat(factories).isNotNull();\n        assertThat(factories).hasSize(2);\n        assertThat(factories.get(0)).isSameInstanceAs(instanceFactory21);\n        assertThat(factories.get(1)).isSameInstanceAs(instanceFactory22);\n    }\n\n    @Test\n    public void getManyFactoriesReturnsAllFactoriesWhenNoSelectorsDefined() {\n        when(instanceFactory21.getSelector()).thenReturn(null);\n        when(instanceFactory22.getSelector()).thenReturn(null);\n\n        List<InstanceFactory<Interface2>> factories = instanceManager\n            .getManyInstanceFactories(Interface2.class, Classifier.NONE, factoryFilter);\n\n        verify(factoryFilter, never()).filter(any());\n        assertThat(factories).isNotNull();\n        assertThat(factories).hasSize(2);\n        assertThat(factories.get(0)).isSameInstanceAs(instanceFactory21);\n        assertThat(factories.get(1)).isSameInstanceAs(instanceFactory22);\n    }\n\n    @Test\n    public void getManyFactoriesReturnsFactoriesWhenSomeFactoriesHaveSelectors() {\n        when(instanceFactory21.getSelector()).thenReturn(null);\n        when(instanceFactory22.getSelector()).thenReturn(new String[]{\"test\"});\n        when(factoryFilter.filter(instanceFactory22)).thenReturn(true);\n\n        List<InstanceFactory<Interface2>> factories = instanceManager\n            .getManyInstanceFactories(Interface2.class, Classifier.NONE, factoryFilter);\n\n        verify(factoryFilter, never()).filter(instanceFactory21);\n        assertThat(factories).isNotNull();\n        assertThat(factories).hasSize(1);\n        assertThat(factories.get(0)).isSameInstanceAs(instanceFactory22);\n    }\n\n    interface Interface1 {}\n    interface Interface2 {}\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/FactoryFilter_MagnetScopeTest.java",
    "content": "package magnet.internal;\n\nimport magnet.SelectorFilter;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.MockitoJUnitRunner;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.when;\n\n@RunWith(MockitoJUnitRunner.Silent.class)\npublic class FactoryFilter_MagnetScopeTest {\n\n    private InstrumentedScope scope;\n\n    @Mock InstanceManager instanceManager;\n    @Mock InstanceFactory instanceFactory;\n    @Mock SelectorFilter selectorFilter;\n\n    @Before\n    public void before() {\n        scope = new InstrumentedScope(new MagnetScope(null, instanceManager));\n    }\n\n    @Test\n    public void noSelectorReturnsTrue() {\n        when(instanceFactory.getSelector()).thenReturn(null);\n        boolean result = scope.filter(instanceFactory);\n        assertThat(result).isTrue();\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void missingSelectorFactoryThrows() {\n        when(instanceFactory.getSelector()).thenReturn(new String[]{\"test\"});\n        scope.filter(instanceFactory);\n    }\n\n    @Test\n    public void existingSelectorReturnsFilterTrue() {\n        scope.bind(SelectorFilter.class, selectorFilter, \"test\");\n        when(instanceFactory.getSelector()).thenReturn(new String[]{\"test\"});\n        when(selectorFilter.filter(any())).thenReturn(true);\n        boolean result = scope.filter(instanceFactory);\n        assertThat(result).isTrue();\n    }\n\n    @Test\n    public void existingSelectorReturnsFilterFalse() {\n        scope.bind(SelectorFilter.class, selectorFilter, \"test\");\n        when(instanceFactory.getSelector()).thenReturn(new String[]{\"test\"});\n        when(selectorFilter.filter(any())).thenReturn(false);\n        boolean result = scope.filter(instanceFactory);\n        assertThat(result).isFalse();\n    }\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/InstanceBucketTest.java",
    "content": "package magnet.internal;\n\nimport magnet.Classifier;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.MockitoJUnitRunner;\n\nimport java.util.List;\n\nimport static com.google.common.truth.Truth.assertThat;\n\n@RunWith(MockitoJUnitRunner.StrictStubs.class)\npublic class InstanceBucketTest {\n\n    @Mock private Factory1 factory1;\n    @Mock private Factory2 factory2;\n\n    @Mock private Interface1 instance1;\n    @Mock private Interface1 instance2;\n\n    @Mock private InstanceBucket.OnInstanceListener listener;\n    @Mock private MagnetScope scope;\n\n    @Test\n    @SuppressWarnings(\"unchecked\")\n    public void test_getScope() {\n        InstanceBucket<String> instances = new InstanceBucket(\n            scope, factory1, Interface1.class, instance1, Classifier.NONE, listener\n        );\n        assertThat(instances.getScope()).isSameInstanceAs(scope);\n    }\n\n    @Test\n    @SuppressWarnings(\"unchecked\")\n    public void test_getInstances_SingleItem() {\n        InstanceBucket<Interface1> instances = new InstanceBucket(\n            scope, factory1, Interface1.class, instance1, Classifier.NONE, listener\n        );\n        List<Interface1> result = instances.getMany();\n        assertThat(result).containsExactly(instance1);\n    }\n\n    @Test\n    @SuppressWarnings(\"unchecked\")\n    public void test_getInstances_ManyItems() {\n        InstanceBucket<Interface1> instances = new InstanceBucket(\n            scope, factory1, Interface1.class, instance1, Classifier.NONE, listener\n        );\n        instances.registerObject(factory2, Interface1.class, instance2, Classifier.NONE);\n        List<Interface1> result = instances.getMany();\n        assertThat(result).containsExactly(instance1, instance2);\n    }\n\n    @Test\n    @SuppressWarnings(\"unchecked\")\n    public void test_getSingleInstance() {\n        InstanceBucket<Interface1> instances = new InstanceBucket(\n            scope, factory1, Interface1.class, instance1, Classifier.NONE, listener\n        );\n        Interface1 result = instances.getSingleInstance();\n        assertThat(result).isSameInstanceAs(instance1);\n    }\n\n    interface Interface1 {}\n    abstract static class Factory1 extends InstanceFactory<Interface1> {}\n    abstract static class Factory2 extends InstanceFactory<Interface1> {}\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/InstrumentedScope.java",
    "content": "package magnet.internal;\n\nimport magnet.Scope;\nimport magnet.Visitor;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/** Used for testing MagnetScopeContainer. */\npublic class InstrumentedScope implements Scope, FactoryFilter {\n\n    public final MagnetScope scope;\n\n    public InstrumentedScope(MagnetScope scope) {\n        this.scope = scope;\n    }\n\n    public InstrumentedScope(Scope scope) {\n        this.scope = (MagnetScope) scope;\n    }\n\n    @Override public <T> @Nullable T getOptional(@NotNull Class<T> type) {\n        return scope.getOptional(type);\n    }\n\n    @Override public <T> @Nullable T getOptional(@NotNull Class<T> type, @NotNull String classifier) {\n        return scope.getOptional(type, classifier);\n    }\n\n    @Override public <T> @NotNull T getSingle(@NotNull Class<T> type) {\n        return scope.getSingle(type);\n    }\n\n    @Override public <T> @NotNull T getSingle(@NotNull Class<T> type, @NotNull String classifier) {\n        return scope.getSingle(type, classifier);\n    }\n\n    @Override public <T> @NotNull List<T> getMany(@NotNull Class<T> type) {\n        return scope.getMany(type);\n    }\n\n    @Override public <T> @NotNull List<T> getMany(@NotNull Class<T> type, @NotNull String classifier) {\n        return scope.getMany(type, classifier);\n    }\n\n    @Override public <T> @NotNull Scope bind(@NotNull Class<T> type, @NotNull T instance) {\n        scope.bind(type, instance);\n        return this;\n    }\n\n    @Override public <T> @NotNull Scope bind(@NotNull Class<T> type, @NotNull T instance, @NotNull String classifier) {\n        scope.bind(type, instance, classifier);\n        return this;\n    }\n\n    @Override public @NotNull Scope createSubscope() {\n        return new InstrumentedScope((MagnetScope) scope.createSubscope());\n    }\n\n    @Override public @NotNull Scope limit(String... limits) {\n        return scope.limit(limits);\n    }\n\n    @Override public void dispose() {\n        scope.dispose();\n    }\n\n    @Override public boolean isDisposed() {\n        return scope.isDisposed();\n    }\n\n    @Override public void accept(Visitor visitor, int depth) {\n        scope.accept(visitor, depth);\n    }\n\n    @Override public boolean filter(InstanceFactory factory) { return scope.filter(factory); }\n\n    /** Returns and object registered right in this scope or null if no object was registered. */\n    @SuppressWarnings(\"unchecked\") <T> T getOptionalInScope(Class<T> type, String classifier) {\n        InstanceBucket<T> instance = scope.instanceBuckets.get(MagnetScope.key(type, classifier));\n        return instance == null ? null : instance.getSingleInstance();\n    }\n\n    /** Returns list of objects registered right in this scope. */\n    @SuppressWarnings(\"unchecked\") <T> List<T> getManyInScope(Class<T> type, String classifier) {\n        InstanceBucket<T> instance = scope.instanceBuckets.get(MagnetScope.key(type, classifier));\n        return instance == null ? Collections.emptyList() : instance.getMany();\n    }\n\n    /** Injects given object right into the scope, as I would be injected using given factory. */\n    @SuppressWarnings(\"unchecked\") public <T> InstrumentedScope instrumentObjectIntoScope(\n        InstanceFactory<T> factory, Class<T> objectType, T object, String classifier\n    ) {\n        String key = MagnetScope.key(objectType, classifier);\n        InstanceBucket existing = scope.instanceBuckets.get(key);\n        if (existing == null) {\n            scope.instanceBuckets.put(\n                key,\n                new InstanceBucket(scope, factory, objectType, object, classifier, scope)\n            );\n        } else {\n            existing.registerObject(factory, objectType, object, classifier);\n        }\n        return this;\n    }\n\n    InstrumentedScope createInstrumentedSubscope() {\n        return new InstrumentedScope((MagnetScope) scope.createSubscope());\n    }\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/MagnetInstanceManagerTest.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Classifier;\nimport magnet.Scope;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.MockitoJUnitRunner;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.when;\n\n@RunWith(MockitoJUnitRunner.Silent.class)\npublic class MagnetInstanceManagerTest {\n\n    private static final String CLASSIFIER_LOCAL = \"local\";\n\n    @Mock InstanceFactory<Type1> instanceFactoryType1Impl1;\n    @Mock InstanceFactory<Type1> instanceFactoryType1Impl2;\n    @Mock InstanceFactory<Type2> instanceFactoryType2Impl1;\n    @Mock InstanceFactory<Type2> instanceFactoryType2Impl2;\n    @Mock InstanceFactory<Type3> instanceFactoryType3Impl1;\n    @Mock FactoryFilter factoryFilter;\n    @Mock Scope scope;\n\n    private MagnetInstanceManager instManager;\n\n    @Before\n    public void before() {\n        instManager = new MagnetInstanceManager();\n\n        when(factoryFilter.filter(any())).thenReturn(true);\n\n        when(instanceFactoryType1Impl1.create(scope)).thenReturn(new Type1Impl());\n        when(instanceFactoryType1Impl2.create(scope)).thenReturn(new Type1Impl());\n        when(instanceFactoryType2Impl1.create(scope)).thenReturn(new Type2Impl());\n        when(instanceFactoryType2Impl2.create(scope)).thenReturn(new Type2Impl());\n        when(instanceFactoryType3Impl1.create(scope)).thenReturn(new Type3Impl());\n\n        InstanceFactory[] factories = new InstanceFactory[]{\n            instanceFactoryType1Impl1,\n            instanceFactoryType1Impl2,\n            instanceFactoryType2Impl1,\n            instanceFactoryType2Impl2,\n            instanceFactoryType3Impl1\n        };\n\n        Map<Class, Object> index = new HashMap<>();\n\n        Map<String, Range> ranges1 = new HashMap<>();\n        ranges1.put(Classifier.NONE, new Range(0, 1, Classifier.NONE));\n        ranges1.put(CLASSIFIER_LOCAL, new Range(1, 1, CLASSIFIER_LOCAL));\n\n        index.put(Type1.class, ranges1);\n        index.put(Type2.class, new Range(2, 2, Classifier.NONE));\n        index.put(Type3.class, new Range(4, 1, CLASSIFIER_LOCAL));\n\n        instManager.register(factories, index);\n    }\n\n    @Test\n    public void getOptionalFactory_Classified_Existing_SingleTypeInstance() {\n        // when\n        InstanceFactory<Type3> factory = instManager.getFilteredInstanceFactory(\n            Type3.class, CLASSIFIER_LOCAL, factoryFilter);\n\n        // then\n        assertThat(factory).isNotNull();\n    }\n\n    @Test\n    public void getOptionalFactory_Classified_Existing_ManyTypeInstances() {\n        // when\n        InstanceFactory<Type1> factory = instManager.getFilteredInstanceFactory(\n            Type1.class, CLASSIFIER_LOCAL, factoryFilter);\n\n        // then\n        assertThat(factory).isNotNull();\n    }\n\n    @Test\n    public void getOptionalFactory_NotClassified_Existing() {\n        // when\n        InstanceFactory<Type1> factory = instManager.getFilteredInstanceFactory(\n            Type1.class, Classifier.NONE, factoryFilter);\n\n        // then\n        assertThat(factory).isNotNull();\n    }\n\n    @Test\n    public void getOptionalFactory_Classified_NotExisting() {\n        // when\n        InstanceFactory<String> factory = instManager.getFilteredInstanceFactory(\n            String.class, CLASSIFIER_LOCAL, factoryFilter);\n\n        // then\n        assertThat(factory).isNull();\n    }\n\n    @Test\n    public void getOptionalFactory_NotClassified_NotExisting() {\n        // when\n        InstanceFactory<String> factory = instManager.getFilteredInstanceFactory(\n            String.class, Classifier.NONE, factoryFilter);\n\n        // then\n        assertThat(factory).isNull();\n    }\n\n    @Test\n    public void getManyFactories_NotClassified_ManyTypeInstances() {\n        // when\n        List<InstanceFactory<Type1>> factories = instManager.getManyInstanceFactories(\n            Type1.class, Classifier.NONE, factoryFilter);\n\n        // then\n        assertThat(factories).hasSize(1);\n        assertThat(factories.get(0)).isEqualTo(instanceFactoryType1Impl1);\n    }\n\n    @Test\n    public void getManyFactories_Classified_ManyTypeInstances() {\n        // when\n        List<InstanceFactory<Type1>> factories = instManager.getManyInstanceFactories(\n            Type1.class, CLASSIFIER_LOCAL, factoryFilter);\n\n        // then\n        assertThat(factories).hasSize(1);\n        assertThat(factories.get(0)).isEqualTo(instanceFactoryType1Impl2);\n    }\n\n    @Test\n    public void getManyFactories_NotClassified_SingleTypeInstances() {\n        // when\n        List<InstanceFactory<Type2>> factories = instManager.getManyInstanceFactories(\n            Type2.class, Classifier.NONE, factoryFilter);\n\n        // then\n        assertThat(factories).hasSize(2);\n        assertThat(factories).containsExactly(instanceFactoryType2Impl1, instanceFactoryType2Impl2);\n    }\n\n    @Test\n    public void getManyFactories_Classified_SingleTypeInstances() {\n        // when\n        List<InstanceFactory<Type3>> factories = instManager.getManyInstanceFactories(\n            Type3.class, CLASSIFIER_LOCAL, factoryFilter);\n\n        // then\n        assertThat(factories).hasSize(1);\n        assertThat(factories.get(0)).isEqualTo(instanceFactoryType3Impl1);\n    }\n\n    interface Type1 {}\n    interface Type2 {}\n    interface Type3 {}\n\n    class Type1Impl implements Type1 {}\n    class Type2Impl implements Type2 {}\n    class Type3Impl implements Type3 {}\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/MagnetScope_CircularDependencyTest.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Scope;\nimport magnet.Scoping;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n@RunWith(JUnit4.class)\npublic class MagnetScope_CircularDependencyTest {\n\n    private MagnetScope scope;\n\n    @Before\n    public void before() {\n        scope = new MagnetScope(null, new StubInstanceManager());\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void dependency_One_Two_Three_One() {\n        scope.getSingle(MenuItem.class, \"one\");\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void dependency_Four_Four() {\n        scope.getSingle(MenuItem.class, \"four\");\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void dependency_Five_Constructor_Five() {\n        scope.getSingle(MenuItem.class, \"five\");\n    }\n\n    private static class MenuItemOneFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(MenuItem.class, \"two\");\n            return new MenuItemOne();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class MenuItemTwoFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(MenuItem.class, \"three\");\n            return new MenuItemTwo();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class MenuItemThreeFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(MenuItem.class, \"one\");\n            return new MenuItemThree();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class MenuItemFourFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(MenuItem.class, \"four\");\n            return new MenuItemFour();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class MenuItemFiveFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            return new MenuItemFive(scope);\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class StubInstanceManager implements InstanceManager {\n        private final Map<String, InstanceFactory<MenuItem>> factories;\n\n        StubInstanceManager() {\n            factories = new HashMap<>();\n            factories.put(\"one\", new MenuItemOneFactory());\n            factories.put(\"two\", new MenuItemTwoFactory());\n            factories.put(\"three\", new MenuItemThreeFactory());\n            factories.put(\"four\", new MenuItemFourFactory());\n            factories.put(\"five\", new MenuItemFiveFactory());\n        }\n\n        @Override\n        public <T> InstanceFactory getInstanceFactory(\n            Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType\n        ) {\n            throw new UnsupportedOperationException();\n        }\n        @Override public <T> InstanceFactory<T> getFilteredInstanceFactory(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            //noinspection unchecked\n            return (InstanceFactory<T>) factories.get(classifier);\n        }\n        @Override public <T> List<InstanceFactory<T>> getManyInstanceFactories(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n    private interface MenuItem {}\n\n    private static class MenuItemOne implements MenuItem {}\n    private static class MenuItemTwo implements MenuItem {}\n    private static class MenuItemThree implements MenuItem {}\n    private static class MenuItemFour implements MenuItem {}\n\n    private static class MenuItemFive implements MenuItem {\n        public MenuItemFive(Scope scope) {\n            scope.getSingle(MenuItem.class, \"five\");\n        }\n    }\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/MagnetScope_DisposeTest.java",
    "content": "package magnet.internal;\n\nimport magnet.Classifier;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.InOrder;\nimport org.mockito.Mock;\nimport org.mockito.junit.MockitoJUnitRunner;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.inOrder;\nimport static org.mockito.Mockito.never;\nimport static org.mockito.Mockito.times;\nimport static org.mockito.Mockito.verify;\nimport static org.mockito.Mockito.when;\n\n@RunWith(MockitoJUnitRunner.StrictStubs.class)\npublic class MagnetScope_DisposeTest {\n\n    @Mock private InstanceManager instanceManager;\n    @Mock private Factory1 factory1;\n    @Mock private Factory2 factory2;\n    @Mock private Factory3 factory3;\n    @Mock private Factory4 factory4;\n    @Mock private Interface instance1;\n    @Mock private Interface instance2;\n    @Mock private Interface instance3;\n    @Mock private Interface instance4;\n\n    @Test\n    public void disposeSingleScope_NoClassifier() {\n        InstrumentedScope scope = new InstrumentedScope(\n            new MagnetScope(null, instanceManager)\n        );\n        when(factory1.isDisposable()).thenReturn(true);\n        scope.instrumentObjectIntoScope(factory1, Interface.class, instance1, Classifier.NONE);\n        scope.instrumentObjectIntoScope(factory2, Interface.class, instance2, Classifier.NONE);\n        when(factory3.isDisposable()).thenReturn(true);\n        scope.instrumentObjectIntoScope(factory3, Interface.class, instance3, Classifier.NONE);\n\n        scope.dispose();\n\n        verify(factory1, times(1)).dispose(instance1);\n        verify(factory2, never()).dispose(any());\n        verify(factory3, times(1)).dispose(instance3);\n    }\n\n    @Test\n    public void disposeSingleScope_WithClassifiers() {\n        InstrumentedScope scope = new InstrumentedScope(\n            new MagnetScope(null, instanceManager)\n        );\n        when(factory1.isDisposable()).thenReturn(true);\n        scope.instrumentObjectIntoScope(factory1, Interface.class, instance1, \"classifier1\");\n        scope.instrumentObjectIntoScope(factory2, Interface.class, instance2, \"classifier2\");\n        when(factory3.isDisposable()).thenReturn(true);\n        scope.instrumentObjectIntoScope(factory3, Interface.class, instance3, Classifier.NONE);\n\n        scope.dispose();\n\n        verify(factory1, times(1)).dispose(instance1);\n        verify(factory2, never()).dispose(any());\n        verify(factory3, times(1)).dispose(instance3);\n    }\n\n    @Test\n    public void disposingParentScope_DisposesChildrenScopes() {\n        MagnetScope parentScope;\n        InstrumentedScope parent = new InstrumentedScope(parentScope = new MagnetScope(null, instanceManager));\n        when(factory1.isDisposable()).thenReturn(true);\n        parent.instrumentObjectIntoScope(factory1, Interface.class, instance1, Classifier.NONE);\n\n        InstrumentedScope child = new InstrumentedScope((MagnetScope) parentScope.createSubscope());\n        when(factory2.isDisposable()).thenReturn(true);\n        child.instrumentObjectIntoScope(factory2, Interface.class, instance2, Classifier.NONE);\n        child.instrumentObjectIntoScope(factory3, Interface.class, instance3, Classifier.NONE);\n\n        parent.dispose();\n\n        verify(factory1, times(1)).dispose(instance1);\n        verify(factory2, times(1)).dispose(instance2);\n        verify(factory3, never()).dispose(instance3);\n    }\n\n    @Test\n    public void disposingChildScope_KeepsParentScopes() {\n        MagnetScope parentScope;\n        InstrumentedScope parent = new InstrumentedScope(parentScope = new MagnetScope(null, instanceManager));\n        parent.instrumentObjectIntoScope(factory1, Interface.class, instance1, Classifier.NONE);\n\n        InstrumentedScope child = new InstrumentedScope((MagnetScope) parentScope.createSubscope());\n        when(factory2.isDisposable()).thenReturn(true);\n        child.instrumentObjectIntoScope(factory2, Interface.class, instance2, Classifier.NONE);\n\n        child.dispose();\n\n        verify(factory2, times(1)).dispose(instance2);\n        verify(factory1, never()).dispose(any());\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void disposedScopeThrowsException() {\n        InstrumentedScope scope = new InstrumentedScope(\n            new MagnetScope(null, instanceManager)\n        );\n        when(factory1.isDisposable()).thenReturn(true);\n        scope.instrumentObjectIntoScope(factory1, Interface.class, instance1, \"classifier1\");\n\n        scope.dispose();\n\n        scope.getOptional(String.class);\n    }\n\n    @Test\n    public void disposeChildScope_InReversOrdered() {\n        InstrumentedScope scope = new InstrumentedScope(\n            new MagnetScope(null, instanceManager)\n        );\n        when(factory1.isDisposable()).thenReturn(true);\n        when(factory2.isDisposable()).thenReturn(true);\n        when(factory3.isDisposable()).thenReturn(true);\n        scope.instrumentObjectIntoScope(factory1, Interface.class, instance1, Classifier.NONE);\n        scope.instrumentObjectIntoScope(factory2, Interface.class, instance2, Classifier.NONE);\n        scope.instrumentObjectIntoScope(factory3, Interface.class, instance3, Classifier.NONE);\n\n        scope.dispose();\n\n        InOrder order = inOrder(factory3, factory2, factory1);\n        order.verify(factory3, times(1)).dispose(instance3);\n        order.verify(factory2, times(1)).dispose(instance2);\n        order.verify(factory1, times(1)).dispose(instance1);\n    }\n\n    @Test\n    public void disposeParentScope_InReversOrdered() {\n\n        when(factory1.isDisposable()).thenReturn(true);\n        when(factory2.isDisposable()).thenReturn(true);\n        when(factory3.isDisposable()).thenReturn(true);\n\n        MagnetScope parentScope;\n        InstrumentedScope parent = new InstrumentedScope(parentScope = new MagnetScope(null, instanceManager));\n        parent.instrumentObjectIntoScope(factory1, Interface.class, instance1, Classifier.NONE);\n\n        InstrumentedScope child = new InstrumentedScope((MagnetScope) parentScope.createSubscope());\n        when(factory2.isDisposable()).thenReturn(true);\n        child.instrumentObjectIntoScope(factory2, Interface.class, instance2, Classifier.NONE);\n\n        parent.instrumentObjectIntoScope(factory3, Interface.class, instance3, Classifier.NONE);\n\n        parent.dispose();\n\n        InOrder order = inOrder(factory2, factory3, factory1);\n        order.verify(factory2, times(1)).dispose(instance2);\n        order.verify(factory3, times(1)).dispose(instance3);\n        order.verify(factory1, times(1)).dispose(instance1);\n    }\n\n    @Test\n    public void disposeFirstChildThenParentScopes() {\n\n        when(factory1.isDisposable()).thenReturn(true);\n        InstrumentedScope parent =\n            new InstrumentedScope(new MagnetScope(null, instanceManager))\n                .instrumentObjectIntoScope(factory1, Interface.class, instance1, Classifier.NONE);\n\n        when(factory2.isDisposable()).thenReturn(true);\n        InstrumentedScope child =\n            parent.createInstrumentedSubscope()\n                .instrumentObjectIntoScope(factory2, Interface.class, instance2, Classifier.NONE);\n\n        child.dispose();\n        parent.dispose();\n\n        InOrder order = inOrder(factory2, factory1);\n        order.verify(factory2, times(1)).dispose(instance2);\n        order.verify(factory1, times(1)).dispose(instance1);\n    }\n\n    @Test\n    public void disposeMultipleChildScopes_123() {\n\n        InstrumentedScope[] child = prepareMultipleChildrenScopes();\n\n        child[1].dispose();\n        child[2].dispose();\n        child[3].dispose();\n        child[0].dispose();\n\n        InOrder order = inOrder(factory2, factory3, factory4, factory1);\n        order.verify(factory2, times(1)).dispose(instance2);\n        order.verify(factory3, times(1)).dispose(instance3);\n        order.verify(factory4, times(1)).dispose(instance4);\n        order.verify(factory1, times(1)).dispose(instance1);\n    }\n\n    @Test\n    public void disposeMultipleChildScopes_132() {\n\n        InstrumentedScope[] child = prepareMultipleChildrenScopes();\n\n        child[1].dispose();\n        child[3].dispose();\n        child[2].dispose();\n        child[0].dispose();\n\n        InOrder order = inOrder(factory2, factory4, factory3, factory1);\n        order.verify(factory2, times(1)).dispose(instance2);\n        order.verify(factory4, times(1)).dispose(instance4);\n        order.verify(factory3, times(1)).dispose(instance3);\n        order.verify(factory1, times(1)).dispose(instance1);\n    }\n\n    @Test\n    public void disposeMultipleChildScopes_213() {\n\n        InstrumentedScope[] child = prepareMultipleChildrenScopes();\n\n        child[2].dispose();\n        child[1].dispose();\n        child[3].dispose();\n        child[0].dispose();\n\n        InOrder order = inOrder(factory3, factory2, factory4, factory1);\n        order.verify(factory3, times(1)).dispose(instance3);\n        order.verify(factory2, times(1)).dispose(instance2);\n        order.verify(factory4, times(1)).dispose(instance4);\n        order.verify(factory1, times(1)).dispose(instance1);\n    }\n\n    @Test\n    public void disposeMultipleChildScopes_231() {\n\n        InstrumentedScope[] child = prepareMultipleChildrenScopes();\n\n        child[2].dispose();\n        child[3].dispose();\n        child[1].dispose();\n        child[0].dispose();\n\n        InOrder order = inOrder(factory3, factory4, factory2, factory1);\n        order.verify(factory3, times(1)).dispose(instance3);\n        order.verify(factory4, times(1)).dispose(instance4);\n        order.verify(factory2, times(1)).dispose(instance2);\n        order.verify(factory1, times(1)).dispose(instance1);\n    }\n\n    @Test\n    public void disposeMultipleChildScopes_312() {\n\n        InstrumentedScope[] child = prepareMultipleChildrenScopes();\n\n        child[3].dispose();\n        child[1].dispose();\n        child[2].dispose();\n        child[0].dispose();\n\n        InOrder order = inOrder(factory4, factory2, factory3, factory1);\n        order.verify(factory4, times(1)).dispose(instance4);\n        order.verify(factory2, times(1)).dispose(instance2);\n        order.verify(factory3, times(1)).dispose(instance3);\n        order.verify(factory1, times(1)).dispose(instance1);\n    }\n\n    @Test\n    public void disposeMultipleChildScopes_321() {\n\n        InstrumentedScope[] child = prepareMultipleChildrenScopes();\n\n        child[3].dispose();\n        child[2].dispose();\n        child[1].dispose();\n        child[0].dispose();\n\n        InOrder order = inOrder(factory4, factory3, factory2, factory1);\n        order.verify(factory4, times(1)).dispose(instance4);\n        order.verify(factory3, times(1)).dispose(instance3);\n        order.verify(factory2, times(1)).dispose(instance2);\n        order.verify(factory1, times(1)).dispose(instance1);\n    }\n\n    private InstrumentedScope[] prepareMultipleChildrenScopes() {\n\n        when(factory1.isDisposable()).thenReturn(true);\n        InstrumentedScope parent =\n            new InstrumentedScope(new MagnetScope(null, instanceManager))\n                .instrumentObjectIntoScope(factory1, Interface.class, instance1, Classifier.NONE);\n\n        when(factory2.isDisposable()).thenReturn(true);\n        InstrumentedScope child1 =\n            parent.createInstrumentedSubscope()\n                .instrumentObjectIntoScope(factory2, Interface.class, instance2, Classifier.NONE);\n\n        when(factory3.isDisposable()).thenReturn(true);\n        InstrumentedScope child2 =\n            parent.createInstrumentedSubscope()\n                .instrumentObjectIntoScope(factory3, Interface.class, instance3, Classifier.NONE);\n\n        when(factory4.isDisposable()).thenReturn(true);\n        InstrumentedScope child3 =\n            parent.createInstrumentedSubscope()\n                .instrumentObjectIntoScope(factory4, Interface.class, instance4, Classifier.NONE);\n\n        return new InstrumentedScope[]{parent, child1, child2, child3};\n\n    }\n\n    interface Interface {}\n    abstract static class Factory1 extends InstanceFactory<Interface> {}\n    abstract static class Factory2 extends InstanceFactory<Interface> {}\n    abstract static class Factory3 extends InstanceFactory<Interface> {}\n    abstract static class Factory4 extends InstanceFactory<Interface> {}\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/MagnetScope_FindDeepForSiblingTypesTest.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Classifier;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mock;\nimport org.mockito.Mockito;\nimport org.mockito.junit.MockitoJUnitRunner;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.when;\n\n@RunWith(MockitoJUnitRunner.Silent.class)\npublic class MagnetScope_FindDeepForSiblingTypesTest {\n\n    @Mock private Implementation1Factory factory1;\n    @Mock private SiblingImplementation1Factory factory21;\n    @Mock private SiblingImplementation2Factory factory22;\n    @Mock private Implementation instance1;\n    @Mock private SiblingImplementation instance2;\n\n    private MagnetInstanceManager instanceManager;\n\n    @Before\n    public void before() {\n\n        instanceManager = new MagnetInstanceManager();\n        InstanceFactory[] factories = new InstanceFactory[]{factory1, factory21, factory22};\n        Map<Class, Object> index = new HashMap<>();\n        index.put(Interface.class, new Range(0, 2, Classifier.NONE));\n        index.put(SiblingInterface.class, new Range(2, 1, Classifier.NONE));\n        instanceManager.register(factories, index);\n\n        when(factory1.create(any())).thenReturn(Mockito.mock(Interface.class));\n        when(factory21.create(any())).thenReturn(Mockito.mock(Interface.class));\n        when(factory22.create(any())).thenReturn(Mockito.mock(SiblingInterface.class));\n\n        when(factory21.getSiblingTypes()).thenReturn(new Class[]{SiblingInterface.class, SiblingImplementation2Factory.class});\n        when(factory22.getSiblingTypes()).thenReturn(new Class[]{Interface.class, SiblingImplementation1Factory.class});\n    }\n\n    @Test\n    public void getMany_collectsAlsoSiblingInstancesFromScope() {\n        // given\n        InstrumentedScope scope0 = new InstrumentedScope(\n            new MagnetScope(null, instanceManager)\n        );\n        scope0.instrumentObjectIntoScope(factory21, Interface.class, instance2, Classifier.NONE);\n        scope0.instrumentObjectIntoScope(factory22, SiblingInterface.class, instance2, Classifier.NONE);\n\n        InstrumentedScope scope1 = (InstrumentedScope) scope0.createSubscope();\n        scope1.instrumentObjectIntoScope(factory1, Interface.class, instance1, Classifier.NONE);\n\n        // when\n        List<Interface> many = scope1.getMany(Interface.class);\n\n        // then\n        assertThat(many).containsExactly(instance1, instance2);\n    }\n\n    // -- configuration\n\n    private interface Interface {}\n    private interface SiblingInterface {}\n\n    private static class Implementation implements Interface {}\n    private static class SiblingImplementation implements Interface, SiblingInterface {}\n\n    private abstract static class Implementation1Factory extends InstanceFactory<Interface> {}\n    private abstract static class SiblingImplementation1Factory extends InstanceFactory<Interface> {}\n    private abstract static class SiblingImplementation2Factory extends InstanceFactory<SiblingInterface> {}\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/MagnetScope_GetManyTest.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Scope;\nimport magnet.Scoping;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.google.common.truth.Truth.assertThat;\n\n@RunWith(JUnit4.class)\npublic class MagnetScope_GetManyTest {\n\n    private InstrumentedScope scope1;\n    private InstrumentedScope scope2;\n\n    @Before\n    public void before() {\n        scope1 = new InstrumentedScope(\n            new MagnetScope(null, new StubInstanceManager()));\n\n        scope2 = (InstrumentedScope) scope1\n            .createSubscope()\n            .bind(Dependency2.class, new Dependency2());\n    }\n\n    @Test\n    public void getSingleScopedMany() {\n        // when\n        List<MenuItem> oneList = scope1.getMany(MenuItem.class, \"one\");\n\n        // then\n        assertThat(oneList).hasSize(3);\n        assertThat(oneList).containsNoDuplicates();\n\n        List<MenuItem> onesInScope = scope1.getManyInScope(MenuItem.class, \"one\");\n        assertThat(onesInScope).hasSize(3);\n        assertThat(onesInScope).containsNoDuplicates();\n        assertThat(onesInScope).containsAtLeastElementsIn(oneList);\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void getMultiScopedMany_requestScope1() {\n        scope1.getMany(MenuItem.class, \"two\");\n    }\n\n    @Test\n    public void getMultiScopedMany_requestScope2() {\n        // when\n        List<MenuItem> twoList = scope2.getMany(MenuItem.class, \"two\");\n\n        // then\n        assertThat(twoList).hasSize(2);\n        assertThat(twoList).containsNoDuplicates();\n\n        List<MenuItem> oneScope1 = scope1.getManyInScope(MenuItem.class, \"one\");\n        List<MenuItem> twoScope1 = scope1.getManyInScope(MenuItem.class, \"two\");\n        List<MenuItem> oneScope2 = scope2.getManyInScope(MenuItem.class, \"one\");\n        List<MenuItem> twoScope2 = scope2.getManyInScope(MenuItem.class, \"two\");\n\n        assertThat(oneScope1).hasSize(3);\n        assertThat(twoScope1).hasSize(1);\n        assertThat(oneScope2).hasSize(0);\n        assertThat(twoScope2).hasSize(1);\n\n        assertThat(twoList).contains(twoScope1.get(0));\n        assertThat(twoList).contains(twoScope2.get(0));\n    }\n\n    private static class MenuItemOne1Factory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            return new MenuItemOne1();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class MenuItemOne2Factory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            return new MenuItemOne2();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class MenuItemOne3Factory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            return new MenuItemOne3();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class MenuItemTwo1Factory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            return new MenuItemTwo1();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class MenuItemTwo2Factory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(Dependency2.class);\n            scope.getMany(MenuItem.class, \"one\");\n            return new MenuItemTwo2();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static class StubInstanceManager implements InstanceManager {\n        private final Map<String, Object> factories;\n\n        StubInstanceManager() {\n            factories = new HashMap<>();\n\n            List<InstanceFactory> oneList = new ArrayList<>();\n            oneList.add(new MenuItemOne1Factory());\n            oneList.add(new MenuItemOne2Factory());\n            oneList.add(new MenuItemOne3Factory());\n            factories.put(\"one\", oneList);\n\n            List<InstanceFactory> twoList = new ArrayList<>();\n            twoList.add(new MenuItemTwo1Factory());\n            twoList.add(new MenuItemTwo2Factory());\n            factories.put(\"two\", twoList);\n        }\n\n        @Override\n        public <T> InstanceFactory getInstanceFactory(\n            Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType\n        ) {\n            throw new UnsupportedOperationException();\n        }\n        @Override public <T> InstanceFactory<T> getFilteredInstanceFactory(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            return (InstanceFactory<T>) factories.get(classifier);\n        }\n        @Override public <T> List<InstanceFactory<T>> getManyInstanceFactories(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            return (List<InstanceFactory<T>>) factories.get(classifier);\n        }\n    }\n\n    private interface MenuItem {}\n\n    private static class MenuItemOne1 implements MenuItem {}\n    private static class MenuItemOne2 implements MenuItem {}\n    private static class MenuItemOne3 implements MenuItem {}\n\n    private static class MenuItemTwo1 implements MenuItem {}\n    private static class MenuItemTwo2 implements MenuItem {}\n\n    private static class Dependency2 {}\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/MagnetScope_ManyInstancesInMultipleScopesTest.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Classifier;\nimport magnet.Scope;\nimport magnet.Scoping;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport static com.google.common.truth.Truth.assertThat;\n\n@RunWith(JUnit4.class)\npublic class MagnetScope_ManyInstancesInMultipleScopesTest {\n\n    private InstrumentedScope scope1;\n    private InstrumentedScope scope2;\n    private InstrumentedScope scope3;\n\n    private InstanceImpl1Factory factory1 = new InstanceImpl1Factory();\n    private InstanceImpl2Factory factory2 = new InstanceImpl2Factory();\n    private InstanceImpl3Factory factory3 = new InstanceImpl3Factory();\n\n    @Before\n    public void before() {\n        scope1 = new InstrumentedScope(new MagnetScope(null, new StubInstanceManager()));\n        scope1.instrumentObjectIntoScope(factory1, InstanceType.class, new InstanceImpl1(), Classifier.NONE);\n\n        scope2 = (InstrumentedScope) scope1.createSubscope();\n        scope2.instrumentObjectIntoScope(factory2, InstanceType.class, new InstanceImpl2(), Classifier.NONE);\n\n        scope3 = (InstrumentedScope) scope2.createSubscope();\n    }\n\n    @Test\n    public void getSingleScopedMany() {\n        // given\n\n        // when\n        List<InstanceType> instances = scope3.getMany(InstanceType.class, \"\");\n\n        // then\n        assertThat(instances).hasSize(3);\n        assertThat(instances).containsNoDuplicates();\n\n        assertThat(scope3.getOptionalInScope(InstanceType.class, \"\")).isNull();\n        assertThat(scope2.getOptionalInScope(InstanceType.class, \"\")).isNotNull();\n\n        List<InstanceType> instancesInScope1 = scope1.getManyInScope(InstanceType.class, \"\");\n        assertThat(instancesInScope1).isNotNull();\n        assertThat(instancesInScope1).hasSize(2);\n    }\n\n    private static class InstanceImpl1Factory extends InstanceFactory<InstanceType> {\n        @Override public InstanceType create(Scope scope) { return new InstanceImpl1(); }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class InstanceImpl2Factory extends InstanceFactory<InstanceType> {\n        @Override public InstanceType create(Scope scope) { return new InstanceImpl2(); }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class InstanceImpl3Factory extends InstanceFactory<InstanceType> {\n        @Override public InstanceType create(Scope scope) { return new InstanceImpl3(); }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private class StubInstanceManager implements InstanceManager {\n        private final List instanceTypeFactories = new ArrayList<>();\n\n        StubInstanceManager() {\n            instanceTypeFactories.add(factory1);\n            instanceTypeFactories.add(factory2);\n            instanceTypeFactories.add(factory3);\n        }\n\n        @Override\n        public <T> InstanceFactory getInstanceFactory(\n            Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType\n        ) {\n            throw new UnsupportedOperationException();\n        }\n        @Override public <T> InstanceFactory<T> getFilteredInstanceFactory(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            throw new UnsupportedOperationException();\n        }\n        @Override public <T> List<InstanceFactory<T>> getManyInstanceFactories(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            if (type == InstanceType.class) {\n                return (List<InstanceFactory<T>>) instanceTypeFactories;\n            }\n            throw new UnsupportedOperationException();\n        }\n    }\n\n    private interface InstanceType {}\n\n    private static class InstanceImpl1 implements InstanceType {}\n    private static class InstanceImpl2 implements InstanceType {}\n    private static class InstanceImpl3 implements InstanceType {}\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/MagnetScope_RegisterAndGetTest.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport static com.google.common.truth.Truth.assertThat;\n\nimport magnet.Scope;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.MockitoJUnitRunner;\n\n@RunWith(MockitoJUnitRunner.StrictStubs.class)\npublic class MagnetScope_RegisterAndGetTest {\n\n    @Mock\n    InstanceManager instanceManager;\n\n    private Scope scope;\n\n    @Before\n    public void before() {\n        scope = new MagnetScope(null, instanceManager);\n    }\n\n    @Test\n    public void noClassifier_GetOptionalNotRegistered() {\n        // when\n        Integer dependency = scope.getOptional(Integer.class);\n\n        // then\n        assertThat(dependency).isNull();\n    }\n\n    @Test\n    public void noClassifier_GetOptionalRegistered() {\n        // given\n        scope.bind(Integer.class, 100);\n\n        // when\n        Integer dependency = scope.getOptional(Integer.class);\n\n        // then\n        assertThat(dependency).isEqualTo(100);\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void noClassifier_GetSingleNotRegistered() {\n        scope.getSingle(Integer.class);\n    }\n\n    @Test\n    public void noClassifier_GetSingleRegistered() {\n        // given\n        scope.bind(Integer.class, 100);\n\n        // when\n        Integer dependency = scope.getSingle(Integer.class);\n\n        // then\n        assertThat(dependency).isEqualTo(100);\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void noClassifier_RegisterOverwrite() {\n        scope.bind(Integer.class, 100);\n        scope.bind(Integer.class, 200);\n    }\n\n    @Test\n    public void classifier_GetOptionalNotRegistered() {\n        // when\n        Integer dependency = scope.getOptional(Integer.class, \"common\");\n\n        // then\n        assertThat(dependency).isNull();\n    }\n\n    @Test\n    public void classifier_GetOptionalRegisteredNoClassifier() {\n        // given\n        scope.bind(Integer.class, 100, \"common\");\n\n        // when\n        Integer dependency = scope.getOptional(Integer.class);\n\n        // then\n        assertThat(dependency).isNull();\n    }\n\n    @Test\n    public void classifier_GetOptionalRegisteredWrongClassifier() {\n        // given\n        scope.bind(Integer.class, 100, \"common\");\n\n        // when\n        Integer dependency = scope.getOptional(Integer.class, \"wrong\");\n\n        // then\n        assertThat(dependency).isNull();\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void classifier_GetSingleNotRegistered() {\n        scope.getSingle(Integer.class, \"common\");\n    }\n\n    @Test\n    public void classifier_GetSingleRegistered() {\n        // given\n        scope.bind(Integer.class, 100, \"common\");\n\n        // when\n        Integer dependency = scope.getSingle(Integer.class, \"common\");\n\n        // then\n        assertThat(dependency).isEqualTo(100);\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void classifier_RegisterOverwrite() {\n        scope.bind(Integer.class, 100, \"common\");\n        scope.bind(Integer.class, 200, \"common\");\n    }\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/MagnetScope_SiblingTypesTest.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Classifier;\nimport magnet.Scope;\nimport magnet.Scoping;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.mockito.junit.MockitoJUnitRunner;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport static com.google.common.truth.Truth.assertThat;\n\n@RunWith(MockitoJUnitRunner.Silent.class)\npublic class MagnetScope_SiblingTypesTest {\n\n    @Test\n    public void sameInstanceIsRegisteredScope() {\n        MagnetInstanceManager instanceManager = createMagnetInstanceManager(Scoping.TOPMOST);\n        Scope topMost = new MagnetScope(null, instanceManager);\n        Scope directScope = topMost.createSubscope();\n\n        Interface1 instance1 = directScope.getSingle(Interface1.class);\n        Interface2 instance2 = directScope.getSingle(Interface2.class);\n        assertThat(instance1).isSameInstanceAs(instance2);\n    }\n\n    @Test\n    public void sameInstanceIsRegisteredScopeInReverseOrder() {\n        MagnetInstanceManager instanceManager = createMagnetInstanceManager(Scoping.TOPMOST);\n        Scope topMost = new MagnetScope(null, instanceManager);\n        Scope directScope = topMost.createSubscope();\n\n        Interface2 instance2 = directScope.getSingle(Interface2.class);\n        Interface1 instance1 = directScope.getSingle(Interface1.class);\n        assertThat(instance1).isSameInstanceAs(instance2);\n    }\n\n    @Test\n    public void sameInstanceIsRegisteredInTopMostScope() {\n        MagnetInstanceManager instanceManager = createMagnetInstanceManager(Scoping.TOPMOST);\n        Scope topMost = new MagnetScope(null, instanceManager);\n        Scope directScope = topMost.createSubscope();\n        directScope.getSingle(Interface1.class);\n\n        Interface1 instance1 = topMost.getSingle(Interface1.class);\n        Interface2 instance2 = topMost.getSingle(Interface2.class);\n        assertThat(instance1).isSameInstanceAs(instance2);\n    }\n\n    @Test\n    public void sameInstanceIsRegisteredInDirectScope() {\n        MagnetInstanceManager instanceManager = createMagnetInstanceManager(Scoping.DIRECT);\n        Scope topMost = new MagnetScope(null, instanceManager);\n        Scope directScope = topMost.createSubscope();\n\n        Interface1 instance1 = directScope.getSingle(Interface1.class);\n        Interface2 instance2 = directScope.getSingle(Interface2.class);\n        assertThat(instance1).isSameInstanceAs(instance2);\n    }\n\n    @Test\n    public void sameInstanceIsNotRegisteredInTopMostScope() {\n        MagnetInstanceManager instanceManager = createMagnetInstanceManager(Scoping.DIRECT);\n        MagnetScope topMost = new MagnetScope(null, instanceManager);\n        Scope directScope = topMost.createSubscope();\n        directScope.getSingle(Interface1.class);\n\n        assertThat(topMost.instanceBuckets).isEmpty();\n    }\n\n    private static MagnetInstanceManager createMagnetInstanceManager(Scoping scoping) {\n        MagnetInstanceManager instanceManager = new MagnetInstanceManager();\n\n        InstanceFactory[] factories = new InstanceFactory[]{\n            new ImplementationInterface1Factory(scoping),\n            new ImplementationInterface2Factory(scoping)\n        };\n\n        Map<Class, Object> index = new HashMap<>();\n        index.put(Interface1.class, new Range(0, 1, Classifier.NONE));\n        index.put(Interface2.class, new Range(1, 1, Classifier.NONE));\n\n        instanceManager.register(factories, index);\n        return instanceManager;\n    }\n\n    interface Interface1 {}\n    interface Interface2 {}\n\n    static class Implementation implements Interface1, Interface2 {}\n\n    static class ImplementationInterface1Factory extends InstanceFactory<Interface1> {\n        private Scoping scoping;\n        ImplementationInterface1Factory(Scoping scoping) { this.scoping = scoping; }\n        @Override public Interface1 create(Scope scope) { return new Implementation(); }\n        @Override public Scoping getScoping() { return this.scoping; }\n        @Override public Class[] getSiblingTypes() {\n            return new Class[]{Interface2.class, ImplementationInterface2Factory.class};\n        }\n    }\n\n    static class ImplementationInterface2Factory extends InstanceFactory<Interface2> {\n        private Scoping scoping;\n        ImplementationInterface2Factory(Scoping scoping) { this.scoping = scoping; }\n        @Override public Interface2 create(Scope scope) { return new Implementation(); }\n        @Override public Scoping getScoping() { return this.scoping; }\n        @Override public Class[] getSiblingTypes() {\n            return new Class[]{Interface1.class, ImplementationInterface1Factory.class};\n        }\n    }\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/MagnetScopingDirectTest.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Scope;\nimport magnet.Scoping;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.google.common.truth.Truth.assertThat;\n\n@RunWith(JUnit4.class)\npublic class MagnetScopingDirectTest {\n\n    private InstrumentedScope scope1;\n    private InstrumentedScope scope2;\n    private InstrumentedScope scope3;\n\n    @Before\n    public void before() {\n        InstanceManager instanceManager = new StubInstanceManager();\n        scope1 = (InstrumentedScope) new InstrumentedScope(\n            new MagnetScope(null, instanceManager))\n            .bind(Dependency1.class, new Dependency1());\n\n        scope2 = (InstrumentedScope) scope1\n            .createSubscope()\n            .bind(Dependency2.class, new Dependency2());\n\n        scope3 = (InstrumentedScope) scope2\n            .createSubscope()\n            .bind(Dependency3.class, new Dependency3());\n    }\n\n    @Test\n    public void itemOne_Scope1() {\n        // when\n        MenuItem menuItem = scope1.getSingle(MenuItem.class, \"one\");\n\n        // then\n        assertThat(menuItem).isNotNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isNotNull();\n    }\n\n    @Test\n    public void itemOne_Scope2() {\n        // when\n        MenuItem menuItem = scope2.getSingle(MenuItem.class, \"one\");\n\n        // then\n        assertThat(menuItem).isNotNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNotNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n    }\n\n    @Test\n    public void itemOne_Scope3() {\n        // when\n        MenuItem menuItem = scope3.getSingle(MenuItem.class, \"one\");\n\n        // then\n        assertThat(menuItem).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"one\")).isNotNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void itemTwo_Scope1() {\n        // when\n        MenuItem menuItem = scope1.getSingle(MenuItem.class, \"two\");\n    }\n\n    @Test\n    public void itemTwo_Scope2() {\n        // when\n        MenuItem menuItem = scope2.getSingle(MenuItem.class, \"two\");\n\n        // then\n        assertThat(menuItem).isNotNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"two\")).isNotNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n    }\n\n    @Test\n    public void itemTwo_Scope3() {\n        // when\n        MenuItem menuItem = scope3.getSingle(MenuItem.class, \"two\");\n\n        // then\n        assertThat(menuItem).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"two\")).isNotNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void itemThree_Scope1() {\n        // when\n        MenuItem menuItem = scope1.getSingle(MenuItem.class, \"three\");\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void itemThree_Scope2() {\n        // when\n        MenuItem menuItem = scope2.getSingle(MenuItem.class, \"three\");\n    }\n\n    @Test\n    public void itemThree_Scope3() {\n        // when\n        MenuItem menuItem = scope3.getSingle(MenuItem.class, \"three\");\n\n        // then\n        assertThat(menuItem).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"three\")).isNotNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n    }\n\n    private static class MenuItemOneFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(Dependency1.class);\n            return new MenuItemOne();\n        }\n        @Override public Scoping getScoping() { return Scoping.DIRECT; }\n    }\n\n    private static class MenuItemTwoFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(MenuItem.class, \"one\");\n            scope.getSingle(Dependency2.class);\n            return new MenuItemTwo();\n        }\n        @Override public Scoping getScoping() { return Scoping.DIRECT; }\n    }\n\n    private static class MenuItemThreeFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(MenuItem.class, \"two\");\n            scope.getSingle(Dependency3.class);\n            return new MenuItemThree();\n        }\n        @Override public Scoping getScoping() { return Scoping.DIRECT; }\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static class StubInstanceManager implements InstanceManager {\n        private final Map<String, InstanceFactory<MenuItem>> factories;\n\n        StubInstanceManager() {\n            factories = new HashMap<>();\n            factories.put(\"one\", new MenuItemOneFactory());\n            factories.put(\"two\", new MenuItemTwoFactory());\n            factories.put(\"three\", new MenuItemThreeFactory());\n        }\n\n        @Override\n        public <T> InstanceFactory getInstanceFactory(\n            Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType\n        ) {\n            throw new UnsupportedOperationException();\n        }\n        @Override public <T> InstanceFactory<T> getFilteredInstanceFactory(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            return (InstanceFactory<T>) factories.get(classifier);\n        }\n        @Override public <T> List<InstanceFactory<T>> getManyInstanceFactories(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n    private interface MenuItem {}\n\n    private static class MenuItemOne implements MenuItem {}\n    private static class MenuItemTwo implements MenuItem {}\n    private static class MenuItemThree implements MenuItem {}\n\n    private static class Dependency1 {}\n    private static class Dependency2 {}\n    private static class Dependency3 {}\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/MagnetScopingNoneTest.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Scope;\nimport magnet.Scoping;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.google.common.truth.Truth.assertThat;\n\n@RunWith(JUnit4.class)\npublic class MagnetScopingNoneTest {\n\n    private InstrumentedScope scope1;\n    private InstrumentedScope scope2;\n    private InstrumentedScope scope3;\n\n    @Before\n    public void before() {\n        InstanceManager instanceManager = new StubInstanceManager();\n        scope1 = (InstrumentedScope) new InstrumentedScope(\n            new MagnetScope(null, instanceManager))\n            .bind(Dependency1.class, new Dependency1());\n\n        scope2 = (InstrumentedScope) scope1\n            .createSubscope()\n            .bind(Dependency2.class, new Dependency2());\n\n        scope3 = (InstrumentedScope) scope2\n            .createSubscope()\n            .bind(Dependency3.class, new Dependency3());\n    }\n\n    @Test\n    public void itemOne_requestedWithinScope1() {\n        // when\n        MenuItem menuItem = scope1.getSingle(MenuItem.class, \"one\");\n\n        // then\n        assertThat(menuItem).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n    }\n\n    @Test\n    public void itemOne_requestedWithinScope2() {\n        // when\n        MenuItem menuItem = scope2.getSingle(MenuItem.class, \"one\");\n\n        // then\n        assertThat(menuItem).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n    }\n\n    @Test\n    public void itemOne_requestedWithinScope3() {\n        // when\n        MenuItem menuItem = scope3.getSingle(MenuItem.class, \"one\");\n\n        // then\n        assertThat(menuItem).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void itemTwo_requestedWithinScope1() {\n        // when\n        scope1.getSingle(MenuItem.class, \"two\");\n    }\n\n    @Test\n    public void itemTwo_requestedWithinScope2() {\n        // when\n        MenuItem menuItem = scope2.getSingle(MenuItem.class, \"two\");\n\n        // then\n        assertThat(menuItem).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"two\")).isEqualTo(menuItem);\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n    }\n\n    @Test\n    public void itemTwo_requestedWithinScope3() {\n        // when\n        MenuItem menuItem = scope3.getSingle(MenuItem.class, \"two\");\n\n        // then\n        assertThat(menuItem).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"two\")).isEqualTo(menuItem);\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void itemThree_requestedWithinScope1() {\n        // when\n        scope1.getSingle(MenuItem.class, \"three\");\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void itemThree_requestedWithinScope2() {\n        // when\n        scope2.getSingle(MenuItem.class, \"three\");\n    }\n\n    @Test\n    public void itemThree_requestedWithinScope3() {\n        // when\n        MenuItem menuItem = scope3.getSingle(MenuItem.class, \"three\");\n\n        // then\n        assertThat(menuItem).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"two\")).isNotNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n    }\n\n    private static class MenuItemOneFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(Dependency1.class);\n            return new MenuItemOne();\n        }\n        @Override public Scoping getScoping() { return Scoping.UNSCOPED; }\n    }\n\n    private static class MenuItemTwoFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(Dependency1.class);\n            scope.getSingle(Dependency2.class);\n            scope.getSingle(MenuItem.class, \"one\");\n            return new MenuItemTwo();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class MenuItemThreeFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(Dependency1.class);\n            scope.getSingle(Dependency3.class);\n            scope.getSingle(MenuItem.class, \"one\");\n            scope.getSingle(MenuItem.class, \"two\");\n            return new MenuItemThree();\n        }\n        @Override public Scoping getScoping() { return Scoping.UNSCOPED; }\n    }\n\n    private static class StubInstanceManager implements InstanceManager {\n        private final Map<String, InstanceFactory<MenuItem>> factories;\n\n        StubInstanceManager() {\n            factories = new HashMap<>();\n            factories.put(\"one\", new MenuItemOneFactory());\n            factories.put(\"two\", new MenuItemTwoFactory());\n            factories.put(\"three\", new MenuItemThreeFactory());\n        }\n\n        @Override\n        public <T> InstanceFactory getInstanceFactory(\n            Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType\n        ) {\n            throw new UnsupportedOperationException();\n        }\n        @Override public <T> InstanceFactory<T> getFilteredInstanceFactory(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            //noinspection unchecked\n            return (InstanceFactory<T>) factories.get(classifier);\n        }\n        @Override public <T> List<InstanceFactory<T>> getManyInstanceFactories(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n    private interface MenuItem {}\n    private static class MenuItemOne implements MenuItem {}\n    private static class MenuItemTwo implements MenuItem {}\n    private static class MenuItemThree implements MenuItem {}\n\n    private static class Dependency1 {}\n    private static class Dependency2 {}\n    private static class Dependency3 {}\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/MagnetScopingTopmostDependsOnDirectTest.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Scope;\nimport magnet.Scoping;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.google.common.truth.Truth.assertThat;\n\n@RunWith(JUnit4.class)\npublic class MagnetScopingTopmostDependsOnDirectTest {\n\n    private InstrumentedScope scope1;\n    private InstrumentedScope scope2;\n    private InstrumentedScope scope3;\n\n    @Before\n    public void before() {\n        InstanceManager instanceManager = new StubInstanceManager();\n\n        scope1 = new InstrumentedScope(new MagnetScope(null, instanceManager));\n        scope2 = (InstrumentedScope) scope1.createSubscope();\n        scope3 = (InstrumentedScope) scope2.createSubscope();\n    }\n\n    private interface MenuItem {}\n\n    private static class MenuItemZero implements MenuItem {}\n    private static class MenuItemOne implements MenuItem {}\n    private static class MenuItemTwo implements MenuItem {}\n    private static class MenuItemThree implements MenuItem {}\n\n    private static class MenuItemZeroFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            return new MenuItemZero();\n        }\n        @Override public Scoping getScoping() { return Scoping.DIRECT; }\n    }\n\n    private static class MenuItemOneFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            return new MenuItemOne();\n        }\n        @Override public Scoping getScoping() { return Scoping.DIRECT; }\n    }\n\n    private static class MenuItemTwoFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(MenuItem.class, \"one\");\n            return new MenuItemTwo();\n        }\n        @Override public Scoping getScoping() { return Scoping.DIRECT; }\n    }\n\n    private static class MenuItemThreeFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(MenuItem.class, \"two\");\n            return new MenuItemThree();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    @Test\n    public void itemThree_getSingleInScope3() {\n        // when\n        MenuItem item = scope3.getSingle(MenuItem.class, \"three\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"three\")).isEqualTo(item);\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n    }\n\n    @Test\n    public void itemThree_getSingleInScope2() {\n        // when\n        MenuItem item = scope2.getSingle(MenuItem.class, \"three\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"three\")).isEqualTo(item);\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n    }\n\n    @Test\n    public void itemThree_getSingleInScope1() {\n        // when\n        MenuItem item = scope1.getSingle(MenuItem.class, \"three\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"three\")).isEqualTo(item);\n    }\n\n    private static class StubInstanceManager implements InstanceManager {\n        private final Map<String, InstanceFactory<MenuItem>> factories;\n\n        StubInstanceManager() {\n            factories = new HashMap<>();\n            factories.put(\"zero\", new MenuItemZeroFactory());\n            factories.put(\"one\", new MenuItemOneFactory());\n            factories.put(\"two\", new MenuItemTwoFactory());\n            factories.put(\"three\", new MenuItemThreeFactory());\n        }\n\n        @Override\n        public <T> InstanceFactory getInstanceFactory(\n            Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType\n        ) {\n            throw new UnsupportedOperationException();\n        }\n\n        @Override public <T> InstanceFactory<T> getFilteredInstanceFactory(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            //noinspection unchecked\n            return (InstanceFactory<T>) factories.get(classifier);\n        }\n        @Override public <T> List<InstanceFactory<T>> getManyInstanceFactories(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/MagnetScopingTopmostDependsOnTopmostTest.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Scope;\nimport magnet.Scoping;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.google.common.truth.Truth.assertThat;\n\n@RunWith(JUnit4.class)\npublic class MagnetScopingTopmostDependsOnTopmostTest {\n\n    private InstrumentedScope scope1;\n    private InstrumentedScope scope2;\n    private InstrumentedScope scope3;\n\n    @Before\n    public void before() {\n        InstanceManager instanceManager = new StubInstanceManager();\n\n        scope1 = (InstrumentedScope) new InstrumentedScope(\n            new MagnetScope(null, instanceManager))\n            .bind(Dependency1.class, new Dependency1());\n\n        scope2 = (InstrumentedScope) scope1\n            .createSubscope()\n            .bind(Dependency2.class, new Dependency2());\n\n        scope3 = (InstrumentedScope) scope2\n            .createSubscope()\n            .bind(Dependency3.class, new Dependency3());\n    }\n\n    private interface MenuItem {}\n\n    private static class MenuItemZero implements MenuItem {}\n    private static class MenuItemOne implements MenuItem {}\n    private static class MenuItemTwo implements MenuItem {}\n    private static class MenuItemThree implements MenuItem {}\n\n    private static class Dependency1 {}\n    private static class Dependency2 {}\n    private static class Dependency3 {}\n\n    private static class MenuItemZeroFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            return new MenuItemZero();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class MenuItemOneFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(Dependency1.class);\n            return new MenuItemOne();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class MenuItemTwoFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(Dependency2.class);\n            scope.getSingle(MenuItem.class, \"one\");\n            return new MenuItemTwo();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    private static class MenuItemThreeFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(Dependency3.class);\n            scope.getSingle(MenuItem.class, \"two\");\n            return new MenuItemThree();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    @Test\n    public void itemZero_getSingleInScope3() {\n        // when\n        MenuItem item = scope3.getSingle(MenuItem.class, \"zero\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"zero\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"zero\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"zero\")).isEqualTo(item);\n    }\n\n    @Test\n    public void itemZero_getSingleInScope2() {\n        // when\n        MenuItem item = scope2.getSingle(MenuItem.class, \"zero\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"zero\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"zero\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"zero\")).isEqualTo(item);\n    }\n\n    @Test\n    public void itemZero_getSingleInScope1() {\n        // when\n        MenuItem item = scope1.getSingle(MenuItem.class, \"zero\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"zero\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"zero\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"zero\")).isEqualTo(item);\n    }\n\n    @Test\n    public void itemOne_getSingleInScope3() {\n        // when\n        MenuItem item = scope3.getSingle(MenuItem.class, \"one\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isEqualTo(item);\n    }\n\n    @Test\n    public void itemOne_getSingleInScope2() {\n        // when\n        MenuItem item = scope2.getSingle(MenuItem.class, \"one\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isEqualTo(item);\n    }\n\n    @Test\n    public void itemOne_getSingleInScope1() {\n        // when\n        MenuItem item = scope1.getSingle(MenuItem.class, \"one\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isEqualTo(item);\n    }\n\n    @Test\n    public void itemTwo_getSingleInScope3() {\n        // when\n        MenuItem item = scope3.getSingle(MenuItem.class, \"two\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"two\")).isEqualTo(item);\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isNotNull();\n    }\n\n    @Test\n    public void itemTwo_getSingleInScope2() {\n        // when\n        MenuItem item = scope2.getSingle(MenuItem.class, \"two\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"two\")).isEqualTo(item);\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isNotNull();\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void itemTwo_getSingleInScope1() {\n        // when\n        scope1.getSingle(MenuItem.class, \"two\");\n    }\n\n    @Test\n    public void itemThree_getSingleInScope3() {\n        // when\n        MenuItem item = scope3.getSingle(MenuItem.class, \"three\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"three\")).isEqualTo(item);\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"two\")).isNotNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"two\")).isNull();\n\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"one\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"one\")).isNotNull();\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void itemThree_getSingleInScope2() {\n        // when\n        scope2.getSingle(MenuItem.class, \"three\");\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void itemThree_getSingleInScope1() {\n        // when\n        scope1.getSingle(MenuItem.class, \"three\");\n    }\n\n    private static class StubInstanceManager implements InstanceManager {\n        private final Map<String, InstanceFactory<MenuItem>> factories;\n\n        StubInstanceManager() {\n            factories = new HashMap<>();\n            factories.put(\"zero\", new MenuItemZeroFactory());\n            factories.put(\"one\", new MenuItemOneFactory());\n            factories.put(\"two\", new MenuItemTwoFactory());\n            factories.put(\"three\", new MenuItemThreeFactory());\n        }\n\n        @Override\n        public <T> InstanceFactory getInstanceFactory(\n            Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType\n        ) {\n            throw new UnsupportedOperationException();\n        }\n\n        @Override public <T> InstanceFactory<T> getFilteredInstanceFactory(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            //noinspection unchecked\n            return (InstanceFactory<T>) factories.get(classifier);\n        }\n        @Override public <T> List<InstanceFactory<T>> getManyInstanceFactories(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/MagnetScopingTopmostDependsOnUnscopedTest.java",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.internal;\n\nimport magnet.Scope;\nimport magnet.Scoping;\nimport org.junit.Before;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\n\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.google.common.truth.Truth.assertThat;\n\n@RunWith(JUnit4.class)\npublic class MagnetScopingTopmostDependsOnUnscopedTest {\n\n    private InstrumentedScope scope1;\n    private InstrumentedScope scope2;\n    private InstrumentedScope scope3;\n\n    @Before\n    public void before() {\n        InstanceManager instanceManager = new StubInstanceManager();\n\n        scope1 = new InstrumentedScope(new MagnetScope(null, instanceManager));\n        scope2 = (InstrumentedScope) scope1.createSubscope();\n        scope3 = (InstrumentedScope) scope2.createSubscope();\n    }\n\n    private interface MenuItem {}\n\n    private static class MenuItemZero implements MenuItem {}\n    private static class MenuItemOne implements MenuItem {}\n    private static class MenuItemTwo implements MenuItem {}\n    private static class MenuItemThree implements MenuItem {}\n\n    private static class MenuItemZeroFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            return new MenuItemZero();\n        }\n        @Override public Scoping getScoping() { return Scoping.UNSCOPED; }\n    }\n\n    private static class MenuItemOneFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            return new MenuItemOne();\n        }\n        @Override public Scoping getScoping() { return Scoping.UNSCOPED; }\n    }\n\n    private static class MenuItemTwoFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(MenuItem.class, \"one\");\n            return new MenuItemTwo();\n        }\n        @Override public Scoping getScoping() { return Scoping.UNSCOPED; }\n    }\n\n    private static class MenuItemThreeFactory extends InstanceFactory<MenuItem> {\n        @Override public MenuItem create(Scope scope) {\n            scope.getSingle(MenuItem.class, \"two\");\n            return new MenuItemThree();\n        }\n        @Override public Scoping getScoping() { return Scoping.TOPMOST; }\n    }\n\n    @Test\n    public void itemThree_getSingleInScope3() {\n        // when\n        MenuItem item = scope3.getSingle(MenuItem.class, \"three\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"three\")).isEqualTo(item);\n    }\n\n    @Test\n    public void itemThree_getSingleInScope2() {\n        // when\n        MenuItem item = scope2.getSingle(MenuItem.class, \"three\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"three\")).isEqualTo(item);\n    }\n\n    @Test\n    public void itemThree_getSingleInScope1() {\n        // when\n        MenuItem item = scope1.getSingle(MenuItem.class, \"three\");\n\n        // then\n        assertThat(item).isNotNull();\n        assertThat(scope3.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n        assertThat(scope2.getOptionalInScope(MenuItem.class, \"three\")).isNull();\n        assertThat(scope1.getOptionalInScope(MenuItem.class, \"three\")).isEqualTo(item);\n    }\n\n    private static class StubInstanceManager implements InstanceManager {\n        private final Map<String, InstanceFactory<MenuItem>> factories;\n\n        StubInstanceManager() {\n            factories = new HashMap<>();\n            factories.put(\"zero\", new MenuItemZeroFactory());\n            factories.put(\"one\", new MenuItemOneFactory());\n            factories.put(\"two\", new MenuItemTwoFactory());\n            factories.put(\"three\", new MenuItemThreeFactory());\n        }\n\n        @Override\n        public <T> InstanceFactory getInstanceFactory(\n            Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType\n        ) {\n            throw new UnsupportedOperationException();\n        }\n\n        @Override public <T> InstanceFactory<T> getFilteredInstanceFactory(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            //noinspection unchecked\n            return (InstanceFactory<T>) factories.get(classifier);\n        }\n        @Override public <T> List<InstanceFactory<T>> getManyInstanceFactories(\n            Class<T> type, String classifier, FactoryFilter factoryFilter\n        ) {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/Scope_GetManyAnySiblingTypesTest_Issue95.java",
    "content": "package magnet.internal;\n\nimport magnet.Scope;\nimport magnet.internal.observer.ScopeObserver;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\nimport org.mockito.Mock;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\n\n@RunWith(JUnit4.class)\npublic class Scope_GetManyAnySiblingTypesTest_Issue95 {\n\n    @Mock private Scope scopeA;\n    @Mock private Scope scopeB;\n\n    @Test\n    public void test() {\n        // given\n        scopeA = InternalFactory\n                .createRootScope(new MapInstanceManager())\n                .bind(Bound1.class, new Bound1());\n\n        scopeB = scopeA\n                .createSubscope()\n                .bind(Bound3.class, new Bound3());\n\n        // when\n        scopeB.getSingle(Dep2Sibling.class);\n        scopeB.getSingle(Dep1.class);\n\n        // then\n        ScopeObserver observer = new ScopeObserver();\n        scopeA.accept(observer, Integer.MAX_VALUE);\n\n        observer.assetThat(scopeA).hasInstanceTypes(Bound1.class);\n        observer.assetThat(scopeB).hasInstanceTypes(\n                Bound3.class, Dep1.class, Dep2.class, Dep2Sibling.class, Dep3.class\n        );\n    }\n\n    @SuppressWarnings(\"unchecked\") private static class MapInstanceManager implements InstanceManager {\n        private HashMap<Class, InstanceFactory> factories = new HashMap<>();\n\n        MapInstanceManager() {\n            factories.put(\n                    Scope_GetManyAnySiblingTypesTest_Issue95.Dep1.class,\n                    new Scope_GetManyAnySiblingTypesTest_Issue95.Dep1Factory()\n            );\n            factories.put(\n                    Scope_GetManyAnySiblingTypesTest_Issue95.Dep2.class,\n                    new Scope_GetManyAnySiblingTypesTest_Issue95.Dep2Factory()\n            );\n            factories.put(\n                    Scope_GetManyAnySiblingTypesTest_Issue95.Dep2Sibling.class,\n                    new Scope_GetManyAnySiblingTypesTest_Issue95.Dep2SiblingFactory()\n            );\n            factories.put(\n                    Scope_GetManyAnySiblingTypesTest_Issue95.Dep3.class,\n                    new Scope_GetManyAnySiblingTypesTest_Issue95.Dep3Factory()\n            );\n        }\n\n        @Override @Nullable public <T> InstanceFactory<T> getInstanceFactory(\n                Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType) {\n            return factories.get(instanceType);\n        }\n\n        @Override @Nullable public <T> InstanceFactory<T> getFilteredInstanceFactory(\n                Class<T> type, String classifier, FactoryFilter factoryFilter) {\n            return factories.get(type);\n        }\n\n        @Override public <T> @NotNull List<InstanceFactory<T>> getManyInstanceFactories(\n                Class<T> type, String classifier, FactoryFilter factoryFilter) {\n            List<InstanceFactory<T>> list = new ArrayList<>();\n            list.add(factories.get(type));\n            return list;\n        }\n    }\n\n    private static class Dep1 {}\n    private static class Dep1Factory extends InstanceFactory<Dep1> {\n        @Override public Dep1 create(Scope scope) {\n            scope.getSingle(Bound1.class);\n            scope.getMany(Dep2.class);\n            return new Dep1();\n        }\n    }\n\n    private interface Dep2 {}\n    private static class Dep2Factory extends InstanceFactory<Dep2> {\n        @Override public Dep2 create(Scope scope) {\n            scope.getSingle(Dep3.class);\n            return new Scope_GetManyAnySiblingTypesTest_Issue95.Dep2Impl();\n        }\n        @Override public Class[] getSiblingTypes() {\n            return new Class[] { Dep2Sibling.class, Scope_GetManyAnySiblingTypesTest_Issue95.Dep2SiblingFactory.class };\n        }\n    }\n\n    private interface Dep2Sibling {}\n    private static class Dep2SiblingFactory extends InstanceFactory<Dep2Sibling> {\n        @Override public Dep2Sibling create(Scope scope) {\n            scope.getSingle(Dep3.class);\n            return new Scope_GetManyAnySiblingTypesTest_Issue95.Dep2Impl();\n        }\n        @Override public Class[] getSiblingTypes() {\n            return new Class[] { Dep2.class, Scope_GetManyAnySiblingTypesTest_Issue95.Dep2Factory.class };\n        }\n    }\n\n    private static class Dep2Impl implements Dep2, Dep2Sibling { }\n\n    private static class Dep3 {}\n    private static class Dep3Factory extends InstanceFactory<Dep3> {\n        @Override public Dep3 create(Scope scope) {\n            scope.getSingle(Bound3.class);\n            return new Dep3();\n        }\n    }\n\n    private static class Bound1 {}\n    private static class Bound3 {}\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/Scope_LimitDirectScoping_DependencyInNonReachableChildScopeTest.java",
    "content": "package magnet.internal;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\nimport org.mockito.Mock;\n\nimport java.util.HashMap;\nimport java.util.List;\n\nimport magnet.Scope;\nimport magnet.Scoping;\n\n@RunWith(JUnit4.class)\npublic class Scope_LimitDirectScoping_DependencyInNonReachableChildScopeTest {\n\n    // Scopes: A <- B<limit> <- C { Bound2 }\n    // Instances: DIRECT Dep1<limit> -> Dep2 -> Bound2\n\n    public @Rule ExpectedException expected = ExpectedException.none();\n\n    private final static String LIMIT = \"limit\";\n\n    private @Mock Scope scopeA;\n    private @Mock Scope scopeB;\n    private @Mock Scope scopeC;\n\n    @Test\n    public void test() {\n        expected.expect(IllegalStateException.class);\n        expected.expectMessage(\"non-reachable child scope\");\n\n        // given\n        scopeA = InternalFactory.createRootScope(new HashMapInstanceManager());\n        scopeB = scopeA.createSubscope().limit(LIMIT);\n        scopeC = scopeB.createSubscope().bind(Bound2.class, new Bound2());\n\n        // when\n        scopeC.getSingle(Dep1.class);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static class HashMapInstanceManager implements InstanceManager {\n        private HashMap<Class, InstanceFactory> factories = new HashMap<>();\n\n        HashMapInstanceManager() {\n            factories.put(Dep1.class, new Dep1Factory());\n            factories.put(Dep2.class, new Dep2Factory());\n        }\n\n        @Override public <T> @Nullable InstanceFactory<T> getInstanceFactory(\n            Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType) {\n            return factories.get(instanceType);\n        }\n\n        @Override public <T> @Nullable InstanceFactory<T> getFilteredInstanceFactory(\n            Class<T> type, String classifier, FactoryFilter factoryFilter) {\n            return factories.get(type);\n        }\n\n        @Override public <T> @NotNull List<InstanceFactory<T>> getManyInstanceFactories(\n            Class<T> type, String classifier, FactoryFilter factoryFilter) {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n    private static class Bound2 {}\n    private static class Dep1 {}\n\n    private static class Dep1Factory extends InstanceFactory<Dep1> {\n        @Override public Dep1 create(Scope scope) {\n            scope.getSingle(Dep2.class);\n            return new Dep1();\n        }\n\n        @Override public Scoping getScoping() { return Scoping.DIRECT; }\n        @Override public String getLimit() { return LIMIT; }\n    }\n\n    private static class Dep2 {}\n    private static class Dep2Factory extends InstanceFactory<Dep2> {\n        @Override public Dep2 create(Scope scope) {\n            scope.getSingle(Bound2.class);\n            return new Dep2();\n        }\n    }\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/Scope_LimitDirectScoping_InstanceWithDependencyTest.java",
    "content": "package magnet.internal;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\nimport org.mockito.Mock;\n\nimport java.util.HashMap;\nimport java.util.List;\n\nimport magnet.Scope;\nimport magnet.Scoping;\nimport magnet.internal.observer.ScopeObserver;\n\n@RunWith(JUnit4.class)\npublic class Scope_LimitDirectScoping_InstanceWithDependencyTest {\n\n    // Scopes: A <- B<limit> <- C { Bound2 }\n    // Instances: Dep2 -> { DIRECT Dep1<limit>, Bound2 }\n\n    public @Rule ExpectedException expected = ExpectedException.none();\n\n    private final static String LIMIT = \"limit\";\n\n    private @Mock Scope scopeA;\n    private @Mock Scope scopeB;\n    private @Mock Scope scopeC;\n\n    @Test\n    public void test_GetFromUnderLimitedScope() {\n        // given\n        scopeA = InternalFactory.createRootScope(new HashMapInstanceManager());\n        scopeB = scopeA.createSubscope().limit(LIMIT);\n        scopeC = scopeB.createSubscope().bind(Bound2.class, new Bound2());\n\n        // when\n        scopeC.getSingle(Dep2.class);\n\n        // then\n        ScopeObserver observer = new ScopeObserver();\n        scopeA.accept(observer, Integer.MAX_VALUE);\n        observer.assetThat(scopeA).hasNoInstances();\n        observer.assetThat(scopeB).hasInstanceTypes(Dep1.class);\n        observer.assetThat(scopeC).hasInstanceTypes(Bound2.class, Dep2.class);\n    }\n\n    @Test\n    public void test_GetFromLimitedScope() {\n        expected.expect(IllegalStateException.class);\n        expected.expectMessage(\"not found in scopes\");\n\n        // given\n        scopeA = InternalFactory.createRootScope(new HashMapInstanceManager());\n        scopeB = scopeA.createSubscope().limit(LIMIT);\n        scopeC = scopeB.createSubscope().bind(Bound2.class, new Bound2());\n\n        // when\n        scopeB.getSingle(Dep2.class);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static class HashMapInstanceManager implements InstanceManager {\n        private HashMap<Class, InstanceFactory> factories = new HashMap<>();\n\n        HashMapInstanceManager() {\n            factories.put(Dep1.class, new Dep1Factory());\n            factories.put(Dep2.class, new Dep2Factory());\n        }\n\n        @Override public <T> @Nullable InstanceFactory<T> getInstanceFactory(\n            Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType) {\n            return factories.get(instanceType);\n        }\n\n        @Override public <T> @Nullable InstanceFactory<T> getFilteredInstanceFactory(\n            Class<T> type, String classifier, FactoryFilter factoryFilter) {\n            return factories.get(type);\n        }\n\n        @Override public <T> @NotNull List<InstanceFactory<T>> getManyInstanceFactories(\n            Class<T> type, String classifier, FactoryFilter factoryFilter) {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n    private static class Bound2 {}\n\n    private static class Dep1 {}\n    private static class Dep1Factory extends InstanceFactory<Dep1> {\n        @Override public Dep1 create(Scope scope) { return new Dep1(); }\n        @Override public Scoping getScoping() { return Scoping.DIRECT; }\n        @Override public String getLimit() { return LIMIT; }\n    }\n\n    private static class Dep2 {}\n    private static class Dep2Factory extends InstanceFactory<Dep2> {\n        @Override public Dep2 create(Scope scope) {\n            scope.getSingle(Dep1.class);\n            scope.getSingle(Bound2.class);\n            return new Dep2();\n        }\n    }\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/Scope_LimitDirectScoping_SingleInstanceTest.java",
    "content": "package magnet.internal;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\nimport org.junit.Rule;\nimport org.junit.Test;\nimport org.junit.rules.ExpectedException;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\nimport org.mockito.Mock;\n\nimport java.util.HashMap;\nimport java.util.List;\n\nimport magnet.Scope;\nimport magnet.Scoping;\nimport magnet.internal.observer.ScopeObserver;\n\n@RunWith(JUnit4.class)\npublic class Scope_LimitDirectScoping_SingleInstanceTest {\n\n    // Scopes: A <- B<limit> <- C\n    // Instances: DIRECT Dep1<limit>\n\n    public @Rule ExpectedException expected = ExpectedException.none();\n\n    private final static String LIMIT = \"limit\";\n\n    private @Mock Scope scopeA;\n    private @Mock Scope scopeB;\n    private @Mock Scope scopeC;\n\n    @Test\n    public void test_GetFromUnderLimitedScope() {\n        // given\n        scopeA = InternalFactory.createRootScope(new HashMapInstanceManager());\n        scopeB = scopeA.createSubscope().limit(LIMIT);\n        scopeC = scopeB.createSubscope();\n\n        // when\n        scopeC.getSingle(Dep1.class);\n\n        // then\n        ScopeObserver observer = new ScopeObserver();\n        scopeA.accept(observer, Integer.MAX_VALUE);\n        observer.assetThat(scopeA).hasNoInstances();\n        observer.assetThat(scopeB).hasInstanceTypes(Dep1.class);\n        observer.assetThat(scopeC).hasNoInstances();\n    }\n\n    @Test\n    public void test_GetFromLimitedScope() {\n        // given\n        scopeA = InternalFactory.createRootScope(new HashMapInstanceManager());\n        scopeB = scopeA.createSubscope().limit(LIMIT);\n        scopeC = scopeB.createSubscope();\n\n        // when\n        scopeB.getSingle(Dep1.class);\n\n        // then\n        ScopeObserver observer = new ScopeObserver();\n        scopeA.accept(observer, Integer.MAX_VALUE);\n        observer.assetThat(scopeA).hasNoInstances();\n        observer.assetThat(scopeB).hasInstanceTypes(Dep1.class);\n        observer.assetThat(scopeC).hasNoInstances();\n    }\n\n    @Test\n    public void test_GetFromAboveLimitedScope() {\n        expected.expect(IllegalStateException.class);\n        expected.expectMessage(\"no scope with limit\");\n\n        // given\n        scopeA = InternalFactory.createRootScope(new HashMapInstanceManager());\n        scopeB = scopeA.createSubscope().limit(LIMIT);\n        scopeC = scopeB.createSubscope();\n\n        // when\n        scopeA.getSingle(Dep1.class);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static class HashMapInstanceManager implements InstanceManager {\n        private HashMap<Class, InstanceFactory> factories = new HashMap<>();\n\n        HashMapInstanceManager() {\n            factories.put(Dep1.class, new Dep1Factory());\n        }\n\n        @Override public <T> @Nullable InstanceFactory<T> getInstanceFactory(\n            Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType) {\n            return factories.get(instanceType);\n        }\n\n        @Override public <T> @Nullable InstanceFactory<T> getFilteredInstanceFactory(\n            Class<T> type, String classifier, FactoryFilter factoryFilter) {\n            return factories.get(type);\n        }\n\n        @Override public <T> @NotNull List<InstanceFactory<T>> getManyInstanceFactories(\n            Class<T> type, String classifier, FactoryFilter factoryFilter) {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n    private static class Dep1 {}\n    private static class Dep1Factory extends InstanceFactory<Dep1> {\n        @Override public Dep1 create(Scope scope) { return new Dep1(); }\n        @Override public Scoping getScoping() { return Scoping.DIRECT; }\n        @Override public String getLimit() { return LIMIT; }\n    }\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/Scope_LimitTest.java",
    "content": "package magnet.internal;\n\nimport magnet.Scope;\nimport magnet.internal.observer.ScopeObserver;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\nimport org.mockito.Mock;\n\nimport java.util.HashMap;\nimport java.util.List;\n\n@RunWith(JUnit4.class)\npublic class Scope_LimitTest {\n\n    private final static String LIMIT = \"limit\";\n\n    @Mock private Scope scopeA;\n    @Mock private Scope scopeB;\n    @Mock private Scope scopeC;\n\n    @Test\n    public void test_limitedInstance_settlesInLimitedSameScope() {\n        // given\n        scopeA = InternalFactory.createRootScope(new HashMapInstanceManager());\n        scopeB = scopeA.createSubscope();\n        scopeC = scopeB.createSubscope().limit(LIMIT);\n\n        // when\n        scopeC.getSingle(Limited.class);\n\n        // then\n        ScopeObserver observer = new ScopeObserver();\n        scopeA.accept(observer, Integer.MAX_VALUE);\n        observer.assetThat(scopeA).hasNoInstances();\n        observer.assetThat(scopeB).hasNoInstances();\n        observer.assetThat(scopeC).hasInstanceTypes(Limited.class);\n    }\n\n    @Test\n    public void test_limitedInstance_settlesInLimitedUpperScope() {\n        // given\n        scopeA = InternalFactory.createRootScope(new HashMapInstanceManager());\n        scopeB = scopeA.createSubscope().limit(LIMIT);\n        scopeC = scopeB.createSubscope();\n\n        // when\n        scopeC.getSingle(Limited.class);\n\n        // then\n        ScopeObserver observer = new ScopeObserver();\n        scopeA.accept(observer, Integer.MAX_VALUE);\n        observer.assetThat(scopeA).hasNoInstances();\n        observer.assetThat(scopeB).hasInstanceTypes(Limited.class);\n        observer.assetThat(scopeC).hasNoInstances();\n    }\n\n    @Test\n    public void test_limitedInstance_settlesInLimitedTopScope() {\n        // given\n        scopeA = InternalFactory.createRootScope(new HashMapInstanceManager()).limit(LIMIT);\n        scopeB = scopeA.createSubscope();\n        scopeC = scopeB.createSubscope();\n\n        // when\n        scopeC.getSingle(Limited.class);\n\n        // then\n        ScopeObserver observer = new ScopeObserver();\n        scopeA.accept(observer, Integer.MAX_VALUE);\n        observer.assetThat(scopeA).hasInstanceTypes(Limited.class);\n        observer.assetThat(scopeB).hasNoInstances();\n        observer.assetThat(scopeC).hasNoInstances();\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void test_limitedInstance_fails_ifNoLimitFound() {\n        // given\n        scopeA = InternalFactory.createRootScope(new HashMapInstanceManager());\n        scopeB = scopeA.createSubscope();\n        scopeC = scopeB.createSubscope();\n\n        // when\n        scopeC.getSingle(Limited.class);\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void test_limitedInstance_fails_ifQueriedAtParentUnlimitedScope() {\n        // given\n        scopeA = InternalFactory.createRootScope(new HashMapInstanceManager());\n        scopeB = scopeA.createSubscope().limit(LIMIT);\n\n        // when\n        scopeA.getSingle(Limited.class);\n    }\n\n    @Test(expected = IllegalStateException.class)\n    public void test_limitedInstance_fails_ifNoMatchingLimitFound() {\n        // given\n        scopeA = InternalFactory.createRootScope(new HashMapInstanceManager());\n        scopeB = scopeA.createSubscope().limit(\"limit-two\");\n        scopeC = scopeB.createSubscope().limit(\"limit-one\");\n\n        // when\n        scopeC.getSingle(Limited.class);\n    }\n\n    @Test\n    public void test_unlimitedInstance_ignoresLimits_settlesInUnlimitedTopScope() {\n        // given\n        scopeA = InternalFactory.createRootScope(new HashMapInstanceManager());\n        scopeB = scopeA.createSubscope().limit(\"limit-two\");\n        scopeC = scopeB.createSubscope().limit(\"limit-one\");\n\n        // when\n        scopeC.getSingle(Unlimited.class);\n\n        // then\n        ScopeObserver observer = new ScopeObserver();\n        scopeA.accept(observer, Integer.MAX_VALUE);\n        observer.assetThat(scopeA).hasInstanceTypes(Unlimited.class);\n        observer.assetThat(scopeB).hasNoInstances();\n        observer.assetThat(scopeC).hasNoInstances();\n    }\n\n    @SuppressWarnings(\"unchecked\") private static class HashMapInstanceManager implements InstanceManager {\n        private HashMap<Class, InstanceFactory> factories = new HashMap<>();\n\n        HashMapInstanceManager() {\n            factories.put(Limited.class, new LimitedFactory());\n            factories.put(Unlimited.class, new UnlimitedFactory());\n        }\n\n        @Override @Nullable public <T> InstanceFactory<T> getInstanceFactory(\n            Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType) {\n            return factories.get(instanceType);\n        }\n\n        @Override @Nullable public <T> InstanceFactory<T> getFilteredInstanceFactory(\n            Class<T> type, String classifier, FactoryFilter factoryFilter) {\n            return factories.get(type);\n        }\n\n        @Override public <T> @NotNull List<InstanceFactory<T>> getManyInstanceFactories(\n            Class<T> type, String classifier, FactoryFilter factoryFilter) {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n    private static class Limited {}\n    private static class LimitedFactory extends InstanceFactory<Limited> {\n        @Override public Limited create(Scope scope) { return new Limited(); }\n        @Override public String getLimit() { return LIMIT; }\n    }\n\n    private static class Unlimited {}\n    private static class UnlimitedFactory extends InstanceFactory<Unlimited> {\n        @Override public Unlimited create(Scope scope) { return new Unlimited(); }\n    }\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/Scope_LimitWithDependencyTest.java",
    "content": "package magnet.internal;\n\nimport magnet.Scope;\nimport magnet.internal.observer.ScopeObserver;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.junit.runners.JUnit4;\nimport org.mockito.Mock;\n\nimport java.util.HashMap;\nimport java.util.List;\n\n@RunWith(JUnit4.class)\npublic class Scope_LimitWithDependencyTest {\n\n    private final static String LIMIT_ONE = \"limit-one\";\n    private final static String LIMIT_TWO = \"limit-two\";\n\n    @Mock private Scope scopeA;\n    @Mock private Scope scopeB;\n    @Mock private Scope scopeC;\n    @Mock private Scope scopeD;\n\n    @Test\n    public void test_dependingInstance_respectsDependencyLimit() {\n        // given\n        scopeA = InternalFactory.createRootScope(new MapInstanceManager());\n        scopeB = scopeA.createSubscope().limit(LIMIT_ONE);\n        scopeC = scopeB.createSubscope();\n        scopeD = scopeC.createSubscope().limit(LIMIT_TWO);\n\n        // when\n        scopeD.getSingle(LimitedOne.class);\n\n        // then\n        ScopeObserver observer = new ScopeObserver();\n        scopeA.accept(observer, Integer.MAX_VALUE);\n        observer.assetThat(scopeA).hasNoInstances();\n        observer.assetThat(scopeB).hasNoInstances();\n        observer.assetThat(scopeC).hasNoInstances();\n        observer.assetThat(scopeD).hasInstanceTypes(LimitedOne.class, LimitedTwo.class);\n    }\n\n    @Test\n    public void test_dependingInstance_respectsOwnLimit() {\n        // given\n        scopeA = InternalFactory.createRootScope(new MapInstanceManager());\n        scopeB = scopeA.createSubscope().limit(LIMIT_TWO);\n        scopeC = scopeB.createSubscope();\n        scopeD = scopeC.createSubscope().limit(LIMIT_ONE);\n\n        // when\n        scopeD.getSingle(LimitedOne.class);\n\n        // then\n        ScopeObserver observer = new ScopeObserver();\n        scopeA.accept(observer, Integer.MAX_VALUE);\n        observer.assetThat(scopeA).hasNoInstances();\n        observer.assetThat(scopeB).hasInstanceTypes(LimitedTwo.class);\n        observer.assetThat(scopeC).hasNoInstances();\n        observer.assetThat(scopeD).hasInstanceTypes(LimitedOne.class);\n    }\n\n    @Test\n    public void test_dependingInstance_isCollocatedWithDependency() {\n        // given\n        scopeA = InternalFactory.createRootScope(new MapInstanceManager());\n        scopeB = scopeA.createSubscope().limit(LIMIT_ONE, LIMIT_TWO);\n        scopeC = scopeB.createSubscope();\n\n        // when\n        scopeC.getSingle(LimitedOne.class);\n\n        // then\n        ScopeObserver observer = new ScopeObserver();\n        scopeA.accept(observer, Integer.MAX_VALUE);\n        observer.assetThat(scopeA).hasNoInstances();\n        observer.assetThat(scopeB).hasInstanceTypes(LimitedOne.class, LimitedTwo.class);\n        observer.assetThat(scopeC).hasNoInstances();\n    }\n\n    @SuppressWarnings(\"unchecked\") private static class MapInstanceManager implements InstanceManager {\n        private HashMap<Class, InstanceFactory> factories = new HashMap<>();\n\n        MapInstanceManager() {\n            factories.put(LimitedOne.class, new LimitedOneFactory());\n            factories.put(LimitedTwo.class, new LimitedTwoFactory());\n        }\n\n        @Override @Nullable public <T> InstanceFactory<T> getInstanceFactory(\n            Class<T> instanceType, String classifier, Class<InstanceFactory<T>> factoryType) {\n            return factories.get(instanceType);\n        }\n\n        @Override @Nullable public <T> InstanceFactory<T> getFilteredInstanceFactory(\n            Class<T> type, String classifier, FactoryFilter factoryFilter) {\n            return factories.get(type);\n        }\n\n        @Override public <T> @NotNull List<InstanceFactory<T>> getManyInstanceFactories(\n            Class<T> type, String classifier, FactoryFilter factoryFilter) {\n            throw new UnsupportedOperationException();\n        }\n    }\n\n    private static class LimitedOne {}\n    private static class LimitedOneFactory extends InstanceFactory<LimitedOne> {\n        @Override public LimitedOne create(Scope scope) {\n            scope.getSingle(LimitedTwo.class);\n            return new LimitedOne();\n        }\n        @Override public String getLimit() { return LIMIT_ONE; }\n    }\n\n    private static class LimitedTwo {}\n    private static class LimitedTwoFactory extends InstanceFactory<LimitedTwo> {\n        @Override public LimitedTwo create(Scope scope) { return new LimitedTwo(); }\n        @Override public String getLimit() { return LIMIT_TWO; }\n    }\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/VisitInstancesTest.java",
    "content": "package magnet.internal;\n\nimport magnet.Classifier;\nimport magnet.Magnet;\nimport magnet.Scope;\nimport magnet.Scoping;\nimport magnet.Visitor;\nimport magnet.internal.events.ObservableScopeVisitor;\nimport magnet.internal.events.OnEnterScope;\nimport magnet.internal.events.OnExitScope;\nimport magnet.internal.events.OnInstance;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static com.google.common.truth.Truth.assertThat;\nimport static magnet.Visitor.Provision.BOUND;\nimport static magnet.Visitor.Provision.INJECTED;\n\npublic class VisitInstancesTest {\n\n    private InstrumentedScope scopeA;\n    private InstrumentedScope scopeB;\n\n    private Bound bound = new Bound();\n    private Bound boundA = new Bound();\n    private Bound boundB = new Bound();\n    private String classifierA = \"classifierA\";\n    private String classifierB = \"classifierB\";\n\n    private InjectedTopMost injectedTopMost = new InjectedTopMost();\n    private InjectedTopMostFactory injectedTopMostFactory = new InjectedTopMostFactory();\n\n    private InjectedDirect injectedDirect = new InjectedDirect();\n    private InjectedDirectFactory injectedDirectFactory = new InjectedDirectFactory();\n\n    private ObservableScopeVisitor visitor;\n\n    @Before\n    public void before() {\n        scopeA = (InstrumentedScope) new InstrumentedScope(Magnet.createRootScope())\n            .instrumentObjectIntoScope(injectedTopMostFactory, InjectedTopMost.class, injectedTopMost, Classifier.NONE)\n            .instrumentObjectIntoScope(injectedTopMostFactory, InjectedTopMost.class, injectedTopMost, classifierA)\n            .instrumentObjectIntoScope(injectedTopMostFactory, InjectedTopMost.class, injectedTopMost, classifierB)\n            .bind(Bound.class, bound)\n            .bind(Bound.class, boundA, classifierA);\n\n        scopeB = (InstrumentedScope) ((InstrumentedScope) scopeA.createSubscope())\n            .instrumentObjectIntoScope(injectedDirectFactory, InjectedDirect.class, injectedDirect, Classifier.NONE)\n            .bind(Bound.class, boundB, classifierB);\n    }\n\n    @Test\n    public void visitAllScopes() {\n        visitor = new ObservableScopeVisitor();\n        scopeA.accept(visitor, Integer.MAX_VALUE);\n\n        assertThat(visitor.visited).containsExactly(\n            new OnEnterScope(scopeA.scope, null),\n            new OnInstance(BOUND, Bound.class, bound, Classifier.NONE, Scoping.DIRECT),\n            new OnInstance(BOUND, Bound.class, boundA, classifierA, Scoping.DIRECT),\n            new OnInstance(INJECTED, InjectedTopMost.class, injectedTopMost, Classifier.NONE, Scoping.TOPMOST),\n            new OnInstance(INJECTED, InjectedTopMost.class, injectedTopMost, classifierA, Scoping.TOPMOST),\n            new OnInstance(INJECTED, InjectedTopMost.class, injectedTopMost, classifierB, Scoping.TOPMOST),\n            new OnEnterScope(scopeB.scope, scopeA.scope),\n            new OnInstance(BOUND, Bound.class, boundB, classifierB, Scoping.DIRECT),\n            new OnInstance(INJECTED, InjectedDirect.class, injectedDirect, Classifier.NONE, Scoping.DIRECT),\n            new OnExitScope(scopeB.scope),\n            new OnExitScope(scopeA.scope)\n        ).inOrder();\n    }\n\n    @Test\n    public void visitRootScope() {\n        visitor = new ObservableScopeVisitor();\n        scopeA.accept(visitor, 0);\n        assertThat(visitor.visited).containsExactly(\n            new OnEnterScope(scopeA.scope, null),\n            new OnInstance(BOUND, Bound.class, bound, Classifier.NONE, Scoping.DIRECT),\n            new OnInstance(BOUND, Bound.class, boundA, classifierA, Scoping.DIRECT),\n            new OnInstance(INJECTED, InjectedTopMost.class, injectedTopMost, Classifier.NONE, Scoping.TOPMOST),\n            new OnInstance(INJECTED, InjectedTopMost.class, injectedTopMost, classifierA, Scoping.TOPMOST),\n            new OnInstance(INJECTED, InjectedTopMost.class, injectedTopMost, classifierB, Scoping.TOPMOST),\n            new OnExitScope(scopeA.scope)\n        );\n    }\n\n    @Test\n    public void visitScope_onEnterScope_skipAllInstances() {\n        visitor = new ObservableScopeVisitor() {\n            @Override\n            public boolean onEnterScope(@NotNull Visitor.Scope scope, @Nullable Visitor.Scope parent) {\n                super.onEnterScope(scope, parent);\n                return false;\n            }\n        };\n        scopeA.accept(visitor, 0);\n\n        assertThat(visitor.visited).containsExactly(\n            new OnEnterScope(scopeA.scope, null),\n            new OnExitScope(scopeA.scope)\n        ).inOrder();\n    }\n\n    @Test\n    public void visitScope_onInstance_skipAfterSecondInstance() {\n        visitor = new ObservableScopeVisitor() {\n            private int count = 0;\n\n            @Override\n            public boolean onInstance(@NotNull Instance instance) {\n                super.onInstance(instance);\n                return ++count < 2;\n            }\n        };\n        scopeA.accept(visitor, Integer.MAX_VALUE);\n\n        assertThat(visitor.visited).containsExactly(\n            new OnEnterScope(scopeA.scope, null),\n            new OnInstance(INJECTED, InjectedTopMost.class, injectedTopMost, classifierA, Scoping.TOPMOST),\n            new OnInstance(INJECTED, InjectedTopMost.class, injectedTopMost, classifierB, Scoping.TOPMOST),\n            new OnExitScope(scopeA.scope)\n        ).inOrder();\n    }\n\n    private static class Bound {}\n\n    private static class InjectedTopMost {}\n\n    private static class InjectedDirect {}\n\n    private class InjectedTopMostFactory extends InstanceFactory<InjectedTopMost> {\n        @Override public InjectedTopMost create(Scope scope) {\n            return injectedTopMost;\n        }\n    }\n\n    private class InjectedDirectFactory extends InstanceFactory<InjectedDirect> {\n        @Override public InjectedDirect create(Scope scope) {\n            return injectedDirect;\n        }\n\n        @Override public Scoping getScoping() {\n            return Scoping.DIRECT;\n        }\n    }\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/VisitScopesTest.java",
    "content": "package magnet.internal;\n\nimport magnet.Magnet;\nimport magnet.Scope;\nimport magnet.internal.events.ObservableScopeVisitor;\nimport magnet.internal.events.OnEnterScope;\nimport magnet.internal.events.OnExitScope;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static com.google.common.truth.Truth.assertThat;\n\npublic class VisitScopesTest {\n\n    private Scope scopeA;\n    private Scope scopeB;\n    private Scope scopeB1;\n    private Scope scopeB2;\n    private Scope scopeC;\n\n    private ObservableScopeVisitor visitor = new ObservableScopeVisitor();\n\n    @Before\n    public void before() {\n        scopeA = Magnet.createRootScope();\n        scopeB = scopeA.createSubscope();\n        scopeB1 = scopeB.createSubscope();\n        scopeB2 = scopeB.createSubscope();\n        scopeC = scopeA.createSubscope();\n    }\n\n    @Test\n    public void visitRootScope_DepthUnlimited() {\n        scopeA.accept(visitor, Integer.MAX_VALUE);\n        assertThat(visitor.visited).containsExactly(\n            new OnEnterScope(scopeA, null),\n            new OnEnterScope(scopeC, scopeA),\n            new OnExitScope(scopeC),\n            new OnEnterScope(scopeB, scopeA),\n            new OnEnterScope(scopeB2, scopeB),\n            new OnExitScope(scopeB2),\n            new OnEnterScope(scopeB1, scopeB),\n            new OnExitScope(scopeB1),\n            new OnExitScope(scopeB),\n            new OnExitScope(scopeA)\n        ).inOrder();\n    }\n\n    @Test\n    public void visitRootScope_Depth0() {\n        scopeA.accept(visitor, 0);\n        assertThat(visitor.visited).containsExactly(\n            new OnEnterScope(scopeA, null),\n            new OnExitScope(scopeA)\n        ).inOrder();\n    }\n\n    @Test\n    public void visitRootScope_Depth1() {\n        scopeA.accept(visitor, 1);\n        assertThat(visitor.visited).containsExactly(\n            new OnEnterScope(scopeA, null),\n            new OnEnterScope(scopeC, scopeA),\n            new OnExitScope(scopeC),\n            new OnEnterScope(scopeB, scopeA),\n            new OnExitScope(scopeB),\n            new OnExitScope(scopeA)\n        ).inOrder();\n    }\n\n    @Test\n    public void visitChildScope_Depth0() {\n        scopeB.accept(visitor, 0);\n        assertThat(visitor.visited).containsExactly(\n            new OnEnterScope(scopeB, scopeA),\n            new OnExitScope(scopeB)\n        ).inOrder();\n    }\n\n    @Test\n    public void visitChildScope_Depth1() {\n        scopeB.accept(visitor, 1);\n        assertThat(visitor.visited).containsExactly(\n            new OnEnterScope(scopeB, scopeA),\n            new OnEnterScope(scopeB2, scopeB),\n            new OnExitScope(scopeB2),\n            new OnEnterScope(scopeB1, scopeB),\n            new OnExitScope(scopeB1),\n            new OnExitScope(scopeB)\n        ).inOrder();\n    }\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/events/ObservableScopeVisitor.java",
    "content": "package magnet.internal.events;\n\nimport magnet.Visitor;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class ObservableScopeVisitor implements Visitor {\n\n    public List<Object> visited = new ArrayList<>();\n    private List<OnInstance> instances = new ArrayList<>();\n\n    @Override\n    public boolean onEnterScope(@NotNull Visitor.Scope scope, @Nullable Visitor.Scope parent) {\n        flushInstances();\n        visited.add(new OnEnterScope(scope, parent));\n        return true;\n    }\n\n    @Override\n    public boolean onInstance(@NotNull Instance instance) {\n        instances.add(new OnInstance(instance));\n        return true;\n    }\n\n    @Override\n    public void onExitScope(@NotNull Visitor.Scope scope) {\n        flushInstances();\n        visited.add(new OnExitScope(scope));\n    }\n\n    private void flushInstances() {\n        if (instances.size() > 0) {\n            Collections.sort(instances);\n            visited.addAll(instances);\n            instances.clear();\n        }\n    }\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/events/OnEnterScope.java",
    "content": "package magnet.internal.events;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.Objects;\n\npublic class OnEnterScope {\n    private final @NotNull Object scope;\n    private final @Nullable Object parent;\n\n    public OnEnterScope(@NotNull Object scope, @Nullable Object parent) {\n        this.scope = scope;\n        this.parent = parent;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        OnEnterScope that = (OnEnterScope) o;\n        return scope.equals(that.scope) &&\n            Objects.equals(parent, that.parent);\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(scope, parent);\n    }\n\n    @Override\n    public String toString() {\n        return \"OnEnterScope: \" + scope;\n    }\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/events/OnExitScope.java",
    "content": "package magnet.internal.events;\n\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.Objects;\n\npublic class OnExitScope {\n    private final @NotNull Object scope;\n\n    public OnExitScope(@NotNull Object scope) {\n        this.scope = scope;\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        OnExitScope that = (OnExitScope) o;\n        return scope.equals(that.scope);\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(scope);\n    }\n\n    @Override\n    public String toString() {\n        return \"OnExitScope: \" + scope;\n    }\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/events/OnInstance.java",
    "content": "package magnet.internal.events;\n\nimport magnet.Scoping;\nimport magnet.Visitor.Instance;\nimport magnet.Visitor.Provision;\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.Objects;\n\npublic class OnInstance implements Comparable<OnInstance> {\n    private final Provision provision;\n    private final Class<?> type;\n    private final Object object;\n    private final String classifier;\n    private final Scoping scoping;\n\n    OnInstance(Instance object) {\n        this.provision = object.getProvision();\n        this.type = object.getType();\n        this.object = object.getValue();\n        this.classifier = object.getClassifier();\n        this.scoping = object.getScoping();\n    }\n\n    public OnInstance(\n        Provision provision,\n        Class<?> type,\n        Object object,\n        String classifier,\n        Scoping scoping\n    ) {\n        this.provision = provision;\n        this.type = type;\n        this.object = object;\n        this.classifier = classifier;\n        this.scoping = scoping;\n    }\n\n    @Override public boolean equals(Object o) {\n        if (this == o) return true;\n        if (o == null || getClass() != o.getClass()) return false;\n        OnInstance that = (OnInstance) o;\n        return provision == that.provision &&\n            type.equals(that.type) &&\n            object.equals(that.object) &&\n            classifier.equals(that.classifier) &&\n            scoping == that.scoping;\n    }\n\n    @Override public int hashCode() {\n        return Objects.hash(provision, type, object, classifier, scoping);\n    }\n\n    @Override public String toString() {\n        return \"OnInstance{ \"\n            + provision + \" \"\n            + scoping + \" \"\n            + type.getSimpleName() + \"@\" + (classifier.length() == 0 ? \"NONE\" : classifier) + \" }\";\n    }\n\n    @Override public int compareTo(@NotNull OnInstance o) {\n        return provision.compareTo(o.provision) * 100\n            + type.getName().compareTo(o.type.getName()) * 10\n            + classifier.compareTo(o.classifier);\n    }\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/observer/ScopeObserver.java",
    "content": "package magnet.internal.observer;\n\nimport magnet.Visitor;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.Comparator;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\nimport static com.google.common.truth.Truth.assertThat;\n\npublic class ScopeObserver implements Visitor {\n\n    @NotNull private final Map<Object, DefaultScopeValidator> validators = new HashMap<>();\n    @Nullable private DefaultScopeValidator currentScopeValidator;\n\n    @Override\n    public boolean onEnterScope(@NotNull Visitor.Scope scope, @Nullable Visitor.Scope parent) {\n        flushScope();\n        currentScopeValidator = new DefaultScopeValidator(scope);\n        return true;\n    }\n\n    @Override\n    public boolean onInstance(@NotNull Instance instance) {\n        if (currentScopeValidator != null) {\n            currentScopeValidator.addInstance(instance);\n        }\n        return true;\n    }\n\n    @Override\n    public void onExitScope(@NotNull Visitor.Scope scope) {\n        flushScope();\n    }\n\n    private void flushScope() {\n        if (currentScopeValidator != null) {\n            //noinspection Java8ListSort,Convert2Lambda\n            Collections.sort(currentScopeValidator.instances, new Comparator<Instance>() {\n                @Override public int compare(Instance o1, Instance o2) {\n                    return o1.getType().getName().compareTo(o2.getType().getName());\n                }\n            });\n            validators.put(currentScopeValidator.scope, currentScopeValidator);\n        }\n    }\n\n    public ScopeValidator assetThat(magnet.Scope scopeA) {\n        ScopeValidator validator = validators.get(scopeA);\n        if (validator == null) {\n            throw new IllegalStateException(\n                String.format(\"Scope %s was not observed\", scopeA)\n            );\n        }\n        return validator;\n    }\n\n    private static class DefaultScopeValidator implements ScopeValidator {\n        private final List<Instance> instances = new ArrayList<>();\n        private Scope scope;\n\n        DefaultScopeValidator(Scope scope) {\n            this.scope = scope;\n        }\n\n        void addInstance(Instance instance) {\n            instances.add(instance);\n        }\n\n        @Override public void hasNoInstances() {\n            assertThat(instances.size()).isEqualTo(0);\n        }\n\n        @Override public void hasInstanceTypes(Class<?>... instanceTypes) {\n            if (instances.size() != instanceTypes.length) {\n                throw new IllegalStateException(\n                    String.format(\n                        \"Expect %s number of instances in %s, while found %s. Actual instances: %s\",\n                        instanceTypes.length, scope, instances.size(), instances.toString()\n                    )\n                );\n            }\n\n            for (int i = 0; i < instances.size(); i++) {\n                if (!instances.get(i).getType().equals(instanceTypes[i])) {\n                    throw new IllegalStateException(\n                        String.format(\n                            \"Expect %s at position %s, while found %s. Actual instances: %s\",\n                            instanceTypes[i], i, instances.get(i), instances.toString()\n                        )\n                    );\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "magnet/src/test/java/magnet/internal/observer/ScopeValidator.java",
    "content": "package magnet.internal.observer;\n\npublic interface ScopeValidator {\n    void hasNoInstances();\n    void hasInstanceTypes(Class<?>... instanceTypes);\n}\n"
  },
  {
    "path": "magnet/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker",
    "content": "mock-maker-inline"
  },
  {
    "path": "magnet-kotlin/build.gradle",
    "content": "plugins {\n    id 'kotlin'\n    id 'com.vanniktech.maven.publish'\n}\n\ncompileKotlin {\n    kotlinOptions {\n        jvmTarget = javaVersion\n    }\n}\n\ncompileTestKotlin {\n    kotlinOptions {\n        jvmTarget = javaVersion\n    }\n}\n\ndependencies {\n    api project(':magnet')\n    implementation deps.kotlinjdk\n\n    testImplementation deps.junit\n    testImplementation deps.truth\n    testImplementation deps.mockito\n    testImplementation deps.mockitoKotlin\n}\n"
  },
  {
    "path": "magnet-kotlin/gradle.properties",
    "content": "POM_NAME=Magnet Runtime Kotlin Extensions\nPOM_ARTIFACT_ID=magnet-kotlin\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "magnet-kotlin/src/main/java/magnet/MagnetExt.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet\n\n/** Creates new root scope and initializes it using given init-function. */\ninline fun createRootScope(init: Scope.() -> Unit): Scope =\n    Magnet.createRootScope().apply(init)\n\n/** Creates new root scope. */\nfun createRootScope(): Scope =\n    Magnet.createRootScope()\n"
  },
  {
    "path": "magnet-kotlin/src/main/java/magnet/ScopeExt.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet\n\n/** Returns an object from the scope or `null`, if object was not found. */\ninline fun <reified T> Scope.getOptional(classifier: String = Classifier.NONE): T? =\n    this.getOptional(T::class.java, classifier)\n\n/** Returns an object from the scope or throws exception, if object was not found. */\ninline fun <reified T> Scope.getSingle(classifier: String = Classifier.NONE): T =\n    this.getSingle(T::class.java, classifier)\n\n/** Returns a list of objects or empty list, if no objects were found. */\ninline fun <reified T> Scope.getMany(classifier: String = Classifier.NONE): List<T> =\n    this.getMany(T::class.java, classifier)\n\n/** Bind given instance into this scope. */\ninline fun <reified T : Any> Scope.bind(instance: T, classifier: String = Classifier.NONE) =\n    this.bind(T::class.java, instance, classifier)\n\n/** Creates a subscope of the current scope. */\ninline fun Scope.createSubscope(init: Scope.() -> Unit): Scope =\n    this.createSubscope().apply(init)\n"
  },
  {
    "path": "magnet-kotlin/src/main/java/magnet/internal/ManyLazy.kt",
    "content": "/*\n * Copyright (C) 2019 Sergej Shafarenka, www.halfbit.de\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 magnet.internal\n\nimport magnet.Scope\nimport java.util.concurrent.atomic.AtomicBoolean\n\nclass ManyLazy<T : Any>(\n    private val scope: Scope,\n    private val type: Class<T>,\n    private val classifier: String\n) : Lazy<List<T>> {\n    private val initialized = AtomicBoolean(false)\n    private lateinit var _value: List<T>\n\n    override val value: List<T>\n        get() {\n            if (!initialized.getAndSet(true)) {\n                _value = scope.getMany(type, classifier)\n            }\n            return _value\n        }\n\n    override fun isInitialized(): Boolean = initialized.get()\n}\n"
  },
  {
    "path": "magnet-kotlin/src/main/java/magnet/internal/OptionalLazy.kt",
    "content": "/*\n * Copyright (C) 2019 Sergej Shafarenka, www.halfbit.de\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 magnet.internal\n\nimport magnet.Scope\nimport java.util.concurrent.atomic.AtomicBoolean\n\nclass OptionalLazy<T>(\n    private val scope: Scope,\n    private val type: Class<T>,\n    private val classifier: String\n) : Lazy<T?> {\n    private val initialized = AtomicBoolean(false)\n    private var _value: T? = null\n\n    override val value: T?\n        get() {\n            if (!initialized.getAndSet(true)) {\n                _value = scope.getOptional(type, classifier)\n            }\n            return _value\n        }\n\n    override fun isInitialized(): Boolean = initialized.get()\n}\n"
  },
  {
    "path": "magnet-kotlin/src/main/java/magnet/internal/SingleLazy.kt",
    "content": "/*\n * Copyright (C) 2019 Sergej Shafarenka, www.halfbit.de\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 magnet.internal\n\nimport magnet.Scope\nimport java.util.concurrent.atomic.AtomicBoolean\n\nclass SingleLazy<T : Any>(\n    private val scope: Scope,\n    private val type: Class<T>,\n    private val classifier: String\n) : Lazy<T> {\n    private val initialized = AtomicBoolean(false)\n    private lateinit var _value: T\n\n    override val value: T\n        get() {\n            if (!initialized.getAndSet(true)) {\n                _value = scope.getSingle(type, classifier)\n            }\n            return _value\n        }\n\n    override fun isInitialized(): Boolean = initialized.get()\n}\n"
  },
  {
    "path": "magnet-kotlin/src/test/java/magnet/kotlin/ScopeExtTest.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.kotlin\n\nimport magnet.Classifier\nimport magnet.Scope\nimport magnet.bind\nimport magnet.getOptional\nimport magnet.getSingle\nimport org.junit.Test\nimport org.junit.runner.RunWith\nimport org.mockito.Mock\nimport org.mockito.Mockito.any\nimport org.mockito.Mockito.anyString\nimport org.mockito.Mockito.verify\nimport org.mockito.junit.MockitoJUnitRunner\nimport org.mockito.Mockito.`when` as on\n\n@Suppress(\"UNUSED_VARIABLE\")\n@RunWith(MockitoJUnitRunner.StrictStubs::class)\nclass ScopeExtTest {\n\n    @Mock\n    lateinit var scope: Scope\n\n    @Test\n    fun testGet() {\n        // when\n        val value: String? = scope.getOptional<String>()\n\n        // then\n        verify(scope).getOptional(String::class.java, Classifier.NONE)\n    }\n\n    @Test\n    fun testRequire() {\n        // when\n        val value = scope.getSingle<String>()\n\n        // then\n        verify(scope).getSingle(String::class.java, Classifier.NONE)\n    }\n\n    @Test\n    fun testRegister() {\n        // given\n        on(scope.bind(any(Class::class.java), any(), anyString())).thenReturn(scope)\n\n        // when\n        scope.bind(\"component\")\n\n        // then\n        verify(scope).bind(String::class.java, \"component\", Classifier.NONE)\n    }\n\n}"
  },
  {
    "path": "magnet-kotlin/src/test/java/magnet/kotlin/internal/ManyLazyTest.kt",
    "content": "package magnet.kotlin.internal\n\nimport com.google.common.truth.Truth.assertThat\nimport org.mockito.kotlin.mock\nimport org.mockito.kotlin.never\nimport org.mockito.kotlin.same\nimport org.mockito.kotlin.verify\nimport magnet.Scope\nimport magnet.internal.ManyLazy\nimport org.junit.Test\n\nclass ManyLazyTest {\n\n    private val value = listOf(\"value\")\n    private val type = String::class.java\n    private val classifier = \"classifier\"\n    private val scope: Scope = mock {\n        on { getMany(same(type), same(classifier)) }.thenReturn(value)\n    }\n\n    private val underTest: Lazy<List<String>> = ManyLazy(scope, type, classifier)\n\n    @Test\n    fun `Constructor doesn't call scope_getMany()`() {\n        verify(scope, never()).getMany(type, classifier)\n    }\n\n    @Test\n    fun `value calls scope_getMany()`() {\n        underTest.value\n        verify(scope).getMany(type, classifier)\n    }\n\n    @Test\n    fun `value calls scope_getMany() once`() {\n        underTest.value\n        underTest.value\n        verify(scope).getMany(type, classifier)\n    }\n\n    @Test\n    fun `value returns value`() {\n        assertThat(underTest.value).isSameInstanceAs(value)\n    }\n\n    @Test\n    fun `isInitialized() returns false when not initialized`() {\n        assertThat(underTest.isInitialized()).isFalse()\n    }\n\n    @Test\n    fun `isInitialized() returns true when initialized`() {\n        underTest.value\n        assertThat(underTest.isInitialized()).isTrue()\n    }\n}"
  },
  {
    "path": "magnet-kotlin/src/test/java/magnet/kotlin/internal/OptionalLazyTest.kt",
    "content": "package magnet.kotlin.internal\n\nimport com.google.common.truth.Truth.assertThat\nimport org.mockito.kotlin.mock\nimport org.mockito.kotlin.never\nimport org.mockito.kotlin.same\nimport org.mockito.kotlin.verify\nimport magnet.Scope\nimport magnet.internal.OptionalLazy\nimport org.junit.Test\n\nclass OptionalLazyTest {\n\n    private val value = \"value\"\n    private val type = String::class.java\n    private val classifier = \"classifier\"\n    private val scope: Scope = mock {\n        on { getOptional(same(type), same(classifier)) }.thenReturn(value)\n    }\n\n    private val underTest: Lazy<String?> = OptionalLazy(scope, type, classifier)\n\n    @Test\n    fun `Constructor doesn't call scope_getOptional()`() {\n        verify(scope, never()).getOptional(type, classifier)\n    }\n\n    @Test\n    fun `value calls scope_getOptional()`() {\n        underTest.value\n        verify(scope).getOptional(type, classifier)\n    }\n\n    @Test\n    fun `value calls scope_getOptional() once`() {\n        underTest.value\n        underTest.value\n        verify(scope).getOptional(type, classifier)\n    }\n\n    @Test\n    fun `value returns value`() {\n        assertThat(underTest.value).isSameInstanceAs(value)\n    }\n\n    @Test\n    fun `isInitialized() returns false when not initialized`() {\n        assertThat(underTest.isInitialized()).isFalse()\n    }\n\n    @Test\n    fun `isInitialized() returns true when initialized`() {\n        underTest.value\n        assertThat(underTest.isInitialized()).isTrue()\n    }\n}"
  },
  {
    "path": "magnet-kotlin/src/test/java/magnet/kotlin/internal/SingleLazyTest.kt",
    "content": "package magnet.kotlin.internal\n\nimport com.google.common.truth.Truth.assertThat\nimport org.mockito.kotlin.mock\nimport org.mockito.kotlin.never\nimport org.mockito.kotlin.same\nimport org.mockito.kotlin.verify\nimport magnet.Scope\nimport magnet.internal.SingleLazy\nimport org.junit.Test\n\nclass SingleLazyTest {\n\n    private val value = \"value\"\n    private val type = String::class.java\n    private val classifier = \"classifier\"\n    private val scope: Scope = mock {\n        on { getSingle(same(type), same(classifier)) }.thenReturn(value)\n    }\n\n    private val underTest: Lazy<String> = SingleLazy(scope, type, classifier)\n\n    @Test\n    fun `Constructor doesn't call scope_getSingle()`() {\n        verify(scope, never()).getSingle(type, classifier)\n    }\n\n    @Test\n    fun `value calls scope_getSingle()`() {\n        underTest.value\n        verify(scope).getSingle(type, classifier)\n    }\n\n    @Test\n    fun `value calls scope_getSingle() once`() {\n        underTest.value\n        underTest.value\n        verify(scope).getSingle(type, classifier)\n    }\n\n    @Test\n    fun `value returns value`() {\n        assertThat(underTest.value).isSameInstanceAs(value)\n    }\n\n    @Test\n    fun `isInitialized() returns false when not initialized`() {\n        assertThat(underTest.isInitialized()).isFalse()\n    }\n\n    @Test\n    fun `isInitialized() returns true when initialized`() {\n        underTest.value\n        assertThat(underTest.isInitialized()).isTrue()\n    }\n}"
  },
  {
    "path": "magnet-processor/build.gradle",
    "content": "plugins {\n    id 'kotlin'\n    id 'com.vanniktech.maven.publish'\n}\n\ncompileKotlin {\n    kotlinOptions {\n        jvmTarget = javaVersion\n    }\n}\n\ncompileTestKotlin {\n    kotlinOptions {\n        jvmTarget = javaVersion\n    }\n}\n\nif (JavaVersion.current() >= JavaVersion.VERSION_16) {\n    test {\n        jvmArgs(\n                // used\n                \"--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED\",\n                \"--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED\",\n                \"--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED\",\n                // the others\n                \"--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED\",\n                \"--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED\",\n                \"--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED\",\n                \"--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED\",\n                \"--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED\",\n                \"--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED\",\n                \"--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED\",\n        )\n    }\n}\n\ndependencies {\n    implementation project(':magnet')\n    implementation project(':magnet-kotlin')\n    implementation deps.kotlinjdk\n    implementation deps.kotlinMetadata\n    implementation deps.javapoet\n\n    testImplementation deps.compileTesting\n    testImplementation deps.jsr305\n    testImplementation files(file(\"libs/tools.jar\"))\n}\n"
  },
  {
    "path": "magnet-processor/gradle.properties",
    "content": "POM_NAME=Magnet Annotation Processor\nPOM_ARTIFACT_ID=magnet-processor\nPOM_PACKAGING=jar"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/MagnetProcessor.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.processor\n\nimport magnet.Instance\nimport magnet.Registry\nimport magnet.Scope\nimport magnet.processor.common.AnnotationValueExtractor\nimport magnet.processor.common.CompilationException\nimport magnet.processor.common.ValidationException\nimport magnet.processor.instances.InstanceProcessor\nimport magnet.processor.registry.RegistryProcessor\nimport javax.annotation.processing.*\nimport javax.lang.model.SourceVersion\nimport javax.lang.model.element.TypeElement\nimport javax.lang.model.util.Elements\nimport javax.lang.model.util.Types\nimport javax.tools.Diagnostic\n\n@SupportedSourceVersion(SourceVersion.RELEASE_11)\nclass MagnetProcessor : AbstractProcessor() {\n\n    private lateinit var env: MagnetProcessorEnv\n    private lateinit var instanceProcessor: InstanceProcessor\n    private lateinit var registryProcessor: RegistryProcessor\n\n    override fun init(processingEnvironment: ProcessingEnvironment) {\n        super.init(processingEnvironment)\n        env = MagnetProcessorEnv(processingEnvironment)\n        instanceProcessor = InstanceProcessor(env)\n        registryProcessor = RegistryProcessor(env)\n    }\n\n    override fun process(\n        annotations: MutableSet<out TypeElement>,\n        roundEnv: RoundEnvironment\n    ): Boolean {\n        return try {\n            val instancesProcessed = instanceProcessor.process(roundEnv)\n            val registryProcessed = registryProcessor.process(roundEnv)\n            instancesProcessed || registryProcessed\n        } catch (e: ValidationException) {\n            env.reportError(e)\n            false\n        } catch (e: CompilationException) {\n            env.reportError(e)\n            false\n        } catch (e: Throwable) {\n            env.reportError(e)\n            e.printStackTrace()\n            false\n        }\n    }\n\n    override fun getSupportedAnnotationTypes(): MutableSet<String> {\n        return mutableSetOf(\n            Instance::class.java.name,\n            Scope::class.java.name,\n            Registry::class.java.name\n        )\n    }\n}\n\nclass MagnetProcessorEnv(\n    private val processEnvironment: ProcessingEnvironment\n) {\n\n    val filer: Filer get() = processEnvironment.filer\n    val elements: Elements get() = processEnvironment.elementUtils\n    val types: Types get() = processEnvironment.typeUtils\n    val annotation = AnnotationValueExtractor(elements)\n\n    fun reportError(e: ValidationException) {\n        processEnvironment.messager.printMessage(Diagnostic.Kind.ERROR, e.message, e.element)\n    }\n\n    fun reportError(e: CompilationException) {\n        processEnvironment.messager.printMessage(\n            Diagnostic.Kind.ERROR,\n            \"Unexpected compilation error,\" +\n                    \" please file the bug at https://github.com/beworker/magnet/issues.\" +\n                    \" Message: ${e.message ?: \"none.\"}\",\n            e.element\n        )\n    }\n\n    fun reportError(e: Throwable) {\n        processEnvironment.messager.printMessage(\n            Diagnostic.Kind.ERROR,\n            \"Unexpected compilation error,\" +\n                    \" please file the bug at https://github.com/beworker/magnet/issues.\" +\n                    \" Message: ${e.message ?: \"none.\"}\"\n        )\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/common/AptUtils.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.common\n\nimport javax.lang.model.element.AnnotationMirror\nimport javax.lang.model.element.AnnotationValue\nimport javax.lang.model.element.Element\nimport javax.lang.model.element.TypeElement\nimport javax.lang.model.type.TypeMirror\nimport javax.lang.model.util.Elements\nimport javax.lang.model.util.SimpleAnnotationValueVisitor6\nimport javax.lang.model.util.Types\n\ninline fun <reified T> AnnotationMirror.isOfAnnotationType(): Boolean =\n    this.annotationType.toString() == T::class.java.name\n\ninline fun <reified A> Element.eachAttributeOf(\n    block: (name: String, value: AnnotationValue) -> Unit\n) {\n    for (annotationMirror in annotationMirrors) {\n        if (annotationMirror.isOfAnnotationType<A>()) {\n            for (entry in annotationMirror.elementValues.entries) {\n                block(entry.key.simpleName.toString(), entry.value)\n            }\n        }\n    }\n}\n\nfun TypeElement.verifyInheritance(element: Element, types: Types) {\n    val isTypeImplemented = types.isAssignable(\n        element.asType(),\n        types.getDeclaredType(this)\n    )\n    if (!isTypeImplemented) {\n        element.throwValidationError(\"$element must implement $this\")\n    }\n}\n\nclass ValidationException(val element: Element, message: String) : Throwable(message)\nclass CompilationException(val element: Element, message: String) : Throwable(message)\n\nfun Element.throwValidationError(message: String): Nothing {\n    throw ValidationException(this, message)\n}\n\nfun Element.throwCompilationError(message: String): Nothing {\n    throw CompilationException(this, message)\n}\n\n@Suppress(\"DEPRECATION\")\nclass AnnotationValueExtractor(\n    private val elements: Elements\n) : SimpleAnnotationValueVisitor6<Void?, Void>() {\n\n    private var value: Any? = null\n\n    override fun visitString(s: String, p: Void?): Void? {\n        value = s\n        return p\n    }\n\n    override fun visitType(t: TypeMirror, p: Void?): Void? {\n        value = elements.getTypeElement(t.toString())\n        return p\n    }\n\n    fun getStringValue(value: AnnotationValue): String {\n        this.value = null\n        value.accept(this, null)\n        return this.value as String\n    }\n\n    fun getTypeElement(value: AnnotationValue): TypeElement {\n        this.value = null\n        value.accept(this, null)\n        return this.value as TypeElement\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/common/KotlinMethodMetadata.kt",
    "content": "/*\n * Copyright (C) 2019-2021 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.common\n\nimport kotlinx.metadata.ClassName\nimport kotlinx.metadata.Flag\nimport kotlinx.metadata.Flags\nimport kotlinx.metadata.KmClassVisitor\nimport kotlinx.metadata.KmConstructorVisitor\nimport kotlinx.metadata.KmFunctionVisitor\nimport kotlinx.metadata.KmPackageVisitor\nimport kotlinx.metadata.KmTypeVisitor\nimport kotlinx.metadata.KmValueParameterVisitor\nimport kotlinx.metadata.KmVariance\nimport kotlinx.metadata.jvm.KotlinClassHeader\nimport kotlinx.metadata.jvm.KotlinClassMetadata\nimport javax.lang.model.element.ExecutableElement\nimport javax.lang.model.element.TypeElement\n\ninterface KotlinMethodMetadata {\n    val method: ExecutableElement\n    fun getTypeMeta(parameterName: String, typeDepth: Int): TypeMeta\n}\n\ndata class ParameterMeta(\n    val name: String,\n    val types: List<TypeMeta>\n)\n\ndata class TypeMeta(\n    val type: String,\n    val nullable: Boolean,\n    val default: Boolean\n)\n\ninterface FunctionSelector {\n    val function: ExecutableElement\n    fun visitFunction(flags: Flags, name: String): Boolean\n    fun acceptFunctionParameters(parameters: Map<String, ParameterMeta>): Map<String, ParameterMeta>\n}\n\ninternal class MethodFunctionSelector(\n    override val function: ExecutableElement\n) : FunctionSelector {\n\n    override fun visitFunction(flags: Flags, name: String) =\n        function.simpleName.toString() == name\n\n    override fun acceptFunctionParameters(parameters: Map<String, ParameterMeta>): Map<String, ParameterMeta> {\n        if (parameters.size != function.parameters.size) {\n            return emptyMap()\n        }\n        return if (function.hasParameters(parameters)) parameters else emptyMap()\n    }\n}\n\nfun ExecutableElement.hasParameters(parameters: Map<String, ParameterMeta>): Boolean {\n    if (parameters.values.size != this.parameters.size) return false\n    parameters.values.forEachIndexed { index, parameterMeta ->\n        if (this.parameters[index].simpleName.toString() != parameterMeta.name) {\n            return false\n        }\n    }\n    return true\n}\n\ninternal class DefaultKotlinMethodMetadata(\n    metadata: Metadata,\n    private val element: TypeElement,\n    private val functionSelector: FunctionSelector\n) : KotlinMethodMetadata {\n\n    override lateinit var method: ExecutableElement\n\n    private val parameterMetas: Map<String, ParameterMeta> =\n        with(metadata) {\n            KotlinClassMetadata.read(\n                KotlinClassHeader(\n                    kind,\n                    metadataVersion,\n                    data1,\n                    data2,\n                    extraString,\n                    packageName,\n                    extraInt\n                )\n            )\n        }.let { kotlinMetadata ->\n            when (kotlinMetadata) {\n                is KotlinClassMetadata.Class ->\n                    AnnotatedClassVisitor(functionSelector).let {\n                        kotlinMetadata.accept(it)\n                        method = functionSelector.function\n                        it.parameters\n                    }\n                is KotlinClassMetadata.FileFacade ->\n                    AnnotatedPackageVisitor(functionSelector).let {\n                        kotlinMetadata.accept(it)\n                        method = functionSelector.function\n                        it.parameters\n                    }\n                else -> throw CompilationException(\n                    element = element,\n                    message = \"Unsupported KotlinClassMetadata of type $kotlinMetadata\"\n                )\n            }\n        }\n\n    override fun getTypeMeta(parameterName: String, typeDepth: Int): TypeMeta {\n        val parameterMeta = parameterMetas[parameterName]\n            ?: element.throwCompilationError(\n                \"Cannot find parameter '$parameterName' in metadata of $element.\" +\n                    \" Available parameters: $parameterMetas\"\n            )\n        if (typeDepth >= parameterMeta.types.size) {\n            element.throwCompilationError(\n                \"Cannot find TypeMeta depth of $typeDepth in ${parameterMeta.types}.\"\n            )\n        }\n        return parameterMeta.types[typeDepth]\n    }\n}\n\nprivate class AnnotatedPackageVisitor(\n    private val functionSelector: FunctionSelector\n) : KmPackageVisitor() {\n    var parameters = emptyMap<String, ParameterMeta>()\n\n    override fun visitFunction(flags: Flags, name: String): KmFunctionVisitor? {\n        return if (functionSelector.visitFunction(flags, name)) {\n            val visitedParameters = mutableMapOf<String, ParameterMeta>()\n\n            object : KmFunctionVisitor() {\n                override fun visitValueParameter(flags: Flags, name: String): KmValueParameterVisitor? {\n                    val valueFlags = flags\n                    return object : KmValueParameterVisitor() {\n                        override fun visitType(flags: Flags): KmTypeVisitor? {\n                            return TypeExtractorVisitor(valueFlags, flags) { typeMeta ->\n                                visitedParameters[name] = ParameterMeta(name, typeMeta)\n                            }\n                        }\n                    }\n                }\n\n                override fun visitEnd() {\n                    parameters = functionSelector.acceptFunctionParameters(visitedParameters)\n                }\n            }\n        } else null\n    }\n}\n\nprivate class AnnotatedClassVisitor(\n    private val functionSelector: FunctionSelector\n) : KmClassVisitor() {\n    var parameters = emptyMap<String, ParameterMeta>()\n\n    override fun visitConstructor(flags: Flags): KmConstructorVisitor? {\n        return if (functionSelector.visitFunction(flags, CONSTRUCTOR_NAME)) {\n            val visitedParameters = mutableMapOf<String, ParameterMeta>()\n\n            object : KmConstructorVisitor() {\n                override fun visitValueParameter(flags: Flags, name: String): KmValueParameterVisitor? {\n                    val valueFlags = flags\n                    return object : KmValueParameterVisitor() {\n                        override fun visitType(flags: Flags): KmTypeVisitor? {\n                            return TypeExtractorVisitor(valueFlags, flags) { typeMeta ->\n                                visitedParameters[name] = ParameterMeta(name, typeMeta)\n                            }\n                        }\n                    }\n                }\n\n                override fun visitEnd() {\n                    parameters = functionSelector.acceptFunctionParameters(visitedParameters)\n                }\n            }\n        } else null\n    }\n\n    override fun visitFunction(flags: Flags, name: String): KmFunctionVisitor? {\n        return if (functionSelector.visitFunction(flags, name)) {\n            val visitedParameters = mutableMapOf<String, ParameterMeta>()\n\n            object : KmFunctionVisitor() {\n                override fun visitValueParameter(flags: Flags, name: String): KmValueParameterVisitor? {\n                    val valueFlags = flags\n                    return object : KmValueParameterVisitor() {\n                        override fun visitType(flags: Flags): KmTypeVisitor? {\n                            return TypeExtractorVisitor(valueFlags, flags) { typeMeta ->\n                                visitedParameters[name] = ParameterMeta(name, typeMeta)\n                            }\n                        }\n                    }\n                }\n\n                override fun visitEnd() {\n                    parameters = functionSelector.acceptFunctionParameters(visitedParameters)\n                }\n            }\n        } else null\n    }\n}\n\nprivate class TypeExtractorVisitor(\n    private val valueFlags: Flags,\n    private val typeFlags: Flags,\n    private val typeMeta: MutableList<TypeMeta> = mutableListOf(),\n    private val onVisitEnd: OnVisitEnd? = null\n) : KmTypeVisitor() {\n\n    override fun visitClass(name: ClassName) {\n        Flag.ValueParameter.DECLARES_DEFAULT_VALUE(valueFlags).let { default ->\n            typeMeta.add(\n                TypeMeta(\n                    type = name,\n                    nullable = Flag.Type.IS_NULLABLE(typeFlags),\n                    default = default\n                )\n            )\n        }\n    }\n\n    override fun visitArgument(flags: Flags, variance: KmVariance): KmTypeVisitor? =\n        TypeExtractorVisitor(valueFlags, flags, typeMeta)\n\n    override fun visitEnd() {\n        onVisitEnd?.invoke(typeMeta)\n    }\n}\n\nconst val CONSTRUCTOR_NAME = \"<init>\"\nprivate typealias OnVisitEnd = (List<TypeMeta>) -> Unit\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/FactoryTypeModel.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.instances\n\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.TypeName\nimport javax.lang.model.element.Element\n\nconst val PARAM_SCOPE_NAME = \"scope\"\n\ninterface FactoryTypeVisitor {\n\n    fun enterFactoryClass(factoryType: FactoryType) {}\n\n    fun enterCreateMethod(createMethod: CreateMethod) {}\n    fun visitCreateMethodParameter(parameter: MethodParameter) {}\n    fun exitCreateMethod(createMethod: CreateMethod) {}\n\n    fun visit(method: GetScopingMethod) {}\n    fun visit(method: GetLimitMethod) {}\n\n    fun enterSiblingTypesMethod(method: GetSiblingTypesMethod) {}\n    fun visitSiblingType(type: ClassName) {}\n    fun exitSiblingTypesMethod(method: GetSiblingTypesMethod) {}\n\n    fun enterGetSelectorMethod(method: GetSelectorMethod) {}\n    fun visitSelectorArgument(argument: String) {}\n    fun exitGetSelectorMethod(method: GetSelectorMethod) {}\n\n    fun exitFactoryClass(factory: FactoryType) {}\n}\n\nclass FactoryType(\n    val element: Element,\n    val interfaceType: ClassName,\n    val classifier: String,\n    val scoping: String,\n    val disabled: Boolean,\n    val factoryType: ClassName,\n    val implementationType: ClassName?,\n    val customFactoryType: TypeName?,\n    val disposerMethodName: String?,\n    val createStatement: CreateStatement,\n    val createMethod: CreateMethod,\n    val getScopingMethod: GetScopingMethod,\n    val getLimitMethod: GetLimitMethod?,\n    val getSelectorMethod: GetSelectorMethod?,\n    val getSiblingTypesMethod: GetSiblingTypesMethod?\n) {\n    fun accept(visitor: FactoryTypeVisitor) {\n        visitor.enterFactoryClass(this)\n        createMethod.accept(visitor)\n        getScopingMethod.accept(visitor)\n        getLimitMethod?.accept(visitor)\n        getSiblingTypesMethod?.accept(visitor)\n        getSelectorMethod?.accept(visitor)\n        visitor.exitFactoryClass(this)\n    }\n}\n\nabstract class CreateStatement\n\nclass TypeCreateStatement(\n    val instanceType: ClassName\n) : CreateStatement()\n\nclass StaticMethodCreateStatement(\n    val staticMethodClassName: ClassName,\n    val staticMethodName: String\n) : CreateStatement()\n\nclass CreateMethod(\n    val methodParameter: List<MethodParameter>\n) {\n    fun accept(visitor: FactoryTypeVisitor) {\n        visitor.enterCreateMethod(this)\n        methodParameter.forEach { parameterNode ->\n            parameterNode.accept(visitor)\n        }\n        visitor.exitCreateMethod(this)\n    }\n}\n\nenum class Cardinality {\n    Single, Optional, Many\n}\n\nsealed class Expression {\n    object Scope : Expression()\n    data class Getter(val cardinality: Cardinality) : Expression()\n    data class LazyGetter(val cardinality: Cardinality) : Expression()\n}\n\ndata class MethodParameter(\n    val name: String,\n    val expression: Expression,\n    val returnType: TypeName,\n    val parameterType: TypeName,\n    val classifier: String,\n    val typeErased: Boolean\n) {\n    fun accept(visitor: FactoryTypeVisitor) {\n        visitor.visitCreateMethodParameter(this)\n    }\n}\n\nclass GetScopingMethod(val scoping: String) {\n    fun accept(visitor: FactoryTypeVisitor) {\n        visitor.visit(this)\n    }\n}\n\nclass GetLimitMethod(val limit: String) {\n    fun accept(visitor: FactoryTypeVisitor) {\n        visitor.visit(this)\n    }\n}\n\nclass GetSiblingTypesMethod(val siblingTypes: List<ClassName>) {\n    fun accept(visitor: FactoryTypeVisitor) {\n        visitor.enterSiblingTypesMethod(this)\n        for (siblingType in siblingTypes) {\n            visitor.visitSiblingType(siblingType)\n        }\n        visitor.exitSiblingTypesMethod(this)\n    }\n}\n\nclass GetSelectorMethod(val selectorArguments: List<String>) {\n    fun accept(visitor: FactoryTypeVisitor) {\n        visitor.enterGetSelectorMethod(this)\n        for (argument in selectorArguments) {\n            visitor.visitSelectorArgument(argument)\n        }\n        visitor.exitGetSelectorMethod(this)\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/InstanceProcessor.kt",
    "content": "package magnet.processor.instances\n\nimport magnet.Instance\nimport magnet.processor.MagnetProcessorEnv\nimport magnet.processor.instances.aspects.index.FactoryIndexCodeGenerator\nimport magnet.processor.instances.generator.CodeWriter\nimport magnet.processor.instances.generator.FactoryTypeCodeGenerator\nimport magnet.processor.instances.parser.InstanceParserForClass\nimport magnet.processor.instances.parser.InstanceParserForMethod\nimport javax.annotation.processing.RoundEnvironment\nimport javax.lang.model.util.ElementFilter\n\nclass InstanceProcessor(\n    private val env: MagnetProcessorEnv\n) {\n\n    private val factoryFromClassAnnotationParser = InstanceParserForClass(env)\n    private val factoryFromMethodAnnotationParser = InstanceParserForMethod(env)\n    private val factoryTypeCodeGenerator = FactoryTypeCodeGenerator()\n    private val factoryIndexCodeGenerator = FactoryIndexCodeGenerator()\n\n    fun process(roundEnv: RoundEnvironment): Boolean {\n\n        val annotatedElements = roundEnv.getElementsAnnotatedWith(Instance::class.java)\n        if (annotatedElements.isEmpty()) {\n            return false\n        }\n\n        val factoryTypes = mutableListOf<FactoryType>()\n        ElementFilter.typesIn(annotatedElements).forEach { element ->\n            val parsedFactoryTypes = with(factoryFromClassAnnotationParser) { element.parse() }\n            for (factoryType in parsedFactoryTypes) {\n                if (!factoryType.disabled) {\n                    factoryTypes.add(factoryType)\n                }\n            }\n        }\n        ElementFilter.methodsIn(annotatedElements).forEach { element ->\n            val parsedFactoryTypes = with(factoryFromMethodAnnotationParser) { element.parse() }\n            for (factoryType in parsedFactoryTypes) {\n                if (!factoryType.disabled) {\n                    factoryTypes.add(factoryType)\n                }\n            }\n        }\n\n        factoryTypes.sortBy { factoryName(it) }\n\n        val codeWriters = mutableListOf<CodeWriter>()\n        factoryTypes.forEach { factoryType ->\n            codeWriters.add(factoryTypeCodeGenerator.generateFrom(factoryType))\n            codeWriters.add(factoryIndexCodeGenerator.generateFrom(factoryType))\n        }\n\n        codeWriters.forEach { codeWriter ->\n            codeWriter.writeInto(env.filer)\n        }\n\n        return true\n    }\n}\n\nprivate fun factoryName(factoryType: FactoryType): String = factoryType.factoryType.simpleName()\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/classifier/ClassifierAttributeParser.kt",
    "content": "package magnet.processor.instances.aspects.classifier\n\nimport magnet.processor.instances.parser.AttributeParser\nimport magnet.processor.instances.parser.ParserInstance\nimport javax.lang.model.element.AnnotationValue\nimport javax.lang.model.element.Element\n\nobject ClassifierAttributeParser : AttributeParser(\"classifier\") {\n    override fun <E : Element> Scope<E>.parse(value: AnnotationValue): ParserInstance<E> =\n        instance.copy(classifier = value.value.toString())\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/disabled/DisabledAttributeParser.kt",
    "content": "package magnet.processor.instances.aspects.disabled\n\nimport magnet.processor.instances.parser.AttributeParser\nimport magnet.processor.instances.parser.ParserInstance\nimport javax.lang.model.element.AnnotationValue\nimport javax.lang.model.element.Element\n\nobject DisabledAttributeParser : AttributeParser(\"disabled\") {\n    override fun <E : Element> Scope<E>.parse(value: AnnotationValue): ParserInstance<E> =\n        instance.copy(disabled = value.value.toString().toBoolean())\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/disposer/DisposeMethodGenerator.kt",
    "content": "package magnet.processor.instances.aspects.disposer\n\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeName\nimport com.squareup.javapoet.TypeSpec\nimport magnet.processor.instances.FactoryType\nimport javax.lang.model.element.Modifier\n\ninternal class DisposeMethodGenerator {\n\n    private var methodBuilder: MethodSpec.Builder? = null\n\n    fun visitFactoryClass(factoryType: FactoryType) {\n        methodBuilder = if (factoryType.disposerMethodName == null) null\n        else MethodSpec\n            .methodBuilder(\"dispose\")\n            .addAnnotation(Override::class.java)\n            .addModifiers(Modifier.PUBLIC)\n            .returns(TypeName.VOID)\n            .addParameter(factoryType.interfaceType, \"instance\")\n            .addStatement(\n                \"((\\$T) instance).\\$L()\",\n                factoryType.implementationType, factoryType.disposerMethodName\n            )\n    }\n\n    fun generate(typeBuilder: TypeSpec.Builder) {\n        methodBuilder?.let { typeBuilder.addMethod(it.build()) }\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/disposer/DisposerAttributeParser.kt",
    "content": "package magnet.processor.instances.aspects.disposer\n\nimport magnet.processor.common.throwValidationError\nimport magnet.processor.instances.parser.AttributeParser\nimport magnet.processor.instances.parser.ParserInstance\nimport javax.lang.model.element.AnnotationValue\nimport javax.lang.model.element.Element\nimport javax.lang.model.element.ElementKind\nimport javax.lang.model.element.ExecutableElement\nimport javax.lang.model.element.Modifier\nimport javax.lang.model.type.TypeKind\n\nobject DisposerAttributeParser : AttributeParser(\"disposer\") {\n    override fun <E : Element> Scope<E>.parse(value: AnnotationValue): ParserInstance<E> =\n        instance.copy(disposer = parseMethodName(value))\n\n    private fun <E : Element> Scope<E>.parseMethodName(value: AnnotationValue): String {\n\n        if (element.kind != ElementKind.CLASS)\n            element.throwValidationError(\"Disposer can be defined for annotated class only.\")\n\n        val methodName = env.annotation\n            .getStringValue(value)\n\n            .removeSurrounding(\"\\\"\")\n\n        val methodElement = element.enclosedElements\n            .find { it.kind == ElementKind.METHOD && it.simpleName.toString() == methodName }\n            ?: element.throwValidationError(\"Instance must declare disposer method $methodName().\")\n\n        val returnType = (methodElement as ExecutableElement).returnType\n        if (returnType.kind != TypeKind.VOID)\n            element.throwValidationError(\"Disposer method $methodName() must return void.\")\n\n        if (methodElement.parameters.size != 0)\n            element.throwValidationError(\"Disposer method $methodName() must have no parameters.\")\n\n        if (methodElement.modifiers.contains(Modifier.PRIVATE))\n            element.throwValidationError(\"Disposer method $methodName() must not be 'private'.\")\n\n        return methodName\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/disposer/DisposerValidator.kt",
    "content": "package magnet.processor.instances.aspects.disposer\n\nimport magnet.Scoping\nimport magnet.processor.MagnetProcessorEnv\nimport magnet.processor.common.throwValidationError\nimport magnet.processor.instances.parser.AspectValidator\nimport magnet.processor.instances.parser.ParserInstance\nimport javax.lang.model.element.Element\n\nobject DisposerValidator : AspectValidator {\n    override fun <E : Element> ParserInstance<E>.validate(\n        env: MagnetProcessorEnv\n    ): ParserInstance<E> {\n        if (disposer != null && scoping == Scoping.UNSCOPED.name)\n            element.throwValidationError(\"Disposer cannot be used with UNSCOPED instances.\")\n        return this\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/disposer/IsDisposableMethodGenerator.kt",
    "content": "package magnet.processor.instances.aspects.disposer\n\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeName\nimport com.squareup.javapoet.TypeSpec\nimport magnet.processor.instances.FactoryType\nimport javax.lang.model.element.Modifier\n\ninternal class IsDisposableMethodGenerator {\n\n    private var methodBuilder: MethodSpec.Builder? = null\n\n    fun visitFactoryClass(factoryType: FactoryType) {\n        methodBuilder = if (factoryType.disposerMethodName == null) null\n        else MethodSpec\n            .methodBuilder(\"isDisposable\")\n            .addAnnotation(Override::class.java)\n            .addModifiers(Modifier.PUBLIC)\n            .returns(TypeName.BOOLEAN)\n            .addStatement(\"return true\")\n    }\n\n    fun generate(typeBuilder: TypeSpec.Builder) {\n        methodBuilder?.let { typeBuilder.addMethod(it.build()) }\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/factory/CreateMethodGenerator.kt",
    "content": "package magnet.processor.instances.aspects.factory\n\nimport com.squareup.javapoet.*\nimport magnet.internal.ManyLazy\nimport magnet.internal.OptionalLazy\nimport magnet.internal.SingleLazy\nimport magnet.processor.instances.*\n\ninterface CreateMethodGenerator {\n\n    fun visitFactoryClass(factoryType: FactoryType) {}\n    fun enterCreateMethod(createMethod: CreateMethod) {}\n    fun visitCreateMethodParameter(parameter: MethodParameter) {}\n    fun exitCreateMethod() {}\n    fun generate(typeBuilder: TypeSpec.Builder)\n\n    fun CodeBlock.Builder.addCreateParameterStatement(parameter: MethodParameter) {\n        when (val expression = parameter.expression) {\n            is Expression.Getter -> {\n                addStatement(\n                    \"\\$T \\$L = scope.${expression.getterName}(\\$T.class, \\$S)\",\n                    parameter.returnType,\n                    parameter.name,\n                    parameter.parameterType,\n                    parameter.classifier\n                )\n            }\n            is Expression.LazyGetter -> {\n                addStatement(\n                    \"\\$T \\$L = new \\$T($PARAM_SCOPE_NAME, \\$T.class, \\$S)\",\n                    parameter.returnType,\n                    parameter.name,\n                    expression.lazyGetterType,\n                    parameter.parameterType,\n                    parameter.classifier\n                )\n            }\n            Expression.Scope -> {}\n        }\n    }\n\n    fun MethodSpec.Builder.addNewInstanceStatement(\n        constructorParameters: String,\n        createStatement: CreateStatement\n    ): MethodSpec.Builder {\n        when (createStatement) {\n            is TypeCreateStatement -> {\n                addStatement(\n                    \"return new \\$T($constructorParameters)\",\n                    createStatement.instanceType\n                )\n            }\n            is StaticMethodCreateStatement -> {\n                addStatement(\n                    \"return \\$T.\\$L($constructorParameters)\",\n                    createStatement.staticMethodClassName,\n                    createStatement.staticMethodName\n                )\n            }\n        }\n        return this\n    }\n}\n\nprivate val Expression.Getter.getterName: String\n    get() = when (cardinality) {\n        Cardinality.Single -> \"getSingle\"\n        Cardinality.Optional -> \"getOptional\"\n        Cardinality.Many -> \"getMany\"\n    }\n\nprivate val Expression.LazyGetter.lazyGetterType: TypeName\n    get() = when (cardinality) {\n        Cardinality.Single -> ClassName.get(SingleLazy::class.java)\n        Cardinality.Optional -> ClassName.get(OptionalLazy::class.java)\n        Cardinality.Many -> ClassName.get(ManyLazy::class.java)\n    }\n\nclass DefaultCreateMethodGenerator : CreateMethodGenerator {\n\n    private val customFactoryGenerator = CustomFactoryCreateMethodGenerator()\n    private val standardFactoryGenerator = StandardFactoryCreateMethodGenerator()\n\n    private lateinit var impl: CreateMethodGenerator\n\n    override fun visitFactoryClass(factoryType: FactoryType) {\n        impl =\n            if (factoryType.customFactoryType != null) customFactoryGenerator else standardFactoryGenerator\n        impl.visitFactoryClass(factoryType)\n    }\n\n    override fun enterCreateMethod(createMethod: CreateMethod) {\n        impl.enterCreateMethod(createMethod)\n    }\n\n    override fun visitCreateMethodParameter(parameter: MethodParameter) {\n        impl.visitCreateMethodParameter(parameter)\n    }\n\n    override fun exitCreateMethod() {\n        impl.exitCreateMethod()\n    }\n\n    override fun generate(typeBuilder: TypeSpec.Builder) {\n        impl.generate(typeBuilder)\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/factory/CustomFactoryCreateMethodGenerator.kt",
    "content": "package magnet.processor.instances.aspects.factory\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.ParameterizedTypeName\nimport com.squareup.javapoet.TypeName\nimport com.squareup.javapoet.TypeSpec\nimport magnet.Factory\nimport magnet.Scope\nimport magnet.Scoping\nimport magnet.processor.instances.CreateMethod\nimport magnet.processor.instances.FactoryType\nimport magnet.processor.instances.MethodParameter\nimport magnet.processor.instances.PARAM_SCOPE_NAME\nimport javax.lang.model.element.Modifier\n\nclass CustomFactoryCreateMethodGenerator : CreateMethodGenerator {\n\n    private lateinit var factoryType: FactoryType\n    private lateinit var factoryFieldType: TypeName\n    private lateinit var instantiateMethodBuilder: MethodSpec.Builder\n    private lateinit var instantiateMethodCodeBuilder: CodeBlock.Builder\n    private var constructorParametersBuilder = StringBuilder()\n\n    override fun visitFactoryClass(factoryType: FactoryType) {\n        this.factoryType = factoryType\n        constructorParametersBuilder.setLength(0)\n\n        val customFactoryType = checkNotNull(factoryType.customFactoryType)\n        factoryFieldType = when (customFactoryType) {\n            is ParameterizedTypeName -> ParameterizedTypeName.get(customFactoryType.rawType, factoryType.interfaceType)\n            else -> customFactoryType\n        }\n    }\n\n    override fun enterCreateMethod(createMethod: CreateMethod) {\n        instantiateMethodBuilder = MethodSpec\n            .methodBuilder(\"instantiate\")\n            .addAnnotation(Override::class.java)\n            .addModifiers(Modifier.PUBLIC)\n            .addParameter(Scope::class.java, \"scope\")\n            .returns(factoryType.interfaceType)\n\n        instantiateMethodCodeBuilder = CodeBlock\n            .builder()\n    }\n\n    override fun visitCreateMethodParameter(parameter: MethodParameter) {\n        instantiateMethodCodeBuilder.addCreateParameterStatement(parameter)\n        constructorParametersBuilder.append(parameter.name).append(\", \")\n    }\n\n    override fun exitCreateMethod() {\n        if (constructorParametersBuilder.isNotEmpty()) {\n            constructorParametersBuilder.setLength(constructorParametersBuilder.length - 2)\n        }\n    }\n\n    override fun generate(typeBuilder: TypeSpec.Builder) {\n        typeBuilder\n            .addSuperinterface(\n                ParameterizedTypeName.get(\n                    ClassName.get(Factory.Instantiator::class.java),\n                    factoryType.interfaceType\n                )\n            )\n            .addField(\n                FieldSpec\n                    .builder(factoryFieldType, \"factory\")\n                    .addModifiers(Modifier.PRIVATE)\n                    .initializer(\"null\")\n                    .build()\n            )\n            .addMethod(\n                MethodSpec\n                    .methodBuilder(\"create\")\n                    .addAnnotation(Override::class.java)\n                    .addModifiers(Modifier.PUBLIC)\n                    .addParameter(Scope::class.java, PARAM_SCOPE_NAME)\n                    .returns(factoryType.interfaceType)\n                    .addCode(\n                        CodeBlock.builder()\n                            .beginControlFlow(\"if (factory == null)\")\n                            .addStatement(\"factory = new \\$T()\", factoryFieldType)\n                            .endControlFlow()\n                            .addStatement(\n                                \"return factory.create(scope, \\$T.class, \\$S, \\$T.\\$L, this)\",\n                                factoryType.interfaceType,\n                                factoryType.classifier,\n                                Scoping::class.java,\n                                factoryType.scoping\n                            )\n                            .build()\n                    )\n                    .build()\n            )\n            .addMethod(\n                instantiateMethodBuilder\n                    .addCode(instantiateMethodCodeBuilder.build())\n                    .addNewInstanceStatement(\n                        constructorParametersBuilder.toString(),\n                        factoryType.createStatement\n                    )\n                    .build()\n            )\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/factory/FactoryAttributeParser.kt",
    "content": "package magnet.processor.instances.aspects.factory\n\nimport com.squareup.javapoet.TypeName\nimport magnet.processor.instances.parser.AttributeParser\nimport magnet.processor.instances.parser.ParserInstance\nimport javax.lang.model.element.AnnotationValue\nimport javax.lang.model.element.Element\n\nobject FactoryAttributeParser : AttributeParser(\"factory\") {\n    override fun <E : Element> Scope<E>.parse(value: AnnotationValue): ParserInstance<E> =\n        instance.copy(factory = parseFactoryType(value))\n\n    private fun <E : Element> Scope<E>.parseFactoryType(value: AnnotationValue): TypeName? =\n        TypeName.get(env.annotation.getTypeElement(value).asType())\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/factory/StandardFactoryCreateMethodGenerator.kt",
    "content": "package magnet.processor.instances.aspects.factory\n\nimport com.squareup.javapoet.AnnotationSpec\nimport com.squareup.javapoet.CodeBlock\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeSpec\nimport magnet.Scope\nimport magnet.processor.instances.CreateMethod\nimport magnet.processor.instances.Expression\nimport magnet.processor.instances.FactoryType\nimport magnet.processor.instances.MethodParameter\nimport magnet.processor.instances.PARAM_SCOPE_NAME\nimport javax.lang.model.element.Modifier\n\nclass StandardFactoryCreateMethodGenerator : CreateMethodGenerator {\n\n    private lateinit var factoryType: FactoryType\n    private var createMethodBuilder: MethodSpec.Builder? = null\n    private var createMethodCodeBuilder: CodeBlock.Builder? = null\n    private var constructorParametersBuilder = StringBuilder()\n    private var isSuppressUncheckedAdded = false\n\n    override fun visitFactoryClass(factoryType: FactoryType) {\n        this.factoryType = factoryType\n        createMethodBuilder = null\n        createMethodCodeBuilder = null\n        constructorParametersBuilder.setLength(0)\n        isSuppressUncheckedAdded = false\n    }\n\n    override fun enterCreateMethod(createMethod: CreateMethod) {\n        createMethodBuilder = MethodSpec\n            .methodBuilder(\"create\")\n            .addAnnotation(Override::class.java)\n            .addModifiers(Modifier.PUBLIC)\n            .addParameter(Scope::class.java, PARAM_SCOPE_NAME)\n            .returns(factoryType.interfaceType)\n        createMethodCodeBuilder = CodeBlock.builder()\n    }\n\n    override fun visitCreateMethodParameter(parameter: MethodParameter) {\n        createMethodCodeBuilder?.let { builder ->\n            builder.addCreateParameterStatement(parameter)\n            val paramName = if (parameter.expression == Expression.Scope) PARAM_SCOPE_NAME else parameter.name\n            constructorParametersBuilder.append(paramName).append(\", \")\n        }\n\n        createMethodBuilder?.let { builder ->\n            if (parameter.typeErased && !isSuppressUncheckedAdded) {\n                isSuppressUncheckedAdded = true\n                builder.addAnnotation(\n                    AnnotationSpec\n                        .builder(SuppressWarnings::class.java)\n                        .addMember(\"value\", \"\\\"unchecked\\\"\")\n                        .build()\n                )\n            }\n        }\n    }\n\n    override fun exitCreateMethod() {\n        if (constructorParametersBuilder.isNotEmpty()) {\n            constructorParametersBuilder.setLength(constructorParametersBuilder.length - 2)\n        }\n    }\n\n    override fun generate(typeBuilder: TypeSpec.Builder) {\n        createMethodBuilder?.let { builder ->\n\n            createMethodCodeBuilder?.let { codeBuilder ->\n                builder.addCode(codeBuilder.build())\n            }\n\n            builder.addNewInstanceStatement(\n                constructorParametersBuilder.toString(),\n                factoryType.createStatement\n            )\n\n            typeBuilder.addMethod(builder.build())\n        }\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/index/FactoryIndexCodeGenerator.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.instances.aspects.index\n\nimport com.squareup.javapoet.AnnotationSpec\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.TypeSpec\nimport magnet.internal.Generated\nimport magnet.internal.Index\nimport magnet.internal.InstanceFactory\nimport magnet.processor.instances.generator.CodeGenerator\nimport magnet.processor.instances.generator.CodeWriter\nimport magnet.processor.instances.FactoryType\nimport magnet.processor.instances.FactoryTypeVisitor\nimport javax.lang.model.element.Modifier\n\nclass FactoryIndexCodeGenerator : FactoryTypeVisitor, CodeGenerator {\n\n    private lateinit var factoryIndexTypeSpec: TypeSpec\n    private lateinit var factoryIndexClassName: ClassName\n\n    override fun exitFactoryClass(factory: FactoryType) {\n        val factoryPackage = factory.factoryType.packageName()\n        val factoryName = factory.factoryType.simpleName()\n        val factoryIndexName = \"${factoryPackage.replace('.', '_')}_$factoryName\"\n\n        factoryIndexClassName = ClassName.get(\"magnet.index\", factoryIndexName)\n\n        factoryIndexTypeSpec = TypeSpec\n            .classBuilder(factoryIndexClassName)\n            .addModifiers(Modifier.PUBLIC, Modifier.FINAL)\n            .addAnnotation(Generated::class.java)\n            .addAnnotation(\n                generateFactoryIndexAnnotation(\n                    factory.factoryType,\n                    factory.interfaceType.reflectionName(),\n                    factory.classifier\n                )\n            )\n            .build()\n    }\n\n    private fun generateFactoryIndexAnnotation(\n        factoryClassName: ClassName,\n        instanceType: String,\n        classifier: String\n    ): AnnotationSpec {\n        return AnnotationSpec.builder(Index::class.java)\n            .addMember(\"factoryType\", \"\\$T.class\", InstanceFactory::class.java)\n            .addMember(\"factoryClass\", \"\\$T.class\", factoryClassName)\n            .addMember(\"instanceType\", \"\\$S\", instanceType)\n            .addMember(\"classifier\", \"\\$S\", classifier)\n            .build()\n    }\n\n    override fun generateFrom(factoryType: FactoryType): CodeWriter {\n        factoryType.accept(this)\n        return CodeWriter(factoryIndexClassName.packageName(), factoryIndexTypeSpec)\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/limitedto/GetLimitMethodGenerator.kt",
    "content": "package magnet.processor.instances.aspects.limitedto\n\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeSpec\nimport magnet.processor.instances.generator.AspectGenerator\nimport magnet.processor.instances.GetLimitMethod\nimport javax.lang.model.element.Modifier\n\ninternal class GetLimitMethodGenerator : AspectGenerator {\n\n    private var getLimit: MethodSpec? = null\n\n    override fun reset() {\n        getLimit = null\n    }\n\n    override fun generate(classBuilder: TypeSpec.Builder) {\n        getLimit?.let { classBuilder.addMethod(it) }\n    }\n\n    fun visit(method: GetLimitMethod) {\n        getLimit = MethodSpec\n            .methodBuilder(\"getLimit\")\n            .addModifiers(Modifier.PUBLIC)\n            .addAnnotation(Override::class.java)\n            .returns(String::class.java)\n            .addStatement(\"return \\$S\", method.limit)\n            .build()\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/limitedto/LimitedToAttributeParser.kt",
    "content": "package magnet.processor.instances.aspects.limitedto\n\nimport magnet.processor.instances.parser.AttributeParser\nimport magnet.processor.instances.parser.ParserInstance\nimport javax.lang.model.element.AnnotationValue\nimport javax.lang.model.element.Element\n\nobject LimitedToAttributeParser : AttributeParser(\"limitedTo\") {\n    override fun <E : Element> Scope<E>.parse(value: AnnotationValue): ParserInstance<E> =\n        instance.copy(limitedTo = value.value.toString())\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/limitedto/LimitedToValidator.kt",
    "content": "package magnet.processor.instances.aspects.limitedto\n\nimport magnet.Scoping\nimport magnet.processor.MagnetProcessorEnv\nimport magnet.processor.common.throwValidationError\nimport magnet.processor.instances.parser.AspectValidator\nimport magnet.processor.instances.parser.ParserInstance\nimport javax.lang.model.element.Element\n\nobject LimitedToValidator : AspectValidator {\n    override fun <E : Element> ParserInstance<E>.validate(\n        env: MagnetProcessorEnv\n    ): ParserInstance<E> {\n        if (limitedTo == \"*\") {\n            element.throwValidationError(\n                \"Limit must not use reserved '*' value. Use another value.\"\n            )\n        } else if (limitedTo.isNotEmpty() && scoping == Scoping.UNSCOPED.name) {\n            element.throwValidationError(\n                \"Limit can only be used with Scoping.TOPMOST and Scoping.DIRECT.\" +\n                    \" Current scoping: Scoping.$scoping\"\n            )\n        }\n        return this\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/scoping/GetScopingMethodGenerator.kt",
    "content": "package magnet.processor.instances.aspects.scoping\n\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeSpec\nimport magnet.Scoping\nimport magnet.processor.instances.generator.AspectGenerator\nimport magnet.processor.instances.GetScopingMethod\nimport javax.lang.model.element.Modifier\n\ninternal class GetScopingMethodGenerator : AspectGenerator {\n\n    private var getScoping: MethodSpec? = null\n\n    override fun generate(classBuilder: TypeSpec.Builder) {\n        getScoping?.let { classBuilder.addMethod(it) }\n    }\n\n    override fun reset() {\n        getScoping = null\n    }\n\n    fun visit(method: GetScopingMethod) {\n        val defaultImplementationAvailable = method.scoping == Scoping.TOPMOST.name\n        if (!defaultImplementationAvailable) {\n            getScoping = MethodSpec\n                .methodBuilder(\"getScoping\")\n                .addModifiers(Modifier.PUBLIC)\n                .addAnnotation(Override::class.java)\n                .returns(Scoping::class.java)\n                .addStatement(\"return \\$T.\\$L\", Scoping::class.java, method.scoping)\n                .build()\n        }\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/scoping/ScopingAttributeParser.kt",
    "content": "package magnet.processor.instances.aspects.scoping\n\nimport magnet.processor.instances.parser.AttributeParser\nimport magnet.processor.instances.parser.ParserInstance\nimport javax.lang.model.element.AnnotationValue\nimport javax.lang.model.element.Element\n\nobject ScopingAttributeParser : AttributeParser(\"scoping\") {\n    override fun <E : Element> Scope<E>.parse(value: AnnotationValue): ParserInstance<E> =\n        instance.copy(scoping = value.value.toString())\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/selector/GetSelectorMethodGenerator.kt",
    "content": "package magnet.processor.instances.aspects.selector\n\nimport com.squareup.javapoet.ArrayTypeName\nimport com.squareup.javapoet.CodeBlock\nimport com.squareup.javapoet.FieldSpec\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeSpec\nimport magnet.processor.instances.generator.AspectGenerator\nimport magnet.processor.instances.GetSelectorMethod\nimport javax.lang.model.element.Modifier\n\ninternal class GetSelectorMethodGenerator : AspectGenerator {\n\n    private var methodSpec: MethodSpec? = null\n    private var constantFieldSpec: FieldSpec? = null\n    private var constantInitializer: CodeBlock.Builder? = null\n    private var argumentsLeft: Int = 0\n\n    override fun generate(classBuilder: TypeSpec.Builder) {\n        constantFieldSpec?.let { classBuilder.addField(it) }\n        methodSpec?.let { classBuilder.addMethod(it) }\n    }\n\n    override fun reset() {\n        methodSpec = null\n        constantFieldSpec = null\n        constantInitializer = null\n        argumentsLeft = 0\n    }\n\n    fun enterGetSelectorMethod(method: GetSelectorMethod) {\n        methodSpec = MethodSpec\n            .methodBuilder(\"getSelector\")\n            .addModifiers(Modifier.PUBLIC)\n            .addAnnotation(Override::class.java)\n            .returns(ArrayTypeName.of(String::class.java))\n            .addStatement(\"return SELECTOR\")\n            .build()\n        constantInitializer = CodeBlock.builder().add(\"{ \")\n        argumentsLeft = method.selectorArguments.size\n    }\n\n    fun visitSelectorArgument(argument: String) {\n        if (--argumentsLeft > 0) {\n            checkNotNull(constantInitializer).add(\"\\$S, \", argument)\n        } else {\n            checkNotNull(constantInitializer).add(\"\\$S }\", argument)\n        }\n    }\n\n    fun exitGetSelectorMethod() {\n        constantFieldSpec = FieldSpec\n            .builder(ArrayTypeName.of(String::class.java), \"SELECTOR\")\n            .addModifiers(Modifier.PRIVATE, Modifier.STATIC)\n            .initializer(checkNotNull(constantInitializer).build())\n            .build()\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/selector/SelectorAttributeParser.kt",
    "content": "package magnet.processor.instances.aspects.selector\n\nimport magnet.processor.common.ValidationException\nimport magnet.processor.instances.parser.AttributeParser\nimport magnet.processor.instances.parser.ParserInstance\nimport javax.lang.model.element.AnnotationValue\nimport javax.lang.model.element.Element\n\nobject SelectorAttributeParser : AttributeParser(\"selector\") {\n\n    override fun <E : Element> Scope<E>.parse(value: AnnotationValue): ParserInstance<E> =\n        instance.copy(selector = parse(value.value.toString()))\n\n    private fun <E : Element> Scope<E>.parse(selector: String): List<String>? {\n        if (selector.isEmpty()) return null\n\n        val parsedSelector = selector.split(DELIMITER)\n        var isSelectorInvalid: Boolean = parsedSelector.size < 4 ||\n            parsedSelector[0].isEmpty() ||\n            parsedSelector[1].isEmpty() ||\n            parsedSelector[2] !in OPERATORS ||\n            parsedSelector[3].isEmpty()\n\n        if (!isSelectorInvalid) {\n            isSelectorInvalid = when (parsedSelector[2]) {\n                \"in\", \"!in\" -> parsedSelector.size != 5\n                else -> parsedSelector.size != 4\n            }\n        }\n\n        if (isSelectorInvalid) {\n            throw ValidationException(\n                element = element,\n                message = \"Invalid selector. Expected format:\" +\n                    \" '[selector id].[selector field] [comparison operator] [value]'.\" +\n                    \" Supported comparison operators: $OPERATORS.\" +\n                    \" Example selectors: 'android.api >= 28', 'android.api in 0..24'\"\n            )\n        }\n\n        return parsedSelector\n    }\n}\n\nprivate val DELIMITER = Regex(\"[\\\\s|.]+\")\nprivate val OPERATORS = arrayListOf(\">\", \"<\", \">=\", \"<=\", \"==\", \"!=\", \"in\", \"!in\")\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/siblings/GetSiblingTypesMethodGenerator.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.instances.aspects.siblings\n\nimport com.squareup.javapoet.ArrayTypeName\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.CodeBlock\nimport com.squareup.javapoet.FieldSpec\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.TypeSpec\nimport magnet.processor.instances.generator.AspectGenerator\nimport magnet.processor.instances.GetSiblingTypesMethod\nimport javax.lang.model.element.Modifier\n\ninternal class GetSiblingTypesMethodGenerator : AspectGenerator {\n\n    private var getSiblingTypes: MethodSpec? = null\n    private var constBuilder: FieldSpec? = null\n    private var constInitializer: CodeBlock.Builder? = null\n    private var typesLeft: Int = 0\n\n    fun enterSiblingTypesMethod(method: GetSiblingTypesMethod) {\n        getSiblingTypes = MethodSpec\n            .methodBuilder(\"getSiblingTypes\")\n            .addModifiers(Modifier.PUBLIC)\n            .addAnnotation(Override::class.java)\n            .returns(ArrayTypeName.of(Class::class.java))\n            .addStatement(\"return SIBLING_TYPES\")\n            .build()\n        constInitializer = CodeBlock.builder().add(\"{ \")\n        typesLeft = method.siblingTypes.size\n    }\n\n    fun visitSiblingType(type: ClassName) {\n        if (--typesLeft > 0) {\n            checkNotNull(constInitializer).add(\"\\$T.class, \", type)\n        } else {\n            checkNotNull(constInitializer).add(\"\\$T.class }\", type)\n        }\n    }\n\n    fun exitSiblingTypesMethod() {\n        constBuilder = FieldSpec\n            .builder(ArrayTypeName.of(Class::class.java), \"SIBLING_TYPES\")\n            .addModifiers(Modifier.PRIVATE, Modifier.STATIC)\n            .initializer(checkNotNull(constInitializer).build())\n            .build()\n    }\n\n    override fun reset() {\n        getSiblingTypes = null\n        constBuilder = null\n        constInitializer = null\n        typesLeft = 0\n    }\n\n    override fun generate(classBuilder: TypeSpec.Builder) {\n        constBuilder?.let { classBuilder.addField(it) }\n        getSiblingTypes?.let { classBuilder.addMethod(it) }\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/type/TypeAndTypesValidator.kt",
    "content": "/*\n * Copyright (C) 2018-2021 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.instances.aspects.type\n\nimport com.squareup.javapoet.ClassName\nimport magnet.Instance\nimport magnet.Scoping\nimport magnet.processor.MagnetProcessorEnv\nimport magnet.processor.common.throwCompilationError\nimport magnet.processor.common.throwValidationError\nimport magnet.processor.instances.parser.AspectValidator\nimport magnet.processor.instances.parser.ParserInstance\nimport javax.lang.model.element.Element\nimport javax.lang.model.element.TypeElement\n\nobject TypeAndTypesValidator : AspectValidator {\n    override fun <E : Element> ParserInstance<E>.validate(\n        env: MagnetProcessorEnv\n    ): ParserInstance<E> {\n        val elementWithType =\n            if (element is TypeElement && declaredType == null && declaredTypes.isNullOrEmpty())\n                copy(declaredType = element.autodetectType()) else this\n        return elementWithType.validateTypes()\n    }\n\n    private fun <E : Element> ParserInstance<E>.validateTypes(): ParserInstance<E> {\n        val isTypeDeclared = declaredType != null\n        val areTypesDeclared = declaredTypes?.isNotEmpty() ?: false\n\n        if (isTypeDeclared && areTypesDeclared)\n            element.throwValidationError(\n                \"${Instance::class.java} must declare either 'type' or 'types' property, not both.\"\n            )\n\n        if (declaredType != null) {\n            val types = arrayListOf(declaredType)\n            return copy(\n                declaredTypes = arrayListOf(declaredType),\n                types = types.map { ClassName.get(it) }\n            )\n        }\n\n        if (declaredTypes != null) {\n            if (scoping == Scoping.UNSCOPED.name)\n                element.throwValidationError(\n                    \"types() property must be used with scoped instances only. Set \" +\n                        \"scoping to Scoping.DIRECT or Scoping.TOPMOST.\"\n                )\n            return copy(\n                types = declaredTypes.map { ClassName.get(it) }\n            )\n        }\n\n        element.throwCompilationError(\"Cannot verify type declaration.\")\n    }\n\n    private fun TypeElement.autodetectType(): TypeElement {\n        if (interfaces.isEmpty()) {\n            val superType = ClassName.get(superclass)\n            if (superType is ClassName && superType.reflectionName() == \"java.lang.Object\") {\n                return this\n            }\n        }\n        throwValidationError(\n            \"${Instance::class.java} must declare either 'type' or 'types' property.\"\n        )\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/type/TypeAttributeParser.kt",
    "content": "package magnet.processor.instances.aspects.type\n\nimport magnet.processor.common.verifyInheritance\nimport magnet.processor.instances.parser.AttributeParser\nimport magnet.processor.instances.parser.ParserInstance\nimport javax.lang.model.element.AnnotationValue\nimport javax.lang.model.element.Element\n\nobject TypeAttributeParser : AttributeParser(\"type\") {\n    override fun <E : Element> Scope<E>.parse(value: AnnotationValue): ParserInstance<E> =\n        env.elements.getTypeElement(value.value.toString())?.let {\n            if (isTypeInheritanceEnforced) it.verifyInheritance(element, env.types)\n            instance.copy(declaredType = it)\n        } ?: instance\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/aspects/type/TypesAttributeParser.kt",
    "content": "package magnet.processor.instances.aspects.type\n\nimport magnet.processor.common.verifyInheritance\nimport magnet.processor.instances.parser.AttributeParser\nimport magnet.processor.instances.parser.ParserInstance\nimport javax.lang.model.element.AnnotationValue\nimport javax.lang.model.element.Element\nimport javax.lang.model.element.TypeElement\nimport javax.lang.model.type.TypeMirror\nimport javax.lang.model.util.Elements\nimport javax.lang.model.util.SimpleAnnotationValueVisitor6\n\nobject TypesAttributeParser : AttributeParser(\"types\") {\n\n    override fun <E : Element> Scope<E>.parse(value: AnnotationValue): ParserInstance<E> {\n        val typesExtractor = TypesExtractor(env.elements)\n            .apply { value.accept(this, null) }\n\n        val interfaceTypeElements = typesExtractor.getExtractedValue() ?: return instance\n        if (isTypeInheritanceEnforced) {\n            for (typeElement in interfaceTypeElements) {\n                typeElement.verifyInheritance(element, env.types)\n            }\n        }\n        return instance.copy(declaredTypes = interfaceTypeElements)\n    }\n}\n\n@Suppress(\"DEPRECATION\")\nprivate class TypesExtractor(private val elements: Elements) :\n    SimpleAnnotationValueVisitor6<Void?, Void>() {\n\n    private val extractedTypes = mutableListOf<String>()\n\n    fun getExtractedValue(): List<TypeElement>? =\n        if (extractedTypes.isEmpty()) null\n        else extractedTypes.map { elements.getTypeElement(it) }\n\n    override fun visitArray(values: MutableList<out AnnotationValue>?, p: Void?): Void? {\n        values?.let { for (value in values) value.accept(this, p) }\n        return p\n    }\n\n    override fun visitType(typeMirror: TypeMirror?, p: Void?): Void? {\n        typeMirror?.let { extractedTypes.add(it.toString()) }\n        return p\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/generator/CodeGenerator.kt",
    "content": "package magnet.processor.instances.generator\n\nimport magnet.processor.instances.FactoryType\n\ninterface CodeGenerator {\n\n    fun generateFrom(factoryType: FactoryType): CodeWriter\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/generator/CodeWriter.kt",
    "content": "package magnet.processor.instances.generator\n\nimport com.squareup.javapoet.JavaFile\nimport com.squareup.javapoet.TypeSpec\nimport javax.annotation.processing.Filer\n\nclass CodeWriter(\n    private var filePackage: String,\n    private var fileTypeSpec: TypeSpec\n) {\n\n    fun writeInto(filer: Filer) {\n        JavaFile\n            .builder(filePackage, fileTypeSpec)\n            .skipJavaLangImports(true)\n            .build()\n            .writeTo(filer)\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/generator/FactoryTypeCodeGenerator.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.instances.generator\n\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.ParameterizedTypeName\nimport com.squareup.javapoet.TypeName\nimport com.squareup.javapoet.TypeSpec\nimport magnet.internal.Generated\nimport magnet.internal.InstanceFactory\nimport magnet.processor.instances.CreateMethod\nimport magnet.processor.instances.FactoryType\nimport magnet.processor.instances.FactoryTypeVisitor\nimport magnet.processor.instances.GetLimitMethod\nimport magnet.processor.instances.GetScopingMethod\nimport magnet.processor.instances.GetSelectorMethod\nimport magnet.processor.instances.GetSiblingTypesMethod\nimport magnet.processor.instances.MethodParameter\nimport magnet.processor.instances.aspects.limitedto.GetLimitMethodGenerator\nimport magnet.processor.instances.aspects.selector.GetSelectorMethodGenerator\nimport magnet.processor.instances.aspects.disposer.DisposeMethodGenerator\nimport magnet.processor.instances.aspects.disposer.IsDisposableMethodGenerator\nimport magnet.processor.instances.aspects.factory.CreateMethodGenerator\nimport magnet.processor.instances.aspects.factory.DefaultCreateMethodGenerator\nimport magnet.processor.instances.aspects.scoping.GetScopingMethodGenerator\nimport magnet.processor.instances.aspects.siblings.GetSiblingTypesMethodGenerator\nimport javax.lang.model.element.Modifier\n\ninterface AspectGenerator {\n    fun generate(classBuilder: TypeSpec.Builder)\n    fun reset()\n}\n\ninternal class Aspect<out G : AspectGenerator>(\n    private val generator: G\n) {\n    private var visited: Boolean = false\n\n    inline fun visit(block: G.() -> Unit) {\n        block(generator)\n        visited = true\n    }\n\n    fun generate(classBuilder: TypeSpec.Builder) {\n        if (visited) {\n            generator.generate(classBuilder)\n        }\n        generator.reset()\n        visited = false\n    }\n}\n\nclass FactoryTypeCodeGenerator : FactoryTypeVisitor, CodeGenerator {\n\n    private var factoryTypeSpec: TypeSpec? = null\n    private var factoryClassName: ClassName? = null\n    private var generateGettersInCreateMethod = false\n\n    private val aspectGetSiblingTypes = Aspect(GetSiblingTypesMethodGenerator())\n    private val aspectGetScoping = Aspect(GetScopingMethodGenerator())\n    private val aspectGetLimit = Aspect(GetLimitMethodGenerator())\n    private val aspectGetSelector = Aspect(GetSelectorMethodGenerator())\n    private val createMethodGenerator: CreateMethodGenerator = DefaultCreateMethodGenerator()\n    private val isDisposableMethodGenerator = IsDisposableMethodGenerator()\n    private val disposeMethodGenerator = DisposeMethodGenerator()\n\n    override fun enterFactoryClass(factoryType: FactoryType) {\n        generateGettersInCreateMethod = factoryType.customFactoryType == null\n        createMethodGenerator.visitFactoryClass(factoryType)\n        isDisposableMethodGenerator.visitFactoryClass(factoryType)\n        disposeMethodGenerator.visitFactoryClass(factoryType)\n    }\n\n    override fun enterCreateMethod(createMethod: CreateMethod) {\n        factoryTypeSpec = null\n        createMethodGenerator.enterCreateMethod(createMethod)\n    }\n\n    override fun visitCreateMethodParameter(parameter: MethodParameter) {\n        createMethodGenerator.visitCreateMethodParameter(parameter)\n    }\n\n    override fun exitCreateMethod(createMethod: CreateMethod) {\n        createMethodGenerator.exitCreateMethod()\n    }\n\n    override fun visit(method: GetScopingMethod) {\n        aspectGetScoping.visit { visit(method) }\n    }\n\n    override fun visit(method: GetLimitMethod) {\n        aspectGetLimit.visit { visit(method) }\n    }\n\n    override fun enterSiblingTypesMethod(method: GetSiblingTypesMethod) {\n        aspectGetSiblingTypes.visit { enterSiblingTypesMethod(method) }\n    }\n\n    override fun visitSiblingType(type: ClassName) {\n        aspectGetSiblingTypes.visit { visitSiblingType(type) }\n    }\n\n    override fun exitSiblingTypesMethod(method: GetSiblingTypesMethod) {\n        aspectGetSiblingTypes.visit { exitSiblingTypesMethod() }\n    }\n\n    override fun enterGetSelectorMethod(method: GetSelectorMethod) {\n        aspectGetSelector.visit { enterGetSelectorMethod(method) }\n    }\n\n    override fun visitSelectorArgument(argument: String) {\n        aspectGetSelector.visit { visitSelectorArgument(argument) }\n    }\n\n    override fun exitGetSelectorMethod(method: GetSelectorMethod) {\n        aspectGetSelector.visit { exitGetSelectorMethod() }\n    }\n\n    override fun exitFactoryClass(factory: FactoryType) {\n\n        factoryClassName = factory.factoryType\n\n        val classBuilder: TypeSpec.Builder = TypeSpec\n            .classBuilder(factoryClassName)\n            .addModifiers(Modifier.PUBLIC, Modifier.FINAL)\n            .addAnnotation(Generated::class.java)\n            .superclass(generateFactorySuperInterface(factory))\n\n        createMethodGenerator.generate(classBuilder)\n\n        aspectGetScoping.generate(classBuilder)\n        aspectGetLimit.generate(classBuilder)\n        aspectGetSiblingTypes.generate(classBuilder)\n        aspectGetSelector.generate(classBuilder)\n        isDisposableMethodGenerator.generate(classBuilder)\n        disposeMethodGenerator.generate(classBuilder)\n\n        classBuilder\n            .addMethod(generateGetTypeMethod(factory))\n\n        factoryTypeSpec = classBuilder.build()\n    }\n\n    private fun generateGetTypeMethod(factoryType: FactoryType): MethodSpec {\n        return MethodSpec\n            .methodBuilder(\"getType\")\n            .addModifiers(Modifier.PUBLIC, Modifier.STATIC)\n            .returns(Class::class.java)\n            .addStatement(\"return \\$T.class\", factoryType.interfaceType)\n            .build()\n    }\n\n    private fun generateFactorySuperInterface(factoryType: FactoryType): TypeName {\n        return ParameterizedTypeName.get(\n            ClassName.get(InstanceFactory::class.java),\n            factoryType.interfaceType\n        )\n    }\n\n    override fun generateFrom(factoryType: FactoryType): CodeWriter {\n        factoryType.accept(this)\n        return CodeWriter(this.factoryClassName!!.packageName(), factoryTypeSpec!!)\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/parser/AspectValidator.kt",
    "content": "package magnet.processor.instances.parser\n\nimport magnet.processor.MagnetProcessorEnv\nimport magnet.processor.instances.aspects.disposer.DisposerValidator\nimport magnet.processor.instances.aspects.limitedto.LimitedToValidator\nimport magnet.processor.instances.aspects.type.TypeAndTypesValidator\nimport javax.lang.model.element.Element\n\ninterface AspectValidator {\n    fun <E : Element> ParserInstance<E>.validate(env: MagnetProcessorEnv): ParserInstance<E>\n\n    object Registry {\n        val VALIDATORS: List<AspectValidator> = listOf(\n            TypeAndTypesValidator,\n            DisposerValidator,\n            LimitedToValidator\n        )\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/parser/AttributeParser.kt",
    "content": "package magnet.processor.instances.parser\n\nimport magnet.processor.MagnetProcessorEnv\nimport magnet.processor.instances.aspects.classifier.ClassifierAttributeParser\nimport magnet.processor.instances.aspects.disabled.DisabledAttributeParser\nimport magnet.processor.instances.aspects.disposer.DisposerAttributeParser\nimport magnet.processor.instances.aspects.factory.FactoryAttributeParser\nimport magnet.processor.instances.aspects.limitedto.LimitedToAttributeParser\nimport magnet.processor.instances.aspects.scoping.ScopingAttributeParser\nimport magnet.processor.instances.aspects.selector.SelectorAttributeParser\nimport magnet.processor.instances.aspects.type.TypeAttributeParser\nimport magnet.processor.instances.aspects.type.TypesAttributeParser\nimport javax.lang.model.element.AnnotationValue\nimport javax.lang.model.element.Element\n\nabstract class AttributeParser(val name: String) {\n\n    data class Scope<E : Element>(\n        val isTypeInheritanceEnforced: Boolean,\n        val instance: ParserInstance<E>,\n        val element: Element,\n        val env: MagnetProcessorEnv\n    )\n\n    abstract fun <E : Element> Scope<E>.parse(value: AnnotationValue): ParserInstance<E>\n\n    object Registry {\n        val PARSERS = mapOf(\n            ClassifierAttributeParser.name to ClassifierAttributeParser,\n            DisabledAttributeParser.name to DisabledAttributeParser,\n            DisposerAttributeParser.name to DisposerAttributeParser,\n            FactoryAttributeParser.name to FactoryAttributeParser,\n            LimitedToAttributeParser.name to LimitedToAttributeParser,\n            ScopingAttributeParser.name to ScopingAttributeParser,\n            SelectorAttributeParser.name to SelectorAttributeParser,\n            TypeAttributeParser.name to TypeAttributeParser,\n            TypesAttributeParser.name to TypesAttributeParser\n        )\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/parser/InstanceParser.kt",
    "content": "/*\n * Copyright (C) 2018-2019 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.instances.parser\n\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.ParameterSpec\nimport com.squareup.javapoet.ParameterizedTypeName\nimport com.squareup.javapoet.TypeName\nimport com.squareup.javapoet.WildcardTypeName\nimport magnet.Classifier\nimport magnet.Instance\nimport magnet.Scope\nimport magnet.processor.MagnetProcessorEnv\nimport magnet.processor.common.KotlinMethodMetadata\nimport magnet.processor.common.eachAttributeOf\nimport magnet.processor.common.isOfAnnotationType\nimport magnet.processor.common.throwCompilationError\nimport magnet.processor.common.throwValidationError\nimport magnet.processor.instances.Cardinality\nimport magnet.processor.instances.Expression\nimport magnet.processor.instances.FactoryType\nimport magnet.processor.instances.MethodParameter\nimport magnet.processor.instances.parser.AspectValidator.Registry.VALIDATORS\nimport magnet.processor.instances.parser.AttributeParser.Registry.PARSERS\nimport javax.lang.model.element.Element\nimport javax.lang.model.element.VariableElement\nimport javax.lang.model.type.TypeKind\n\nconst val FACTORY_SUFFIX = \"MagnetFactory\"\nprivate const val CLASS_NULLABLE = \".Nullable\"\n\ninternal abstract class InstanceParser<E : Element>(\n    private val env: MagnetProcessorEnv,\n    private val isTypeInheritanceEnforced: Boolean\n) {\n\n    private val scopeTypeName = ClassName.get(Scope::class.java)\n    private val listTypeName = ClassName.get(List::class.java)\n    private val lazyTypeName = ClassName.get(Lazy::class.java)\n\n    fun E.parse(): List<FactoryType> {\n\n        onBeforeParsing()\n\n        var scope = AttributeParser.Scope(\n            isTypeInheritanceEnforced = isTypeInheritanceEnforced,\n            instance = ParserInstance(this),\n            element = this,\n            env = env\n        )\n        eachAttributeOf<Instance> { name, value ->\n            PARSERS[name]?.apply {\n                scope = scope.copy(\n                    instance = scope.parse(value)\n                )\n            } ?: throwCompilationError(\n                \"Unsupported attribute '$name'.\" +\n                    \" Do you use the same versions of magnet processor and runtime libraries?\"\n            )\n        }\n\n        var instance = scope.instance\n        for (validator in VALIDATORS) {\n            with(validator) {\n                instance = instance.validate(env)\n            }\n        }\n\n        return generateFactories(instance)\n    }\n\n    protected open fun E.onBeforeParsing() {}\n    protected abstract fun generateFactories(instance: ParserInstance<E>): List<FactoryType>\n\n    protected fun parseMethodParameter(\n        element: Element,\n        variable: VariableElement,\n        methodMeta: KotlinMethodMetadata?\n    ): MethodParameter {\n\n        val variableType = variable.asType()\n        if (variableType.kind == TypeKind.TYPEVAR) {\n            element.throwValidationError(\n                \"Constructor parameter '${variable.simpleName}' is specified using a generic\" +\n                    \" type which is not supported by Magnet. Use a non-parameterized class or\" +\n                    \" interface type instead. To inject current scope into an instance,\" +\n                    \" add 'scope: Scope' to the constructor parameters.\"\n            )\n        }\n\n        val paramSpec = ParameterSpec.get(variable)\n        val paramType = paramSpec.type\n        val paramName = paramSpec.name\n\n        var paramReturnType: TypeName = paramType\n        var paramExpression: Expression = Expression.Scope\n        var paramParameterType: TypeName = paramType\n        var paramClassifier: String = Classifier.NONE\n        var paramTypeErased = false\n\n        paramParameterType.parseParamType(\n            paramName, methodMeta, variable\n        ) { returnType, expression, parameterType, classifier, erased ->\n            paramReturnType = returnType\n            paramExpression = expression\n            paramParameterType = parameterType\n            paramClassifier = classifier\n            paramTypeErased = erased\n        }\n\n        return MethodParameter(\n            name = paramName,\n            expression = paramExpression,\n            returnType = paramReturnType,\n            parameterType = paramParameterType,\n            classifier = paramClassifier,\n            typeErased = paramTypeErased\n        )\n    }\n\n    private fun TypeName.parseParamType(\n        paramName: String,\n        methodMeta: KotlinMethodMetadata?,\n        variable: VariableElement,\n        block: (\n            returnType: TypeName,\n            expression: Expression,\n            parameterType: TypeName,\n            classifier: String,\n            typeErased: Boolean\n        ) -> Unit\n    ) {\n        var paramReturnType: TypeName = this\n        var paramExpression: Expression = Expression.Scope\n        var paramParameterType: TypeName = this\n        var paramClassifier: String = Classifier.NONE\n        var paramTypeErased = false\n\n        when (this) {\n            scopeTypeName -> {\n                paramExpression = Expression.Scope\n            }\n\n            is ParameterizedTypeName -> {\n                when (rawType) {\n                    listTypeName -> {\n                        val (type, erased) = firstArgumentRawType(variable)\n                        paramParameterType = type\n                        paramTypeErased = erased\n                        paramReturnType = if (erased) listTypeName\n                        else ParameterizedTypeName.get(listTypeName, paramParameterType)\n                        paramExpression = Expression.Getter(Cardinality.Many)\n                        variable.annotations { _, classifier ->\n                            paramClassifier = classifier\n                        }\n                    }\n\n                    lazyTypeName -> {\n                        if (methodMeta == null) variable.throwValidationError(\n                            \"Lazy can only be used with Kotlin classes.\"\n                        )\n\n                        parseLazyArgumentType(\n                            paramName, methodMeta, variable\n                        ) { returnType, cardinality, parameterType ->\n                            paramReturnType = ParameterizedTypeName.get(lazyTypeName, returnType)\n                            paramParameterType = parameterType\n                            paramExpression = Expression.LazyGetter(cardinality)\n                            variable.annotations { _, classifier ->\n                                paramClassifier = classifier\n                            }\n                        }\n                    }\n\n                    else -> {\n                        paramParameterType = rawType\n                        paramTypeErased = true\n                        variable.annotations { cardinality, classifier ->\n                            paramExpression = Expression.Getter(cardinality)\n                            paramClassifier = classifier\n                        }\n                    }\n                }\n            }\n\n            else -> {\n                variable.annotations { cardinality, classifier ->\n                    paramExpression = Expression.Getter(cardinality)\n                    paramClassifier = classifier\n                }\n            }\n        }\n\n        block(\n            paramReturnType,\n            paramExpression,\n            paramParameterType,\n            paramClassifier,\n            paramTypeErased\n        )\n    }\n\n    private fun ParameterizedTypeName.parseLazyArgumentType(\n        paramName: String,\n        methodMeta: KotlinMethodMetadata,\n        variable: VariableElement,\n        block: (\n            returnType: TypeName,\n            cardinality: Cardinality,\n            parameterType: TypeName\n        ) -> Unit\n    ) {\n        when (val argumentType = typeArguments.first().withoutWildcards(variable)) {\n            scopeTypeName -> variable.throwValidationError(\"Lazy cannot be parametrized with Scope type.\")\n            is ParameterizedTypeName -> {\n                when (argumentType.rawType) {\n                    lazyTypeName -> variable.throwValidationError(\"Lazy cannot be parametrized with another Lazy type.\")\n                    listTypeName -> {\n                        if (methodMeta.getTypeMeta(paramName, 1).nullable) {\n                            variable.throwValidationError(\n                                \"Lazy<List> must be parametrized with none nullable List type.\"\n                            )\n                        }\n                        when (val listArgumentType = argumentType.typeArguments.first().withoutWildcards(variable)) {\n                            is ParameterizedTypeName -> {\n                                block(\n                                    ParameterizedTypeName.get(listTypeName, listArgumentType),\n                                    Cardinality.Many,\n                                    listArgumentType.rawType\n                                )\n                            }\n                            else -> {\n                                if (methodMeta.getTypeMeta(paramName, 2).nullable) {\n                                    variable.throwValidationError(\n                                        \"Lazy<List<T>> must be parametrized with none nullable type.\"\n                                    )\n                                }\n                                block(\n                                    ParameterizedTypeName.get(listTypeName, listArgumentType),\n                                    Cardinality.Many,\n                                    listArgumentType\n                                )\n                            }\n                        }\n                    }\n                    else -> {\n                        block(\n                            argumentType,\n                            methodMeta.getNullableCardinality(paramName, 1),\n                            argumentType.rawType\n                        )\n                    }\n                }\n            }\n            else -> {\n                block(\n                    argumentType,\n                    methodMeta.getNullableCardinality(paramName, 1),\n                    argumentType\n                )\n            }\n        }\n    }\n}\n\nprivate fun KotlinMethodMetadata.getNullableCardinality(paramName: String, paramDepth: Int): Cardinality =\n    if (getTypeMeta(paramName, paramDepth).nullable) Cardinality.Optional\n    else Cardinality.Single\n\nprivate fun TypeName.withoutWildcards(element: Element): TypeName =\n    if (this is WildcardTypeName) {\n        checkBounds(element)\n        upperBounds.first()\n    } else this\n\nprivate fun WildcardTypeName.firstUpperBoundsRawType(element: Element): Pair<TypeName, Boolean> {\n    checkBounds(element)\n    return when (val type = upperBounds.first()) {\n        is ParameterizedTypeName -> type.rawType to true\n        is WildcardTypeName -> type.firstUpperBoundsRawType(element)\n        else -> type to false\n    }\n}\n\nprivate fun WildcardTypeName.checkBounds(element: Element) {\n    if (lowerBounds.size > 0) {\n        element.throwValidationError(\n            \"Magnet supports single upper bounds class parameter only,\" +\n                \" while lower bounds class parameter was found.\"\n        )\n    }\n\n    if (upperBounds.size > 1) {\n        element.throwValidationError(\n            \"Magnet supports single upper bounds class parameter only,\" +\n                \" for example List<${upperBounds.first()}>\"\n        )\n    }\n}\n\nprivate fun ParameterizedTypeName.firstArgumentRawType(element: Element): Pair<TypeName, Boolean> {\n    if (typeArguments.size > 1) {\n        element.throwValidationError(\"Magnet supports type parametrized with a single argument only.\")\n    }\n    return when (val argumentType = typeArguments.first()) {\n        is ParameterizedTypeName -> argumentType.rawType to true\n        is WildcardTypeName -> argumentType.firstUpperBoundsRawType(element)\n        else -> argumentType to false\n    }\n}\n\nprivate inline fun VariableElement.annotations(block: (Cardinality, String) -> Unit) {\n    var cardinality = Cardinality.Single\n    var classifier = Classifier.NONE\n    annotationMirrors.forEach { annotationMirror ->\n        if (annotationMirror.isOfAnnotationType<Classifier>()) {\n            val declaredClassifier: String? = annotationMirror.elementValues.values.firstOrNull()?.value.toString()\n            declaredClassifier?.let {\n                classifier = it.removeSurrounding(\"\\\"\", \"\\\"\")\n            }\n        } else {\n            val annotationType = annotationMirror.annotationType.toString()\n            if (annotationType.endsWith(CLASS_NULLABLE)) {\n                cardinality = Cardinality.Optional\n            }\n        }\n    }\n    block(cardinality, classifier)\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/parser/InstanceParserForClass.kt",
    "content": "/*\n * Copyright (C) 2018-2021 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.instances.parser\n\nimport com.squareup.javapoet.ClassName\nimport kotlinx.metadata.Flag\nimport kotlinx.metadata.Flags\nimport magnet.Instance\nimport magnet.processor.MagnetProcessorEnv\nimport magnet.processor.common.CONSTRUCTOR_NAME\nimport magnet.processor.common.DefaultKotlinMethodMetadata\nimport magnet.processor.common.FunctionSelector\nimport magnet.processor.common.KotlinMethodMetadata\nimport magnet.processor.common.ParameterMeta\nimport magnet.processor.common.hasParameters\nimport magnet.processor.common.throwCompilationError\nimport magnet.processor.common.throwValidationError\nimport magnet.processor.instances.CreateMethod\nimport magnet.processor.instances.FactoryType\nimport magnet.processor.instances.GetLimitMethod\nimport magnet.processor.instances.GetScopingMethod\nimport magnet.processor.instances.GetSelectorMethod\nimport magnet.processor.instances.GetSiblingTypesMethod\nimport magnet.processor.instances.MethodParameter\nimport magnet.processor.instances.TypeCreateStatement\nimport javax.lang.model.element.Element\nimport javax.lang.model.element.ExecutableElement\nimport javax.lang.model.element.Modifier\nimport javax.lang.model.element.TypeElement\nimport javax.lang.model.util.ElementFilter\n\ninternal class InstanceParserForClass(\n    env: MagnetProcessorEnv\n) : InstanceParser<TypeElement>(env, true) {\n\n    override fun generateFactories(instance: ParserInstance<TypeElement>): List<FactoryType> {\n\n        val instanceType = ClassName.get(instance.element)\n        val instancePackage = instanceType.packageName()\n\n        return instance.types.map {\n\n            val hasSiblingTypes = instance.types.size > 1\n            val getSiblingTypesMethod = if (hasSiblingTypes) {\n                val types = instance.types - it\n                val siblingTypes = mutableListOf<ClassName>()\n                for (type in types) {\n                    siblingTypes.add(type)\n                    val factoryName = generateFactoryName(true, instanceType, type)\n                    siblingTypes.add(ClassName.bestGuess(\"$instancePackage.$factoryName\"))\n                }\n                GetSiblingTypesMethod(siblingTypes)\n            } else null\n\n            val selectorAttributes = instance.selector\n            val getSelectorMethod = if (selectorAttributes == null) null else GetSelectorMethod(selectorAttributes)\n            val getLimitMethod = if (instance.limitedTo.isEmpty()) null else GetLimitMethod(instance.limitedTo)\n\n            val factoryName = generateFactoryName(hasSiblingTypes, instanceType, it)\n            FactoryType(\n                element = instance.element,\n                interfaceType = it,\n                classifier = instance.classifier,\n                scoping = instance.scoping,\n                disposerMethodName = instance.disposer,\n                disabled = instance.disabled,\n                customFactoryType = instance.factory,\n                implementationType = instanceType,\n                factoryType = ClassName.bestGuess(\"$instancePackage.$factoryName\"),\n                createStatement = TypeCreateStatement(instanceType),\n                createMethod = parseCreateMethod(instance.element),\n                getScopingMethod = GetScopingMethod(instance.scoping),\n                getLimitMethod = getLimitMethod,\n                getSelectorMethod = getSelectorMethod,\n                getSiblingTypesMethod = getSiblingTypesMethod\n            )\n        }\n    }\n\n    private fun parseCreateMethod(element: TypeElement): CreateMethod {\n\n        val constructors = ElementFilter\n            .constructorsIn(element.enclosedElements)\n            .filterNot {\n                it.modifiers.contains(Modifier.PRIVATE) ||\n                    it.modifiers.contains(Modifier.PROTECTED)\n            }\n\n        val methodMeta: KotlinMethodMetadata? = element\n            .getAnnotation(Metadata::class.java)\n            ?.let {\n                DefaultKotlinMethodMetadata(\n                    metadata = it,\n                    element = element,\n                    functionSelector = ConstructorFunctionSelector(element, constructors)\n                )\n            }\n\n        val methodParameters = mutableListOf<MethodParameter>().apply {\n            val constructor =\n                if (methodMeta == null) selectJavaConstructor(constructors, element)\n                else selectKotlinConstructor(methodMeta)\n\n            for (parameter in constructor.parameters) {\n                add(parseMethodParameter(element, parameter, methodMeta))\n            }\n        }\n\n        return CreateMethod(methodParameters)\n    }\n}\n\nprivate fun Element.throwExactlyOneConstructorRequired(): Nothing =\n    throwValidationError(\n        \"Classes annotated with ${magnet.Instance::class.java} must have exactly one\" +\n            \" public or package-private constructor.\"\n    )\n\nprivate fun generateFactoryName(\n    hasSiblingsTypes: Boolean,\n    instanceType: ClassName,\n    interfaceType: ClassName\n): String =\n    if (hasSiblingsTypes) \"${instanceType.getFullName()}${interfaceType.getFullName()}$FACTORY_SUFFIX\"\n    else \"${instanceType.getFullName()}$FACTORY_SUFFIX\"\n\nprivate fun ClassName.getFullName(): String {\n    if (enclosingClassName() == null) {\n        return simpleName()\n    }\n    val nameBuilder = StringBuilder(simpleName())\n    var typeClassName = this\n    while (typeClassName.enclosingClassName() != null) {\n        nameBuilder.insert(0, typeClassName.enclosingClassName().simpleName())\n        typeClassName = typeClassName.enclosingClassName()\n    }\n    return nameBuilder.toString()\n}\n\nprivate fun selectJavaConstructor(constructors: List<ExecutableElement>, element: TypeElement): ExecutableElement =\n    if (constructors.size == 1) constructors[0] else element.throwExactlyOneConstructorRequired()\n\nprivate fun selectKotlinConstructor(methodMeta: KotlinMethodMetadata): ExecutableElement =\n    methodMeta.method\n\nprivate class ConstructorFunctionSelector(\n    private val element: TypeElement,\n    private val constructors: List<ExecutableElement>\n) : FunctionSelector {\n\n    override val function: ExecutableElement\n        get() = overloadConstructor\n            ?.let { return it }\n            ?: element.throwExactlyOneConstructorRequired()\n\n    private var overloadConstructor: ExecutableElement? = null\n\n    override fun visitFunction(flags: Flags, name: String): Boolean =\n        name == CONSTRUCTOR_NAME && !Flag.Constructor.IS_SECONDARY(flags)\n\n    override fun acceptFunctionParameters(parameters: Map<String, ParameterMeta>): Map<String, ParameterMeta> {\n        val overloadedParameters = parameters.filter { it.value.types.firstOrNull()?.default != true }\n        overloadConstructor = constructors.find { it.hasParameters(overloadedParameters) }\n        if (overloadConstructor == null) {\n            val primaryConstructor = constructors.find { it.hasParameters(parameters) }\n                ?: element.throwCompilationError(\n                    \"Overloaded secondary constructor expected.\\n\" +\n                        \" Primary constructor: $parameters\\n\" +\n                        \" Secondary constructor: $overloadedParameters\"\n                )\n\n            primaryConstructor.throwValidationError(\n                \"Constructor with default arguments in a class annotated with ${Instance::class}\" +\n                    \" must have @JmvOverloads annotation.\" +\n                    \" Use: class ${element.simpleName} @JvmOverloads constructor(...)\"\n            )\n        }\n        return overloadedParameters\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/parser/InstanceParserForMethod.kt",
    "content": "/*\n * Copyright (C) 2018-2021 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.instances.parser\n\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.ParameterizedTypeName\nimport com.squareup.javapoet.TypeName\nimport magnet.Classifier\nimport magnet.Instance\nimport magnet.processor.MagnetProcessorEnv\nimport magnet.processor.common.CompilationException\nimport magnet.processor.common.DefaultKotlinMethodMetadata\nimport magnet.processor.common.KotlinMethodMetadata\nimport magnet.processor.common.MethodFunctionSelector\nimport magnet.processor.common.throwValidationError\nimport magnet.processor.instances.CreateMethod\nimport magnet.processor.instances.FactoryType\nimport magnet.processor.instances.GetLimitMethod\nimport magnet.processor.instances.GetScopingMethod\nimport magnet.processor.instances.GetSelectorMethod\nimport magnet.processor.instances.GetSiblingTypesMethod\nimport magnet.processor.instances.MethodParameter\nimport magnet.processor.instances.StaticMethodCreateStatement\nimport javax.lang.model.element.Element\nimport javax.lang.model.element.ExecutableElement\nimport javax.lang.model.element.Modifier\nimport javax.lang.model.element.TypeElement\n\n/** Awesome static factory method parser. */\ninternal class InstanceParserForMethod(\n    env: MagnetProcessorEnv\n) : InstanceParser<ExecutableElement>(env, false) {\n\n    override fun ExecutableElement.onBeforeParsing() {\n        if (!modifiers.contains(Modifier.STATIC))\n            throwValidationError(\n                \"Method annotated by ${Instance::class.java} must be 'static'\"\n            )\n\n        if (modifiers.contains(Modifier.PRIVATE))\n            throwValidationError(\n                \"Method annotated by ${Instance::class.java} must not be 'private'\"\n            )\n    }\n\n    override fun generateFactories(instance: ParserInstance<ExecutableElement>): List<FactoryType> {\n        val element = instance.element\n        val staticMethodReturnType = TypeName.get(element.returnType)\n        for (type in instance.types) {\n            if (type != staticMethodReturnType) {\n                if (staticMethodReturnType is ParameterizedTypeName) {\n                    if (instance.classifier == Classifier.NONE) {\n                        element.throwValidationError(\n                            \"Method providing a parametrised type must have 'classifier' value\" +\n                                \" set in @${Instance::class.java.simpleName} annotation.\"\n                        )\n                    }\n                } else {\n                    element.throwValidationError(\n                        \"Method must return instance of ${type.reflectionName()} as declared\" +\n                            \" by @${Instance::class.java.simpleName} annotation.\" +\n                            \" Returned type: $staticMethodReturnType.\"\n                    )\n                }\n            }\n        }\n\n        val staticMethodClassName = ClassName.get(element.enclosingElement as TypeElement)\n        val staticMethodName = element.simpleName.toString()\n        val uniqueFactoryNameBuilder = StringBuilder()\n            .append(staticMethodClassName.packageName())\n            .append('.')\n            .append(staticMethodClassName.simpleName().capitalize())\n            .append(staticMethodName.capitalize())\n\n        val topmostElement = element.getTopmostTypeElement()\n        val methodMeta: KotlinMethodMetadata? = topmostElement\n            .getAnnotation(Metadata::class.java)\n            ?.let {\n                DefaultKotlinMethodMetadata(\n                    metadata = it,\n                    element = topmostElement,\n                    functionSelector = MethodFunctionSelector(element)\n                )\n            }\n\n        val methodParameters = mutableListOf<MethodParameter>()\n        element.parameters.forEach { variable ->\n            val methodParameter = parseMethodParameter(element, variable, methodMeta)\n            methodParameters.add(methodParameter)\n            uniqueFactoryNameBuilder.append(methodParameter.name.capitalize())\n        }\n\n        val instanceFullName = uniqueFactoryNameBuilder.toString()\n        return instance.types.map {\n\n            val isSingleTypeFactory = instance.types.size == 1\n            val getSiblingTypesMethod = if (isSingleTypeFactory) null else {\n                val types = instance.types - it\n                val siblingTypes = mutableListOf<ClassName>()\n                for (type in types) {\n                    siblingTypes.add(type)\n                    val factoryFullName = generateFactoryName(false, instanceFullName, type)\n                    siblingTypes.add(ClassName.bestGuess(factoryFullName))\n                }\n                GetSiblingTypesMethod(siblingTypes)\n            }\n\n            val selectorAttributes = instance.selector\n            val getSelectorMethod = if (selectorAttributes == null) null else GetSelectorMethod(selectorAttributes)\n            val getLimitMethod = if (instance.limitedTo.isEmpty()) null else GetLimitMethod(instance.limitedTo)\n\n            val factoryFullName = generateFactoryName(isSingleTypeFactory, instanceFullName, it)\n            FactoryType(\n                element = element,\n                interfaceType = it,\n                classifier = instance.classifier,\n                scoping = instance.scoping,\n                disposerMethodName = instance.disposer,\n                disabled = instance.disabled,\n                customFactoryType = instance.factory,\n                implementationType = null,\n                factoryType = ClassName.bestGuess(factoryFullName),\n                createStatement = StaticMethodCreateStatement(staticMethodClassName, staticMethodName),\n                createMethod = CreateMethod(methodParameters),\n                getScopingMethod = GetScopingMethod(instance.scoping),\n                getLimitMethod = getLimitMethod,\n                getSelectorMethod = getSelectorMethod,\n                getSiblingTypesMethod = getSiblingTypesMethod\n            )\n        }\n    }\n}\n\nprivate fun String.capitalize() =\n    replaceFirstChar {\n        if (it.isLowerCase()) it.uppercaseChar().toString()\n        else it.toString()\n    }\n\nprivate fun Element.getTopmostTypeElement(): TypeElement {\n    var result: TypeElement? = null\n    var element: Element? = this\n    while (element != null) {\n        if (element is TypeElement) {\n            result = element\n        }\n        element = element.enclosingElement\n    }\n    return result\n        ?: throw CompilationException(\n            element = this,\n            message = \"Static method must be declared in a class.\"\n        )\n}\n\nprivate fun generateFactoryName(isSingleTypeFactory: Boolean, instanceName: String, it: ClassName): String =\n    if (isSingleTypeFactory) \"${instanceName}MagnetFactory\"\n    else \"$instanceName${it.simpleName()}MagnetFactory\"\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/instances/parser/ParserInstance.kt",
    "content": "package magnet.processor.instances.parser\n\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.TypeName\nimport magnet.Classifier\nimport magnet.Scoping\nimport javax.lang.model.element.Element\nimport javax.lang.model.element.TypeElement\n\ndata class ParserInstance<E : Element>(\n    val element: E,\n    val declaredType: TypeElement? = null,\n    val declaredTypes: List<TypeElement>? = null,\n    val types: List<ClassName> = emptyList(),\n    val classifier: String = Classifier.NONE,\n    val scoping: String = Scoping.TOPMOST.name,\n    val limitedTo: String = \"\",\n    val selector: List<String>? = null,\n    val factory: TypeName? = null,\n    val disposer: String? = null,\n    val disabled: Boolean = false\n)\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/registry/Model.kt",
    "content": "package magnet.processor.registry\n\nimport com.squareup.javapoet.ClassName\n\nclass Model private constructor() {\n\n    class Registry(\n        val instanceFactories: List<InstanceFactory>\n    )\n\n    class InstanceFactory(\n        val factoryClass: ClassName,\n        val instanceType: ClassName,\n        val classifier: String\n    )\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/registry/RegistryGenerator.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.registry\n\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.MethodSpec\nimport com.squareup.javapoet.ParameterSpec\nimport com.squareup.javapoet.TypeSpec\nimport magnet.internal.Generated\nimport magnet.processor.instances.generator.CodeWriter\nimport magnet.processor.registry.instances.InstanceIndexGenerator\nimport javax.lang.model.element.Modifier\n\nprivate const val INSTANCE_MANAGER = \"instanceManager\"\nprivate const val INSTANCE_MANAGER_NAME = \"MagnetInstanceManager\"\nprivate const val INSTANCE_MANAGER_PACKAGE = \"magnet.internal\"\n\nclass RegistryGenerator {\n\n    private val instanceIndexGenerator = InstanceIndexGenerator()\n\n    fun generate(registry: Model.Registry): CodeWriter {\n\n        val instanceFactoriesIndex = instanceIndexGenerator.generate(registry)\n        val registryClassName = ClassName.bestGuess(REGISTRY_CLASS_NAME)\n        val factoryRegistryClassName = ClassName.get(INSTANCE_MANAGER_PACKAGE, INSTANCE_MANAGER_NAME)\n\n        val typeSpec = TypeSpec\n            .classBuilder(registryClassName)\n            .addModifiers(Modifier.PUBLIC, Modifier.FINAL)\n            .addAnnotation(Generated::class.java)\n            .addMethod(MethodSpec\n                .methodBuilder(\"register\")\n                .addModifiers(Modifier.PUBLIC, Modifier.STATIC)\n                .addParameter(ParameterSpec\n                    .builder(factoryRegistryClassName, INSTANCE_MANAGER)\n                    .build())\n                .addCode(instanceFactoriesIndex)\n                .addStatement(\"\\$L.register(factories, index)\", INSTANCE_MANAGER)\n                .build())\n            .build()\n\n        val packageName = registryClassName.packageName()\n        return CodeWriter(packageName, typeSpec)\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/registry/RegistryParser.kt",
    "content": "package magnet.processor.registry\n\nimport com.squareup.javapoet.ClassName\nimport magnet.internal.Index\nimport magnet.internal.InstanceFactory\nimport magnet.processor.common.AnnotationValueExtractor\nimport magnet.processor.common.isOfAnnotationType\nimport javax.lang.model.AnnotatedConstruct\nimport javax.lang.model.element.PackageElement\nimport javax.lang.model.element.TypeElement\n\nclass RegistryParser(\n    private val extractor: AnnotationValueExtractor\n) {\n\n    fun parse(element: PackageElement): Model.Registry {\n\n        val instanceFactories = mutableListOf<Model.InstanceFactory>()\n        val factoryIndexElements = element.enclosedElements ?: emptyList()\n\n        for (factoryIndexElement in factoryIndexElements) {\n            factoryIndexElement.annotationValues { factoryType, factoryClass, instanceType, classifier ->\n                when {\n                    factoryType.isOfType(InstanceFactory::class.java) ->\n                        instanceFactories.add(\n                            Model.InstanceFactory(\n                                factoryClass = factoryClass,\n                                instanceType = instanceType,\n                                classifier = classifier\n                            )\n                        )\n                }\n            }\n        }\n\n        return Model.Registry(\n            instanceFactories = instanceFactories\n        )\n    }\n\n    private inline fun AnnotatedConstruct.annotationValues(\n        block: (\n            factoryType: ClassName,\n            factoryClass: ClassName,\n            instanceType: ClassName,\n            classifier: String\n        ) -> Unit\n    ) {\n\n        var factoryType: TypeElement? = null\n        var factoryClass: TypeElement? = null\n        var instanceType: String? = null\n        var classifier: String? = null\n\n        for (annotationMirror in annotationMirrors) {\n            if (annotationMirror.isOfAnnotationType<Index>()) {\n                for (entry in annotationMirror.elementValues.entries) {\n                    val entryName = entry.key.simpleName.toString()\n                    val entryValue = entry.value\n                    when (entryName) {\n                        \"factoryType\" -> factoryType = extractor.getTypeElement(entryValue)\n                        \"factoryClass\" -> factoryClass = extractor.getTypeElement(entryValue)\n                        \"instanceType\" -> instanceType = extractor.getStringValue(entryValue)\n                        \"classifier\" -> classifier = extractor.getStringValue(entryValue)\n                    }\n                }\n                break\n            }\n        }\n\n        block(\n            ClassName.get(requireNotNull(factoryType)),\n            ClassName.get(requireNotNull(factoryClass)),\n            ClassName.bestGuess(requireNotNull(instanceType)),\n            requireNotNull(classifier)\n        )\n    }\n}\n\nprivate fun ClassName.isOfType(type: Class<*>): Boolean =\n    packageName() == type.`package`.name && simpleName() == type.simpleName\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/registry/RegistryProcessor.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.registry\n\nimport magnet.Registry\nimport magnet.processor.MagnetProcessorEnv\nimport javax.annotation.processing.RoundEnvironment\n\nconst val REGISTRY_CLASS_NAME = \"magnet.internal.MagnetIndexer\"\nconst val INDEX_PACKAGE = \"magnet.index\"\n\nclass RegistryProcessor(\n    private val env: MagnetProcessorEnv\n) {\n\n    private val registryParser by lazy { RegistryParser(env.annotation) }\n    private val magnetIndexerGenerator by lazy { RegistryGenerator() }\n    private var generateRegistryOnNextRound = false\n\n    fun process(roundEnv: RoundEnvironment): Boolean {\n\n        val generatedRegistryElement = env.elements.getTypeElement(REGISTRY_CLASS_NAME)\n        if (generatedRegistryElement != null) {\n            return false\n        }\n\n        val annotatedRegistryElement = roundEnv.getElementsAnnotatedWith(Registry::class.java)\n        if (!generateRegistryOnNextRound) {\n            generateRegistryOnNextRound = annotatedRegistryElement.isNotEmpty()\n            return false\n        }\n\n        val packageElement = env.elements.getPackageElement(INDEX_PACKAGE)\n        val registry = if (packageElement != null) registryParser.parse(packageElement)\n        else Model.Registry(instanceFactories = emptyList())\n\n        magnetIndexerGenerator\n            .generate(registry)\n            .writeInto(env.filer)\n\n        return true\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/registry/instances/IndexGeneratorVisitor.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.registry.instances\n\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.CodeBlock\nimport magnet.processor.registry.instances.Model.Index\nimport magnet.processor.registry.instances.Model.IndexVisitor\nimport magnet.processor.registry.instances.Model.Inst\nimport magnet.processor.registry.instances.Model.Range\nimport magnet.processor.registry.instances.Model.Section\n\nclass IndexGeneratorVisitor : IndexVisitor {\n\n    val indexBuilder: CodeBlock.Builder = CodeBlock.builder()\n    val targetsBuilder: CodeBlock.Builder = CodeBlock.builder()\n\n    private val rangeClassName: ClassName = ClassName.bestGuess(\"magnet.internal.Range\")\n    private var generateSingleRange = false\n    private var currentSection: Section? = null\n    private var sectionIndex = 0\n\n    override fun visit(inst: Inst) {\n        // nop\n    }\n\n    override fun visit(index: Index) {\n        // nop\n    }\n\n    override fun visit(section: Section) {\n\n        generateSingleRange = section.ranges.size == 1\n        currentSection = section\n\n        if (generateSingleRange) {\n            return\n        }\n\n        val targetsName = \"ranges${++sectionIndex}\"\n\n        indexBuilder.addStatement(\n            \"index.put(\\$T.getType(), \\$L)\",\n            section.firstFactory,\n            targetsName\n        )\n\n        val mapSize = Math.max(Math.round(section.ranges.size / .75f), 8)\n        targetsBuilder.addStatement(\n            \"\\$T<\\$T, \\$T> \\$L = new \\$T<>($mapSize)\",\n            Map::class.java,\n            String::class.java,\n            rangeClassName,\n            targetsName,\n            HashMap::class.java\n        )\n    }\n\n    override fun visit(range: Range) {\n\n        if (generateSingleRange) {\n            currentSection?.let {\n                indexBuilder.addStatement(\n                    \"index.put(\\$T.getType(), new \\$T(\\$L, \\$L, \\$S))\",\n                    range.firstFactory,\n                    rangeClassName,\n                    range.from,\n                    range.impls.size,\n                    range.classifier\n                )\n            }\n            return\n        }\n\n        val targetsName = \"ranges$sectionIndex\"\n\n        targetsBuilder.addStatement(\n            \"\\$L.put(\\$S, new \\$T(\\$L, \\$L, \\$S))\",\n            targetsName,\n            range.classifier,\n            rangeClassName,\n            range.from,\n            range.impls.size,\n            range.classifier\n        )\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/registry/instances/Indexer.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.registry.instances\n\nimport magnet.processor.registry.instances.Model.Index\nimport magnet.processor.registry.instances.Model.Inst\nimport magnet.processor.registry.instances.Model.InstComparator\n\nclass Indexer(\n    private val comparator: Comparator<Inst> = InstComparator()\n) {\n\n    fun index(instances: List<Inst>): Index {\n        val sorted = instances.sortedWith(comparator)\n        val indexer = SectionsCreatorVisitor()\n        sorted.forEach {\n            it.accept(indexer)\n        }\n        return Index(sorted, indexer.sections)\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/registry/instances/InstanceIndexGenerator.kt",
    "content": "package magnet.processor.registry.instances\n\nimport com.squareup.javapoet.ClassName\nimport com.squareup.javapoet.CodeBlock\nimport magnet.internal.InstanceFactory\nimport magnet.processor.registry.Model.Registry\n\ninternal class InstanceIndexGenerator {\n\n    fun generate(registry: Registry): CodeBlock {\n\n        val index = Indexer().index(\n            registry.instanceFactories.map {\n                Model.Inst(\n                    type = it.instanceType.toQualifiedName(),\n                    classifier = it.classifier,\n                    factory = it.factoryClass\n                )\n            }\n        )\n\n        return CodeBlock.builder()\n            .add(generateArrayOfFactoriesCodeBlock(index))\n            .add(generateIndexCodeBlock(index))\n            .build()\n    }\n\n    private fun generateIndexCodeBlock(index: Model.Index): CodeBlock {\n        val indexGenerator = IndexGeneratorVisitor()\n        index.accept(indexGenerator)\n\n        val mapSize = Math.max(Math.round(index.instances.size / 0.75f), 16)\n        return CodeBlock.builder()\n            .addStatement(\n                \"\\$T<\\$T, \\$T> index = new \\$T<>($mapSize)\",\n                Map::class.java,\n                Class::class.java,\n                Object::class.java,\n                HashMap::class.java\n            )\n            .add(indexGenerator.targetsBuilder.build())\n            .add(indexGenerator.indexBuilder.build())\n            .build()\n    }\n\n    private fun generateArrayOfFactoriesCodeBlock(index: Model.Index): CodeBlock {\n        if (index.instances.isEmpty()) {\n            return CodeBlock.builder()\n                .addStatement(\"\\$T[] factories = new \\$T[0]\", InstanceFactory::class.java, InstanceFactory::class.java)\n                .build()\n        } else {\n            val builder = CodeBlock.builder()\n                .add(\"\\$T[] factories = new \\$T[] {\", InstanceFactory::class.java, InstanceFactory::class.java)\n                .indent()\n\n            index.instances.forEach {\n                builder.add(\"\\nnew \\$T(),\", it.factory)\n            }\n\n            return builder\n                .unindent()\n                .add(\"\\n};\\n\")\n                .build()\n        }\n    }\n}\n\nprivate fun ClassName.toQualifiedName(): String =\n    \"${this.packageName()}.${this.simpleName()}\"\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/registry/instances/Model.kt",
    "content": "package magnet.processor.registry.instances\n\nimport com.squareup.javapoet.ClassName\n\nclass Model private constructor() {\n\n    class Index(\n        val instances: List<Inst>,\n        val sections: List<Section>\n    ) {\n\n        fun accept(visitor: IndexVisitor) {\n            visitor.visit(this)\n            sections.forEach {\n                it.accept(visitor)\n            }\n        }\n    }\n\n    class Inst(\n        val type: String,\n        val classifier: String,\n        val factory: ClassName\n    ) {\n        fun accept(visitor: InstVisitor) {\n            visitor.visit(this)\n        }\n    }\n\n    class InstComparator : Comparator<Inst> {\n        override fun compare(left: Inst, right: Inst): Int {\n            val c1 = left.type.compareTo(right.type)\n            if (c1 != 0) {\n                return c1\n            }\n            val c2 = left.classifier.compareTo(right.classifier)\n            if (c2 != 0) {\n                return c2\n            }\n            return left.factory.compareTo(right.factory)\n        }\n    }\n\n    interface InstVisitor {\n        fun visit(inst: Inst)\n    }\n\n    class Range(\n        val type: String,\n        val classifier: String,\n        private val inst: Inst,\n        val from: Int\n    ) {\n        val impls = mutableListOf<Inst>()\n        val firstFactory\n            get() = impls[0].factory\n\n        init {\n            impls.add(inst)\n        }\n\n        fun accept(visitor: IndexVisitor) {\n            visitor.visit(this)\n            impls.forEach {\n                it.accept(visitor)\n            }\n        }\n    }\n\n    class Section(\n        val type: String\n    ) {\n        val ranges = mutableMapOf<String, Range>()\n        val firstFactory\n            get() = ranges.values.elementAt(0).firstFactory\n\n        fun accept(visitor: IndexVisitor) {\n            visitor.visit(this)\n            ranges.forEach {\n                it.value.accept(visitor)\n            }\n        }\n    }\n\n    interface IndexVisitor : InstVisitor {\n        fun visit(index: Index)\n        fun visit(section: Section)\n        fun visit(range: Range)\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/java/magnet/processor/registry/instances/SectionsCreatorVisitor.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.processor.registry.instances\n\nimport magnet.processor.registry.instances.Model.Inst\nimport magnet.processor.registry.instances.Model.InstVisitor\nimport magnet.processor.registry.instances.Model.Range\nimport magnet.processor.registry.instances.Model.Section\n\nclass SectionsCreatorVisitor : InstVisitor {\n\n    val sections: List<Section>\n        get() {\n            return sectionsByType.map {\n                it.value\n            }\n        }\n\n    private val sectionsByType = mutableMapOf<String, Section>()\n    private var currentRange: Range? = null\n\n    override fun visit(inst: Inst) {\n\n        if (currentRange == null) {\n            addRange(inst)\n            return\n        }\n\n        currentRange?.let {\n            if (it.type == inst.type &&\n                it.classifier == inst.classifier) {\n                it.impls.add(inst)\n                return\n            }\n            addRange(inst)\n            return\n        }\n    }\n\n    private fun addRange(inst: Inst) {\n\n        val section = sectionsByType.getOrPut(inst.type) {\n            Section(inst.type)\n        }\n\n        val rangeIndex = calculateIndex()\n        val range = Range(inst.type, inst.classifier, inst, rangeIndex)\n        section.ranges[range.classifier] = range\n\n        currentRange = range\n    }\n\n    private fun calculateIndex(): Int {\n        currentRange?.let {\n            return it.from + it.impls.size\n        }\n        return 0\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/main/resources/META-INF/gradle/incremental.annotation.processors",
    "content": "magnet.processor.MagnetProcessor,aggregating"
  },
  {
    "path": "magnet-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor",
    "content": "magnet.processor.MagnetProcessor"
  },
  {
    "path": "magnet-processor/src/test/java/magnet/processor/GenerateRegistryForInstanceFactoriesTest.kt",
    "content": "package magnet.processor\n\nimport com.google.testing.compile.CompilationSubject\nimport com.google.testing.compile.Compiler\nimport com.google.testing.compile.JavaFileObjects\nimport org.junit.Test\nimport javax.tools.JavaFileObject\n\nclass GenerateRegistryForInstanceFactoriesTest {\n\n    private fun withResource(name: String): JavaFileObject =\n        JavaFileObjects.forResource(javaClass.simpleName + '/' + name)\n\n    @Test\n    fun `No factories`() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"App.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeeded()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"magnet/internal/MagnetIndexer\")\n            .hasSourceEquivalentTo(withResource(\"expected/MagnetIndexer2.java\"))\n    }\n\n    @Test\n    fun `Single factory`() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"App.java\"),\n                withResource(\"Interface1.java\"),\n                withResource(\"Implementation1.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeeded()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"magnet/internal/MagnetIndexer\")\n            .hasSourceEquivalentTo(withResource(\"expected/MagnetIndexer1.java\"))\n    }\n\n    @Test\n    fun `Single factory, inner implementation`() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"App.java\"),\n                withResource(\"Interface7.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeeded()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"magnet/internal/MagnetIndexer\")\n            .hasSourceEquivalentTo(withResource(\"expected/MagnetIndexer7.java\"))\n    }\n\n    @Test\n    fun `Many factories, same type`() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"App.java\"),\n                withResource(\"Interface3.java\"),\n                withResource(\"Implementation3_1.java\"),\n                withResource(\"Implementation3_2.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeeded()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"magnet/internal/MagnetIndexer\")\n            .hasSourceEquivalentTo(withResource(\"expected/MagnetIndexer3.java\"))\n    }\n\n    @Test\n    fun `Many factories, same type, same classifier`() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"App.java\"),\n                withResource(\"Interface5.java\"),\n                withResource(\"Implementation5_1.java\"),\n                withResource(\"Implementation5_2.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeeded()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"magnet/internal/MagnetIndexer\")\n            .hasSourceEquivalentTo(withResource(\"expected/MagnetIndexer5.java\"))\n    }\n\n    @Test\n    fun `Many factories, same type, different classifiers`() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"App.java\"),\n                withResource(\"Interface4.java\"),\n                withResource(\"Implementation4_1.java\"),\n                withResource(\"Implementation4_2.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeeded()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"magnet/internal/MagnetIndexer\")\n            .hasSourceEquivalentTo(withResource(\"expected/MagnetIndexer4.java\"))\n    }\n\n    @Test\n    fun `Many factories, different types`() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"App.java\"),\n                withResource(\"Interface6_1.java\"),\n                withResource(\"Interface6_2.java\"),\n                withResource(\"Implementation6_1.java\"),\n                withResource(\"Implementation6_2.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeeded()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"magnet/internal/MagnetIndexer\")\n            .hasSourceEquivalentTo(withResource(\"expected/MagnetIndexer6.java\"))\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/java/magnet/processor/IndexerTest.kt",
    "content": "package magnet.processor\n\nimport com.google.common.truth.Truth.assertThat\nimport com.squareup.javapoet.ClassName\nimport magnet.processor.registry.instances.Indexer\nimport magnet.processor.registry.instances.Model.Inst\nimport org.junit.Test\n\nclass IndexerTest {\n\n    @Test\n    fun test_IndexNodes() {\n        val index = Indexer().index(unsortedNodes())\n\n        assertThat(index.instances.toTypedArray()\n            contentDeepEquals sortedNodes().toTypedArray())\n    }\n\n    @Test\n    fun test_IndexSections() {\n        val index = Indexer().index(unsortedNodes())\n\n        assertThat(index.sections.size).isEqualTo(3)\n\n        assertThat(index.sections[0].type).isEqualTo(\"AType\")\n        assertThat(index.sections[0].ranges.size).isEqualTo(3)\n\n        assertThat(index.sections[1].type).isEqualTo(\"BType\")\n        assertThat(index.sections[1].ranges.size).isEqualTo(1)\n\n        assertThat(index.sections[2].type).isEqualTo(\"CType\")\n        assertThat(index.sections[2].ranges.size).isEqualTo(4)\n    }\n\n    private fun unsortedNodes(): List<Inst> {\n        val factory = ClassName.bestGuess(\"Factory\")\n        return listOf(\n            Inst(\"CType\", \"four\", factory),\n            Inst(\"CType\", \"two\", factory),\n            Inst(\"CType\", \"one\", factory),\n            Inst(\"CType\", \"three\", factory),\n            Inst(\"CType\", \"four\", factory),\n\n            Inst(\"BType\", \"\", factory),\n            Inst(\"BType\", \"\", factory),\n            Inst(\"BType\", \"\", factory),\n\n            Inst(\"AType\", \"\", factory),\n            Inst(\"AType\", \"one\", factory),\n            Inst(\"AType\", \"\", factory),\n            Inst(\"AType\", \"two\", factory),\n            Inst(\"AType\", \"one\", factory)\n        )\n    }\n\n    private fun sortedNodes(): List<Inst> {\n        val factory = ClassName.bestGuess(\"Factory\")\n        return listOf(\n            Inst(\"AType\", \"\", factory),\n            Inst(\"AType\", \"\", factory),\n            Inst(\"AType\", \"one\", factory),\n            Inst(\"AType\", \"one\", factory),\n            Inst(\"AType\", \"two\", factory),\n            Inst(\"BType\", \"\", factory),\n            Inst(\"BType\", \"\", factory),\n            Inst(\"BType\", \"\", factory),\n            Inst(\"CType\", \"four\", factory),\n            Inst(\"CType\", \"four\", factory),\n            Inst(\"CType\", \"one\", factory),\n            Inst(\"CType\", \"three\", factory),\n            Inst(\"CType\", \"two\", factory)\n        )\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/java/magnet/processor/InstanceCustomFactoryProcessorTest.kt",
    "content": "package magnet.processor\n\nimport com.google.testing.compile.CompilationSubject\nimport com.google.testing.compile.Compiler\nimport com.google.testing.compile.JavaFileObjects\nimport org.junit.Test\nimport javax.tools.JavaFileObject\n\nclass InstanceCustomFactoryProcessorTest {\n\n    private fun withResource(name: String): JavaFileObject =\n        JavaFileObjects.forResource(javaClass.simpleName + '/' + name)\n\n    @Test\n    fun `Not parametrized custom Factory`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface1.java\"),\n                withResource(\"Implementation1.java\"),\n                withResource(\"CustomFactory1.java\")\n            )\n        CompilationSubject.assertThat(compilation).succeeded()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"test/Implementation1MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"expected/Implementation1MagnetFactory.java\"))\n    }\n\n    @Test\n    fun `Parametrized custom Factory`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface2.java\"),\n                withResource(\"Implementation2.java\"),\n                withResource(\"CustomFactory2.java\")\n            )\n        CompilationSubject.assertThat(compilation).succeeded()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"test/Implementation2MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"expected/Implementation2MagnetFactory.java\"))\n    }\n\n    @Test\n    fun `Custom Factory for implementation with dependencies`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface3.java\"),\n                withResource(\"Implementation3.java\"),\n                withResource(\"CustomFactory3.java\")\n            )\n        CompilationSubject.assertThat(compilation).succeeded()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"test/Implementation3MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"expected/Implementation3MagnetFactory.java\"))\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/java/magnet/processor/InstanceDisposerTest.kt",
    "content": "package magnet.processor\n\nimport com.google.testing.compile.CompilationSubject\nimport com.google.testing.compile.Compiler\nimport com.google.testing.compile.JavaFileObjects\nimport org.junit.Test\nimport javax.tools.JavaFileObject\n\nclass InstanceDisposerTest {\n\n    private fun withResource(name: String): JavaFileObject =\n        JavaFileObjects.forResource(javaClass.simpleName + '/' + name)\n\n    @Test\n    fun `Disposer method gets generated`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation1.java\")\n            )\n        CompilationSubject.assertThat(compilation).succeeded()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"test/Implementation1MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"expected/Implementation1MagnetFactory.java\"))\n    }\n\n    @Test\n    fun `Disposer must be present`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation2.java\")\n            )\n        CompilationSubject.assertThat(compilation).failed()\n        CompilationSubject.assertThat(compilation).hadErrorContaining(\"disposer method\")\n    }\n\n    @Test\n    fun `Disposer must have no parameters`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation3.java\")\n            )\n        CompilationSubject.assertThat(compilation).failed()\n        CompilationSubject.assertThat(compilation).hadErrorContaining(\"must have no parameters\")\n    }\n\n    @Test\n    fun `Disposer must return void`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation4.java\")\n            )\n        CompilationSubject.assertThat(compilation).failed()\n        CompilationSubject.assertThat(compilation).hadErrorContaining(\"must return void\")\n    }\n\n    @Test\n    fun `Disposer cannot be used with UNSCOPED instances`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation5.java\")\n            )\n        CompilationSubject.assertThat(compilation).failed()\n        CompilationSubject.assertThat(compilation).hadErrorContaining(\"UNSCOPED\")\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/java/magnet/processor/InstanceIndexProcessorTest.kt",
    "content": "package magnet.processor\n\nimport com.google.testing.compile.CompilationSubject\nimport com.google.testing.compile.CompilationSubject.assertThat\nimport com.google.testing.compile.Compiler\nimport com.google.testing.compile.JavaFileObjects\nimport org.junit.Test\nimport javax.tools.JavaFileObject\n\nclass InstanceIndexProcessorTest {\n\n    private fun withResource(name: String): JavaFileObject =\n        JavaFileObjects.forResource(javaClass.simpleName + '/' + name)\n\n    @Test\n    fun `InstanceFactory index gets generated with classifier`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface1.java\"),\n                withResource(\"Implementation1.java\")\n            )\n        assertThat(compilation).succeeded()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"magnet.index/app_test_Implementation1MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/app_test_Implementation1MagnetFactory.java\"))\n    }\n\n    @Test\n    fun `InstanceFactory index gets generated without classifier`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface2.java\"),\n                withResource(\"Implementation2.java\")\n            )\n        assertThat(compilation).succeeded()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"magnet.index/app_test_Implementation2MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/app_test_Implementation2MagnetFactory.java\"))\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/java/magnet/processor/MagnetProcessorFactoryNamesTest.kt",
    "content": "package magnet.processor\n\nimport com.google.testing.compile.CompilationSubject\nimport com.google.testing.compile.Compiler\nimport com.google.testing.compile.JavaFileObjects\nimport org.junit.Test\nimport javax.tools.JavaFileObject\n\nclass MagnetProcessorFactoryNamesTest {\n\n    private fun withResource(name: String): JavaFileObject =\n        JavaFileObjects.forResource(javaClass.simpleName + '/' + name)\n\n    @Test\n    fun `Generate fully named factories for top level classes`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Delegate1.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeededWithoutWarnings()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"test/Delegate1MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/Delegate1MagnetFactory.java\"))\n    }\n\n    @Test\n    fun `Generate fully named factories for inner classes`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface1.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeededWithoutWarnings()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"test/Interface1DelegateMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/Interface1DelegateMagnetFactory.java\"))\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/java/magnet/processor/MagnetProcessorTest.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnet.processor\n\nimport com.google.testing.compile.CompilationSubject.assertThat\nimport com.google.testing.compile.Compiler\nimport com.google.testing.compile.JavaFileObjects\nimport org.junit.Test\nimport javax.tools.JavaFileObject\n\nclass MagnetProcessorTest {\n\n    @Test\n    fun generateFactory_NoParams() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePageNoParams.java\"),\n                withResource(\"Page.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/extension/HomePageNoParamsMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/HomePageNoParamsMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_WithScope() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePageWithScope.java\"),\n                withResource(\"Page.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/extension/HomePageWithScopeMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/HomePageWithScopeMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_WithArbitraryParams() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePageWithParams.java\"),\n                withResource(\"Page.java\"),\n                withResource(\"HomeRepository.java\"),\n                withResource(\"UserData.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/extension/HomePageWithParamsMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/HomePageWithParamsMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_WithArbitraryParamsAndScope() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePage.java\"),\n                withResource(\"Page.java\"),\n                withResource(\"HomeRepository.java\"),\n                withResource(\"UserData.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/extension/HomePageMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/HomePageMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_FailsOnGenericTypeInConstructorParameter() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePageWithGenericParam.java\"),\n                withResource(\"Page.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"is specified using a generic type\")\n    }\n\n    @Test\n    fun generateFactory_TypeNotImplemented() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Tab.java\"),\n                withResource(\"UnimplementedTab.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"must implement\")\n    }\n\n    @Test\n    fun generateFactory_DisabledAnnotation() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Tab.java\"),\n                withResource(\"DisabledTab.java\")\n            )\n\n        assertThat(compilation).succeeded()\n        com.google.common.truth.Truth.assertThat(compilation.generatedFiles().size).isEqualTo(2)\n    }\n\n    @Test\n    fun generateFactory_WithClassifierParams() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePageWithClassifierParams.java\"),\n                withResource(\"Page.java\"),\n                withResource(\"HomeRepository.java\"),\n                withResource(\"UserData.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/extension/HomePageWithClassifierParamsMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/HomePageWithClassifierParamsMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_WithManyParams() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePageWithManyParams.java\"),\n                withResource(\"Page.java\"),\n                withResource(\"HomeRepository.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/extension/HomePageWithManyParamsMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/HomePageWithManyParamsMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_WithManyParameterizedParams() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePageWithManyParameterizedParams.java\"),\n                withResource(\"Page.java\"),\n                withResource(\"WorkProcessor.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/extension/HomePageWithManyParameterizedParamsMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/HomePageWithManyParameterizedParamsMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_WithManyParameterizedWildcardOutParams() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePageWithManyParameterizedWildcardOutParams.java\"),\n                withResource(\"Page.java\"),\n                withResource(\"WorkProcessor.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/extension/HomePageWithManyParameterizedWildcardOutParamsMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/HomePageWithManyParameterizedWildcardOutParamsMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_WithManyParameterizedWildcardInParams() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePageWithManyParameterizedWildcardInParams.java\"),\n                withResource(\"Page.java\"),\n                withResource(\"WorkProcessor.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/extension/HomePageWithManyParameterizedWildcardInParamsMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/HomePageWithManyParameterizedWildcardInParamsMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_WithManyParameterizedWildcardKnownParams() {\n\n        // This is what Kotlin provides to annotation processor, when Kotlin generics are used as parameters\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePageWithManyParameterizedWildcardKnownParams.java\"),\n                withResource(\"Page.java\"),\n                withResource(\"WorkProcessor.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/extension/HomePageWithManyParameterizedWildcardKnownParamsMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/HomePageWithManyParameterizedWildcardKnownParamsMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_WithManyWildcardParams() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePageWithManyWildcardParams.java\"),\n                withResource(\"Page.java\"),\n                withResource(\"HomeRepository.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/extension/HomePageWithManyWildcardParamsMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/HomePageWithManyWildcardParamsMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_UsingStaticMethod() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePageWithStaticConstructor.java\"),\n                withResource(\"HomePageWithStaticConstructorSingle.java\"),\n                withResource(\"Page.java\"),\n                withResource(\"HomeRepository.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/extension/utils/HomePageWithStaticConstructorSingleCreateRepositoriesMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/HomePageWithStaticConstructorSingleCreateRepositoriesMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_StaticMethodProvidesInnerClass() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"StaticMethodProvidesInnerClass/PowerManager.java\"),\n                withResource(\"StaticMethodProvidesInnerClass/PowerManagerProvider.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/PowerManagerProviderProvideWakeLockMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"StaticMethodProvidesInnerClass/expected/PowerManagerProviderProvideWakeLockMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Covariance_Constructor_ManyParameter() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Covariance_Constructor_ManyParameter/Foo.java\"),\n                withResource(\"Covariance_Constructor_ManyParameter/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"Covariance_Constructor_ManyParameter/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Covariance_Constructor_SingleParameter() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Covariance_Constructor_SingleParameter/Foo.java\"),\n                withResource(\"Covariance_Constructor_SingleParameter/UnderTest.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"is specified using a generic type\")\n    }\n\n    @Test\n    fun generateFactory_Lazy_Constructor_NoKotlinMetadata() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"Lazy_Constructor_NoKotlinMetadata/UnderTest.java\"))\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"can only be used with Kotlin classes\")\n    }\n\n    @Test\n    fun generateFactory_Lazy_Constructor_OptionalParameter() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"Lazy_Constructor_OptionalParameter/UnderTest.java\"))\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"Lazy_Constructor_OptionalParameter/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Lazy_Constructor_OptionalParameter_Wildcard() {\n        val root = \"Lazy_Constructor_OptionalParameter_Wildcard\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"$root/UnderTest.java\"))\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$root/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Lazy_Constructor_SingleParameter() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"Lazy_Constructor_SingleParameter/UnderTest.java\"))\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"Lazy_Constructor_SingleParameter/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Lazy_Constructor_SingleParameter_Wildcard() {\n        val root = \"Lazy_Constructor_SingleParameter_Wildcard\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"$root/UnderTest.java\"))\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$root/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Lazy_Constructor_ManyParameter() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"Lazy_Constructor_ManyParameter/UnderTest.java\"))\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"Lazy_Constructor_ManyParameter/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Lazy_Constructor_ManyParameter_Wildcard() {\n        val root = \"Lazy_Constructor_ManyParameter_Wildcard\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"$root/UnderTest.java\"))\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$root/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Lazy_Constructor_ManyParameter_NullableGenericType() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"Lazy_Constructor_ManyParameter_NullableGenericType/UnderTest.java\"))\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"be parametrized with none nullable type\")\n    }\n\n    @Test\n    fun generateFactory_Lazy_Constructor_ManyParameter_NullableListType() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"Lazy_Constructor_ManyParameter_NullableListType/UnderTest.java\"))\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"be parametrized with none nullable List type\")\n    }\n\n    @Test\n    fun generateFactory_Lazy_Method_SingleParameter() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"Lazy_Method_SingleParameter/UnderTest.java\"))\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestProvideUnderTestDepMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"Lazy_Method_SingleParameter/expected/UnderTestProvideUnderTestDepMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Lazy_Method_SingleParameter_Wildcard() {\n        val root = \"Lazy_Method_SingleParameter_Wildcard\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"$root/UnderTest.java\"))\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestProvideUnderTestDepMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$root/expected/UnderTestProvideUnderTestDepMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Generics_ProvideTypeWithParameter() {\n\n        val path = \"Generics_ProvideTypeWithParameter\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\"),\n                withResource(\"$path/Type.java\"),\n                withResource(\"$path/Parameter.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestProvideTypeMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$path/expected/UnderTestProvideTypeMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Generics_ProvideTypeWithParameter_NoClassifier() {\n\n        val path = \"Generics_ProvideTypeWithParameter_NoClassifier\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\"),\n                withResource(\"$path/Type.java\"),\n                withResource(\"$path/Parameter.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"must have 'classifier' value\")\n    }\n\n    @Test\n    fun generateFactory_Lazy_Constructor_SingleParameter_ParameterizedType() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Lazy_Constructor_SingleParameter_ParameterizedType/Foo.java\"),\n                withResource(\"Lazy_Constructor_SingleParameter_ParameterizedType/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"Lazy_Constructor_SingleParameter_ParameterizedType/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Lazy_Method_OptionalParameter() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"Lazy_Method_OptionalParameter/UnderTest.java\"))\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestProvideUnderTestDepMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"Lazy_Method_OptionalParameter/expected/UnderTestProvideUnderTestDepMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Lazy_Method_OptionalParameter_Wildcard() {\n        val root = \"Lazy_Method_OptionalParameter_Wildcard\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"$root/UnderTest.java\"))\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestProvideUnderTestDepMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$root/expected/UnderTestProvideUnderTestDepMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Limit_NotEmpty_GenerateGetter() {\n        val root = \"Limit_NotEmpty_HasGetter\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"$root/UnderTest.java\"))\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$root/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Limit_Empty_NoGetter() {\n        val root = \"Limit_Empty_NoGetter\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"$root/UnderTest.java\"))\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$root/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Limit_ReservedAsterix_Fails() {\n        val root = \"Limit_ReservedAsterisks_Fails\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"$root/UnderTest.java\"))\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"Use another value\")\n    }\n\n    @Test\n    fun generateFactory_Limit_ScopingDirect_GeneratesGetter() {\n        val root = \"Limit_ScopingDirect_GeneratesGetter\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"$root/UnderTest.java\"))\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$root/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Limit_ScopingUnscoped_Fails() {\n        val root = \"Limit_ScopingUnscoped_Fails\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"$root/UnderTest.java\"))\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"Limit can only be used with Scoping.TOPMOST\")\n    }\n\n    @Test\n    fun generateFactory_Lazy_Method_NoKotlinMetadata() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(withResource(\"Lazy_Method_NoKotlinMetadata/UnderTest.java\"))\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"can only be used with Kotlin classes\")\n    }\n\n    @Test\n    fun generateFactory_ScopeParameter_CustomName() {\n\n        val path = \"ScopeParameter_CustomName\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$path/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_ScopeParameter_CustomName_KotlinClass() {\n\n        val path = \"ScopeParameter_CustomName_KotlinClass\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$path/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_ScopeParameter_DefaultName() {\n\n        val path = \"ScopeParameter_DefaultName\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$path/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_DefaultArguments_JvmOverloads_AtTheEnd() {\n\n        val path = \"DefaultArguments_JvmOverloads_AtTheEnd\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$path/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_DefaultArguments_JvmOverloads_InTheMiddle() {\n\n        val path = \"DefaultArguments_JvmOverloads_InTheMiddle\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$path/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_DefaultArguments_JvmOverloads_Mixed() {\n\n        val path = \"DefaultArguments_JvmOverloads_Mixed\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$path/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_StaticMethodNeedsDependencyWithClassifier() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"StaticMethodNeedsDependencyWithClassifier/Constants.java\"),\n                withResource(\"StaticMethodNeedsDependencyWithClassifier/Input.java\"),\n                withResource(\"StaticMethodNeedsDependencyWithClassifier/Output.java\"),\n                withResource(\"StaticMethodNeedsDependencyWithClassifier/StaticFunction.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/StaticFunctionProvideInputMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"StaticMethodNeedsDependencyWithClassifier/generated/StaticFunctionProvideInputMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_DisabledAnnotation_UsingStaticMethod() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"HomePageWithStaticConstructor.java\"),\n                withResource(\"HomePageWithStaticConstructorDisabled.java\"),\n                withResource(\"Page.java\"),\n                withResource(\"HomeRepository.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        com.google.common.truth.Truth.assertThat(compilation.generatedFiles().size).isEqualTo(4)\n    }\n\n    @Test\n    fun generateFactoryIndex_ForInterfaceWithGenericType() {\n\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Executor.java\"),\n                withResource(\"ExecutorImpl.java\"),\n                withResource(\"AppExtensionRegistry.java\")\n            )\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/extension/ExecutorImplMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/ForInterfaceWithGenericType_ExecutorMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Constructor_Public_PackagePrivate() {\n\n        val path = \"Constructor_Public_PackagePrivate\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"must have exactly one public or package-private constructor\")\n    }\n\n    @Test\n    fun generateFactory_Constructor_Public_Public() {\n\n        val path = \"Constructor_Public_Public\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"must have exactly one public or package-private constructor\")\n    }\n\n    @Test\n    fun generateFactory_Constructor_Public_Protected() {\n\n        val path = \"Constructor_Public_Protected\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$path/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Constructor_Public_Private() {\n\n        val path = \"Constructor_Public_Private\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$path/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Constructor_PackagePrivate_PackagePrivate() {\n\n        val path = \"Constructor_PackagePrivate_PackagePrivate\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"must have exactly one public or package-private constructor\")\n    }\n\n    @Test\n    fun generateFactory_Constructor_Private() {\n\n        val path = \"Constructor_Private\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"must have exactly one public or package-private constructor\")\n    }\n\n    @Test\n    fun generateFactory_Constructor_Protected() {\n\n        val path = \"Constructor_Protected\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"must have exactly one public or package-private constructor\")\n    }\n\n    @Test\n    fun generateFactory_Constructor_PackagePrivate_Private() {\n\n        val path = \"Constructor_PackagePrivate_Private\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$path/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Constructor_Public_Public_Kotlin() {\n\n        val path = \"Constructor_Public_Public_Kotlin\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"must have exactly one public or package-private constructor\")\n    }\n\n    @Test\n    fun generateFactory_Generics_GetSingle_Unchecked() {\n        val path = \"Generics_GetSingle_Unchecked\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/Dependency.java\"),\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$path/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_Generics_GetOptional_Unchecked() {\n        val path = \"Generics_GetOptional_Unchecked\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/Dependency.java\"),\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$path/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    @Test\n    fun generateFactory_TypeAutoDetect_ExtendsObjectNoInterfaces() {\n        val path = \"TypeAutoDetect_ExtendsObjectNoInterfaces\"\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"$path/UnderTest.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"app/UnderTestMagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"$path/expected/UnderTestMagnetFactory.java\"))\n    }\n\n    private fun withResource(name: String): JavaFileObject {\n        return JavaFileObjects.forResource(javaClass.simpleName + '/' + name)\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/java/magnet/processor/SelectorInFactoryClassTest.kt",
    "content": "package magnet.processor\n\nimport com.google.testing.compile.CompilationSubject\nimport com.google.testing.compile.Compiler\nimport com.google.testing.compile.JavaFileObjects\nimport org.junit.Test\nimport javax.tools.JavaFileObject\n\nclass SelectorInFactoryClassTest {\n\n    @Test\n    fun `Empty selector is allowed`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation1.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeededWithoutWarnings()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"selector/Implementation1MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/Implementation1MagnetFactory.java\"))\n    }\n\n    @Test\n    fun `Invalid selector fails compilation`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation2.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).failed()\n        CompilationSubject.assertThat(compilation).hadErrorContaining(\"Invalid selector\")\n    }\n\n    @Test\n    fun `Empty selector id fails compilation`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation3.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).failed()\n        CompilationSubject.assertThat(compilation).hadErrorContaining(\"Invalid selector\")\n    }\n\n    @Test\n    fun `Empty selector filed fails compilation`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation4.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).failed()\n        CompilationSubject.assertThat(compilation).hadErrorContaining(\"Invalid selector\")\n    }\n\n    @Test\n    fun `Invalid selector operator fails compilation`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation5.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).failed()\n        CompilationSubject.assertThat(compilation).hadErrorContaining(\"Invalid selector\")\n    }\n\n    @Test\n    fun `Empty selector operand fails compilation`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation6.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).failed()\n        CompilationSubject.assertThat(compilation).hadErrorContaining(\"Invalid selector\")\n    }\n\n    @Test\n    fun `Valid selector (1 operand)`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation7.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeededWithoutWarnings()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"selector/Implementation7MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/Implementation7MagnetFactory.java\"))\n    }\n\n    @Test\n    fun `Valid selector (2 operands, in)`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation8.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeededWithoutWarnings()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"selector/Implementation8MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/Implementation8MagnetFactory.java\"))\n    }\n\n    @Test\n    fun `Valid selector (1 operand, !=)`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation9.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeededWithoutWarnings()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"selector/Implementation9MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/Implementation9MagnetFactory.java\"))\n    }\n\n    @Test\n    fun `Valid selector (2 operands, !in)`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface.java\"),\n                withResource(\"Implementation10.java\")\n            )\n\n        CompilationSubject.assertThat(compilation).succeededWithoutWarnings()\n\n        CompilationSubject.assertThat(compilation)\n            .generatedSourceFile(\"selector/Implementation10MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/Implementation10MagnetFactory.java\"))\n    }\n\n    private fun withResource(name: String): JavaFileObject =\n        JavaFileObjects.forResource(javaClass.simpleName + '/' + name)\n}\n"
  },
  {
    "path": "magnet-processor/src/test/java/magnet/processor/SiblingTypesTest.kt",
    "content": "package magnet.processor\n\nimport com.google.testing.compile.CompilationSubject.assertThat\nimport com.google.testing.compile.Compiler\nimport com.google.testing.compile.JavaFileObjects\nimport org.junit.Test\nimport javax.tools.JavaFileObject\n\nclass SiblingTypesTest {\n\n    @Test\n    fun `Either type() or types() is required`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface1.java\"),\n                withResource(\"Interface2.java\"),\n                withResource(\"Implementation1.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"must declare\")\n    }\n\n    @Test\n    fun `Both type() or types() are not allowed`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface1.java\"),\n                withResource(\"Interface2.java\"),\n                withResource(\"Implementation2.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"not both\")\n    }\n\n    @Test\n    fun `Inheritance verification fails for types()`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface1.java\"),\n                withResource(\"Interface2.java\"),\n                withResource(\"Implementation3.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"must implement siblings.Interface2\")\n    }\n\n    @Test\n    fun `types() generates multiple factories`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface1.java\"),\n                withResource(\"Interface2.java\"),\n                withResource(\"Implementation4.java\")\n            )\n\n        assertThat(compilation).succeededWithoutWarnings()\n\n        assertThat(compilation)\n            .generatedSourceFile(\"siblings/Implementation4Interface1MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/Implementation4Interface1MagnetFactory.java\"))\n\n        assertThat(compilation)\n            .generatedSourceFile(\"siblings/Implementation4Interface2MagnetFactory\")\n            .hasSourceEquivalentTo(withResource(\"generated/Implementation4Interface2MagnetFactory.java\"))\n    }\n\n    @Test\n    fun `types() must be used with scoped instances`() {\n        val compilation = Compiler.javac()\n            .withProcessors(MagnetProcessor())\n            .compile(\n                withResource(\"Interface1.java\"),\n                withResource(\"Interface2.java\"),\n                withResource(\"Implementation5.java\")\n            )\n\n        assertThat(compilation).failed()\n        assertThat(compilation).hadErrorContaining(\"must be used with scoped instances\")\n    }\n\n    private fun withResource(name: String): JavaFileObject =\n        JavaFileObjects.forResource(javaClass.simpleName + '/' + name)\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/App.java",
    "content": "package test;\n\nimport magnet.Registry;\n\n@Registry\nclass App {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Implementation1.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(type = Interface1.class)\nclass Implementation1 implements Interface1 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Implementation3_1.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(type = Interface3.class)\nclass Implementation3_1 implements Interface3 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Implementation3_2.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(type = Interface3.class)\nclass Implementation3_2 implements Interface3 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Implementation4_1.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(\n    type = Interface4.class,\n    classifier = \"one\"\n)\nclass Implementation4_1 implements Interface4 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Implementation4_2.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(\n    type = Interface4.class,\n    classifier = \"two\"\n)\nclass Implementation4_2 implements Interface4 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Implementation5_1.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(\n    type = Interface5.class,\n    classifier = \"zero\"\n)\nclass Implementation5_1 implements Interface5 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Implementation5_2.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(\n    type = Interface5.class,\n    classifier = \"zero\"\n)\nclass Implementation5_2 implements Interface5 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Implementation6_1.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(type = Interface6_1.class)\nclass Implementation6_1 implements Interface6_1 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Implementation6_2.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(type = Interface6_2.class)\nclass Implementation6_2 implements Interface6_2 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Interface1.java",
    "content": "package test;\n\ninterface Interface1 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Interface3.java",
    "content": "package test;\n\ninterface Interface3 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Interface4.java",
    "content": "package test;\n\ninterface Interface4 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Interface5.java",
    "content": "package test;\n\ninterface Interface5 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Interface6_1.java",
    "content": "package test;\n\ninterface Interface6_1 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Interface6_2.java",
    "content": "package test;\n\ninterface Interface6_2 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/Interface7.java",
    "content": "package test;\n\nimport magnet.Instance;\n\ninterface Interface7 {\n\n    @Instance(type = Interface7.class)\n    class Implementation7 implements Interface7 {}\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/expected/MagnetIndexer1.java",
    "content": "package magnet.internal;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport test.Implementation1MagnetFactory;\n\n@Generated\npublic final class MagnetIndexer {\n    public static void register(MagnetInstanceManager instanceManager) {\n        InstanceFactory[] factories = new InstanceFactory[] {\n            new Implementation1MagnetFactory(),\n        };\n        Map<Class, Object> index = new HashMap<>(16);\n        index.put(Implementation1MagnetFactory.getType(), new Range(0, 1, \"\"));\n        instanceManager.register(factories, index);\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/expected/MagnetIndexer2.java",
    "content": "package magnet.internal;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n@Generated\npublic final class MagnetIndexer {\n    public static void register(MagnetInstanceManager instanceManager) {\n        InstanceFactory[] factories = new InstanceFactory[0];\n        Map<Class, Object> index = new HashMap<>(16);\n        instanceManager.register(factories, index);\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/expected/MagnetIndexer3.java",
    "content": "package magnet.internal;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport test.Implementation3_1MagnetFactory;\nimport test.Implementation3_2MagnetFactory;\n\n@Generated\npublic final class MagnetIndexer {\n    public static void register(MagnetInstanceManager instanceManager) {\n        InstanceFactory[] factories = new InstanceFactory[] {\n            new Implementation3_1MagnetFactory(),\n            new Implementation3_2MagnetFactory(),\n        };\n        Map<Class, Object> index = new HashMap<>(16);\n        index.put(Implementation3_1MagnetFactory.getType(), new Range(0, 2, \"\"));\n        instanceManager.register(factories, index);\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/expected/MagnetIndexer4.java",
    "content": "package magnet.internal;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport test.Implementation4_1MagnetFactory;\nimport test.Implementation4_2MagnetFactory;\n\n@Generated\npublic final class MagnetIndexer {\n    public static void register(MagnetInstanceManager instanceManager) {\n        InstanceFactory[] factories = new InstanceFactory[] {\n            new Implementation4_1MagnetFactory(),\n            new Implementation4_2MagnetFactory(),\n        };\n        Map<Class, Object> index = new HashMap<>(16);\n        Map<String, Range> ranges1 = new HashMap<>(8);\n        ranges1.put(\"one\", new Range(0, 1, \"one\"));\n        ranges1.put(\"two\", new Range(1, 1, \"two\"));\n        index.put(Implementation4_1MagnetFactory.getType(), ranges1);\n        instanceManager.register(factories, index);\n    }"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/expected/MagnetIndexer5.java",
    "content": "package magnet.internal;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport test.Implementation5_1MagnetFactory;\nimport test.Implementation5_2MagnetFactory;\n\n@Generated\npublic final class MagnetIndexer {\n    public static void register(MagnetInstanceManager instanceManager) {\n        InstanceFactory[] factories = new InstanceFactory[] {\n            new Implementation5_1MagnetFactory(),\n            new Implementation5_2MagnetFactory(),\n        };\n        Map<Class, Object> index = new HashMap<>(16);\n        index.put(Implementation5_1MagnetFactory.getType(), new Range(0, 2, \"zero\"));\n        instanceManager.register(factories, index);\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/expected/MagnetIndexer6.java",
    "content": "package magnet.internal;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport test.Implementation6_1MagnetFactory;\nimport test.Implementation6_2MagnetFactory;\n\n@Generated\npublic final class MagnetIndexer {\n    public static void register(MagnetInstanceManager instanceManager) {\n        InstanceFactory[] factories = new InstanceFactory[] {\n            new Implementation6_1MagnetFactory(),\n            new Implementation6_2MagnetFactory(),\n        };\n        Map<Class, Object> index = new HashMap<>(16);\n        index.put(Implementation6_1MagnetFactory.getType(), new Range(0, 1, \"\"));\n        index.put(Implementation6_2MagnetFactory.getType(), new Range(1, 1, \"\"));\n        instanceManager.register(factories, index);\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/GenerateRegistryForInstanceFactoriesTest/expected/MagnetIndexer7.java",
    "content": "package magnet.internal;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport test.Interface7Implementation7MagnetFactory;\n\n@Generated\npublic final class MagnetIndexer {\n    public static void register(MagnetInstanceManager instanceManager) {\n        InstanceFactory[] factories = new InstanceFactory[] {\n            new Interface7Implementation7MagnetFactory(),\n        };\n        Map<Class, Object> index = new HashMap<>(16);\n        index.put(Interface7Implementation7MagnetFactory.getType(), new Range(0, 1, \"\"));\n        instanceManager.register(factories, index);\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceCustomFactoryProcessorTest/CustomFactory1.java",
    "content": "package test;\n\nimport magnet.Factory;\nimport magnet.Scope;\nimport magnet.Scoping;\nimport org.jetbrains.annotations.NotNull;\n\nclass CustomFactory1 implements Factory<Interface1> {\n\n    @NotNull\n    @Override\n    public Interface1 create(\n        @NotNull Scope scope,\n        @NotNull Class<Interface1> type,\n        @NotNull String classifier,\n        @NotNull Scoping scoping,\n        @NotNull Instantiator<Interface1> instantiator\n    ) {\n        return null;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceCustomFactoryProcessorTest/CustomFactory2.java",
    "content": "package test;\n\nimport magnet.Factory;\nimport magnet.Scope;\nimport magnet.Scoping;\nimport org.jetbrains.annotations.NotNull;\n\nclass CustomFactory2<T> implements Factory<T> {\n\n    @NotNull\n    @Override\n    public T create(\n        @NotNull Scope scope,\n        @NotNull Class<T> type,\n        @NotNull String classifier,\n        @NotNull Scoping scoping,\n        @NotNull Instantiator<T> instantiator) {\n        return null;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceCustomFactoryProcessorTest/CustomFactory3.java",
    "content": "package test;\n\nimport magnet.Factory;\nimport magnet.Scope;\nimport magnet.Scoping;\nimport org.jetbrains.annotations.NotNull;\n\nclass CustomFactory3 implements Factory<Interface3> {\n\n    @NotNull\n    @Override\n    public Interface3 create(\n        @NotNull Scope scope,\n        @NotNull Class<Interface3> type,\n        @NotNull String classifier,\n        @NotNull Scoping scoping,\n        @NotNull Instantiator<Interface3> instantiator\n    ) {\n        return null;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceCustomFactoryProcessorTest/Implementation1.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(\n    type = Interface1.class,\n    factory = CustomFactory1.class\n)\npublic class Implementation1 implements Interface1 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceCustomFactoryProcessorTest/Implementation2.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(\n    type = Interface2.class,\n    factory = CustomFactory2.class\n)\npublic class Implementation2 implements Interface2 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceCustomFactoryProcessorTest/Implementation3.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(\n    type = Interface3.class,\n    factory = CustomFactory3.class\n)\npublic class Implementation3 implements Interface3 {\n\n    public Implementation3(String value1, Long value2) {}\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceCustomFactoryProcessorTest/Interface1.java",
    "content": "package test;\n\npublic interface Interface1 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceCustomFactoryProcessorTest/Interface2.java",
    "content": "package test;\n\npublic interface Interface2 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceCustomFactoryProcessorTest/Interface3.java",
    "content": "package test;\n\npublic interface Interface3 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceCustomFactoryProcessorTest/expected/Implementation1MagnetFactory.java",
    "content": "package test;\n\nimport magnet.Factory;\nimport magnet.Scope;\nimport magnet.Scoping;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class Implementation1MagnetFactory extends InstanceFactory<Interface1> implements Factory.Instantiator<Interface1> {\n\n    private CustomFactory1 factory = null;\n\n    @Override\n    public Interface1 create(Scope scope) {\n        if (factory == null) {\n            factory = new CustomFactory1();\n        }\n        return factory.create(scope, Interface1.class, \"\", Scoping.TOPMOST, this);\n    }\n\n    @Override\n    public Interface1 instantiate(Scope scope) {\n        return new Implementation1();\n    }\n\n    public static Class getType() {\n        return Interface1.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceCustomFactoryProcessorTest/expected/Implementation2MagnetFactory.java",
    "content": "package test;\n\nimport magnet.Factory;\nimport magnet.Scope;\nimport magnet.Scoping;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class Implementation2MagnetFactory extends InstanceFactory<Interface2> implements Factory.Instantiator<Interface2> {\n\n    private CustomFactory2<Interface2> factory = null;\n\n    @Override\n    public Interface2 create(Scope scope) {\n        if (factory == null) {\n            factory = new CustomFactory2<Interface2>();\n        }\n        return factory.create(scope, Interface2.class, \"\", Scoping.TOPMOST, this);\n    }\n\n    @Override\n    public Interface2 instantiate(Scope scope) {\n        return new Implementation2();\n    }\n\n    public static Class getType() {\n        return Interface2.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceCustomFactoryProcessorTest/expected/Implementation3MagnetFactory.java",
    "content": "package test;\n\nimport magnet.Factory;\nimport magnet.Scope;\nimport magnet.Scoping;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class Implementation3MagnetFactory extends InstanceFactory<Interface3> implements Factory.Instantiator<Interface3> {\n\n    private CustomFactory3 factory = null;\n\n    @Override\n    public Interface3 create(Scope scope) {\n        if (factory == null) {\n            factory = new CustomFactory3();\n        }\n        return factory.create(scope, Interface3.class, \"\", Scoping.TOPMOST, this);\n    }\n\n    @Override\n    public Interface3 instantiate(Scope scope) {\n        String value1 = scope.getSingle(String.class, \"\");\n        Long value2 = scope.getSingle(Long.class, \"\");\n        return new Implementation3(value1, value2);\n    }\n\n    public static Class getType() {\n        return Interface3.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceDisposerTest/Implementation1.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(\n    type = Interface.class,\n    disposer = \"disposeIt\"\n)\npublic class Implementation1 implements Interface {\n\n    void disposeIt() {}\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceDisposerTest/Implementation2.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(\n    type = Interface.class,\n    disposer = \"disposeIt\"\n)\npublic class Implementation2 implements Interface {\n\n    void dispose() {}\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceDisposerTest/Implementation3.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(\n    type = Interface.class,\n    disposer = \"disposeIt\"\n)\npublic class Implementation3 implements Interface {\n\n    void disposeIt(String value) {}\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceDisposerTest/Implementation4.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(\n    type = Interface.class,\n    disposer = \"disposeIt\"\n)\npublic class Implementation4 implements Interface {\n\n    String disposeIt() { return null; }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceDisposerTest/Implementation5.java",
    "content": "package test;\n\nimport magnet.Instance;\nimport magnet.Scoping;\n\n@Instance(\n    type = Interface.class,\n    scoping = Scoping.UNSCOPED,\n    disposer = \"disposeIt\"\n)\npublic class Implementation5 implements Interface {\n\n    void disposeIt() { return null; }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceDisposerTest/Interface.java",
    "content": "package test;\n\npublic interface Interface {}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceDisposerTest/expected/Implementation1MagnetFactory.java",
    "content": "package test;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class Implementation1MagnetFactory extends InstanceFactory<Interface> {\n\n    @Override\n    public Interface create(Scope scope) {\n        return new Implementation1();\n    }\n\n    @Override\n    public boolean isDisposable() {\n        return true;\n    }\n\n    @Override\n    public void dispose(Interface instance) {\n        ((Implementation1) instance).disposeIt();\n    }\n\n    public static Class getType() {\n        return Interface.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceIndexProcessorTest/Implementation1.java",
    "content": "package app.test;\n\nimport app.Interface1;\nimport magnet.Instance;\n\n@Instance(\n    type = Interface1.class,\n    classifier = \"implementation1\"\n)\nclass Implementation1 implements Interface1 {\n\n    Implementation1() {}\n\n    @Override\n    public int getId() {\n        return 0;\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceIndexProcessorTest/Implementation2.java",
    "content": "package app.test;\n\nimport app.Interface2;\nimport magnet.Instance;\n\n@Instance(type = Interface2.class)\nclass Implementation2 implements Interface2 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceIndexProcessorTest/Interface1.java",
    "content": "package app;\n\npublic interface Interface1 {\n    int getId();\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceIndexProcessorTest/Interface2.java",
    "content": "package app;\n\npublic interface Interface2 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceIndexProcessorTest/generated/app_test_Implementation1MagnetFactory.java",
    "content": "package magnet.index;\n\nimport app.test.Implementation1MagnetFactory;\nimport magnet.internal.Generated;\nimport magnet.internal.Index;\nimport magnet.internal.InstanceFactory;\n\n@Generated\n@Index(\n    factoryType = InstanceFactory.class,\n    factoryClass = Implementation1MagnetFactory.class,\n    instanceType = \"app.Interface1\",\n    classifier = \"implementation1\"\n)\npublic final class app_test_Implementation1MagnetFactory {}"
  },
  {
    "path": "magnet-processor/src/test/resources/InstanceIndexProcessorTest/generated/app_test_Implementation2MagnetFactory.java",
    "content": "package magnet.index;\n\nimport app.test.Implementation2MagnetFactory;\nimport magnet.internal.Generated;\nimport magnet.internal.Index;\nimport magnet.internal.InstanceFactory;\n\n@Generated\n@Index(\n    factoryType = InstanceFactory.class,\n    factoryClass = Implementation2MagnetFactory.class,\n    instanceType = \"app.Interface2\",\n    classifier = \"\"\n)\npublic final class app_test_Implementation2MagnetFactory {}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorFactoryNamesTest/Delegate1.java",
    "content": "package test;\n\nimport magnet.Instance;\n\n@Instance(type = Delegate1.class)\nclass Delegate1 {}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorFactoryNamesTest/Interface1.java",
    "content": "package test;\n\nimport magnet.Instance;\n\ninterface Interface1 {\n\n    @Instance(type = Interface1.Delegate.class)\n    class Delegate {}\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorFactoryNamesTest/generated/Delegate1MagnetFactory.java",
    "content": "package test;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class Delegate1MagnetFactory extends InstanceFactory<Delegate1> {\n    @Override\n    public Delegate1 create(Scope scope) {\n        return new Delegate1();\n    }\n\n    public static Class getType() {\n        return Delegate1.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorFactoryNamesTest/generated/Interface1DelegateMagnetFactory.java",
    "content": "package test;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class Interface1DelegateMagnetFactory extends InstanceFactory<Interface1.Delegate> {\n    @Override\n    public Interface1.Delegate create(Scope scope) {\n        return new Interface1.Delegate();\n    }\n\n    public static Class getType() {\n        return Interface1.Delegate.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/AppExtensionRegistry.java",
    "content": "package app;\n\nimport magnet.Registry;\n\n@Registry\npublic interface AppExtensionRegistry {}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Constructor_PackagePrivate_PackagePrivate/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(type = UnderTest.class)\nclass UnderTest {\n\n    UnderTest(Scope scope) { }\n    UnderTest() { }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Constructor_PackagePrivate_Private/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(type = UnderTest.class)\nclass UnderTest {\n\n    UnderTest(Scope scope) { }\n    private UnderTest() { }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Constructor_PackagePrivate_Private/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n  @Override\n  public UnderTest create(Scope scope) {\n    return new UnderTest(scope);\n  }\n\n  public static Class getType() {\n    return UnderTest.class;\n  }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Constructor_Private/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\n\n@Instance(type = UnderTest.class)\nclass UnderTest {\n\n    private UnderTest() { }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Constructor_Protected/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\n\n@Instance(type = UnderTest.class)\nclass UnderTest {\n\n    protected UnderTest() { }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Constructor_Public_PackagePrivate/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(type = UnderTest.class)\nclass UnderTest {\n\n    public UnderTest(Scope scope) { }\n    UnderTest() { }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Constructor_Public_Private/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(type = UnderTest.class)\nclass UnderTest {\n\n    public UnderTest(Scope scope) { }\n    private UnderTest() { }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Constructor_Public_Private/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n  @Override\n  public UnderTest create(Scope scope) {\n    return new UnderTest(scope);\n  }\n\n  public static Class getType() {\n    return UnderTest.class;\n  }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Constructor_Public_Protected/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(type = UnderTest.class)\nclass UnderTest {\n\n    public UnderTest(Scope scope) { }\n    protected UnderTest() { }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Constructor_Public_Protected/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n  @Override\n  public UnderTest create(Scope scope) {\n    return new UnderTest(scope);\n  }\n\n  public static Class getType() {\n    return UnderTest.class;\n  }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Constructor_Public_Public/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(type = UnderTest.class)\nclass UnderTest {\n\n    public UnderTest(Scope scope) { }\n    public UnderTest() { }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Constructor_Public_Public_Kotlin/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport magnet.Scope;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 15},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u001a\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0002\\n\\u0002\\u0018\\u0002\\n\\u0002\\b\\u0002\\b\\u0007\\u0018\\u00002\\u00020\\u0001B\\u000f\\b\\u0016\\u0012\\u0006\\u0010\\u0002\\u001a\\u00020\\u0003¢\\u0006\\u0002\\u0010\\u0004B\\u000f\\b\\u0016\\u0012\\u0006\\u0010\\u0005\\u001a\\u00020\\u0006¢\\u0006\\u0002\\u0010\\u0007¨\\u0006\\b\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"value\", \"\", \"(Ljava/lang/String;)V\", \"parentScope\", \"Lmagnet/Scope;\", \"(Lmagnet/Scope;)V\", \"magnet-processor\"}\n)\n@Instance(\n    type = UnderTest.class\n)\npublic final class UnderTest {\n    public UnderTest(@NotNull String value) {\n        super();\n    }\n\n    public UnderTest(@NotNull Scope parentScope) {\n        super();\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Covariance_Constructor_ManyParameter/Foo.java",
    "content": "package app;\n\npublic class Foo {\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Covariance_Constructor_ManyParameter/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\n\nimport java.util.List;\n\n@Instance(type = UnderTest.class)\npublic class UnderTest {\n\n    public UnderTest(List<? extends Foo> dep) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Covariance_Constructor_ManyParameter/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport java.util.List;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        List<Foo> dep = scope.getMany(Foo.class, \"\");\n        return new UnderTest(dep);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Covariance_Constructor_SingleParameter/Foo.java",
    "content": "package app;\n\npublic class Foo {\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Covariance_Constructor_SingleParameter/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\n\n@Instance(type = UnderTest.class)\npublic class UnderTest<T extends Foo> {\n\n    public UnderTest(T dep) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/DefaultArguments_JvmOverloads_AtTheEnd/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 15},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u0012\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0004\\b\\u0007\\u0018\\u00002\\u00020\\u0001B!\\b\\u0007\\u0012\\u0006\\u0010\\u0002\\u001a\\u00020\\u0003\\u0012\\u0006\\u0010\\u0004\\u001a\\u00020\\u0003\\u0012\\b\\b\\u0002\\u0010\\u0005\\u001a\\u00020\\u0003¢\\u0006\\u0002\\u0010\\u0006R\\u000e\\u0010\\u0002\\u001a\\u00020\\u0003X\\u0082\\u0004¢\\u0006\\u0002\\n\\u0000R\\u000e\\u0010\\u0004\\u001a\\u00020\\u0003X\\u0082\\u0004¢\\u0006\\u0002\\n\\u0000R\\u000e\\u0010\\u0005\\u001a\\u00020\\u0003X\\u0082\\u0004¢\\u0006\\u0002\\n\\u0000¨\\u0006\\u0007\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"value1\", \"\", \"value2\", \"value3\", \"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V\", \"magnet-processor\"}\n)\n@Instance(\n    type = UnderTest.class\n)\npublic final class UnderTest {\n\n    public UnderTest(@NotNull String value1, @NotNull String value2, @NotNull String value3) {\n        super();\n    }\n\n    public UnderTest(@NotNull String value1, @NotNull String value2) {\n        super();\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/DefaultArguments_JvmOverloads_AtTheEnd/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        String value1 = scope.getSingle(String.class, \"\");\n        String value2 = scope.getSingle(String.class, \"\");\n        return new UnderTest(value1, value2);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/DefaultArguments_JvmOverloads_InTheMiddle/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 15},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u0012\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0004\\b\\u0007\\u0018\\u00002\\u00020\\u0001B!\\b\\u0007\\u0012\\u0006\\u0010\\u0002\\u001a\\u00020\\u0003\\u0012\\b\\b\\u0002\\u0010\\u0004\\u001a\\u00020\\u0003\\u0012\\u0006\\u0010\\u0005\\u001a\\u00020\\u0003¢\\u0006\\u0002\\u0010\\u0006R\\u000e\\u0010\\u0002\\u001a\\u00020\\u0003X\\u0082\\u0004¢\\u0006\\u0002\\n\\u0000R\\u000e\\u0010\\u0004\\u001a\\u00020\\u0003X\\u0082\\u0004¢\\u0006\\u0002\\n\\u0000R\\u000e\\u0010\\u0005\\u001a\\u00020\\u0003X\\u0082\\u0004¢\\u0006\\u0002\\n\\u0000¨\\u0006\\u0007\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"value1\", \"\", \"value2\", \"value3\", \"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V\", \"magnet-processor\"}\n)\n@Instance(\n    type = UnderTest.class\n)\npublic final class UnderTest {\n\n    public UnderTest(@NotNull String value1, @NotNull String value2, @NotNull String value3) {\n        super();\n    }\n\n    public UnderTest(@NotNull String value1, @NotNull String value3) {\n        super();\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/DefaultArguments_JvmOverloads_InTheMiddle/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        String value1 = scope.getSingle(String.class, \"\");\n        String value3 = scope.getSingle(String.class, \"\");\n        return new UnderTest(value1, value3);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/DefaultArguments_JvmOverloads_Mixed/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 15},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u0012\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0005\\b\\u0007\\u0018\\u00002\\u00020\\u0001B+\\b\\u0007\\u0012\\u0006\\u0010\\u0002\\u001a\\u00020\\u0003\\u0012\\b\\b\\u0002\\u0010\\u0004\\u001a\\u00020\\u0003\\u0012\\u0006\\u0010\\u0005\\u001a\\u00020\\u0003\\u0012\\b\\b\\u0002\\u0010\\u0006\\u001a\\u00020\\u0003¢\\u0006\\u0002\\u0010\\u0007R\\u000e\\u0010\\u0002\\u001a\\u00020\\u0003X\\u0082\\u0004¢\\u0006\\u0002\\n\\u0000R\\u000e\\u0010\\u0004\\u001a\\u00020\\u0003X\\u0082\\u0004¢\\u0006\\u0002\\n\\u0000R\\u000e\\u0010\\u0005\\u001a\\u00020\\u0003X\\u0082\\u0004¢\\u0006\\u0002\\n\\u0000R\\u000e\\u0010\\u0006\\u001a\\u00020\\u0003X\\u0082\\u0004¢\\u0006\\u0002\\n\\u0000¨\\u0006\\b\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"value1\", \"\", \"value2\", \"value3\", \"value4\", \"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V\", \"magnet-processor\"}\n)\n@Instance(\n    type = UnderTest.class\n)\npublic final class UnderTest {\n\n    public UnderTest(@NotNull String value1, @NotNull String value2, @NotNull String value3, @NotNull String value4) {\n        super();\n    }\n\n    public UnderTest(@NotNull String value1, @NotNull String value2, @NotNull String value3) {\n        super();\n    }\n\n    public UnderTest(@NotNull String value1, @NotNull String value3) {\n        super();\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/DefaultArguments_JvmOverloads_Mixed/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        String value1 = scope.getSingle(String.class, \"\");\n        String value3 = scope.getSingle(String.class, \"\");\n        return new UnderTest(value1, value3);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/DisabledTab.java",
    "content": "package app.extension;\n\nimport magnet.Instance;\n\n@Instance(type = Tab.class, disabled = true)\nclass UnimplementedTypeTab implements Tab {}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Executor.java",
    "content": "package app.extension;\n\ninterface Executor<R extends Runnable> {\n\n    void execute(R runnable);\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/ExecutorImpl.java",
    "content": "package app.extension;\n\nimport magnet.Instance;\n\n@Instance(\n        type = Executor.class\n)\nclass ExecutorImpl implements Executor<Runnable> {\n\n    @Override\n    public void execute(Runnable runnable) { }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/ExecutorMaster.java",
    "content": "package app.extension;\n\nimport magnet.Instance;\n\n@Instance(type = ExecutorMaster.class)\nclass ExecutorMaster {\n\n    public ExecutorMaster(Executor<Runnable> executor) {}\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_GetOptional_Unchecked/Dependency.java",
    "content": "package app;\n\ninterface Dependency<T extends Runnable> {\n    void run();\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_GetOptional_Unchecked/UnderTest.java",
    "content": "package app;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport magnet.Instance;\n\n@Instance(type = UnderTest.class)\nclass UnderTest {\n    public UnderTest(@Nullable Dependency<Thread> dependency) { }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_GetOptional_Unchecked/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public UnderTest create(Scope scope) {\n        Dependency<Thread> dependency = scope.getOptional(Dependency.class, \"\");\n        return new UnderTest(dependency);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_GetSingle_Unchecked/Dependency.java",
    "content": "package app;\n\ninterface Dependency<T extends Runnable> {\n    void run();\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_GetSingle_Unchecked/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\n\n@Instance(type = UnderTest.class)\nclass UnderTest {\n    public UnderTest(Dependency<Thread> dependency) { }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_GetSingle_Unchecked/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public UnderTest create(Scope scope) {\n        Dependency<Thread> dependency = scope.getSingle(Dependency.class, \"\");\n        return new UnderTest(dependency);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_ProvideTypeWithParameter/Parameter.java",
    "content": "package app;\n\nclass Parameter {\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_ProvideTypeWithParameter/Type.java",
    "content": "package app;\n\ninterface Type<Parameter> {\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_ProvideTypeWithParameter/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\n\nclass UnderTest {\n\n    @Instance(type = Type.class, classifier = \"parameter-type\")\n    public static Type<Parameter> provideType() {\n        return new Type<Parameter>() {\n        };\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_ProvideTypeWithParameter/expected/UnderTestProvideTypeMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestProvideTypeMagnetFactory extends InstanceFactory<Type> {\n    @Override\n    public Type create(Scope scope) {\n        return UnderTest.provideType();\n    }\n\n    public static Class getType() {\n        return Type.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_ProvideTypeWithParameter_NoClassifier/Parameter.java",
    "content": "package app;\n\nclass Parameter {\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_ProvideTypeWithParameter_NoClassifier/Type.java",
    "content": "package app;\n\ninterface Type<Parameter> {\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_ProvideTypeWithParameter_NoClassifier/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\n\nclass UnderTest {\n\n    @Instance(type = Type.class)\n    public static Type<Parameter> provideType() {\n        return new Type<Parameter>() {\n        };\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Generics_ProvideTypeWithParameter_NoClassifier/expected/UnderTestProvideTypeMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestProvideTypeMagnetFactory extends InstanceFactory<Type> {\n    @Override\n    public Type create(Scope scope) {\n        return UnderTest.provideType();\n    }\n\n    public static Class getType() {\n        return Type.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePage.java",
    "content": "package app.extension;\n\nimport app.HomeRepository;\nimport app.Page;\nimport app.UserData;\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(type = Page.class)\nclass HomePage implements Page {\n\n    HomePage(\n            HomeRepository homeRepository,\n            UserData userData,\n            Scope scope\n    ) { }\n\n    @Override\n    public void show() {\n        // nop\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageMenuItem.java",
    "content": "package app.extension;\n\nimport app.MenuItem;\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(\n        type = MenuItem.class,\n        classifier = \"main-menu\"\n)\nclass HomePageMenuItem implements MenuItem {\n\n    HomePageMenuItem(Scope scope) {\n    }\n\n    @Override\n    public int getId() {\n        return 1;\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageNoParams.java",
    "content": "package app.extension;\n\nimport app.Page;\nimport magnet.Instance;\n\n@Instance(type = Page.class)\nclass HomePageNoParams implements Page {\n\n    HomePageNoParams() { }\n\n    @Override\n    public void show() {\n        // nop\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageWithClassifierParams.java",
    "content": "package app.extension;\n\nimport javax.annotation.Nullable;\n\nimport app.HomeRepository;\nimport app.Page;\nimport app.UserData;\nimport magnet.Instance;\nimport magnet.Classifier;\n\n@Instance(type = Page.class)\nclass HomePageWithClassifierParams implements Page {\n\n    private static final String LOCAL = \"local\";\n\n    HomePageWithClassifierParams(\n            @Nullable @Classifier(LOCAL) HomeRepository homeRepository,\n            @Classifier(\"global\") UserData userData\n    ) { }\n\n    @Override\n    public void show() {\n        // nop\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageWithGenericParam.java",
    "content": "package app.extension;\n\nimport app.Page;\nimport magnet.Instance;\n\n@Instance(type = Page.class)\nclass HomePageWithGenericParam<T extends Object> implements Page {\n\n    HomePageWithGenericParam(T genericThing) { }\n\n    @Override\n    public void show() {\n        // nop\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageWithManyParameterizedParams.java",
    "content": "package app.extension;\n\nimport java.util.List;\n\nimport javax.annotation.Nullable;\n\nimport app.WorkProcessor;\nimport app.Page;\nimport magnet.Classifier;\nimport magnet.Instance;\n\n@Instance(type = Page.class)\nclass HomePageWithManyParameterizedParams<T extends Runnable> implements Page {\n\n    HomePageWithManyParameterizedParams(\n            List<WorkProcessor<T>> variant1,\n            @Classifier(\"global\") List<WorkProcessor<T>> variant2,\n            @Nullable List<WorkProcessor<T>> variant3,\n            @Nullable @Classifier(\"global\") List<WorkProcessor<T>> variant4\n    ) { }\n\n    @Override\n    public void show() {\n        // nop\n    }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageWithManyParameterizedWildcardInParams.java",
    "content": "package app.extension;\n\nimport java.util.List;\n\nimport javax.annotation.Nullable;\n\nimport app.WorkProcessor;\nimport app.Page;\nimport magnet.Classifier;\nimport magnet.Instance;\n\n@Instance(type = Page.class)\nclass HomePageWithManyParameterizedWildcardInParams implements Page {\n\n    HomePageWithManyParameterizedWildcardInParams(\n            List<? extends WorkProcessor<? super Runnable>> variant1,\n            @Classifier(\"global\") List<? extends WorkProcessor<? super Runnable>> variant2,\n            @Nullable List<? extends WorkProcessor<? super Runnable>> variant3,\n            @Nullable @Classifier(\"global\") List<? extends WorkProcessor<? super Runnable>> variant4\n    ) { }\n\n    @Override\n    public void show() {\n        // nop\n    }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageWithManyParameterizedWildcardKnownParams.java",
    "content": "package app.extension;\n\nimport java.util.List;\n\nimport javax.annotation.Nullable;\n\nimport app.WorkProcessor;\nimport app.Page;\nimport magnet.Classifier;\nimport magnet.Instance;\n\n@Instance(type = Page.class)\nclass HomePageWithManyParameterizedWildcardKnownParams implements Page {\n\n    HomePageWithManyParameterizedWildcardKnownParams(\n            List<? extends WorkProcessor<Runnable>> variant1,\n            @Classifier(\"global\") List<? extends WorkProcessor<Runnable>> variant2,\n            @Nullable List<? extends WorkProcessor<Runnable>> variant3,\n            @Nullable @Classifier(\"global\") List<? extends WorkProcessor<Runnable>> variant4\n    ) { }\n\n    @Override\n    public void show() {\n        // nop\n    }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageWithManyParameterizedWildcardOutParams.java",
    "content": "package app.extension;\n\nimport java.util.List;\n\nimport javax.annotation.Nullable;\n\nimport app.WorkProcessor;\nimport app.Page;\nimport magnet.Classifier;\nimport magnet.Instance;\n\n@Instance(type = Page.class)\nclass HomePageWithManyParameterizedWildcardOutParams implements Page {\n\n    HomePageWithManyParameterizedWildcardOutParams(\n            List<? extends WorkProcessor<? extends Runnable>> variant1,\n            @Classifier(\"global\") List<? extends WorkProcessor<? extends Runnable>> variant2,\n            @Nullable List<? extends WorkProcessor<? extends Runnable>> variant3,\n            @Nullable @Classifier(\"global\") List<? extends WorkProcessor<? extends Runnable>> variant4\n    ) { }\n\n    @Override\n    public void show() {\n        // nop\n    }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageWithManyParams.java",
    "content": "package app.extension;\n\nimport javax.annotation.Nullable;\n\nimport app.HomeRepository;\nimport app.Page;\nimport java.util.List;\n\nimport magnet.Classifier;\nimport magnet.Instance;\n\n\n@Instance(type = Page.class)\nclass HomePageWithManyParams implements Page {\n\n    HomePageWithManyParams(\n            List<HomeRepository> variant1,\n            @Classifier(\"global\") List<HomeRepository> variant2,\n            @Nullable List<HomeRepository> variant3,\n            @Nullable @Classifier(\"global\") List<HomeRepository> variant4\n    ) { }\n\n    @Override\n    public void show() {\n        // nop\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageWithManyWildcardParams.java",
    "content": "package app.extension;\n\nimport java.util.List;\n\nimport app.HomeRepository;\nimport app.Page;\nimport magnet.Instance;\n\n@Instance(type = Page.class)\nclass HomePageWithManyWildcardParams implements Page {\n\n    HomePageWithManyWildcardParams(\n            List<? extends HomeRepository> repositories\n    ) { }\n\n    @Override\n    public void show() {\n        // nop\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageWithParams.java",
    "content": "package app.extension;\n\nimport org.jetbrains.annotations.NotNull;\n\nimport javax.annotation.Nullable;\n\nimport app.HomeRepository;\nimport app.Page;\nimport app.UserData;\nimport magnet.Instance;\n\n@Instance(type = Page.class)\nclass HomePageWithParams implements Page {\n\n    HomePageWithParams(\n            @Nullable HomeRepository homeRepository,\n            @NotNull UserData userData\n    ) { }\n\n    @Override\n    public void show() {\n        // nop\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageWithScope.java",
    "content": "package app.extension;\n\nimport app.Page;\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(type = Page.class)\nclass HomePageWithScope implements Page {\n\n    HomePageWithScope(Scope scope) { }\n\n    @Override\n    public void show() {\n        // nop\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageWithStaticConstructor.java",
    "content": "package app.extension;\n\nimport java.util.List;\n\nimport app.HomeRepository;\nimport app.Page;\n\npublic class HomePageWithStaticConstructor implements Page {\n\n    public HomePageWithStaticConstructor(\n            List<? extends HomeRepository> repositories\n    ) { }\n\n    @Override\n    public void show() {\n        // nop\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageWithStaticConstructorDisabled.java",
    "content": "package app.extension.utils;\n\nimport java.util.List;\n\nimport app.HomeRepository;\nimport app.Page;\nimport app.extension.HomePageWithStaticConstructor;\nimport magnet.Instance;\nimport magnet.Scoping;\n\npublic class HomePageWithStaticConstructorDisabled {\n\n    @Instance(\n            type = app.Page.class,\n            scoping = Scoping.UNSCOPED,\n            disabled = true\n    )\n    public static Page create(List<? extends HomeRepository> repositories) {\n        return new HomePageWithStaticConstructor(repositories);\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomePageWithStaticConstructorSingle.java",
    "content": "package app.extension.utils;\n\nimport java.util.List;\n\nimport app.HomeRepository;\nimport app.Page;\nimport app.extension.HomePageWithStaticConstructor;\nimport magnet.Instance;\nimport magnet.Scoping;\n\npublic class HomePageWithStaticConstructorSingle {\n\n    @Instance(\n            type = app.Page.class,\n            scoping = Scoping.UNSCOPED\n    )\n    public static Page create(List<? extends HomeRepository> repositories) {\n        return new HomePageWithStaticConstructor(repositories);\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/HomeRepository.java",
    "content": "package app;\n\npublic interface HomeRepository {\n\n    String[] getHomePageData();\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_ManyParameter/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.List;\n\n@Metadata(\n    mv = {1, 1, 13},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u001a\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010 \\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0002\\b\\u0007\\u0018\\u00002\\u00020\\u0001B\\u0019\\u0012\\u0012\\u0010\\u0002\\u001a\\u000e\\u0012\\n\\u0012\\b\\u0012\\u0004\\u0012\\u00020\\u00050\\u00040\\u0003¢\\u0006\\u0002\\u0010\\u0006¨\\u0006\\u0007\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"dep\", \"Lkotlin/Lazy;\", \"\", \"\", \"(Lkotlin/Lazy;)V\", \"magnet-processor\"}\n)\n@Instance(type = UnderTest.class)\npublic class UnderTest {\n\n    public UnderTest(@NotNull Lazy<List<String>> dep) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_ManyParameter/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport java.util.List;\nimport kotlin.Lazy;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\nimport magnet.internal.ManyLazy;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        Lazy<List<String>> dep = new ManyLazy(scope, String.class, \"\");\n        return new UnderTest(dep);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_ManyParameter_NullableGenericType/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.List;\n\n@Metadata(\n    mv = {1, 1, 13},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u001a\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010 \\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0002\\b\\u0007\\u0018\\u00002\\u00020\\u0001B\\u001b\\u0012\\u0014\\u0010\\u0002\\u001a\\u0010\\u0012\\f\\u0012\\n\\u0012\\u0006\\u0012\\u0004\\u0018\\u00010\\u00050\\u00040\\u0003¢\\u0006\\u0002\\u0010\\u0006¨\\u0006\\u0007\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"dep\", \"Lkotlin/Lazy;\", \"\", \"\", \"(Lkotlin/Lazy;)V\", \"de.halfbit.magnet-processor.main\"}\n)\n@Instance(type = UnderTest.class)\npublic class UnderTest {\n\n    public UnderTest(@NotNull Lazy<List<String>> dep) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_ManyParameter_NullableListType/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.List;\n\n@Metadata(\n    mv = {1, 1, 13},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u001a\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010 \\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0002\\b\\u0007\\u0018\\u00002\\u00020\\u0001B\\u001b\\u0012\\u0014\\u0010\\u0002\\u001a\\u0010\\u0012\\f\\u0012\\n\\u0012\\u0004\\u0012\\u00020\\u0005\\u0018\\u00010\\u00040\\u0003¢\\u0006\\u0002\\u0010\\u0006¨\\u0006\\u0007\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"dep\", \"Lkotlin/Lazy;\", \"\", \"\", \"(Lkotlin/Lazy;)V\", \"de.halfbit.magnet-processor.main\"}\n)\n@Instance(type = UnderTest.class)\npublic class UnderTest {\n\n    public UnderTest(@NotNull Lazy<List<String>> dep) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_ManyParameter_Wildcard/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.List;\n\n@Metadata(\n    mv = {1, 1, 15},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u001a\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010 \\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0002\\b\\u0007\\u0018\\u00002\\u00020\\u0001B\\u0019\\u0012\\u0012\\u0010\\u0002\\u001a\\u000e\\u0012\\n\\u0012\\b\\u0012\\u0004\\u0012\\u00020\\u00050\\u00040\\u0003¢\\u0006\\u0002\\u0010\\u0006¨\\u0006\\u0007\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"dep\", \"Lkotlin/Lazy;\", \"\", \"\", \"(Lkotlin/Lazy;)V\", \"magnet-processor\"}\n)\n@Instance(type = UnderTest.class)\npublic class UnderTest {\n\n    public UnderTest(@NotNull Lazy<? extends List<? extends String>> dep) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_ManyParameter_Wildcard/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport java.util.List;\nimport kotlin.Lazy;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\nimport magnet.internal.ManyLazy;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        Lazy<List<String>> dep = new ManyLazy(scope, String.class, \"\");\n        return new UnderTest(dep);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_NoKotlinMetadata/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\n@Instance(type = UnderTest.class)\npublic class UnderTest {\n\n    public UnderTest(@NotNull Lazy<String> dep) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_OptionalParameter/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 13},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u0016\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0002\\u0018\\u00002\\u00020\\u0001B\\u0015\\u0012\\u000e\\u0010\\u0002\\u001a\\n\\u0012\\u0006\\u0012\\u0004\\u0018\\u00010\\u00040\\u0003¢\\u0006\\u0002\\u0010\\u0005¨\\u0006\\u0006\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"dep\", \"Lkotlin/Lazy;\", \"\", \"(Lkotlin/Lazy;)V\", \"magnet-processor\"}\n)\n@Instance(type = UnderTest.class)\npublic class UnderTest {\n\n    public UnderTest(@NotNull Lazy<String> dep) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_OptionalParameter/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\nimport magnet.internal.OptionalLazy;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        Lazy<String> dep = new OptionalLazy(scope, String.class, \"\");\n        return new UnderTest(dep);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_OptionalParameter_Wildcard/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 13},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u0016\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0002\\u0018\\u00002\\u00020\\u0001B\\u0015\\u0012\\u000e\\u0010\\u0002\\u001a\\n\\u0012\\u0006\\u0012\\u0004\\u0018\\u00010\\u00040\\u0003¢\\u0006\\u0002\\u0010\\u0005¨\\u0006\\u0006\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"dep\", \"Lkotlin/Lazy;\", \"\", \"(Lkotlin/Lazy;)V\", \"magnet-processor\"}\n)\n@Instance(type = UnderTest.class)\npublic class UnderTest {\n\n    public UnderTest(@NotNull Lazy<? extends String> dep) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_OptionalParameter_Wildcard/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\nimport magnet.internal.OptionalLazy;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        Lazy<String> dep = new OptionalLazy(scope, String.class, \"\");\n        return new UnderTest(dep);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_SingleParameter/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 13},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u0016\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0002\\u0018\\u00002\\u00020\\u0001B\\u0013\\u0012\\f\\u0010\\u0002\\u001a\\b\\u0012\\u0004\\u0012\\u00020\\u00040\\u0003¢\\u0006\\u0002\\u0010\\u0005¨\\u0006\\u0006\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"dep\", \"Lkotlin/Lazy;\", \"\", \"(Lkotlin/Lazy;)V\", \"magnet-processor\"}\n)\n@Instance(type = UnderTest.class)\npublic class UnderTest {\n\n    public UnderTest(@NotNull Lazy<String> dep) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_SingleParameter/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\nimport magnet.internal.SingleLazy;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        Lazy<String> dep = new SingleLazy(scope, String.class, \"\");\n        return new UnderTest(dep);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_SingleParameter_ParameterizedType/Foo.java",
    "content": "package app;\n\npublic class Foo<T> {\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_SingleParameter_ParameterizedType/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 13},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u001a\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0002\\b\\u0007\\u0018\\u00002\\u00020\\u0001B\\u0019\\u0012\\u0012\\u0010\\u0002\\u001a\\u000e\\u0012\\n\\u0012\\b\\u0012\\u0004\\u0012\\u00020\\u00050\\u00040\\u0003¢\\u0006\\u0002\\u0010\\u0006¨\\u0006\\u0007\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"dep\", \"Lkotlin/Lazy;\", \"Lapp/Foo;\", \"\", \"(Lkotlin/Lazy;)V\", \"de.halfbit.magnet-processor.main\"}\n)\n@Instance(type = UnderTest.class)\npublic class UnderTest {\n\n    public UnderTest(@NotNull Lazy<Foo<String>> dep) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_SingleParameter_ParameterizedType/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\nimport magnet.internal.SingleLazy;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        Lazy<Foo<String>> dep = new SingleLazy(scope, Foo.class, \"\");\n        return new UnderTest(dep);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_SingleParameter_Wildcard/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 13},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u0016\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u000e\\n\\u0002\\b\\u0002\\u0018\\u00002\\u00020\\u0001B\\u0013\\u0012\\f\\u0010\\u0002\\u001a\\b\\u0012\\u0004\\u0012\\u00020\\u00040\\u0003¢\\u0006\\u0002\\u0010\\u0005¨\\u0006\\u0006\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"dep\", \"Lkotlin/Lazy;\", \"\", \"(Lkotlin/Lazy;)V\", \"magnet-processor\"}\n)\n@Instance(type = UnderTest.class)\npublic class UnderTest {\n\n    public UnderTest(@NotNull Lazy<? extends String> dep) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Constructor_SingleParameter_Wildcard/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\nimport magnet.internal.SingleLazy;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        Lazy<String> dep = new SingleLazy(scope, String.class, \"\");\n        return new UnderTest(dep);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Method_NoKotlinMetadata/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\npublic class UnderTest {\n\n    @Instance(type = UnderTest.class)\n    public static UnderTest provideUnderTest(@NotNull Lazy<String> dep) {\n        return UnderTest();\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Method_OptionalParameter/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 13},\n    bv = {1, 0, 3},\n    k = 2,\n    d1 = {\"\\u0000\\u0012\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u000e\\n\\u0000\\u001a\\u0018\\u0010\\u0000\\u001a\\u00020\\u00012\\u000e\\u0010\\u0002\\u001a\\n\\u0012\\u0006\\u0012\\u0004\\u0018\\u00010\\u00040\\u0003H\\u0007¨\\u0006\\u0005\"},\n    d2 = {\"provideUnderTest\", \"Lapp/UnderTest;\", \"dep\", \"Lkotlin/Lazy;\", \"\", \"magnet-processor\"}\n)\npublic class UnderTest {\n\n    @Instance(type = UnderTest.class)\n    public static UnderTest provideUnderTest(@NotNull Lazy<String> dep) {\n        return new UnderTest();\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Method_OptionalParameter/expected/UnderTestProvideUnderTestDepMagnetFactory.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\nimport magnet.internal.OptionalLazy;\n\n@Generated\npublic final class UnderTestProvideUnderTestDepMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        Lazy<String> dep = new OptionalLazy(scope, String.class, \"\");\n        return UnderTest.provideUnderTest(dep);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Method_OptionalParameter_Wildcard/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 13},\n    bv = {1, 0, 3},\n    k = 2,\n    d1 = {\"\\u0000\\u0012\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u000e\\n\\u0000\\u001a\\u0018\\u0010\\u0000\\u001a\\u00020\\u00012\\u000e\\u0010\\u0002\\u001a\\n\\u0012\\u0006\\u0012\\u0004\\u0018\\u00010\\u00040\\u0003H\\u0007¨\\u0006\\u0005\"},\n    d2 = {\"provideUnderTest\", \"Lapp/UnderTest;\", \"dep\", \"Lkotlin/Lazy;\", \"\", \"magnet-processor\"}\n)\npublic class UnderTest {\n\n    @Instance(type = UnderTest.class)\n    public static UnderTest provideUnderTest(@NotNull Lazy<? extends String> dep) {\n        return new UnderTest();\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Method_OptionalParameter_Wildcard/expected/UnderTestProvideUnderTestDepMagnetFactory.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\nimport magnet.internal.OptionalLazy;\n\n@Generated\npublic final class UnderTestProvideUnderTestDepMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        Lazy<String> dep = new OptionalLazy(scope, String.class, \"\");\n        return UnderTest.provideUnderTest(dep);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Method_SingleParameter/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 13},\n    bv = {1, 0, 3},\n    k = 2,\n    d1 = {\"\\u0000\\u0012\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u000e\\n\\u0000\\u001a\\u0016\\u0010\\u0000\\u001a\\u00020\\u00012\\f\\u0010\\u0002\\u001a\\b\\u0012\\u0004\\u0012\\u00020\\u00040\\u0003H\\u0007¨\\u0006\\u0005\"},\n    d2 = {\"provideUnderTest\", \"Lapp/UnderTest;\", \"dep\", \"Lkotlin/Lazy;\", \"\", \"magnet-processor\"}\n)\npublic class UnderTest {\n\n    @Instance(type = UnderTest.class)\n    public static UnderTest provideUnderTest(@NotNull Lazy<String> dep) {\n        return new UnderTest();\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Method_SingleParameter/expected/UnderTestProvideUnderTestDepMagnetFactory.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\nimport magnet.internal.SingleLazy;\n\n@Generated\npublic final class UnderTestProvideUnderTestDepMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        Lazy<String> dep = new SingleLazy(scope, String.class, \"\");\n        return UnderTest.provideUnderTest(dep);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Method_SingleParameter_Wildcard/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 13},\n    bv = {1, 0, 3},\n    k = 2,\n    d1 = {\"\\u0000\\u0012\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u000e\\n\\u0000\\u001a\\u0016\\u0010\\u0000\\u001a\\u00020\\u00012\\f\\u0010\\u0002\\u001a\\b\\u0012\\u0004\\u0012\\u00020\\u00040\\u0003H\\u0007¨\\u0006\\u0005\"},\n    d2 = {\"provideUnderTest\", \"Lapp/UnderTest;\", \"dep\", \"Lkotlin/Lazy;\", \"\", \"magnet-processor\"}\n)\npublic class UnderTest {\n\n    @Instance(type = UnderTest.class)\n    public static UnderTest provideUnderTest(@NotNull Lazy<? extends String> dep) {\n        return new UnderTest();\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Lazy_Method_SingleParameter_Wildcard/expected/UnderTestProvideUnderTestDepMagnetFactory.java",
    "content": "package app;\n\nimport kotlin.Lazy;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\nimport magnet.internal.SingleLazy;\n\n@Generated\npublic final class UnderTestProvideUnderTestDepMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        Lazy<String> dep = new SingleLazy(scope, String.class, \"\");\n        return UnderTest.provideUnderTest(dep);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Limit_Empty_NoGetter/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(\n    type = UnderTest.class,\n    limitedTo = \"\"\n)\npublic class UnderTest {\n    public UnderTest(Scope scope) {\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Limit_Empty_NoGetter/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        return new UnderTest(scope);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Limit_NotEmpty_HasGetter/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(\n    type = UnderTest.class,\n    limitedTo = \"activity\"\n)\npublic class UnderTest {\n    public UnderTest(Scope scope) {\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Limit_NotEmpty_HasGetter/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        return new UnderTest(scope);\n    }\n\n    @Override\n    public String getLimit() {\n        return \"activity\";\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Limit_ReservedAsterisks_Fails/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(\n    type = UnderTest.class,\n    limitedTo = \"*\"\n)\npublic class UnderTest {\n    public UnderTest(Scope scope) {\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Limit_ScopingDirect_GeneratesGetter/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\nimport magnet.Scope;\nimport magnet.Scoping;\n\n@Instance(\n    type = UnderTest.class,\n    scoping = Scoping.DIRECT,\n    limitedTo = \"activity\"\n)\npublic class UnderTest {\n    public UnderTest(Scope scope) {\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Limit_ScopingDirect_GeneratesGetter/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.Scoping;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        return new UnderTest(scope);\n    }\n\n    @Override\n    public Scoping getScoping() {\n        return Scoping.DIRECT;\n    }\n\n    @Override\n    public String getLimit() {\n        return \"activity\";\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Limit_ScopingUnscoped_Fails/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\nimport magnet.Scope;\nimport magnet.Scoping;\n\n@Instance(\n    type = UnderTest.class,\n    scoping = Scoping.UNSCOPED,\n    limitedTo = \"activity\"\n)\npublic class UnderTest {\n    public UnderTest(Scope scope) {\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/MenuItem.java",
    "content": "package app;\n\npublic interface MenuItem {\n    int getId();\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Page.java",
    "content": "package app;\n\npublic interface Page {\n    void show();\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/ScopeParameter_CustomName/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(type = UnderTest.class)\npublic class UnderTest {\n\n    public UnderTest(Scope parentScope) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/ScopeParameter_CustomName/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        return new UnderTest(scope);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/ScopeParameter_CustomName_KotlinClass/UnderTest.java",
    "content": "package app;\n\nimport kotlin.Metadata;\nimport magnet.Instance;\nimport magnet.Scope;\nimport org.jetbrains.annotations.NotNull;\n\n@Metadata(\n    mv = {1, 1, 15},\n    bv = {1, 0, 3},\n    k = 1,\n    d1 = {\"\\u0000\\u0012\\n\\u0002\\u0018\\u0002\\n\\u0002\\u0010\\u0000\\n\\u0000\\n\\u0002\\u0018\\u0002\\n\\u0002\\b\\u0002\\b\\u0007\\u0018\\u00002\\u00020\\u0001B\\r\\u0012\\u0006\\u0010\\u0002\\u001a\\u00020\\u0003¢\\u0006\\u0002\\u0010\\u0004R\\u000e\\u0010\\u0002\\u001a\\u00020\\u0003X\\u0082\\u0004¢\\u0006\\u0002\\n\\u0000¨\\u0006\\u0005\"},\n    d2 = {\"Lapp/UnderTest;\", \"\", \"parentScope\", \"Lmagnet/Scope;\", \"(Lmagnet/Scope;)V\", \"magnet-processor\"}\n)\n@Instance(\n    type = UnderTest.class\n)\npublic final class UnderTest {\n\n    public UnderTest(@NotNull Scope parentScope) {\n        super();\n    }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/ScopeParameter_CustomName_KotlinClass/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        return new UnderTest(scope);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/ScopeParameter_DefaultName/UnderTest.java",
    "content": "package app;\n\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(type = UnderTest.class)\npublic class UnderTest {\n\n    public UnderTest(Scope scope) {\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/ScopeParameter_DefaultName/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n    @Override\n    public UnderTest create(Scope scope) {\n        return new UnderTest(scope);\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/StaticMethodNeedsDependencyWithClassifier/Constants.java",
    "content": "package app;\n\npublic final class Constants {\n    public static final String APPLICATION = \"application\";\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/StaticMethodNeedsDependencyWithClassifier/Input.java",
    "content": "package app;\n\npublic interface Input { }"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/StaticMethodNeedsDependencyWithClassifier/Output.java",
    "content": "package app;\n\npublic class Output { }"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/StaticMethodNeedsDependencyWithClassifier/StaticFunction.java",
    "content": "package app;\n\nimport magnet.Classifier;\nimport magnet.Instance;\n\npublic class StaticFunction {\n\n    @Instance(type = Output.class)\n    public static Output provide(@Classifier(Constants.APPLICATION) Input input) {\n        return new Output();\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/StaticMethodNeedsDependencyWithClassifier/generated/StaticFunctionProvideInputMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class StaticFunctionProvideInputMagnetFactory extends InstanceFactory<Output> {\n\n    @Override\n    public Output create(Scope scope) {\n        Input input = scope.getSingle(Input.class, \"application\");\n        return StaticFunction.provide(input);\n    }\n\n    public static Class getType() {\n        return Output.class;\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/StaticMethodProvidesInnerClass/PowerManager.java",
    "content": "package app;\n\npublic class PowerManager {\n    public static class WakeLock {\n        public void aquire(Long timeout) {}\n        public void release() {}\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/StaticMethodProvidesInnerClass/PowerManagerProvider.java",
    "content": "package app;\n\nimport magnet.Instance;\n\npublic class PowerManagerProvider {\n\n    @Instance(type = PowerManager.WakeLock.class)\n    public static PowerManager.WakeLock provideWakeLock() {\n        return new PowerManager.WakeLock();\n    }\n\n}\n\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/StaticMethodProvidesInnerClass/expected/PowerManagerProviderProvideWakeLockMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class PowerManagerProviderProvideWakeLockMagnetFactory extends InstanceFactory<PowerManager.WakeLock> {\n\n    @Override\n    public PowerManager.WakeLock create(Scope scope) {\n        return PowerManagerProvider.provideWakeLock();\n    }\n\n    public static Class getType() {\n        return PowerManager.WakeLock.class;\n    }\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/Tab.java",
    "content": "package app.extension;\n\ninterface Tab {}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/TypeAutoDetect_ExtendsObjectNoInterfaces/UnderTest.java",
    "content": "package app;\n\nimport org.jetbrains.annotations.Nullable;\n\nimport magnet.Instance;\n\n@Instance\nclass UnderTest {\n    public UnderTest() { }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/TypeAutoDetect_ExtendsObjectNoInterfaces/expected/UnderTestMagnetFactory.java",
    "content": "package app;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class UnderTestMagnetFactory extends InstanceFactory<UnderTest> {\n\n    @Override\n    public UnderTest create(Scope scope) {\n        return new UnderTest();\n    }\n\n    public static Class getType() {\n        return UnderTest.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/UnimplementedTab.java",
    "content": "package app.extension;\n\nimport magnet.Instance;\n\n@Instance(type = Tab.class)\nclass UnimplementedTypeTab {}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/UserData.java",
    "content": "package app;\n\npublic interface UserData {\n\n    String getFullName();\n    String getEmail();\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/UserPage.java",
    "content": "package app.extension;\n\nimport app.Page;\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(type = Page.class)\nclass UserPage implements Page {\n\n    UserPage(Scope registry) {\n    }\n\n    @Override\n    public void show() {\n        // nop\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/UserPageMenuItem.java",
    "content": "package app.extension;\n\nimport app.MenuItem;\nimport magnet.Instance;\nimport magnet.Scope;\n\n@Instance(\n        type = MenuItem.class,\n        classifier = \"extended-menu\"\n)\nclass UserPageMenuItem implements MenuItem {\n\n    UserPageMenuItem(Scope registry) {\n    }\n\n    @Override\n    public int getId() {\n        return 0;\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/WorkProcessor.java",
    "content": "package app;\n\npublic interface WorkProcessor<I extends Runnable> {\n\n    void processWork(I processor);\n\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/generated/ForInterfaceWithGenericType_ExecutorMagnetFactory.java",
    "content": "package app.extension;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class ExecutorImplMagnetFactory extends InstanceFactory<Executor> {\n    @Override\n    public Executor create(Scope scope) {\n        return new ExecutorImpl();\n    }\n\n    public static Class getType() {\n        return Executor.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/generated/HomePageMagnetFactory.java",
    "content": "package app.extension;\n\nimport app.HomeRepository;\nimport app.Page;\nimport app.UserData;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class HomePageMagnetFactory extends InstanceFactory<Page> {\n\n    @Override\n    public Page create(Scope scope) {\n        HomeRepository homeRepository = scope.getSingle(HomeRepository.class, \"\");\n        UserData userData = scope.getSingle(UserData.class, \"\");\n        return new HomePage(homeRepository, userData, scope);\n    }\n\n    public static Class getType() {\n        return Page.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/generated/HomePageNoParamsMagnetFactory.java",
    "content": "package app.extension;\n\nimport app.Page;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class HomePageNoParamsMagnetFactory extends InstanceFactory<Page> {\n\n    @Override\n    public Page create(Scope scope) {\n        return new HomePageNoParams();\n    }\n\n    public static Class getType() {\n        return Page.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/generated/HomePageWithClassifierParamsMagnetFactory.java",
    "content": "package app.extension;\n\nimport app.HomeRepository;\nimport app.Page;\nimport app.UserData;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class HomePageWithClassifierParamsMagnetFactory extends InstanceFactory<Page> {\n\n    @Override\n    public Page create(Scope scope) {\n        HomeRepository homeRepository = scope.getOptional(HomeRepository.class, \"local\");\n        UserData userData = scope.getSingle(UserData.class, \"global\");\n        return new HomePageWithClassifierParams(homeRepository, userData);\n    }\n\n    public static Class getType() {\n        return Page.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/generated/HomePageWithManyParameterizedParamsMagnetFactory.java",
    "content": "package app.extension;\n\nimport app.Page;\nimport app.WorkProcessor;\nimport java.util.List;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class HomePageWithManyParameterizedParamsMagnetFactory extends InstanceFactory<Page> {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public Page create(Scope scope) {\n        List variant1 = scope.getMany(WorkProcessor.class, \"\");\n        List variant2 = scope.getMany(WorkProcessor.class, \"global\");\n        List variant3 = scope.getMany(WorkProcessor.class, \"\");\n        List variant4 = scope.getMany(WorkProcessor.class, \"global\");\n        return new HomePageWithManyParameterizedParams(variant1, variant2, variant3, variant4);\n    }\n\n    public static Class getType() {\n        return Page.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/generated/HomePageWithManyParameterizedWildcardInParamsMagnetFactory.java",
    "content": "package app.extension;\n\nimport app.Page;\nimport app.WorkProcessor;\nimport java.util.List;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class HomePageWithManyParameterizedWildcardInParamsMagnetFactory extends InstanceFactory<Page> {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public Page create(Scope scope) {\n        List variant1 = scope.getMany(WorkProcessor.class, \"\");\n        List variant2 = scope.getMany(WorkProcessor.class, \"global\");\n        List variant3 = scope.getMany(WorkProcessor.class, \"\");\n        List variant4 = scope.getMany(WorkProcessor.class, \"global\");\n        return new HomePageWithManyParameterizedWildcardInParams(variant1, variant2, variant3, variant4);\n    }\n\n    public static Class getType() {\n        return Page.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/generated/HomePageWithManyParameterizedWildcardKnownParamsMagnetFactory.java",
    "content": "package app.extension;\n\nimport app.Page;\nimport app.WorkProcessor;\nimport java.util.List;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class HomePageWithManyParameterizedWildcardKnownParamsMagnetFactory extends InstanceFactory<Page> {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public Page create(Scope scope) {\n        List variant1 = scope.getMany(WorkProcessor.class, \"\");\n        List variant2 = scope.getMany(WorkProcessor.class, \"global\");\n        List variant3 = scope.getMany(WorkProcessor.class, \"\");\n        List variant4 = scope.getMany(WorkProcessor.class, \"global\");\n        return new HomePageWithManyParameterizedWildcardKnownParams(variant1, variant2, variant3, variant4);\n    }\n\n    public static Class getType() {\n        return Page.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/generated/HomePageWithManyParameterizedWildcardOutParamsMagnetFactory.java",
    "content": "package app.extension;\n\nimport app.Page;\nimport app.WorkProcessor;\nimport java.util.List;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class HomePageWithManyParameterizedWildcardOutParamsMagnetFactory extends InstanceFactory<Page> {\n    @Override\n    @SuppressWarnings(\"unchecked\")\n    public Page create(Scope scope) {\n        List variant1 = scope.getMany(WorkProcessor.class, \"\");\n        List variant2 = scope.getMany(WorkProcessor.class, \"global\");\n        List variant3 = scope.getMany(WorkProcessor.class, \"\");\n        List variant4 = scope.getMany(WorkProcessor.class, \"global\");\n        return new HomePageWithManyParameterizedWildcardOutParams(variant1, variant2, variant3, variant4);\n    }\n\n    public static Class getType() {\n        return Page.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/generated/HomePageWithManyParamsMagnetFactory.java",
    "content": "package app.extension;\n\nimport app.HomeRepository;\nimport app.Page;\nimport java.util.List;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class HomePageWithManyParamsMagnetFactory extends InstanceFactory<Page> {\n\n    @Override\n    public Page create(Scope scope) {\n        List<HomeRepository> variant1 = scope.getMany(HomeRepository.class, \"\");\n        List<HomeRepository> variant2 = scope.getMany(HomeRepository.class, \"global\");\n        List<HomeRepository> variant3 = scope.getMany(HomeRepository.class, \"\");\n        List<HomeRepository> variant4 = scope.getMany(HomeRepository.class, \"global\");\n        return new HomePageWithManyParams(variant1, variant2, variant3, variant4);\n    }\n\n    public static Class getType() {\n        return Page.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/generated/HomePageWithManyWildcardParamsMagnetFactory.java",
    "content": "package app.extension;\n\nimport app.HomeRepository;\nimport app.Page;\nimport java.util.List;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class HomePageWithManyWildcardParamsMagnetFactory extends InstanceFactory<Page> {\n\n    @Override\n    public Page create(Scope scope) {\n        List<HomeRepository> repositories = scope.getMany(HomeRepository.class, \"\");\n        return new HomePageWithManyWildcardParams(repositories);\n    }\n\n    public static Class getType() {\n        return Page.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/generated/HomePageWithParamsMagnetFactory.java",
    "content": "package app.extension;\n\nimport app.HomeRepository;\nimport app.Page;\nimport app.UserData;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class HomePageWithParamsMagnetFactory extends InstanceFactory<Page> {\n\n    @Override\n    public Page create(Scope scope) {\n        HomeRepository homeRepository = scope.getOptional(HomeRepository.class, \"\");\n        UserData userData = scope.getSingle(UserData.class, \"\");\n        return new HomePageWithParams(homeRepository, userData);\n    }\n\n    public static Class getType() {\n        return Page.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/generated/HomePageWithScopeMagnetFactory.java",
    "content": "package app.extension;\n\nimport app.Page;\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class HomePageWithScopeMagnetFactory extends InstanceFactory<Page> {\n\n    @Override\n    public Page create(Scope scope) {\n        return new HomePageWithScope(scope);\n    }\n\n    public static Class getType() {\n        return Page.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/MagnetProcessorTest/generated/HomePageWithStaticConstructorSingleCreateRepositoriesMagnetFactory.java",
    "content": "package app.extension.utils;\n\nimport app.HomeRepository;\nimport app.Page;\nimport java.util.List;\nimport magnet.Scope;\nimport magnet.Scoping;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class HomePageWithStaticConstructorSingleCreateRepositoriesMagnetFactory extends InstanceFactory<Page> {\n\n    @Override\n    public Page create(Scope scope) {\n        List<HomeRepository> repositories = scope.getMany(HomeRepository.class, \"\");\n        return HomePageWithStaticConstructorSingle.create(repositories);\n    }\n\n    @Override\n    public Scoping getScoping() {\n        return Scoping.UNSCOPED;\n    }\n\n    public static Class getType() {\n        return Page.class;\n    }\n\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/Implementation1.java",
    "content": "package selector;\n\nimport magnet.Instance;\n\n@Instance(\n    types = Interface.class,\n    selector = \"\"\n)\nclass Implementation1 implements Interface {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/Implementation10.java",
    "content": "package selector;\n\nimport magnet.Instance;\n\n@Instance(\n    types = Interface.class,\n    selector = \"android.api !in 5..10\"\n)\nclass Implementation10 implements Interface {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/Implementation2.java",
    "content": "package selector;\n\nimport magnet.Instance;\n\n@Instance(\n    types = Interface.class,\n    selector = \"kaboom\"\n)\nclass Implementation2 implements Interface {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/Implementation3.java",
    "content": "package selector;\n\nimport magnet.Instance;\n\n@Instance(\n    types = Interface.class,\n    selector = \".api > 25\"\n)\nclass Implementation3 implements Interface {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/Implementation4.java",
    "content": "package selector;\n\nimport magnet.Instance;\n\n@Instance(\n    types = Interface.class,\n    selector = \"android. > 25\"\n)\nclass Implementation4 implements Interface {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/Implementation5.java",
    "content": "package selector;\n\nimport magnet.Instance;\n\n@Instance(\n    types = Interface.class,\n    selector = \"android.api kaboom 25\"\n)\nclass Implementation5 implements Interface {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/Implementation6.java",
    "content": "package selector;\n\nimport magnet.Instance;\n\n@Instance(\n    types = Interface.class,\n    selector = \"android.api >\"\n)\nclass Implementation6 implements Interface {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/Implementation7.java",
    "content": "package selector;\n\nimport magnet.Instance;\n\n@Instance(\n    types = Interface.class,\n    selector = \"android.api >= 28\"\n)\nclass Implementation7 implements Interface {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/Implementation8.java",
    "content": "package selector;\n\nimport magnet.Instance;\n\n@Instance(\n    types = Interface.class,\n    selector = \"android.api in 1..19\"\n)\nclass Implementation8 implements Interface {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/Implementation9.java",
    "content": "package selector;\n\nimport magnet.Instance;\n\n@Instance(\n    types = Interface.class,\n    selector = \"android.api != 19\"\n)\nclass Implementation9 implements Interface {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/Interface.java",
    "content": "package selector;\n\ninterface Interface {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/generated/Implementation10MagnetFactory.java",
    "content": "package selector;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class Implementation10MagnetFactory extends InstanceFactory<Interface> {\n    private static String[] SELECTOR = { \"android\", \"api\", \"!in\", \"5\", \"10\" };\n\n    @Override\n    public Interface create(Scope scope) {\n        return new Implementation10();\n    }\n\n    @Override\n    public String[] getSelector() {\n        return SELECTOR;\n    }\n\n    public static Class getType() {\n        return Interface.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/generated/Implementation1MagnetFactory.java",
    "content": "package selector;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class Implementation1MagnetFactory extends InstanceFactory<Interface> {\n    @Override\n    public Interface create(Scope scope) {\n        return new Implementation1();\n    }\n\n    public static Class getType() {\n        return Interface.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/generated/Implementation7MagnetFactory.java",
    "content": "package selector;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class Implementation7MagnetFactory extends InstanceFactory<Interface> {\n    private static String[] SELECTOR = { \"android\", \"api\", \">=\", \"28\" };\n\n    @Override\n    public Interface create(Scope scope) {\n        return new Implementation7();\n    }\n\n    @Override\n    public String[] getSelector() {\n        return SELECTOR;\n    }\n\n    public static Class getType() {\n        return Interface.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/generated/Implementation8MagnetFactory.java",
    "content": "package selector;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class Implementation8MagnetFactory extends InstanceFactory<Interface> {\n    private static String[] SELECTOR = { \"android\", \"api\", \"in\", \"1\", \"19\" };\n\n    @Override\n    public Interface create(Scope scope) {\n        return new Implementation8();\n    }\n\n    @Override\n    public String[] getSelector() {\n        return SELECTOR;\n    }\n\n    public static Class getType() {\n        return Interface.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/SelectorInFactoryClassTest/generated/Implementation9MagnetFactory.java",
    "content": "package selector;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class Implementation9MagnetFactory extends InstanceFactory<Interface> {\n    private static String[] SELECTOR = { \"android\", \"api\", \"!=\", \"19\" };\n\n    @Override\n    public Interface create(Scope scope) {\n        return new Implementation9();\n    }\n\n    @Override\n    public String[] getSelector() {\n        return SELECTOR;\n    }\n\n    public static Class getType() {\n        return Interface.class;\n    }\n}"
  },
  {
    "path": "magnet-processor/src/test/resources/SiblingTypesTest/Implementation1.java",
    "content": "package siblings;\n\nimport magnet.Instance;\n\n@Instance()\nclass Implementation1 implements Interface1, Interface2 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SiblingTypesTest/Implementation2.java",
    "content": "package siblings;\n\nimport magnet.Instance;\n\n@Instance(type = Interface1.class, types = {Interface1.class, Interface2.class})\nclass Implementation1 implements Interface1, Interface2 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SiblingTypesTest/Implementation3.java",
    "content": "package siblings;\n\nimport magnet.Instance;\n\n@Instance(type = Interface1.class, types = {Interface1.class, Interface2.class})\nclass Implementation1 implements Interface1 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SiblingTypesTest/Implementation4.java",
    "content": "package siblings;\n\nimport magnet.Instance;\n\n@Instance(types = {Interface1.class, Interface2.class})\nclass Implementation4 implements Interface1, Interface2 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SiblingTypesTest/Implementation5.java",
    "content": "package siblings;\n\nimport magnet.Instance;\nimport magnet.Scoping;\n\n@Instance(types = {Interface1.class, Interface2.class}, scoping = Scoping.UNSCOPED)\nclass Implementation5 implements Interface1, Interface2 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SiblingTypesTest/Interface1.java",
    "content": "package siblings;\n\ninterface Interface1 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SiblingTypesTest/Interface2.java",
    "content": "package siblings;\n\ninterface Interface2 {}"
  },
  {
    "path": "magnet-processor/src/test/resources/SiblingTypesTest/generated/Implementation4Interface1MagnetFactory.java",
    "content": "package siblings;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class Implementation4Interface1MagnetFactory extends InstanceFactory<Interface1> {\n    private static Class[] SIBLING_TYPES = {Interface2.class, Implementation4Interface2MagnetFactory.class};\n\n    @Override\n    public Interface1 create(Scope scope) {\n        return new Implementation4();\n    }\n\n    @Override\n    public Class[] getSiblingTypes() {\n        return SIBLING_TYPES\n    }\n\n    public static Class getType() {\n        return Interface1.class;\n    }\n}\n"
  },
  {
    "path": "magnet-processor/src/test/resources/SiblingTypesTest/generated/Implementation4Interface2MagnetFactory.java",
    "content": "package siblings;\n\nimport magnet.Scope;\nimport magnet.internal.Generated;\nimport magnet.internal.InstanceFactory;\n\n@Generated\npublic final class Implementation4Interface2MagnetFactory extends InstanceFactory<Interface2> {\n    private static Class[] SIBLING_TYPES = {Interface1.class, Implementation4Interface1MagnetFactory.class};\n\n    @Override\n    public Interface2 create(Scope scope) {\n        return new Implementation4();\n    }\n\n    @Override\n    public Class[] getSiblingTypes() {\n        return SIBLING_TYPES;\n    }\n\n    public static Class getType() {\n        return Interface2.class;\n    }\n}\n"
  },
  {
    "path": "magnetx-app/build.gradle",
    "content": "plugins {\n    id 'kotlin'\n    id 'kotlin-kapt'\n    id 'com.vanniktech.maven.publish'\n}\n\ncompileKotlin {\n    kotlinOptions {\n        jvmTarget = javaVersion\n    }\n}\n\ncompileTestKotlin {\n    kotlinOptions {\n        jvmTarget = javaVersion\n    }\n}\n\ndependencies {\n    implementation deps.kotlinjdk\n    api project(':magnet')\n    kapt project(':magnet-processor')\n}\n"
  },
  {
    "path": "magnetx-app/gradle.properties",
    "content": "POM_NAME=Application Extension API for Magnet\nPOM_ARTIFACT_ID=magnetx-app\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "magnetx-app/src/main/kotlin/magnetx/AppExtension.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnetx\n\nimport magnet.Instance\n\n/**\n * Interface to be implemented by extensions of `android.app.Application` class.\n * Application implementation class should query the extensions using `getMany()`\n * operator with `AppExtension` type from the application scope.\n *\n * ### Scope dependencies\n * `application: Application`\n *\n * ### Scoping\n * any scoping\n *\n * ### Usage example\n * ```kotlin\n * @Instance(\n *   type = AppExtension::class,\n *   scoping = Scoping.UNSCOPED\n * )\n * internal class LeakCanaryAppExtension(\n *   private val app: Application\n * ) : AppExtension {\n *   override fun onCreate() {\n *     if (LeakCanary.isInAnalyzerProcess(context)) {\n *       return\n *     }\n *     LeakCanary.install(context as Application)\n *   }\n * }\n * ```\n */\ninterface AppExtension {\n\n    /**\n     * Called on each registered extension when `Application.onCreate()` is called.\n     *\n     * For more information see\n     * [https://developer.android.com/reference/android/app/Application.html#onCreate()]\n     */\n    fun onCreate()\n\n    /**\n     * Called on each registered extension when `Application.onTrimMemory()` is called.\n     *\n     * For more information see\n     * [https://developer.android.com/reference/android/app/Application.html#onTrimMemory(int)]\n     */\n    fun onTrimMemory(level: Int) {}\n\n    /**\n     * Delegate to be used in Application for dispatching application events to\n     * all registered application extensions.\n     */\n    @Instance(type = AppExtension.Delegate::class)\n    class Delegate(private val appExtensions: List<AppExtension>) {\n        fun onCreate() {\n            for (appExtension in appExtensions) {\n                appExtension.onCreate()\n            }\n        }\n\n        fun onTrimMemory(level: Int) {\n            for (appExtension in appExtensions) {\n                appExtension.onTrimMemory(level)\n            }\n        }\n    }\n\n}\n"
  },
  {
    "path": "magnetx-app-rx3android/build.gradle",
    "content": "plugins {\n    id 'com.android.library'\n    id 'kotlin-android'\n    id 'kotlin-kapt'\n    id 'com.vanniktech.maven.publish'\n}\n\nrepositories {\n    maven { url 'https://maven.google.com' }\n}\n\nandroid {\n    compileSdkVersion 32\n    defaultConfig {\n        minSdkVersion 15\n        targetSdkVersion 32\n    }\n}\n\ndependencies {\n    compileOnly deps.rx3android\n    implementation deps.kotlinjdk\n    implementation project(':magnet')\n    kapt project(':magnet-processor')\n    api project(':magnetx-app')\n}\n\ntasks.withType(Javadoc).all {\n    excludes = ['**/*.kt']\n}\n"
  },
  {
    "path": "magnetx-app-rx3android/gradle.properties",
    "content": "POM_NAME=Application magnet registering MainThreadSchedulerHandler at RxAndroidPlugins (RxJava3)\nPOM_ARTIFACT_ID=magnetx-app-rx3android\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "magnetx-app-rx3android/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"magnetx.app.rx3android\"/>\n"
  },
  {
    "path": "magnetx-app-rx3android/src/main/java/magnetx/RxAndroidAppExtension.kt",
    "content": "/*\n * Copyright (C) 2020 Sergej Shafarenka, www.halfbit.de\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 magnetx\n\nimport android.os.Looper\nimport io.reactivex.rxjava3.android.plugins.RxAndroidPlugins\nimport io.reactivex.rxjava3.android.schedulers.AndroidSchedulers\nimport magnet.Instance\nimport magnet.Scoping\n\n@Instance(\n    type = AppExtension::class,\n    scoping = Scoping.UNSCOPED\n)\nclass RxAndroidAppExtension : AppExtension {\n\n    override fun onCreate() {\n        RxAndroidPlugins.setMainThreadSchedulerHandler {\n            AndroidSchedulers.from(Looper.getMainLooper(), true)\n        }\n    }\n\n}\n"
  },
  {
    "path": "magnetx-app-rxandroid/build.gradle",
    "content": "plugins {\n    id 'com.android.library'\n    id 'kotlin-android'\n    id 'kotlin-kapt'\n    id 'com.vanniktech.maven.publish'\n}\n\nrepositories {\n    maven { url 'https://maven.google.com' }\n}\n\nandroid {\n    compileSdkVersion 32\n    defaultConfig {\n        minSdkVersion 15\n        targetSdkVersion 32\n        versionCode 0\n        versionName \"0\"\n    }\n}\n\ndependencies {\n    compileOnly deps.rxandroid\n    implementation deps.kotlinjdk\n    implementation project(':magnet')\n    kapt project(':magnet-processor')\n    api project(':magnetx-app')\n}\n\ntasks.withType(Javadoc).all {\n    excludes = ['**/*.kt']\n}\n"
  },
  {
    "path": "magnetx-app-rxandroid/gradle.properties",
    "content": "POM_NAME=Application magnet registering MainThreadSchedulerHandler at RxAndroidPlugins\nPOM_ARTIFACT_ID=magnetx-app-rxandroid\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "magnetx-app-rxandroid/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"magnetx.app.rxandroid\"/>\n"
  },
  {
    "path": "magnetx-app-rxandroid/src/main/java/magnetx/RxAndroidAppExtension.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnetx\n\nimport android.os.Looper\nimport io.reactivex.android.plugins.RxAndroidPlugins\nimport io.reactivex.android.schedulers.AndroidSchedulers\nimport magnet.Instance\nimport magnet.Scoping\n\n@Instance(\n    type = AppExtension::class,\n    scoping = Scoping.UNSCOPED\n)\nclass RxAndroidAppExtension : AppExtension {\n\n    override fun onCreate() {\n        RxAndroidPlugins.setMainThreadSchedulerHandler {\n            AndroidSchedulers.from(Looper.getMainLooper(), true)\n        }\n    }\n\n}\n"
  },
  {
    "path": "magnetx-app-stetho/build.gradle",
    "content": "plugins {\n    id 'com.android.library'\n    id 'kotlin-android'\n    id 'kotlin-kapt'\n    id 'com.vanniktech.maven.publish'\n}\n\nrepositories {\n    maven { url 'https://maven.google.com' }\n}\n\nandroid {\n    compileSdkVersion 31\n    defaultConfig {\n        minSdkVersion 15\n        targetSdkVersion 31\n        versionCode 0\n        versionName \"0\"\n    }\n}\n\ndependencies {\n    api project(':magnetx-app')\n    compileOnly deps.stetho\n    implementation deps.kotlinjdk\n    kapt project(':magnet-processor')\n}\n\ntasks.withType(Javadoc).all {\n    excludes = ['**/*.kt']\n}\n"
  },
  {
    "path": "magnetx-app-stetho/gradle.properties",
    "content": "POM_NAME=Magnet application extension for Stetho\nPOM_ARTIFACT_ID=magnetx-app-stetho\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "magnetx-app-stetho/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"magnetx.app.stetho\"/>\n"
  },
  {
    "path": "magnetx-app-stetho/src/main/java/magnetx/app/stetho/StethoAppExtension.kt",
    "content": "/*\n * Copyright (C) 2019 Sergej Shafarenka, www.halfbit.de\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 magnetx.app.stetho\n\nimport android.app.Application\nimport android.content.Context\nimport com.facebook.stetho.Stetho\nimport magnet.Instance\nimport magnet.Scoping\nimport magnetx.AppExtension\n\n@Instance(\n    type = AppExtension::class,\n    scoping = Scoping.UNSCOPED\n)\nclass StethoAppExtension(\n    private val application: Application,\n    private val stethoInitializers: List<Initializer>\n) : AppExtension {\n\n    override fun onCreate() {\n        Stetho.initialize(\n            Stetho\n                .newInitializerBuilder(application)\n                .also {\n                    for (stethoInitializer in stethoInitializers) {\n                        stethoInitializer.initialize(it, application)\n                    }\n                }\n                .build()\n        )\n    }\n\n    /**\n     * Implement this interface and annotate in with unscoped {@link Instance}\n     * to participate on initializing Stetho on application launch.\n     */\n    interface Initializer {\n        fun initialize(builder: Stetho.InitializerBuilder, context: Context)\n    }\n}\n"
  },
  {
    "path": "magnetx-app-stetho-scope/build.gradle",
    "content": "plugins {\n    id 'com.android.library'\n    id 'kotlin-android'\n    id 'kotlin-kapt'\n    id 'com.vanniktech.maven.publish'\n}\n\nrepositories {\n    maven { url 'https://maven.google.com' }\n}\n\nandroid {\n    compileSdkVersion 32\n    defaultConfig {\n        minSdkVersion 15\n        targetSdkVersion 32\n        versionCode 0\n        versionName \"0\"\n    }\n}\n\ndependencies {\n    api project(':magnetx-app-stetho')\n    compileOnly deps.stetho\n    implementation deps.kotlinjdk\n    kapt project(':magnet-processor')\n}\n\ntasks.withType(Javadoc).all {\n    excludes = ['**/*.kt']\n}\n"
  },
  {
    "path": "magnetx-app-stetho-scope/gradle.properties",
    "content": "POM_NAME=Magnet application extension providing a Stetho scope dumper\nPOM_ARTIFACT_ID=magnetx-app-stetho-scope\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "magnetx-app-stetho-scope/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"magnetx.app.stetho.scope\"/>\n"
  },
  {
    "path": "magnetx-app-stetho-scope/src/main/java/magnetx/app/stetho/scope/ScopeDumper.kt",
    "content": "/*\n * Copyright (C) 2019 Sergej Shafarenka, www.halfbit.de\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 magnetx.app.stetho.scope\n\nimport magnet.Classifier\nimport magnet.Visitor\nimport magnet.Visitor.Instance\nimport magnet.Visitor.Scope\nimport java.io.PrintStream\n\ninternal class ScopeDumper(private val writer: PrintStream) : Visitor {\n\n    private val instances = mutableListOf<Instance>()\n    private var currentScope: Scope? = null\n    private var level = 0\n\n    override fun onEnterScope(scope: Scope, parent: Scope?): Boolean {\n        currentScope?.let { instances.dump(it, level, writer) }\n        currentScope = scope\n        level++\n        return true\n    }\n\n    override fun onInstance(instance: Instance): Boolean {\n        instances.add(instance)\n        return true\n    }\n\n    override fun onExitScope(scope: Scope) {\n        currentScope?.let { instances.dump(it, level, writer) }\n        currentScope = null\n        level--\n    }\n}\n\nprivate fun MutableList<Instance>.dump(scope: Scope, level: Int, writer: PrintStream) {\n    val indentScope = \"   \".repeat(level - 1)\n    val limits = scope.limits?.let { \"<${it.joinToString(\", \")}> \" } ?: \"\"\n    writer.println(\"$indentScope [$level] $limits$scope\")\n\n    sortWith(compareBy({ it.provision }, { it.scoping }, { it.limit }, { it.type.name }))\n    val indentInstance = \"   \".repeat(level)\n    for (instance in this) {\n        val line = when (instance.provision) {\n            Visitor.Provision.BOUND -> instance.renderBound()\n            Visitor.Provision.INJECTED -> instance.renderInjected()\n        }\n        writer.println(\"$indentInstance $line\")\n    }\n    clear()\n}\n\nprivate fun Instance.renderBound(): String =\n    if (classifier == Classifier.NONE) \"$provision ${type.simpleName} $value\"\n    else \"$provision ${type.name}@$classifier $value\"\n\nprivate fun Instance.renderInjected(): String {\n    val renderedScoping = if (limit.isNotEmpty()) \"<$limit>\" else scoping.toString()\n    return if (classifier == Classifier.NONE) \"$renderedScoping ${type.simpleName} $value\"\n    else \"$renderedScoping ${type.simpleName}@$classifier $value\"\n}\n\n"
  },
  {
    "path": "magnetx-app-stetho-scope/src/main/java/magnetx/app/stetho/scope/StethoScopeDumpPlugin.kt",
    "content": "/*\n * Copyright (C) 2019 Sergej Shafarenka, www.halfbit.de\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 magnetx.app.stetho.scope\n\nimport com.facebook.stetho.dumpapp.ArgsHelper\nimport com.facebook.stetho.dumpapp.DumpUsageException\nimport com.facebook.stetho.dumpapp.DumperContext\nimport com.facebook.stetho.dumpapp.DumperPlugin\nimport magnet.Scope\nimport java.io.PrintStream\n\ninternal class StethoScopeDumpPlugin(\n    private val scope: Scope\n) : DumperPlugin {\n\n    override fun getName(): String = NAME_MAGNET\n\n    override fun dump(dumpContext: DumperContext) {\n        val writer: PrintStream = dumpContext.stdout\n        val args: Iterator<String> = dumpContext.argsAsList.iterator()\n\n        val command: String? = ArgsHelper.nextOptionalArg(args, null)\n        when (command) {\n            CMD_SCOPE -> doDumpScopes(args, writer)\n            else -> {\n                doUsage(writer)\n                if (command != null) {\n                    throw DumpUsageException(\"Unknown command: $command\")\n                }\n            }\n        }\n    }\n\n    private fun doDumpScopes(args: Iterator<String>, writer: PrintStream) {\n        val depth = ArgsHelper.nextOptionalArg(args, null)?.toInt() ?: Integer.MAX_VALUE\n        scope.accept(ScopeDumper(writer), depth)\n    }\n\n    private fun doUsage(writer: PrintStream) {\n        with(writer) {\n            println(\"Usage: ./dumpapp magnet scope [<depth:Int>]\")\n            println()\n        }\n    }\n}\n\nprivate const val NAME_MAGNET = \"magnet\"\nprivate const val CMD_SCOPE = \"scope\""
  },
  {
    "path": "magnetx-app-stetho-scope/src/main/java/magnetx/app/stetho/scope/StethoScopeInitializer.kt",
    "content": "/*\n * Copyright (C) 2019 Sergej Shafarenka, www.halfbit.de\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 magnetx.app.stetho.scope\n\nimport android.content.Context\nimport com.facebook.stetho.Stetho\nimport magnet.Instance\nimport magnet.Scope\nimport magnet.Scoping\nimport magnetx.app.stetho.StethoAppExtension\n\n@Instance(\n    type = StethoAppExtension.Initializer::class,\n    scoping = Scoping.UNSCOPED\n)\ninternal class StethoScopeInitializer(\n    private val scope: Scope\n) : StethoAppExtension.Initializer {\n    override fun initialize(builder: Stetho.InitializerBuilder, context: Context) {\n        builder.enableDumpapp {\n            Stetho.DefaultDumperPluginsBuilder(context)\n                .provide(StethoScopeDumpPlugin(scope))\n                .finish()\n        }\n    }\n}\n"
  },
  {
    "path": "magnetx-selector-android/build.gradle",
    "content": "plugins {\n    id 'kotlin'\n    id 'kotlin-kapt'\n    id 'com.vanniktech.maven.publish'\n}\n\nrepositories {\n    maven { url 'https://maven.google.com' }\n}\n\ncompileKotlin {\n    kotlinOptions {\n        jvmTarget = javaVersion\n    }\n}\n\ncompileTestKotlin {\n    kotlinOptions {\n        jvmTarget = javaVersion\n    }\n}\n\ndependencies {\n    compileOnly deps.android\n    implementation deps.kotlinjdk\n    implementation project(':magnet')\n    kapt project(':magnet-processor')\n}"
  },
  {
    "path": "magnetx-selector-android/gradle.properties",
    "content": "POM_NAME=Magner selection filter evaluating Android API level field\nPOM_ARTIFACT_ID=magnetx-selector-android\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "magnetx-selector-android/src/main/kotlin/magnetx/AndroidSelectorFilter.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnetx\n\nimport android.os.Build\nimport magnet.Instance\nimport magnet.SelectorFilter\n\n@Instance(\n    type = SelectorFilter::class,\n    classifier = \"android\"\n)\ninternal class AndroidSelectorFilter : SelectorFilter() {\n\n    override fun filter(selector: Array<out String>): Boolean {\n        check(selector.size >= 4) { \"Unexpected selector length: ${selector.size}. $VERSION_ERROR\" }\n        check(selector[1] == \"api\") { \"Unexpected selector key ${selector[1]}. $VERSION_ERROR\" }\n\n        val operator = when (selector[2]) {\n            \">=\" -> Operator.GreatOrEqual\n            \"<=\" -> Operator.LessOrEqual\n            \">\" -> Operator.Great\n            \"<\" -> Operator.Less\n            \"==\" -> Operator.Equal\n            \"!=\" -> Operator.NotEqual\n            \"in\" -> Operator.In\n            \"!in\" -> Operator.NotIn\n            else -> error(\"Unsupported operator ${selector[2]}. $VERSION_ERROR\")\n        }\n\n        return when (operator) {\n            is Operator.OneOperand -> operator.apply(operand = selector[3].toInt())\n            is Operator.TwoOperands -> {\n                check(selector.size > 4) { \"Unexpected selector length ${selector.size} for $operator. $VERSION_ERROR\" }\n                operator.apply(operand1 = selector[3].toInt(), operand2 = selector[4].toInt())\n            }\n            else -> error(\"Unsupported operator type: $operator\")\n        }\n    }\n\n    companion object {\n        private const val VERSION_ERROR = \"Make sure to use same versions of 'magnet' and 'magnetx' packages.\"\n    }\n\n}\n\nprivate sealed class Operator {\n\n    interface OneOperand {\n        fun apply(operand: Int): Boolean\n    }\n\n    interface TwoOperands {\n        fun apply(operand1: Int, operand2: Int): Boolean\n    }\n\n    object NotIn : Operator(), TwoOperands {\n        override fun apply(operand1: Int, operand2: Int): Boolean = Build.VERSION.SDK_INT !in operand1..operand2\n    }\n\n    object In : Operator(), TwoOperands {\n        override fun apply(operand1: Int, operand2: Int): Boolean = Build.VERSION.SDK_INT in operand1..operand2\n    }\n\n    object Less : Operator(), OneOperand {\n        override fun apply(operand: Int) = Build.VERSION.SDK_INT < operand\n    }\n\n    object Great : Operator(), OneOperand {\n        override fun apply(operand: Int) = Build.VERSION.SDK_INT > operand\n    }\n\n    object LessOrEqual : Operator(), OneOperand {\n        override fun apply(operand: Int) = Build.VERSION.SDK_INT <= operand\n    }\n\n    object GreatOrEqual : Operator(), OneOperand {\n        override fun apply(operand: Int) = Build.VERSION.SDK_INT >= operand\n    }\n\n    object Equal : Operator(), OneOperand {\n        override fun apply(operand: Int) = Build.VERSION.SDK_INT == operand\n    }\n\n    object NotEqual : Operator(), OneOperand {\n        override fun apply(operand: Int) = Build.VERSION.SDK_INT != operand\n    }\n}\n"
  },
  {
    "path": "magnetx-selector-features/build.gradle",
    "content": "plugins {\n    id 'kotlin'\n    id 'kotlin-kapt'\n    id 'com.vanniktech.maven.publish'\n}\n\nrepositories {\n    maven { url 'https://maven.google.com' }\n}\n\ncompileKotlin {\n    kotlinOptions {\n        jvmTarget = javaVersion\n    }\n}\n\ncompileTestKotlin {\n    kotlinOptions {\n        jvmTarget = javaVersion\n    }\n}\n\ndependencies {\n    compileOnly deps.android\n    implementation deps.kotlinjdk\n    implementation project(':magnet')\n    kapt project(':magnet-processor')\n}\n"
  },
  {
    "path": "magnetx-selector-features/gradle.properties",
    "content": "POM_NAME=Magner selection filter evaluating feature flags stored in provided SharedPreferences\nPOM_ARTIFACT_ID=magnetx-selector-features\nPOM_PACKAGING=jar\n"
  },
  {
    "path": "magnetx-selector-features/src/main/AndroidManifest.xml",
    "content": "<manifest package=\"magnetx.selector.features\"/>\n"
  },
  {
    "path": "magnetx-selector-features/src/main/java/magnetx/FeaturesSelectorFilter.kt",
    "content": "/*\n * Copyright (C) 2018 Sergej Shafarenka, www.halfbit.de\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 magnetx\n\nimport android.content.SharedPreferences\nimport magnet.Classifier\nimport magnet.Instance\nimport magnet.SelectorFilter\n\nconst val FEATURE_SELECTOR = \"features\"\n\n/**\n * This class enables selective injection based on boolean values stored in\n * provided shared preferences. Add the library containing this class to your\n * app module to enable feature selector.\n *\n *\n * ### Scope dependencies\n * `@Classifier(FEATURE_SELECTOR) preferences: SharedPreferences`\n *\n * ### Scoping\n * any scoping\n */\n@Instance(\n    type = SelectorFilter::class,\n    classifier = FEATURE_SELECTOR\n)\ninternal class FeaturesSelectorFilter(\n    @Classifier(FEATURE_SELECTOR) private val preferences: SharedPreferences\n) : SelectorFilter() {\n\n    override fun filter(selector: Array<String>): Boolean {\n        check(selector.size == 4) { \"Expected selector length 4, actual: ${selector.size}.\" }\n\n        val operator = when (selector[2]) {\n            \"==\" -> Operator.Equal\n            \"!=\" -> Operator.NotEqual\n            else -> error(\"Supported operators == and !=, actual: ${selector[2]}\")\n        }\n\n        return operator.apply(\n            key = selector[1],\n            operand = selector[3].toBoolean(),\n            preferences = preferences\n        )\n    }\n  \n}\n\nprivate sealed class Operator {\n\n    abstract fun apply(key: String, operand: Boolean, preferences: SharedPreferences): Boolean\n\n    object Equal : Operator() {\n        override fun apply(key: String, operand: Boolean, preferences: SharedPreferences) =\n            preferences.getBoolean(key, false) == operand\n    }\n\n    object NotEqual : Operator() {\n        override fun apply(key: String, operand: Boolean, preferences: SharedPreferences) =\n            preferences.getBoolean(key, false) != operand\n    }\n\n}\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':magnet',\n        ':magnet-kotlin',\n        ':magnet-processor',\n        ':magnetx-app',\n        ':magnetx-app-stetho',\n        ':magnetx-app-stetho-scope',\n        ':magnetx-app-rxandroid',\n        ':magnetx-app-rx3android',\n        ':magnetx-selector-android',\n        ':magnetx-selector-features'\n"
  }
]