Skip to content

Commit

Permalink
feat: Added option to comment out property in yaml (#4741)
Browse files Browse the repository at this point in the history
* feat: Added option to comment out property in yaml

Refs: #4740

* Update rewrite-yaml/src/main/java/org/openrewrite/yaml/CommentOutProperty.java

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Update rewrite-yaml/src/main/java/org/openrewrite/yaml/CommentOutProperty.java

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Handle nullable Boolean correctly for usage from rewrite.yml

* Drop unused default

* Prevent double negation

* Adopt `else if`

---------

Co-authored-by: Andrei Shakirin <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Tim te Beek <[email protected]>
  • Loading branch information
4 people authored Dec 5, 2024
1 parent 72793ae commit 20de532
Show file tree
Hide file tree
Showing 2 changed files with 231 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@

import lombok.EqualsAndHashCode;
import lombok.Value;
import org.openrewrite.*;
import org.jspecify.annotations.Nullable;
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;
Expand All @@ -40,6 +44,12 @@ 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)
@Nullable
Boolean commentOutProperty;

@Override
public String getDisplayName() {
return "Comment out property";
Expand All @@ -61,6 +71,7 @@ public TreeVisitor<?, ExecutionContext> getVisitor() {
private boolean nextDocNeedsNewline;
private String comment = "";
private String indentation = "";
private boolean isBlockCommentExists;

@Override
public Yaml.Document visitDocument(Yaml.Document document, ExecutionContext ctx) {
Expand All @@ -72,7 +83,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() && !Boolean.FALSE.equals(commentOutProperty)) {
String newPrefix = String.format("%s# %s%s%s",
indentation,
commentText,
Expand All @@ -89,7 +100,9 @@ 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()) {
if (Boolean.FALSE.equals(commentOutProperty)) {
return addBockCommentIfNecessary(entry, ctx);
} else if (!comment.isEmpty()) {
// add comment and return
String newPrefix = entry.getPrefix() + "# " + commentText + comment + entry.getPrefix();
comment = "";
Expand All @@ -103,20 +116,13 @@ public Yaml.Mapping.Entry visitMappingEntry(Yaml.Mapping.Entry entry, ExecutionC
String lastIndentation = indentation;
indentation = entry.getPrefix();

if (!comment.isEmpty()) {
if (!comment.isEmpty() && !Boolean.FALSE.equals(commentOutProperty)) {
String newPrefix = entry.getPrefix() + "# " + commentText + comment + entry.getPrefix();
comment = "";
return entry.withPrefix(newPrefix);
}

Deque<Yaml.Mapping.Entry> 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();
Expand All @@ -128,12 +134,50 @@ 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 (Boolean.FALSE.equals(commentOutProperty)) {
if (!entry.getPrefix().contains(commentText) && !isBlockCommentExists) {
return entry.withPrefix(entry.getPrefix() + "# " + commentText + (entry.getPrefix().contains("\n") ? entry.getPrefix() : "\n" + entry.getPrefix()));
}
} else {
doAfterVisit(new DeleteProperty(propertyKey, null, null, null).getVisitor());
}
return entry;
}

return super.visitMappingEntry(entry, ctx);
}

private 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 String calculateCurrentKeyPath() {
Deque<Yaml.Mapping.Entry> 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("."));
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,17 @@

import org.junit.jupiter.api.Test;
import org.openrewrite.DocumentExample;
import org.openrewrite.test.RecipeSpec;
import org.openrewrite.test.RewriteTest;

import static org.openrewrite.yaml.Assertions.yaml;

class CommentOutPropertyTest implements RewriteTest {

@Override
public void defaults(RecipeSpec spec) {
spec.recipe(new CommentOutProperty("management.metrics.binders.files.enabled", "some comments"));
}

@DocumentExample("comment out a map entry")
@Test
void regular() {
rewriteRun(
spec -> spec.recipe(new CommentOutProperty("foo.bar.sequence.propertyA",
"Some comments")),
spec -> spec.recipe(new CommentOutProperty("foo.bar.sequence.propertyA", "Some comments", null)),
yaml(
"""
foo:
Expand Down Expand Up @@ -63,8 +56,7 @@ void regular() {
@Test
void commentSequence() {
rewriteRun(
spec -> spec.recipe(new CommentOutProperty("foo.bar.sequence",
"Some comments")),
spec -> spec.recipe(new CommentOutProperty("foo.bar.sequence", "Some comments", null)),
yaml(
"""
foo:
Expand Down Expand Up @@ -92,8 +84,7 @@ void commentSequence() {
@Test
void commentSingleProperty() {
rewriteRun(
spec -> spec.recipe(new CommentOutProperty("with.java-version",
"Some comments")),
spec -> spec.recipe(new CommentOutProperty("with.java-version", "Some comments", null)),
yaml(
"""
with:
Expand All @@ -115,8 +106,7 @@ void commentSingleProperty() {
@Test
void commentLastPropertyWithIndent() {
rewriteRun(
spec -> spec.recipe(new CommentOutProperty("with.java-version",
"Some comments")),
spec -> spec.recipe(new CommentOutProperty("with.java-version", "Some comments", null)),
yaml(
"""
with:
Expand All @@ -136,8 +126,7 @@ void commentLastPropertyWithIndent() {
@Test
void commentLastPropertyOfFirstDocument() {
rewriteRun(
spec -> spec.recipe(new CommentOutProperty("with.java-version",
"Some comments")),
spec -> spec.recipe(new CommentOutProperty("with.java-version", "Some comments", null)),
yaml(
"""
with:
Expand All @@ -159,8 +148,7 @@ void commentLastPropertyOfFirstDocument() {
@Test
void commentLastProperty() {
rewriteRun(
spec -> spec.recipe(new CommentOutProperty("test",
"Some comments")),
spec -> spec.recipe(new CommentOutProperty("test", "Some comments", null)),
yaml(
"""
test: foo
Expand All @@ -172,4 +160,172 @@ 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
"""
)
);
}
}

0 comments on commit 20de532

Please sign in to comment.