Skip to content

Commit b76a71e

Browse files
committed
Start migrating Anvil KSP to Metro
1 parent d4d57b1 commit b76a71e

File tree

703 files changed

+3523
-2820
lines changed

Some content is hidden

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

703 files changed

+3523
-2820
lines changed

.gitmodules

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +0,0 @@
1-
[submodule "enterprise"]
2-
path = enterprise
3-
url = [email protected]:element-hq/element-android-enterprise.git

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: 1 addition & 2 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)
1514
implementation(libs.anvil.compiler.utils)
15+
implementation(libs.metro.runtime)
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: 18 additions & 20 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

@@ -57,9 +56,9 @@ class ContributesNodeProcessor(
5756
if (validSymbols.isEmpty()) return invalidSymbols
5857

5958
for (ksClass in validSymbols) {
60-
if (config.enableLogging) {
59+
// if (config.enableLogging) {
6160
logger.warn("Processing ${ksClass.qualifiedName?.asString()}")
62-
}
61+
// }
6362
generateModule(ksClass)
6463
generateFactory(ksClass)
6564
}
@@ -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/src/main/kotlin/io/element/android/x/ElementXApplication.kt

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

1010
import android.app.Application
1111
import androidx.startup.AppInitializer
12+
import dev.zacsweers.metro.asContribution
13+
import dev.zacsweers.metro.createGraphFactory
1214
import io.element.android.features.cachecleaner.api.CacheCleanerInitializer
1315
import io.element.android.libraries.di.DaggerComponentOwner
1416
import io.element.android.x.di.AppComponent
15-
import io.element.android.x.di.DaggerAppComponent
17+
import io.element.android.x.di.globalGraph
1618
import io.element.android.x.info.logApplicationInfo
1719
import io.element.android.x.initializer.CrashInitializer
1820
import io.element.android.x.initializer.PlatformInitializer
1921

2022
class ElementXApplication : Application(), DaggerComponentOwner {
21-
override val daggerComponent: AppComponent = DaggerAppComponent.factory().create(this)
23+
override val daggerComponent: AppComponent = globalGraph.asContribution<AppComponent.Factory>().create(this)
2224

2325
override fun onCreate() {
2426
super.onCreate()

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ 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
24+
import io.element.android.libraries.di.annotations.ApplicationContext
2525
import io.element.android.libraries.di.DaggerComponentOwner
2626
import kotlinx.coroutines.launch
2727
import kotlinx.parcelize.Parcelize

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.ContributesTo
1111
import io.element.android.features.api.MigrationEntryPoint
1212
import io.element.android.features.enterprise.api.EnterpriseService
1313
import io.element.android.features.lockscreen.api.LockScreenEntryPoint
1414
import io.element.android.features.lockscreen.api.LockScreenService
1515
import io.element.android.features.rageshake.api.reporter.BugReporter
1616
import io.element.android.libraries.core.meta.BuildMeta
1717
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
18-
import io.element.android.libraries.di.AppScope
18+
import dev.zacsweers.metro.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: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2023, 2024 New Vector Ltd.
2+
* Copyright 2025 New Vector Ltd.
33
*
44
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
55
* Please see LICENSE files in the repository root for full details.
@@ -8,20 +8,22 @@
88
package io.element.android.x.di
99

1010
import android.content.Context
11-
import com.squareup.anvil.annotations.MergeComponent
12-
import dagger.BindsInstance
11+
import dev.zacsweers.metro.ContributesTo
12+
import dev.zacsweers.metro.GraphExtension
13+
import dev.zacsweers.metro.Provides
1314
import io.element.android.libraries.architecture.NodeFactoriesBindings
14-
import io.element.android.libraries.di.AppScope
15-
import io.element.android.libraries.di.ApplicationContext
16-
import io.element.android.libraries.di.SingleIn
15+
import dev.zacsweers.metro.AppScope
16+
import io.element.android.libraries.di.annotations.ApplicationContext
1717

18-
@SingleIn(AppScope::class)
19-
@MergeComponent(AppScope::class)
18+
@GraphExtension(AppScope::class)
2019
interface AppComponent : NodeFactoriesBindings {
21-
@MergeComponent.Factory
20+
val sessionComponentFactory: SessionComponent.Factory
21+
22+
@ContributesTo(GlobalScope::class)
23+
@GraphExtension.Factory
2224
interface Factory {
2325
fun create(
24-
@ApplicationContext @BindsInstance
26+
@ApplicationContext @Provides
2527
context: Context
2628
): AppComponent
2729
}

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ 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.BindingContainer
15+
import dev.zacsweers.metro.ContributesTo
16+
import dev.zacsweers.metro.Named
17+
import dev.zacsweers.metro.Provides
1718
import io.element.android.appconfig.ApplicationConfig
1819
import io.element.android.features.enterprise.api.EnterpriseService
1920
import io.element.android.features.messages.impl.timeline.components.customreaction.DefaultEmojibaseProvider
@@ -23,10 +24,10 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
2324
import io.element.android.libraries.core.meta.BuildMeta
2425
import io.element.android.libraries.core.meta.BuildType
2526
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
27+
import dev.zacsweers.metro.AppScope
28+
import io.element.android.libraries.di.annotations.ApplicationContext
2829
import io.element.android.libraries.di.CacheDirectory
29-
import io.element.android.libraries.di.SingleIn
30+
import dev.zacsweers.metro.SingleIn
3031
import io.element.android.libraries.di.annotations.AppCoroutineScope
3132
import io.element.android.x.BuildConfig
3233
import io.element.android.x.R
@@ -37,16 +38,17 @@ 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+
@Named("baseDirectory")
4446
fun providesBaseDirectory(@ApplicationContext context: Context): File {
4547
return File(context.filesDir, "sessions")
4648
}
4749

4850
@Provides
49-
@CacheDirectory
51+
@Named("cacheDirectory")
5052
fun providesCacheDirectory(@ApplicationContext context: Context): File {
5153
return context.cacheDir
5254
}

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

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,19 @@
77

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

10-
import com.squareup.anvil.annotations.ContributesBinding
10+
import dev.zacsweers.metro.ContributesBinding
1111
import io.element.android.appnav.di.RoomComponentFactory
1212
import io.element.android.libraries.di.SessionScope
1313
import io.element.android.libraries.matrix.api.room.JoinedRoom
14-
import javax.inject.Inject
14+
import dev.zacsweers.metro.Inject
1515

1616
@ContributesBinding(SessionScope::class)
17-
class DefaultRoomComponentFactory @Inject constructor(
18-
private val roomComponentBuilder: RoomComponent.Builder
17+
@Inject
18+
class DefaultRoomComponentFactory(
19+
private val sessionComponent: SessionComponent,
1920
) : RoomComponentFactory {
2021
override fun create(room: JoinedRoom): Any {
21-
return roomComponentBuilder
22-
.joinedRoom(room)
23-
.baseRoom(room)
24-
.build()
22+
return sessionComponent.roomComponentFactory
23+
.create(room, room)
2524
}
2625
}

0 commit comments

Comments
 (0)