Skip to content

Commit

Permalink
make annotations-optional a KMP library (#81)
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielittner authored Oct 31, 2024
1 parent e003fa9 commit c957242
Show file tree
Hide file tree
Showing 11 changed files with 199 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

- **Enhancement**: Improve error messaging for error types used as annotation arguments.
- **Enhancement**: Initial support for jakarta.inject annotations. Note that Dagger itself appears to only partially support these at the moment. Generated code is identical, but jakarta `@Inject`/`@Qualifier`/`@Scope` annotations should be recognized now.
- **Enhancement**: `annotations` and `annotations-optional` are now Kotlin multiplatfom libraries.
- **Enhancement**: `@SingleIn` and `@ForScope` can now be used with jakarta.inject and kotlin-inject.
- Update Dagger to `2.52`.

0.3.3
Expand Down
19 changes: 17 additions & 2 deletions annotations-optional/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi

plugins {
id("conventions.library")
id("conventions.kmp-library")
id("conventions.publish")
}

Expand All @@ -8,9 +10,22 @@ publish {
artifactId = "annotations-optional",
pomName = "Anvil Optional Annotations",
pomDescription = "Optional annotations that we\"ve found to be helpful with managing larger dependency graphs",
overrideArtifactId = false,
)
}

kotlin {
@OptIn(ExperimentalKotlinGradlePluginApi::class)
compilerOptions {
freeCompilerArgs.add("-Xexpect-actual-classes")
}
}

