Skip to content

Commit 0e86b2c

Browse files
authored
Merge pull request #5253 from element-hq/metro-v2
Migrate Anvil KSP to Metro
2 parents 6833b76 + 5ee0a40 commit 0e86b2c

File tree

796 files changed

+3590
-3030
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

796 files changed

+3590
-3030
lines changed

anvilannotations/src/main/kotlin/io/element/android/anvilannotations/ContributesNode.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import kotlin.reflect.KClass
1313
* Adds Node to the specified component graph.
1414
* Equivalent to the following declaration:
1515
*
16-
* @Module
16+
* @BindingContainer
1717
* @ContributesTo(Scope::class)
1818
* abstract class YourNodeModule {
1919

anvilcodegen/build.gradle.kts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@ plugins {
1111

1212
dependencies {
1313
implementation(projects.anvilannotations)
14-
api(libs.anvil.compiler.api)
15-
implementation(libs.anvil.compiler.utils)
14+
implementation(libs.metro.runtime)
15+
implementation(libs.kotlin.compiler)
1616
implementation(libs.kotlinpoet)
17-
implementation(libs.dagger)
1817
implementation(libs.ksp.plugin)
1918
implementation(libs.kotlinpoet.ksp)
2019
}

anvilcodegen/src/main/kotlin/io/element/android/anvilcodegen/ContributesNodeProcessor.kt

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import com.google.devtools.ksp.symbol.KSAnnotated
1919
import com.google.devtools.ksp.symbol.KSClassDeclaration
2020
import com.google.devtools.ksp.symbol.KSType
2121
import com.google.devtools.ksp.validate
22-
import com.squareup.anvil.annotations.ContributesTo
2322
import com.squareup.kotlinpoet.AnnotationSpec
2423
import com.squareup.kotlinpoet.ClassName
2524
import com.squareup.kotlinpoet.FileSpec
@@ -30,12 +29,12 @@ import com.squareup.kotlinpoet.STAR
3029
import com.squareup.kotlinpoet.TypeSpec
3130
import com.squareup.kotlinpoet.ksp.toTypeName
3231
import com.squareup.kotlinpoet.ksp.writeTo
33-
import dagger.Binds
34-
import dagger.Module
35-
import dagger.assisted.Assisted
36-
import dagger.assisted.AssistedFactory
37-
import dagger.assisted.AssistedInject
38-
import dagger.multibindings.IntoMap
32+
import dev.zacsweers.metro.Assisted
33+
import dev.zacsweers.metro.AssistedFactory
34+
import dev.zacsweers.metro.BindingContainer
35+
import dev.zacsweers.metro.Binds
36+
import dev.zacsweers.metro.ContributesTo
37+
import dev.zacsweers.metro.IntoMap
3938
import io.element.android.anvilannotations.ContributesNode
4039
import org.jetbrains.kotlin.name.FqName
4140

@@ -77,9 +76,8 @@ class ContributesNodeProcessor(
7776
fileName = moduleClassName,
7877
)
7978
.addType(
80-
TypeSpec.classBuilder(moduleClassName)
81-
.addModifiers(KModifier.ABSTRACT)
82-
.addAnnotation(Module::class)
79+
TypeSpec.interfaceBuilder(moduleClassName)
80+
.addAnnotation(BindingContainer::class)
8381
.addAnnotation(AnnotationSpec.builder(ContributesTo::class).addMember("%T::class", scope.toTypeName()).build())
8482
.addFunction(
8583
FunSpec.builder("bind${ksClass.simpleName.asString()}Factory")
@@ -103,7 +101,7 @@ class ContributesNodeProcessor(
103101
content.writeTo(
104102
codeGenerator = codeGenerator,
105103
dependencies = Dependencies(
106-
aggregating = true,
104+
aggregating = false,
107105
ksClass.containingFile!!
108106
),
109107
)
@@ -113,23 +111,23 @@ class ContributesNodeProcessor(
113111
private fun generateFactory(ksClass: KSClassDeclaration) {
114112
val generatedPackage = ksClass.packageName.asString()
115113
val assistedFactoryClassName = "${ksClass.simpleName.asString()}_AssistedFactory"
116-
val constructor = ksClass.getConstructors().singleOrNull { it.isAnnotationPresent(AssistedInject::class) }
117-
val assistedParameters = constructor?.parameters?.filter { it.isAnnotationPresent(Assisted::class) }.orEmpty()
118-
if (constructor == null || assistedParameters.size != 2) {
114+
val constructor = ksClass.getConstructors().first { it.parameters.isNotEmpty() }
115+
val assistedParameters = constructor.parameters.filter { it.isAnnotationPresent(Assisted::class) }
116+
if (assistedParameters.size != 2) {
119117
error(
120-
"${ksClass.qualifiedName} must have an @AssistedInject constructor with 2 @Assisted parameters",
118+
"${ksClass.qualifiedName?.asString()} must have an @Inject constructor with 2 @Assisted parameters. Found: ${assistedParameters.size}",
121119
)
122120
}
123121
val contextAssistedParam = assistedParameters[0]
124122
if (contextAssistedParam.name?.asString() != "buildContext") {
125123
error(
126-
"${ksClass.qualifiedName} @Assisted parameter must be named buildContext",
124+
"${ksClass.qualifiedName?.asString()} @Assisted parameter must be named buildContext",
127125
)
128126
}
129127
val pluginsAssistedParam = assistedParameters[1]
130128
if (pluginsAssistedParam.name?.asString() != "plugins") {
131129
error(
132-
"${ksClass.qualifiedName} @Assisted parameter must be named plugins",
130+
"${ksClass.qualifiedName?.asString()} @Assisted parameter must be named plugins",
133131
)
134132
}
135133

@@ -156,7 +154,7 @@ class ContributesNodeProcessor(
156154
content.writeTo(
157155
codeGenerator = codeGenerator,
158156
dependencies = Dependencies(
159-
aggregating = true,
157+
aggregating = false,
160158
ksClass.containingFile!!
161159
),
162160
)

app/build.gradle.kts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import com.android.build.gradle.tasks.GenerateBuildConfig
1313
import com.google.firebase.appdistribution.gradle.firebaseAppDistribution
1414
import config.BuildTimeConfig
1515
import extension.AssetCopyTask
16-
import extension.ComponentMergingStrategy
1716
import extension.GitBranchNameValueSource
1817
import extension.GitRevisionValueSource
1918
import extension.allEnterpriseImpl
@@ -23,7 +22,7 @@ import extension.allServicesImpl
2322
import extension.buildConfigFieldStr
2423
import extension.koverDependencies
2524
import extension.locales
26-
import extension.setupAnvil
25+
import extension.setupDependencyInjection
2726
import extension.setupKover
2827
import java.util.Locale
2928

@@ -37,7 +36,7 @@ plugins {
3736
alias(libs.plugins.licensee)
3837
alias(libs.plugins.kotlin.serialization)
3938
// To be able to update the firebase.xml files, uncomment and build the project
40-
// id("com.google.gms.google-services")
39+
// alias(libs.plugins.gms.google.services)
4140
}
4241

4342
setupKover()
@@ -248,11 +247,7 @@ knit {
248247
}
249248
}
250249

251-
setupAnvil(
252-
generateDaggerCode = true,
253-
generateDaggerFactoriesUsingAnvil = false,
254-
componentMergingStrategy = ComponentMergingStrategy.KSP,
255-
)
250+
setupDependencyInjection()
256251

257252
dependencies {
258253
allLibrariesImpl()

app/src/main/kotlin/io/element/android/x/ElementXApplication.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,16 @@ package io.element.android.x
99

1010
import android.app.Application
1111
import androidx.startup.AppInitializer
12+
import dev.zacsweers.metro.createGraphFactory
1213
import io.element.android.features.cachecleaner.api.CacheCleanerInitializer
13-
import io.element.android.libraries.di.DaggerComponentOwner
14-
import io.element.android.x.di.AppComponent
15-
import io.element.android.x.di.DaggerAppComponent
14+
import io.element.android.libraries.di.DependencyInjectionGraphOwner
15+
import io.element.android.x.di.AppGraph
1616
import io.element.android.x.info.logApplicationInfo
1717
import io.element.android.x.initializer.CrashInitializer
1818
import io.element.android.x.initializer.PlatformInitializer
1919

20-
class ElementXApplication : Application(), DaggerComponentOwner {
21-
override val daggerComponent: AppComponent = DaggerAppComponent.factory().create(this)
20+
class ElementXApplication : Application(), DependencyInjectionGraphOwner {
21+
override val graph: AppGraph = createGraphFactory<AppGraph.Factory>().create(this)
2222

2323
override fun onCreate() {
2424
super.onCreate()

app/src/main/kotlin/io/element/android/x/MainNode.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import com.bumble.appyx.core.node.ParentNode
2121
import com.bumble.appyx.core.plugin.Plugin
2222
import io.element.android.appnav.RootFlowNode
2323
import io.element.android.libraries.architecture.createNode
24-
import io.element.android.libraries.di.ApplicationContext
25-
import io.element.android.libraries.di.DaggerComponentOwner
24+
import io.element.android.libraries.di.DependencyInjectionGraphOwner
25+
import io.element.android.libraries.di.annotations.ApplicationContext
2626
import kotlinx.coroutines.launch
2727
import kotlinx.parcelize.Parcelize
2828

@@ -38,8 +38,8 @@ class MainNode(
3838
buildContext = buildContext,
3939
plugins = plugins,
4040
),
41-
DaggerComponentOwner {
42-
override val daggerComponent = (context as DaggerComponentOwner).daggerComponent
41+
DependencyInjectionGraphOwner {
42+
override val graph = (context as DependencyInjectionGraphOwner).graph
4343

4444
override fun resolve(navTarget: RootNavTarget, buildContext: BuildContext): Node {
4545
return createNode<RootFlowNode>(buildContext = buildContext)

app/src/main/kotlin/io/element/android/x/di/AppBindings.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@
77

88
package io.element.android.x.di
99

10-
import com.squareup.anvil.annotations.ContributesTo
10+
import dev.zacsweers.metro.AppScope
11+
import dev.zacsweers.metro.ContributesTo
1112
import io.element.android.features.api.MigrationEntryPoint
1213
import io.element.android.features.enterprise.api.EnterpriseService
1314
import io.element.android.features.lockscreen.api.LockScreenEntryPoint
1415
import io.element.android.features.lockscreen.api.LockScreenService
1516
import io.element.android.features.rageshake.api.reporter.BugReporter
1617
import io.element.android.libraries.core.meta.BuildMeta
1718
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
18-
import io.element.android.libraries.di.AppScope
1919
import io.element.android.libraries.featureflag.api.FeatureFlagService
2020
import io.element.android.libraries.matrix.api.platform.InitPlatformService
2121
import io.element.android.libraries.matrix.api.tracing.TracingService

app/src/main/kotlin/io/element/android/x/di/AppComponent.kt

Lines changed: 0 additions & 28 deletions
This file was deleted.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2025 New Vector Ltd.
3+
*
4+
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
5+
* Please see LICENSE files in the repository root for full details.
6+
*/
7+
8+
package io.element.android.x.di
9+
10+
import android.content.Context
11+
import dev.zacsweers.metro.AppScope
12+
import dev.zacsweers.metro.DependencyGraph
13+
import dev.zacsweers.metro.Provides
14+
import io.element.android.libraries.architecture.NodeFactoriesBindings
15+
import io.element.android.libraries.di.annotations.ApplicationContext
16+
17+
@DependencyGraph(AppScope::class)
18+
interface AppGraph : NodeFactoriesBindings {
19+
val sessionGraphFactory: SessionGraph.Factory
20+
21+
@DependencyGraph.Factory
22+
interface Factory {
23+
fun create(
24+
@ApplicationContext @Provides
25+
context: Context
26+
): AppGraph
27+
}
28+
}

app/src/main/kotlin/io/element/android/x/di/AppModule.kt

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ import android.content.Context
1111
import android.content.SharedPreferences
1212
import android.content.res.Resources
1313
import androidx.preference.PreferenceManager
14-
import com.squareup.anvil.annotations.ContributesTo
15-
import dagger.Module
16-
import dagger.Provides
14+
import dev.zacsweers.metro.AppScope
15+
import dev.zacsweers.metro.BindingContainer
16+
import dev.zacsweers.metro.ContributesTo
17+
import dev.zacsweers.metro.Provides
18+
import dev.zacsweers.metro.SingleIn
1719
import io.element.android.appconfig.ApplicationConfig
1820
import io.element.android.features.enterprise.api.EnterpriseService
1921
import io.element.android.features.messages.impl.timeline.components.customreaction.DefaultEmojibaseProvider
@@ -23,11 +25,10 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
2325
import io.element.android.libraries.core.meta.BuildMeta
2426
import io.element.android.libraries.core.meta.BuildType
2527
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
26-
import io.element.android.libraries.di.AppScope
27-
import io.element.android.libraries.di.ApplicationContext
28+
import io.element.android.libraries.di.BaseDirectory
2829
import io.element.android.libraries.di.CacheDirectory
29-
import io.element.android.libraries.di.SingleIn
3030
import io.element.android.libraries.di.annotations.AppCoroutineScope
31+
import io.element.android.libraries.di.annotations.ApplicationContext
3132
import io.element.android.x.BuildConfig
3233
import io.element.android.x.R
3334
import kotlinx.coroutines.CoroutineName
@@ -37,10 +38,11 @@ import kotlinx.coroutines.MainScope
3738
import kotlinx.coroutines.plus
3839
import java.io.File
3940

40-
@Module
41+
@BindingContainer
4142
@ContributesTo(AppScope::class)
4243
object AppModule {
4344
@Provides
45+
@BaseDirectory
4446
fun providesBaseDirectory(@ApplicationContext context: Context): File {
4547
return File(context.filesDir, "sessions")
4648
}

0 commit comments

Comments
 (0)