Skip to content

Commit f8a8c04

Browse files
Extending YAML DeleteProperty to also allow glob patterns. (#6639)
1 parent bbad994 commit f8a8c04

3 files changed

Lines changed: 225 additions & 87 deletions

File tree

rewrite-yaml/src/main/java/org/openrewrite/yaml/DeleteProperty.java

Lines changed: 60 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.openrewrite.*;
2323
import org.openrewrite.internal.ListUtils;
2424
import org.openrewrite.internal.NameCaseConvention;
25+
import org.openrewrite.internal.NameCaseConvention.Compiled;
2526
import org.openrewrite.marker.Marker;
2627
import org.openrewrite.yaml.tree.Yaml;
2728

@@ -37,8 +38,8 @@
3738
@EqualsAndHashCode(callSuper = false)
3839
public class DeleteProperty extends Recipe {
3940
@Option(displayName = "Property key",
40-
description = "The key to be deleted.",
41-
example = "management.metrics.binders.files.enabled")
41+
description = "The key to be deleted. Supports glob patterns.",
42+
example = "management.metrics.binders.files.*")
4243
String propertyKey;
4344

4445
@Deprecated
@@ -71,11 +72,14 @@ public class DeleteProperty extends Recipe {
7172

7273
@Override
7374
public TreeVisitor<?, ExecutionContext> getVisitor() {
75+
Compiled keyMatcher = (!Boolean.FALSE.equals(relaxedBinding) ?
76+
NameCaseConvention.LOWER_CAMEL :
77+
NameCaseConvention.EXACT).compile(propertyKey);
78+
7479
return Preconditions.check(new FindSourceFiles(filePattern), new YamlIsoVisitor<ExecutionContext>() {
7580

7681
@Override
7782
public Yaml.Documents visitDocuments(Yaml.Documents documents, ExecutionContext ctx) {
78-
// TODO: Update DeleteProperty to support documents having Anchor / Alias Pairs
7983
if (documents != new ReplaceAliasWithAnchorValueVisitor<ExecutionContext>().visit(documents, ctx)) {
8084
return documents;
8185
}
@@ -95,94 +99,81 @@ public Yaml.Mapping.Entry visitMappingEntry(Yaml.Mapping.Entry entry, ExecutionC
9599
.map(e2 -> e2.getKey().getValue())
96100
.collect(joining("."));
97101

98-
if (!Boolean.FALSE.equals(relaxedBinding) ? NameCaseConvention.equalsRelaxedBinding(prop, propertyKey) : prop.equals(propertyKey)) {
99-
doAfterVisit(new DeletePropertyVisitor<>(entry));
102+
if (keyMatcher.matchesGlob(prop)) {
103+
e = ToBeRemoved.withMarker(e);
100104
if (Boolean.TRUE.equals(coalesce)) {
101105
maybeCoalesceProperties();
102106
}
103107
}
104108

105109
return e;
106110
}
107-
});
108-
}
109-
110-
private static class DeletePropertyVisitor<P> extends YamlVisitor<P> {
111-
private final Yaml.Mapping.Entry scope;
112111

113-
private DeletePropertyVisitor(Yaml.Mapping.Entry scope) {
114-
this.scope = scope;
115-
}
112+
@Override
113+
public Yaml.Sequence visitSequence(Yaml.Sequence sequence, ExecutionContext ctx) {
114+
Yaml.Sequence s = super.visitSequence(sequence, ctx);
115+
List<Yaml.Sequence.Entry> entries = s.getEntries();
116+
if (entries.isEmpty()) {
117+
return s;
118+
}
116119

117-
@Override
118-
public Yaml visitSequence(Yaml.Sequence sequence, P p) {
119-
sequence = (Yaml.Sequence) super.visitSequence(sequence, p);
120-
List<Yaml.Sequence.Entry> entries = sequence.getEntries();
121-
if (entries.isEmpty()) {
122-
return sequence;
120+
entries = ListUtils.map(entries, entry -> ToBeRemoved.hasMarker(entry) ? null : entry);
121+
return entries.isEmpty() ? ToBeRemoved.withMarker(s) : s.withEntries(entries);
123122
}
124123

125-
entries = ListUtils.map(entries, entry -> ToBeRemoved.hasMarker(entry) ? null : entry);
126-
return entries.isEmpty() ? ToBeRemoved.withMarker(sequence) : sequence.withEntries(entries);
127-
}
128-
129-
@Override
130-
public Yaml visitSequenceEntry(Yaml.Sequence.Entry entry, P p) {
131-
entry = (Yaml.Sequence.Entry) super.visitSequenceEntry(entry, p);
132-
if (entry.getBlock() instanceof Yaml.Mapping) {
133-
Yaml.Mapping m = (Yaml.Mapping) entry.getBlock();
134-
if (ToBeRemoved.hasMarker(m)) {
135-
return ToBeRemoved.withMarker(entry);
124+
@Override
125+
public Yaml.Sequence.Entry visitSequenceEntry(Yaml.Sequence.Entry entry, ExecutionContext ctx) {
126+
Yaml.Sequence.Entry e = super.visitSequenceEntry(entry, ctx);
127+
if (e.getBlock() instanceof Yaml.Mapping) {
128+
Yaml.Mapping m = (Yaml.Mapping) e.getBlock();
129+
if (ToBeRemoved.hasMarker(m)) {
130+
return ToBeRemoved.withMarker(e);
131+
}
136132
}
133+
return e;
137134
}
138-
return entry;
139-
}
140-
141-
@Override
142-
public Yaml visitMapping(Yaml.Mapping mapping, P p) {
143-
Yaml.Mapping m = (Yaml.Mapping) super.visitMapping(mapping, p);
144-
145-
boolean changed = false;
146-
List<Yaml.Mapping.Entry> entries = new ArrayList<>();
147-
String deletedPrefix = null;
148-
int count = 0;
149-
for (Yaml.Mapping.Entry entry : m.getEntries()) {
150-
if (ToBeRemoved.hasMarker(entry.getValue())) {
151-
changed = true;
152-
continue;
153-
}
154135

155-
if (entry == scope || (entry.getValue() instanceof Yaml.Mapping && ((Yaml.Mapping) entry.getValue()).getEntries().isEmpty())) {
156-
deletedPrefix = entry.getPrefix();
157-
changed = true;
158-
} else {
159-
if (deletedPrefix != null) {
160-
if (count == 0 && containsOnlyWhitespace(entry.getPrefix())) {
161-
// do this only if the entry will be the first element
162-
entry = entry.withPrefix(deletedPrefix);
136+
@Override
137+
public Yaml.Mapping visitMapping(Yaml.Mapping mapping, ExecutionContext ctx) {
138+
Yaml.Mapping m = super.visitMapping(mapping, ctx);
139+
140+
boolean changed = false;
141+
List<Yaml.Mapping.Entry> entries = new ArrayList<>();
142+
String firstDeletedPrefix = null;
143+
for (Yaml.Mapping.Entry entry : m.getEntries()) {
144+
if (ToBeRemoved.hasMarker(entry.getValue()) ||
145+
ToBeRemoved.hasMarker(entry) ||
146+
(entry.getValue() instanceof Yaml.Mapping && ((Yaml.Mapping) entry.getValue()).getEntries().isEmpty())) {
147+
// Entry is being deleted - capture prefix from the first deleted entry before any kept entries
148+
if (entries.isEmpty() && firstDeletedPrefix == null) {
149+
firstDeletedPrefix = entry.getPrefix();
150+
}
151+
changed = true;
152+
} else {
153+
if (entries.isEmpty() && firstDeletedPrefix != null && containsOnlyWhitespace(entry.getPrefix())) {
154+
// This is the first kept entry and there were deleted entries before it
155+
entry = entry.withPrefix(firstDeletedPrefix);
163156
}
164-
deletedPrefix = null;
157+
entries.add(entry);
165158
}
166-
entries.add(entry);
167-
count++;
168159
}
169-
}
170160

171-
if (changed) {
172-
m = m.withEntries(entries);
173-
if (entries.isEmpty()) {
174-
m = ToBeRemoved.withMarker(m);
175-
}
161+
if (changed) {
162+
m = m.withEntries(entries);
163+
if (entries.isEmpty()) {
164+
m = ToBeRemoved.withMarker(m);
165+
}
176166

177-
if (getCursor().getParentOrThrow().getValue() instanceof Yaml.Document) {
178-
Yaml.Document document = getCursor().getParentOrThrow().getValue();
179-
if (!document.isExplicit()) {
180-
m = m.withEntries(m.getEntries());
167+
if (getCursor().getParentOrThrow().getValue() instanceof Yaml.Document) {
168+
Yaml.Document document = getCursor().getParentOrThrow().getValue();
169+
if (!document.isExplicit()) {
170+
m = m.withEntries(m.getEntries());
171+
}
181172
}
182173
}
174+
return m;
183175
}
184-
return m;
185-
}
176+
});
186177
}
187178

188179
private static boolean containsOnlyWhitespace(@Nullable String str) {

0 commit comments

Comments
 (0)