Skip to content

Commit b8acd28

Browse files
authored
[Filtering] Add support for filtering packages like Maven plugin (#53)
This adds package filters similar to how the Maven plugin filters in its `<packages>` block. This supports ant-like patterns similar to how patterns filter. Partial implementation of #16.
1 parent 73a391b commit b8acd28

File tree

7 files changed

+669
-16
lines changed

7 files changed

+669
-16
lines changed

README.md

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,29 @@ sourceSets {
201201
}
202202
```
203203

204+
#### packages - `JavaPackageNamePatternFilterable`
205+
206+
Default: All packages
207+
208+
Package filters can be used to include, or exclude individual or groups of packages to be generated. These filters use a
209+
similar pattern to `include`/`exclude` with `SourceSet`.
210+
211+
```groovy
212+
sourceSets {
213+
main {
214+
assertJ {
215+
packages {
216+
include "org.example**" // include *all* packages in `org.example`
217+
exclude "org.example.foo" // exclude `org.example.foo` specifically
218+
}
219+
}
220+
}
221+
}
222+
```
223+
224+
See [`PackageFilter` tests](src/test/groovy/org/assertj/generator/gradle/parameter/PackageFilter.groovy) for more
225+
examples.
226+
204227
#### entryPoints - `EntryPointsGeneratorOptions`
205228

206229
Default: Only generate "standard" assertion entrypoint
@@ -238,25 +261,25 @@ A useful trick to turn on _only_ a set of values is to just set the `entryPoints
238261

239262
```groovy
240263
sourceSets {
241-
main {
242-
assertJ {
243-
entryPoints = ['BDD', 'JUNIT_SOFT'] // turn on _only_ BDD and JUnit Soft
244-
}
264+
main {
265+
assertJ {
266+
entryPoints = ['BDD', 'JUNIT_SOFT'] // turn on _only_ BDD and JUnit Soft
245267
}
268+
}
246269
}
247270
```
248271

249272
Or within the `entryPoints` closure:
250273

251274
```groovy
252275
sourceSets {
253-
main {
254-
assertJ {
255-
entryPoints {
256-
only 'BDD', 'JUNIT_SOFT' // turn on _only_ BDD and JUnit Soft
257-
}
258-
}
276+
main {
277+
assertJ {
278+
entryPoints {
279+
only 'BDD', 'JUNIT_SOFT' // turn on _only_ BDD and JUnit Soft
280+
}
259281
}
282+
}
260283
}
261284
```
262285

src/main/kotlin/org/assertj/generator/gradle/tasks/AssertJGenerationTask.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import org.assertj.assertions.generator.description.converter.ClassToClassDescri
2020
import org.assertj.assertions.generator.util.ClassUtil
2121
import org.assertj.generator.gradle.tasks.config.AssertJGeneratorExtension
2222
import org.assertj.generator.gradle.tasks.config.SerializedTemplate
23+
import org.assertj.generator.gradle.tasks.config.patterns.JavaPackageNamePatternFilterable
2324
import org.gradle.api.DefaultTask
2425
import org.gradle.api.file.ConfigurableFileCollection
2526
import org.gradle.api.file.DirectoryProperty
@@ -77,10 +78,13 @@ open class AssertJGenerationTask @Inject internal constructor(
7778
val outputDir: DirectoryProperty
7879

7980
@get:Input
80-
internal val skip: Property<Boolean> = objects.property<Boolean>()
81+
internal val skip: Property<Boolean> = objects.property()
8182

8283
@get:Input
83-
internal val hierarchical: Property<Boolean> = objects.property<Boolean>()
84+
internal val hierarchical: Property<Boolean> = objects.property()
85+
86+
@get:Input
87+
internal val packagesFilterable: Property<JavaPackageNamePatternFilterable> = objects.property()
8488

8589
@get:Input
8690
internal val entryPoints: SetProperty<AssertionsEntryPointType> = objects.setProperty()
@@ -110,6 +114,7 @@ open class AssertJGenerationTask @Inject internal constructor(
110114

111115
skip.set(project.provider { assertJOptions.skip })
112116
hierarchical.set(project.provider { assertJOptions.hierarchical })
117+
packagesFilterable.set(project.provider { assertJOptions.packages })
113118
entryPoints.set(project.provider { assertJOptions.entryPoints.entryPoints })
114119
entryPointsClassPackage.set(project.provider { assertJOptions.entryPoints.classPackage })
115120
}
@@ -125,7 +130,9 @@ open class AssertJGenerationTask @Inject internal constructor(
125130

126131
val classLoader = URLClassLoader((generationClasspath + classDirectories).map { it.toURI().toURL() }.toTypedArray())
127132

133+
val packagesPredicate = packagesFilterable.get().asPredicate()
128134
val allClassNames = getClassNames(classDirectories)
135+
.filter { packagesPredicate.test(it.substringBeforeLast('.')) }
129136

130137
@Suppress("SpreadOperator") // Java interop
131138
val allClasses = ClassUtil.collectClasses(

src/main/kotlin/org/assertj/generator/gradle/tasks/config/AssertJGeneratorExtension.kt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
package org.assertj.generator.gradle.tasks.config
1414

1515
import org.assertj.assertions.generator.AssertionsEntryPointType
16+
import org.assertj.generator.gradle.tasks.config.patterns.JavaPackageNamePatternFilterable
1617
import org.gradle.api.Action
1718
import org.gradle.api.Project
1819
import org.gradle.api.file.DirectoryProperty
@@ -34,6 +35,12 @@ open class AssertJGeneratorExtension @Inject internal constructor(
3435
val classDirectories: SourceDirectorySet =
3536
objects.sourceDirectorySet("assertJClasses", "Classes to generate AssertJ assertions from")
3637

38+
val packages: JavaPackageNamePatternFilterable = objects.newInstance()
39+
40+
fun packages(action: Action<in JavaPackageNamePatternFilterable>): AssertJGeneratorExtension = apply {
41+
action.execute(packages)
42+
}
43+
3744
/**
3845
* Generate generating Soft Assertions entry point class.
3946
* @return templates value, never {@code null}
@@ -44,9 +51,8 @@ open class AssertJGeneratorExtension @Inject internal constructor(
4451
* Method used for improving configuration DSL
4552
* @return {@code this}
4653
*/
47-
fun templates(action: Action<in Templates>): AssertJGeneratorExtension {
54+
fun templates(action: Action<in Templates>): AssertJGeneratorExtension = apply {
4855
action.execute(templates)
49-
return this
5056
}
5157

5258
/**
@@ -82,9 +88,8 @@ open class AssertJGeneratorExtension @Inject internal constructor(
8288
* Used to change "entry point" class generation.
8389
* @return this
8490
*/
85-
fun entryPoints(action: Action<in EntryPointGeneratorOptions>): AssertJGeneratorExtension {
91+
fun entryPoints(action: Action<in EntryPointGeneratorOptions>): AssertJGeneratorExtension = apply {
8692
action.execute(entryPoints)
87-
return this
8893
}
8994

9095
/**
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright 2023. assertj-generator-gradle-plugin contributors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
package org.assertj.generator.gradle.tasks.config.patterns
14+
15+
import java.io.IOException
16+
import java.io.ObjectInputStream
17+
import java.io.ObjectOutputStream
18+
import java.util.function.Predicate
19+
20+
@Suppress("UNCHECKED_CAST")
21+
sealed class JavaIdentifierNamePatternFilterableBase<T, SELF>
22+
where SELF : JavaIdentifierNamePatternFilterableBase<T, SELF> {
23+
private var includePredicates = mutableSetOf<PatternPredicate<T>>()
24+
private var excludePredicates = mutableSetOf<PatternPredicate<T>>()
25+
26+
internal abstract fun compilePatterns(patterns: Iterable<String>): Sequence<PatternPredicate<T>>
27+
28+
internal fun asPredicate(): Predicate<T> {
29+
return Predicate { t ->
30+
(includePredicates.isEmpty() || includePredicates.any { it.test(t) }) &&
31+
(excludePredicates.isEmpty() || excludePredicates.none { it.test(t) })
32+
}
33+
}
34+
35+
fun setIncludes(includes: Iterable<String>): SELF {
36+
this.includePredicates = compilePatterns(includes).toMutableSet()
37+
return this as SELF
38+
}
39+
40+
fun setExcludes(excludes: Iterable<String>): SELF {
41+
this.excludePredicates = compilePatterns(excludes).toMutableSet()
42+
return this as SELF
43+
}
44+
45+
fun include(vararg includes: String): SELF {
46+
this.includePredicates += compilePatterns(includes.asIterable())
47+
return this as SELF
48+
}
49+
50+
fun include(includes: Iterable<String>): SELF {
51+
this.includePredicates += compilePatterns(includes)
52+
return this as SELF
53+
}
54+
55+
fun exclude(vararg excludes: String): SELF {
56+
this.excludePredicates += compilePatterns(excludes.asIterable())
57+
return this as SELF
58+
}
59+
60+
fun exclude(excludes: Iterable<String>): SELF {
61+
this.excludePredicates += compilePatterns(excludes)
62+
return this as SELF
63+
}
64+
65+
internal interface PatternPredicate<T> : Predicate<T> {
66+
val pattern: String
67+
}
68+
69+
@Throws(IOException::class)
70+
protected fun writeObjectImpl(o: ObjectOutputStream) {
71+
o.writeInt(includePredicates.size)
72+
for (pattern in includePredicates.map { it.pattern }) {
73+
o.writeUTF(pattern)
74+
}
75+
76+
o.writeInt(excludePredicates.size)
77+
for (pattern in excludePredicates.map { it.pattern }) {
78+
o.writeUTF(pattern)
79+
}
80+
}
81+
82+
@Throws(IOException::class, ClassNotFoundException::class)
83+
protected fun readObjectImpl(i: ObjectInputStream) {
84+
val includesSize = i.readInt()
85+
setIncludes((0 until includesSize).map { i.readUTF() })
86+
87+
val excludesSize = i.readInt()
88+
setExcludes((0 until excludesSize).map { i.readUTF() })
89+
}
90+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2023. assertj-generator-gradle-plugin contributors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
package org.assertj.generator.gradle.tasks.config.patterns
14+
15+
private const val WILDCARD_MARKER = "!!WILDCARD_MARKER!!"
16+
17+
internal object JavaNamePatternCompiler {
18+
fun compilePattern(pattern: String): Regex {
19+
val escapedPackageCharacters = pattern
20+
.replace(".", "\\.")
21+
.replace("$", "\\$")
22+
23+
// Order matters because if we do single "*" first we double remove the "**"
24+
val withWildcardMarkers = escapedPackageCharacters
25+
.replace("**", "[\\w\\.]$WILDCARD_MARKER")
26+
.replace("*", "\\w$WILDCARD_MARKER")
27+
28+
val withRegexWildcards = withWildcardMarkers.replace(WILDCARD_MARKER, "*")
29+
30+
return Regex(withRegexWildcards)
31+
}
32+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2023. assertj-generator-gradle-plugin contributors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
package org.assertj.generator.gradle.tasks.config.patterns
14+
15+
import com.google.common.reflect.TypeToken
16+
import org.assertj.generator.gradle.tasks.config.patterns.JavaNamePatternCompiler.compilePattern
17+
import java.io.IOException
18+
import java.io.ObjectInputStream
19+
import java.io.ObjectOutputStream
20+
import java.io.Serializable
21+
22+
/**
23+
* Implements a similar construction to [org.gradle.api.tasks.util.PatternFilterable] that will match
24+
* [TypeToken] instances.
25+
*/
26+
open class JavaPackageNamePatternFilterable internal constructor() :
27+
JavaIdentifierNamePatternFilterableBase<String, JavaPackageNamePatternFilterable>(), Serializable {
28+
29+
override fun compilePatterns(patterns: Iterable<String>): Sequence<PatternPredicate<String>> {
30+
return patterns.asSequence().map { PackagePatternPredicate.compile(it) }
31+
}
32+
33+
@Throws(IOException::class)
34+
protected fun writeObject(o: ObjectOutputStream) {
35+
super.writeObjectImpl(o)
36+
}
37+
38+
@Throws(IOException::class, ClassNotFoundException::class)
39+
protected fun readObject(i: ObjectInputStream) {
40+
super.readObjectImpl(i)
41+
}
42+
43+
internal data class PackagePatternPredicate(
44+
override val pattern: String,
45+
private val namePattern: Regex,
46+
) : PatternPredicate<String> {
47+
override fun test(t: String): Boolean {
48+
return namePattern.matches(t)
49+
}
50+
51+
companion object {
52+
fun compile(pattern: String) = PackagePatternPredicate(pattern, compilePattern(pattern))
53+
}
54+
}
55+
56+
companion object {
57+
private const val serialVersionUID = 48634795L
58+
}
59+
}

0 commit comments

Comments
 (0)