Skip to content

Commit c840f8e

Browse files
authored
Support direct graph extension accessors (#920)
1 parent db3582d commit c840f8e

20 files changed

Lines changed: 430 additions & 94 deletions

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ interface LoggedInGraph {
7575
interface AppGraph : LoggedInGraph.Factory
7676
```
7777

78-
- Contribute the factory to the parent graph via ContributesGraphExtension.
78+
- Contribute the factory to the parent graph via `@ContributesGraphExtension`.
7979

8080
```kotlin
81-
@GraphExtension
81+
@ContributesGraphExtension(LoggedInScope::class)
8282
interface LoggedInGraph {
8383
@ContributesGraphExtension.Factory(AppScope::class)
8484
interface Factory {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
@GraphExtension
2+
interface LoggedInGraph {
3+
val int: Int
4+
}
5+
6+
@DependencyGraph
7+
interface AppGraph {
8+
@Provides fun provideInt(): Int = 3
9+
10+
fun loggedInGraph(): LoggedInGraph
11+
12+
val loggedInGraphProp: LoggedInGraph
13+
}
14+
15+
fun box(): String {
16+
val graph = createGraph<AppGraph>()
17+
assertEquals(3, graph.loggedInGraph().int)
18+
assertEquals(3, graph.loggedInGraphProp.int)
19+
return "OK"
20+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
abstract class LoggedInScope
2+
3+
@GraphExtension
4+
@SingleIn(LoggedInScope::class)
5+
interface LoggedInGraph {
6+
val int: Int
7+
}
8+
9+
@DependencyGraph
10+
interface AppGraph {
11+
@Provides fun provideInt(): Int = 3
12+
13+
fun loggedInGraph(): LoggedInGraph
14+
val loggedInGraphProp: LoggedInGraph
15+
}
16+
17+
fun box(): String {
18+
val graph = createGraph<AppGraph>()
19+
val loggedInGraph = graph.loggedInGraph()
20+
assertEquals(3, loggedInGraph.int)
21+
assertSame(loggedInGraph, graph.loggedInGraph())
22+
assertSame(graph.loggedInGraphProp, graph.loggedInGraph())
23+
return "OK"
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/ExtensionAccessorsCannotHaveParameters.kt:(294,300): error: Graph extension accessors may not have parameters. Use `@GraphExtension.Factory` instead.
2+
3+
/ExtensionAccessorsCannotHaveParameters.kt:(308,314): error: Graph extension accessors may not have parameters. Use `@GraphExtension.Factory` instead.
4+
5+
/ExtensionAccessorsCannotHaveParameters.kt:(343,349): error: Graph extension accessors may not have extension receivers. Use `@GraphExtension.Factory` instead.
6+
7+
/ExtensionAccessorsCannotHaveParameters.kt:(391,408): error: The feature "context parameters" is experimental and should be enabled explicitly. This can be done by supplying the compiler argument '-Xcontext-parameters', but note that no stability guarantees are provided.
8+
9+
/ExtensionAccessorsCannotHaveParameters.kt:(399,402): error: Graph extension accessors may not have context parameters.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// RENDER_DIAGNOSTICS_FULL_TEXT
2+
@GraphExtension
3+
interface LoggedInGraph {
4+
val int: Int
5+
}
6+
7+
@DependencyGraph
8+
interface AppGraph {
9+
@Provides fun provideInt(): Int = 3
10+
11+
// Legal
12+
fun loggedInGraphFactory(): LoggedInGraph
13+
14+
// Illegal
15+
fun loggedInGraphFactory(<!DEPENDENCY_GRAPH_ERROR!>param1<!>: Long, <!DEPENDENCY_GRAPH_ERROR!>param2<!>: Int): LoggedInGraph
16+
17+
fun <!DEPENDENCY_GRAPH_ERROR!>String<!>.loggedInGraphFactory(): LoggedInGraph
18+
19+
<!UNSUPPORTED_FEATURE!>context(<!DEPENDENCY_GRAPH_ERROR!>int<!>: Int)<!>
20+
fun loggedInGraphFactory(): LoggedInGraph
21+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/ExtensionsWithFactoriesMustUseThem.kt:(389,402): error: Graph extension 'LoggedInGraph' has a creator type 'LoggedInGraph.Factory' that must be used to create its instances. Either make 'AppGraph' implement 'LoggedInGraph.Factory' or expose an accessor for 'LoggedInGraph.Factory' instead of 'LoggedInGraph' directly.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RENDER_DIAGNOSTICS_FULL_TEXT
2+
@GraphExtension
3+
interface LoggedInGraph {
4+
val int: Int
5+
6+
@GraphExtension.Factory
7+
interface Factory {
8+
fun create(): LoggedInGraph
9+
}
10+
}
11+
12+
@DependencyGraph
13+
interface AppGraph : LoggedInGraph.Factory {
14+
@Provides fun provideInt(): Int = 3
15+
16+
// Illegal even though AppGraph implements _a_ factory, just not this one
17+
fun <!DEPENDENCY_GRAPH_ERROR!>loggedInGraph<!>(): LoggedInGraph
18+
19+
// Legal
20+
fun loggedInGraphFactory(): LoggedInGraph.Factory
21+
22+
override fun create(): LoggedInGraph
23+
}

compiler-tests/src/test/data/dump/ir/dependencygraph/UnusedScopedConstructorInjectedClassWithConstructorAnnotatedIsDiscovered.fir.kt.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@ interface ExampleGraph : $$MetroContributionToAppScope {
113113
class LoggedInGraphImpl : LoggedInGraph {
114114
private /* final field */ val exampleGraphInstance: $$MetroGraph = $$MetroGraph
115115
private /* final field */ val exampleGraphInstanceProvider: Provider<$$MetroGraph> = Companion.invoke<$$MetroGraph>(value = $$MetroGraph)
116-
private /* final field */ val dependencyProvider: Provider<Dependency> = <this>.#exampleGraphInstance.accessor_kKldZjk_provider()
116+
private /* final field */ val dependencyProvider: Provider<Dependency> = provider<Dependency>(provider = local fun <anonymous>(): Dependency {
117+
return <this>.#exampleGraphInstance.accessor_kKldZjk_provider().invoke()
118+
}
119+
)
117120
private /* final field */ val childDependencyProvider: Provider<ChildDependency> = Companion.provider<Provider<ChildDependency>, ChildDependency>(delegate = Companion.create(dep = <this>.#dependencyProvider))
118121
constructor($$MetroGraph: $$MetroGraph) /* primary */ {
119122
super/*Any*/()

compiler-tests/src/test/java/dev/zacsweers/metro/compiler/BoxTestGenerated.java

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler-tests/src/test/java/dev/zacsweers/metro/compiler/DiagnosticTestGenerated.java

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)