diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6d9f9c6..0ff73e5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,9 +15,9 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'temurin' - java-version: '11' + java-version: '17' - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@v4 with: ref: ${{ github.ref }} - name: Publish diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a5c774b..85283f8 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -12,9 +12,9 @@ jobs: uses: actions/setup-java@v4 with: distribution: 'temurin' - java-version: '11' + java-version: '17' - name: Checkout - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + uses: actions/checkout@v4 - name: Run tests uses: burrunan/gradle-cache-action@v1 with: diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 372a9f9..43c5758 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -15,6 +15,6 @@ dependencies { kotlin { jvmToolchain { - languageVersion.set(JavaLanguageVersion.of(11)) + languageVersion.set(JavaLanguageVersion.of(17)) } } diff --git a/buildSrc/src/main/kotlin/kotlin.gradle.kts b/buildSrc/src/main/kotlin/kotlin.gradle.kts index 6d97e83..7bf9bca 100644 --- a/buildSrc/src/main/kotlin/kotlin.gradle.kts +++ b/buildSrc/src/main/kotlin/kotlin.gradle.kts @@ -4,6 +4,6 @@ plugins { kotlin { jvmToolchain { - languageVersion.set(JavaLanguageVersion.of(11)) + languageVersion.set(JavaLanguageVersion.of(17)) } } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/release.gradle.kts b/buildSrc/src/main/kotlin/release.gradle.kts index 2f2749c..f694429 100644 --- a/buildSrc/src/main/kotlin/release.gradle.kts +++ b/buildSrc/src/main/kotlin/release.gradle.kts @@ -23,7 +23,7 @@ tasks.register("publish") { tasks.register("clean") { group = "build" - delete = setOf(buildDir) + delete = setOf(layout.buildDirectory) } nexusPublishing { diff --git a/gradle.properties b/gradle.properties index 00547ea..05983f5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ kotlin.code.style=official -org.gradle.jvmargs=-Xmx4096m -XX:MaxPermSize=1024m +org.gradle.jvmargs=-Xmx4096m kapt.includeCompileClasspath=false group=com.faendir.kotlin.autodsl \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f18ef6d..357da77 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,15 +1,14 @@ [versions] -kotlin = "1.9.0" +kotlin = "1.9.23" dokka = "1.9.20" jgitver = "0.10.0-rc03" nexusPublish = "2.0.0" -ksp = "1.9.0-1.0.11" -kotlinPoet = "1.14.2" +ksp = "1.9.23-1.0.19" +kotlinPoet = "1.16.0" kotlinBard = "0.5.1" -compileTesting = "1.5.0" +compileTesting = "0.4.1" junit = "5.10.2" strikt = "0.34.1" -autoCommon = "1.1.2" intellijPlugin = "1.17.3" [plugins] @@ -27,5 +26,5 @@ dokka-core = { module = "org.jetbrains.dokka:dokka-core", version.ref = "dokka" jgitver = { module = "gradle.plugin.fr.brouillard.oss.gradle:gradle-jgitver-plugin", version.ref = "jgitver" } nexusPublish = { module = "io.github.gradle-nexus:publish-plugin", version.ref = "nexusPublish" } junit = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" } -kotlin-compileTesting = { module = "com.github.tschuchortdev:kotlin-compile-testing-ksp", version.ref = "compileTesting" } +kotlin-compileTesting = { module = "dev.zacsweers.kctfork:ksp", version.ref = "compileTesting" } strikt = { module = "io.strikt:strikt-core", version.ref = "strikt" } \ No newline at end of file diff --git a/processor/build.gradle.kts b/processor/build.gradle.kts index a30a9ee..615dfe6 100644 --- a/processor/build.gradle.kts +++ b/processor/build.gradle.kts @@ -10,5 +10,26 @@ dependencies { implementation(libs.kotlinpoet.ksp) implementation(libs.kotlinpoet.metadata) implementation(libs.kotlinbard) - implementation(kotlin("compiler-embeddable", "1.8.0")) + implementation(kotlin("compiler-embeddable")) +} + +kotlin.sourceSets.all { + languageSettings.optIn("org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi") +} + +if (JavaVersion.current() >= JavaVersion.VERSION_16) { + tasks.withType { + jvmArgs( + "--add-opens=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", + "--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", + "--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED", + "--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", + "--add-opens=jdk.compiler/com.sun.tools.javac.jvm=ALL-UNNAMED", + "--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", + "--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED", + "--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED", + "--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", + "--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", + ) + } } diff --git a/processor/src/main/kotlin/com/faendir/kotlin/autodsl/kapt/KaptCodeWriter.kt b/processor/src/main/kotlin/com/faendir/kotlin/autodsl/kapt/KaptCodeWriter.kt index e9551bb..49df79e 100644 --- a/processor/src/main/kotlin/com/faendir/kotlin/autodsl/kapt/KaptCodeWriter.kt +++ b/processor/src/main/kotlin/com/faendir/kotlin/autodsl/kapt/KaptCodeWriter.kt @@ -4,16 +4,16 @@ import com.faendir.kotlin.autodsl.CodeWriter import com.squareup.kotlinpoet.FileSpec import java.io.File import javax.annotation.processing.ProcessingEnvironment -import javax.lang.model.element.Element -import javax.lang.model.element.TypeElement import javax.tools.Diagnostic class KaptCodeWriter(processingEnv: ProcessingEnvironment) : CodeWriter { - private val dir : File = processingEnv.options["kapt.kotlin.generated"]?.let { File(it) } + private val dir: File = processingEnv.options["kapt.kotlin.generated"]?.let { File(it) } ?: run { processingEnv.messager.printMessage(Diagnostic.Kind.ERROR, "Can't find the target directory for generated Kotlin files. Are you using kapt?") throw IllegalStateException() } - override fun emit(source: Type, fileSpec: FileSpec) = fileSpec.writeTo(dir) + override fun emit(source: Type, fileSpec: FileSpec) { + fileSpec.writeTo(dir) + } } \ No newline at end of file diff --git a/processor/src/main/kotlin/com/faendir/kotlin/autodsl/kapt/KaptSourceInfoResolver.kt b/processor/src/main/kotlin/com/faendir/kotlin/autodsl/kapt/KaptSourceInfoResolver.kt index 566a6fb..e85e46d 100644 --- a/processor/src/main/kotlin/com/faendir/kotlin/autodsl/kapt/KaptSourceInfoResolver.kt +++ b/processor/src/main/kotlin/com/faendir/kotlin/autodsl/kapt/KaptSourceInfoResolver.kt @@ -7,10 +7,16 @@ import com.faendir.kotlin.autodsl.nonnull import com.google.devtools.ksp.symbol.ClassKind import com.squareup.kotlinpoet.* import com.squareup.kotlinpoet.metadata.* -import kotlinx.metadata.Flag import kotlinx.metadata.KmClass import kotlinx.metadata.KmConstructor import kotlinx.metadata.KmValueParameter +import kotlinx.metadata.Modality +import kotlinx.metadata.Visibility +import kotlinx.metadata.declaresDefaultValue +import kotlinx.metadata.isSecondary +import kotlinx.metadata.kind +import kotlinx.metadata.modality +import kotlinx.metadata.visibility import javax.annotation.processing.ProcessingEnvironment import javax.annotation.processing.RoundEnvironment import javax.lang.model.element.ElementKind @@ -30,14 +36,14 @@ class KaptSourceInfoResolver(private val processingEnv: ProcessingEnvironment, p override fun getClassesWithAnnotation(annotation: Type): List = roundEnv.getElementsAnnotatedWith(annotation.element).filterIsInstance().map { Type(it) } - override fun Type.getClassKind(): ClassKind = when { - kmClass.isEnum -> ClassKind.ENUM_CLASS - kmClass.isAnnotation -> ClassKind.ANNOTATION_CLASS - kmClass.isInterface -> ClassKind.INTERFACE - kmClass.isEnumEntry -> ClassKind.ENUM_ENTRY - kmClass.isClass -> ClassKind.CLASS - kmClass.isObject -> ClassKind.OBJECT - else -> throw IllegalArgumentException() + override fun Type.getClassKind(): ClassKind = when(kmClass.kind) { + kotlinx.metadata.ClassKind.CLASS -> ClassKind.CLASS + kotlinx.metadata.ClassKind.INTERFACE -> ClassKind.INTERFACE + kotlinx.metadata.ClassKind.ENUM_CLASS -> ClassKind.ENUM_CLASS + kotlinx.metadata.ClassKind.ENUM_ENTRY -> ClassKind.ENUM_ENTRY + kotlinx.metadata.ClassKind.ANNOTATION_CLASS -> ClassKind.ANNOTATION_CLASS + kotlinx.metadata.ClassKind.OBJECT -> ClassKind.OBJECT + kotlinx.metadata.ClassKind.COMPANION_OBJECT -> ClassKind.OBJECT } override fun Annotated.getAnnotationTypeProperty(annotation: KClass, property: KProperty1>): ClassName? = try { @@ -51,7 +57,7 @@ class KaptSourceInfoResolver(private val processingEnv: ProcessingEnvironment, p override fun Annotated.getAnnotationProperty(annotation: KClass, property: KProperty1): V? = getAnnotation(annotation)?.let(property) - override fun Type.isAbstract(): Boolean = Flag.IS_ABSTRACT(kmClass.flags) + override fun Type.isAbstract(): Boolean = kmClass.modality == Modality.ABSTRACT override fun Type.getConstructors(): List { val constructorElements = element.enclosedElements.filterIsInstance().filter { it.kind == ElementKind.CONSTRUCTOR }.toMutableList() @@ -71,9 +77,9 @@ class KaptSourceInfoResolver(private val processingEnv: ProcessingEnvironment, p }.map { (kmConstructor, element) -> Constructor(element, kmConstructor) } } - override fun Constructor.isAccessible(): Boolean = Flag.IS_PUBLIC(kmConstructor.flags) || Flag.IS_INTERNAL(kmConstructor.flags) + override fun Constructor.isAccessible(): Boolean = kmConstructor.visibility in listOf(Visibility.PUBLIC, Visibility.INTERNAL) - override fun Type.getPrimaryConstructor(): Constructor? = getConstructors().find { it.kmConstructor.isPrimary } + override fun Type.getPrimaryConstructor(): Constructor? = getConstructors().find { !it.kmConstructor.isSecondary } override fun Constructor.isValid(): Boolean = true @@ -82,6 +88,7 @@ class KaptSourceInfoResolver(private val processingEnv: ProcessingEnvironment, p override fun Type.asClassName(): ClassName = kmClass.asClassName() + @OptIn(KotlinPoetMetadataPreview::class) override fun Parameter.getTypeDeclaration(): Type? { val element = processingEnv.typeUtils.asElement(element.asType()) as? TypeElement val kmType = try { diff --git a/processor/src/main/kotlin/com/faendir/kotlin/autodsl/kapt/utils.kt b/processor/src/main/kotlin/com/faendir/kotlin/autodsl/kapt/utils.kt index dc75ed0..7adea98 100644 --- a/processor/src/main/kotlin/com/faendir/kotlin/autodsl/kapt/utils.kt +++ b/processor/src/main/kotlin/com/faendir/kotlin/autodsl/kapt/utils.kt @@ -2,7 +2,6 @@ package com.faendir.kotlin.autodsl.kapt import com.squareup.kotlinpoet.* import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy -import io.github.enjoydambience.kotlinbard.nullable import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName diff --git a/processor/src/test/kotlin/com/faendir/kotlin/autodsl/compileutils.kt b/processor/src/test/kotlin/com/faendir/kotlin/autodsl/compileutils.kt index 3284001..ca2f326 100644 --- a/processor/src/test/kotlin/com/faendir/kotlin/autodsl/compileutils.kt +++ b/processor/src/test/kotlin/com/faendir/kotlin/autodsl/compileutils.kt @@ -2,6 +2,7 @@ package com.faendir.kotlin.autodsl import com.faendir.kotlin.autodsl.kapt.KaptProcessor import com.faendir.kotlin.autodsl.ksp.KspProcessorProvider +import com.tschuchort.compiletesting.JvmCompilationResult import com.tschuchort.compiletesting.KotlinCompilation import com.tschuchort.compiletesting.SourceFile.Companion.fromPath import com.tschuchort.compiletesting.SourceFile.Companion.kotlin @@ -14,10 +15,10 @@ import strikt.assertions.isEqualTo import java.io.File import kotlin.test.assertNotNull -internal val KotlinCompilation.Result.workingDir: File +internal val JvmCompilationResult.workingDir: File get() = outputDirectory.parentFile!! -val KotlinCompilation.Result.kspGeneratedSources: List +val JvmCompilationResult.kspGeneratedSources: List get() = workingDir.resolve("ksp/sources/kotlin").collectSourceFiles() private fun File.collectSourceFiles(): List { @@ -50,13 +51,13 @@ fun compileKsp( symbolProcessorProviders = listOf(KspProcessorProvider()) } val pass1 = compilation.compile() - expectThat(pass1).get(KotlinCompilation.Result::exitCode).isEqualTo(expect) + expectThat(pass1).get(JvmCompilationResult::exitCode).isEqualTo(expect) val pass2 = KotlinCompilation().apply { inheritClassPath = true jvmTarget = "1.8" sources = compilation.sources + pass1.kspGeneratedSources.map { fromPath(it) } + kotlin("Eval.kt", eval) }.compile() - expectThat(pass2).get(KotlinCompilation.Result::exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + expectThat(pass2).get(JvmCompilationResult::exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) pass2.callEval() return pass1.kspGeneratedSources } @@ -72,14 +73,14 @@ fun compileKapt( sources = listOf(kotlin("Source.kt", source), kotlin("Eval.kt", eval)) annotationProcessors = listOf(KaptProcessor()) }.compile() - expectThat(result).get(KotlinCompilation.Result::exitCode).isEqualTo(expect) + expectThat(result).get(JvmCompilationResult::exitCode).isEqualTo(expect) if (expect == KotlinCompilation.ExitCode.OK) { result.callEval() } return result.generatedFiles.filter { it.extension == "kt" } } -private fun KotlinCompilation.Result.callEval() = classLoader.loadClass("EvalKt").declaredMethods +private fun JvmCompilationResult.callEval() = classLoader.loadClass("EvalKt").declaredMethods .first { it.name[0] != '$' /* skip jacoco added function */ } .run { isAccessible = true diff --git a/renovate.json b/renovate.json index 5f12ca7..40a4ac7 100644 --- a/renovate.json +++ b/renovate.json @@ -20,7 +20,7 @@ "automergeType": "branch" }, { - "matchPackagePatterns": ["^org\\.jetbrains\\.kotlin", "^com\\.google\\.devtools\\.ksp"], + "matchPackagePatterns": ["^org\\.jetbrains\\.kotlin", "^com\\.google\\.devtools\\.ksp", "^dev\\.zacsweers\\.kctfork"], "groupName": "kotlin" } ] diff --git a/sample-ksp/build.gradle.kts b/sample-ksp/build.gradle.kts index a19adf7..19b05b3 100644 --- a/sample-ksp/build.gradle.kts +++ b/sample-ksp/build.gradle.kts @@ -8,16 +8,3 @@ dependencies { implementation(projects.annotations) ksp(projects.processor) } - -sourceSets { - main { - java { - srcDir(file("$buildDir/generated/ksp/main/kotlin")) - } - } - test { - java { - srcDir(file("$buildDir/generated/ksp/test/kotlin")) - } - } -}