Skip to content

Commit ef7f14a

Browse files
Added recipe to delete toml table by Identifier (#6127)
* Delete the toml table * Add nullable annotation, mostly to trigger new build * comments --------- Co-authored-by: Tim te Beek <tim@moderne.io>
1 parent 186c617 commit ef7f14a

2 files changed

Lines changed: 299 additions & 0 deletions

File tree

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.toml;
17+
18+
import lombok.EqualsAndHashCode;
19+
import lombok.Value;
20+
import org.jspecify.annotations.Nullable;
21+
import org.openrewrite.ExecutionContext;
22+
import org.openrewrite.Option;
23+
import org.openrewrite.Recipe;
24+
import org.openrewrite.TreeVisitor;
25+
import org.openrewrite.internal.ListUtils;
26+
import org.openrewrite.toml.tree.Toml;
27+
import org.openrewrite.toml.tree.TomlValue;
28+
29+
@Value
30+
@EqualsAndHashCode(callSuper = false)
31+
public class DeleteTable extends Recipe {
32+
@Option(displayName = "Table name",
33+
description = "The name of the TOML table to delete.",
34+
example = "dependencies")
35+
String tableName;
36+
37+
@Override
38+
public String getDisplayName() {
39+
return "Delete TOML table";
40+
}
41+
42+
@Override
43+
public String getDescription() {
44+
return "Delete a TOML table.";
45+
}
46+
47+
@Override
48+
public TreeVisitor<?, ExecutionContext> getVisitor() {
49+
return new TomlVisitor<ExecutionContext>() {
50+
@Override
51+
public Toml visitDocument(Toml.Document document, ExecutionContext ctx) {
52+
Toml.Document doc = (Toml.Document) super.visitDocument(document, ctx);
53+
if (doc != document) {
54+
doc = doc.withValues(ListUtils.mapFirst(doc.getValues(), first -> {
55+
TomlValue originalFirst = document.getValues().get(0);
56+
if (first != originalFirst) {
57+
return first.withPrefix(originalFirst.getPrefix());
58+
}
59+
return first;
60+
}));
61+
}
62+
return doc;
63+
}
64+
65+
@Override
66+
public @Nullable Toml visitTable(Toml.Table table, ExecutionContext ctx) {
67+
Toml.Table t = (Toml.Table) super.visitTable(table, ctx);
68+
if (t.getName() != null && tableName.equals(t.getName().getName())) {
69+
return null;
70+
}
71+
return t;
72+
}
73+
};
74+
}
75+
}
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
* <p>
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
* <p>
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
* <p>
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.openrewrite.toml;
17+
18+
import org.junit.jupiter.api.Test;
19+
import org.openrewrite.DocumentExample;
20+
import org.openrewrite.test.RewriteTest;
21+
22+
import static org.openrewrite.toml.Assertions.toml;
23+
24+
class DeleteTableTest implements RewriteTest {
25+
26+
@DocumentExample
27+
@Test
28+
void deleteArrayOfTables() {
29+
rewriteRun(
30+
spec -> spec.recipe(new DeleteTable(
31+
"package.contributors"
32+
)),
33+
toml(
34+
"""
35+
[package]
36+
name = "example-package"
37+
version = "1.0.0"
38+
authors = ["Alice Smith"]
39+
40+
[[package.contributors]]
41+
name = "Bob Johnson"
42+
email = "bob@example.com"
43+
44+
[[package.contributors]]
45+
name = "Carol White"
46+
email = "carol@example.com"
47+
""",
48+
"""
49+
[package]
50+
name = "example-package"
51+
version = "1.0.0"
52+
authors = ["Alice Smith"]
53+
"""
54+
)
55+
);
56+
}
57+
58+
@Test
59+
void deleteTopLevelTable() {
60+
rewriteRun(
61+
spec -> spec.recipe(new DeleteTable(
62+
"dependencies"
63+
)),
64+
toml(
65+
"""
66+
[package]
67+
name = "my-project"
68+
version = "1.0.0"
69+
70+
[dependencies]
71+
library-a = "^2.0.0"
72+
library-b = "^1.5.0"
73+
74+
[dev-dependencies]
75+
test-tool = "^3.0.0"
76+
""",
77+
"""
78+
[package]
79+
name = "my-project"
80+
version = "1.0.0"
81+
82+
[dev-dependencies]
83+
test-tool = "^3.0.0"
84+
"""
85+
)
86+
);
87+
}
88+
89+
@Test
90+
void deleteNestedTable() {
91+
rewriteRun(
92+
spec -> spec.recipe(new DeleteTable(
93+
"tool.formatter.options"
94+
)),
95+
toml(
96+
"""
97+
[tool.linter]
98+
name = "test-project"
99+
version = "0.1.0"
100+
101+
[tool.formatter.options]
102+
max-line-length = 100
103+
indent-size = 4
104+
105+
[tool.builder]
106+
target = "dist"
107+
""",
108+
"""
109+
[tool.linter]
110+
name = "test-project"
111+
version = "0.1.0"
112+
113+
[tool.builder]
114+
target = "dist"
115+
"""
116+
)
117+
);
118+
}
119+
120+
@Test
121+
void deleteMiddleTable() {
122+
rewriteRun(
123+
spec -> spec.recipe(new DeleteTable(
124+
"database"
125+
)),
126+
toml(
127+
"""
128+
[server]
129+
host = "localhost"
130+
port = 8080
131+
132+
[database]
133+
host = "db.example.com"
134+
port = 5432
135+
name = "mydb"
136+
137+
[logging]
138+
level = "info"
139+
""",
140+
"""
141+
[server]
142+
host = "localhost"
143+
port = 8080
144+
145+
[logging]
146+
level = "info"
147+
"""
148+
)
149+
);
150+
}
151+
152+
@Test
153+
void deleteFirstTable() {
154+
rewriteRun(
155+
spec -> spec.recipe(new DeleteTable(
156+
"metadata"
157+
)),
158+
toml(
159+
"""
160+
[metadata]
161+
created = "2025-01-01"
162+
163+
[application]
164+
name = "myapp"
165+
version = "2.0.0"
166+
""",
167+
"""
168+
[application]
169+
name = "myapp"
170+
version = "2.0.0"
171+
"""
172+
)
173+
);
174+
}
175+
176+
@Test
177+
void deleteLastTable() {
178+
rewriteRun(
179+
spec -> spec.recipe(new DeleteTable(
180+
"extras"
181+
)),
182+
toml(
183+
"""
184+
[package]
185+
name = "sample"
186+
187+
[dependencies]
188+
core-lib = "^1.0.0"
189+
190+
[extras]
191+
optional = ["extra-feature"]
192+
""",
193+
"""
194+
[package]
195+
name = "sample"
196+
197+
[dependencies]
198+
core-lib = "^1.0.0"
199+
"""
200+
)
201+
);
202+
}
203+
204+
@Test
205+
void doNotDeleteUnmatchedTables() {
206+
rewriteRun(
207+
spec -> spec.recipe(new DeleteTable(
208+
"tool.analyzer"
209+
)),
210+
toml(
211+
"""
212+
[tool.linter]
213+
name = "project"
214+
215+
[tool.formatter.options]
216+
max-width = 80
217+
218+
[tool.builder]
219+
target = "output"
220+
"""
221+
)
222+
);
223+
}
224+
}

0 commit comments

Comments
 (0)