Skip to content

Commit e0b75da

Browse files
committed
Update to Detekt 2.0.
Also enable much stricter checks.
1 parent 001d90a commit e0b75da

18 files changed

+578
-39
lines changed

aockt-test/src/main/kotlin/AdventSpec.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ import kotlin.time.Duration
4949
* @param T The implementation class of the [Solution] to be tested.
5050
* @param body A context in which to configure the tests.
5151
*/
52-
@Suppress("UnnecessaryAbstractClass")
52+
@Suppress("AbstractClassCanBeConcreteClass")
5353
@OptIn(ExperimentalKotest::class)
5454
@AocktDsl
5555
public abstract class AdventSpec<T : Solution>(

aockt-test/src/main/kotlin/internal/AdventDayID.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ internal data class AdventDayID(
2020

2121
override fun toString(): String = "Y${year}D${day.toString().padStart(2, '0')}"
2222

23-
@Suppress("MagicNumber")
23+
@Suppress("MagicNumber", "UnnamedParameterUse")
2424
override fun compareTo(other: AdventDayID): Int = compareValuesBy(this, other) { year * 100 + day }
2525

2626
private companion object {

aockt-test/src/main/kotlin/internal/AdventPartScopeImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ internal class AdventPartScopeImpl : AdventPartScope {
1616
}
1717

1818
/** Applies the [block] function for each registered example. */
19-
inline fun forEachIndexed(block: (Int, PuzzleInput, String) -> Unit) =
19+
inline fun forEachIndexed(block: (Int, PuzzleInput, String) -> Unit): Unit =
2020
examples.forEachIndexed { index, example -> block(index, example.first, example.second) }
2121
}

aockt-test/src/main/kotlin/internal/AdventSpecConfig.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ internal data class AdventSpecConfig(
2626
}
2727

2828
/** Return a copy of this config with all non-null overrides given applied. */
29+
@Suppress("DataClassContainsFunctions")
2930
fun override(
3031
efficiencyBenchmark: Duration?,
3132
executionMode: ExecMode?,

aockt-test/src/main/kotlin/internal/AdventSpecExt.kt

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ internal fun AdventSpec<*>.definePart(
114114
* @param examples A configuration block defining the example values.
115115
*/
116116
@OptIn(ExperimentalKotest::class)
117+
@Suppress("SuspendFunWithCoroutineScopeReceiver")
117118
private suspend fun FunSpecContainerScope.defineExamples(
118119
config: AdventSpecConfig,
119120
partFunction: (String) -> Any,
@@ -148,6 +149,7 @@ private suspend fun FunSpecContainerScope.defineExamples(
148149
* @param correctAnswer The actual puzzle solution, if known.
149150
*/
150151
@OptIn(ExperimentalKotest::class)
152+
@Suppress("SuspendFunWithCoroutineScopeReceiver")
151153
private suspend fun FunSpecContainerScope.defineInput(
152154
config: AdventSpecConfig,
153155
expensive: Boolean,
@@ -156,11 +158,11 @@ private suspend fun FunSpecContainerScope.defineInput(
156158
correctAnswer: PuzzleAnswer?,
157159
) {
158160
context("The solution").config(enabled = config.executionMode != ExecMode.ExamplesOnly) {
159-
val solutionKnown = correctAnswer != null
161+
val isSolutionKnown = correctAnswer != null
160162
var answer: PuzzleAnswer? = null
161163
var duration: Duration? = null
162164

163-
test(name = if (solutionKnown) "Is correct" else "Computes an answer") {
165+
test(name = if (isSolutionKnown) "Is correct" else "Computes an answer") {
164166
runCatching {
165167
val (value, time) = measureTimedValue { partFunction(input.toString()) }
166168
answer = PuzzleAnswer(value.toString())
@@ -172,15 +174,15 @@ private suspend fun FunSpecContainerScope.defineInput(
172174
.build()
173175
}
174176

175-
if (solutionKnown) {
177+
if (isSolutionKnown) {
176178
withClue("Got different answer than the known solution.") {
177179
answer shouldBe correctAnswer
178180
}
179181
}
180182
}
181183

182184
// If solution is unverified, create a dummy ignored test to display the value in the test report.
183-
if (!solutionKnown && answer != null) {
185+
if (!isSolutionKnown && answer != null) {
184186
xtest("Has unverified answer ($answer)") {}
185187
}
186188

@@ -192,7 +194,7 @@ private suspend fun FunSpecContainerScope.defineInput(
192194
}
193195

194196
val benchmark = config.efficiencyBenchmark
195-
val durationSuffix = if (answer != null) duration.toString() else "N/A"
197+
val durationSuffix = duration?.takeIf { answer != null }?.toString() ?: "N/A"
196198
test("Is reasonably efficient ($durationSuffix)").config(enabled = enableSpeedTesting) {
197199
withClue("The solution did not complete under the configured benchmark of $benchmark") {
198200
@Suppress("UnsafeCallOnNullableType")

aockt-test/src/main/kotlin/internal/AocktDisplayNameFormatter.kt

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,18 @@ internal class AocktDisplayNameFormatter(private val disabled: Boolean = false)
2424
return null
2525
}
2626

27-
return buildString {
28-
append(AdventDayID(annotation.year, annotation.day))
29-
if (annotation.title.isNotEmpty()) {
30-
append(": ")
31-
append(annotation.title)
32-
}
33-
if (annotation.variant != "default") {
34-
append(" (")
35-
append(annotation.variant)
36-
append(')')
27+
return with(annotation) {
28+
buildString {
29+
append(AdventDayID(year, day))
30+
if (title.isNotEmpty()) {
31+
append(": ")
32+
append(title)
33+
}
34+
if (variant != "default") {
35+
append(" (")
36+
append(variant)
37+
append(')')
38+
}
3739
}
3840
}
3941
}

aockt-test/src/main/kotlin/internal/Exceptions.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package io.github.jadarma.aockt.test.internal
33
import io.github.jadarma.aockt.core.Solution
44
import io.github.jadarma.aockt.test.AdventSpec
55
import io.github.jadarma.aockt.test.AdventDay
6+
import io.kotest.common.reflection.bestName
67
import kotlin.reflect.KClass
78

89
/** Base [Exception] type for all exceptions related to AocKt. */
@@ -16,7 +17,7 @@ internal class ConfigurationException(message: String? = null) : AocktException(
1617
* It is required in order to determine test input.
1718
*/
1819
internal class MissingAdventDayAnnotationException(kclass: KClass<out AdventSpec<*>>) : AocktException(
19-
message = "Class ${kclass.qualifiedName} is an AdventSpec but is missing the AdventDay annotation.",
20+
message = "Class ${kclass.bestName()} is an AdventSpec but is missing the AdventDay annotation.",
2021
)
2122

2223
/**
@@ -25,13 +26,13 @@ internal class MissingAdventDayAnnotationException(kclass: KClass<out AdventSpec
2526
* Add a no-arg constructor to it or declare it as an object.
2627
*/
2728
internal class MissingNoArgConstructorException(kclass: KClass<out Solution>) : AocktException(
28-
message = "Class ${kclass.qualifiedName} is a Solution but it is missing a no-arg constructor.",
29+
message = "Class ${kclass.bestName()} is a Solution but it is missing a no-arg constructor.",
2930
)
3031

3132
/**
3233
* An [AdventSpec] declared the same part scope twice.
3334
* The [AdventSpec.partOne] and [AdventSpec.partTwo] should be used at most once per spec.
3435
*/
3536
internal class DuplicatePartDefinitionException(spec: KClass<*>, part: AdventDayPart) : AocktException(
36-
message = "In ${spec.qualifiedName}, part$part has been declared twice.",
37+
message = "In ${spec.bestName()}, part$part has been declared twice.",
3738
)

aockt-test/src/main/kotlin/internal/TestData.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
package io.github.jadarma.aockt.test.internal
2+
23
import io.github.jadarma.aockt.core.Solution
34

45
/**

aockt-test/src/test/kotlin/integration/MultipleSolutions.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class Y9999D01SequencesTest : Y9999D01Spec<Y9999D01UsingSequences>()
4646
* Part 2: Return the product of the numbers.
4747
* ```
4848
*/
49-
@Suppress("UnnecessaryAbstractClass")
49+
@Suppress("AbstractClassCanBeInterface")
5050
abstract class Y9999D01Spec<T : Solution> : AdventSpec<T>({
5151

5252
partOne {
Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,44 @@
1-
import io.gitlab.arturbosch.detekt.Detekt
1+
import dev.detekt.gradle.Detekt
22
import org.gradle.kotlin.dsl.kotlin
3-
import org.gradle.kotlin.dsl.withType
43

54
plugins {
65
kotlin("jvm")
7-
id("io.gitlab.arturbosch.detekt")
6+
id("dev.detekt")
87
}
98

109
detekt {
11-
buildUponDefaultConfig = true
10+
buildUponDefaultConfig = false
1211
parallel = true
1312
baseline = file("$rootDir/gradle/detekt/baseline/${project.name}.xml")
14-
config.from(
15-
files(
13+
}
14+
15+
tasks {
16+
val detektMain: Detekt by named<Detekt>("detektMain") {
17+
config.setFrom(
1618
"$rootDir/gradle/detekt/config/detekt.yml",
1719
"$rootDir/gradle/detekt/config/${project.name}.yml",
1820
)
19-
)
20-
}
21+
}
22+
val detektTest: Detekt by named<Detekt>("detektTest") {
23+
config.setFrom(
24+
"$rootDir/gradle/detekt/config/detekt.yml",
25+
"$rootDir/gradle/detekt/config/${project.name}.yml",
26+
"$rootDir/gradle/detekt/config/detekt-test.yml",
27+
)
28+
}
29+
30+
check.configure {
31+
// Replace the default detekt dependency and instead force the use of type resolution.
32+
dependsOn(detektMain, detektTest)
33+
setDependsOn(dependsOn.filterNot { it is TaskProvider<*> && it.name == "detekt" })
34+
}
2135

22-
tasks.withType<Detekt>().configureEach {
23-
jvmTarget = CompileOptions.Kotlin.jvmTarget.target
36+
withType<Detekt>().configureEach {
37+
reports {
38+
html.required = true
39+
sarif.required = true
40+
md.required = false
41+
xml.required = false
42+
}
43+
}
2444
}

0 commit comments

Comments
 (0)