diff --git a/.gitignore b/.gitignore
index 12ce845e..4dcabb7a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,42 +1,8 @@
-# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
-# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
-# From: https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore
-
# User-specific stuff
-.idea/**/workspace.xml
-.idea/**/tasks.xml
-.idea/**/misc.xml
-.idea/**/usage.statistics.xml
-.idea/**/dictionaries
-.idea/**/shelf
-
-# Generated files
-.idea/**/contentModel.xml
-
-# Sensitive or high-churn files
-.idea/**/dataSources/
-.idea/**/dataSources.ids
-.idea/**/dataSources.local.xml
-.idea/**/sqlDataSources.xml
-.idea/**/dynamic.xml
-.idea/**/uiDesigner.xml
-.idea/**/dbnavigator.xml
-
-# Gradle
-.idea/**/gradle.xml
-.idea/**/libraries
-
-# Gradle and Maven with auto-import
-# When using Gradle or Maven with auto-import, you should exclude module files,
-# since they will be recreated, and may cause churn.
-.idea/artifacts
-.idea/compiler.xml
-.idea/jarRepositories.xml
-.idea/modules.xml
-.idea/*.iml
-.idea/modules
-*.iml
-*.ipr
+.idea/
+!.idea/codeStyles
+!.idea/inspectionProfiles
+!.idea/vcs.xml
# Build dirs
/build/
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
deleted file mode 100644
index 148fdd24..00000000
--- a/.idea/kotlinc.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/codegen/impl/src/main/kotlin/com/yandex/yatagan/codegen/impl/AssistedInjectFactoryGenerator.kt b/codegen/impl/src/main/kotlin/com/yandex/yatagan/codegen/impl/AssistedInjectFactoryGenerator.kt
index c185e3d0..edecbf97 100644
--- a/codegen/impl/src/main/kotlin/com/yandex/yatagan/codegen/impl/AssistedInjectFactoryGenerator.kt
+++ b/codegen/impl/src/main/kotlin/com/yandex/yatagan/codegen/impl/AssistedInjectFactoryGenerator.kt
@@ -25,6 +25,7 @@ import com.yandex.yatagan.codegen.poetry.buildExpression
import com.yandex.yatagan.core.graph.BindingGraph
import com.yandex.yatagan.core.graph.bindings.AssistedInjectFactoryBinding
import com.yandex.yatagan.core.model.AssistedInjectFactoryModel
+import com.yandex.yatagan.core.model.ConditionScope
import com.yandex.yatagan.core.model.component1
import com.yandex.yatagan.core.model.component2
import javax.inject.Inject
@@ -38,13 +39,15 @@ internal class AssistedInjectFactoryGenerator @Inject constructor(
) : ComponentGenerator.Contributor {
private val modelToImpl: Map by lazy {
val classNamespace = Namespace()
- thisGraph.localAssistedInjectFactories.associateWith { model ->
- componentImplName.nestedClass(classNamespace.name(
- nameModel = model.name,
- suffix = "Impl",
- firstCapital = true,
- ))
- }
+ thisGraph.localAssistedInjectFactories
+ .filter { it.value != ConditionScope.Never }
+ .mapValues {
+ componentImplName.nestedClass(classNamespace.name(
+ nameModel = it.key.name,
+ suffix = "Impl",
+ firstCapital = true,
+ ))
+ }
}
fun generateCreation(
diff --git a/core/graph/api/api/api.api b/core/graph/api/api/api.api
index 248e0d19..64c82bd0 100644
--- a/core/graph/api/api/api.api
+++ b/core/graph/api/api/api.api
@@ -3,7 +3,7 @@ public abstract interface class com/yandex/yatagan/core/graph/BindingGraph : com
public abstract fun getCreator ()Lcom/yandex/yatagan/core/model/ComponentFactoryModel;
public abstract fun getDependencies ()Ljava/util/Collection;
public abstract fun getEntryPoints ()Ljava/util/Collection;
- public abstract fun getLocalAssistedInjectFactories ()Ljava/util/Collection;
+ public abstract fun getLocalAssistedInjectFactories ()Ljava/util/Map;
public abstract fun getLocalBindings ()Ljava/util/Map;
public abstract fun getLocalConditionLiterals ()Ljava/util/Map;
public abstract fun getMemberInjectors ()Ljava/util/Collection;
diff --git a/core/graph/api/src/main/kotlin/com/yandex/yatagan/core/graph/BindingGraph.kt b/core/graph/api/src/main/kotlin/com/yandex/yatagan/core/graph/BindingGraph.kt
index 556123dc..f573d2c7 100644
--- a/core/graph/api/src/main/kotlin/com/yandex/yatagan/core/graph/BindingGraph.kt
+++ b/core/graph/api/src/main/kotlin/com/yandex/yatagan/core/graph/BindingGraph.kt
@@ -71,7 +71,8 @@ public interface BindingGraph : MayBeInvalid, Extensible,
/**
* [AssistedInjectFactoryModel]s that are hosted in this graph.
*/
- public val localAssistedInjectFactories: Collection
+ @Incubating
+ public val localAssistedInjectFactories: Map
/**
* A collection of parent (not necessarily direct) [BindingGraph]s, from which bindings and/or conditions are used
diff --git a/core/graph/impl/src/main/kotlin/com/yandex/yatagan/core/graph/impl/BindingGraphImpl.kt b/core/graph/impl/src/main/kotlin/com/yandex/yatagan/core/graph/impl/BindingGraphImpl.kt
index a641ff48..10a36b4b 100644
--- a/core/graph/impl/src/main/kotlin/com/yandex/yatagan/core/graph/impl/BindingGraphImpl.kt
+++ b/core/graph/impl/src/main/kotlin/com/yandex/yatagan/core/graph/impl/BindingGraphImpl.kt
@@ -122,7 +122,7 @@ internal class BindingGraphImpl private constructor(
internal val localNodes = mutableSetOf()
override val localBindings = mutableMapOf()
override val localConditionLiterals = mutableMapOf()
- override val localAssistedInjectFactories = mutableSetOf()
+ override val localAssistedInjectFactories = mutableMapOf()
override val usedParents = mutableSetOf()
override val children: Collection
@@ -210,7 +210,7 @@ internal class BindingGraphImpl private constructor(
binding.accept(object : Binding.Visitor {
override fun visitOther(binding: Binding) = Unit
override fun visitAssistedInjectFactory(binding: AssistedInjectFactoryBinding) {
- localAssistedInjectFactories += binding.model
+ localAssistedInjectFactories[binding.model] = binding.conditionScope
}
})
}
@@ -259,7 +259,7 @@ internal class BindingGraphImpl private constructor(
for (child in childrenSequence(includeThis = false)) {
child as BindingGraphImpl
val usesConditions = child.localConditionLiterals.keys.removeAll(localConditionLiterals.keys)
- val usesAssistedInjectFactories = child.localAssistedInjectFactories.removeAll(localAssistedInjectFactories)
+ val usesAssistedInjectFactories = child.localAssistedInjectFactories.keys.removeAll(localAssistedInjectFactories.keys)
if (usesConditions || usesAssistedInjectFactories) {
// This will never be seen by materialization and that's okay, because no bindings are required here.
child.usedParents += this
diff --git a/testing/tests/src/test/kotlin/com/yandex/yatagan/testing/tests/ConditionsTest.kt b/testing/tests/src/test/kotlin/com/yandex/yatagan/testing/tests/ConditionsTest.kt
index 922d9b42..767e0fb6 100644
--- a/testing/tests/src/test/kotlin/com/yandex/yatagan/testing/tests/ConditionsTest.kt
+++ b/testing/tests/src/test/kotlin/com/yandex/yatagan/testing/tests/ConditionsTest.kt
@@ -1216,4 +1216,52 @@ class ConditionsTest(
compileRunAndValidate()
}
+
+ @Test
+ fun `issue #209 - assisted factory generated for unsupported variants`() {
+ includeFromSourceSet(flavors)
+
+ givenKotlinSource("test.TestCase", """
+ import com.yandex.yatagan.*
+ import javax.inject.*
+
+ @AssistedFactory
+ interface PhoneAssistedFactory {
+ fun create(i: Int): PhoneAssistedClass
+ }
+
+ @Conditional(onlyIn = [DeviceType.Phone::class])
+ class PhoneAssistedClass @AssistedInject constructor(
+ phoneDependency: PhoneDependency,
+ @Assisted arg: Int,
+ )
+
+ @Conditional(onlyIn = [DeviceType.Phone::class])
+ class PhoneDependency @Inject constructor()
+
+ class CommonClass @Inject constructor(
+ phoneFactory: Optional,
+ )
+
+ interface CommonComponent {
+ fun getCommonClass(): CommonClass
+ }
+
+ @Component(variant = [DeviceType.Phone::class])
+ interface PhoneComponent: CommonComponent
+
+ @Component(variant = [DeviceType.Tablet::class])
+ interface TabletComponent: CommonComponent
+
+ fun test() {
+ val phoneComponent = Yatagan.create(PhoneComponent::class.java)
+ val tabletComponent = Yatagan.create(TabletComponent::class.java)
+
+ val phoneCommon = phoneComponent.getCommonClass()
+ val tabletCommon = tabletComponent.getCommonClass()
+ }
+ """.trimIndent())
+
+ compileRunAndValidate()
+ }
}
\ No newline at end of file
diff --git a/testing/tests/src/test/resources/golden/ConditionsTest/issue-209-assisted-factory-generated-for-unsupported-variants.golden-code.txt b/testing/tests/src/test/resources/golden/ConditionsTest/issue-209-assisted-factory-generated-for-unsupported-variants.golden-code.txt
new file mode 100644
index 00000000..03c53374
--- /dev/null
+++ b/testing/tests/src/test/resources/golden/ConditionsTest/issue-209-assisted-factory-generated-for-unsupported-variants.golden-code.txt
@@ -0,0 +1,101 @@
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Name: test/YataganTabletComponent.java
+package test;
+
+import com.yandex.yatagan.AutoBuilder;
+import com.yandex.yatagan.Optional;
+import com.yandex.yatagan.internal.Checks;
+import com.yandex.yatagan.internal.YataganGenerated;
+import java.lang.Class;
+import java.lang.Override;
+import java.lang.SuppressWarnings;
+import java.util.Collections;
+import javax.annotation.processing.Generated;
+
+@SuppressWarnings({"unchecked", "rawtypes", "NullableProblems", "deprecation"})
+@YataganGenerated
+@Generated("com.yandex.yatagan.codegen.impl.ComponentGenerator")
+public final class YataganTabletComponent implements TabletComponent {
+ private YataganTabletComponent() {
+ }
+
+ @Override
+ public CommonClass getCommonClass() {
+ return new CommonClass(Optional.empty());
+ }
+
+ public static AutoBuilder autoBuilder() {
+ return new AutoBuilderImpl();
+ }
+
+ private static final class AutoBuilderImpl implements AutoBuilder {
+ @Override
+ public final AutoBuilder provideInput(I input,
+ Class inputClass) {
+ Checks.reportUnexpectedAutoBuilderInput(input.getClass(), Collections.emptyList());
+ return this;
+ }
+
+ @Override
+ public final YataganTabletComponent create() {
+ return new YataganTabletComponent();
+ }
+ }
+}
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Name: test/YataganPhoneComponent.java
+package test;
+
+import com.yandex.yatagan.AutoBuilder;
+import com.yandex.yatagan.Optional;
+import com.yandex.yatagan.internal.Checks;
+import com.yandex.yatagan.internal.YataganGenerated;
+import java.lang.Class;
+import java.lang.Override;
+import java.lang.SuppressWarnings;
+import java.util.Collections;
+import javax.annotation.processing.Generated;
+
+@SuppressWarnings({"unchecked", "rawtypes", "NullableProblems", "deprecation"})
+@YataganGenerated
+@Generated("com.yandex.yatagan.codegen.impl.ComponentGenerator")
+public final class YataganPhoneComponent implements PhoneComponent {
+ private YataganPhoneComponent() {
+ }
+
+ @Override
+ public CommonClass getCommonClass() {
+ return new CommonClass(this.optOfPhoneAssistedFactory());
+ }
+
+ Optional optOfPhoneAssistedFactory() {
+ return Optional.of(this.new PhoneAssistedFactoryImpl());
+ }
+
+ public static AutoBuilder autoBuilder() {
+ return new AutoBuilderImpl();
+ }
+
+ private final class PhoneAssistedFactoryImpl implements PhoneAssistedFactory {
+ @Override
+ public PhoneAssistedClass create(int i) {
+ return new PhoneAssistedClass(new PhoneDependency(), i);
+ }
+ }
+
+ private static final class AutoBuilderImpl implements AutoBuilder {
+ @Override
+ public final AutoBuilder provideInput(I input, Class inputClass) {
+ Checks.reportUnexpectedAutoBuilderInput(input.getClass(), Collections.emptyList());
+ return this;
+ }
+
+ @Override
+ public final YataganPhoneComponent create() {
+ return new YataganPhoneComponent();
+ }
+ }
+}
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~