diff --git a/rewrite-yaml/src/main/java/org/openrewrite/yaml/CommentOutProperty.java b/rewrite-yaml/src/main/java/org/openrewrite/yaml/CommentOutProperty.java index 83d5563bc10..72a73594ce0 100644 --- a/rewrite-yaml/src/main/java/org/openrewrite/yaml/CommentOutProperty.java +++ b/rewrite-yaml/src/main/java/org/openrewrite/yaml/CommentOutProperty.java @@ -15,9 +15,14 @@ */ package org.openrewrite.yaml; +import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Value; -import org.openrewrite.*; +import org.jetbrains.annotations.NotNull; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Option; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; import org.openrewrite.yaml.tree.Yaml; import java.util.ArrayDeque; @@ -28,6 +33,7 @@ import static java.util.stream.StreamSupport.stream; @Value +@AllArgsConstructor @EqualsAndHashCode(callSuper = false) public class CommentOutProperty extends Recipe { @Option(displayName = "Property key", @@ -40,6 +46,23 @@ public class CommentOutProperty extends Recipe { example = "The `foo` property is deprecated, please migrate") String commentText; + @Option(example = "true", displayName = "Comment out property", + description = "If false, property wouldn't be commented out, only comment will be added. By default, set to true", + required = false) + Boolean commentOutProperty; + + public CommentOutProperty() { + this.propertyKey = ""; + this.commentText = ""; + this.commentOutProperty = true; + } + + public CommentOutProperty(String propertyKey, String commentText) { + this.propertyKey = propertyKey; + this.commentText = commentText; + this.commentOutProperty = true; + } + @Override public String getDisplayName() { return "Comment out property"; @@ -61,6 +84,7 @@ public TreeVisitor getVisitor() { private boolean nextDocNeedsNewline; private String comment = ""; private String indentation = ""; + private boolean isBlockCommentExists; @Override public Yaml.Document visitDocument(Yaml.Document document, ExecutionContext ctx) { @@ -72,7 +96,7 @@ public Yaml.Document visitDocument(Yaml.Document document, ExecutionContext ctx) } // Add any leftover comment to the end of document - if (!comment.isEmpty()) { + if (!comment.isEmpty() && commentOutProperty) { String newPrefix = String.format("%s# %s%s%s", indentation, commentText, @@ -89,11 +113,15 @@ public Yaml.Document visitDocument(Yaml.Document document, ExecutionContext ctx) public Yaml.Sequence.Entry visitSequenceEntry(Yaml.Sequence.Entry entry, ExecutionContext ctx) { indentation = entry.getPrefix(); - if (!comment.isEmpty()) { - // add comment and return - String newPrefix = entry.getPrefix() + "# " + commentText + comment + entry.getPrefix(); - comment = ""; - return entry.withPrefix(newPrefix); + if (commentOutProperty) { + if (!comment.isEmpty()) { + // add comment and return + String newPrefix = entry.getPrefix() + "# " + commentText + comment + entry.getPrefix(); + comment = ""; + return entry.withPrefix(newPrefix); + } + } else { + return addBockCommentIfNecessary(entry, ctx); } return super.visitSequenceEntry(entry, ctx); } @@ -103,20 +131,13 @@ public Yaml.Mapping.Entry visitMappingEntry(Yaml.Mapping.Entry entry, ExecutionC String lastIndentation = indentation; indentation = entry.getPrefix(); - if (!comment.isEmpty()) { + if (!comment.isEmpty() && commentOutProperty) { String newPrefix = entry.getPrefix() + "# " + commentText + comment + entry.getPrefix(); comment = ""; return entry.withPrefix(newPrefix); } - Deque propertyEntries = getCursor().getPathAsStream() - .filter(Yaml.Mapping.Entry.class::isInstance) - .map(Yaml.Mapping.Entry.class::cast) - .collect(Collectors.toCollection(ArrayDeque::new)); - - String prop = stream(spliteratorUnknownSize(propertyEntries.descendingIterator(), 0), false) - .map(e2 -> e2.getKey().getValue()) - .collect(Collectors.joining(".")); + String prop = calculateCurrentKeyPath(); if (prop.equals(propertyKey)) { String prefix = entry.getPrefix(); @@ -128,12 +149,48 @@ public Yaml.Mapping.Entry visitMappingEntry(Yaml.Mapping.Entry entry, ExecutionC comment = lastIndentation + "#" + entry.print(getCursor().getParentTreeCursor()); } - doAfterVisit(new DeleteProperty(propertyKey, null, null, null).getVisitor()); + if (commentOutProperty) { + doAfterVisit(new DeleteProperty(propertyKey, null, null, null).getVisitor()); + } else if (!entry.getPrefix().contains(commentText) && !isBlockCommentExists) { + return entry.withPrefix(entry.getPrefix() + "# " + commentText + (entry.getPrefix().contains("\n")? entry.getPrefix() : "\n" + entry.getPrefix())); + } return entry; } return super.visitMappingEntry(entry, ctx); } + + private @NotNull Yaml.Sequence.Entry addBockCommentIfNecessary(Yaml.Sequence.Entry entry, ExecutionContext ctx) { + boolean propertyExistsInSequence = isPropertyExistsInSequence(entry); + if (propertyExistsInSequence) { + isBlockCommentExists = true; + if (!entry.getPrefix().contains(commentText)) { + return entry.withPrefix(entry.getPrefix() + "# " + commentText + (entry.getPrefix().contains("\n") ? entry.getPrefix() : "\n" + entry.getPrefix())); + } + } + return super.visitSequenceEntry(entry, ctx); + } + + private boolean isPropertyExistsInSequence(Yaml.Sequence.Entry entry) { + if (!(entry.getBlock() instanceof Yaml.Mapping)) { + return false; + } + Yaml.Mapping mapping = (Yaml.Mapping) entry.getBlock(); + String prop = calculateCurrentKeyPath(); + return mapping.getEntries().stream() + .anyMatch(e -> propertyKey.equals(prop + "." + e.getKey().getValue())); + } + + private @NotNull String calculateCurrentKeyPath() { + Deque propertyEntries = getCursor().getPathAsStream() + .filter(Yaml.Mapping.Entry.class::isInstance) + .map(Yaml.Mapping.Entry.class::cast) + .collect(Collectors.toCollection(ArrayDeque::new)); + + return stream(spliteratorUnknownSize(propertyEntries.descendingIterator(), 0), false) + .map(e2 -> e2.getKey().getValue()) + .collect(Collectors.joining(".")); + } }; } } diff --git a/rewrite-yaml/src/test/java/org/openrewrite/yaml/CommentOutPropertyTest.java b/rewrite-yaml/src/test/java/org/openrewrite/yaml/CommentOutPropertyTest.java index 57334b24734..fbc07026968 100644 --- a/rewrite-yaml/src/test/java/org/openrewrite/yaml/CommentOutPropertyTest.java +++ b/rewrite-yaml/src/test/java/org/openrewrite/yaml/CommentOutPropertyTest.java @@ -172,4 +172,178 @@ void commentLastProperty() { ) ); } + + @DocumentExample("comment out a map entry") + @Test + void sequenceKeepProperty() { + rewriteRun( + spec -> spec.recipe(new CommentOutProperty("foo.bar.sequence.propertyA", + "Some comments", false)), + yaml( + """ + foo: + bar: + sequence: + - name: name + - propertyA: fieldA + - propertyB: fieldB + scalar: value + """, + """ + foo: + bar: + sequence: + - name: name + # Some comments + - propertyA: fieldA + - propertyB: fieldB + scalar: value + """ + ) + ); + } + + @DocumentExample("comment out a map entry") + @Test + void sequenceFirstKeepProperty() { + rewriteRun( + spec -> spec.recipe(new CommentOutProperty("foo.bar.sequence.name", + "Some comments", false)), + yaml( + """ + foo: + bar: + sequence: + - name: name + - propertyA: fieldA + - propertyB: fieldB + scalar: value + """, + """ + foo: + bar: + sequence: + # Some comments + - name: name + - propertyA: fieldA + - propertyB: fieldB + scalar: value + """ + ) + ); + } + + @DocumentExample("comment out entire sequence") + @Test + void commentSequenceKeepProperty() { + rewriteRun( + spec -> spec.recipe(new CommentOutProperty("foo.bar.sequence", + "Some comments", false)), + yaml( + """ + foo: + bar: + sequence: + - name: name + - propertyA: fieldA + - propertyB: fieldB + scalar: value + """, + """ + foo: + bar: + # Some comments + sequence: + - name: name + - propertyA: fieldA + - propertyB: fieldB + scalar: value + """ + ) + ); + } + + @Test + void commentSinglePropertyKeepProperty() { + rewriteRun( + spec -> spec.recipe(new CommentOutProperty("with.java-version", + "Some comments", false)), + yaml( + """ + with: + java-cache: 'maven' + java-version: 11 + test: 'bar' + """, + """ + with: + java-cache: 'maven' + # Some comments + java-version: 11 + test: 'bar' + """ + ) + ); + } + + @Test + void commentLastPropertyWithIndentKeepProperty() { + rewriteRun( + spec -> spec.recipe(new CommentOutProperty("with.java-version", + "Some comments", false)), + yaml( + """ + with: + java-cache: 'maven' + java-version: 11 + """, + """ + with: + java-cache: 'maven' + # Some comments + java-version: 11 + """ + ) + ); + } + + @Test + void commentLastPropertyOfFirstDocumentKeepProperty() { + rewriteRun( + spec -> spec.recipe(new CommentOutProperty("with.java-version", + "Some comments", false)), + yaml( + """ + with: + java-cache: 'maven' + java-version: 11 + --- + """, + """ + with: + java-cache: 'maven' + # Some comments + java-version: 11 + --- + """ + ) + ); + } + + @Test + void commentLastPropertyKeepProperty() { + rewriteRun( + spec -> spec.recipe(new CommentOutProperty("test", + "Some comments", false)), + yaml( + """ + test: foo + """, + """ + # Some comments + test: foo + """ + ) + ); + } }