From 041ea0c2140fd9e0cd0ae7cc0736e311fad67de3 Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Sun, 19 Jul 2026 20:06:13 -0700 Subject: [PATCH 1/4] Update Gradle to 9.6.1 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index eb84db6..a9db115 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 retries=0 retryBackOffMs=500 From a2b3f90e625e30777f67d345d5e7787dcff167dd Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Sun, 19 Jul 2026 19:23:33 -0700 Subject: [PATCH 2/4] Migrate to Crankcase build logic Still needs to enable `-Werror` and Checkstyle, plus migrate to new release mechanism possibly? --- build-logic/build.gradle.kts | 18 +++ build-logic/settings.gradle.kts | 28 ++++ .../piston.core-ap-conventions.gradle.kts | 5 + .../kotlin/piston.java-conventions.gradle.kts | 28 ++++ build.gradle.kts | 6 - buildSrc/build.gradle.kts | 20 --- buildSrc/src/main/kotlin/Libs.kt | 23 --- buildSrc/src/main/kotlin/common.kt | 139 ------------------ core-ap/annotations/build.gradle.kts | 8 +- core-ap/processor/build.gradle.kts | 43 +++--- core-ap/runtime/build.gradle.kts | 8 +- core/build.gradle.kts | 18 ++- default-impl/build.gradle.kts | 18 ++- gradle/libs.versions.toml | 31 ++++ settings.gradle.kts | 26 ++++ 15 files changed, 187 insertions(+), 232 deletions(-) create mode 100644 build-logic/build.gradle.kts create mode 100644 build-logic/settings.gradle.kts create mode 100644 build-logic/src/main/kotlin/piston.core-ap-conventions.gradle.kts create mode 100644 build-logic/src/main/kotlin/piston.java-conventions.gradle.kts delete mode 100644 buildSrc/build.gradle.kts delete mode 100644 buildSrc/src/main/kotlin/Libs.kt delete mode 100644 buildSrc/src/main/kotlin/common.kt create mode 100644 gradle/libs.versions.toml diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts new file mode 100644 index 0000000..7f1b386 --- /dev/null +++ b/build-logic/build.gradle.kts @@ -0,0 +1,18 @@ +plugins { + `kotlin-dsl` +} + +repositories { + gradlePluginPortal() + maven { + name = "EngineHub" + url = uri("https://repo.enginehub.org/libs-release/") + } +} + +dependencies { + implementation(libs.crankcase.java) + implementation(libs.crankcase.javaLibrary) + implementation(libs.crankcase.licensing) + implementation(libs.crankcase.publishing) +} diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 0000000..46f5132 --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,28 @@ +pluginManagement { + repositories { + maven { + name = "EngineHub" + url = uri("https://repo.enginehub.org/libs-release/") + } + maven { + name = "EngineHub Central Mirror" + url = uri("https://repo.enginehub.org/internal/maven-central-proxy/") + } + maven { + name = "EngineHub Plugin Portal Mirror" + url = uri("https://repo.enginehub.org/internal/plugin-portal-proxy/") + } + } +} +plugins { + id("org.enginehub.crankcase.repo-reconfiguration") version "0.1.2" +} +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} + +rootProject.name = "build-logic" diff --git a/build-logic/src/main/kotlin/piston.core-ap-conventions.gradle.kts b/build-logic/src/main/kotlin/piston.core-ap-conventions.gradle.kts new file mode 100644 index 0000000..0314aee --- /dev/null +++ b/build-logic/src/main/kotlin/piston.core-ap-conventions.gradle.kts @@ -0,0 +1,5 @@ +plugins { + id("piston.java-conventions") +} + +group = "${providers.gradleProperty("group").get()}.core-ap" diff --git a/build-logic/src/main/kotlin/piston.java-conventions.gradle.kts b/build-logic/src/main/kotlin/piston.java-conventions.gradle.kts new file mode 100644 index 0000000..8d5d8a6 --- /dev/null +++ b/build-logic/src/main/kotlin/piston.java-conventions.gradle.kts @@ -0,0 +1,28 @@ +plugins { + id("org.enginehub.crankcase.java-library") + id("org.enginehub.crankcase.licensing") + id("org.enginehub.crankcase.publishing") + jacoco +} + +crankcaseJava { + javaRelease = 25 + // TODO: fix all warnings + failOnWarnings = false +} + +tasks.named("processTestResources") { + from(isolated.rootProject.projectDirectory.dir("common-test-resources")) +} + +publishing { + publications { + register("maven") { + from(components["java"]) + } + } +} + +rootProject.tasks.named("afterReleaseBuild").configure { + dependsOn(tasks.named("build")) +} diff --git a/build.gradle.kts b/build.gradle.kts index bc7bff9..d050f1a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,12 +3,6 @@ plugins { jacoco } -configureArtifactory() - -repositories { - mavenCentral() -} - release { tagTemplate = "v\${version}" buildTasks = listOf() diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts deleted file mode 100644 index 09ad788..0000000 --- a/buildSrc/build.gradle.kts +++ /dev/null @@ -1,20 +0,0 @@ -plugins { - `kotlin-dsl` - kotlin("jvm") version embeddedKotlinVersion -} - -repositories { - mavenCentral() - gradlePluginPortal() - maven { - name = "EngineHub Repository" - url = uri("https://maven.enginehub.org/repo/") - } -} - -dependencies { - implementation(gradleApi()) - implementation(gradleKotlinDsl()) - implementation("net.octyl.level-headered:plugin:0.1.2") - implementation("org.jfrog.buildinfo:build-info-extractor-gradle:5.1.14") -} diff --git a/buildSrc/src/main/kotlin/Libs.kt b/buildSrc/src/main/kotlin/Libs.kt deleted file mode 100644 index 5966713..0000000 --- a/buildSrc/src/main/kotlin/Libs.kt +++ /dev/null @@ -1,23 +0,0 @@ -object Libs { - private const val junitVersion = "6.1.0" - const val junitApi = "org.junit.jupiter:junit-jupiter-api:$junitVersion" - const val junitEngine = "org.junit.jupiter:junit-jupiter-engine:$junitVersion" - const val junitPlatformLauncher = "org.junit.platform:junit-platform-launcher:$junitVersion" - const val guava = "com.google.guava:guava:33.6.0-jre" - private const val kyoriAdventureVersion = "5.1.1" - const val kyoriAdventure = "net.kyori:adventure-api:$kyoriAdventureVersion" - const val kyoriAdventureTextPlain = "net.kyori:adventure-text-serializer-plain:$kyoriAdventureVersion" - const val autoCommon = "com.google.auto:auto-common:1.2.2" - private const val autoValueVersion = "1.11.1" - const val autoValueAnnotations = "com.google.auto.value:auto-value-annotations:$autoValueVersion" - const val autoValueProcessor = "com.google.auto.value:auto-value:$autoValueVersion" - const val autoService = "com.google.auto.service:auto-service:1.1.1" - const val javapoet = "com.squareup:javapoet:1.13.0" - // Sync with Mojang's Log4j - private const val log4jVersion = "2.26.0" - const val log4jApi = "org.apache.logging.log4j:log4j-api:$log4jVersion" - const val log4jCore = "org.apache.logging.log4j:log4j-core:$log4jVersion" - const val jspecify = "org.jspecify:jspecify:1.0.0" - const val compileTesting = "com.google.testing.compile:compile-testing:0.23.0" - const val mockito = "org.mockito:mockito-core:5.23.0" -} diff --git a/buildSrc/src/main/kotlin/common.kt b/buildSrc/src/main/kotlin/common.kt deleted file mode 100644 index f0f9b95..0000000 --- a/buildSrc/src/main/kotlin/common.kt +++ /dev/null @@ -1,139 +0,0 @@ -import net.octyl.levelheadered.LevelHeaderedExtension -import org.gradle.api.JavaVersion -import org.gradle.api.Project -import org.gradle.api.plugins.JavaPluginExtension -import org.gradle.api.publish.PublishingExtension -import org.gradle.api.publish.maven.MavenPublication -import org.gradle.api.tasks.Copy -import org.gradle.api.tasks.compile.JavaCompile -import org.gradle.api.tasks.javadoc.Javadoc -import org.gradle.api.tasks.testing.Test -import org.gradle.external.javadoc.CoreJavadocOptions -import org.gradle.jvm.toolchain.JavaLanguageVersion -import org.gradle.kotlin.dsl.apply -import org.gradle.kotlin.dsl.configure -import org.gradle.kotlin.dsl.delegateClosureOf -import org.gradle.kotlin.dsl.dependencies -import org.gradle.kotlin.dsl.get -import org.gradle.kotlin.dsl.named -import org.gradle.kotlin.dsl.register -import org.gradle.kotlin.dsl.repositories -import org.gradle.kotlin.dsl.the -import org.gradle.kotlin.dsl.withType -import org.jfrog.gradle.plugin.artifactory.dsl.ArtifactoryPluginConvention -import org.jfrog.gradle.plugin.artifactory.dsl.PublisherConfig -import org.jfrog.gradle.plugin.artifactory.task.ArtifactoryTask - -fun Project.applyCommonConfig( - group: String = rootProject.group.toString() -) { - apply(plugin = "java-library") - apply(plugin = "java") - apply(plugin = "net.octyl.level-headered") - apply(plugin = "maven-publish") - apply(plugin = "com.jfrog.artifactory") - apply(plugin = "jacoco") - - project.group = group - - configure { - headerTemplate(rootProject.file("HEADER.txt")) - } - - tasks.withType().configureEach { - useJUnitPlatform() - } - - repositories { - mavenCentral() - } - - tasks.named("processTestResources") { - from(rootProject.file("common-test-resources")) - } - - configure { - toolchain.languageVersion.set(JavaLanguageVersion.of(25)) - } - tasks.named("compileJava") { - options.encoding = "UTF-8" - } - tasks.named("compileTestJava") { - options.encoding = "UTF-8" - } - tasks.withType().configureEach { - (options as CoreJavadocOptions).addStringOption("Xdoclint:none", "-quiet") - } - - dependencies { - "testImplementation"(Libs.junitApi) - "testImplementation"(Libs.junitEngine) - "testRuntimeOnly"(Libs.junitPlatformLauncher) - } - - addExtraArchiveArtifacts() - - configureMavenPublish() - - val build = tasks.named("build") - rootProject.tasks.named("afterReleaseBuild").configure { - dependsOn(build) - } -} - -private fun Project.addExtraArchiveArtifacts() { - configure { - withSourcesJar() - withJavadocJar() - } -} - -private fun Project.configureMavenPublish() { - configure { - publications { - register("maven") { - groupId = project.group.toString() - artifactId = project.name - version = project.version.toString() - - from(components["java"]) - } - } - } -} - -fun Project.configureArtifactory() { - apply(plugin = "maven-publish") - apply(plugin = "com.jfrog.artifactory") - val ext = extensions.extraProperties - if (!project.hasProperty("artifactory_contextUrl")) - ext["artifactory_contextUrl"] = "http://localhost" - if (!project.hasProperty("artifactory_user")) - ext["artifactory_user"] = "guest" - if (!project.hasProperty("artifactory_password")) - ext["artifactory_password"] = "" - configure { - publish { - contextUrl = project.property("artifactory_contextUrl").toString() - repository { - repoKey = when { - "SNAPSHOT" in project.version.toString() -> "libs-snapshot-local" - else -> "libs-release-local" - } - username = project.property("artifactory_user").toString() - password = project.property("artifactory_password").toString() - } - defaults { - publications("maven") - setPublishArtifacts(true) - } - } - } - tasks.named("artifactoryPublish") { - skip = true - } -} - -fun Project.applyCoreApConfig() { - applyCommonConfig(group = rootProject.group.toString() + ".core-ap") -} diff --git a/core-ap/annotations/build.gradle.kts b/core-ap/annotations/build.gradle.kts index 5c33ba3..8768d52 100644 --- a/core-ap/annotations/build.gradle.kts +++ b/core-ap/annotations/build.gradle.kts @@ -1,6 +1,8 @@ -applyCoreApConfig() +plugins { + id("piston.core-ap-conventions") +} dependencies { - "api"(project(":core")) - "api"(project(":core-ap:runtime")) + api(project(":core")) + api(project(":core-ap:runtime")) } diff --git a/core-ap/processor/build.gradle.kts b/core-ap/processor/build.gradle.kts index 27ae8f0..c62aaf5 100644 --- a/core-ap/processor/build.gradle.kts +++ b/core-ap/processor/build.gradle.kts @@ -1,10 +1,9 @@ plugins { - kotlin("jvm") version "2.4.0" - kotlin("kapt") version "2.4.0" + alias(libs.plugins.kotlinJvm) + alias(libs.plugins.kotlinKapt) + id("piston.core-ap-conventions") } -applyCoreApConfig() - kapt.includeCompileClasspath = false tasks.test { @@ -19,26 +18,26 @@ tasks.test { } dependencies { - "implementation"(project(":core")) - "implementation"(project(":core-ap:annotations")) - "implementation"(project(":core-ap:runtime")) - "implementation"(Libs.guava) - "implementation"(Libs.javapoet) - "implementation"(Libs.autoCommon) - "compileOnly"(Libs.autoValueAnnotations) - "kapt"(Libs.autoValueProcessor) - "compileOnly"(Libs.autoService) - "kapt"(Libs.autoService) + implementation(project(":core")) + implementation(project(":core-ap:annotations")) + implementation(project(":core-ap:runtime")) + implementation(libs.guava) + implementation(libs.javapoet) + implementation(libs.autoCommon) + compileOnly(libs.autoValueAnnotations) + kapt(libs.autoValueProcessor) + compileOnly(libs.autoService) + kapt(libs.autoService) - "testImplementation"(kotlin("stdlib")) - "testImplementation"(Libs.compileTesting) { + testImplementation(kotlin("stdlib")) + testImplementation(libs.compileTesting) { exclude("junit", "junit") } - "testImplementation"(Libs.mockito) - "testRuntimeOnly"(Libs.log4jCore) - "testImplementation"(project(":default-impl")) - "testCompileOnly"(Libs.autoService) - "kaptTest"(Libs.autoService) - "kaptTest"(project(":core-ap:processor")) + testImplementation(libs.mockito) + testRuntimeOnly(libs.log4jCore) + testImplementation(project(":default-impl")) + testCompileOnly(libs.autoService) + kaptTest(libs.autoService) + kaptTest(project(":core-ap:processor")) } diff --git a/core-ap/runtime/build.gradle.kts b/core-ap/runtime/build.gradle.kts index 4bbfbec..0da8a03 100644 --- a/core-ap/runtime/build.gradle.kts +++ b/core-ap/runtime/build.gradle.kts @@ -1,7 +1,9 @@ -applyCoreApConfig() +plugins { + id("piston.core-ap-conventions") +} dependencies { - "api"(project(":core")) + api(project(":core")) - "testImplementation"(Libs.mockito) + testImplementation(libs.mockito) } diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 9dde589..2f9c99f 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,11 +1,13 @@ -applyCommonConfig() +plugins { + id("piston.java-conventions") +} dependencies { - "api"(Libs.guava) - "api"(Libs.kyoriAdventure) - "api"(Libs.jspecify) - "implementation"(Libs.kyoriAdventureTextPlain) - "compileOnly"(Libs.autoValueAnnotations) - "annotationProcessor"(Libs.autoValueProcessor) - "testImplementation"(Libs.mockito) + api(libs.guava) + api(libs.kyoriAdventure) + api(libs.jspecify) + implementation(libs.kyoriAdventureTextPlain) + compileOnly(libs.autoValueAnnotations) + annotationProcessor(libs.autoValueProcessor) + testImplementation(libs.mockito) } diff --git a/default-impl/build.gradle.kts b/default-impl/build.gradle.kts index 95ac7fb..b5d53c7 100644 --- a/default-impl/build.gradle.kts +++ b/default-impl/build.gradle.kts @@ -1,11 +1,13 @@ -applyCommonConfig() +plugins { + id("piston.java-conventions") +} dependencies { - "api"(project(":core")) - "implementation"(Libs.log4jApi) - "compileOnly"(Libs.autoValueAnnotations) - "annotationProcessor"(Libs.autoValueProcessor) - "compileOnlyApi"(Libs.autoService) - "annotationProcessor"(Libs.autoService) - "testRuntimeOnly"(Libs.log4jCore) + api(project(":core")) + implementation(libs.log4jApi) + compileOnly(libs.autoValueAnnotations) + annotationProcessor(libs.autoValueProcessor) + compileOnlyApi(libs.autoService) + annotationProcessor(libs.autoService) + testRuntimeOnly(libs.log4jCore) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..e2f7fa1 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,31 @@ +[versions] +crankcase = "0.1.2" +kotlin = "2.4.0" +autoValue = "1.11.1" +kyoriAdventure = "5.1.1" +# Sync with Mojang's Log4j +log4j = "2.26.0" + +[libraries] +crankcase-java = { module = "org.enginehub.crankcase:java", version.ref = "crankcase" } +crankcase-javaLibrary = { module = "org.enginehub.crankcase:java-library", version.ref = "crankcase" } +crankcase-licensing = { module = "org.enginehub.crankcase:licensing", version.ref = "crankcase" } +crankcase-publishing = { module = "org.enginehub.crankcase:publishing", version.ref = "crankcase" } + +guava = "com.google.guava:guava:33.6.0-jre" +kyoriAdventure = { module = "net.kyori:adventure-api", version.ref = "kyoriAdventure" } +kyoriAdventureTextPlain = { module = "net.kyori:adventure-text-serializer-plain", version.ref = "kyoriAdventure" } +autoCommon = "com.google.auto:auto-common:1.2.2" +autoValueAnnotations = { module = "com.google.auto.value:auto-value-annotations", version.ref = "autoValue" } +autoValueProcessor = { module = "com.google.auto.value:auto-value", version.ref = "autoValue" } +autoService = "com.google.auto.service:auto-service:1.1.1" +javapoet = "com.squareup:javapoet:1.13.0" +log4jApi = { module = "org.apache.logging.log4j:log4j-api", version.ref = "log4j" } +log4jCore = { module = "org.apache.logging.log4j:log4j-core", version.ref = "log4j" } +jspecify = "org.jspecify:jspecify:1.0.0" +compileTesting = "com.google.testing.compile:compile-testing:0.23.0" +mockito = "org.mockito:mockito-core:5.23.0" + +[plugins] +kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +kotlinKapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } diff --git a/settings.gradle.kts b/settings.gradle.kts index d8eca5d..8373320 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,9 +1,35 @@ +pluginManagement { + // pluginManagement repositories resolve plugins before repo-reconfiguration can apply, so they + // must point at EngineHub mirrors directly rather than upstream URLs. + repositories { + maven { + name = "EngineHub" + url = uri("https://repo.enginehub.org/libs-release/") + } + maven { + name = "EngineHub Central Mirror" + url = uri("https://repo.enginehub.org/internal/maven-central-proxy/") + } + maven { + name = "EngineHub Plugin Portal Mirror" + url = uri("https://repo.enginehub.org/internal/plugin-portal-proxy/") + } + } +} plugins { + id("org.enginehub.crankcase.repo-reconfiguration") version "0.1.2" id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } +dependencyResolutionManagement { + repositories { + mavenCentral() + } +} rootProject.name = "piston" +includeBuild("build-logic") + include(":core", ":default-impl") listOf("annotations", "processor", "runtime").forEach { include(":core-ap:$it") From 67a6f3770bb85570c031af2d5b18597fd54b3cab Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Sun, 19 Jul 2026 19:44:39 -0700 Subject: [PATCH 3/4] Add Crankcase checkstyle, fix violations --- build-logic/build.gradle.kts | 1 + .../kotlin/piston.java-conventions.gradle.kts | 1 + .../piston/annotation/CommandContainer.java | 2 ++ .../gen/CommandParameterInterpreter.java | 28 +++++++++---------- .../piston/gen/CommandProcessor.java | 6 ++-- .../gen/CommandRegistrationGenerator.java | 14 +++++----- .../piston/gen/ConditionGenerator.java | 2 +- .../piston/gen/GenerationSupportImpl.java | 20 +++++++------ .../gen/optimize/CollectionOptimization.java | 2 +- .../piston/gen/optimize/Optimization.java | 2 +- .../piston/gen/util/AnnoValueExtraction.java | 12 +++++--- .../piston/gen/util/CodeBlockUtil.java | 7 ++++- .../enginehub/piston/gen/util/SafeName.java | 5 ++++ .../piston/gen/util/TypeNameUtil.java | 4 +-- .../piston/gen/value/CommandInfo.java | 2 +- .../enginehub/piston/gen/value/KeyInfo.java | 16 +++++------ .../piston/gen/value/RegistrationInfo.java | 2 +- .../piston/gen/value/RequiredVariable.java | 2 +- .../piston/gen/value/ReservedNames.java | 5 ++++ .../piston/internal/RegistrationUtil.java | 2 +- .../piston/util/RegistrationUtilTest.java | 2 ++ .../java/org/enginehub/piston/ArgBinding.java | 3 +- .../java/org/enginehub/piston/Command.java | 6 ++-- .../org/enginehub/piston/config/Config.java | 3 +- .../enginehub/piston/config/ConfigHolder.java | 2 +- .../piston/converter/ArgumentConverters.java | 8 +++--- .../piston/converter/FailedConversion.java | 12 +++++--- .../converter/SuccessfulConversion.java | 10 +++++-- .../piston/exception/UsageException.java | 1 + .../enginehub/piston/inject/Annotations.java | 25 +++++++++++------ .../piston/part/CommandArgument.java | 1 + .../org/enginehub/piston/util/CaseHelper.java | 5 ++++ .../org/enginehub/piston/util/PartHelper.java | 4 +++ .../enginehub/piston/util/ValueProvider.java | 2 +- .../org/enginehub/piston/ConditionTest.java | 2 +- .../piston/exception/ConstructionTest.java | 2 +- .../enginehub/piston/impl/CommandParser.java | 4 +-- gradle/libs.versions.toml | 1 + 38 files changed, 142 insertions(+), 86 deletions(-) diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 7f1b386..86b2f9e 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -11,6 +11,7 @@ repositories { } dependencies { + implementation(libs.crankcase.checkstyle) implementation(libs.crankcase.java) implementation(libs.crankcase.javaLibrary) implementation(libs.crankcase.licensing) diff --git a/build-logic/src/main/kotlin/piston.java-conventions.gradle.kts b/build-logic/src/main/kotlin/piston.java-conventions.gradle.kts index 8d5d8a6..ddcd06b 100644 --- a/build-logic/src/main/kotlin/piston.java-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/piston.java-conventions.gradle.kts @@ -1,4 +1,5 @@ plugins { + id("org.enginehub.crankcase.checkstyle") id("org.enginehub.crankcase.java-library") id("org.enginehub.crankcase.licensing") id("org.enginehub.crankcase.publishing") diff --git a/core-ap/annotations/src/main/java/org/enginehub/piston/annotation/CommandContainer.java b/core-ap/annotations/src/main/java/org/enginehub/piston/annotation/CommandContainer.java index d60c882..4c3c66c 100644 --- a/core-ap/annotations/src/main/java/org/enginehub/piston/annotation/CommandContainer.java +++ b/core-ap/annotations/src/main/java/org/enginehub/piston/annotation/CommandContainer.java @@ -42,11 +42,13 @@ * but if you add an interface that matches existing methods, then * those will be overriden, allowing for more generic configuration. *

+ * *

* For example, you could add an interface representing the addition * of a {@link CommandConditionGenerator} to the registration builder, * and then you will be able to inject all builders using a single method. *

+ * *

* N.B.: The registration class always implements {@link CommandRegistration}, * regardless of the content of this array. diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandParameterInterpreter.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandParameterInterpreter.java index 10b1324..5a2d170 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandParameterInterpreter.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandParameterInterpreter.java @@ -43,6 +43,10 @@ import org.enginehub.piston.part.CommandParts; import org.enginehub.piston.part.NoArgCommandFlag; +import java.lang.annotation.Annotation; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; @@ -50,10 +54,6 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; -import java.lang.annotation.Annotation; -import java.util.List; -import java.util.Map; -import java.util.stream.Stream; import static com.google.auto.common.MoreElements.asType; import static com.google.auto.common.MoreElements.getAnnotationMirror; @@ -81,7 +81,7 @@ private static boolean isUnconverted(ProcessingEnvironment env, VariableElement return env.getTypeUtils().isAssignable(parameter.asType(), commandValue); } - private final Map, ParamTransform> ANNOTATION_TRANSFORMS = ImmutableMap.of( + private final Map, ParamTransform> annotationTransforms = ImmutableMap.of( Arg.class, this::argTransform, ArgFlag.class, this::argFlagTransform, Switch.class, this::switchTransform @@ -109,8 +109,8 @@ private CommandParamInfo argTransform(VariableElement parameter) { String desc = getValue(parameter, arg, "desc", String.class); List defaults = getList(parameter, arg, "def", String.class); CodeBlock.Builder construction = CodeBlock.builder() - .add("$T.arg($L, $L)\n" + - ".defaultsTo($L)\n", + .add("$T.arg($L, $L)\n" + + ".defaultsTo($L)\n", CommandParts.class, transCompOf(prefixArgName(env, name)), textCompOf(desc), stringListForGen(defaults.stream())); addArgTypes(parameter, construction); @@ -138,10 +138,10 @@ private CommandParamInfo argFlagTransform(VariableElement parameter) { String desc = getValue(parameter, arg, "desc", String.class); List defaults = getList(parameter, arg, "def", String.class); CodeBlock.Builder construction = CodeBlock.builder() - .add("$T.flag('$L', $L)\n" + - ".withRequiredArg()\n" + - ".argNamed($L)\n" + - ".defaultsTo($L)\n", + .add("$T.flag('$L', $L)\n" + + ".withRequiredArg()\n" + + ".argNamed($L)\n" + + ".defaultsTo($L)\n", CommandParts.class, name, textCompOf(desc), transCompOf(prefixArgName(env, argName)), stringListForGen(defaults.stream())); @@ -243,7 +243,7 @@ private CommandParamInfo commandParameterValue(VariableElement parameter) { .extractSpec(ExtractSpec.builder() .name("extract$" + parameter.getSimpleName().toString()) .type(TypeName.get(parameter.asType())) - .extractMethodBody(var -> + .extractMethodBody(_ -> CodeBlock.of("$[return $L;\n$]", ReservedNames.PARAMETERS)) .build()) .build(); @@ -254,7 +254,7 @@ private CommandParamInfo injectableValue(VariableElement parameter) { .extractSpec(ExtractSpec.builder() .name("extract$" + parameter.getSimpleName().toString()) .type(TypeName.get(parameter.asType())) - .extractMethodBody(var -> { + .extractMethodBody(_ -> { CodeBlock paramKey = asKeyType(parameter); return CodeBlock.builder() .addStatement("return $T.requireOptional($L, $S, $L.injectedValue($L))", @@ -298,7 +298,7 @@ List getParams() { private CommandParamInfo getParam(VariableElement parameter) { ImmutableList transforms = - ANNOTATION_TRANSFORMS.entrySet().stream() + annotationTransforms.entrySet().stream() .filter(e -> isAnnotationPresent(parameter, e.getKey())) .map(Map.Entry::getValue) .collect(toImmutableList()); diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandProcessor.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandProcessor.java index a57430c..351596d 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandProcessor.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandProcessor.java @@ -222,13 +222,13 @@ private CommandInfo getCommandInfo(ExecutableElement method, GenerationSupport g .build(); } - private final LoadingCache IS_CONDITION = + private final LoadingCache isCondition = CacheBuilder.newBuilder() .weakKeys() // take 50 falses, or many more trues // we value a positive result more .maximumWeight(5000) - .weigher((k, v) -> v ? 1 : 100) + .weigher((_, v) -> v ? 1 : 100) .build(CacheLoader.from((TypeElement element) -> { if (element == null) { return false; @@ -245,7 +245,7 @@ private static boolean isExactlyConditionAnno(TypeElement element) { private Optional findCommandCondition(ExecutableElement method) { return method.getAnnotationMirrors().stream() - .filter(mirror -> IS_CONDITION.getUnchecked( + .filter(mirror -> isCondition.getUnchecked( asType(mirror.getAnnotationType().asElement()) )) // reset the generic to just AnnotationMirror, no wildcard diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandRegistrationGenerator.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandRegistrationGenerator.java index c066809..548cd1b 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandRegistrationGenerator.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandRegistrationGenerator.java @@ -43,13 +43,6 @@ import org.enginehub.piston.internal.RegistrationUtil; import org.enginehub.piston.part.CommandParts; -import javax.annotation.processing.Filer; -import javax.annotation.processing.Generated; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.TypeElement; -import javax.lang.model.type.TypeMirror; import java.io.IOException; import java.lang.reflect.Method; import java.time.Instant; @@ -57,6 +50,13 @@ import java.util.Objects; import java.util.function.Function; import java.util.stream.Stream; +import javax.annotation.processing.Filer; +import javax.annotation.processing.Generated; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeMirror; import static com.google.common.base.Preconditions.checkState; import static com.google.common.collect.ImmutableList.toImmutableList; diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/ConditionGenerator.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/ConditionGenerator.java index 953728b..d33cc82 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/ConditionGenerator.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/ConditionGenerator.java @@ -52,7 +52,7 @@ CommandCondInfo generateCondition() { TypeName generatorClassName = getAnnotationValue(conditionMirror, "value") .accept(new SimpleAnnotationValueVisitor8() { @Override - public TypeName visitType(TypeMirror t, Void aVoid) { + public TypeName visitType(TypeMirror t, Void unused) { return TypeName.get(t); } }, null); diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/GenerationSupportImpl.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/GenerationSupportImpl.java index 2e13fe1..bb8738d 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/GenerationSupportImpl.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/GenerationSupportImpl.java @@ -46,12 +46,16 @@ private static final class ShareKey { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } ShareKey shareKey1 = (ShareKey) o; - return type.equals(shareKey1.type) && - name.equals(shareKey1.name) && - shareKey.equals(shareKey1.shareKey); + return type.equals(shareKey1.type) + && name.equals(shareKey1.name) + && shareKey.equals(shareKey1.shareKey); } @Override @@ -65,7 +69,7 @@ public int hashCode() { private final Map sharedDepNames = new HashMap<>(); private final Map sharedFieldNames = new HashMap<>(); - public GenerationSupportImpl(IdentifierTracker identifierTracker, + GenerationSupportImpl(IdentifierTracker identifierTracker, RegistrationInfo.Builder builder) { this.identifierTracker = identifierTracker; this.builder = builder; @@ -76,7 +80,7 @@ public String requestDependency(TypeName type, String name, @Nullable Object sha ShareKey hashKey = shareKey == null ? null : new ShareKey(type, name, shareKey); if (hashKey != null) { return sharedDepNames.computeIfAbsent(hashKey, - k -> requestDependencyUnshared(type, name) + _ -> requestDependencyUnshared(type, name) ); } return requestDependencyUnshared(type, name); @@ -96,7 +100,7 @@ public String requestField(TypeName type, String name, @Nullable Object shareKey ShareKey hashKey = shareKey == null ? null : new ShareKey(type, name, shareKey); if (hashKey != null) { return sharedFieldNames.computeIfAbsent(hashKey, - k -> requestFieldUnshared(type, name) + _ -> requestFieldUnshared(type, name) ); } return requestFieldUnshared(type, name); diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/CollectionOptimization.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/CollectionOptimization.java index 806e914..a2eb062 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/CollectionOptimization.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/CollectionOptimization.java @@ -25,7 +25,7 @@ /** * Represents an optimization over a collection. * - * @param + * @param the element type of the optimized collection */ @FunctionalInterface public interface CollectionOptimization extends Optimization> { diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/Optimization.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/Optimization.java index 57f31da..0e1fbf7 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/Optimization.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/Optimization.java @@ -22,7 +22,7 @@ /** * Represents an optimization. * - * @param + * @param the type being optimized */ @FunctionalInterface public interface Optimization { diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/AnnoValueExtraction.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/AnnoValueExtraction.java index 24e0b8f..33fb9ae 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/AnnoValueExtraction.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/AnnoValueExtraction.java @@ -23,14 +23,14 @@ import com.google.common.primitives.Primitives; import org.jspecify.annotations.Nullable; +import java.util.List; +import java.util.Objects; +import java.util.function.Predicate; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.AnnotationValueVisitor; import javax.lang.model.element.Element; import javax.lang.model.util.SimpleAnnotationValueVisitor8; -import java.util.List; -import java.util.Objects; -import java.util.function.Predicate; import static com.google.auto.common.AnnotationMirrors.getAnnotationValue; @@ -46,7 +46,7 @@ private static final class GeneralResult { @Nullable private final Object bad; - public GeneralResult(@Nullable Object good, @Nullable Object bad) { + GeneralResult(@Nullable Object good, @Nullable Object bad) { this.good = good; this.bad = bad; } @@ -108,4 +108,8 @@ public List visitArray(List vals, Void unused) { }, null); } + private AnnoValueExtraction() { + throw new RuntimeException(); + } + } diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/CodeBlockUtil.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/CodeBlockUtil.java index 8d4c5af..10cae66 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/CodeBlockUtil.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/CodeBlockUtil.java @@ -26,11 +26,11 @@ import org.enginehub.piston.internal.RegistrationUtil; import org.jspecify.annotations.Nullable; -import javax.lang.model.element.ExecutableElement; import java.lang.reflect.Method; import java.util.function.Supplier; import java.util.stream.Collector; import java.util.stream.Stream; +import javax.lang.model.element.ExecutableElement; import static java.util.Objects.requireNonNull; import static org.enginehub.piston.gen.util.TypeNameUtil.rawType; @@ -157,4 +157,9 @@ public CodeBlock finish() { .build(); } } + + private CodeBlockUtil() { + throw new RuntimeException(); + } + } diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/SafeName.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/SafeName.java index a1acbef..3d989b5 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/SafeName.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/SafeName.java @@ -79,4 +79,9 @@ private static CharSequence getNameAsIdentifierRaw(TypeName typeName) { // just use toString() as a last resort return typeName.toString(); } + + private SafeName() { + throw new RuntimeException(); + } + } diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/TypeNameUtil.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/TypeNameUtil.java index 7bf6efe..e49ff16 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/TypeNameUtil.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/TypeNameUtil.java @@ -36,8 +36,8 @@ public static TypeName rawType(TypeName typeName) { } else if (typeName.isPrimitive()) { return typeName; } - throw new IllegalArgumentException("Not able to create a raw type from " + - "'" + typeName + "' (" + typeName.getClass() + ")"); + throw new IllegalArgumentException("Not able to create a raw type from " + + "'" + typeName + "' (" + typeName.getClass() + ")"); } public static TypeName firstTypeArg(TypeName typeName) { diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/CommandInfo.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/CommandInfo.java index aa4f0e9..3fce5ac 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/CommandInfo.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/CommandInfo.java @@ -23,9 +23,9 @@ import com.google.common.collect.ImmutableList; import org.jspecify.annotations.Nullable; -import javax.lang.model.element.ExecutableElement; import java.util.Collection; import java.util.Optional; +import javax.lang.model.element.ExecutableElement; @AutoValue public abstract class CommandInfo { diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/KeyInfo.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/KeyInfo.java index 1c79135..710c7dc 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/KeyInfo.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/KeyInfo.java @@ -63,12 +63,12 @@ public final TypeName wrappedTypeName(Class wrapper) { public final String getVariableName() { AnnotationSpec spec = annotationSpec(); - return SafeName.getNameAsIdentifier(typeName()) + - "_" + - (spec == null + return SafeName.getNameAsIdentifier(typeName()) + + "_" + + (spec == null ? "" - : getSpecName(spec) + "_") + - "Key"; + : getSpecName(spec) + "_") + + "Key"; } private String getSpecName(AnnotationSpec spec) { @@ -143,11 +143,11 @@ private CodeBlock runtimeAnnotationExtractor(AnnotationSpec annotationSpec) { .beginControlFlow("try") .addStatement( // from this class - "return getClass()" + + "return getClass()" // retrieve this method - ".getDeclaredMethod(\"a\", $T.class)" + + + ".getDeclaredMethod(\"a\", $T.class)" // and get its first parameter's first annotation (again, only one) - ".getParameterAnnotations()[0][0]", Object.class) + + ".getParameterAnnotations()[0][0]", Object.class) .nextControlFlow("catch ($T e)", NoSuchMethodException.class) .addStatement("throw new $T(e)", RuntimeException.class) .endControlFlow() diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/RegistrationInfo.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/RegistrationInfo.java index 90abf58..9f78bfb 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/RegistrationInfo.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/RegistrationInfo.java @@ -25,9 +25,9 @@ import com.squareup.javapoet.ClassName; import org.jspecify.annotations.Nullable; +import java.util.Collection; import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; -import java.util.Collection; @AutoValue public abstract class RegistrationInfo { diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/RequiredVariable.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/RequiredVariable.java index 1544480..fdb3323 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/RequiredVariable.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/RequiredVariable.java @@ -54,7 +54,7 @@ public interface Builder { } /** - * Is this variable inherited from another interface? + * Check if this variable is inherited from another interface. */ public abstract boolean isInherited(); diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/ReservedNames.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/ReservedNames.java index 2bb35e0..57aa3a0 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/ReservedNames.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/ReservedNames.java @@ -49,4 +49,9 @@ public static ImmutableMultiset methodNames() { BUILDER ); } + + private ReservedNames() { + throw new RuntimeException(); + } + } diff --git a/core-ap/runtime/src/main/java/org/enginehub/piston/internal/RegistrationUtil.java b/core-ap/runtime/src/main/java/org/enginehub/piston/internal/RegistrationUtil.java index 3ff35e9..84a15cf 100644 --- a/core-ap/runtime/src/main/java/org/enginehub/piston/internal/RegistrationUtil.java +++ b/core-ap/runtime/src/main/java/org/enginehub/piston/internal/RegistrationUtil.java @@ -41,7 +41,7 @@ public static T requireOptional(Key type, String name, Optional option public static Method getCommandMethod(Class registrationClass, String methodName, Class... parameterTypes) { try { return registrationClass.getDeclaredMethod(methodName, parameterTypes); - } catch (NoSuchMethodException e) { + } catch (NoSuchMethodException _) { throw new IllegalStateException("Missing command method: " + methodName); } } diff --git a/core-ap/runtime/src/test/java/org/enginehub/piston/util/RegistrationUtilTest.java b/core-ap/runtime/src/test/java/org/enginehub/piston/util/RegistrationUtilTest.java index de29d12..1e2ea5b 100644 --- a/core-ap/runtime/src/test/java/org/enginehub/piston/util/RegistrationUtilTest.java +++ b/core-ap/runtime/src/test/java/org/enginehub/piston/util/RegistrationUtilTest.java @@ -91,6 +91,7 @@ void listenersBeforeCall() { verify(listener).beforeCall(fakeCommandMethod, parameters); verifyNoMoreInteractions(listener); } + @Test void listenersAfterCall() { RegistrationUtil.listenersAfterCall(ImmutableList.of(listener), fakeCommandMethod, parameters); @@ -98,6 +99,7 @@ void listenersAfterCall() { verify(listener).afterCall(fakeCommandMethod, parameters); verifyNoMoreInteractions(listener); } + @Test void listenersAfterThrow() { Throwable ex = new RuntimeException(); diff --git a/core/src/main/java/org/enginehub/piston/ArgBinding.java b/core/src/main/java/org/enginehub/piston/ArgBinding.java index f156cbd..a784d30 100644 --- a/core/src/main/java/org/enginehub/piston/ArgBinding.java +++ b/core/src/main/java/org/enginehub/piston/ArgBinding.java @@ -20,7 +20,6 @@ package org.enginehub.piston; import com.google.common.collect.ImmutableSet; -import org.enginehub.piston.converter.SuccessfulConversion; import org.enginehub.piston.part.CommandPart; public interface ArgBinding { @@ -31,7 +30,7 @@ public interface ArgBinding { String getInput(); /** - * Did we match the given part exactly? + * Check if we matched the given part exactly. * * @param part the part, must be contained in the parts returned by {@link #getParts()} * @since 0.5.8 diff --git a/core/src/main/java/org/enginehub/piston/Command.java b/core/src/main/java/org/enginehub/piston/Command.java index 94e9650..3f468ef 100644 --- a/core/src/main/java/org/enginehub/piston/Command.java +++ b/core/src/main/java/org/enginehub/piston/Command.java @@ -51,7 +51,7 @@ interface Action { * An action that does nothing, and returns 0. Useful for * commands that only have subcommands, and do nothing. */ - Action NULL_ACTION = params -> 0; + Action NULL_ACTION = _ -> 0; /** * Run the action. @@ -71,12 +71,12 @@ interface Condition { /** * An condition that always returns true. */ - Condition TRUE = p -> true; + Condition TRUE = _ -> true; /** * An condition that always returns false. */ - Condition FALSE = p -> false; + Condition FALSE = _ -> false; /** * Determine if the condition is satisfied. diff --git a/core/src/main/java/org/enginehub/piston/config/Config.java b/core/src/main/java/org/enginehub/piston/config/Config.java index 73a942b..4374064 100644 --- a/core/src/main/java/org/enginehub/piston/config/Config.java +++ b/core/src/main/java/org/enginehub/piston/config/Config.java @@ -53,8 +53,7 @@ public String getKey() { return key; } - public @Nullable - T getValue() { + public @Nullable T getValue() { return value; } diff --git a/core/src/main/java/org/enginehub/piston/config/ConfigHolder.java b/core/src/main/java/org/enginehub/piston/config/ConfigHolder.java index 68577da..109b29f 100644 --- a/core/src/main/java/org/enginehub/piston/config/ConfigHolder.java +++ b/core/src/main/java/org/enginehub/piston/config/ConfigHolder.java @@ -48,7 +48,7 @@ public Map> getConfigs() { public Config getConfig(Config defaultValue) { @SuppressWarnings("unchecked") - Config c = (Config) configs.computeIfAbsent(defaultValue.getKey(), k -> defaultValue); + Config c = (Config) configs.computeIfAbsent(defaultValue.getKey(), _ -> defaultValue); return c; } diff --git a/core/src/main/java/org/enginehub/piston/converter/ArgumentConverters.java b/core/src/main/java/org/enginehub/piston/converter/ArgumentConverters.java index a7777cc..e0530c1 100644 --- a/core/src/main/java/org/enginehub/piston/converter/ArgumentConverters.java +++ b/core/src/main/java/org/enginehub/piston/converter/ArgumentConverters.java @@ -46,7 +46,7 @@ public class ArgumentConverters { private static final ArgumentConverter STRING_ARGUMENT_CONVERTER = - SimpleArgumentConverter.from((s, c) -> SuccessfulConversion.fromSingle(s), "any text"); + SimpleArgumentConverter.from((s, _) -> SuccessfulConversion.fromSingle(s), "any text"); public static ArgumentConverter forString() { return STRING_ARGUMENT_CONVERTER; @@ -63,7 +63,7 @@ private static Optional> valueOfConverters(TypeToken handle = MethodHandles.publicLookup().findStatic( c, "valueOf", methodType(c, String.class) ); - } catch (NoSuchMethodException | IllegalAccessException e) { + } catch (NoSuchMethodException | IllegalAccessException _) { return Optional.empty(); } @@ -83,7 +83,7 @@ private static Optional> constructorConverters(TypeToke handle = MethodHandles.publicLookup().findConstructor( c, methodType(void.class, String.class) ); - } catch (NoSuchMethodException | IllegalAccessException e) { + } catch (NoSuchMethodException | IllegalAccessException _) { return Optional.empty(); } @@ -188,7 +188,7 @@ private interface ACProvider { type -> { if (Objects.equals(type.wrap().getRawType(), Character.class)) { return Optional.of(SimpleArgumentConverter.from( - (s, c) -> SuccessfulConversion.fromSingle(s.charAt(0)), + (s, _) -> SuccessfulConversion.fromSingle(s.charAt(0)), "any character" )); } diff --git a/core/src/main/java/org/enginehub/piston/converter/FailedConversion.java b/core/src/main/java/org/enginehub/piston/converter/FailedConversion.java index bed94da..5ee153f 100644 --- a/core/src/main/java/org/enginehub/piston/converter/FailedConversion.java +++ b/core/src/main/java/org/enginehub/piston/converter/FailedConversion.java @@ -88,11 +88,15 @@ public Collection get() { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } FailedConversion that = (FailedConversion) o; - return error.equals(that.error) && - otherFailures.equals(that.otherFailures); + return error.equals(that.error) + && otherFailures.equals(that.otherFailures); } @Override diff --git a/core/src/main/java/org/enginehub/piston/converter/SuccessfulConversion.java b/core/src/main/java/org/enginehub/piston/converter/SuccessfulConversion.java index 059bb25..52fbc30 100644 --- a/core/src/main/java/org/enginehub/piston/converter/SuccessfulConversion.java +++ b/core/src/main/java/org/enginehub/piston/converter/SuccessfulConversion.java @@ -52,7 +52,7 @@ private SuccessfulConversion(Collection result, boolean exactMatch) { } /** - * Is this conversion an exact match for a complete input? + * Check if this conversion is an exact match for a complete input. * *

* This may be {@code false} if the conversion is a partial match, or if the input was @@ -102,8 +102,12 @@ public Collection get() { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } SuccessfulConversion that = (SuccessfulConversion) o; return result.equals(that.result); } diff --git a/core/src/main/java/org/enginehub/piston/exception/UsageException.java b/core/src/main/java/org/enginehub/piston/exception/UsageException.java index cf7bd65..97a2738 100644 --- a/core/src/main/java/org/enginehub/piston/exception/UsageException.java +++ b/core/src/main/java/org/enginehub/piston/exception/UsageException.java @@ -25,6 +25,7 @@ /** * Parent class for all usage-related exceptions. * + *

* Provides a partially complete parsing result to assist in providing better help messages. */ public class UsageException extends CommandException { diff --git a/core/src/main/java/org/enginehub/piston/inject/Annotations.java b/core/src/main/java/org/enginehub/piston/inject/Annotations.java index 175b765..2d13de2 100644 --- a/core/src/main/java/org/enginehub/piston/inject/Annotations.java +++ b/core/src/main/java/org/enginehub/piston/inject/Annotations.java @@ -61,11 +61,15 @@ private MethodKey(String name, List> signature) { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } MethodKey methodKey = (MethodKey) o; - return name.equals(methodKey.name) && - signature.equals(methodKey.signature); + return name.equals(methodKey.name) + && signature.equals(methodKey.signature); } @Override @@ -85,7 +89,7 @@ Object invoke(Class type, private static final Map ANNOTATION_METHODS = ImmutableMap.of( - MethodKey.of(Class.class, "annotationType"), (type, members, args) -> type, + MethodKey.of(Class.class, "annotationType"), (type, _, _) -> type, MethodKey.of(boolean.class, "equals", Object.class), (type, members, args) -> { if (!type.isInstance(args[0])) { return false; @@ -99,7 +103,7 @@ Object invoke(Class type, } return true; }, - MethodKey.of(int.class, "hashCode"), (type, members, args) -> { + MethodKey.of(int.class, "hashCode"), (_, members, _) -> { int result = 0; for (String name : members.keySet()) { Object value = members.get(name); @@ -107,7 +111,7 @@ Object invoke(Class type, } return result; }, - MethodKey.of(String.class, "toString"), (type, members, args) -> { + MethodKey.of(String.class, "toString"), (type, members, _) -> { StringBuilder output = new StringBuilder("@") .append(type.getName()) .append('('); @@ -142,7 +146,7 @@ static Annotation allDefaultsAnnotation(Class annotationTy return (Annotation) Proxy.newProxyInstance( annotationType.getClassLoader(), new Class[] {annotationType}, - (proxy, method, args) -> { + (_, method, args) -> { AnnoMethod call = ANNOTATION_METHODS.get(MethodKey.from(method)); if (call != null) { return call.invoke(annotationType, members, args); @@ -155,4 +159,9 @@ static Annotation allDefaultsAnnotation(Class annotationTy } ); } + + private Annotations() { + throw new RuntimeException(); + } + } diff --git a/core/src/main/java/org/enginehub/piston/part/CommandArgument.java b/core/src/main/java/org/enginehub/piston/part/CommandArgument.java index 5c94ecb..7ecf73b 100644 --- a/core/src/main/java/org/enginehub/piston/part/CommandArgument.java +++ b/core/src/main/java/org/enginehub/piston/part/CommandArgument.java @@ -84,6 +84,7 @@ public final Builder ofTypes(Collection> types) { /** * Check if this argument a variable argument. * + *

* That is, does it accept a variable amount of inputs, rather than one? */ public abstract boolean isVariable(); diff --git a/core/src/main/java/org/enginehub/piston/util/CaseHelper.java b/core/src/main/java/org/enginehub/piston/util/CaseHelper.java index 3a8f396..99b763b 100644 --- a/core/src/main/java/org/enginehub/piston/util/CaseHelper.java +++ b/core/src/main/java/org/enginehub/piston/util/CaseHelper.java @@ -97,4 +97,9 @@ public static String camelToTitle(String camelCase) { camelCase.length()); return out.toString(); } + + private CaseHelper() { + throw new RuntimeException(); + } + } diff --git a/core/src/main/java/org/enginehub/piston/util/PartHelper.java b/core/src/main/java/org/enginehub/piston/util/PartHelper.java index a24a602..a62dc98 100644 --- a/core/src/main/java/org/enginehub/piston/util/PartHelper.java +++ b/core/src/main/java/org/enginehub/piston/util/PartHelper.java @@ -111,4 +111,8 @@ private static Stream buildOptionalMerging(SubCommandPart optionalSub )); } + private PartHelper() { + throw new RuntimeException(); + } + } diff --git a/core/src/main/java/org/enginehub/piston/util/ValueProvider.java b/core/src/main/java/org/enginehub/piston/util/ValueProvider.java index b5e8321..3650448 100644 --- a/core/src/main/java/org/enginehub/piston/util/ValueProvider.java +++ b/core/src/main/java/org/enginehub/piston/util/ValueProvider.java @@ -30,7 +30,7 @@ public interface ValueProvider { static ValueProvider constant(@Nullable T value) { Optional opt = Optional.ofNullable(value); - return context -> opt; + return _ -> opt; } /** diff --git a/core/src/test/java/org/enginehub/piston/ConditionTest.java b/core/src/test/java/org/enginehub/piston/ConditionTest.java index 855ed29..784a160 100644 --- a/core/src/test/java/org/enginehub/piston/ConditionTest.java +++ b/core/src/test/java/org/enginehub/piston/ConditionTest.java @@ -59,7 +59,7 @@ interface ConditionSubtype extends Command.Condition { @Test void as() { assertFalse(FALSE.as(ConditionSubtype.class).isPresent()); - ConditionSubtype st = ctx -> true; + ConditionSubtype st = _ -> true; assertEquals(st, st.as(ConditionSubtype.class).orElse(null)); } diff --git a/core/src/test/java/org/enginehub/piston/exception/ConstructionTest.java b/core/src/test/java/org/enginehub/piston/exception/ConstructionTest.java index a0e66a2..ee6d40d 100644 --- a/core/src/test/java/org/enginehub/piston/exception/ConstructionTest.java +++ b/core/src/test/java/org/enginehub/piston/exception/ConstructionTest.java @@ -42,7 +42,7 @@ public class ConstructionTest { @Test void conditionFailedException() { Command command = mock(Command.class); - Command.Condition uniqCondition = p -> false; + Command.Condition uniqCondition = _ -> false; when(command.getCondition()).thenReturn(uniqCondition); ImmutableList commands = ImmutableList.of(command); ConditionFailedException ex = new ConditionFailedException(commands); diff --git a/default-impl/src/main/java/org/enginehub/piston/impl/CommandParser.java b/default-impl/src/main/java/org/enginehub/piston/impl/CommandParser.java index cfdb105..fa2ed41 100644 --- a/default-impl/src/main/java/org/enginehub/piston/impl/CommandParser.java +++ b/default-impl/src/main/java/org/enginehub/piston/impl/CommandParser.java @@ -556,8 +556,8 @@ private void parseFlags(String flags) { if (flag instanceof ArgAcceptingCommandFlag argPart) { if (i + 1 < flags.length()) { // Only allow argument-flags at the end of flag-combos. - throw usageException(text("Argument-accepting flags must be " + - "at the end of combined flag groups.")); + throw usageException(text("Argument-accepting flags must be " + + "at the end of combined flag groups.")); } bind(flag, true); if (!hasNextArgument()) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e2f7fa1..0824cb0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,6 +7,7 @@ kyoriAdventure = "5.1.1" log4j = "2.26.0" [libraries] +crankcase-checkstyle = { module = "org.enginehub.crankcase:checkstyle", version.ref = "crankcase" } crankcase-java = { module = "org.enginehub.crankcase:java", version.ref = "crankcase" } crankcase-javaLibrary = { module = "org.enginehub.crankcase:java-library", version.ref = "crankcase" } crankcase-licensing = { module = "org.enginehub.crankcase:licensing", version.ref = "crankcase" } From 20e60c17bdb37110b9a453311bc7e389ad2602db Mon Sep 17 00:00:00 2001 From: Octavia Togami Date: Sun, 19 Jul 2026 20:51:10 -0700 Subject: [PATCH 4/4] Clean up warnings and enable failOnWarnings This has minor API breakage, but it fixes ambiguity with SuccessfulConversion --- .../kotlin/piston.java-conventions.gradle.kts | 6 +- .../gen/CommandParameterInterpreter.java | 24 ++++-- .../piston/gen/CommandProcessor.java | 5 +- .../gen/CommandRegistrationGenerator.java | 4 - .../gen/optimize/CollectionOptimization.java | 1 - .../CommandParamInfoOptimization.java | 8 +- .../gen/optimize/ExtractSpecOptimization.java | 44 ----------- .../piston/gen/optimize/Optimization.java | 1 - .../piston/gen/util/CodeBlockUtil.java | 8 +- .../enginehub/piston/gen/util/SafeName.java | 13 ++-- .../piston/gen/util/TypeNameUtil.java | 12 +-- .../piston/gen/value/ExtractSpec.java | 3 +- .../piston/gen/value/RegistrationInfo.java | 7 +- .../piston/internal/RegistrationUtil.java | 2 +- .../org/enginehub/piston/config/Config.java | 1 + .../enginehub/piston/config/ConfigHolder.java | 7 +- .../piston/converter/ConversionResult.java | 12 +-- .../piston/converter/FailedConversion.java | 8 +- .../converter/SuccessfulConversion.java | 23 +++--- .../exception/ConversionFailedException.java | 1 + .../enginehub/piston/inject/Annotations.java | 5 +- .../piston/inject/InjectedValueAccess.java | 2 + .../piston/inject/MemoizingValueAccess.java | 4 +- .../piston/util/ComponentHelper.java | 6 +- .../converter/SuccessfulConversionTest.java | 74 +++++++++++++++++++ .../piston/impl/CommandManagerImpl.java | 1 + .../enginehub/piston/impl/CommandParser.java | 7 -- 27 files changed, 161 insertions(+), 128 deletions(-) delete mode 100644 core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/ExtractSpecOptimization.java create mode 100644 core/src/test/java/org/enginehub/piston/converter/SuccessfulConversionTest.java diff --git a/build-logic/src/main/kotlin/piston.java-conventions.gradle.kts b/build-logic/src/main/kotlin/piston.java-conventions.gradle.kts index ddcd06b..e2a9559 100644 --- a/build-logic/src/main/kotlin/piston.java-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/piston.java-conventions.gradle.kts @@ -8,8 +8,10 @@ plugins { crankcaseJava { javaRelease = 25 - // TODO: fix all warnings - failOnWarnings = false + // AutoValue & JSpecify annotations are never claimed by a processor + disabledLints.add("processing") + // exceptions are Serializable via Throwable, but we never serialize them + disabledLints.add("serial") } tasks.named("processTestResources") { diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandParameterInterpreter.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandParameterInterpreter.java index 5a2d170..2e01b2c 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandParameterInterpreter.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandParameterInterpreter.java @@ -109,10 +109,14 @@ private CommandParamInfo argTransform(VariableElement parameter) { String desc = getValue(parameter, arg, "desc", String.class); List defaults = getList(parameter, arg, "def", String.class); CodeBlock.Builder construction = CodeBlock.builder() - .add("$T.arg($L, $L)\n" - + ".defaultsTo($L)\n", + .add( + """ + $T.arg($L, $L) + .defaultsTo($L) + """, CommandParts.class, transCompOf(prefixArgName(env, name)), textCompOf(desc), - stringListForGen(defaults.stream())); + stringListForGen(defaults.stream()) + ); addArgTypes(parameter, construction); if (getValue(parameter, arg, "variable", boolean.class)) { construction.add(".variable(true)\n"); @@ -138,13 +142,17 @@ private CommandParamInfo argFlagTransform(VariableElement parameter) { String desc = getValue(parameter, arg, "desc", String.class); List defaults = getList(parameter, arg, "def", String.class); CodeBlock.Builder construction = CodeBlock.builder() - .add("$T.flag('$L', $L)\n" - + ".withRequiredArg()\n" - + ".argNamed($L)\n" - + ".defaultsTo($L)\n", + .add( + """ + $T.flag('$L', $L) + .withRequiredArg() + .argNamed($L) + .defaultsTo($L) + """, CommandParts.class, name, textCompOf(desc), transCompOf(prefixArgName(env, argName)), - stringListForGen(defaults.stream())); + stringListForGen(defaults.stream()) + ); addArgTypes(parameter, construction); construction.add(".build()"); return CommandParamInfo.builder() diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandProcessor.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandProcessor.java index 351596d..4a06d49 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandProcessor.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandProcessor.java @@ -36,7 +36,6 @@ import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.gen.optimize.CommandInfoOptimization; import org.enginehub.piston.gen.optimize.CommandParamInfoOptimization; -import org.enginehub.piston.gen.optimize.ExtractSpecOptimization; import org.enginehub.piston.gen.util.ProcessingException; import org.enginehub.piston.gen.value.CommandInfo; import org.enginehub.piston.gen.value.CommandParamInfo; @@ -169,9 +168,7 @@ private String getRegistrationClassName(ClassName className) { private CommandInfoOptimization buildOptimizer(IdentifierTracker identifierTracker) { return new CommandInfoOptimization( - new CommandParamInfoOptimization( - new ExtractSpecOptimization(identifierTracker), - identifierTracker), + new CommandParamInfoOptimization(identifierTracker), identifierTracker); } diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandRegistrationGenerator.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandRegistrationGenerator.java index 548cd1b..511a007 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandRegistrationGenerator.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/CommandRegistrationGenerator.java @@ -133,10 +133,6 @@ private Stream getInjectedVariables() { return injectedVariables.stream(); } - private static boolean isCommandStatic(CommandInfo info) { - return info.getCommandMethod().getModifiers().contains(STATIC); - } - private Modifier[] getApiVisibilityModifiers() { return info.getClassVisibility() == null ? new Modifier[0] diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/CollectionOptimization.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/CollectionOptimization.java index a2eb062..858b70d 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/CollectionOptimization.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/CollectionOptimization.java @@ -27,7 +27,6 @@ * * @param the element type of the optimized collection */ -@FunctionalInterface public interface CollectionOptimization extends Optimization> { @Override diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/CommandParamInfoOptimization.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/CommandParamInfoOptimization.java index e07e8ca..858c415 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/CommandParamInfoOptimization.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/CommandParamInfoOptimization.java @@ -28,17 +28,11 @@ public class CommandParamInfoOptimization implements CollectionOptimization { - private final ExtractSpecOptimization extractSpecOptimization; - private final IdentifierTracker identifierTracker; // map from an original param to one with the modified name private final Map newSpecMapping = new HashMap<>(); - public CommandParamInfoOptimization( - ExtractSpecOptimization extractSpecOptimization, - IdentifierTracker identifierTracker - ) { - this.extractSpecOptimization = extractSpecOptimization; + public CommandParamInfoOptimization(IdentifierTracker identifierTracker) { this.identifierTracker = identifierTracker; } diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/ExtractSpecOptimization.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/ExtractSpecOptimization.java deleted file mode 100644 index 03f0fc0..0000000 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/ExtractSpecOptimization.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Piston, a flexible command management system. - * Copyright (C) EngineHub - * Copyright (C) Piston contributors - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see . - */ - -package org.enginehub.piston.gen.optimize; - -import org.enginehub.piston.gen.IdentifierTracker; -import org.enginehub.piston.gen.value.ExtractSpec; - -import java.util.HashMap; -import java.util.Map; - -public class ExtractSpecOptimization implements Optimization { - - private final IdentifierTracker identifierTracker; - // map from an original spec to one with the modified name - private final Map newSpecMapping = new HashMap<>(); - - public ExtractSpecOptimization(IdentifierTracker identifierTracker) { - this.identifierTracker = identifierTracker; - } - - @Override - public ExtractSpec optimize(ExtractSpec input) { - return newSpecMapping.computeIfAbsent(input, i -> - i.toBuilder().name(identifierTracker.methodName(i.getName())).build() - ); - } -} diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/Optimization.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/Optimization.java index 0e1fbf7..2b13486 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/Optimization.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/optimize/Optimization.java @@ -24,7 +24,6 @@ * * @param the type being optimized */ -@FunctionalInterface public interface Optimization { T optimize(T input); diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/CodeBlockUtil.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/CodeBlockUtil.java index 10cae66..653462f 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/CodeBlockUtil.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/CodeBlockUtil.java @@ -114,7 +114,7 @@ private static final class CodeBlockJoiner { this.suffix = requireNonNull(suffix); } - public CodeBlockJoiner setEmptyValue(@Nullable CodeBlock emptyValue) { + CodeBlockJoiner setEmptyValue(@Nullable CodeBlock emptyValue) { this.emptyValue = emptyValue; return this; } @@ -128,11 +128,11 @@ private CodeBlock.Builder prepareBuilder() { return value; } - public void add(CodeBlock block) { + void add(CodeBlock block) { prepareBuilder().add(block); } - public CodeBlockJoiner merge(CodeBlockJoiner joiner) { + CodeBlockJoiner merge(CodeBlockJoiner joiner) { // do not inline -- want to finish the joiner before adding, // in case `joiner` == `this` CodeBlock content = joiner.finishRaw().build(); @@ -147,7 +147,7 @@ private CodeBlock.Builder finishRaw() { return value == null ? CodeBlock.builder() : value; } - public CodeBlock finish() { + CodeBlock finish() { if (value == null && emptyValue != null) { return emptyValue; } diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/SafeName.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/SafeName.java index 3d989b5..8804d20 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/SafeName.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/SafeName.java @@ -57,12 +57,11 @@ public static String getNameAsIdentifier(TypeName typeName) { } private static CharSequence getNameAsIdentifierRaw(TypeName typeName) { - if (typeName instanceof ClassName) { + if (typeName instanceof ClassName className) { // good, just the raw name works here - return ((ClassName) typeName).simpleName(); - } else if (typeName instanceof ParameterizedTypeName) { + return className.simpleName(); + } else if (typeName instanceof ParameterizedTypeName pt) { // append the type parameters - ParameterizedTypeName pt = (ParameterizedTypeName) typeName; ClassName raw = pt.rawType; StringBuilder result = new StringBuilder( getNameAsIdentifierRaw(raw) @@ -71,10 +70,10 @@ private static CharSequence getNameAsIdentifierRaw(TypeName typeName) { result.append('$').append(getNameAsIdentifierRaw(typeArgument)); } return result; - } else if (typeName instanceof ArrayTypeName) { + } else if (typeName instanceof ArrayTypeName arrayTypeName) { // append Array to the name - CharSequence base = getNameAsIdentifierRaw(((ArrayTypeName) typeName).componentType); - return new StringBuilder(base).append("$Array"); + CharSequence base = getNameAsIdentifierRaw(arrayTypeName.componentType); + return base + "$Array"; } // just use toString() as a last resort return typeName.toString(); diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/TypeNameUtil.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/TypeNameUtil.java index e49ff16..d17d750 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/TypeNameUtil.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/util/TypeNameUtil.java @@ -29,10 +29,10 @@ public class TypeNameUtil { public static TypeName rawType(TypeName typeName) { if (typeName instanceof ClassName) { return typeName; - } else if (typeName instanceof ArrayTypeName) { - return ArrayTypeName.of(rawType(((ArrayTypeName) typeName).componentType)); - } else if (typeName instanceof ParameterizedTypeName) { - return ((ParameterizedTypeName) typeName).rawType; + } else if (typeName instanceof ArrayTypeName arrayTypeName) { + return ArrayTypeName.of(rawType(arrayTypeName.componentType)); + } else if (typeName instanceof ParameterizedTypeName parameterized) { + return parameterized.rawType; } else if (typeName.isPrimitive()) { return typeName; } @@ -41,8 +41,8 @@ public static TypeName rawType(TypeName typeName) { } public static TypeName firstTypeArg(TypeName typeName) { - if (typeName instanceof ParameterizedTypeName) { - return ((ParameterizedTypeName) typeName).typeArguments.get(0); + if (typeName instanceof ParameterizedTypeName parameterized) { + return parameterized.typeArguments.get(0); } return TypeName.OBJECT; } diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/ExtractSpec.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/ExtractSpec.java index d2040b8..f270162 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/ExtractSpec.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/ExtractSpec.java @@ -91,10 +91,9 @@ public final boolean equals(Object obj) { if (this == obj) { return true; } - if (!(obj instanceof ExtractSpec)) { + if (!(obj instanceof ExtractSpec spec)) { return false; } - ExtractSpec spec = (ExtractSpec) obj; boolean fastChecks = Objects.equals(getName(), spec.getName()) && Objects.equals(getType(), spec.getType()); if (!fastChecks) { diff --git a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/RegistrationInfo.java b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/RegistrationInfo.java index 9f78bfb..98a7dca 100644 --- a/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/RegistrationInfo.java +++ b/core-ap/processor/src/main/java/org/enginehub/piston/gen/value/RegistrationInfo.java @@ -34,9 +34,10 @@ public abstract class RegistrationInfo { public static Builder builder() { Builder builder = new AutoValue_RegistrationInfo.Builder(); - builder.injectedVariablesBuilder(); - builder.declaredFieldsBuilder(); - builder.keyTypesBuilder(); + // calling the sub-builders initializes them, so the collections default to empty + var _ = builder.injectedVariablesBuilder(); + var _ = builder.declaredFieldsBuilder(); + var _ = builder.keyTypesBuilder(); return builder; } diff --git a/core-ap/runtime/src/main/java/org/enginehub/piston/internal/RegistrationUtil.java b/core-ap/runtime/src/main/java/org/enginehub/piston/internal/RegistrationUtil.java index 84a15cf..aa6e309 100644 --- a/core-ap/runtime/src/main/java/org/enginehub/piston/internal/RegistrationUtil.java +++ b/core-ap/runtime/src/main/java/org/enginehub/piston/internal/RegistrationUtil.java @@ -38,7 +38,7 @@ public static T requireOptional(Key type, String name, Optional option ); } - public static Method getCommandMethod(Class registrationClass, String methodName, Class... parameterTypes) { + public static Method getCommandMethod(Class registrationClass, String methodName, Class... parameterTypes) { try { return registrationClass.getDeclaredMethod(methodName, parameterTypes); } catch (NoSuchMethodException _) { diff --git a/core/src/main/java/org/enginehub/piston/config/Config.java b/core/src/main/java/org/enginehub/piston/config/Config.java index 4374064..2fb7099 100644 --- a/core/src/main/java/org/enginehub/piston/config/Config.java +++ b/core/src/main/java/org/enginehub/piston/config/Config.java @@ -38,6 +38,7 @@ public abstract class Config { private final String key; private @Nullable T value; + @SuppressWarnings("this-escape") protected Config(String key, @Nullable T defaultValue) { this.key = key; checkValue(defaultValue); diff --git a/core/src/main/java/org/enginehub/piston/config/ConfigHolder.java b/core/src/main/java/org/enginehub/piston/config/ConfigHolder.java index 109b29f..198f610 100644 --- a/core/src/main/java/org/enginehub/piston/config/ConfigHolder.java +++ b/core/src/main/java/org/enginehub/piston/config/ConfigHolder.java @@ -19,6 +19,7 @@ package org.enginehub.piston.config; +import com.google.errorprone.annotations.InlineMe; import net.kyori.adventure.text.Component; import java.util.HashMap; @@ -64,7 +65,11 @@ public void addConfig(Config config) { * @deprecated Use {@link ConfigRenderer} instead */ @Deprecated - public Component replace(Component input) { + @InlineMe( + replacement = "ConfigRenderer.getInstance().render(input, this)", + imports = "org.enginehub.piston.config.ConfigRenderer" + ) + public final Component replace(Component input) { return ConfigRenderer.getInstance().render(input, this); } diff --git a/core/src/main/java/org/enginehub/piston/converter/ConversionResult.java b/core/src/main/java/org/enginehub/piston/converter/ConversionResult.java index 46550f8..31cb0f4 100644 --- a/core/src/main/java/org/enginehub/piston/converter/ConversionResult.java +++ b/core/src/main/java/org/enginehub/piston/converter/ConversionResult.java @@ -22,7 +22,7 @@ import com.google.common.collect.ImmutableList; import org.enginehub.piston.inject.InjectedValueAccess; -import java.util.Collection; +import java.util.SequencedCollection; import java.util.function.Function; import static com.google.common.base.Preconditions.checkArgument; @@ -74,17 +74,19 @@ public abstract class ConversionResult { * @param the new type * @return the new result */ - public abstract ConversionResult map(Function, ? extends Collection> mapper); + public abstract ConversionResult map( + Function, ? extends SequencedCollection> mapper + ); public final ConversionResult mapSingle(Function mapper) { return map(many -> { checkArgument(many.size() == 1, "Need exactly one result"); - U result = mapper.apply(many.iterator().next()); + U result = mapper.apply(many.getFirst()); return result == null ? null : ImmutableList.of(result); }); } - public final Collection orElse(Collection other) { + public final SequencedCollection orElse(SequencedCollection other) { if (isSuccessful()) { return get(); } @@ -94,6 +96,6 @@ public final Collection orElse(Collection other) { /** * Get the result, or throw an exception with all collected errors. */ - public abstract Collection get(); + public abstract ImmutableList get(); } diff --git a/core/src/main/java/org/enginehub/piston/converter/FailedConversion.java b/core/src/main/java/org/enginehub/piston/converter/FailedConversion.java index 5ee153f..c12ad4c 100644 --- a/core/src/main/java/org/enginehub/piston/converter/FailedConversion.java +++ b/core/src/main/java/org/enginehub/piston/converter/FailedConversion.java @@ -19,11 +19,13 @@ package org.enginehub.piston.converter; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import java.util.Collection; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.SequencedCollection; import java.util.function.Function; public final class FailedConversion extends ConversionResult { @@ -69,7 +71,9 @@ public ConversionResult orElse(ConversionResult result) { } @Override - public ConversionResult map(Function, ? extends Collection> mapper) { + public ConversionResult map( + Function, ? extends SequencedCollection> mapper + ) { return failureAsAny(); } @@ -82,7 +86,7 @@ public ImmutableSet> getOtherFailures() { } @Override - public Collection get() { + public ImmutableList get() { throw FailedConversionMapper.mapOnto(NoSuchElementException::new, this); } diff --git a/core/src/main/java/org/enginehub/piston/converter/SuccessfulConversion.java b/core/src/main/java/org/enginehub/piston/converter/SuccessfulConversion.java index 52fbc30..12c62ac 100644 --- a/core/src/main/java/org/enginehub/piston/converter/SuccessfulConversion.java +++ b/core/src/main/java/org/enginehub/piston/converter/SuccessfulConversion.java @@ -20,9 +20,10 @@ package org.enginehub.piston.converter; import com.google.common.collect.ImmutableList; +import org.jspecify.annotations.Nullable; -import java.util.Collection; import java.util.Objects; +import java.util.SequencedCollection; import java.util.function.Function; public final class SuccessfulConversion extends ConversionResult { @@ -35,19 +36,19 @@ public static SuccessfulConversion fromSingle(T result, boolean exactMatc return from(ImmutableList.of(result), exactMatch); } - public static SuccessfulConversion from(Collection result) { + public static SuccessfulConversion from(SequencedCollection result) { return new SuccessfulConversion<>(result, true); } - public static SuccessfulConversion from(Collection result, boolean exactMatch) { + public static SuccessfulConversion from(SequencedCollection result, boolean exactMatch) { return new SuccessfulConversion<>(result, exactMatch); } - private final Collection result; + private final ImmutableList result; private final boolean exactMatch; - private SuccessfulConversion(Collection result, boolean exactMatch) { - this.result = result; + private SuccessfulConversion(SequencedCollection result, boolean exactMatch) { + this.result = ImmutableList.copyOf(result); this.exactMatch = exactMatch; } @@ -82,8 +83,10 @@ public ConversionResult orElse(ConversionResult result) { } @Override - public ConversionResult map(Function, ? extends Collection> mapper) { - Collection mapped; + public ConversionResult map( + Function, ? extends SequencedCollection> mapper + ) { + SequencedCollection mapped; try { mapped = mapper.apply(get()); } catch (Throwable t) { @@ -96,12 +99,12 @@ public ConversionResult map(Function, ? extends Col } @Override - public Collection get() { + public ImmutableList get() { return result; } @Override - public boolean equals(Object o) { + public boolean equals(@Nullable Object o) { if (this == o) { return true; } diff --git a/core/src/main/java/org/enginehub/piston/exception/ConversionFailedException.java b/core/src/main/java/org/enginehub/piston/exception/ConversionFailedException.java index abc3018..e5a64be 100644 --- a/core/src/main/java/org/enginehub/piston/exception/ConversionFailedException.java +++ b/core/src/main/java/org/enginehub/piston/exception/ConversionFailedException.java @@ -51,6 +51,7 @@ private static Component getMessage(Component conversionTarget, ArgumentConverte private final ArgumentConverter converter; private final FailedConversion conversion; + @SuppressWarnings("this-escape") public ConversionFailedException(CommandParseResult parseResult, Component conversionTarget, ArgumentConverter converter, diff --git a/core/src/main/java/org/enginehub/piston/inject/Annotations.java b/core/src/main/java/org/enginehub/piston/inject/Annotations.java index 2d13de2..2301cde 100644 --- a/core/src/main/java/org/enginehub/piston/inject/Annotations.java +++ b/core/src/main/java/org/enginehub/piston/inject/Annotations.java @@ -26,7 +26,6 @@ import org.jspecify.annotations.Nullable; import java.lang.annotation.Annotation; -import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; @@ -135,8 +134,6 @@ private static String valueToString(@Nullable Object value) { return value.toString(); } - private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); - static Annotation allDefaultsAnnotation(Class annotationType) { Map members = Stream.of(annotationType.getDeclaredMethods()) .collect(toMap( @@ -145,7 +142,7 @@ static Annotation allDefaultsAnnotation(Class annotationTy )); return (Annotation) Proxy.newProxyInstance( annotationType.getClassLoader(), - new Class[] {annotationType}, + new Class[] {annotationType}, (_, method, args) -> { AnnoMethod call = ANNOTATION_METHODS.get(MethodKey.from(method)); if (call != null) { diff --git a/core/src/main/java/org/enginehub/piston/inject/InjectedValueAccess.java b/core/src/main/java/org/enginehub/piston/inject/InjectedValueAccess.java index 67fa4cc..7e3f4cf 100644 --- a/core/src/main/java/org/enginehub/piston/inject/InjectedValueAccess.java +++ b/core/src/main/java/org/enginehub/piston/inject/InjectedValueAccess.java @@ -28,6 +28,8 @@ */ public interface InjectedValueAccess { + // the cycle is only enterable through this field, so two threads can't deadlock on it + @SuppressWarnings("ClassInitializationDeadlock") InjectedValueAccess EMPTY = EmptyInjectedValueAccess.INSTANCE; /** diff --git a/core/src/main/java/org/enginehub/piston/inject/MemoizingValueAccess.java b/core/src/main/java/org/enginehub/piston/inject/MemoizingValueAccess.java index a21a9e2..713ed15 100644 --- a/core/src/main/java/org/enginehub/piston/inject/MemoizingValueAccess.java +++ b/core/src/main/java/org/enginehub/piston/inject/MemoizingValueAccess.java @@ -34,8 +34,8 @@ public final class MemoizingValueAccess implements InjectedValueAccess { public static MemoizingValueAccess wrap(InjectedValueAccess delegate) { - if (delegate instanceof MemoizingValueAccess) { - return (MemoizingValueAccess) delegate; + if (delegate instanceof MemoizingValueAccess memoizing) { + return memoizing; } return new MemoizingValueAccess(delegate); } diff --git a/core/src/main/java/org/enginehub/piston/util/ComponentHelper.java b/core/src/main/java/org/enginehub/piston/util/ComponentHelper.java index e313004..8deb1c2 100644 --- a/core/src/main/java/org/enginehub/piston/util/ComponentHelper.java +++ b/core/src/main/java/org/enginehub/piston/util/ComponentHelper.java @@ -75,18 +75,18 @@ private TextComponent.Builder initBuilder() { return value; } - public void add(Component component) { + void add(Component component) { initBuilder().append(component); } - public ComponentJoiner merge(ComponentJoiner other) { + ComponentJoiner merge(ComponentJoiner other) { if (other.value != null) { initBuilder().append(other.value.build()); } return this; } - public Component finish() { + Component finish() { if (value == null) { if (nullValue != null) { return nullValue; diff --git a/core/src/test/java/org/enginehub/piston/converter/SuccessfulConversionTest.java b/core/src/test/java/org/enginehub/piston/converter/SuccessfulConversionTest.java new file mode 100644 index 0000000..7a7c18c --- /dev/null +++ b/core/src/test/java/org/enginehub/piston/converter/SuccessfulConversionTest.java @@ -0,0 +1,74 @@ +/* + * Piston, a flexible command management system. + * Copyright (C) EngineHub + * Copyright (C) Piston contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package org.enginehub.piston.converter; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +public class SuccessfulConversionTest { + + @Test + void equalContentsFromDifferentCollectionTypes() { + assertEquals( + SuccessfulConversion.from(List.of("a", "b")), + SuccessfulConversion.from(new LinkedHashSet<>(List.of("a", "b"))) + ); + } + + @Test + void equalContentsFromCollectionWithoutEquals() { + assertEquals( + SuccessfulConversion.from(List.of("a", "b")), + SuccessfulConversion.from(new ArrayDeque<>(List.of("a", "b"))) + ); + } + + @Test + void equalContentsHashConsistently() { + assertEquals( + SuccessfulConversion.from(List.of("a", "b")).hashCode(), + SuccessfulConversion.from(new ArrayDeque<>(List.of("a", "b"))).hashCode() + ); + } + + @Test + void differingContentsAreNotEqual() { + assertNotEquals( + SuccessfulConversion.from(List.of("a", "b")), + SuccessfulConversion.from(List.of("b", "a")) + ); + } + + @Test + void mutatingTheSourceDoesNotAffectTheResult() { + List source = new ArrayList<>(List.of("a")); + SuccessfulConversion conversion = SuccessfulConversion.from(source); + source.add("b"); + assertEquals(List.of("a"), conversion.get()); + } + +} diff --git a/default-impl/src/main/java/org/enginehub/piston/impl/CommandManagerImpl.java b/default-impl/src/main/java/org/enginehub/piston/impl/CommandManagerImpl.java index 65445c8..82e0ea4 100644 --- a/default-impl/src/main/java/org/enginehub/piston/impl/CommandManagerImpl.java +++ b/default-impl/src/main/java/org/enginehub/piston/impl/CommandManagerImpl.java @@ -58,6 +58,7 @@ public class CommandManagerImpl implements CommandManager { private final Map, ArgumentConverter> converters = new HashMap<>(); private final CommandInfoCache commandInfoCache = new CommandInfoCache(); + @SuppressWarnings("this-escape") public CommandManagerImpl() { registerConverter(Key.of(String.class), ArgumentConverters.forString()); for (Class wrapperType : ImmutableList.of( diff --git a/default-impl/src/main/java/org/enginehub/piston/impl/CommandParser.java b/default-impl/src/main/java/org/enginehub/piston/impl/CommandParser.java index fa2ed41..5512c7f 100644 --- a/default-impl/src/main/java/org/enginehub/piston/impl/CommandParser.java +++ b/default-impl/src/main/java/org/enginehub/piston/impl/CommandParser.java @@ -273,13 +273,6 @@ private ArgConsumingCommandPart nextPart() { return perCommandDetails().partIter.next(); } - private void unconsumePart() { - ListIterator partIter = perCommandDetails().partIter; - checkState(partIter.hasPrevious(), - "Trying to unconsume nothing"); - partIter.previous(); - } - private void bind(CommandPart part, boolean exact) { argBindings.put(part, exact); }