Skip to content
Open
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
4 changes: 4 additions & 0 deletions build-logic/build-parameters/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ buildParameters {
defaultValue.set(true)
description.set("Skip forbidden-apis verifications")
}
bool("skipOpenrewrite") {
defaultValue.set(true)
description.set("Skip OpenRewrite code cleanup (rewriteRun/rewriteDryRun). Enabled off by default until the recipe artifacts are added to gradle/verification-metadata.xml")
}
bool("suppressPomMetadataWarnings") {
defaultValue.set(true)
description.set("Skip suppressPomMetadataWarningsFor warnings triggered by inability to map test fixtures dependences to Maven pom.xml")
Expand Down
1 change: 1 addition & 0 deletions build-logic/jvm/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ dependencies {
api("org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin:2.2.21")
api("org.jetbrains.kotlin.kapt:org.jetbrains.kotlin.kapt.gradle.plugin:2.2.21")
api("org.jetbrains.dokka-javadoc:org.jetbrains.dokka-javadoc.gradle.plugin:2.1.0")
api(projects.openrewrite)
}
67 changes: 67 additions & 0 deletions build-logic/jvm/src/main/kotlin/build-logic.openrewrite.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

plugins {
id("build-logic.openrewrite-base")
}

dependencies {
// rewrite-core, rewrite-java, rewrite-kotlin and the other parsers arrive transitively
// with the recipe modules below; the isolated worker resolves everything from here.
"openrewrite"(platform("org.openrewrite.recipe:rewrite-recipe-bom:3.34.0"))
"openrewrite"("org.openrewrite.recipe:rewrite-static-analysis")
"openrewrite"("org.openrewrite.recipe:rewrite-testing-frameworks")
// JavaParser.fromJavaVersion() picks the parser backend matching the worker JVM, so the
// version-specific parsers must be on the recipe classpath.
"openrewrite"("org.openrewrite:rewrite-java-17")
"openrewrite"("org.openrewrite:rewrite-java-21")
"openrewrite"("org.openrewrite:rewrite-java-25")
}

openrewrite {
configFile.set(rootProject.file("config/openrewrite/rewrite.yml"))
// Report violations instead of failing the dry run so the aggregate styleCheck task can
// collect the reports from every module.
failOnDryRunResults.set(false)

activeStyles.add("org.apache.jmeter.style.Style")

// See config/openrewrite/rewrite.yml. These static-analysis recipes run on Java and Kotlin.
activeRecipes.add("org.apache.jmeter.staticanalysis.CodeCleanup")
activeRecipes.add("org.apache.jmeter.staticanalysis.CommonStaticAnalysis")

plugins.withId("build-logic.test-junit5") {
activeRecipes.add("org.openrewrite.java.testing.junit5.JUnit5BestPractices")
activeRecipes.add("org.openrewrite.java.testing.junit5.CleanupAssertions")
}

// Recipes that crash or corrupt output are disabled by name here instead of dropping the
// whole composite. AssertThrowsOnLastStatement throws on Kotlin sources; see the fix in
// https://github.com/openrewrite/rewrite-testing-frameworks/pull/1048
disabledRecipes.add("org.openrewrite.java.testing.junit5.AssertThrowsOnLastStatement")

// Kotlin processing is off by default (see build-logic.openrewrite-base). When it is enabled
// via -PopenrewriteKotlin=true, these Java recipes still corrupt Kotlin and must also be
// disabled — verified by applying them and compiling the result:
// - ShortenFullyQualifiedTypeReferences drops a qualifier without adding the import
// (`API.Status.EXPERIMENTAL` -> `Status.EXPERIMENTAL`);
// - TypecastParenPad mangles `x as Foo` into `x asFoo` (root cause fixed in
// https://github.com/openrewrite/rewrite/pull/8236);
// - OperatorWrap moves a binary `+` to the start of the next line, which Kotlin parses as a
// unary plus and breaks the expression.
// They are left active by default because they are safe and useful on the Java sources.
}
32 changes: 32 additions & 0 deletions build-logic/openrewrite/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

plugins {
id("build-logic.kotlin-dsl-gradle-plugin")
}

dependencies {
// The OpenRewrite libraries are needed only to COMPILE the worker: at runtime the worker
// runs in an isolated process and gets rewrite-core/java/kotlin plus the recipe modules
// from the project's `openrewrite` configuration. Keeping them compileOnly avoids pulling
// OpenRewrite (and ClassGraph) onto the Gradle build-logic classpath.
compileOnly(platform("org.openrewrite.recipe:rewrite-recipe-bom:3.34.0"))
compileOnly("org.openrewrite:rewrite-core")
compileOnly("org.openrewrite:rewrite-java")
compileOnly("org.openrewrite:rewrite-kotlin")
compileOnly("org.openrewrite:rewrite-xml")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import org.apache.jmeter.buildtools.openrewrite.OpenRewriteBaseTask
import org.apache.jmeter.buildtools.openrewrite.OpenRewriteDiagnoseTask
import org.apache.jmeter.buildtools.openrewrite.OpenRewriteDryRunTask
import org.apache.jmeter.buildtools.openrewrite.OpenRewriteExtension
import org.apache.jmeter.buildtools.openrewrite.OpenRewriteRunTask
import org.gradle.api.attributes.Bundling
import org.gradle.api.attributes.java.TargetJvmEnvironment
import org.gradle.api.file.SourceDirectorySet
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.language.base.plugins.LifecycleBasePlugin

val openrewrite by configurations.creating {
description = "OpenRewrite recipe dependencies"
isCanBeConsumed = false
isCanBeResolved = false
}

val openrewriteClasspath by configurations.creating {
description = "Resolvable OpenRewrite recipe classpath"
isCanBeConsumed = false
isCanBeResolved = true
extendsFrom(openrewrite)
attributes {
attribute(
Bundling.BUNDLING_ATTRIBUTE,
objects.named(Bundling::class.java, Bundling.EXTERNAL)
)
attribute(
TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE,
objects.named(TargetJvmEnvironment::class.java, TargetJvmEnvironment.STANDARD_JVM)
)
}
}

val openrewriteExtension = extensions.create<OpenRewriteExtension>(OpenRewriteExtension.NAME)

fun configureCommon(task: OpenRewriteBaseTask) {
task.group = "openrewrite"
task.activeRecipes.set(openrewriteExtension.activeRecipes)
task.disabledRecipes.set(openrewriteExtension.disabledRecipes)
// Additively disable more recipes from the command line, e.g.
// -PopenrewriteDisable=org.openrewrite.java.ShortenFullyQualifiedTypeReferences,org.openrewrite.staticanalysis.TypecastParenPad
task.disabledRecipes.addAll(
providers.gradleProperty("openrewriteDisable")
.map { prop -> prop.split(",").map { it.trim() }.filter { it.isNotEmpty() } }
.orElse(emptyList())
)
task.activeStyles.set(openrewriteExtension.activeStyles)
task.rewriteClasspath.from(openrewriteClasspath)
task.configFile.set(openrewriteExtension.configFile)
task.projectRootDir.set(layout.projectDirectory)
task.logCompilationWarningsAndErrors.convention(false)
// Allow flipping Kotlin processing from the command line, e.g. -PopenrewriteKotlin=true
task.processKotlin.set(
providers.gradleProperty("openrewriteKotlin")
.map { it.toBoolean() }
.orElse(openrewriteExtension.processKotlin)
)
}

tasks.register<OpenRewriteRunTask>("rewriteRun") {
description = "Applies the active OpenRewrite recipes in place"
configureCommon(this)
}

tasks.register<OpenRewriteDryRunTask>("rewriteDryRun") {
description = "Reports the changes the active OpenRewrite recipes would make"
configureCommon(this)
reportDir.set(layout.buildDirectory.dir("reports/openrewrite"))
failOnDryRunResults.set(openrewriteExtension.failOnDryRunResults)
}

tasks.register<OpenRewriteDiagnoseTask>("rewriteDiagnose") {
description = "Runs each active leaf recipe on its own and reports failures and no-ops"
configureCommon(this)
reportDir.set(layout.buildDirectory.dir("reports/openrewrite"))
}

plugins.withId("java") {
the<JavaPluginExtension>().sourceSets.all {
val sourceSet: SourceSet = this
val javaRelease = tasks.named<JavaCompile>(sourceSet.compileJavaTaskName)
.flatMap { it.options.release }
tasks.withType<OpenRewriteBaseTask>().configureEach {
sourceSets.maybeCreate(sourceSet.name).apply {
this.javaRelease.set(javaRelease)
// Include the compiled classes (Java AND Kotlin output) so the Java parser can
// resolve types declared in Kotlin sources of the same module.
compileClasspath.from(sourceSet.compileClasspath)
compileClasspath.from(sourceSet.output.classesDirs)
srcDirSets.maybeCreate("java").files.from(sourceSet.java)
}
}
}
}

plugins.withId("org.jetbrains.kotlin.jvm") {
the<JavaPluginExtension>().sourceSets.all {
val sourceSet: SourceSet = this
val kotlin = (sourceSet as ExtensionAware).extensions.getByName("kotlin") as SourceDirectorySet
tasks.withType<OpenRewriteBaseTask>().configureEach {
sourceSets.maybeCreate(sourceSet.name)
.srcDirSets.maybeCreate("kotlin").files.from(kotlin)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.jmeter.buildtools.openrewrite

import org.gradle.api.model.ObjectFactory
import org.gradle.kotlin.dsl.property
import org.gradle.kotlin.dsl.setProperty
import javax.inject.Inject

open class OpenRewriteExtension @Inject constructor(objects: ObjectFactory) {
companion object {
const val NAME = "openrewrite"
}

val configFile = objects.fileProperty()

val activeStyles = objects.setProperty<String>()

val activeRecipes = objects.setProperty<String>()

/** Fully qualified recipe names to prune from the active recipe tree, e.g. ones that crash. */
val disabledRecipes = objects.setProperty<String>()

val failOnDryRunResults = objects.property<Boolean>().convention(true)

/**
* Whether to parse and rewrite Kotlin sources.
*
* Off by default: rewrite-kotlin does not round-trip Kotlin faithfully yet (for example it
* prints `x as Foo` back as `x asFoo`), so applying recipes corrupts otherwise untouched code.
* The Java parser still resolves types declared in Kotlin because the module's compiled Kotlin
* classes are on its compile classpath, so Java cleanup stays correct with this off.
*/
val processKotlin = objects.property<Boolean>().convention(false)
}
Loading
Loading