Skip to content

Commit

Permalink
Updates for final release
Browse files Browse the repository at this point in the history
- use codegen.kt within codegen.kt
- Correctly set JVM targets
- Stop publishing Gradle metadata
- Add addAnnotation to Annotatable.Builder instead
- No longer mark SubSpecDelegateProvider as @CodeGenInternal
  • Loading branch information
DRSchlaubi committed Sep 12, 2023
1 parent 73f2262 commit fc4be35
Show file tree
Hide file tree
Showing 27 changed files with 248 additions and 178 deletions.
2 changes: 1 addition & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions .idea/jsonSchemas.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ allprojects {

repositories {
mavenCentral()
maven("https://oss.sonatype.org/content/repositories/snapshots/")
}
}

subprojects {
configureJVMTarget()
}

tasks {
dokkaHtmlMultiModule {
outputDirectory = layout.projectDirectory.dir("docs/api")
Expand Down
35 changes: 35 additions & 0 deletions buildSrc/src/main/kotlin/JVMTarget.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import gradle.kotlin.dsl.accessors._8d1ef46afdac024fc616c6e49cc7c389.java
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.kotlin.dsl.the
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
import org.gradle.kotlin.dsl.*
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget

fun Project.configureJVMTarget() {
plugins.withId("org.gradle.java") {
java {
sourceCompatibility = JavaVersion.VERSION_1_8
}
}

plugins.withId("org.jetbrains.kotlin.jvm") {
the<KotlinJvmProjectExtension>().compilerOptions {
jvmTarget = JvmTarget.JVM_1_8
}
}

plugins.withId("org.jetbrains.kotlin.multiplatform") {
the<KotlinMultiplatformExtension>().targets {
withType<KotlinJvmTarget>().configureEach {
compilations.all {
compilerOptions.configure {
jvmTarget = JvmTarget.JVM_1_8
}
}
}
}
}
}
9 changes: 8 additions & 1 deletion buildSrc/src/main/kotlin/kord-publishing.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ tasks {

mavenPublishing {
publishToMavenCentral()
if (false) {
if (!System.getenv("ORG_GRADLE_PROJECT_signingInMemoryKey").isNullOrBlank()) {
signAllPublications()
}

Expand Down Expand Up @@ -82,6 +82,13 @@ plugins.withId("org.jetbrains.kotlin.multiplatform") {

withType<PublishToMavenRepository> {
enabled = name == "publishMavenPublicationToMavenRepository"
|| name == "publishMavenPublicationToMavenCentralRepository"
}

// Theoretically, this makes us loose information, however, that information is not relevant, since this is
// pretty much only a JVM lib targeting JVM 1.8 (so validation of that is unnecessary)
withType<GenerateModuleMetadata> {
enabled = false
}
}
}
2 changes: 1 addition & 1 deletion code-processor/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ kotlin {
}

dependencies {
implementation(libs.kotlinpoet)
implementation(libs.codegen.kotlinpoet)
implementation(libs.kotlinpoet.ksp)
implementation(libs.ksp.api)
implementation(projects.kspAnnotations)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import com.squareup.kotlinpoet.ksp.writeTo
import dev.kord.codegen.generator.packageName
import dev.kord.codegen.generator.utils.*
import dev.kord.codegen.generator.visitors.VisitorBase
import dev.kord.codegen.kotlinpoet.AnnotationSpec
import dev.kord.codegen.kotlinpoet.LambdaTypeName
import dev.kord.codegen.kotlinpoet.TypeAliasSpec
import dev.kord.codegen.ksp.companionDeclaration

/**
Expand Down Expand Up @@ -46,12 +49,11 @@ object BuilderVisitor : VisitorBase() {

val addBuilder = RunOnceFunction<FileSpec.Builder, String> { file, builderName ->
file.optInForContracts()
val alias = LambdaTypeName.get(
val alias = LambdaTypeName(
classDeclaration.toClassName().nestedClass("Builder"),
returnType = UNIT
).copy(annotations = listOf(AnnotationSpec.builder(CODEGEN_DSL).build()))
val typeAliasSpec =
TypeAliasSpec.builder(builderName, alias).build()
).copy(annotations = listOf(AnnotationSpec(CODEGEN_DSL)))
val typeAliasSpec = TypeAliasSpec(builderName, alias)
file.members.add(0, typeAliasSpec)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ package dev.kord.codegen.generator.constructor_inliner
import com.google.devtools.ksp.symbol.KSValueParameter
import com.squareup.kotlinpoet.*
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import com.squareup.kotlinpoet.jvm.jvmWildcard
import com.squareup.kotlinpoet.ksp.toClassName
import dev.kord.codegen.generator.utils.*
import dev.kord.codegen.generator.builder_functions.FactoryFunction
import dev.kord.codegen.kotlinpoet.FunSpec
import dev.kord.codegen.kotlinpoet.withControlFlow

context(FactoryFunction)
private fun FunSpec.Builder.getValueParametersList(packageName: String): CodeBlock {
Expand Down Expand Up @@ -72,16 +75,16 @@ fun FactoryFunction.generateInlinedConstructorWithNameDelegate(
returns(SUB_SPEC_DELEGATE_PROVIDER.parameterizedBy(specType.toClassName()))

val code = buildCodeBlock {
beginControlFlow("return·%M { %L ->", PRODUCE_BY_NAME, constructor.nameProperty)
addStatement(
"%L(%L).also(::%L)",
builderFunctionName.takeIf { !constructor.useQualifiedName }
?.escapeIfNecessary()
?: "$packageName.$builderFunctionName",
valueParameterList,
constructor.functionName,
)
endControlFlow()
withControlFlow("return·%M { %L ->", PRODUCE_BY_NAME, constructor.nameProperty) {
addStatement(
"%L(%L).also(::%L)",
builderFunctionName.takeIf { !constructor.useQualifiedName }
?.escapeIfNecessary()
?: "$packageName.$builderFunctionName",
valueParameterList,
constructor.functionName,
)
}
}

addCode(code)
Expand All @@ -105,8 +108,12 @@ private fun FactoryFunction.generateInlinedConstructor(
}
val builderParameter = getBuilderParameter(packageName)

return FunSpec.builder(name).apply {
receiver(constructor.forClass.toClassName())
return FunSpec(name) {
if (constructor.forClass.declaration.typeParameters.isNotEmpty()) {
receiver(constructor.forClass.toClassName().parameterizedBy(STAR))
} else {
receiver(constructor.forClass.toClassName())
}

if (hasBuilder) {
if (!noinline) {
Expand All @@ -120,5 +127,5 @@ private fun FactoryFunction.generateInlinedConstructor(
if (hasBuilder) {
addParameter(builderParameter)
}
}.build()
}
}
12 changes: 8 additions & 4 deletions code-processor/src/main/kotlin/reification/Reifyer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import com.squareup.kotlinpoet.ksp.*
import dev.kord.codegen.generator.utils.addAnnotationsFromFunction
import dev.kord.codegen.generator.utils.toParameterSpec
import dev.kord.codegen.generator.utils.toTypeParameterResolver
import dev.kord.codegen.kotlinpoet.CodeBlock
import dev.kord.codegen.kotlinpoet.FunSpec
import java.lang.reflect.Modifier
import kotlin.reflect.KClass

Expand All @@ -32,7 +34,7 @@ val TYPE_NAME_OF = MemberName("com.squareup.kotlinpoet", "typeNameOf")
fun MaybeReifiableFunction.reify(): FunSpec {
val nameAllocator = NameAllocator()

return FunSpec.builder(simpleName.asString()).apply {
return FunSpec(simpleName.asString()) {
addModifiers(KModifier.INLINE)
// If the parent of the function is a class,
// we need to define the reified function as an extension of that class
Expand All @@ -55,7 +57,9 @@ fun MaybeReifiableFunction.reify(): FunSpec {
}
} else if (extensionReceiver != null) {
// otherwise, just use the receiver of the actual function
receiver(extensionReceiver.toTypeName())
if (!extensionReceiver.resolve().isError) {
receiver(extensionReceiver.toTypeName())
}
}

val typeVariableResolver = typeVariables.toTypeParameterResolver()
Expand Down Expand Up @@ -91,7 +95,7 @@ fun MaybeReifiableFunction.reify(): FunSpec {
else -> error("Unreifiable type: ${it.type}")
}
} else {
buildCodeBlock {
CodeBlock {
if (KModifier.VARARG in it.modifiers) {
add("%N·=·", it)
}
Expand All @@ -102,7 +106,7 @@ fun MaybeReifiableFunction.reify(): FunSpec {

addAnnotationsFromFunction(this@reify)
addCode("return·%N(%L)", simpleName.asString(), valueParameters)
}.build()
}
}

@PublishedApi
Expand Down
10 changes: 4 additions & 6 deletions code-processor/src/main/kotlin/utils/ContractHelper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package dev.kord.codegen.generator.utils

import com.squareup.kotlinpoet.*
import com.squareup.kotlinpoet.MemberName.Companion.member
import dev.kord.codegen.kotlinpoet.addAnnotation
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind

private val OPT_IN = ClassName("kotlin", "OptIn")
private val CONTRACT = MemberName("kotlin.contracts", "contract")
Expand All @@ -26,9 +26,7 @@ fun FunSpec.Builder.addCallsInPlaceExactlyOnce(builderProperty: ParameterSpec) {
* Adds the required opt-in for [ExperimentalContracts].
*/
fun Annotatable.Builder<*>.optInForContracts() {
addAnnotation(
AnnotationSpec.builder(OPT_IN)
.addMember("%T::class", ClassName("kotlin.contracts", "ExperimentalContracts"))
.build()
)
addAnnotation(OPT_IN) {
addMember("%T::class", ClassName("kotlin.contracts", "ExperimentalContracts"))
}
}
11 changes: 0 additions & 11 deletions code-processor/src/main/kotlin/utils/KSPUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,6 @@ fun KSValueParameter.toParameterSpec(typeParamResolver: TypeParameterResolver =
}
.build()

fun KSFunctionDeclaration.toFunSpec(typeParamResolver: TypeParameterResolver = TypeParameterResolver.EMPTY) =
FunSpec.builder(simpleName.asString())
.apply {
val declarationTypeResolver = parentDeclaration!!.typeParameters.toTypeParameterResolver()
val functionResolver = typeParameters.toTypeParameterResolver(declarationTypeResolver)
addParameters(this@toFunSpec.parameters.map { it.toParameterSpec(functionResolver) })
addModifiers(this@toFunSpec.modifiers.mapNotNull(Modifier::toKModifier))
returns(ANY)
returns(returnType!!.toTypeName(parentDeclaration!!.typeParameters.toTypeParameterResolver(typeParamResolver)))
}.build()

private val KSValueParameter.modifiers: Set<KModifier>
get() = buildSet {
if (this is KSModifierListOwner) {
Expand Down
23 changes: 17 additions & 6 deletions code-processor/src/main/kotlin/utils/Names.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
@file:OptIn(CodeGenInternal::class)

package dev.kord.codegen.generator.utils

import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.MemberName
import com.squareup.kotlinpoet.asClassName
import dev.kord.codegen.kotlinpoet.CodeGenDsl
import dev.kord.codegen.kotlinpoet.CodeGenInternal
import dev.kord.codegen.kotlinpoet.asMemberName
import dev.kord.codegen.kotlinpoet.delegate.SubSpecDelegateProvider
import dev.kord.codegen.kotlinpoet.delegate.produceByName
import dev.kord.codegen.kotlinpoet.emptyCodeBlock
import kotlin.reflect.KFunction

private val produceByName: KFunction<SubSpecDelegateProvider<String>> = ::produceByName

val CODEGEN_DSL = ClassName("dev.kord.codegen.kotlinpoet", "CodeGenDsl")
val EMPTY_CODE_BLOCK = MemberName("dev.kord.codegen.kotlinpoet", "emptyCodeBlock")
val PRODUCE_BY_NAME = MemberName("dev.kord.codegen.kotlinpoet.delegate", "produceByName")
val SUB_SPEC_DELEGATE_PROVIDER = ClassName("dev.kord.codegen.kotlinpoet.delegate", "SubSpecDelegateProvider")
val CODEGEN_DSL = CodeGenDsl::class.asClassName()
val EMPTY_CODE_BLOCK = ::emptyCodeBlock.asMemberName()
val PRODUCE_BY_NAME = produceByName.asMemberName()
val SUB_SPEC_DELEGATE_PROVIDER = SubSpecDelegateProvider::class.asClassName()
3 changes: 2 additions & 1 deletion code-processor/src/main/kotlin/utils/ParameterHelpers.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package dev.kord.codegen.generator.utils

import com.squareup.kotlinpoet.*
import dev.kord.codegen.kotlinpoet.CodeBlock

/**
* Maps an [Iterable] of [ParameterSpecs][ParameterSpec] to a [CodeBlock], representing the value parameter list
* of a function call.
*/
fun Iterable<ParameterSpec>.mapToValueParameterList() =
map {
buildCodeBlock {
CodeBlock {
// If the parameter is a varag, we need to spread it, which can be done
// using the spread operator or using named arguments
// however using named arguments works regardless of the position of the argument
Expand Down
7 changes: 7 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@ kotlin = "1.9.10"
kotlinpoet = "1.14.2"
ksp = "1.9.10-1.0.13"

# The compiled binary of codegen.kt we use to compile codegen.kt itself
codegen-kt = "main-SNAPSHOT"

[libraries]
ksp-api = { group = "com.google.devtools.ksp", name = "symbol-processing-api", version.ref = "ksp" }
kotlinpoet = { group = "com.squareup", name = "kotlinpoet", version.ref = "kotlinpoet" }
kotlinpoet-ksp = { group = "com.squareup", name = "kotlinpoet-ksp", version.ref = "kotlinpoet" }

codegen-kotlinpoet = { group = "dev.kord.codegen", name = "kotlinpoet", version = "main-20230912.212936-5" }
codegen-ksp = { group = "dev.kord.codegen", name = "ksp", version = "main-20230912.211940-5" }
codegen-ksp-processor = { group = "dev.kord.codegen", name = "ksp-processor", version = "main-20230912.211940-7" }

mockk = { group = "io.mockk", name = "mockk", version = "1.13.7" }

kotlin-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlin" }
Expand Down
Loading

0 comments on commit fc4be35

Please sign in to comment.