dependencies {
api(libs.inject)
commonMainCompileOnly(libs.kotlinInject)
// non jvm targets don't support compile only dependencies
nonJvmMainApi(libs.kotlinInject)

jvmMainCompileOnly(libs.inject)
jvmMainCompileOnly(libs.jakarta)
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package com.squareup.anvil.annotations.optional

import javax.inject.Qualifier
import kotlin.annotation.AnnotationRetention.RUNTIME
import kotlin.reflect.KClass
import me.tatarka.inject.annotations.Scope as KotlinInjectScope

/**
* A class based [qualfier](Qualifier).
* A class based [qualifier](Qualifier).
*
* This can be used in combination with other Anvil annotations to avoid having
* to manually define qualifier annotations for each component and to maintain
Expand All @@ -24,9 +24,9 @@ import kotlin.reflect.KClass
* class UserAuthenticator @Inject constructor() : Authenticator
* ```
*/
@Qualifier
@KotlinInjectScope
@Retention(RUNTIME)
public annotation class ForScope(
public expect annotation class ForScope(
/**
* The marker that identifies the component in which the annotated object is
* provided or bound in.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.squareup.anvil.annotations.optional

import javax.inject.Scope
import kotlin.annotation.AnnotationRetention.RUNTIME
import kotlin.reflect.KClass
import me.tatarka.inject.annotations.Qualifier as KotlinInjectQualifier

/**
* Identifies a type that the injector only instantiates once for the given
Expand Down Expand Up @@ -30,9 +30,9 @@ import kotlin.reflect.KClass
*
* See Also: [@Scope](Scope)
*/
@Scope
@KotlinInjectQualifier
@Retention(RUNTIME)
public annotation class SingleIn(
public expect annotation class SingleIn(
/**
* The marker that identifies this scope.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.squareup.anvil.annotations.optional

import kotlin.annotation.AnnotationRetention.RUNTIME
import kotlin.reflect.KClass
import jakarta.inject.Qualifier as JakartaQualifier
import javax.inject.Qualifier as JavaxQualifier
import me.tatarka.inject.annotations.Qualifier as KotlinInjectQualifier

/**
* A class based [qualifier](Qualifier).
*
* This can be used in combination with other Anvil annotations to avoid having
* to manually define qualifier annotations for each component and to maintain
* consistency.
*
* Example:
* ```
* interface Authenticator
*
* @ForScope(AppScope::class)
* @ContributesBinding(AppScope::class)
* class CommonAuthenticator @Inject constructor() : Authenticator
*
* @ForScope(UserScope::class)
* @ContributesBinding(UserScope::class)
* class UserAuthenticator @Inject constructor() : Authenticator
* ```
*/
@JavaxQualifier
@JakartaQualifier
@KotlinInjectQualifier
@Retention(RUNTIME)
public actual annotation class ForScope(
/**
* The marker that identifies the component in which the annotated object is
* provided or bound in.
*/
actual val scope: KClass<*>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.squareup.anvil.annotations.optional

import kotlin.annotation.AnnotationRetention.RUNTIME
import kotlin.reflect.KClass
import jakarta.inject.Scope as JakartaScope
import javax.inject.Scope as JavaxScope
import me.tatarka.inject.annotations.Scope as KotlinInjectScope

/**
* Identifies a type that the injector only instantiates once for the given
* [scope] marker.
*
* This can be used in combination with other Anvil annotations to avoid having
* to manually define scope annotations for each component and to maintain
* consistency.
*
* Component example:
* ```
* @SingleIn(AppScope::class)
* @MergeComponent(AppScope::class)
* interface AppComponent
* ```
*
* Contribution example:
* ```
* interface Authenticator
*
* @SingleIn(AppScope::class)
* @ContributesBinding(AppScope::class)
* class RealAuthenticator @Inject constructor() : Authenticator
* ```
*
* See Also: [@Scope](Scope)
*/
@JavaxScope
@JakartaScope
@KotlinInjectScope
@Retention(RUNTIME)
public actual annotation class SingleIn(
/**
* The marker that identifies this scope.
*/
actual val scope: KClass<*>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.squareup.anvil.annotations.optional

import kotlin.annotation.AnnotationRetention.RUNTIME
import kotlin.reflect.KClass
import me.tatarka.inject.annotations.Qualifier as KotlinInjectQualifier

/**
* A class based [qualifier](Qualifier).
*
* This can be used in combination with other Anvil annotations to avoid having
* to manually define qualifier annotations for each component and to maintain
* consistency.
*
* Example:
* ```
* interface Authenticator
*
* @ForScope(AppScope::class)
* @ContributesBinding(AppScope::class)
* class CommonAuthenticator @Inject constructor() : Authenticator
*
* @ForScope(UserScope::class)
* @ContributesBinding(UserScope::class)
* class UserAuthenticator @Inject constructor() : Authenticator
* ```
*/
@KotlinInjectQualifier
@Retention(RUNTIME)
public actual annotation class ForScope(
/**
* The marker that identifies the component in which the annotated object is
* provided or bound in.
*/
actual val scope: KClass<*>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.squareup.anvil.annotations.optional

import kotlin.annotation.AnnotationRetention.RUNTIME
import kotlin.reflect.KClass
import me.tatarka.inject.annotations.Scope as KotlinInjectScope

/**
* Identifies a type that the injector only instantiates once for the given
* [scope] marker.
*
* This can be used in combination with other Anvil annotations to avoid having
* to manually define scope annotations for each component and to maintain
* consistency.
*
* Component example:
* ```
* @SingleIn(AppScope::class)
* @MergeComponent(AppScope::class)
* interface AppComponent
* ```
*
* Contribution example:
* ```
* interface Authenticator
*
* @SingleIn(AppScope::class)
* @ContributesBinding(AppScope::class)
* class RealAuthenticator @Inject constructor() : Authenticator
* ```
*
* See Also: [@Scope](Scope)
*/
@KotlinInjectScope
@Retention(RUNTIME)
public actual annotation class SingleIn(
/**
* The marker that identifies this scope.
*/
actual val scope: KClass<*>,
)
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,19 @@ class LibraryKmpPlugin : Plugin<Project> {
watchosSimulatorArm64()
watchosX64()

mingwX64()
// TODO: re-enable when kotlin-inject supports it
// mingwX64()

applyDefaultHierarchyTemplate()

sourceSets.apply {
val nonJvmMain = create("nonJvmMain")
nonJvmMain.dependsOn(commonMain.get())

nativeMain.get().dependsOn(nonJvmMain)
jsMain.get().dependsOn(nonJvmMain)
getByName("wasmJsMain").dependsOn(nonJvmMain)
}
}
configureBinaryCompatibilityValidator()
configureExplicitApi()
Expand Down
3 changes: 3 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,6 @@ android.defaults.buildfeatures.viewBinding=false

# Suppress the warning about MPP being in alpha.
kotlin.mpp.stability.nowarn=true

# TODO: remove when updating to Kotlin 2.0
kotlin.native.ignoreIncorrectDependencies=true
1 change: 1 addition & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ gradlePublishRaw = { module = "com.gradle.publish:plugin-publish-plugin", versio
guava = "com.google.guava:guava:33.2.1-jre"

inject = "javax.inject:javax.inject:1"
kotlinInject = "me.tatarka.inject:kotlin-inject-runtime:0.7.2"
jakarta = "jakarta.inject:jakarta.inject-api:2.0.1"
jsr250 = "javax.annotation:jsr250-api:1.0"
junit = "junit:junit:4.13.2"
Expand Down

0 comments on commit c957242

Please sign in to comment.