Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
branches: [ main ]
pull_request:

env:
ORG_GRADLE_PROJECT_version: ${{ github.sha }}

jobs:

build:
Expand Down
11 changes: 5 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ on:
release:
types: [published]

env:
ORG_GRADLE_PROJECT_version: ${{ github.event.release.tag_name }}
ORG_GRADLE_PROJECT_githubRepository: ${{ github.repository }}

jobs:
release:
name: Release Artefacts
Expand All @@ -30,14 +34,11 @@ jobs:
run: ./gradlew clean dependencies
- name: Assemble Artefacts
run: ./gradlew assemble
env:
ORG_GRADLE_PROJECT_githubRepository: ${{ github.repository }}
- name: Release Artefacts
run: ./gradlew release
env:
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.PACKAGE_SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingKeyPassword: ${{ secrets.PACKAGE_SIGNING_KEY_PASSWORD }}
ORG_GRADLE_PROJECT_githubRepository: ${{ github.repository }}
ORG_GRADLE_PROJECT_githubToken: ${{ secrets.RELEASE_GITHUB_TOKEN }}
ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.OSSRH_USERNAME }}
ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.OSSRH_PASSWORD }}
Expand Down Expand Up @@ -66,9 +67,7 @@ jobs:
- name: Prepare
run: ./gradlew clean dependencies
- name: Generate Documentation
run: ./gradlew dokkaHtml
env:
ORG_GRADLE_PROJECT_githubRepository: ${{ github.repository }}
run: ./gradlew dokkaGenerate
- name: Publish Documentation
uses: peaceiris/actions-gh-pages@v3.9.3
with:
Expand Down
55 changes: 22 additions & 33 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import io.github.gradlenexus.publishplugin.NexusRepository
import org.gradle.api.JavaVersion.VERSION_1_8
import org.jetbrains.dokka.gradle.DokkaTask
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.dsl.JvmTarget

plugins {
kotlin("jvm") version "1.9.25"
id("com.palantir.git-version") version "3.2.0"
id("org.jetbrains.dokka") version "1.9.20"
kotlin("jvm") version "2.1.10"
id("org.jetbrains.dokka-javadoc") version "2.0.0"
id("org.jetbrains.dokka") version "2.0.0"
`maven-publish`
signing
id("io.github.gradle-nexus.publish-plugin") version "1.3.0"
idea
id("io.github.gradle-nexus.publish-plugin") version "2.0.0"
}

group = "de.joshuagleitze"
version = if (isSnapshot) versionDetails.gitHash else versionDetails.lastTag.drop("v")
status = if (isSnapshot) "snapshot" else "release"
version = if (version == "unspecified") "local" else version
status = if (version == "local") "snapshot" else "release"

repositories {
mavenCentral()
Expand All @@ -30,29 +28,23 @@ dependencies {
testImplementation(kotlin("reflect", KotlinVersion.CURRENT.toString()))
}

testRuntimeOnly(name = "junit-platform-launcher", group = "org.junit.platform", version = "1.12.1")
testRuntimeOnly(name = "junit-jupiter-engine", group = "org.junit.jupiter", version = "5.7.2")
}

idea {
module {
isDownloadSources = true
isDownloadJavadoc = true
}
}

