Skip to content

Commit 2c0d047

Browse files
authored
Support using type-safe dependency accessors in ShadowJar.dependencies (#1322)
* Update dependency resolution for types * Update filterProjectDependencies * Update excludeDependency * Try to wrap accessors with `dependency` * Remove the usage of DependencyValueSource * Accept any for project * Update changelog * Note "Using type-safe dependency accessors"
1 parent 85f58bc commit 2c0d047

File tree

8 files changed

+94
-11
lines changed

8 files changed

+94
-11
lines changed

api/shadow.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ public abstract interface class com/github/jengelman/gradle/plugins/shadow/tasks
153153
public abstract fun dependency (Lorg/gradle/api/artifacts/Dependency;)Lorg/gradle/api/specs/Spec;
154154
public abstract fun exclude (Lorg/gradle/api/specs/Spec;)V
155155
public abstract fun include (Lorg/gradle/api/specs/Spec;)V
156+
public abstract fun project (Ljava/lang/Object;)Lorg/gradle/api/specs/Spec;
156157
public abstract fun project (Ljava/lang/String;)Lorg/gradle/api/specs/Spec;
157158
public abstract fun project (Ljava/util/Map;)Lorg/gradle/api/specs/Spec;
158159
public abstract fun resolve (Ljava/util/Collection;)Lorg/gradle/api/file/FileCollection;

docs/changes/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
**Added**
77

88
- Add Kotlin DSL examples in docs. ([#1306](https://github.com/GradleUp/shadow/pull/1306))
9+
- Support using type-safe dependency accessors in `ShadowJar.dependencies`. ([#1322](https://github.com/GradleUp/shadow/pull/1322))
910

1011
**Changed**
1112

docs/configuration/dependencies/README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,44 @@ This same pattern can be used for any of the dependency notation fields.
219219
}
220220
```
221221

222+
### Using type-safe dependency accessors
223+
224+
You can also use type-safe project accessors or version catalog accessors to filter dependencies.
225+
226+
=== "Kotlin"
227+
228+
```kotlin
229+
dependencies {
230+
// Have to declare this dependency in your libs.versions.toml
231+
implementation(libs.log4j.core)
232+
// Have to enable `TYPESAFE_PROJECT_ACCESSORS` flag in your settings.gradle.kts
233+
implementation(projects.api)
234+
}
235+
tasks.shadowJar {
236+
dependencies {
237+
exclude(dependency(libs.log4j.core))
238+
exclude(project(projects.api))
239+
}
240+
}
241+
```
242+
243+
=== "Groovy"
244+
245+
```groovy
246+
dependencies {
247+
// Have to declare this dependency in your libs.versions.toml
248+
implementation libs.log4j.core
249+
// Have to enable `TYPESAFE_PROJECT_ACCESSORS` flag in your settings.gradle
250+
implementation projects.api
251+
}
252+
tasks.named('shadowJar', com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar) {
253+
dependencies {
254+
exclude(dependency(libs.log4j.core))
255+
exclude(project(projects.api))
256+
}
257+
}
258+
```
259+
222260
### Programmatically Selecting Dependencies to Filter
223261

224262
If more complex decisions are needed to select the dependencies to be included, the

src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/BasePluginTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ abstract class BasePluginTest {
141141
buildCache {
142142
$buildCacheBlock
143143
}
144+
enableFeaturePreview 'TYPESAFE_PROJECT_ACCESSORS'
144145
$endBlock
145146
""".trimIndent() + System.lineSeparator()
146147
}

src/functionalTest/kotlin/com/github/jengelman/gradle/plugins/shadow/FilteringTest.kt

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import kotlin.io.path.writeText
88
import org.junit.jupiter.api.BeforeAll
99
import org.junit.jupiter.api.BeforeEach
1010
import org.junit.jupiter.api.Test
11+
import org.junit.jupiter.params.ParameterizedTest
12+
import org.junit.jupiter.params.provider.ValueSource
1113

1214
class FilteringTest : BasePluginTest() {
1315
@BeforeAll
@@ -60,9 +62,10 @@ class FilteringTest : BasePluginTest() {
6062
}
6163
}
6264

63-
@Test
64-
fun excludeDependency() {
65-
dependOnAndExcludeArtifactD()
65+
@ParameterizedTest
66+
@ValueSource(booleans = [false, true])
67+
fun excludeDependency(useAccessor: Boolean) {
68+
dependOnAndExcludeArtifactD(useAccessor)
6669

6770
run(shadowJarTask)
6871

@@ -124,12 +127,14 @@ class FilteringTest : BasePluginTest() {
124127
}
125128
}
126129

127-
@Test
128-
fun filterProjectDependencies() {
130+
@ParameterizedTest
131+
@ValueSource(booleans = [false, true])
132+
fun filterProjectDependencies(useAccessor: Boolean) {
133+
val clientProject = if (useAccessor) "project(projects.client)" else "project(':client')"
129134
writeClientAndServerModules(
130135
serverShadowBlock = """
131136
dependencies {
132-
exclude(project(':client'))
137+
exclude($clientProject)
133138
}
134139
""".trimIndent(),
135140
)
@@ -205,15 +210,25 @@ class FilteringTest : BasePluginTest() {
205210
commonAssertions()
206211
}
207212

208-
private fun dependOnAndExcludeArtifactD() {
213+
private fun dependOnAndExcludeArtifactD(useAccessor: Boolean = false) {
214+
settingsScriptPath.appendText(
215+
"""
216+
dependencyResolutionManagement {
217+
versionCatalogs.create('libs') {
218+
library('my-d', 'my:d:1.0')
219+
}
220+
}
221+
""".trimIndent(),
222+
)
223+
val dependency = if (useAccessor) "libs.my.d" else "'my:d:1.0'"
209224
projectScriptPath.appendText(
210225
"""
211226
dependencies {
212-
implementation 'my:d:1.0'
227+
implementation $dependency
213228
}
214229
$shadowJar {
215230
dependencies {
216-
exclude(dependency('my:d:1.0'))
231+
exclude(dependency($dependency))
217232
}
218233
}
219234
""".trimIndent(),

src/integrationTest/kotlin/com/github/jengelman/gradle/plugins/shadow/snippet/SnippetExecutable.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,13 @@ sealed class SnippetExecutable : Executable {
3434
mavenLocal()
3535
mavenCentral()
3636
}
37+
versionCatalogs.create('libs') {
38+
library('log4j-core', 'org.apache.logging.log4j:log4j-core:2.11.1')
39+
}
3740
}
38-
include 'api', 'main'
41+
include ':api', ':main'
42+
rootProject.name = 'snippet'
43+
enableFeaturePreview 'TYPESAFE_PROJECT_ACCESSORS'
3944
""".trimIndent(),
4045
)
4146
projectRoot.addSubProject("api", pluginsBlock)

src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/internal/AbstractDependencyFilter.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.DependencyFilter
44
import org.gradle.api.Project
55
import org.gradle.api.artifacts.Configuration
66
import org.gradle.api.artifacts.Dependency
7+
import org.gradle.api.artifacts.ProjectDependency
78
import org.gradle.api.artifacts.ResolvedArtifact
89
import org.gradle.api.artifacts.ResolvedDependency
910
import org.gradle.api.file.FileCollection
11+
import org.gradle.api.provider.Provider
1012
import org.gradle.api.specs.Spec
1113

1214
internal sealed class AbstractDependencyFilter(
@@ -43,6 +45,17 @@ internal sealed class AbstractDependencyFilter(
4345
includeSpecs.add(spec)
4446
}
4547

48+
override fun project(notation: Any): Spec<ResolvedDependency> {
49+
@Suppress("UNCHECKED_CAST")
50+
return when (notation) {
51+
is ProjectDependency -> dependency(notation)
52+
is Provider<*> -> project(notation.get() as String)
53+
is String -> project(notation)
54+
is Map<*, *> -> project(notation as Map<String, *>)
55+
else -> error("Unsupported notation type: ${notation::class.java}")
56+
}
57+
}
58+
4659
override fun project(notation: Map<String, *>): Spec<ResolvedDependency> {
4760
return dependency(project.dependencies.project(notation))
4861
}
@@ -52,7 +65,11 @@ internal sealed class AbstractDependencyFilter(
5265
}
5366

5467
override fun dependency(dependencyNotation: Any): Spec<ResolvedDependency> {
55-
return dependency(project.dependencies.create(dependencyNotation))
68+
val realNotation = when (dependencyNotation) {
69+
is Provider<*> -> dependencyNotation.get()
70+
else -> dependencyNotation
71+
}
72+
return dependency(project.dependencies.create(realNotation))
5673
}
5774

5875
override fun dependency(dependency: Dependency): Spec<ResolvedDependency> {

src/main/kotlin/com/github/jengelman/gradle/plugins/shadow/tasks/DependencyFilter.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ public interface DependencyFilter : Serializable {
2929
*/
3030
public fun include(spec: Spec<ResolvedDependency>)
3131

32+
/**
33+
* Create a [Spec] that matches the provided project [notation].
34+
*/
35+
public fun project(notation: Any): Spec<ResolvedDependency>
36+
3237
/**
3338
* Create a [Spec] that matches the provided project [notation].
3439
*/

0 commit comments

Comments
 (0)