Skip to content

Commit

Permalink
Release 1.1.0 (#4)
Browse files Browse the repository at this point in the history
* (build-logic, core logging):Add Context function
- Publish generated files
- Restructure file generation logic

* core: Fix indent of contract call

* all: Unify test platform APIs

* Add serialization module

Co-Authored-By: Michael Rittmeister <michael@rittmeister.in>

* Add EmptyJsonObject.kt

* Final preparations for 1.1.0

* Install Proper Java version in CI

* Fix kbson test dependency

* Fix gradle buildscript

* Export json dependency as api

* Fix ios api

Co-authored-by: NyCode <me@nycode.dev>
  • Loading branch information
DRSchlaubi and NyCodeGHG authored Apr 6, 2022
1 parent c82e642 commit 8d995f3
Show file tree
Hide file tree
Showing 56 changed files with 1,228 additions and 117 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ jobs:
name: Run tests and linter
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
- uses: gradle/gradle-build-action@v2
name: Validate Code
with:
Expand All @@ -30,6 +34,10 @@ jobs:
name: Run binary compatibility validator
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
- uses: gradle/gradle-build-action@v2
name: Validate Binary Compatibility
with:
Expand All @@ -50,6 +58,10 @@ jobs:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
- uses: gradle/gradle-build-action@v2
name: Publish Code
with:
Expand All @@ -61,6 +73,10 @@ jobs:
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v2
with:
distribution: 'temurin' # See 'Supported distributions' for available options
java-version: '17'
- uses: gradle/gradle-build-action@v2
name: Generate Docs
with:
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {


allprojects {
version = "1.0.1"
version = "1.1.0"
group = "dev.schlaubi"
repositories {
mavenCentral()
Expand Down
3 changes: 2 additions & 1 deletion buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ repositories {
}

dependencies {
implementation(kotlin("gradle-plugin", version = "1.6.10"))
implementation(kotlin("gradle-plugin", version = "1.6.20"))
implementation(kotlin("serialization", version = "1.6.20"))
implementation("org.jetbrains.dokka", "dokka-gradle-plugin", "1.6.10")
implementation("org.jlleitschuh.gradle", "ktlint-gradle", "10.2.1")
implementation("com.squareup", "kotlinpoet", "1.11.0")
Expand Down
44 changes: 44 additions & 0 deletions buildSrc/src/main/kotlin/AbstractGenerateFilesTask.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import com.squareup.kotlinpoet.FileSpec
import org.gradle.api.DefaultTask
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputDirectory
import java.nio.file.Files
import java.nio.file.Path

abstract class AbstractGenerateFilesTask : DefaultTask() {

@get:Input
abstract val `package`: Property<String>

@get:OutputDirectory
protected val outputDir = project.projectDir
.toPath()
.resolvePaths("src")

protected fun generateFile(
sourceSet: String,
fileName: String,
filter: (CharSequence) -> CharSequence = { it },
block: FileSpec.Builder.() -> Unit
) {
val file = FileSpec.builder(`package`.get(), fileName)
.apply(block)
.addFileComment("This file is generated by Gradle task $name please do not edit it manually")
.build()

val builder = StringBuilder()
file.writeTo(builder)
val newOutput = filter(builder)

val out = outputDir
.resolve("${sourceSet}Generated")
.resolvePaths(*file.packageName.split('.').toTypedArray())
.resolve("$fileName.kt")
Files.createDirectories(out.parent)
Files.writeString(out, newOutput)
}

protected fun Path.resolvePaths(vararg relative: String) =
relative.toList().fold(this) { parent, currentRelative -> parent.resolve(currentRelative) }
}
99 changes: 99 additions & 0 deletions buildSrc/src/main/kotlin/GenerateContextFunctionsTask.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.LambdaTypeName
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import com.squareup.kotlinpoet.TypeAliasSpec
import com.squareup.kotlinpoet.TypeVariableName
import org.gradle.api.tasks.TaskAction

const val returnTypeParameter = "ReturnType"

abstract class GenerateContextFunctionsTask : AbstractGenerateFilesTask() {
@TaskAction
fun generate() {
generateFile("common", "ContextFunctions", {
it.replace("import `?lambda_A(, [A-Z])*`?\n".toRegex(), "")
.replaceFirst("lambda_A", "A.() -> ReturnType")
.replace("`lambda_A(?:, ((?:(?:, )?[A-Z])*)`)?".toRegex(), "context($1) A.() -> ReturnType")
}) {
addImport("kotlin.contracts", "InvocationKind", "contract")

val alphabet = ('A'..'Z').toList()

val functions = ArrayList<FunSpec>(alphabet.size)

repeat(alphabet.size) {
val count = it + 1
val current = alphabet.take(count)
val typeVariables = (current.map(Char::toString) + returnTypeParameter).map { name ->
TypeVariableName(name)
}

val lambdaRaw = LambdaTypeName.get(
typeVariables.first(),
returnType = typeVariables.last()
).toString()

val lambda = "lambda_${typeVariables.dropLast(1).joinToString(", ") { variable -> variable.name }}"

val typeAlias = ClassName(packageName, "ContextReceiver$count")

addTypeAlias(
TypeAliasSpec.builder(typeAlias.simpleName, ClassName("", lambda))
.addModifiers(KModifier.PUBLIC)
.addTypeVariables(typeVariables)
.addKdoc(
"""
Lambda with $count context receivers.
@see context""".trimIndent()
)
.build()
)

val argumentList = if (count > 1) {
(typeVariables.subList(1, typeVariables.size - 1)
.map { variable -> variable.name.toLowerCase() } + 'a').joinToString(
", "
)
} else {
'a'
}

val function = FunSpec.builder("context")
.addModifiers(KModifier.PUBLIC, KModifier.INLINE)
.addTypeVariables(typeVariables)
.apply {
typeVariables.dropLast(1).forEach { type ->
addParameter(type.name.toLowerCase(), type)
}
}
.addParameter("block", typeAlias.parameterizedBy(typeVariables))
.returns(typeVariables.last())
.addKdoc(
"""
Adds ${
typeVariables.dropLast(1)
.joinToString("], [", "[", "]") { it.name.toLowerCase() }
} to the context of [block] and returns its return value.
""".trimIndent()
)
.addCode(
"""
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
return block.invoke($argumentList)
""".trimIndent()
)
.build()

functions += function
}

functions.forEach { addFunction(it) }
}
}
}
78 changes: 22 additions & 56 deletions buildSrc/src/main/kotlin/GenerateLoggerFunctionsTask.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,22 @@ import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.ParameterSpec
import org.gradle.api.DefaultTask
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.TaskAction
import org.intellij.lang.annotations.Language
import java.nio.file.Path

abstract class GenerateLoggerFunctionsTask : DefaultTask() {

@get:Input
abstract val `package`: Property<String>
abstract class GenerateLoggerFunctionsTask : AbstractGenerateFilesTask() {

@get:Input
abstract val logLevels: ListProperty<String>

private val outputDir = project.buildDir
.toPath()
.resolvePaths("generated", "src")

@Suppress("PrivatePropertyName")
private val KLogger = ClassName("mu", "KLogger")

init {
outputs.dir(outputDir)
}

@TaskAction
fun generate() {
generateFile("commonMain") {
generateFile("common", "InlinedLogger") {
logLevels.get().forEach { level ->
val functionName = "${level}Inlined"

Expand All @@ -41,49 +27,48 @@ abstract class GenerateLoggerFunctionsTask : DefaultTask() {
}
}

generateFile("jvmMain") {
generateFile("jvm", "InlinedLogger") {
generateLoggerFunctions { level, functionName ->
// e.g debug -> isDebugEnabled
val enabledPropertyName = "is${level[0].toUpperCase()}${level.drop(1)}Enabled"

debugLevelInlined(functionName, level, KModifier.ACTUAL) {
val code = """
if ($enabledPropertyName) {
$level(message())
}
""".trimIndent()
if ($enabledPropertyName) {
$level(message())
}
""".trimIndent()
addCode(code)
}
debugLevelInlinedWithThrowable(functionName, level, KModifier.ACTUAL) {
val code = """
if ($enabledPropertyName) {
val computedMessage = message()
$level(throwable) { computedMessage }
}
""".trimIndent()
if ($enabledPropertyName) {
val computedMessage = message()
$level(throwable) { computedMessage }
}
""".trimIndent()
addCode(code)
}
}
}

generateNonSLF4JFile("jsMain")
generateNonSLF4JFile("nativeMain")
generateNonSLF4JFile("js")
generateNonSLF4JFile("native")
}

private fun generateNonSLF4JFile(name: String) {
generateFile(name) {
addImport("mu", "KotlinLoggingLevel")
addImport("mu", "isLoggingEnabled")
generateFile(name, "InlinedLogger") {
addImport("mu", "KotlinLoggingLevel", "isLoggingEnabled")

generateLoggerFunctions { level, functionName ->
@Language("kotlin")
fun code(call: String) = """
if (KotlinLoggingLevel.${level.toUpperCase()}.isLoggingEnabled()) {
val computedLogMessage = message()
$call
}
""".trimIndent()
if (KotlinLoggingLevel.${level.toUpperCase()}.isLoggingEnabled()) {
val computedLogMessage = message()
$call
}
""".trimIndent()

debugLevelInlined(functionName, level, KModifier.ACTUAL) {
addCode(code("$level { computedLogMessage }"))
Expand All @@ -103,17 +88,6 @@ abstract class GenerateLoggerFunctionsTask : DefaultTask() {
}
}

private fun generateFile(sourceSet: String, block: FileSpec.Builder.() -> Unit) {
val file = FileSpec.builder(`package`.get(), "InlinedLogger")
.apply {
commonImports()
}
.apply(block)
.build()

file.writeTo(outputDir.resolve(sourceSet))
}

private fun FileSpec.Builder.debugLevelInlined(
functionName: String,
level: String?,
Expand Down Expand Up @@ -156,12 +130,4 @@ abstract class GenerateLoggerFunctionsTask : DefaultTask() {
code()
}
}


private fun FileSpec.Builder.commonImports() {
addImport(KLogger.packageName, KLogger.simpleName)
}
}

private fun Path.resolvePaths(vararg relative: String) =
relative.toList().fold(this) { parent, currentRelative -> parent.resolve(currentRelative) }
3 changes: 3 additions & 0 deletions buildSrc/src/main/kotlin/GradleExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ private fun notation(group: String, name: String, version: String? = null) =
fun KotlinDependencyHandler.api(group: String, name: String, version: String? = null) =
api(notation(group, name, version))

fun KotlinDependencyHandler.compileOnly(group: String, name: String, version: String? = null) =
compileOnly(notation(group, name, version))

fun KotlinDependencyHandler.implementation(group: String, name: String, version: String? = null) =
implementation(notation(group, name, version))

Expand Down
17 changes: 9 additions & 8 deletions buildSrc/src/main/kotlin/Targets.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,19 @@ inline fun KotlinMultiplatformExtension.native(block: KotlinMultiplatformExtensi
native(block())

fun KotlinMultiplatformExtension.native(target: KotlinNativeTarget) {
val nativeMain = sourceSets.maybeCreate("nativeMain").apply {
dependsOn(sourceSets.getByName("commonMain"))
}
val nativeTest = sourceSets.maybeCreate("nativeTest").apply {
dependsOn(sourceSets.getByName("commonTest"))
}

sourceSets.apply {
getByName(target.name + "Main") {
dependsOn(getByName("nativeMain"))
dependsOn(nativeMain)
}
getByName(target.name + "Test") {
dependsOn(getByName("nativeTest"))
dependsOn(nativeTest)
}
}
}

fun KotlinMultiplatformExtension.all() {
fullJs()
desktopAll()
appleMobilePlatforms()
}
9 changes: 9 additions & 0 deletions buildSrc/src/main/kotlin/all-platforms.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
plugins {
kotlin("multiplatform")
}

kotlin {
fullJs()
desktopAll()
appleMobilePlatforms()
}
Loading

0 comments on commit 8d995f3

Please sign in to comment.