Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added gradle recipe to remove enableFeaturePreview method #4191

Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.openrewrite.gradle;

import java.util.List;
import lombok.EqualsAndHashCode;
import lombok.Value;
import org.jetbrains.annotations.NotNull;
import org.openrewrite.ExecutionContext;
import org.openrewrite.Option;
import org.openrewrite.Preconditions;
import org.openrewrite.Recipe;
import org.openrewrite.TreeVisitor;
import org.openrewrite.groovy.GroovyIsoVisitor;
import org.openrewrite.java.tree.Expression;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.J.Literal;
import org.openrewrite.java.tree.J.MethodInvocation;

@Value
@EqualsAndHashCode(callSuper = false)
public class RemoveEnableFeaturePreview extends Recipe {

@Option(displayName = "The feature preview name",
description = "The name of the feature preview to remove.",
example = "ONE_LOCKFILE_PER_PROJECT"
)
public String previewFeatureName;

@Override
public @NotNull String getDisplayName() {
return "Remove an enabled Gradle preview feature";
}

@Override
public @NotNull String getDescription() {
return "Remove an enabled Gradle preview feature from `settings.gradle`.";
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
return Preconditions.check(
new IsSettingsGradle<>(),
new RemoveEnableFeaturePreviewVisitor());
}

public class RemoveEnableFeaturePreviewVisitor extends GroovyIsoVisitor<ExecutionContext> {

@Override
public MethodInvocation visitMethodInvocation(
MethodInvocation method, @NotNull ExecutionContext executionContext) {

if (!"enableFeaturePreview".equals(method.getSimpleName())) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was using a method matcher, and it passed tests fine, but I manually ran this recipe against a few local gradle projects and it worked on 1 but on another it didn't match at all. The one it didn't work on, I debugged the LST and found that the method had a methodType of null for some reason. I dont' know if it's a bug in the parser or not, but I changed the logic here to just check the method name, check that there's exactly 1 argument, and check that the argument matches the @Option passed in.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It being flaky is a bit curious to me. My likely suspect though is that in the cases where it is not working, the type is missing from the Groovy AST -- coming out of the Groovy Compiler -- prior to it being mapped to the OpenRewrite Groovy LST.

return method;
}

List<Expression> arguments = method.getArguments();
if (arguments == null || arguments.size() != 1) {
return method;
}

Expression argument = arguments.get(0);
if (argument instanceof J.Literal) {
String candidatePreviewFeatureName = (String) ((Literal) argument).getValue();
if (previewFeatureName.equals(candidatePreviewFeatureName)) {
return null;
}
}

return method;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/*
* Copyright 2024 the original author or authors.
* <p>
* Licensed 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
* <p>
* https://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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.openrewrite.gradle;

import java.nio.file.Paths;
import org.junit.jupiter.api.Test;
import org.openrewrite.test.RewriteTest;

public class RemoveEnableFeaturePreviewTest implements RewriteTest {

@Test
void testRemoveEnableFeaturePreviewMethodRecipe_singleQuotes() {
//language=gradle
rewriteRun(
spec -> spec.recipe(new RemoveEnableFeaturePreview("ONE_LOCKFILE_PER_PROJECT")),
Assertions.settingsGradle(
"""
pluginManagement {
repositories {
gradlePluginPortal()
}
}

rootProject.name = 'merge-service'
enableFeaturePreview('ONE_LOCKFILE_PER_PROJECT')
""",
"""
pluginManagement {
repositories {
gradlePluginPortal()
}
}

rootProject.name = 'merge-service'
""",
spec -> spec.path(Paths.get("settings.gradle"))
)
);
}

@Test
void testRemoveEnableFeaturePreviewMethodRecipe_doubleQuotes() {
//language=gradle
rewriteRun(
spec -> spec.recipe(new RemoveEnableFeaturePreview("ONE_LOCKFILE_PER_PROJECT")),
Assertions.settingsGradle(
"""
pluginManagement {
repositories {
gradlePluginPortal()
}
}

rootProject.name = 'merge-service'
enableFeaturePreview("ONE_LOCKFILE_PER_PROJECT")

include 'service'
""",
"""
pluginManagement {
repositories {
gradlePluginPortal()
}
}

rootProject.name = 'merge-service'

include 'service'
""",
spec -> spec.path(Paths.get("settings.gradle"))
)
);
}

@Test
void testRemoveEnableFeaturePreviewMethodRecipe_noChange() {
//language=gradle
rewriteRun(
spec -> spec.recipe(new RemoveEnableFeaturePreview("ONE_LOCKFILE_PER_PROJECT")),
Assertions.settingsGradle(
"""
pluginManagement {
repositories {
gradlePluginPortal()
}
}

enableFeaturePreview("DIFFERENT_FEATURE")

rootProject.name = 'merge-service'

include 'service'
""",
spec -> spec.path(Paths.get("settings.gradle"))
)
);
}

@Test
void testRemoveEnableFeaturePreviewMethodRecipe_noChangeNoArgument() {
//language=gradle
rewriteRun(
spec -> spec.recipe(new RemoveEnableFeaturePreview("ONE_LOCKFILE_PER_PROJECT")),
Assertions.settingsGradle(
"""
pluginManagement {
repositories {
gradlePluginPortal()
}
}

enableFeaturePreview()

rootProject.name = 'merge-service'

include 'service'
""",
spec -> spec.path(Paths.get("settings.gradle"))
)
);
}

@Test
void testRemoveEnableFeaturePreviewMethodRecipe_noChangeNullArgument() {
//language=gradle
rewriteRun(
spec -> spec.recipe(new RemoveEnableFeaturePreview("ONE_LOCKFILE_PER_PROJECT")),
Assertions.settingsGradle(
"""
pluginManagement {
repositories {
gradlePluginPortal()
}
}

enableFeaturePreview(null)

rootProject.name = 'merge-service'

include 'service'
""",
spec -> spec.path(Paths.get("settings.gradle"))
)
);
}

}