Skip to content

Commit

Permalink
Interop for kotlinx metadata (#3)
Browse files Browse the repository at this point in the history
* Start metadata

* Updates

* Updates

* Metadata updates

* Updates

* upodates

* Updates

* Updates

* Update

* Formatting

* Updates

* Fix

* Update version

* Add annotations

* Fix properties

* Bump ver

* stable

---------

Co-authored-by: BuildTools <[email protected]>
  • Loading branch information
deotimedev and BuildTools authored Jan 30, 2023
1 parent ff4bcc4 commit 1231270
Show file tree
Hide file tree
Showing 23 changed files with 493 additions and 37 deletions.
1 change: 1 addition & 0 deletions all/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ plugins {
dependencies {
api(project(":dsl"))
api(project(":ksp"))
api(project(":metadata"))
}

publishing {
Expand Down
6 changes: 4 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ allprojects {
}

tasks.withType<KotlinCompile> {
kotlinOptions.jvmTarget = "1.8"
kotlinOptions.languageVersion = "1.8"
kotlinOptions {
jvmTarget = "1.8"
languageVersion = "1.8"
}
}


Expand Down
48 changes: 33 additions & 15 deletions dsl/src/main/kotlin/me/deotime/kpoetdsl/Attributes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ interface Attributes {
fun build(): T

companion object {
inline fun <T : Attributes.Buildable<B>, B> T.buildWith(assembler: Assembler<T>) =
inline fun <T : Buildable<B>, B> T.buildWith(assembler: Assembler<T>) =
apply(assembler).build()
}
}
Expand All @@ -56,6 +56,7 @@ interface Attributes {
interface Modifiers : Has {
val modifiers: List<KModifier>
fun modifiers(vararg modifiers: KModifier)
fun modifiers(modifiers: List<KModifier>)
fun modifiers(assembler: CollectionAssembler<KModifier>)
}

Expand All @@ -72,6 +73,7 @@ interface Attributes {

interface Parameters : Has {
val typeParameters: List<TypeVariableName>
fun typeParameters(params: Iterable<TypeVariableName>)
fun typeParameters(builder: CollectionAssembler<TypeVariableName>)
}

Expand All @@ -83,6 +85,7 @@ interface Attributes {

interface Annotations : Has {
val annotations: List<AnnotationSpec>

@KotlinPoetDsl
fun annotate(assembler: Assembler<AnnotationBuilder>)

Expand All @@ -102,8 +105,10 @@ interface Attributes {

interface Functions : Has, Operator.Scope {
val functions: List<FunSpec>

@KotlinPoetDsl
fun function(assembler: Assembler<FunctionBuilder>)

@KotlinPoetDsl
fun function(name: String, assembler: Assembler<FunctionBuilder>)

Expand All @@ -115,11 +120,13 @@ interface Attributes {

@KotlinPoetDsl
fun <T : TypeBuilder> type(name: String, kind: TypeKind<T, *>, assembler: Assembler<T>)

@KotlinPoetDsl
fun <T : TypeBuilder> type(kind: TypeKind<T, TypeKind.Naming.None>, assembler: Assembler<T>)

@KotlinPoetDsl
fun enum(name: String, assembler: Assembler<TypeBuilder.Enum>)

@KotlinPoetDsl
fun annotation(name: String, assembler: Assembler<TypeBuilder.Annotation>)

Expand All @@ -128,8 +135,10 @@ interface Attributes {

interface Properties : Has {
val properties: List<PropertySpec>

@KotlinPoetDsl
fun property(assembler: Assembler<PropertyBuilder>)

@KotlinPoetDsl
fun property(name: String, assembler: Assembler<PropertyBuilder>)

Expand Down Expand Up @@ -187,16 +196,23 @@ interface Attributes {
override fun modifiers(vararg modifiers: KModifier) {
holder(source) += modifiers
}

override fun modifiers(modifiers: List<KModifier>) {
holder(source) += modifiers
}
}

internal fun <S> parameterizedTypeVisitor(
cozy: SourcedCozy<S>,
visitor: (S) -> MutableCollection<TypeVariableName>
holder: (S) -> MutableCollection<TypeVariableName>
): Has.Type.Parameters =
object : Has.Type.Parameters, Sourced<S> by sourcedByCozy(cozy) {
override val typeParameters get() = visitor(source).toList()
override val typeParameters get() = holder(source).toList()
override fun typeParameters(params: Iterable<TypeVariableName>) {
holder(source) += params
}
override fun typeParameters(builder: CollectionAssembler<TypeVariableName>) {
buildCollectionTo(visitor(source), builder)
buildCollectionTo(holder(source), builder)
}
}

Expand Down Expand Up @@ -245,14 +261,16 @@ interface Attributes {
holder: (S) -> MutableList<in TypeSpec>
): Has.Classes =
object : Has.Classes, Sourced<S> by sourcedByCozy(cozy) {
@Suppress("UselessCallOnCollection") // inspection is wrong
@Suppress("UselessCallOnCollection") // https://youtrack.jetbrains.com/issue/KTIJ-24175
override val types
get() = holder(source).filterIsInstance<TypeSpec>()

@Suppress("UNCHECKED_CAST")
override fun <T : TypeBuilder> type(name: String, kind: TypeKind<T, *>, assembler: Assembler<T>) {
val builder =
(if (kind == TypeKind.Scope.Enum) TypeBuilder.Enum.cozy() else TypeBuilder.cozy(kind)) as T

val builder = Cozy<T>().let { cozyHolder ->
kind.builder(cozyHolder, kind).also { cozyHolder(it) }
}
holder(source) += builder.buildWith {
name(name)
assembler()
Expand Down Expand Up @@ -286,14 +304,14 @@ interface Attributes {
override fun build() = holder(source)
}

internal fun <S> codeVisitor(cozy: SourcedCozy<S>, visitor: (S, CodeBlock) -> Unit): Has.Code =
internal fun <S> codeVisitor(cozy: SourcedCozy<S>, holder: (S, CodeBlock) -> Unit): Has.Code =
object : Has.Code, Sourced<S> by sourcedByCozy(cozy) {
override fun code(assembler: Assembler<CodeBuilder>) {
visitor(source, CodeBuilder.cozy().buildWith(assembler))
holder(source, CodeBuilder.cozy().buildWith(assembler))
}

override fun code(format: String, vararg args: Any?) {
visitor(source, CodeBlock.of(format, *args))
holder(source, CodeBlock.of(format, *args))
}
}

Expand Down Expand Up @@ -321,23 +339,23 @@ interface Attributes {
}
}

internal fun <S> functionVisitor(cozy: SourcedCozy<S>, visitor: (S) -> MutableList<in FunSpec>): Has.Functions =
internal fun <S> functionVisitor(cozy: SourcedCozy<S>, holder: (S) -> MutableList<in FunSpec>): Has.Functions =
object : Has.Functions, Sourced<S> by sourcedByCozy(cozy) {

@Suppress("UselessCallOnCollection") // inspection is wrong
override val functions
get() = visitor(source).filterIsInstance<FunSpec>()
get() = holder(source).filterIsInstance<FunSpec>()

override fun function(assembler: Assembler<FunctionBuilder>) {
visitor(source) += FunctionBuilder.cozy().buildWith(assembler)
holder(source) += FunctionBuilder.cozy().buildWith(assembler)
}

override fun function(name: String, assembler: Assembler<FunctionBuilder>) {
visitor(source) += FunctionBuilder.cozy().apply { name(name) }.buildWith(assembler)
holder(source) += FunctionBuilder.cozy().apply { name(name) }.buildWith(assembler)
}

override fun FunSpec.unaryPlus() {
visitor(source) += this
holder(source) += this
}
}

Expand Down
7 changes: 7 additions & 0 deletions dsl/src/main/kotlin/me/deotime/kpoetdsl/CodeBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package me.deotime.kpoetdsl
import com.squareup.kotlinpoet.CodeBlock
import me.deotime.kpoetdsl.Attributes.Buildable.Companion.buildWith
import me.deotime.kpoetdsl.Cozy.Initializer.Simple.Companion.cozy
import me.deotime.kpoetdsl.utils.Assembler

@KotlinPoetDsl
class CodeBuilder private constructor(private val cozy: Cozy<CodeBuilder>) :
Expand All @@ -15,8 +16,14 @@ class CodeBuilder private constructor(private val cozy: Cozy<CodeBuilder>) :
}

operator fun String.unaryPlus() = +this()

fun namedArguments(args: Map<String, Any?>) =
args.map { (name, value) -> "$name = $value" }.joinToString()

companion object Initializer : Cozy.Initializer.Simple<CodeBuilder> by cozied(::CodeBuilder)
}

operator fun String.invoke(vararg args: Any?) = CodeBlock.of(this, *args)

typealias CodeAssembler = Assembler<CodeBuilder>

6 changes: 5 additions & 1 deletion dsl/src/main/kotlin/me/deotime/kpoetdsl/FileBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ class FileBuilder private constructor(private val cozy: Cozy<FileBuilder>) :

inline fun <reified T> import() = import(T::class)

override fun build() = KotlinCode(source.build())
override fun build() = KotlinCode(
StringBuilder().apply(source.build()::writeTo).toString(),
source.name,
source.packageName
)

companion object Initializer : Cozy.Initializer.Simple<FileBuilder> by cozied(::FileBuilder)
}
Expand Down
12 changes: 12 additions & 0 deletions dsl/src/main/kotlin/me/deotime/kpoetdsl/FunctionBuilder.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package me.deotime.kpoetdsl

import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.TypeName
import com.squareup.kotlinpoet.asTypeName
import me.deotime.kpoetdsl.Attributes.Buildable.Companion.buildWith
Expand Down Expand Up @@ -29,6 +31,7 @@ class FunctionBuilder private constructor(private val cozy: Cozy<FunctionBuilder
modifiers = FunSpec.Builder::modifiers,
annotations = FunSpec.Builder::annotations,
),
Attributes.Has.Type.Parameters by Attributes.parameterizedTypeVisitor(cozy, FunSpec.Builder::typeVariables),
Maybe<FunSpec.Builder> by maybe(),
Required.Holder by requiredHolder(),
Operator.Scope {
Expand Down Expand Up @@ -93,8 +96,17 @@ class FunctionBuilder private constructor(private val cozy: Cozy<FunctionBuilder
}

fun receiver(type: KClass<*>) = receiver(type.asTypeName())

@OptIn(ExperimentalKotlinPoetApi::class)
fun context(types: Iterable<TypeName>){
source.contextReceivers(types)
}
inline fun <reified T> receiver() = receiver(typeOf<T>().asTypeName())

operator fun ParameterSpec.unaryPlus() {
source.addParameter(this)
}

private fun nameNoOp() {
name("no-op")
}
Expand Down
15 changes: 9 additions & 6 deletions dsl/src/main/kotlin/me/deotime/kpoetdsl/KotlinCode.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package me.deotime.kpoetdsl

import com.squareup.kotlinpoet.FileSpec
data class KotlinCode(
val source: String,
val name: String,
val packageName: String,
) {

class KotlinCode(
override val source: FileSpec
) : Attributes.Sourced<FileSpec> {
private val value = StringBuilder().apply(source::writeTo).toString()
// TODO This is obviously not reliable and should be actually be checked somehow
fun withoutPublic() = copy(source = source.replace("public ", ""))
fun properFormatting() = copy(source = source.replace(" ", "\t"))

override fun toString() = value
override fun toString() = source
}
3 changes: 3 additions & 0 deletions dsl/src/main/kotlin/me/deotime/kpoetdsl/KotlinPoetDsl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ package me.deotime.kpoetdsl

@DslMarker
annotation class KotlinPoetDsl

@RequiresOptIn
annotation class ExperimentalKotlinPoetDSL
31 changes: 20 additions & 11 deletions dsl/src/main/kotlin/me/deotime/kpoetdsl/TypeBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import me.deotime.kpoetdsl.Attributes.Buildable.Companion.buildWith
import me.deotime.kpoetdsl.Attributes.Has.Annotations.Companion.annotate
import me.deotime.kpoetdsl.Cozy.Initializer.Simple.Companion.cozy
import me.deotime.kpoetdsl.TypeKind.Scope.Companion.Annotation
import me.deotime.kpoetdsl.TypeKind.Scope.Companion.Anonymous
import me.deotime.kpoetdsl.TypeKind.Scope.Companion.Enum
import me.deotime.kpoetdsl.TypeKind.Scope.Companion.Unknown
import me.deotime.kpoetdsl.utils.Assembler
Expand All @@ -20,7 +21,7 @@ import kotlin.annotation.AnnotationTarget as KTAnnoTarget

@KotlinPoetDsl
sealed class TypeBuilder private constructor(
private val cozy: Cozy<out TypeBuilder>,
protected val cozy: Cozy<out TypeBuilder>,
private val kind: TypeKind<*, *>
) :
Attributes.Sourced<TypeSpec.Builder>,
Expand All @@ -38,7 +39,7 @@ sealed class TypeBuilder private constructor(
Required.Holder by requiredHolder(),
Maybe<TypeSpec.Builder> by maybe() {

override val source by withRequired { kind.init(if (kind == TypeKind.Scope.Enum) "no-op" else name) }
override val source by withRequired { kind.init(if (kind == TypeKind.Scope.Anonymous) "no-op" else name) }

private val primaryConstructor = FunctionBuilder.cozy().apply { constructor() }

Expand Down Expand Up @@ -94,7 +95,7 @@ sealed class TypeBuilder private constructor(
inline val entries get(): Map<String, TypeSpec> = source.enumConstants
@KotlinPoetDsl
inline fun entry(name: String, assembler: Assembler<TypeBuilder> = { }) {
val spec = TypeBuilder.cozy(TypeKind.Scope.Enum).buildWith(assembler)
val spec = TypeBuilder.cozy(TypeKind.Scope.Anonymous).buildWith(assembler)
source.addEnumConstant(name, spec)
}

Expand Down Expand Up @@ -161,10 +162,14 @@ sealed class TypeBuilder private constructor(
}


private class Normal(cozy: Cozy<out TypeBuilder>, kind: TypeKind<*, *>) : TypeBuilder(cozy, kind)
internal class Normal(cozy: Cozy<out TypeBuilder>, kind: TypeKind<*, *>) : TypeBuilder(cozy, kind)

companion object Initializer :
Cozy.Initializer<TypeBuilder, TypeKind<*, *>> by cozied(::Normal),
Cozy.Initializer<TypeBuilder, TypeKind<*, *>> by cozied(
{ cozy, context ->
(context as TypeKind<TypeBuilder, *>).builder(cozy, context)
}
),
Crumple<TypeSpec, TypeBuilder> {
override fun TypeSpec.invoke(closure: TypeBuilder.() -> Unit) = cozy(TypeKind.Scope.Unknown).apply {
value = this@invoke.toBuilder()
Expand All @@ -173,10 +178,11 @@ sealed class TypeBuilder private constructor(

}

private typealias NormalTypeKind = TypeKind<TypeBuilder, TypeKind.Naming>

@JvmInline
value class TypeKind<T : TypeBuilder, N : TypeKind.Naming> private constructor(val init: (String) -> TypeSpec.Builder) {
class TypeKind<T : TypeBuilder, N : TypeKind.Naming> private constructor(
val builder: (Cozy<T>, TypeKind<*, *>) -> T,
val init: (String) -> TypeSpec.Builder
) {

operator fun getValue(ref: Any?, prop: KProperty<*>?) = this

Expand All @@ -187,16 +193,19 @@ value class TypeKind<T : TypeBuilder, N : TypeKind.Naming> private constructor(v
interface Scope {
companion object : Scope {

private fun NormalTypeKind(init: (String) -> TypeSpec.Builder): TypeKind<TypeBuilder, Naming> = TypeKind(TypeBuilder::Normal, init)

val Scope.Class by NormalTypeKind(TypeSpec.Companion::classBuilder)
val Scope.Interface by NormalTypeKind(TypeSpec.Companion::interfaceBuilder)
val Scope.Annotation by NormalTypeKind(TypeSpec.Companion::annotationBuilder)
val Scope.Object by NormalTypeKind(TypeSpec.Companion::objectBuilder)
val Scope.Value by NormalTypeKind(TypeSpec.Companion::valueClassBuilder)
val Scope.Functional by NormalTypeKind(TypeSpec.Companion::funInterfaceBuilder)
val Scope.Anonymous by TypeKind<TypeBuilder, Naming.None> { TypeSpec.anonymousClassBuilder() }
val Scope.Enum by TypeKind<TypeBuilder.Enum, Naming>(TypeSpec.Companion::enumBuilder)
val Scope.Anonymous by TypeKind<TypeBuilder, Naming.None>(TypeBuilder::Normal) { TypeSpec.anonymousClassBuilder() }
@Suppress("UNCHECKED_CAST")
val Scope.Enum by TypeKind<TypeBuilder.Enum, Naming>({ cozy, _ -> TypeBuilder.Enum(cozy as Cozy<TypeBuilder.Enum>) }, TypeSpec.Companion::enumBuilder)

internal val Scope.Unknown by TypeKind<Nothing, Nothing> { error("Unknown kind cannot be created") }
internal val Scope.Unknown by TypeKind<Nothing, Nothing>({ _, _ -> error("Unknown kind cannot be created") }) { error("Unknown kind cannot be created") }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package me.deotime.kpoetdsl.utils
interface CollectionBuilder<T> {
operator fun T.unaryPlus()
operator fun T.unaryMinus()

operator fun Iterable<T>.unaryPlus() = forEach { it.unaryPlus() }
operator fun Iterable<T>.unaryMinus() = forEach { it.unaryMinus() }
}

@PublishedApi
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
kotlin.code.style=official
version = 1.2.0
version = 2.0.2
Loading

0 comments on commit 1231270

Please sign in to comment.