From abab89020b3b5c3473a33bbc7b7864e59736f6f5 Mon Sep 17 00:00:00 2001 From: manu Date: Wed, 21 Feb 2024 19:35:39 +0100 Subject: [PATCH 1/6] Replaced inject parameters with context parameters --- README.md | 12 +- build.gradle.kts | 4 +- buildSrc/src/main/kotlin/dependencies.kt | 4 - .../kotlin/com/ivianuu/injekt/common/Scope.kt | 2 +- .../com/ivianuu/injekt/common/TypeKey.kt | 2 +- compiler/build.gradle.kts | 20 ---- .../com/ivianuu/injekt/compiler/Infos.kt | 34 ++++-- .../compiler/InjektComponentRegistrar.kt | 8 -- .../ivianuu/injekt/compiler/InjektFqNames.kt | 2 +- .../com/ivianuu/injekt/compiler/InjektUtil.kt | 2 - .../injekt/compiler/PersistedTypeRef.kt | 9 +- .../compiler/analysis/InjectCallChecker.kt | 6 +- .../analysis/InjectFunctionDescriptor.kt | 107 ------------------ .../InjectSyntheticScopesProviderExtension.kt | 98 ---------------- .../analysis/InjektDeclarationChecker.kt | 26 ----- ...ektStorageComponentContainerContributor.kt | 25 +--- .../injekt/compiler/resolution/CallableRef.kt | 6 +- .../compiler/resolution/CollectInjectables.kt | 46 +++----- .../injekt/compiler/resolution/Injectable.kt | 5 +- .../injekt/compiler/resolution/TypeRef.kt | 6 - core/build.gradle.kts | 6 + .../kotlin/com/ivianuu/injekt/Api.kt | 18 +-- ide/.gitignore | 2 - ide/build.gradle.kts | 39 ------- .../injekt/ide/InjektProjectInitializer.kt | 28 ----- ide/src/main/resources/META-INF/plugin.xml | 25 ---- integration-tests/build.gradle.kts | 1 - .../InjectableDeclarationCheckTest.kt | 23 ---- .../InjectableDeclarationTest.kt | 98 +--------------- .../injekt/integrationtests/ResolutionTest.kt | 20 +--- .../injekt/integrationtests/ResolveTest.kt | 49 +++----- .../injekt/integrationtests/TagTest.kt | 2 +- .../injekt/integrationtests/TypeKeyTest.kt | 2 +- settings.gradle.kts | 1 - 34 files changed, 101 insertions(+), 637 deletions(-) delete mode 100644 compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectFunctionDescriptor.kt delete mode 100644 compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectSyntheticScopesProviderExtension.kt delete mode 100644 ide/.gitignore delete mode 100644 ide/build.gradle.kts delete mode 100644 ide/src/main/kotlin/com/ivianuu/injekt/ide/InjektProjectInitializer.kt delete mode 100644 ide/src/main/resources/META-INF/plugin.xml diff --git a/README.md b/README.md index 224a96687a..5e5175d805 100644 --- a/README.md +++ b/README.md @@ -109,13 +109,13 @@ or to break circular dependencies. You can do this by injecting a function. ```kotlin // inject a function to create multiple Tokens -fun run(@Inject tokenFactory: () -> Token) { +fun run(tokenFactory: () -> Token = inject) { val tokenA = tokenFactory() val tokenB = tokenFactory() } // inject a function to create a MyViewModel with the additional String parameter -@Composable fun MyScreen(@Inject viewModelFactory: (String) -> MyViewModel) { +@Composable fun MyScreen(viewModelFactory: (String) -> MyViewModel = inject) { val viewModel = remember { viewModelFactory("user_id") } } @@ -139,7 +139,7 @@ Value classes: @JvmInline value class PlaylistId(val value: String) @JvmInline value class TrackId(val value: String) -fun loadPlaylistTracks(@Inject playlistId: PlaylistId, @Inject trackId: TrackId): List = ... +fun loadPlaylistTracks(playlistId: PlaylistId = inject, trackId: TrackId = inject): List = ... ``` Tags: @@ -147,7 +147,7 @@ Tags: @Tag annotation class PlaylistId @Tag annotation class TrackId -fun loadPlaylistTracks(@Inject playlistId: @PlaylistId String, @Inject trackId: @TrackId String): List = ... +fun loadPlaylistTracks(playlistId: @PlaylistId String = inject, trackId: @TrackId String = inject): List = ... ``` Optionally you can add a typealias for your tag to make it easier to use @@ -157,7 +157,7 @@ typealias PlaylistId = @PlaylistIdTag String @Tag annotation class TrackIdTag typealias TrackId = @TrackIdTag String -fun loadPlaylistTracks(@Inject playlistId: PlaylistId, @Inject trackId: TrackId): List = ... +fun loadPlaylistTracks(playlistId: PlaylistId = inject, trackId: TrackId = inject): List = ... ``` # Type keys @@ -188,7 +188,5 @@ dependencies { } ``` -# Ide plugin is required to remove errors in the IDE (code should still compile) - # More complex uses can be found in my essentials project(base project for my apps) # https://github.com/IVIanuu/essentials \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 3b1d83135b..62a014cd5f 100755 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,8 +2,7 @@ * Copyright 2022 Manuel Wrage. Use of this source code is governed by the Apache 2.0 license. */ -import com.vanniktech.maven.publish.MavenPublishBaseExtension -import com.vanniktech.maven.publish.SonatypeHost +import com.vanniktech.maven.publish.* buildscript { repositories { @@ -23,7 +22,6 @@ buildscript { classpath(Deps.KotlinSerialization.gradlePlugin) classpath(Deps.Ksp.gradlePlugin) classpath(Deps.mavenPublishGradlePlugin) - classpath(Deps.shadowGradlePlugin) } } diff --git a/buildSrc/src/main/kotlin/dependencies.kt b/buildSrc/src/main/kotlin/dependencies.kt index 8c9768f0e6..9be0df6c3d 100755 --- a/buildSrc/src/main/kotlin/dependencies.kt +++ b/buildSrc/src/main/kotlin/dependencies.kt @@ -99,8 +99,4 @@ object Deps { const val mavenPublishGradlePlugin = "com.vanniktech:gradle-maven-publish-plugin:0.24.0" const val mockk = "io.mockk:mockk:1.11.0" - - const val roboelectric = "org.robolectric:robolectric:4.10.3" - - const val shadowGradlePlugin = "gradle.plugin.com.github.johnrengelman:shadow:7.1.2" } diff --git a/common/src/commonMain/kotlin/com/ivianuu/injekt/common/Scope.kt b/common/src/commonMain/kotlin/com/ivianuu/injekt/common/Scope.kt index 65bf4a5774..b92ec11b61 100644 --- a/common/src/commonMain/kotlin/com/ivianuu/injekt/common/Scope.kt +++ b/common/src/commonMain/kotlin/com/ivianuu/injekt/common/Scope.kt @@ -15,7 +15,7 @@ class Scope : SynchronizedObject() { (if (value !== NULL) value else null) as T } - inline operator fun invoke(@Inject key: TypeKey, init: () -> T): T = + inline operator fun invoke(key: TypeKey = inject, init: () -> T): T = invoke(key.value, init) companion object { diff --git a/common/src/commonMain/kotlin/com/ivianuu/injekt/common/TypeKey.kt b/common/src/commonMain/kotlin/com/ivianuu/injekt/common/TypeKey.kt index dcef19a73d..7410336ca9 100644 --- a/common/src/commonMain/kotlin/com/ivianuu/injekt/common/TypeKey.kt +++ b/common/src/commonMain/kotlin/com/ivianuu/injekt/common/TypeKey.kt @@ -14,4 +14,4 @@ import com.ivianuu.injekt.* /** * Returns the [TypeKey] of [T] */ -inline fun typeKeyOf(@Inject x: TypeKey): TypeKey = x +inline fun typeKeyOf(x: TypeKey = inject): TypeKey = x diff --git a/compiler/build.gradle.kts b/compiler/build.gradle.kts index e79e038fbd..357f3ec4bd 100755 --- a/compiler/build.gradle.kts +++ b/compiler/build.gradle.kts @@ -2,32 +2,12 @@ * Copyright 2022 Manuel Wrage. Use of this source code is governed by the Apache 2.0 license. */ -import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar - plugins { kotlin("jvm") kotlin("plugin.serialization") - id("com.github.johnrengelman.shadow") id("com.google.devtools.ksp") } -val shadowJar = tasks.getByName("shadowJar") { - relocate("org.jetbrains.kotlin.com.intellij", "com.intellij") - dependencies { - exclude(dependency("org.jetbrains.kotlin:kotlin-stdlib")) - exclude(dependency("org.jetbrains.kotlin:kotlin-stdlib-common")) - exclude(dependency("org.jetbrains:annotations")) - - exclude(dependency("com.intellij:openapi")) - exclude(dependency("com.intellij:extensions")) - exclude(dependency("com.intellij:annotations")) - } -} - -artifacts { - archives(shadowJar) -} - dependencies { implementation(Deps.AutoService.annotations) ksp(Deps.AutoService.processor) diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/Infos.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/Infos.kt index 4f2daf1261..2eb4b1ba4e 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/Infos.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/Infos.kt @@ -6,14 +6,15 @@ package com.ivianuu.injekt.compiler -import com.ivianuu.injekt.compiler.analysis.* import com.ivianuu.injekt.compiler.resolution.* import kotlinx.serialization.* import kotlinx.serialization.json.* import org.jetbrains.kotlin.backend.common.descriptors.* import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.* +import org.jetbrains.kotlin.js.resolve.diagnostics.* import org.jetbrains.kotlin.name.* +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.constants.* import org.jetbrains.kotlin.resolve.descriptorUtil.* @@ -26,7 +27,11 @@ import org.jetbrains.kotlin.utils.addToStdlib.* * Stores information about a callable which is NOT stored by the kotlin compiler * but is critical to injekt */ -data class CallableInfo(val type: TypeRef, val parameterTypes: Map) +data class CallableInfo( + val type: TypeRef, + val parameterTypes: Map, + val injectParameters: Set +) fun CallableDescriptor.callableInfo(ctx: Context): CallableInfo = if (this is PropertyAccessorDescriptor) correspondingProperty.callableInfo(ctx) @@ -88,7 +93,14 @@ fun CallableDescriptor.callableInfo(ctx: Context): CallableInfo = this[parameter.injektIndex()] = parameter.type.toTypeRef(ctx) } - val info = CallableInfo(type, parameterTypes) + val injectParameters = valueParameters + .filter { + it.findPsi().safeAs()?.defaultValue?.text == + InjektFqNames.inject.shortName().asString() + } + .mapTo(mutableSetOf()) { it.index } + + val info = CallableInfo(type, parameterTypes, injectParameters) // important to cache the info before persisting it ctx.trace!!.record(sliceOf("callable_info"), this, info) @@ -105,10 +117,10 @@ private fun CallableDescriptor.persistInfoIfNeeded(info: CallableInfo, ctx: Cont safeAs()?.visibility?.shouldPersistInfo() != true) return - if (hasAnnotation(InjektFqNames.DeclarationInfo)) - return + if (hasAnnotation(InjektFqNames.DeclarationInfo)) return - val shouldPersistInfo = info.type.shouldBePersisted() || + val shouldPersistInfo = info.injectParameters.isNotEmpty() || + info.type.shouldBePersisted() || info.parameterTypes.any { (_, parameterType) -> parameterType.shouldBePersisted() } if (!shouldPersistInfo) return @@ -128,19 +140,22 @@ private fun CallableDescriptor.persistInfoIfNeeded(info: CallableInfo, ctx: Cont @Serializable data class PersistedCallableInfo( val type: PersistedTypeRef, - val parameterTypes: Map + val parameterTypes: Map, + val injectParameters: Set ) fun CallableInfo.toPersistedCallableInfo(ctx: Context) = PersistedCallableInfo( type = type.toPersistedTypeRef(ctx), parameterTypes = parameterTypes - .mapValues { it.value.toPersistedTypeRef(ctx) } + .mapValues { it.value.toPersistedTypeRef(ctx) }, + injectParameters = injectParameters ) fun PersistedCallableInfo.toCallableInfo(ctx: Context) = CallableInfo( type = type.toTypeRef(ctx), parameterTypes = parameterTypes - .mapValues { it.value.toTypeRef(ctx) } + .mapValues { it.value.toTypeRef(ctx) }, + injectParameters = injectParameters ) /** @@ -319,7 +334,6 @@ private fun Annotated.updateAnnotation(annotation: AnnotationDescriptor) { LazyClassDescriptor::class, "annotations" ) { newAnnotations } - is InjectFunctionDescriptor -> underlyingDescriptor.updateAnnotation(annotation) is FunctionImportedFromObject -> callableFromObject.updateAnnotation(annotation) else -> throw AssertionError("Cannot add annotation to $this $javaClass") } diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektComponentRegistrar.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektComponentRegistrar.kt index 5ba5f2d493..566853845e 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektComponentRegistrar.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektComponentRegistrar.kt @@ -42,14 +42,6 @@ class InjektComponentRegistrar : ComponentRegistrar { InjectCallChecker() ) - // extension point does not exist CLI for some reason - // but it's still queried later - SyntheticScopeProviderExtension.registerExtensionPoint(project) - SyntheticScopeProviderExtension.registerExtension( - project, - InjectSyntheticScopeProviderExtension() - ) - @Suppress("DEPRECATION") Extensions.getRootArea().getExtensionPoint(DiagnosticSuppressor.EP_NAME) .registerExtension(InjektDiagnosticSuppressor(), project) diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektFqNames.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektFqNames.kt index 009ffa6ee8..7fb2cd3eb5 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektFqNames.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektFqNames.kt @@ -9,8 +9,8 @@ import org.jetbrains.kotlin.name.* object InjektFqNames { val InjektPackage = FqName("com.ivianuu.injekt") - val Inject = InjektPackage.child("Inject".asNameId()) val Provide = InjektPackage.child("Provide".asNameId()) + val inject = InjektPackage.child("inject".asNameId()) val Tag = InjektPackage.child("Tag".asNameId()) val Spread = InjektPackage.child("Spread".asNameId()) diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektUtil.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektUtil.kt index 98a7980df0..b609c33671 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektUtil.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektUtil.kt @@ -6,7 +6,6 @@ package com.ivianuu.injekt.compiler -import com.ivianuu.injekt.compiler.analysis.* import org.jetbrains.kotlin.builtins.functions.* import org.jetbrains.kotlin.com.intellij.openapi.project.* import org.jetbrains.kotlin.descriptors.* @@ -47,7 +46,6 @@ fun DeclarationDescriptor.isExternalDeclaration(ctx: Context): Boolean = fun DeclarationDescriptor.isDeserializedDeclaration(): Boolean = this is DeserializedDescriptor || (this is PropertyAccessorDescriptor && correspondingProperty.isDeserializedDeclaration()) || - (this is InjectFunctionDescriptor && underlyingDescriptor.isDeserializedDeclaration()) || this is DeserializedTypeParameterDescriptor || this is JavaClassDescriptor || this is FunctionClassDescriptor diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/PersistedTypeRef.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/PersistedTypeRef.kt index 3833102d78..f8a725f113 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/PersistedTypeRef.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/PersistedTypeRef.kt @@ -14,8 +14,7 @@ import org.jetbrains.kotlin.types.model.* val isStarProjection: Boolean, val variance: TypeVariance, val isMarkedNullable: Boolean, - val isProvide: Boolean, - val isInject: Boolean + val isProvide: Boolean ) fun TypeRef.toPersistedTypeRef(ctx: Context): PersistedTypeRef = @@ -25,8 +24,7 @@ fun TypeRef.toPersistedTypeRef(ctx: Context): PersistedTypeRef = isStarProjection = isStarProjection, variance = variance, isMarkedNullable = isMarkedNullable, - isProvide = isProvide, - isInject = isInject + isProvide = isProvide ) fun PersistedTypeRef.toTypeRef(ctx: Context): TypeRef { @@ -46,7 +44,6 @@ fun PersistedTypeRef.toTypeRef(ctx: Context): TypeRef { arguments = arguments, variance = variance, isMarkedNullable = isMarkedNullable, - isProvide = isProvide, - isInject = isInject + isProvide = isProvide ) } diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectCallChecker.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectCallChecker.kt index d013992da3..e8ddb43ca8 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectCallChecker.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectCallChecker.kt @@ -55,7 +55,9 @@ import org.jetbrains.kotlin.utils.* private fun checkCall(resolvedCall: ResolvedCall<*>, ctx: Context) { val resultingDescriptor = resolvedCall.resultingDescriptor - if (resultingDescriptor !is InjectFunctionDescriptor) return + + val info = resultingDescriptor.callableInfo(ctx) + if (info.injectParameters.isEmpty()) return val callExpression = resolvedCall.call.callElement @@ -87,7 +89,7 @@ import org.jetbrains.kotlin.utils.* val requests = callee.callable.allParameters .transform { val index = it.injektIndex() - if (valueArgumentsByIndex[index] is DefaultValueArgument && it.isInject(ctx)) + if (valueArgumentsByIndex[index] is DefaultValueArgument && index in info.injectParameters) add(it.toInjectableRequest(callee, ctx)) } diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectFunctionDescriptor.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectFunctionDescriptor.kt deleted file mode 100644 index 3ee649d7cc..0000000000 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectFunctionDescriptor.kt +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2022 Manuel Wrage. Use of this source code is governed by the Apache 2.0 license. - */ - -package com.ivianuu.injekt.compiler.analysis - -import com.ivianuu.injekt.compiler.* -import com.ivianuu.injekt.compiler.resolution.* -import org.jetbrains.kotlin.backend.common.descriptors.* -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.load.java.descriptors.* -import org.jetbrains.kotlin.resolve.calls.components.* -import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.utils.addToStdlib.* - -interface InjectFunctionDescriptor : FunctionDescriptor { - val underlyingDescriptor: FunctionDescriptor -} - -class InjectValueParameterDescriptor( - private val parent: InjectFunctionDescriptor, - val underlyingDescriptor: ValueParameterDescriptor, - val ctx: Context -) : ValueParameterDescriptor by underlyingDescriptor { - private val declaresDefaultValue = - underlyingDescriptor.isInject(ctx) || underlyingDescriptor.declaresDefaultValue() - override fun declaresDefaultValue(): Boolean = declaresDefaultValue - - override fun getContainingDeclaration(): CallableDescriptor = parent -} - -val ValueParameterDescriptor.hasDefaultValueIgnoringInject: Boolean - get() = (this as? InjectValueParameterDescriptor)?.underlyingDescriptor?.hasDefaultValue() - ?: hasDefaultValue() - -abstract class AbstractInjectFunctionDescriptor( - final override val underlyingDescriptor: FunctionDescriptor, - private val ctx: Context -) : InjectFunctionDescriptor { - private val valueParams = underlyingDescriptor - .valueParameters - .mapTo(mutableListOf()) { valueParameter -> - InjectValueParameterDescriptor(this, valueParameter, ctx) - } - - @OptIn(UnsafeCastFunction::class) - override fun getValueParameters(): MutableList = - valueParams.cast() -} - -fun FunctionDescriptor.toInjectFunctionDescriptor(ctx: Context): InjectFunctionDescriptor? { - if (this is InjectFunctionDescriptor) return this - if (this is JavaMethodDescriptor) return null - if (allParameters.none { it.isInject(ctx) }) return null - return when (this) { - is ClassConstructorDescriptor -> InjectConstructorDescriptorImpl(this, ctx) - is SimpleFunctionDescriptor -> InjectSimpleFunctionDescriptorImpl(this, ctx) - else -> InjectFunctionDescriptorImpl(this, ctx) - } -} - -class InjectConstructorDescriptorImpl( - underlyingDescriptor: ClassConstructorDescriptor, - private val ctx: Context -) : AbstractInjectFunctionDescriptor(underlyingDescriptor, ctx), - ClassConstructorDescriptor by underlyingDescriptor { - override fun substitute(substitutor: TypeSubstitutor): ClassConstructorDescriptor = - InjectConstructorDescriptorImpl( - underlyingDescriptor - .substitute(substitutor) as ClassConstructorDescriptor, - ctx - ) - - override fun getValueParameters(): MutableList = - super.getValueParameters() -} - -class InjectFunctionDescriptorImpl( - underlyingDescriptor: FunctionDescriptor, - private val ctx: Context -) : AbstractInjectFunctionDescriptor(underlyingDescriptor, ctx), - FunctionDescriptor by underlyingDescriptor { - override fun substitute(substitutor: TypeSubstitutor): FunctionDescriptor = - InjectFunctionDescriptorImpl( - underlyingDescriptor.substitute(substitutor) as FunctionDescriptor, - ctx - ) - - override fun getValueParameters(): MutableList = - super.getValueParameters() -} - -class InjectSimpleFunctionDescriptorImpl( - underlyingDescriptor: SimpleFunctionDescriptor, - private val ctx: Context -) : AbstractInjectFunctionDescriptor(underlyingDescriptor, ctx), - SimpleFunctionDescriptor by underlyingDescriptor { - override fun substitute(substitutor: TypeSubstitutor): FunctionDescriptor = - InjectSimpleFunctionDescriptorImpl( - underlyingDescriptor - .substitute(substitutor) as SimpleFunctionDescriptor, - ctx - ) - - override fun getValueParameters(): MutableList = - super.getValueParameters() -} diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectSyntheticScopesProviderExtension.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectSyntheticScopesProviderExtension.kt deleted file mode 100644 index cc56610afd..0000000000 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectSyntheticScopesProviderExtension.kt +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright 2022 Manuel Wrage. Use of this source code is governed by the Apache 2.0 license. - */ - -@file:OptIn(UnsafeCastFunction::class) - -package com.ivianuu.injekt.compiler.analysis - -import com.ivianuu.injekt.compiler.* -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.incremental.components.* -import org.jetbrains.kotlin.name.* -import org.jetbrains.kotlin.resolve.* -import org.jetbrains.kotlin.resolve.sam.* -import org.jetbrains.kotlin.resolve.scopes.* -import org.jetbrains.kotlin.resolve.scopes.synthetic.* -import org.jetbrains.kotlin.storage.* -import org.jetbrains.kotlin.synthetic.* -import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.utils.addToStdlib.* - -class InjectSyntheticScopeProviderExtension : SyntheticScopeProviderExtension { - override fun getScopes( - moduleDescriptor: ModuleDescriptor, - javaSyntheticPropertiesScope: JavaSyntheticPropertiesScope - ): List { - val ctx = Context( - moduleDescriptor, - DelegatingBindingTrace(BindingContext.EMPTY, "synthetic scopes") - ) - return listOf(InjectSyntheticScope(ctx)) - } -} - -class InjectSyntheticScopes( - storageManager: StorageManager, - lookupTracker: LookupTracker, - samResolver: SamConversionResolver, - samConversionOracle: SamConversionOracle, - ctx: Context -) : SyntheticScopes { - private val delegate = FunInterfaceConstructorsScopeProvider( - storageManager, lookupTracker, samResolver, samConversionOracle) - override val scopes = delegate.scopes + InjectSyntheticScope( - ctx.withTrace( - DelegatingBindingTrace(BindingContext.EMPTY, "synthetic scopes") - ) - ) -} - -private class InjectSyntheticScope(private val ctx: Context) : SyntheticScope.Default() { - override fun getSyntheticConstructor(constructor: ConstructorDescriptor): ConstructorDescriptor? = - constructor.toInjectFunctionDescriptor(ctx) as? ConstructorDescriptor - - override fun getSyntheticConstructors( - contributedClassifier: ClassifierDescriptor, - location: LookupLocation - ): Collection = contributedClassifier.safeAs() - ?.constructors - ?.mapNotNull { it.toInjectFunctionDescriptor(ctx) } ?: emptyList() - - override fun getSyntheticMemberFunctions(receiverTypes: Collection): Collection = - receiverTypes - .transform { receiverType -> - for (declaration in receiverType.memberScope.getContributedDescriptors()) { - if (declaration is ClassDescriptor && declaration.isInner) { - for (constructor in declaration.constructors) - constructor.toInjectFunctionDescriptor(ctx) - ?.let { add(it) } - } else - declaration.safeAs()?.toInjectFunctionDescriptor(ctx) - ?.let { add(it) } - } - } - - override fun getSyntheticMemberFunctions( - receiverTypes: Collection, - name: Name, - location: LookupLocation - ): Collection = receiverTypes - .transform { receiverType -> - for (function in receiverType.memberScope.getContributedFunctions(name, location)) - function.toInjectFunctionDescriptor(ctx)?.let { add(it) } - receiverType.memberScope.getContributedClassifier(name, location) - ?.safeAs() - ?.takeIf { it.isInner } - ?.constructors - ?.forEach { constructor -> - constructor.toInjectFunctionDescriptor(ctx)?.let { add(it) } - } - } - - override fun getSyntheticStaticFunctions( - contributedFunctions: Collection, - location: LookupLocation - ): Collection = contributedFunctions - .mapNotNull { it.toInjectFunctionDescriptor(ctx) } -} diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektDeclarationChecker.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektDeclarationChecker.kt index 44eaa0723a..f469d16f65 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektDeclarationChecker.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektDeclarationChecker.kt @@ -46,7 +46,6 @@ class InjektDeclarationChecker(private val baseCtx: Context) : DeclarationChecke checkSpreadingInjectable(declaration, descriptor.typeParameters, ctx) checkOverrides(declaration, descriptor, ctx) checkExceptActual(declaration, descriptor, ctx) - checkReceiver(descriptor, declaration, ctx) } private fun checkClass( @@ -131,7 +130,6 @@ class InjektDeclarationChecker(private val baseCtx: Context) : DeclarationChecke descriptor: PropertyDescriptor, ctx: Context ) { - checkReceiver(descriptor, declaration, ctx) checkOverrides(declaration, descriptor, ctx) checkExceptActual(declaration, descriptor, ctx) } @@ -148,21 +146,6 @@ class InjektDeclarationChecker(private val baseCtx: Context) : DeclarationChecke ctx.reportError(declaration, "injectable variable must be initialized, delegated or marked with lateinit") } - private fun checkReceiver( - descriptor: CallableDescriptor, - declaration: KtDeclaration, - ctx: Context - ) { - if (descriptor.extensionReceiverParameter?.hasAnnotation(InjektFqNames.Inject) == true || - descriptor.extensionReceiverParameter?.type?.hasAnnotation(InjektFqNames.Inject) == true) - ctx.reportError( - declaration.safeAs()?.receiverTypeReference - ?: declaration.safeAs()?.receiverTypeReference - ?: declaration, - "receiver cannot be injected" - ) - } - private fun checkSpreadingInjectable( declaration: KtDeclaration, typeParameters: List, @@ -225,15 +208,6 @@ class InjektDeclarationChecker(private val baseCtx: Context) : DeclarationChecke !descriptor.hasAnnotation(InjektFqNames.Provide)) return false - if (descriptor is CallableMemberDescriptor) - for ((index, overriddenValueParameter) in - overriddenDescriptor.cast().valueParameters.withIndex()) { - val valueParameter = descriptor.valueParameters[index] - if (overriddenValueParameter.hasAnnotation(InjektFqNames.Inject) != - valueParameter.hasAnnotation(InjektFqNames.Inject)) - return false - } - val (typeParameters, overriddenTypeParameters) = when (descriptor) { is CallableMemberDescriptor -> descriptor.typeParameters to overriddenDescriptor.cast() diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektStorageComponentContainerContributor.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektStorageComponentContainerContributor.kt index a4aeff2597..ccb7ccaf87 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektStorageComponentContainerContributor.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektStorageComponentContainerContributor.kt @@ -9,7 +9,6 @@ import org.jetbrains.kotlin.container.* import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.extensions.* import org.jetbrains.kotlin.platform.* -import org.jetbrains.kotlin.synthetic.* class InjektStorageComponentContainerContributor : StorageComponentContainerContributor { override fun registerModuleComponents( @@ -18,29 +17,7 @@ class InjektStorageComponentContainerContributor : StorageComponentContainerCont moduleDescriptor: ModuleDescriptor, ) { val ctx = Context(moduleDescriptor, null) - - val hasSyntheticScopesExtension = container.readPrivateFinalField( - StorageComponentContainer::class, - "componentStorage" - ) - .readPrivateFinalField>( - ComponentStorage::class, - "descriptors" - ) - .let { descriptors -> - descriptors.any { - it is SingletonTypeComponentDescriptor && - it.klass == JavaSyntheticScopes::class.java - } - } - - if (!hasSyntheticScopesExtension) { - container.useInstance(ctx) - container.useImpl() - } - container.useInstance(InjektDeclarationChecker(ctx)) - if (!isIde) - container.useInstance(InfoPatcher(ctx)) + if (!isIde) container.useInstance(InfoPatcher(ctx)) } } diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/CallableRef.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/CallableRef.kt index a47db04ace..ac0e5cb05b 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/CallableRef.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/CallableRef.kt @@ -19,7 +19,8 @@ data class CallableRef( val typeParameters: List, val parameterTypes: Map, val typeArguments: Map, - val callableFqName: FqName + val callableFqName: FqName, + val injectParameters: Set ) fun CallableRef.substitute(map: Map): CallableRef { @@ -65,6 +66,7 @@ fun CallableDescriptor.toCallableRef(ctx: Context): CallableRef = safeAs()?.let { it.lambdaInjectable.callableFqName.child(it.name) } ?: safeAs()?.fqNameSafe?.parent() ?: - fqNameSafe + fqNameSafe, + injectParameters = info.injectParameters ) } diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/CollectInjectables.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/CollectInjectables.kt index 206a866cbc..9a30d19e46 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/CollectInjectables.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/CollectInjectables.kt @@ -18,7 +18,6 @@ import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.descriptorUtil.* import org.jetbrains.kotlin.resolve.scopes.* import org.jetbrains.kotlin.resolve.scopes.receivers.* -import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.utils.addToStdlib.* import java.util.* @@ -96,33 +95,24 @@ fun ResolutionScope.collectMemberInjectables( } fun Annotated.isProvide(ctx: Context): Boolean = - hasAnnotationForInjection(InjektFqNames.Provide, ctx) || isInject(ctx) - -fun Annotated.isInject(ctx: Context): Boolean = - hasAnnotationForInjection(InjektFqNames.Inject, ctx) - -private fun Annotated.hasAnnotationForInjection(fqName: FqName, ctx: Context): Boolean = - ctx.cached( - "annotation_for_injection_$fqName", - if (this is KotlinType) System.identityHashCode(this) else this - ) { - hasAnnotation(fqName) || - (this is ParameterDescriptor && type.hasAnnotation(fqName)) || - (this is ParameterDescriptor && - containingDeclaration.safeAs() - ?.findPsi() - ?.safeAs() - ?.getArgumentDescriptor(ctx) - ?.containingDeclaration - ?.returnType - ?.memberScope - ?.getContributedDescriptors() - ?.filterIsInstance() - ?.singleOrNull { it.modality == Modality.ABSTRACT } - ?.valueParameters - ?.singleOrNull { it.injektIndex() == injektIndex() } - ?.hasAnnotationForInjection(fqName, ctx) == true) - } + hasAnnotation(InjektFqNames.Provide) || + (this is ParameterDescriptor && type.hasAnnotation(InjektFqNames.Provide)) || + (this is ValueParameterDescriptor && + index in containingDeclaration.cast().callableInfo(ctx).injectParameters) || + (this is ParameterDescriptor && + containingDeclaration.safeAs() + ?.findPsi() + ?.safeAs() + ?.getArgumentDescriptor(ctx) + ?.containingDeclaration + ?.returnType + ?.memberScope + ?.getContributedDescriptors() + ?.filterIsInstance() + ?.singleOrNull { it.modality == Modality.ABSTRACT } + ?.valueParameters + ?.singleOrNull { it.injektIndex() == injektIndex() } + ?.isProvide(ctx) == true) fun ClassDescriptor.injectableConstructors(ctx: Context): List = ctx.cached("injectable_constructors", this) { diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/Injectable.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/Injectable.kt index 1b1cbff5f1..fc98e0928f 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/Injectable.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/Injectable.kt @@ -7,11 +7,11 @@ package com.ivianuu.injekt.compiler.resolution import com.ivianuu.injekt.compiler.* -import com.ivianuu.injekt.compiler.analysis.* import org.jetbrains.kotlin.backend.common.descriptors.* import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.incremental.components.* import org.jetbrains.kotlin.name.* +import org.jetbrains.kotlin.resolve.calls.components.* import org.jetbrains.kotlin.resolve.descriptorUtil.* import org.jetbrains.kotlin.utils.addToStdlib.* @@ -135,5 +135,6 @@ fun ParameterDescriptor.toInjectableRequest(callable: CallableRef, ctx: Context) callableTypeArguments = callable.typeArguments, parameterName = injektName(), parameterIndex = injektIndex(), - isRequired = this !is ValueParameterDescriptor || !hasDefaultValueIgnoringInject + isRequired = this !is ValueParameterDescriptor || + injektIndex() in callable.injectParameters || !hasDefaultValue() ) diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/TypeRef.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/TypeRef.kt index ca73eb77ae..14f3a8031e 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/TypeRef.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/TypeRef.kt @@ -129,7 +129,6 @@ fun KotlinType.toTypeRef( else it }, isProvide = kotlinType.hasAnnotation(InjektFqNames.Provide), - isInject = kotlinType.hasAnnotation(InjektFqNames.Inject), isStarProjection = false, frameworkKey = "", variance = variance @@ -165,7 +164,6 @@ data class TypeRef( val isMarkedNullable: Boolean = false, val arguments: List = emptyList(), val isProvide: Boolean = false, - val isInject: Boolean = false, val isStarProjection: Boolean = false, val frameworkKey: String = "", val variance: TypeVariance = TypeVariance.INV, @@ -249,7 +247,6 @@ data class TypeRef( result = 31 * result + isMarkedNullable.hashCode() result = 31 * result + arguments.hashCode() result = 31 * result + isProvide.hashCode() - result = 31 * result + isInject.hashCode() result = 31 * result + isStarProjection.hashCode() result = 31 * result + frameworkKey.hashCode() result = 31 * result + variance.hashCode() @@ -309,18 +306,15 @@ fun TypeRef.substitute(map: Map): TypeRef { val newNullability = if (isStarProjection) substitution.isMarkedNullable else isMarkedNullable || substitution.isMarkedNullable val newIsProvide = isProvide || substitution.isProvide - val newIsInject = isInject || substitution.isInject val newVariance = if (substitution.variance != TypeVariance.INV) substitution.variance else variance return if (newNullability != substitution.isMarkedNullable || newIsProvide != substitution.isProvide || - newIsInject != substitution.isInject || newVariance != substitution.variance ) { substitution.copy( isMarkedNullable = newNullability, isProvide = newIsProvide, - isInject = newIsInject, variance = newVariance ) } else substitution diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 55963c2065..eb3a6a02b6 100755 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.tasks.* + /* * Copyright 2022 Manuel Wrage. Use of this source code is governed by the Apache 2.0 license. */ @@ -44,4 +46,8 @@ kotlin { } } +tasks.withType { + kotlinOptions.jvmTarget = "1.8" +} + plugins.apply("com.vanniktech.maven.publish") diff --git a/core/src/commonMain/kotlin/com/ivianuu/injekt/Api.kt b/core/src/commonMain/kotlin/com/ivianuu/injekt/Api.kt index c7eb250f6a..b827c155f4 100644 --- a/core/src/commonMain/kotlin/com/ivianuu/injekt/Api.kt +++ b/core/src/commonMain/kotlin/com/ivianuu/injekt/Api.kt @@ -34,23 +34,9 @@ package com.ivianuu.injekt ) annotation class Provide -/** - * Automatically injects a argument if no explicit argument was provided - */ -@Target( - // fun func(@Inject foo: Foo) - AnnotationTarget.VALUE_PARAMETER, - - // Lambda - // val func: (@Inject Foo) -> Bar = { bar() } - AnnotationTarget.TYPE -) -annotation class Inject +val inject: Nothing = throw IllegalStateException("injekt compiler intrinsic") -/** - * Returns a provided instance of [T] - */ -inline fun inject(@Inject x: T): T = x +inline fun inject(x: T = inject) = x /** * Marks an annotation as an tag which can then be used diff --git a/ide/.gitignore b/ide/.gitignore deleted file mode 100644 index 084117257d..0000000000 --- a/ide/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/build -/sandbox \ No newline at end of file diff --git a/ide/build.gradle.kts b/ide/build.gradle.kts deleted file mode 100644 index 4d8c6c374c..0000000000 --- a/ide/build.gradle.kts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2022 Manuel Wrage. Use of this source code is governed by the Apache 2.0 license. - */ - -plugins { - kotlin("jvm") - id("org.jetbrains.intellij") version "1.11.0" -} - -intellij { - pluginName.set("Injekt ide plugin") - updateSinceUntilBuild.set(false) - plugins.addAll("org.jetbrains.kotlin", "gradle", "gradle-java", "java") - localPath.set("/home/manu/android-studio") -} - -/*tasks.withType { - token(project.property("ideaToken") as String) -}*/ - -tasks { - buildSearchableOptions { - enabled = false - } - instrumentCode { - compilerVersion.set("201.7846.76") - } - runIde { - jbrVersion.set("11_0_3b360.2") - } - buildSearchableOptions { - jbrVersion.set("11_0_3b360.2") - } -} - -dependencies { - api(project(":compiler", "shadow")) - api(Deps.KotlinSerialization.json) -} diff --git a/ide/src/main/kotlin/com/ivianuu/injekt/ide/InjektProjectInitializer.kt b/ide/src/main/kotlin/com/ivianuu/injekt/ide/InjektProjectInitializer.kt deleted file mode 100644 index 9dd6cb00d8..0000000000 --- a/ide/src/main/kotlin/com/ivianuu/injekt/ide/InjektProjectInitializer.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2022 Manuel Wrage. Use of this source code is governed by the Apache 2.0 license. - */ - -package com.ivianuu.injekt.ide - -import com.intellij.openapi.extensions.* -import com.intellij.openapi.project.* -import com.ivianuu.injekt.compiler.analysis.* -import org.jetbrains.kotlin.extensions.* -import org.jetbrains.kotlin.resolve.diagnostics.* -import org.jetbrains.kotlin.synthetic.* - -class InjektProjectInitializer : ProjectManagerListener { - override fun projectOpened(project: Project) { - StorageComponentContainerContributor.registerExtension( - project, - InjektStorageComponentContainerContributor() - ) - SyntheticScopeProviderExtension.registerExtension( - project, - InjectSyntheticScopeProviderExtension() - ) - @Suppress("DEPRECATION") - Extensions.getRootArea().getExtensionPoint(DiagnosticSuppressor.EP_NAME) - .registerExtension(InjektDiagnosticSuppressor()) - } -} diff --git a/ide/src/main/resources/META-INF/plugin.xml b/ide/src/main/resources/META-INF/plugin.xml deleted file mode 100644 index c2cc1f285c..0000000000 --- a/ide/src/main/resources/META-INF/plugin.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - com.ivianuu.injekt - Injekt - - Injekt - - 2022.3.1 - - 0.0.1-dev506 - - - - com.intellij.gradle - com.intellij.java - org.jetbrains.kotlin - - - - - \ No newline at end of file diff --git a/integration-tests/build.gradle.kts b/integration-tests/build.gradle.kts index 1b0178d446..67a10cfbfd 100644 --- a/integration-tests/build.gradle.kts +++ b/integration-tests/build.gradle.kts @@ -39,7 +39,6 @@ kotlin { implementation(Deps.junit) implementation(Deps.AndroidX.Test.core) implementation(Deps.AndroidX.Test.junit) - implementation(Deps.roboelectric) implementation(Deps.junit) implementation(Deps.kotestAssertions) } diff --git a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/InjectableDeclarationCheckTest.kt b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/InjectableDeclarationCheckTest.kt index b31b0f5f2e..85c60275e0 100644 --- a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/InjectableDeclarationCheckTest.kt +++ b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/InjectableDeclarationCheckTest.kt @@ -75,14 +75,6 @@ class InjectableDeclarationCheckTest { """ ) - @Test fun testInjectReceiverOnFunction() = codegen( - """ - fun @receiver:Inject Foo.bar() = Bar(this) - """ - ) { - compilationShouldHaveFailed("receiver cannot be injected") - } - @Test fun testProvideLocalVariableWithoutInitializer() = codegen( """ fun invoke() { @@ -144,21 +136,6 @@ class InjectableDeclarationCheckTest { compilationShouldHaveFailed("'foo' overrides nothing") } - @Test fun testFunctionWithInjectParameterOverrideWithoutInjectAnnotation() = codegen( - """ - abstract class MySuperClass { - abstract fun bar(@Inject foo: Foo): Bar - } - """, - """ - class MySubClass : MySuperClass() { - override fun bar(foo: Foo) = Bar(foo) - } - """ - ) { - compilationShouldHaveFailed("'bar' overrides nothing") - } - @Test fun testNonSpreadTypeParameterOverrideWithSpreadOverridden() = singleAndMultiCodegen( """ abstract class MySuperClass { diff --git a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/InjectableDeclarationTest.kt b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/InjectableDeclarationTest.kt index b3859167ff..2aa69812c9 100644 --- a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/InjectableDeclarationTest.kt +++ b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/InjectableDeclarationTest.kt @@ -162,7 +162,7 @@ class InjectableDeclarationTest { @Test fun testInjectValueParameter() = codegen( """ - fun invoke(@Inject foo: Foo) = inject() + fun invoke(foo: Foo = inject) = inject() """ ) { val foo = Foo() @@ -171,7 +171,7 @@ class InjectableDeclarationTest { @Test fun testMultipleInjectValueParameter() = codegen( """ - fun invoke(@Inject foo: Foo, @Inject bar: Bar) = inject() to inject() + fun invoke(foo: Foo = inject, bar: Bar = inject) = inject() to inject() """ ) { val foo = Foo() @@ -205,38 +205,11 @@ class InjectableDeclarationTest { invokeSingleFile(foo) shouldBeSameInstanceAs foo } - @Test fun testInjectLambdaParameterDeclarationSite() = singleAndMultiCodegen( - """ - inline fun withProvidedInstance(value: T, block: (@Inject T) -> R) = block(value) - """, - """ - fun invoke(foo: Foo) = withProvidedInstance(foo) { inject() } - """ - ) { - val foo = Foo() - invokeSingleFile(foo) shouldBeSameInstanceAs foo - } - @Test fun testInjectFunInterfaceDeclarationSite() = singleAndMultiCodegen( """ fun interface Lambda { - operator fun invoke(@Inject x: T): R - } - - inline fun withProvidedInstance(value: T, block: Lambda) = block(value) - """, - """ - fun invoke(foo: Foo) = withProvidedInstance(foo, Lambda { inject() }) - """ - ) { - val foo = Foo() - invokeSingleFile(foo) shouldBeSameInstanceAs foo - } - - @Test fun testInjectFunInterfaceDeclarationSite2() = singleAndMultiCodegen( - """ - fun interface Lambda { - operator fun invoke(x: @Inject T): R + fun actualInvoke(@Provide x: T): R + operator fun invoke(x: T = inject) = actualInvoke(x) } inline fun withProvidedInstance(value: T, block: Lambda) = block(value) @@ -249,65 +222,6 @@ class InjectableDeclarationTest { invokeSingleFile(foo) shouldBeSameInstanceAs foo } - @Test fun testCanLeaveOutFunctionInjectParameters() = singleAndMultiCodegen( - """ - fun usesFoo(@Inject foo: Foo) { - } - """, - """ - @Provide val foo = Foo() - fun invoke() { - usesFoo() - } - """ - ) - - @Test fun testCanLeaveOutConstructorInjectParameters() = singleAndMultiCodegen( - """ - class FooHolder(@Inject foo: Foo) - """, - """ - @Provide val foo = Foo() - fun invoke() { - FooHolder() - } - """ - ) - - @Test fun testCanLeaveOutSuperConstructorInjectParameters() = singleAndMultiCodegen( - """ - abstract class AbstractFooHolder(@Inject foo: Foo) - """, - """ - @Provide val foo = Foo() - class FooHolderImpl : AbstractFooHolder() - """ - ) - - @Test fun testCanLeaveOutInjectLambdaParameters() = singleAndMultiCodegen( - """ - val lambda: (@Inject Foo) -> Foo = { inject() } - """, - """ - fun invoke(@Inject foo: Foo) = lambda() - """ - ) { - val foo = Foo() - invokeSingleFile(foo) shouldBeSameInstanceAs foo - } - - @Test fun testCanLeaveOutInjectExtensionLambdaParameters() = singleAndMultiCodegen( - """ - val lambda: Unit.(@Inject Foo) -> Foo = { inject() } - """, - """ - fun invoke(@Inject foo: Foo) = lambda(Unit) - """ - ) { - val foo = Foo() - invokeSingleFile(foo) shouldBeSameInstanceAs foo - } - @Test fun testProvideLambdaParameterUseSite() = singleAndMultiCodegen( """ inline fun withProvidedInstance(value: T, block: (T) -> R) = block(value) @@ -363,7 +277,7 @@ class InjectableDeclarationTest { """ class Outer(@Provide val _foo: Foo) { val foo = Inner().foo - inner class Inner(@Inject val foo: Foo) + inner class Inner(val foo: Foo = inject) } fun invoke(foo: Foo): Foo = Outer(foo).foo """ @@ -376,7 +290,7 @@ class InjectableDeclarationTest { """ class Outer(@Provide val _foo: Foo) { val foo = Inner().foo - class Inner(@Inject val foo: Foo) + class Inner(val foo: Foo = inject) } fun invoke(foo: Foo): Foo = Outer(foo).foo """ diff --git a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/ResolutionTest.kt b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/ResolutionTest.kt index 5605cca967..8cc4d1729a 100644 --- a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/ResolutionTest.kt +++ b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/ResolutionTest.kt @@ -271,7 +271,7 @@ class ResolutionTest { interface Ord @Provide object IntOrd : Ord @Provide object NumberOrd : Ord - fun useOrd(@Inject ord: Ord) = ord + fun useOrd(ord: Ord = inject) = ord """, """ fun invoke() = useOrd() @@ -286,7 +286,7 @@ class ResolutionTest { @Provide fun anyOrd(): Ord = object : Ord {} @Provide fun numberOrd(): Ord = object : Ord {} @Provide fun intOrd(): Ord = object : Ord {} - fun useOrd(@Inject ord: Ord) = ord + fun useOrd(ord: Ord = inject) = ord """, """ fun invoke() = useOrd() @@ -301,7 +301,7 @@ class ResolutionTest { @Provide fun anyOrd(): Ord = object : Ord {} @Provide fun numberOrd(): Ord = object : Ord {} @Provide fun intOrd(long: Long): Ord = object : Ord {} - fun useOrd(@Inject ord: Ord) = ord + fun useOrd(ord: Ord = inject) = ord """, """ fun invoke() = useOrd() @@ -333,25 +333,13 @@ class ResolutionTest { compilationShouldHaveFailed("no injectable") } - @Test fun testUsesDefaultValueOnNoCandidatesError() = codegen( - """ - fun invoke(_foo: Foo): Foo { - fun inner(@Inject foo: Foo = _foo) = foo - return inner() - } - """ - ) { - val foo = Foo() - invokeSingleFile(foo) shouldBeSameInstanceAs foo - } - @Test fun testDoesNotPreferValueArgumentOverAnother() = codegen( """ @Provide class FooModule { @Provide fun foo() = Foo() } - fun createFoo(@Inject foo1: Foo, @Inject foo2: Foo) = inject() + fun createFoo(foo1: Foo = inject, foo2: Foo = inject) = inject() """ ) { compilationShouldHaveFailed("ambiguous") diff --git a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/ResolveTest.kt b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/ResolveTest.kt index 4c7bff1f7a..e3ef9a921d 100644 --- a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/ResolveTest.kt +++ b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/ResolveTest.kt @@ -4,7 +4,6 @@ package com.ivianuu.injekt.integrationtests -import io.kotest.matchers.nulls.* import io.kotest.matchers.types.* import org.junit.* @@ -180,7 +179,7 @@ class ResolveTest { @Test fun testFunctionInvocationWithInjectables() = singleAndMultiCodegen( """ @Provide val foo = Foo() - fun usesFoo(@Inject foo: Foo) { + fun usesFoo(foo: Foo = inject) { } """, """ @@ -196,7 +195,7 @@ class ResolveTest { """ @Provide val foo = Foo() fun invoke() { - fun usesFoo(@Inject foo: Foo) { + fun usesFoo(foo: Foo = inject) { } usesFoo() } @@ -208,7 +207,7 @@ class ResolveTest { @Test fun testConstructorInvocationWithInjectables() = singleAndMultiCodegen( """ @Provide val foo = Foo() - class UsesFoo(@Inject foo: Foo) + class UsesFoo(foo: Foo = inject) """, """ fun invoke() { @@ -223,7 +222,7 @@ class ResolveTest { """ @Provide val foo = Foo() fun invoke() { - class UsesFoo(@Inject foo: Foo) + class UsesFoo(foo: Foo = inject) UsesFoo() } """ @@ -448,7 +447,7 @@ class ResolveTest { """ @Provide val foo = Foo() - fun String.myFunc(@Inject foo: Foo) { + fun String.myFunc(foo: Foo = inject) { } """, """ @@ -456,11 +455,10 @@ class ResolveTest { """ ) - // todo @Test - fun testSmartcastWithInject() = codegen( + @Test fun testSmartcastWithInject() = codegen( """ class MyType { - fun doSomething(@Inject key: TypeKey) { + fun doSomething(key: TypeKey = inject) { } } fun invoke(myType: MyType?) { @@ -474,28 +472,28 @@ class ResolveTest { @Test fun testInvocationOfFunctionDeclaredInSuperClassWithInjectParameters() = singleAndMultiCodegen( """ open class MySuperClass { - fun func(@Inject foo: Foo) { + fun func(foo: Foo = inject) { } } class MySubClass : MySuperClass() """, """ - fun invoke(@Inject foo: Foo) = MySubClass().func() + fun invoke(foo: Foo = inject) = MySubClass().func() """ ) @Test fun testInvocationOfFunctionDeclaredInSuperClassWithGenericInjectParameters() = singleAndMultiCodegen( """ open class MySuperClass { - fun func(@Inject s: S) { + fun func(s: S = inject) { } } class MySubClass : MySuperClass() """, """ - fun invoke(@Inject foo: Foo) = MySubClass().func() + fun invoke(foo: Foo = inject) = MySubClass().func() """ ) @@ -547,7 +545,7 @@ class ResolveTest { interface FooHolder { val foo: Foo } - fun FooHolder(@Inject foo: Foo) = object : FooHolder { + fun FooHolder(foo: Foo = inject) = object : FooHolder { override val foo = foo } class MyClass(@Provide foo: Foo) : FooHolder by FooHolder() @@ -559,7 +557,7 @@ class ResolveTest { interface FooHolder { val foo: Foo } - fun FooHolder(@Inject foo: Foo) = object : FooHolder { + fun FooHolder(foo: Foo = inject) = object : FooHolder { override val foo = foo } class MyClass() : FooHolder by FooHolder() { @@ -572,7 +570,7 @@ class ResolveTest { @Test fun testCannotResolveClassProvideDeclarationInSuperTypeExpression() = codegen( """ - abstract class MyAbstractClass(@Inject foo: Foo) + abstract class MyAbstractClass(foo: Foo = inject) class MyClass : MyAbstractClass() { @Provide val foo = Foo() } @@ -999,7 +997,7 @@ class ResolveTest { @Provide @Tag1 object NoopLogger : Logger - fun log(@Inject logger: Logger) { + fun log(logger: Logger = inject) { } """, """ @@ -1034,23 +1032,6 @@ class ResolveTest { """ ) - @Test fun testCannotResolveAInjectableInBlockWhichIsDeclaredAfterIt() = codegen( - """ - fun injectOrNull(@Inject x: T? = null): T? = x - fun invoke(foo: Foo): Pair { - val a = injectOrNull() - @Provide val provided = foo - val b = injectOrNull() - return a to b - } - """ - ) { - val foo = Foo() - val result = invokeSingleFile>(foo) - result.first.shouldBeNull() - result.second shouldBeSameInstanceAs foo - } - @Test fun testCannotResolveUnconstrainedType() = codegen( """ @Provide fun everything(): T = error("") diff --git a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TagTest.kt b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TagTest.kt index e661c7fd9b..a883a2203d 100644 --- a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TagTest.kt +++ b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TagTest.kt @@ -86,7 +86,7 @@ class TagTest { @Tag annotation class MyTag """, """ - fun invoke(@Inject value: @MyTag String) { + fun invoke(value: @MyTag String = inject) { } """ ) diff --git a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TypeKeyTest.kt b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TypeKeyTest.kt index 274f107058..624fab6653 100644 --- a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TypeKeyTest.kt +++ b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TypeKeyTest.kt @@ -26,7 +26,7 @@ class TypeKeyTest { @Test fun testTypeKeyWithTypeParameters() = singleAndMultiCodegen( """ - inline fun listTypeKeyOf(@Inject single: TypeKey) = inject>>() + inline fun listTypeKeyOf(single: TypeKey = inject) = inject>>() """, """ fun invoke() = listTypeKeyOf() diff --git a/settings.gradle.kts b/settings.gradle.kts index 8651b9903c..2634db2285 100755 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,7 +7,6 @@ include( ":compiler", ":core", ":gradle-plugin", - ":ide", ":ksp", ":integration-tests", ":sample" From 8d7dfd6761e6cdaeb13545bd8d77e6210f5ca5e8 Mon Sep 17 00:00:00 2001 From: manu Date: Wed, 21 Feb 2024 20:19:06 +0100 Subject: [PATCH 2/6] Removed ide plugin requirement --- README.md | 14 +++++-- .../kotlin/com/ivianuu/injekt/common/Scope.kt | 4 +- .../compiler/InjektComponentRegistrar.kt | 4 -- .../analysis/InjektDiagnosticSuppressor.kt | 37 ------------------- .../injekt/integrationtests/ResolveTest.kt | 4 +- .../SpreadingInjectableTest.kt | 24 ++++++++---- .../injekt/integrationtests/TagTest.kt | 15 +++++--- .../injekt/integrationtests/TestModels.kt | 9 +++-- .../integrationtests/TypeSubstitutionTest.kt | 3 +- 9 files changed, 50 insertions(+), 64 deletions(-) delete mode 100644 compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektDiagnosticSuppressor.kt diff --git a/README.md b/README.md index 5e5175d805..692d38b9ae 100644 --- a/README.md +++ b/README.md @@ -144,17 +144,23 @@ fun loadPlaylistTracks(playlistId: PlaylistId = inject, trackId: TrackId = injec Tags: ```kotlin -@Tag annotation class PlaylistId -@Tag annotation class TrackId +@Tag +@Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) +annotation class PlaylistId +@Tag +@Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) +annotation class TrackId fun loadPlaylistTracks(playlistId: @PlaylistId String = inject, trackId: @TrackId String = inject): List = ... ``` Optionally you can add a typealias for your tag to make it easier to use ```kotlin -@Tag annotation class PlaylistIdTag +@Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) +annotation class PlaylistIdTag typealias PlaylistId = @PlaylistIdTag String -@Tag annotation class TrackIdTag +@Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) +annotation class TrackIdTag typealias TrackId = @TrackIdTag String fun loadPlaylistTracks(playlistId: PlaylistId = inject, trackId: TrackId = inject): List = ... diff --git a/common/src/commonMain/kotlin/com/ivianuu/injekt/common/Scope.kt b/common/src/commonMain/kotlin/com/ivianuu/injekt/common/Scope.kt index b92ec11b61..2dd32a7d5a 100644 --- a/common/src/commonMain/kotlin/com/ivianuu/injekt/common/Scope.kt +++ b/common/src/commonMain/kotlin/com/ivianuu/injekt/common/Scope.kt @@ -23,7 +23,9 @@ class Scope : SynchronizedObject() { } } -@Tag annotation class Scoped { +@Tag +@Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) +annotation class Scoped { @Provide companion object { @Provide inline fun <@Spread T : @Scoped S, S : Any, N> scoped( scope: Scope, diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektComponentRegistrar.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektComponentRegistrar.kt index 566853845e..778cc47ac5 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektComponentRegistrar.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektComponentRegistrar.kt @@ -41,10 +41,6 @@ class InjektComponentRegistrar : ComponentRegistrar { project, InjectCallChecker() ) - - @Suppress("DEPRECATION") - Extensions.getRootArea().getExtensionPoint(DiagnosticSuppressor.EP_NAME) - .registerExtension(InjektDiagnosticSuppressor(), project) } } diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektDiagnosticSuppressor.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektDiagnosticSuppressor.kt deleted file mode 100644 index 854300431b..0000000000 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektDiagnosticSuppressor.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2022 Manuel Wrage. Use of this source code is governed by the Apache 2.0 license. - */ - -@file:OptIn(UnsafeCastFunction::class) - -package com.ivianuu.injekt.compiler.analysis - -import com.ivianuu.injekt.compiler.* -import org.jetbrains.kotlin.diagnostics.* -import org.jetbrains.kotlin.resolve.* -import org.jetbrains.kotlin.resolve.diagnostics.* -import org.jetbrains.kotlin.utils.addToStdlib.* - -class InjektDiagnosticSuppressor : DiagnosticSuppressor { - override fun isSuppressed(diagnostic: Diagnostic): Boolean = - isSuppressed(diagnostic, null) - - override fun isSuppressed(diagnostic: Diagnostic, bindingContext: BindingContext?): Boolean { - if (diagnostic.factory == Errors.ANNOTATION_USED_AS_ANNOTATION_ARGUMENT) - return true - - if (bindingContext == null) - return false - - if (diagnostic.factory == Errors.WRONG_ANNOTATION_TARGET) { - val annotationDescriptor = - bindingContext[BindingContext.ANNOTATION, diagnostic.psiElement.cast()] - if (annotationDescriptor?.type?.constructor?.declarationDescriptor - ?.hasAnnotation(InjektFqNames.Tag) == true - ) - return true - } - - return false - } -} diff --git a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/ResolveTest.kt b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/ResolveTest.kt index e3ef9a921d..5e48e41b2f 100644 --- a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/ResolveTest.kt +++ b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/ResolveTest.kt @@ -234,7 +234,9 @@ class ResolveTest { """ @Provide fun foos() = Foo() to Foo() - @Tag annotation class First + @Tag + @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class First @Provide fun first(pair: Pair): A = pair.first as A """, """ diff --git a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/SpreadingInjectableTest.kt b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/SpreadingInjectableTest.kt index bc99b79508..978dc4d8a0 100644 --- a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/SpreadingInjectableTest.kt +++ b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/SpreadingInjectableTest.kt @@ -12,7 +12,8 @@ import org.junit.* class SpreadingInjectableTest { @Test fun testSpreadingInjectableFunction() = singleAndMultiCodegen( """ - @Tag annotation class Trigger + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class Trigger @Provide fun <@Spread T : @Trigger S, S> triggerImpl(instance: T): S = instance @Provide fun foo(): @Trigger Foo = Foo() @@ -29,9 +30,11 @@ class SpreadingInjectableTest { @Provide class MyModule<@Spread T : @Trigger S, S> { @Provide fun intoSet(instance: T): @Final S = instance } - @Tag annotation class Trigger + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class Trigger - @Tag annotation class Final + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class Final @Provide fun foo(): @Trigger Foo = Foo() @Provide fun string(): @Trigger String = "" @@ -53,7 +56,8 @@ class SpreadingInjectableTest { @Test fun testSpreadingInjectableTriggeredByClass() = singleAndMultiCodegen( """ - @Tag annotation class Trigger + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class Trigger @Provide fun <@Spread T : @Trigger S, S> triggerImpl(instance: T): S = instance @Trigger @Provide class NotAny @@ -67,7 +71,8 @@ class SpreadingInjectableTest { @Test fun testSpreadingInjectableChain() = singleAndMultiCodegen( """ - @Tag annotation class A + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class A @Provide fun <@Spread T : @A S, S> aImpl() = AModule_() @@ -75,14 +80,16 @@ class SpreadingInjectableTest { @Provide fun my(instance: T): @B T = instance } - @Tag annotation class B + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class B @Provide fun <@Spread T : @B S, S> bImpl() = BModule_() class BModule_ { @Provide fun my(instance: T): @C Any? = instance } - @Tag annotation class C + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class C @Provide fun <@Spread T : @C Any?> cImpl() = Foo() @Provide fun dummy(): @A Long = 0L @@ -96,7 +103,8 @@ class SpreadingInjectableTest { @Test fun testMultipleSpreadCandidatesWithSameType() = singleAndMultiCodegen( """ - @Tag annotation class Trigger + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class Trigger @Provide fun <@Spread T : @Trigger String> triggerImpl(instance: T): String = instance @Provide fun a(): @Trigger String = "a" diff --git a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TagTest.kt b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TagTest.kt index a883a2203d..bd56b905d0 100644 --- a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TagTest.kt +++ b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TagTest.kt @@ -83,7 +83,8 @@ class TagTest { @Test fun testTagDoesNotNeedToSpecifyTypeTarget() = singleAndMultiCodegen( """ - @Tag annotation class MyTag + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class MyTag """, """ fun invoke(value: @MyTag String = inject) { @@ -93,7 +94,8 @@ class TagTest { @Test fun testTagWithTypeParameters() = singleAndMultiCodegen( """ - @Tag annotation class MyTag + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class MyTag @Provide val taggedFoo: @MyTag Foo = Foo() """, """ @@ -105,7 +107,8 @@ class TagTest { @Test fun testTagWithGenericTypeArguments() = singleAndMultiCodegen( """ - @Tag annotation class MyTag + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class MyTag @Provide fun taggedFoo(): @MyTag Foo = Foo() """, """ @@ -117,7 +120,8 @@ class TagTest { @Test fun testTagTypeAliasPattern() = singleAndMultiCodegen( """ - @Tag annotation class TaggedFooTag + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class TaggedFooTag typealias TaggedFoo = @TaggedFooTag Foo @Provide val taggedFoo: TaggedFoo = Foo() """, @@ -130,7 +134,8 @@ class TagTest { """ typealias ComponentScope = @ComponentScopeTag String - @Tag annotation class ComponentScopeTag { + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class ComponentScopeTag { @Provide companion object { @Provide fun scope(): ComponentScope = "" } diff --git a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TestModels.kt b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TestModels.kt index a79c4b635a..c71e499c34 100644 --- a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TestModels.kt +++ b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TestModels.kt @@ -18,11 +18,14 @@ class CommandA : Command class CommandB : Command -@Tag annotation class Tag1 +@Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) +annotation class Tag1 -@Tag annotation class Tag2 +@Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) +annotation class Tag2 -@Tag annotation class TypedTag +@Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) +annotation class TypedTag object TestScope1 diff --git a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TypeSubstitutionTest.kt b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TypeSubstitutionTest.kt index 9893cd8725..9ee8e54d9b 100644 --- a/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TypeSubstitutionTest.kt +++ b/integration-tests/src/jvmTest/kotlin/com/ivianuu/injekt/integrationtests/TypeSubstitutionTest.kt @@ -95,7 +95,8 @@ class TypeSubstitutionTest { interface DialogKey : Key - @Tag annotation class KeyUiTag> + @Tag @Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.TYPE) + annotation class KeyUiTag> typealias KeyUi = @KeyUiTag @Composable () -> Unit typealias ModelKeyUi = (ModelKeyUiScope) -> Unit From 120ba0f83990b4cdebd43a6f6fe9ab4bfb03bece Mon Sep 17 00:00:00 2001 From: manu Date: Wed, 21 Feb 2024 20:29:24 +0100 Subject: [PATCH 3/6] Removed ide logic --- .../com/ivianuu/injekt/compiler/InjektUtil.kt | 21 ------------------- ...ektStorageComponentContainerContributor.kt | 2 +- .../transform/InjektIrGenerationExtension.kt | 2 -- 3 files changed, 1 insertion(+), 24 deletions(-) diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektUtil.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektUtil.kt index b609c33671..7cc4d377c5 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektUtil.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/InjektUtil.kt @@ -7,7 +7,6 @@ package com.ivianuu.injekt.compiler import org.jetbrains.kotlin.builtins.functions.* -import org.jetbrains.kotlin.com.intellij.openapi.project.* import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.* import org.jetbrains.kotlin.incremental.components.* @@ -36,8 +35,6 @@ fun KtFunction.getArgumentDescriptor(ctx: Context): ValueParameterDescriptor? { return mapping.valueParameter } -val isIde = Project::class.java.name == "com.intellij.openapi.project.Project" - fun KtDeclaration.descriptor(ctx: Context) = ctx.trace!!.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, this] as? D @@ -196,24 +193,6 @@ fun ParameterDescriptor.injektIndex(): Int = if (this is ValueParameterDescripto } } -fun Any.readPrivateFinalField(clazz: KClass<*>, fieldName: String): T { - val field = clazz.java.declaredFields - .single { it.name == fieldName } - field.isAccessible = true - val modifiersField = try { - Field::class.java.getDeclaredField("modifiers") - } catch (e: Throwable) { - val getDeclaredFields0 = Class::class.java.getDeclaredMethod("getDeclaredFields0", Boolean::class.java) - getDeclaredFields0.isAccessible = true - getDeclaredFields0.invoke(Field::class.java, false) - .cast>() - .single { it.name == "modifiers" } - } - modifiersField.isAccessible = true - modifiersField.setInt(field, field.modifiers and Modifier.FINAL.inv()) - return field.get(this) as T -} - fun Any.updatePrivateFinalField(clazz: KClass<*>, fieldName: String, transform: T.() -> T): T { val field = clazz.java.declaredFields .single { it.name == fieldName } diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektStorageComponentContainerContributor.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektStorageComponentContainerContributor.kt index ccb7ccaf87..626509ff9d 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektStorageComponentContainerContributor.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjektStorageComponentContainerContributor.kt @@ -18,6 +18,6 @@ class InjektStorageComponentContainerContributor : StorageComponentContainerCont ) { val ctx = Context(moduleDescriptor, null) container.useInstance(InjektDeclarationChecker(ctx)) - if (!isIde) container.useInstance(InfoPatcher(ctx)) + container.useInstance(InfoPatcher(ctx)) } } diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/transform/InjektIrGenerationExtension.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/transform/InjektIrGenerationExtension.kt index a02b615631..c16d104e11 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/transform/InjektIrGenerationExtension.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/transform/InjektIrGenerationExtension.kt @@ -7,7 +7,6 @@ package com.ivianuu.injekt.compiler.transform import com.ivianuu.injekt.compiler.* import org.jetbrains.kotlin.backend.common.extensions.* import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.resolve.* import java.io.* @@ -22,7 +21,6 @@ class InjektIrGenerationExtension(private val dumpDir: File) : IrGenerationExten moduleFragment.transform(InjectCallTransformer(pluginContext, ctx), null) - moduleFragment.patchDeclarationParents() moduleFragment.dumpToFiles(dumpDir, ctx) } } From 1aaa17f7f0d559c93ece93ed5733b3c9f48c4457 Mon Sep 17 00:00:00 2001 From: manu Date: Wed, 21 Feb 2024 20:30:57 +0100 Subject: [PATCH 4/6] Removed unused parameter --- .../com/ivianuu/injekt/compiler/analysis/InjectCallChecker.kt | 2 +- .../com/ivianuu/injekt/compiler/resolution/Injectable.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectCallChecker.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectCallChecker.kt index e8ddb43ca8..2390ee1c2f 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectCallChecker.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/analysis/InjectCallChecker.kt @@ -90,7 +90,7 @@ import org.jetbrains.kotlin.utils.* .transform { val index = it.injektIndex() if (valueArgumentsByIndex[index] is DefaultValueArgument && index in info.injectParameters) - add(it.toInjectableRequest(callee, ctx)) + add(it.toInjectableRequest(callee)) } if (requests.isEmpty()) return diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/Injectable.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/Injectable.kt index fc98e0928f..7d2110b009 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/Injectable.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/resolution/Injectable.kt @@ -30,7 +30,7 @@ class CallableInjectable( ) : Injectable { override val dependencies = (if (callable.callable is ConstructorDescriptor) callable.callable.valueParameters else callable.callable.allParameters) - .map { it.toInjectableRequest(callable, ownerScope.ctx) } + .map { it.toInjectableRequest(callable) } override val callableFqName = if (callable.callable is ClassConstructorDescriptor) callable.callable.constructedClass.fqNameSafe else callable.callable.fqNameSafe @@ -128,7 +128,7 @@ data class InjectableRequest( val isRequired: Boolean = true ) -fun ParameterDescriptor.toInjectableRequest(callable: CallableRef, ctx: Context): InjectableRequest = +fun ParameterDescriptor.toInjectableRequest(callable: CallableRef): InjectableRequest = InjectableRequest( type = callable.parameterTypes[injektIndex()]!!, callableFqName = callable.callableFqName, From e3992a098c9f464db7be1323694ab25099ec70b1 Mon Sep 17 00:00:00 2001 From: manu Date: Wed, 21 Feb 2024 20:35:24 +0100 Subject: [PATCH 5/6] Ir clean up --- .../transform/InjectCallTransformer.kt | 66 +++++++++---------- 1 file changed, 30 insertions(+), 36 deletions(-) diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/transform/InjectCallTransformer.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/transform/InjectCallTransformer.kt index c2210d5ed5..dff37118ce 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/transform/InjectCallTransformer.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/transform/InjectCallTransformer.kt @@ -83,7 +83,7 @@ class InjectCallTransformer( val scope: InjectablesScope, val irScope: Scope ) { - val symbol = irScope.scopeOwnerSymbol + val irBuilder = DeclarationIrBuilder(irCtx, irScope.scopeOwnerSymbol) val functionWrappedExpressions = mutableMapOf IrExpression>() val statements = if (scope == rootContext.result.scope) rootContext.statements else mutableListOf() @@ -113,7 +113,7 @@ class InjectCallTransformer( if (!result.candidate.type.isNullableType || result.dependencyResults.keys.firstOrNull()?.parameterIndex != DISPATCH_RECEIVER_INDEX) expression - else DeclarationIrBuilder(irCtx, symbol).run { + else irBuilder.run { irBlock { expression as IrFunctionAccessExpression val tmpDispatchReceiver = irTemporary(expression.dispatchReceiver!!) @@ -179,11 +179,10 @@ class InjectCallTransformer( } return@expression { - DeclarationIrBuilder(irCtx, symbol) - .irCall( - function.symbol, - result.candidate.type.toIrType(irCtx).typeOrNull!! - ) + irBuilder.irCall( + function.symbol, + result.candidate.type.toIrType(irCtx).typeOrNull!! + ) } } }.invoke(this) @@ -191,8 +190,7 @@ class InjectCallTransformer( private fun ScopeContext.lambdaExpression( result: ResolutionResult.Success.Value, injectable: LambdaInjectable - ): IrExpression = DeclarationIrBuilder(irCtx, symbol) - .irLambda(injectable.type.toIrType(irCtx).typeOrNull!!) { function -> + ): IrExpression = irBuilder.irLambda(injectable.type.toIrType(irCtx).typeOrNull!!) { function -> val dependencyResult = result.dependencyResults.values.single() val dependencyScopeContext = if (injectable.dependencyScope == this@lambdaExpression.scope) null else ScopeContext( @@ -234,7 +232,7 @@ class InjectCallTransformer( private fun ScopeContext.listExpression( result: ResolutionResult.Success.Value, injectable: ListInjectable - ): IrExpression = DeclarationIrBuilder(irCtx, symbol).irBlock { + ): IrExpression = irBuilder.irBlock { val tmpList = irTemporary( irCall(mutableListOf) .apply { @@ -268,7 +266,7 @@ class InjectCallTransformer( private fun ScopeContext.typeKeyExpression( result: ResolutionResult.Success.Value, injectable: TypeKeyInjectable - ): IrExpression = DeclarationIrBuilder(irCtx, symbol).run { + ): IrExpression = irBuilder.run { val expressions = mutableListOf() var currentString = "" fun commitCurrentString() { @@ -334,15 +332,16 @@ class InjectCallTransformer( } private fun ScopeContext.objectExpression(type: TypeRef): IrExpression = - DeclarationIrBuilder(irCtx, symbol) - .irGetObject(irCtx.referenceClass(type.classifier.fqName)!!) + irBuilder.irGetObject(irCtx.referenceClass(type.classifier.fqName)!!) private fun ScopeContext.functionExpression( result: ResolutionResult.Success.Value, injectable: CallableInjectable, descriptor: CallableDescriptor - ): IrExpression = DeclarationIrBuilder(irCtx, symbol) - .irCall(descriptor.irCallable(irCtx).symbol, injectable.type.toIrType(irCtx).typeOrNull!!) + ): IrExpression = irBuilder.irCall( + descriptor.irCallable(irCtx).symbol, + injectable.type.toIrType(irCtx).typeOrNull!! + ) .apply { fillTypeParameters(injectable.callable) inject(this@functionExpression, result.dependencyResults) @@ -350,7 +349,7 @@ class InjectCallTransformer( private fun ScopeContext.receiverExpression( descriptor: ParameterDescriptor - ): IrExpression = DeclarationIrBuilder(irCtx, symbol).run { + ): IrExpression = irBuilder.run { allScopes.reversed().firstNotNullOfOrNull { scope -> val element = scope.irElement when { @@ -376,14 +375,13 @@ class InjectCallTransformer( ): IrExpression = when (val containingDeclaration = descriptor.containingDeclaration) { is ClassDescriptor -> receiverExpression(descriptor) - is CallableDescriptor -> DeclarationIrBuilder(irCtx, symbol) - .irGet( - injectable.type.toIrType(irCtx).typeOrNull!!, - (parameterMap[descriptor] ?: containingDeclaration.irCallable(irCtx) - .allParameters - .single { it.descriptor.injektIndex() == descriptor.injektIndex() }) - .symbol - ) + is CallableDescriptor -> irBuilder.irGet( + injectable.type.toIrType(irCtx).typeOrNull!!, + (parameterMap[descriptor] ?: containingDeclaration.irCallable(irCtx) + .allParameters + .single { it.descriptor.injektIndex() == descriptor.injektIndex() }) + .symbol + ) else -> error("Unexpected parent $descriptor $containingDeclaration") } @@ -399,18 +397,14 @@ class InjectCallTransformer( private fun ScopeContext.localVariableExpression( descriptor: LocalVariableDescriptor, injectable: CallableInjectable - ): IrExpression = if (descriptor.getter != null) - DeclarationIrBuilder(irCtx, symbol) - .irCall( - irCtx.symbolTable.descriptorExtension.referenceSimpleFunction(descriptor.getter!!), - injectable.type.toIrType(irCtx).typeOrNull!! - ) - else - DeclarationIrBuilder(irCtx, symbol) - .irGet( - injectable.type.toIrType(irCtx).typeOrNull!!, - localVariables.single { it.descriptor == descriptor }.symbol - ) + ): IrExpression = if (descriptor.getter != null) irBuilder.irCall( + irCtx.symbolTable.descriptorExtension.referenceSimpleFunction(descriptor.getter!!), + injectable.type.toIrType(irCtx).typeOrNull!! + ) + else irBuilder.irGet( + injectable.type.toIrType(irCtx).typeOrNull!!, + localVariables.single { it.descriptor == descriptor }.symbol + ) private val localVariables = mutableListOf() From 5b2ce8b2992c3c52bc3c4887c69afd37e8bb19ee Mon Sep 17 00:00:00 2001 From: manu Date: Wed, 21 Feb 2024 20:40:55 +0100 Subject: [PATCH 6/6] ... --- .../injekt/compiler/transform/InjectCallTransformer.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/transform/InjectCallTransformer.kt b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/transform/InjectCallTransformer.kt index dff37118ce..6eedc7432e 100644 --- a/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/transform/InjectCallTransformer.kt +++ b/compiler/src/main/kotlin/com/ivianuu/injekt/compiler/transform/InjectCallTransformer.kt @@ -32,7 +32,7 @@ class InjectCallTransformer( private val irCtx: IrPluginContext, private val ctx: Context ) : IrElementTransformerVoidWithContext() { - private inner class RootContext(val result: InjectionResult.Success, val startOffset: Int) { + private inner class RootContext(val result: InjectionResult.Success) { val statements = mutableListOf() val highestScope = mutableMapOf() @@ -433,7 +433,7 @@ class InjectCallTransformer( return DeclarationIrBuilder(irCtx, result.symbol) .irBlock { - val rootContext = RootContext(injectionResult, result.startOffset) + val rootContext = RootContext(injectionResult) try { ScopeContext( parent = null,