Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
45c3abc
[BOOK-382] chore: metro ์˜์กด์„ฑ ์ถ”๊ฐ€
easyhooon Nov 10, 2025
265ed6b
[BOOK-434] refactor: feature ๋ชจ๋“ˆ metro migration
easyhooon Nov 10, 2025
457d2d9
[BOOK-434] refactor: repository ๋ชจ๋“ˆ metro migration
easyhooon Nov 10, 2025
1f6c226
[BOOK-434] refactor: Hilt -> Metro WIP
easyhooon Nov 11, 2025
80231ec
[BOOK-434] refactor: @Inject -> @AssistedInject
easyhooon Nov 11, 2025
869e8db
[BOOK-434] refactor: DataGraph AppGraph ์ฑ…์ž„ ๋ถ„๋ฆฌ
easyhooon Nov 11, 2025
d128622
[BOOK-434] refactor: @Provides -> @Binds
easyhooon Nov 11, 2025
5273273
[BOOK-434] feat: UnavailableContent ๊ตฌ์„ฑ
easyhooon Nov 12, 2025
238d1ac
[BOOK-434] refactor: CircuitGraph AppGraph ์—์„œ ๋ถ„๋ฆฌ
easyhooon Nov 12, 2025
50da68a
[BOOK-434] chore: CrossFadeNavDecoratorFactory ์ฃผ์ž… ๋ฐฉ์‹ ์›๋ณต
easyhooon Nov 12, 2025
e8af5fa
[BOOK-434] chore: annotation ์ˆœ์„œ ๋ณ€๊ฒฝ
easyhooon Nov 12, 2025
69a57b1
[BOOK-434] fix: build problem WIP
easyhooon Nov 13, 2025
7083ee8
[BOOK-434] fix: ApplicationContext ์ฃผ์ž… ๋ฐฉ์‹ ๋ณ€๊ฒฝ
easyhooon Nov 14, 2025
3704bdc
[BOOK-434] chore: metro version update
easyhooon Nov 18, 2025
8f2b542
[BOOK-434] chore: hilt ์˜์กด์„ฑ ์ œ๊ฑฐ
easyhooon Nov 19, 2025
a579a3f
[BOOK-434] chore: metro plugin ์ง์ ‘ ์ฃผ์ž… ๋ฐฉ์‹์œผ๋กœ ๋ณ€๊ฒฝ
easyhooon Nov 19, 2025
ea31299
[BOOK-434] chore: ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋ฒ„์ „ ์ตœ์‹ ํ™”
easyhooon Nov 19, 2025
61fe0a9
Merge branch 'develop' into BOOK-434-refactor/#222
easyhooon Nov 20, 2025
0970f3e
[BOOK-434] chore: metro version upgrade
easyhooon Nov 20, 2025
419ce1a
[BOOK-434] fix: Build Error
easyhooon Nov 20, 2025
f538d44
[BOOK-434] fix: Runtime Build
easyhooon Nov 20, 2025
e998355
[BOOK-434] chore: code style check success
easyhooon Nov 21, 2025
819c4b5
[BOOK-434] fix: stability.config.conf ํŒŒ์ผ ์ƒ์„ฑ ๋ฐ ๋ฃจํŠธ ํ”„๋กœ์ ํŠธ ์œ„์น˜๋ฅผ ๋ฐ”๋ผ๋ณด๋„๋ก ์ˆ˜์ •
easyhooon Nov 21, 2025
9b83728
[BOOK-434] chore: .stability ํŒŒ์ผ ์ตœ์‹ ํ™”
easyhooon Nov 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@