tasks.withType<Test> {
tasks.withType<Test>().configureEach {
useJUnitPlatform()
reports.junitXml.required.set(true)
reports.junitXml.required = true
}

java {
sourceCompatibility = VERSION_1_8
targetCompatibility = VERSION_1_8
}

tasks.withType<KotlinCompile> {
kotlinOptions {
jvmTarget = "1.8"
kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_1_8
}
}

Expand All @@ -62,28 +54,28 @@ val githubRepository: String? by project
val githubOwner = githubRepository?.split("/")?.get(0)
val githubToken: String? by project

val sourcesJar by tasks.creating(Jar::class) {
val sourcesJar by tasks.registering(Jar::class) {
group = "build"
description = "Assembles the source code into a jar"
archiveClassifier.set("sources")
from(sourceSets.main.get().allSource)
}

tasks.withType<DokkaTask> {
dokkaSourceSets.named("main") {
dokka {
dokkaSourceSets.main {
sourceLink {
localDirectory.set(file("src/main/kotlin"))
remoteUrl.set(uri("https://github.com/$githubRepository/blob/main/src/main/kotlin").toURL())
remoteLineSuffix.set("#L")
localDirectory = file("src/main/kotlin")
remoteUrl = uri("https://github.com/$githubRepository/blob/main/src/main/kotlin")
remoteLineSuffix = "#L"
}
}
}

val dokkaJar by tasks.creating(Jar::class) {
val dokkaJar by tasks.registering(Jar::class) {
group = "build"
description = "Assembles the Kotlin docs with Dokka"
archiveClassifier.set("javadoc")
from(tasks.named("dokkaJavadoc"))
from(tasks.named("dokkaGeneratePublicationJavadoc"))
}

artifacts {
Expand Down Expand Up @@ -166,15 +158,12 @@ signing {
val closeAndReleaseStagingRepository by project.tasks
closeAndReleaseStagingRepository.mustRunAfter(mavenCentral.publishTask)

task("release") {
val release by tasks.registering {
group = "release"
description = "Releases the project to Maven Central"
dependsOn(githubPackages.publishTask, mavenCentral.publishTask, closeAndReleaseStagingRepository)
}

val Project.isSnapshot get() = versionDetails.commitDistance != 0
fun String.drop(prefix: String) = if (this.startsWith(prefix)) this.drop(prefix.length) else this

val Project.versionDetails get() = (this.extra["versionDetails"] as groovy.lang.Closure<*>)() as com.palantir.gradle.gitversion.VersionDetails
val ArtifactRepository.publishTask get() = tasks["publishAllPublicationsTo${this.name}Repository"]
val NexusRepository.publishTask get() = "publishTo${this.name.replaceFirstChar { it.titlecase() }}"
6 changes: 6 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
org.gradle.parallel=true
org.gradle.configuration-cache=true
org.gradle.configuration-cache.parallel=true

org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled
org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true
25 changes: 0 additions & 25 deletions renovate.json

This file was deleted.

13 changes: 13 additions & 0 deletions renovate.json5
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
/* Simulate this configuration locally by running:
podman run --rm \
--mount type=bind,src="$(pwd)",dst=/repo \
--workdir /repo \
--user 0 \
--env RENOVATE_GITHUB_COM_TOKEN=$(secret-tool lookup service renovate-dry-run) \
--env LOG_LEVEL=debug \
renovate/renovate --dry-run=full --platform=local
*/
$schema: "https://docs.renovatebot.com/renovate-schema.json",
extends: ["github>jGleitz/renovate-config:default.json5"],
}
2 changes: 1 addition & 1 deletion src/main/kotlin/BaseStringNotation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ abstract class BaseStringNotation(private val splitAt: Regex): StringNotation {
.foldIndexed(StringBuffer()) { index, existing, part -> existing.append(printBeforePart(index, part)).append(part) }
.toString()

override fun toString() = this::class.java.simpleName!!
override fun toString(): String = this::class.java.simpleName
}
35 changes: 18 additions & 17 deletions src/main/kotlin/JavaNotations.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@ import javax.lang.model.SourceVersion
* Allowed characters are determined using [Character.isJavaIdentifierStart] and [Character.isJavaIdentifierPart]. Keywords are detected
* using [SourceVersion.isKeyword].
*/
object JavaTypeName: StringNotation by UpperCamelCase {
data object JavaTypeName : StringNotation by UpperCamelCase {
override fun print(word: Word) = UpperCamelCase.print(
Word(word.parts.mapIndexed { index, wordPart ->
if (index == 0) wordPart.keepOnlyJavaIdentifierChars()
else wordPart.keepOnlyJavaIdentifierContinuationChars()
})
)
.neutralizeJavaReservedKeywords()

override fun toString() = this::class.java.simpleName!!
}

/**
Expand All @@ -30,17 +28,17 @@ object JavaTypeName: StringNotation by UpperCamelCase {
* Allowed characters are determined using [Character.isJavaIdentifierStart] and [Character.isJavaIdentifierPart]. Keywords are detected
* using [SourceVersion.isKeyword].
*/
object JavaMemberName: BaseStringNotation(camelCaseSplitRegex) {
override fun transformPartAfterParse(index: Int, part: String) = part.toLowerCase(Locale.ROOT)
object JavaMemberName : BaseStringNotation(camelCaseSplitRegex) {
override fun transformPartAfterParse(index: Int, part: String) = part.lowercase(Locale.ROOT)

override fun print(word: Word) = word.parts
.foldIndexed(StringBuffer()) { index, existing, part ->
val filteredPart =
if (index == 0) part.keepOnlyJavaIdentifierChars()
else part.keepOnlyJavaIdentifierContinuationChars()
val nextPart =
if (existing.contains(Regex("[a-zA-Z]"))) filteredPart.toFirstUpperOtherLowerCase()
else filteredPart.toLowerCase()
if (existing.contains(Regex("[a-zA-Z]"))) filteredPart.firstUpperThenLowerCase()
else filteredPart.lowercase(Locale.getDefault())
existing.append(printBeforePart(index, nextPart)).append(nextPart)
}.toString().makeValidJavaIdentifier()
}
Expand All @@ -54,10 +52,10 @@ object JavaMemberName: BaseStringNotation(camelCaseSplitRegex) {
* Allowed characters are determined using [Character.isJavaIdentifierStart] and [Character.isJavaIdentifierPart]. Keywords are detected
* using [SourceVersion.isKeyword].
*/
object JavaPackagePart: BaseStringNotation(Regex("_|${camelCaseSplitRegex.pattern}")) {
override fun transformPartAfterParse(index: Int, part: String) = part.toLowerCase(Locale.ROOT)
object JavaPackagePart : BaseStringNotation(Regex("_|${camelCaseSplitRegex.pattern}")) {
override fun transformPartAfterParse(index: Int, part: String) = part.lowercase(Locale.ROOT)

override fun transformPartToPrint(index: Int, part: String) = part.toLowerCase(Locale.ROOT)
override fun transformPartToPrint(index: Int, part: String) = part.lowercase(Locale.ROOT)

override fun print(word: Word) = super.print(word).makeValidJavaIdentifier()
}
Expand All @@ -69,8 +67,8 @@ object JavaPackagePart: BaseStringNotation(Regex("_|${camelCaseSplitRegex.patter
* Allowed characters are determined using [Character.isJavaIdentifierStart] and [Character.isJavaIdentifierPart]. Keywords are detected
* using [SourceVersion.isKeyword].
*/
object JavaPackageName: BaseStringNotation(Regex("\\.")) {
override fun transformPartToPrint(index: Int, part: String) = part.toLowerCase(Locale.ROOT).makeValidJavaIdentifier()
object JavaPackageName : BaseStringNotation(Regex("\\.")) {
override fun transformPartToPrint(index: Int, part: String) = part.lowercase(Locale.ROOT).makeValidJavaIdentifier()

override fun printBeforeInnerPart(index: Int, part: String) = "."
}
Expand All @@ -82,10 +80,8 @@ object JavaPackageName: BaseStringNotation(Regex("\\.")) {
* Allowed characters are determined using [Character.isJavaIdentifierStart] and [Character.isJavaIdentifierPart]. Keywords are detected
* using [SourceVersion.isKeyword].
*/
object JavaConstantName: StringNotation by ScreamingSnakeCase {
data object JavaConstantName : StringNotation by ScreamingSnakeCase {
override fun print(word: Word) = ScreamingSnakeCase.print(word).makeValidJavaIdentifier()

override fun toString() = this::class.java.simpleName!!
}

private fun String.makeValidJavaIdentifier() = this.keepOnlyJavaIdentifierChars().neutralizeJavaReservedKeywords()
Expand All @@ -95,10 +91,15 @@ private fun String.keepOnlyJavaIdentifierChars() = this.chars()
.keepOnlyJavaIdentifierContinuationChars()
.collectToString()

private fun String.keepOnlyJavaIdentifierContinuationChars() = this.chars().keepOnlyJavaIdentifierContinuationChars().collectToString()
private fun String.keepOnlyJavaIdentifierContinuationChars() =
this.chars().keepOnlyJavaIdentifierContinuationChars().collectToString()

private fun IntStream.keepOnlyJavaIdentifierContinuationChars() = this.filter { Character.isJavaIdentifierPart(it) }
private fun IntStream.collectToString() =
this.collect({ StringBuilder() }, { left, right -> left.appendCodePoint(right) }, { left, right -> left.append(right) })
this.collect(
{ StringBuilder() },
{ left, right -> left.appendCodePoint(right) },
{ left, right -> left.append(right) })
.toString()

private fun String.neutralizeJavaReservedKeywords() = when {
Expand Down
24 changes: 13 additions & 11 deletions src/main/kotlin/Notations.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,33 @@ internal val camelCaseSplitRegex = Regex("(?<=.)(?=\\p{Lu})")
*
* @see JavaTypeName
*/
object UpperCamelCase: BaseStringNotation(camelCaseSplitRegex) {
override fun transformPartAfterParse(index: Int, part: String) = part.toLowerCase(Locale.ROOT)
object UpperCamelCase : BaseStringNotation(camelCaseSplitRegex) {
override fun transformPartAfterParse(index: Int, part: String) = part.lowercase(Locale.ROOT)

public override fun transformPartToPrint(index: Int, part: String) = part.toFirstUpperOtherLowerCase()
public override fun transformPartToPrint(index: Int, part: String) = part.firstUpperThenLowerCase()
}

/**
* The `lowerCamelCase` notation.
*
* @see JavaMemberName
*/
object LowerCamelCase: BaseStringNotation(camelCaseSplitRegex) {
override fun transformPartAfterParse(index: Int, part: String) = part.toLowerCase(Locale.ROOT)
object LowerCamelCase : BaseStringNotation(camelCaseSplitRegex) {
override fun transformPartAfterParse(index: Int, part: String) = part.lowercase(Locale.ROOT)

override fun transformPartToPrint(index: Int, part: String) = if (index == 0) part.toLowerCase() else part.toFirstUpperOtherLowerCase()
override fun transformPartToPrint(index: Int, part: String) =
if (index == 0) part.lowercase(Locale.ROOT) else part.firstUpperThenLowerCase()
}

/**
* The `SCREAMING_SNAKE_CASE` notation.
*/
object ScreamingSnakeCase: BaseStringNotation(Regex("_")) {
override fun transformPartAfterParse(index: Int, part: String) = part.toLowerCase(Locale.ROOT)
object ScreamingSnakeCase : BaseStringNotation(Regex("_")) {
override fun transformPartAfterParse(index: Int, part: String) = part.lowercase(Locale.ROOT)

override fun printBeforeInnerPart(index: Int, part: String) = "_"

override fun transformPartToPrint(index: Int, part: String) = part.toUpperCase()
override fun transformPartToPrint(index: Int, part: String) = part.uppercase(Locale.ROOT)
}

/**
Expand All @@ -49,9 +50,10 @@ object SnakeCase: BaseStringNotation(Regex("_")) {
* one or more characters of whitespace as a [part][Word.parts]. [Printing][StringNotation.print] will print the parts separated by one
* space.
*/
object NormalWords: BaseStringNotation(Regex("[\\s]+")) {
object NormalWords: BaseStringNotation(Regex("\\s+")) {
override fun printBeforeInnerPart(index: Int, part: String) = " "
}

internal fun String.toFirstUpperOtherLowerCase() = if (isNotEmpty()) this[0].toUpperCase() + substring(1).toLowerCase() else this
internal fun String.firstUpperThenLowerCase() =
if (isNotEmpty()) this[0].uppercaseChar() + substring(1).lowercase(Locale.ROOT) else this

8 changes: 2 additions & 6 deletions src/test/kotlin/WordTest.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package de.joshuagleitze.stringnotation

import ch.tutteli.atrium.api.fluent.en_GB.asIterable
import ch.tutteli.atrium.api.fluent.en_GB.containsExactly
import ch.tutteli.atrium.api.fluent.en_GB.feature
import ch.tutteli.atrium.api.fluent.en_GB.notToBe
import ch.tutteli.atrium.api.fluent.en_GB.toBe
import ch.tutteli.atrium.api.fluent.en_GB.*
import ch.tutteli.atrium.api.verbs.expect
import org.junit.jupiter.api.Test

Expand Down Expand Up @@ -55,7 +51,7 @@ class WordTest {
@Test
fun `allows to map parts`() {
expect(Word("a", "b", "c"))
.feature(Word::mapParts, String::toUpperCase)
.feature(Word::mapParts, String::uppercase)
.toBe(Word("A", "B", "C"))
}

Expand Down
Loading