Skip to content

Commit f252e0e

Browse files
committed
Applies changes to master -- not UTD
1 parent 19243b0 commit f252e0e

28 files changed

+1926
-617
lines changed

config/detekt/detekt.yml

+791
Large diffs are not rendered by default.

core/build.gradle.kts

+30-5
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,14 @@ plugins {
1515
alias(libs.plugins.dokka)
1616
alias(libs.plugins.arrow.gradle.publish)
1717
alias(libs.plugins.semver.gradle)
18+
alias(libs.plugins.detekt)
1819
//id("com.xebia.asfuture").version("0.0.1")
1920
}
2021

22+
dependencies {
23+
detektPlugins(project(":detekt-rules"))
24+
}
25+
2126
java {
2227
sourceCompatibility = JavaVersion.VERSION_11
2328
targetCompatibility = JavaVersion.VERSION_11
@@ -26,6 +31,13 @@ java {
2631
}
2732
}
2833

34+
detekt {
35+
toolVersion = "1.23.1"
36+
source = files("src/commonMain/kotlin", "src/jvmMain/kotlin")
37+
config.setFrom("../config/detekt/detekt.yml")
38+
autoCorrect = true
39+
}
40+
2941
kotlin {
3042
jvm {
3143
compilations {
@@ -67,6 +79,10 @@ kotlin {
6779
api(libs.kotlinx.serialization.json)
6880
api(libs.ktor.utils)
6981
api(projects.xefTokenizer)
82+
api(libs.jackson)
83+
api(libs.jackson.schema)
84+
api(libs.jackson.schema.jakarta)
85+
api(libs.jakarta.validation)
7086
implementation(libs.bundles.ktor.client)
7187
implementation(libs.klogging)
7288
implementation(libs.uuid)
@@ -87,11 +103,6 @@ kotlin {
87103
implementation(libs.logback)
88104
implementation(libs.skrape)
89105
implementation(libs.rss.reader)
90-
api(libs.jackson)
91-
api(libs.jackson.schema)
92-
api(libs.jackson.schema.jakarta)
93-
api(libs.jakarta.validation)
94-
implementation(libs.kotlinx.coroutines.reactive)
95106
api(libs.ktor.client.cio)
96107
}
97108
}
@@ -161,6 +172,20 @@ spotless {
161172
}
162173

163174
tasks {
175+
176+
withType<io.gitlab.arturbosch.detekt.Detekt>().configureEach {
177+
dependsOn(":detekt-rules:assemble")
178+
autoCorrect = true
179+
}
180+
named("detektJvmMain") {
181+
dependsOn(":detekt-rules:assemble")
182+
getByName("build").dependsOn(this)
183+
}
184+
named("detekt") {
185+
dependsOn(":detekt-rules:assemble")
186+
getByName("build").dependsOn(this)
187+
}
188+
164189
withType<Test>().configureEach {
165190
maxParallelForks = Runtime.getRuntime().availableProcessors()
166191
useJUnitPlatform()

core/src/jvmMain/kotlin/com/xebia/functional/xef/auto/PlatformConversation.jvm.kt

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import com.xebia.functional.xef.prompt.Prompt
1010
import com.xebia.functional.xef.vectorstores.ConversationId
1111
import com.xebia.functional.xef.vectorstores.VectorStore
1212
import java.util.concurrent.CompletableFuture
13+
import java.util.concurrent.Flow
1314
import kotlinx.coroutines.CoroutineScope
1415
import kotlinx.coroutines.SupervisorJob
1516
import kotlinx.coroutines.cancel
@@ -112,7 +113,7 @@ actual constructor(
112113
question: String,
113114
promptConfiguration: PromptConfiguration = PromptConfiguration.DEFAULTS,
114115
functions: List<CFunction> = emptyList(),
115-
): Publisher<String> =
116+
): Flow.Publisher<String> =
116117
chat
117118
.promptStreaming(
118119
question = question,

detekt-rules/build.gradle.kts

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
@file:Suppress("DSL_SCOPE_VIOLATION")
2+
3+
repositories { mavenCentral() }
4+
5+
plugins {
6+
`kotlin-dsl`
7+
base
8+
alias(libs.plugins.spotless)
9+
}
10+
11+
spotless {
12+
kotlin {
13+
target("**/*.kt")
14+
ktfmt().googleStyle()
15+
}
16+
}
17+
18+
19+
dependencies {
20+
api(libs.detekt.api)
21+
testImplementation(libs.detekt.test)
22+
testImplementation(libs.kotest.assertions)
23+
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
24+
implementation(libs.klogging)
25+
}
26+
27+
tasks.withType<Jar>() {
28+
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
29+
}
30+
31+
tasks.withType<Test>().configureEach {
32+
maxParallelForks = Runtime.getRuntime().availableProcessors()
33+
useJUnitPlatform()
34+
systemProperty("junit.jupiter.testinstance.lifecycle.default", "per_class")
35+
systemProperty("compile-snippet-tests", project.hasProperty("compile-test-snippets"))
36+
testLogging {
37+
setExceptionFormat("full")
38+
setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError"))
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package org.example.detekt
2+
3+
import io.gitlab.arturbosch.detekt.api.Config
4+
import io.gitlab.arturbosch.detekt.api.CorrectableCodeSmell
5+
import io.gitlab.arturbosch.detekt.api.Debt
6+
import io.gitlab.arturbosch.detekt.api.Entity
7+
import io.gitlab.arturbosch.detekt.api.Issue
8+
import io.gitlab.arturbosch.detekt.api.Rule
9+
import io.gitlab.arturbosch.detekt.api.Severity
10+
import org.jetbrains.kotlin.psi.KtClass
11+
12+
/** Fixes occurrences of inline data class when enabled to allow for jvm language interop. */
13+
class JvmInlineAnnotation(config: Config) : Rule(config) {
14+
15+
override val issue: Issue =
16+
Issue(
17+
javaClass.simpleName,
18+
Severity.Defect,
19+
"This rule reports an public inline value class as incompatible with other jvm languages.",
20+
Debt.FIVE_MINS
21+
)
22+
23+
/**
24+
* * Reports inline value classes not marked @JvmInline as a lint warning, and autofixes the
25+
* declaration to include @JvmInline.
26+
*/
27+
override fun visitClass(klass: KtClass) {
28+
29+
if (
30+
klass.isValue() &&
31+
klass.annotationEntries.filter { e -> e.shortName?.asString() == "JvmInline" }.size < 1
32+
) {
33+
report(
34+
CorrectableCodeSmell(
35+
issue,
36+
Entity.from(klass),
37+
"Kotlin inline value classes are not compatible with other jvm lanugages.",
38+
emptyList(),
39+
listOf(Entity.from(klass)),
40+
false
41+
)
42+
)
43+
}
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package org.example.detekt
2+
3+
import io.gitlab.arturbosch.detekt.api.*
4+
import org.jetbrains.kotlin.psi.KtClass
5+
import org.jetbrains.kotlin.psi.KtElement
6+
import org.jetbrains.kotlin.psi.KtNamedFunction
7+
import org.jetbrains.kotlin.psi.KtVisitorVoid
8+
import org.jetbrains.kotlin.resolve.BindingContext
9+
import org.jetbrains.kotlin.resolve.isValueClassType
10+
import org.jetbrains.kotlin.types.KotlinType
11+
12+
/** Fixes occurrences of inline data class when enabled to allow for jvm language interop. */
13+
class PublicDataClassConstructorWithValueParameters(config: Config) : Rule(config) {
14+
15+
override val issue: Issue =
16+
Issue(
17+
javaClass.simpleName,
18+
Severity.Defect,
19+
"This rule reports public data classes that are incompatible with other jvm languages.",
20+
Debt.FIVE_MINS
21+
)
22+
23+
/** * Reports inline value classes not marked @JvmInline as a lint warning. */
24+
override fun visitClass(ktClass: KtClass) {
25+
try {
26+
if (
27+
ktClass.isData() &&
28+
ktClass.hasPrimaryConstructor() &&
29+
ktClass.primaryConstructor?.valueParameters?.any {
30+
val ktpe = bindingContext.get(BindingContext.TYPE, it.typeReference)
31+
32+
(ktpe as KotlinType).unwrap().isValueClassType()
33+
} == true
34+
) {
35+
var hasJvmStaticConstructor = false
36+
val hasCompanionObjects = ktClass.companionObjects.isNotEmpty()
37+
if (!hasCompanionObjects) {
38+
hasJvmStaticConstructor = false
39+
} else {
40+
ktClass.companionObjects.forEach { ktObjectDeclaration ->
41+
if (!hasJvmStaticConstructor) {
42+
ktObjectDeclaration.acceptChildren(
43+
object : KtVisitorVoid() {
44+
override fun visitKtElement(element: KtElement) {
45+
try {
46+
element.acceptChildren(this)
47+
} catch (_: UnsupportedOperationException) {}
48+
}
49+
50+
override fun visitNamedFunction(function: KtNamedFunction) {
51+
if (!hasJvmStaticConstructor) {
52+
val klassParametersAsString =
53+
ktClass.primaryConstructor?.valueParameterList?.parameters?.fold("") {
54+
acc,
55+
parameter ->
56+
if (acc == "") {
57+
acc + parameter.name + ":" + parameter.typeReference?.text
58+
} else {
59+
acc + ", " + parameter.name + ":" + parameter.typeReference?.text
60+
}
61+
}
62+
val functionParametersAsStrings =
63+
function.valueParameterList?.parameters?.fold("") { acc, parameter ->
64+
if (acc == "") {
65+
acc + parameter.name + ":" + parameter.typeReference?.text
66+
} else {
67+
acc + ", " + parameter.name + ":" + parameter.typeReference?.text
68+
}
69+
}
70+
val functionHasJvmStatic =
71+
function.annotationEntries.any { it.shortName?.asString() == "JvmStatic" }
72+
val functionHasAllButLastDefaultConstructorParameter =
73+
klassParametersAsString == functionParametersAsStrings
74+
hasJvmStaticConstructor =
75+
functionHasJvmStatic && functionHasAllButLastDefaultConstructorParameter
76+
}
77+
}
78+
}
79+
)
80+
}
81+
}
82+
}
83+
if (!hasJvmStaticConstructor) {
84+
report(
85+
CorrectableCodeSmell(
86+
issue,
87+
Entity.from(ktClass),
88+
"Kotlin data classes must have a JVM static factory method to be compatible with other jvm languages.",
89+
emptyList(),
90+
listOf(Entity.from(ktClass)),
91+
true
92+
)
93+
)
94+
}
95+
}
96+
} catch (_: Exception) {}
97+
}
98+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.example.detekt
2+
3+
import io.gitlab.arturbosch.detekt.api.Config
4+
import io.gitlab.arturbosch.detekt.api.RuleSet
5+
import io.gitlab.arturbosch.detekt.api.RuleSetProvider
6+
7+
class XefRuleSetProvider : RuleSetProvider {
8+
override val ruleSetId: String = "XefRuleSet"
9+
10+
override fun instance(config: Config): RuleSet {
11+
return RuleSet(
12+
ruleSetId,
13+
listOf(JvmInlineAnnotation(config), PublicDataClassConstructorWithValueParameters(config)),
14+
)
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.example.detekt.XefRuleSetProvider
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
XefRuleSet:
2+
JvmInlineAnnotation:
3+
active: true
4+
PublicDataClassConstructorWithValueParameters:
5+
active: true
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<configuration>
2+
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
3+
<encoder>
4+
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} MDC=%X{user} - %msg%n</pattern>
5+
</encoder>
6+
</appender>
7+
8+
<root level="debug">
9+
<appender-ref ref="STDOUT" />
10+
</root>
11+
</configuration>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package org.example.detekt
2+
3+
import io.gitlab.arturbosch.detekt.api.Config
4+
import io.gitlab.arturbosch.detekt.rules.KotlinCoreEnvironmentTest
5+
import io.gitlab.arturbosch.detekt.test.compileAndLintWithContext
6+
import io.kotest.matchers.collections.shouldHaveSize
7+
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
8+
import org.junit.jupiter.api.Test
9+
10+
@KotlinCoreEnvironmentTest
11+
internal class JvmInlineAnnotationTest(private val env: KotlinCoreEnvironment) {
12+
13+
@Test
14+
fun `reports missing jvminline annotations`() {
15+
val code = """
16+
value class User(val id: String)
17+
"""
18+
val findings = JvmInlineAnnotation(Config.empty).compileAndLintWithContext(env, code)
19+
findings shouldHaveSize 1
20+
}
21+
22+
@Test
23+
fun `doesn't report annotated value classes`() {
24+
val code =
25+
"""
26+
import kotlin.jvm.JvmInline
27+
@JvmInline value class User(val id: String)
28+
"""
29+
val findings = JvmInlineAnnotation(Config.empty).compileAndLintWithContext(env, code)
30+
findings shouldHaveSize 0
31+
}
32+
}

0 commit comments

Comments
 (0)