- [Circuit](https://github.com/slackhq/circuit)
- ~~Google ML Kit~~ Google Cloud Vision
- Dagger Hilt
- ~~Dagger Hilt~~ Metro
- Retrofit, OkHttp3
- Lottie-Compose
- Firebase(Analytics, Crashlytics, Remote Config)
Expand Down
10 changes: 7 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
@file:Suppress("INLINE_FROM_HIGHER_PLATFORM")

import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import com.google.devtools.ksp.gradle.KspExtension
import org.gradle.kotlin.dsl.configure
import java.util.Properties

plugins {
alias(libs.plugins.booket.android.application)
alias(libs.plugins.booket.android.application.compose)
alias(libs.plugins.booket.android.hilt)
alias(libs.plugins.booket.android.firebase)
alias(libs.plugins.metro)
alias(libs.plugins.ksp)
}

android {
Expand Down Expand Up @@ -63,8 +66,8 @@ composeStabilityAnalyzer {
enabled.set(true)
}

ksp {
arg("circuit.codegen.mode", "hilt")
extensions.configure<KspExtension> {
arg("circuit.codegen.mode", "metro")
}

dependencies {
Expand All @@ -75,6 +78,7 @@ dependencies {
projects.core.datastore.api,
projects.core.datastore.impl,
projects.core.designsystem,
projects.core.di,
projects.core.model,
projects.core.network,
projects.core.ui,
Expand Down
4 changes: 3 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

<application
android:name=".BooketApplication"
android:appComponentFactory="com.ninecraft.booket.di.MetroAppComponentFactory"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
Expand All @@ -21,7 +22,8 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Booket"
tools:targetApi="31">
tools:targetApi="31"
tools:replace="android:appComponentFactory">

<provider
android:name="androidx.startup.InitializationProvider"
Expand Down
7 changes: 5 additions & 2 deletions app/src/main/kotlin/com/ninecraft/booket/BooketApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ import coil.ImageLoader
import coil.ImageLoaderFactory
import coil.disk.DiskCache
import coil.util.DebugLogger
import dagger.hilt.android.HiltAndroidApp
import com.ninecraft.booket.di.AppGraph
import dev.zacsweers.metro.createGraphFactory

@HiltAndroidApp
class BooketApplication : Application(), ImageLoaderFactory {

val appGraph by lazy { createGraphFactory<AppGraph.Factory>().create(this) }

override fun newImageLoader(): ImageLoader {
return ImageLoader.Builder(this)
.diskCache {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.ninecraft.booket
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationCompat
Expand All @@ -11,20 +12,24 @@ import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import com.ninecraft.booket.core.data.api.repository.UserRepository
import com.ninecraft.booket.core.designsystem.R
import com.ninecraft.booket.core.di.ServiceKey
import com.ninecraft.booket.feature.main.MainActivity
import dagger.hilt.android.AndroidEntryPoint
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesIntoMap
import dev.zacsweers.metro.Inject
import dev.zacsweers.metro.binding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import javax.inject.Inject

@AndroidEntryPoint
class ReedFirebaseMessagingService : FirebaseMessagingService() {

@Inject
lateinit var userRepository: UserRepository
@ContributesIntoMap(AppScope::class, binding = binding<Service>())
@ServiceKey(ReedFirebaseMessagingService::class)
@Inject
class ReedFirebaseMessagingService(
private val userRepository: UserRepository,
) : FirebaseMessagingService() {

private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())

Expand Down
31 changes: 31 additions & 0 deletions app/src/main/kotlin/com/ninecraft/booket/di/AppGraph.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.ninecraft.booket.di

import android.app.Activity
import android.app.Service
import android.content.Context
import com.ninecraft.booket.core.di.ApplicationContext
import com.ninecraft.booket.core.di.DataScope
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.DependencyGraph
import dev.zacsweers.metro.Multibinds
import dev.zacsweers.metro.Provider
import dev.zacsweers.metro.Provides
import kotlin.reflect.KClass

@DependencyGraph(
scope = AppScope::class,
additionalScopes = [DataScope::class],
)
interface AppGraph {

@Multibinds(allowEmpty = true)
val activityProviders: Map<KClass<out Activity>, Provider<Activity>>

@Multibinds(allowEmpty = true)
val serviceProviders: Map<KClass<out Service>, Provider<Service>>

@DependencyGraph.Factory
fun interface Factory {
fun create(@ApplicationContext @Provides context: Context): AppGraph
}
}
52 changes: 52 additions & 0 deletions app/src/main/kotlin/com/ninecraft/booket/di/CircuitGraph.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.ninecraft.booket.di

import androidx.compose.foundation.background
import androidx.compose.foundation.text.BasicText
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle
import com.slack.circuit.foundation.Circuit
import com.slack.circuit.foundation.LocalCircuit
import com.slack.circuit.runtime.Navigator
import com.slack.circuit.runtime.presenter.Presenter
import com.slack.circuit.runtime.ui.Ui
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesTo
import dev.zacsweers.metro.Multibinds
import dev.zacsweers.metro.Provides

@ContributesTo(AppScope::class)
interface CircuitGraph {

@Multibinds(allowEmpty = true)
fun presenterFactories(): Set<Presenter.Factory>

@Multibinds(allowEmpty = true)
fun uiFactories(): Set<Ui.Factory>

@Provides
fun provideCircuit(
presenterFactories: Set<Presenter.Factory>,
uiFactories: Set<Ui.Factory>,
): Circuit {
return Circuit.Builder()
.addPresenterFactories(presenterFactories)
.addUiFactories(uiFactories)
.setAnimatedNavDecoratorFactory(CrossFadeNavDecoratorFactory())
.setOnUnavailableContent { screen, modifier ->
val circuit = LocalCircuit.current
BasicText(
text = """
Route not available: ${screen.javaClass.name}.
Presenter: ${circuit?.presenter(screen, Navigator.NoOp)?.javaClass}
UI: ${circuit?.ui(screen)?.javaClass}
All presenterFactories: ${circuit?.newBuilder()?.presenterFactories}
All uiFactories: ${circuit?.newBuilder()?.uiFactories}
"""
.trimIndent(),
modifier = modifier.background(Color.Red),
style = TextStyle(color = Color.Yellow),
)
}
.build()
}
}
34 changes: 0 additions & 34 deletions app/src/main/kotlin/com/ninecraft/booket/di/CircuitModule.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.ninecraft.booket.di

import android.app.Activity
import android.app.Application
import android.app.Service
import android.content.Intent
import androidx.annotation.Keep
import androidx.core.app.AppComponentFactory
import com.ninecraft.booket.BooketApplication
import dev.zacsweers.metro.Provider
import kotlin.reflect.KClass

/**
* AppComponentFactory that uses Metro for constructor injection of Activities and Services.
*
* Requires minSdk 28+. For lower versions, use manual graph access.
*/
@Keep
class MetroAppComponentFactory : AppComponentFactory() {

private inline fun <reified T : Any> getInstance(
cl: ClassLoader,
className: String,
providers: Map<KClass<out T>, Provider<T>>,
): T? {
val clazz = Class.forName(className, false, cl).asSubclass(T::class.java)
val modelProvider = providers[clazz.kotlin] ?: return null
return modelProvider()
}

override fun instantiateActivityCompat(
cl: ClassLoader,
className: String,
intent: Intent?,
): Activity {
return getInstance(cl, className, activityProviders)
?: super.instantiateActivityCompat(cl, className, intent)
}
Comment on lines +31 to +38
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

โš ๏ธ Potential issue | ๐Ÿ”ด Critical

lateinit ๋ณ€์ˆ˜ ์ ‘๊ทผ ์‹œ ์ดˆ๊ธฐํ™” ์ˆœ์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

activityProviders๋Š” instantiateApplicationCompat์—์„œ ์ดˆ๊ธฐํ™”๋˜์ง€๋งŒ, Activity๊ฐ€ Application๋ณด๋‹ค ๋จผ์ € ์ƒ์„ฑ๋˜๋Š” ๊ฒฝ์šฐ UninitializedPropertyAccessException์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์ดˆ๊ธฐํ™” ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๊ฑฐ๋‚˜ nullable ํƒ€์ž…์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•˜์„ธ์š”.

๋‹ค์Œ diff๋ฅผ ์ ์šฉํ•˜์—ฌ ์ดˆ๊ธฐํ™” ์ฒดํฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

     override fun instantiateActivityCompat(
         cl: ClassLoader,
         className: String,
         intent: Intent?,
     ): Activity {
-        return getInstance(cl, className, activityProviders)
+        return if (::activityProviders.isInitialized) {
+            getInstance(cl, className, activityProviders)
+        } else {
+            null
+        }
             ?: super.instantiateActivityCompat(cl, className, intent)
     }
๐Ÿ“ Committable suggestion

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
override fun instantiateActivityCompat(
cl: ClassLoader,
className: String,
intent: Intent?,
): Activity {
return getInstance(cl, className, activityProviders)
?: super.instantiateActivityCompat(cl, className, intent)
}
override fun instantiateActivityCompat(
cl: ClassLoader,
className: String,
intent: Intent?,
): Activity {
return if (::activityProviders.isInitialized) {
getInstance(cl, className, activityProviders)
} else {
null
}
?: super.instantiateActivityCompat(cl, className, intent)
}
๐Ÿค– Prompt for AI Agents
In app/src/main/kotlin/com/ninecraft/booket/di/MetroAppComponentFactory.kt
around lines 31 to 38, accessing the lateinit activityProviders in
instantiateActivityCompat can throw UninitializedPropertyAccessException if an
Activity is created before instantiateApplicationCompat initializes it; change
the code to guard access by either checking initialization
(::activityProviders.isInitialized) before using it or make activityProviders
nullable and use a safe-call (activityProviders?.let { ... } ?:
super.instantiateActivityCompat(...)) so you only use activityProviders when
initialized and otherwise fall back to the super implementation.


override fun instantiateServiceCompat(
cl: ClassLoader,
className: String,
intent: Intent?,
): Service {
return getInstance(cl, className, serviceProviders)
?: super.instantiateServiceCompat(cl, className, intent)
}
Comment on lines +40 to +47
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

โš ๏ธ Potential issue | ๐Ÿ”ด Critical

lateinit ๋ณ€์ˆ˜ ์ ‘๊ทผ ์‹œ ์ดˆ๊ธฐํ™” ์ˆœ์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

serviceProviders๋„ ๋™์ผํ•œ ์ดˆ๊ธฐํ™” ์ˆœ์„œ ๋ฌธ์ œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. Activity์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ์ดˆ๊ธฐํ™” ์ฒดํฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ diff๋ฅผ ์ ์šฉํ•˜์„ธ์š”:

     override fun instantiateServiceCompat(
         cl: ClassLoader,
         className: String,
         intent: Intent?,
     ): Service {
-        return getInstance(cl, className, serviceProviders)
+        return if (::serviceProviders.isInitialized) {
+            getInstance(cl, className, serviceProviders)
+        } else {
+            null
+        }
             ?: super.instantiateServiceCompat(cl, className, intent)
     }
๐Ÿค– Prompt for AI Agents
In app/src/main/kotlin/com/ninecraft/booket/di/MetroAppComponentFactory.kt
around lines 40 to 47, accessing the lateinit serviceProviders can lead to
initialization-order crashes; add the same initialization check used for
Activity providers before using it. Modify instantiateServiceCompat to verify
::serviceProviders.isInitialized (or a safe null/initialized guard) and only
call getInstance when initialized, otherwise fall back to
super.instantiateServiceCompat; ensure no direct access to the lateinit property
without the guard to avoid UninitializedPropertyAccessException.


override fun instantiateApplicationCompat(cl: ClassLoader, className: String): Application {
val app = super.instantiateApplicationCompat(cl, className)
val appGraph = (app as BooketApplication).appGraph
activityProviders = appGraph.activityProviders
serviceProviders = appGraph.serviceProviders
return app
}
Comment on lines +49 to +55
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

โš ๏ธ Potential issue | ๐Ÿ”ด Critical

ํƒ€์ž… ์บ์ŠคํŒ…๊ณผ thread safety ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  1. Line 51์˜ unsafe cast: BooketApplication์œผ๋กœ์˜ ์บ์ŠคํŒ…์ด ์‹คํŒจํ•˜๋ฉด ClassCastException์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.
  2. Thread safety: companion object์˜ lateinit var์— ๋Œ€ํ•œ ๋™์‹œ ํ• ๋‹น์ด ๋™๊ธฐํ™”๋˜์ง€ ์•Š์•„ race condition์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ diff๋ฅผ ์ ์šฉํ•˜์—ฌ ์•ˆ์ „์„ฑ์„ ๊ฐœ์„ ํ•˜์„ธ์š”:

     override fun instantiateApplicationCompat(cl: ClassLoader, className: String): Application {
         val app = super.instantiateApplicationCompat(cl, className)
-        val appGraph = (app as BooketApplication).appGraph
-        activityProviders = appGraph.activityProviders
-        serviceProviders = appGraph.serviceProviders
+        if (app is BooketApplication) {
+            synchronized(this) {
+                if (!::activityProviders.isInitialized) {
+                    val appGraph = app.appGraph
+                    activityProviders = appGraph.activityProviders
+                    serviceProviders = appGraph.serviceProviders
+                }
+            }
+        }
         return app
     }
๐Ÿ“ Committable suggestion

โ€ผ๏ธ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
override fun instantiateApplicationCompat(cl: ClassLoader, className: String): Application {
val app = super.instantiateApplicationCompat(cl, className)
val appGraph = (app as BooketApplication).appGraph
activityProviders = appGraph.activityProviders
serviceProviders = appGraph.serviceProviders
return app
}
override fun instantiateApplicationCompat(cl: ClassLoader, className: String): Application {
val app = super.instantiateApplicationCompat(cl, className)
if (app is BooketApplication) {
synchronized(this) {
if (!::activityProviders.isInitialized) {
val appGraph = app.appGraph
activityProviders = appGraph.activityProviders
serviceProviders = appGraph.serviceProviders
}
}
}
return app
}


companion object {
private lateinit var activityProviders: Map<KClass<out Activity>, Provider<Activity>>
private lateinit var serviceProviders: Map<KClass<out Service>, Provider<Service>>
}
}
2 changes: 1 addition & 1 deletion build-logic/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ dependencies {
compileOnly(libs.android.gradle.plugin)
compileOnly(libs.kotlin.gradle.plugin)
compileOnly(libs.compose.compiler.gradle.plugin)
compileOnly(libs.ksp.gradle.plugin)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

โš ๏ธ Potential issue | ๐Ÿ”ด Critical

๐Ÿงฉ Analysis chain

Metro ๋ฐ KSP ๋ฒ„์ „ ํ˜ธํ™˜์„ฑ์„ ํ™•์ธํ•˜์„ธ์š”.

KSP ํ”Œ๋Ÿฌ๊ทธ์ธ ์˜์กด์„ฑ์ด ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. Metro DI ํ”„๋ ˆ์ž„์›Œํฌ๋กœ์˜ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์— ํ•„์š”ํ•œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด์ง€๋งŒ, ์‚ฌ์šฉ ์ค‘์ธ Metro ๋ฐ KSP ๋ฒ„์ „์ด ์„œ๋กœ ํ˜ธํ™˜๋˜๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๋ฒ„์ „ ์ •๋ณด๋ฅผ ํ™•์ธํ•˜์„ธ์š”:

๋˜ํ•œ ์ตœ์‹  Metro ๋ฌธ์„œ๋ฅผ ํ™•์ธํ•˜์—ฌ ๊ถŒ์žฅ KSP ๋ฒ„์ „์„ ํ™•์ธํ•˜์„ธ์š”:


๐Ÿ Script executed:

#!/bin/bash
# Description: Metro์™€ KSP ๋ฒ„์ „ ํ™•์ธ

# Metro ๋ฒ„์ „ ํ™•์ธ
echo "=== Metro ๋ฒ„์ „ ==="
rg -n "metro.*=.*\"" gradle/libs.versions.toml

# KSP ๋ฒ„์ „ ํ™•์ธ  
echo "=== KSP ๋ฒ„์ „ ==="
rg -n "ksp.*=.*\"" gradle/libs.versions.toml

# Metro plugin ์‚ฌ์šฉ ํ™•์ธ
echo "=== Metro plugin ์‚ฌ์šฉ ==="
rg -n "alias\(libs\.plugins\.metro\)" --type kotlin

Length of output: 949


๐ŸŒ Web query:

What is the recommended KSP version for Metro DI library?

๐Ÿ’ก Result:

Use KSP 2.2.20-2.0.3. [1][2]

Sources:
[1] Metro installation example showing ksp-version = "2.2.20-2.0.3". [2] Metro compatibility notes (Kotlin 2.2.0 / Metro 0.4.0+).


KSP ๋ฒ„์ „์ด Metro์™€ ํ˜ธํ™˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ”„๋กœ์ ํŠธ๋Š” KSP 2.3.0์„ ์‚ฌ์šฉ ์ค‘์ด์ง€๋งŒ, Metro 0.7.7์€ KSP 2.2.20-2.0.3์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. KSP 2.3.0์€ ๊ถŒ์žฅ ๋ฒ„์ „๋ณด๋‹ค ์ตœ์‹ ์ด๋ฏ€๋กœ Metro์™€์˜ ํ˜ธํ™˜์„ฑ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. gradle/libs.versions.toml์˜ KSP ๋ฒ„์ „์„ ๊ถŒ์žฅ ๋ฒ„์ „์œผ๋กœ ๋ณ€๊ฒฝํ•˜์„ธ์š”.

ksp = "2.2.20-2.0.3"
๐Ÿค– Prompt for AI Agents
In build-logic/build.gradle.kts around line 12, the project pins KSP to a newer,
incompatible version via compileOnly(libs.ksp.gradle.plugin); update the KSP
entry in gradle/libs.versions.toml to the Metro-recommended value ksp =
"2.2.20-2.0.3" so libs.ksp.gradle.plugin resolves to that compatible version,
then refresh Gradle (or run ./gradlew --refresh-dependencies and a build) to
verify the plugin now uses the updated KSP version.

implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
}

Expand All @@ -20,7 +21,6 @@ gradlePlugin {
"android.library.compose" to "AndroidLibraryComposeConventionPlugin",
"android.feature" to "AndroidFeatureConventionPlugin",
"android.firebase" to "AndroidFirebaseConventionPlugin",
"android.hilt" to "AndroidHiltConventionPlugin",
"android.retrofit" to "AndroidRetrofitConventionPlugin",
"jvm.library" to "JvmLibraryConventionPlugin",
"kotlin.library.serialization" to "KotlinLibrarySerializationConventionPlugin",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@

import com.google.devtools.ksp.gradle.KspExtension
import com.ninecraft.booket.convention.api
import com.ninecraft.booket.convention.applyPlugins
import com.ninecraft.booket.convention.implementation
Expand All @@ -7,6 +8,7 @@ import com.ninecraft.booket.convention.libs
import com.ninecraft.booket.convention.project
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.dependencies

internal class AndroidFeatureConventionPlugin : Plugin<Project> {
Expand All @@ -15,9 +17,14 @@ internal class AndroidFeatureConventionPlugin : Plugin<Project> {
applyPlugins(
"booket.android.library",
"booket.android.library.compose",
"booket.android.hilt",
"dev.zacsweers.metro",
"com.google.devtools.ksp",
)

extensions.configure<KspExtension> {
arg("circuit.codegen.mode", "metro")
}

dependencies {
implementation(project(path = ":core:common"))
implementation(project(path = ":core:data:api"))
Expand Down
24 changes: 0 additions & 24 deletions build-logic/src/main/kotlin/AndroidHiltConventionPlugin.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ internal fun Project.configureCompose(
reportsDestination.file("build/composeReports")

stabilityConfigurationFiles.addAll(
project.layout.projectDirectory.file("stability.config.conf"),
project.rootProject.layout.projectDirectory.file("stability.config.conf"),
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ object Plugins {
const val ANDROID_LIBRARY = "com.android.library"

const val COMPOSE_STABILITY_ANALYZER = "com.github.skydoves.compose.stability.analyzer"

const val HILT = "dagger.hilt.android.plugin"
const val METRO = "dev.zacsweers.metro"
const val KSP = "com.google.devtools.ksp"
const val GOOGLE_SERVICES = "com.google.gms.google-services"
const val FIREBASE_CRASHLYTICS = "com.google.firebase.crashlytics"
Expand Down
Loading
Loading