diff --git a/rewrite-properties/src/main/java/org/openrewrite/properties/AddPropertyComment.java b/rewrite-properties/src/main/java/org/openrewrite/properties/AddPropertyComment.java new file mode 100755 index 00000000000..73048521f1d --- /dev/null +++ b/rewrite-properties/src/main/java/org/openrewrite/properties/AddPropertyComment.java @@ -0,0 +1,112 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * 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 + *

+ * https://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.openrewrite.properties; + +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.jspecify.annotations.Nullable; +import org.openrewrite.*; +import org.openrewrite.internal.ListUtils; +import org.openrewrite.marker.Markers; +import org.openrewrite.properties.search.FindProperties; +import org.openrewrite.properties.tree.Properties; + +import java.util.Arrays; +import java.util.function.Function; + +import static org.openrewrite.Tree.randomId; + +@Value +@EqualsAndHashCode(callSuper = false) +public class AddPropertyComment extends Recipe { + + @Option(displayName = "Property key", + description = "The name of the property to add comment.", + example = "management.metrics.binders") + String propertyKey; + + @Option(example = "comment", displayName = "Comment", + description = "The comment to be added.") + String comment; + + @Option(example = "true", displayName = "Comment out property", + description = "If true, property will be commented out.", + required = false) + @Nullable + Boolean commentOutProperty; + + @Override + public String getDisplayName() { + return "Add comment before property key"; + } + + @Override + public String getDescription() { + return "Add a new comment before a property key if not already present, optionally commenting out the property."; + } + + @Override + public TreeVisitor getVisitor() { + PropertiesVisitor propertiesVisitor = new PropertiesVisitor() { + @Override + public Properties visitFile(Properties.File file, ExecutionContext ctx) { + Properties.File p = file.withContent(ListUtils.flatMap(file.getContent(), new Function() { + Properties.@Nullable Content previousContent = null; + + @Override + public Object apply(Properties.Content c) { + if (c instanceof Properties.Entry && + ((Properties.Entry) c).getKey().equals(propertyKey) && + !isCommentAlreadyPresent(previousContent, comment)) { + Properties.Comment commentContent = new Properties.Comment( + randomId(), + previousContent == null ? "" : "\n", + Markers.EMPTY, + Properties.Comment.Delimiter.HASH_TAG, + " " + comment.trim()); + previousContent = c; + return Arrays.asList(commentContent, c.getPrefix().contains("\n") ? + c : c.withPrefix("\n" + c.getPrefix())); + } + previousContent = c; + return c; + } + } + )); + return super.visitFile(p, ctx); + } + + @Override + public Properties visitEntry(Properties.Entry entry, ExecutionContext ctx) { + if (Boolean.TRUE.equals(commentOutProperty) && entry.getKey().equals(propertyKey)) { + return new Properties.Comment( + randomId(), + entry.getPrefix(), + entry.getMarkers(), + Properties.Comment.Delimiter.HASH_TAG, + " " + entry.printTrimmed(getCursor())); + } + return super.visitEntry(entry, ctx); + } + }; + return Preconditions.check(new FindProperties(propertyKey, false).getVisitor(), propertiesVisitor); + } + + private boolean isCommentAlreadyPresent(Properties.@Nullable Content previousContent, String comment) { + return previousContent instanceof Properties.Comment && + ((Properties.Comment) previousContent).getMessage().contains(comment.trim()); + } +} diff --git a/rewrite-properties/src/test/java/org/openrewrite/properties/AddPropertyCommentTest.java b/rewrite-properties/src/test/java/org/openrewrite/properties/AddPropertyCommentTest.java new file mode 100755 index 00000000000..05f643df5ce --- /dev/null +++ b/rewrite-properties/src/test/java/org/openrewrite/properties/AddPropertyCommentTest.java @@ -0,0 +1,189 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * 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 + *

+ * https://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.openrewrite.properties; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.properties.Assertions.properties; + +class AddPropertyCommentTest implements RewriteTest { + + @DocumentExample + @Test + void shouldAddCommentToFirstProperty() { + rewriteRun( + spec -> spec.recipe(new AddPropertyComment( + "management.metrics.enable.process.files", + "myComment", + false + )), + properties( + """ + management.metrics.enable.process.files=true + yyy=true + """, + """ + # myComment + management.metrics.enable.process.files=true + yyy=true + """ + ) + ); + } + + @Test + void shouldAddCommentToMiddleProperty() { + rewriteRun( + spec -> spec.recipe(new AddPropertyComment( + "management.metrics.enable.process.files", + "myComment", + false + )), + properties( + """ + xxx=true + management.metrics.enable.process.files=true + yyy=true + """, + """ + xxx=true + # myComment + management.metrics.enable.process.files=true + yyy=true + """ + ) + ); + } + + @Test + void shouldAcceptExistingComment() { + rewriteRun( + spec -> spec.recipe(new AddPropertyComment( + "management.metrics.enable.process.files", + "myComment", + false + )), + properties( + """ + # myComment + management.metrics.enable.process.files=true + """ + ) + ); + } + + @Test + void shouldSkipNotExistingProperty() { + rewriteRun( + spec -> spec.recipe(new AddPropertyComment( + "xxx", + "myComment", + false + )), + properties( + """ + yyy=true + """ + ) + ); + } + + @Test + void shouldCommentOutFirstProperty() { + rewriteRun( + spec -> spec.recipe(new AddPropertyComment( + "management.metrics.enable.process.files", + "myComment", + true + )), + properties( + """ + management.metrics.enable.process.files=true + yyy=true + """, + """ + # myComment + # management.metrics.enable.process.files=true + yyy=true + """ + ) + ); + } + + @Test + void shouldCommentOutMiddleProperty() { + rewriteRun( + spec -> spec.recipe(new AddPropertyComment( + "management.metrics.enable.process.files", + "myComment", + true + )), + properties( + """ + xxx=true + management.metrics.enable.process.files=true + yyy=true + """, + """ + xxx=true + # myComment + # management.metrics.enable.process.files=true + yyy=true + """ + ) + ); + } + + @Test + void shouldAcceptExistingCommentAndCommentOutProperty() { + rewriteRun( + spec -> spec.recipe(new AddPropertyComment( + "management.metrics.enable.process.files", + "myComment", + true + )), + properties( + """ + # myComment + management.metrics.enable.process.files=true + """, + """ + # myComment + # management.metrics.enable.process.files=true + """ + ) + ); + } + + @Test + void shouldASkipCommentOutProperty() { + rewriteRun( + spec -> spec.recipe(new AddPropertyComment( + "management.metrics.enable.process.files", + "myComment", + true + )), + properties( + """ + # myComment + # management.metrics.enable.process.files=true + """ + ) + ); + } +}