Skip to content

Commit 1dc08e0

Browse files
committed
Fix filterSuppressions handling of members
`builder.addShape` does not allow adding member shapes directly. Instead use ReplaceShapes which handles replacing member shapes too.
1 parent 6ace718 commit 1dc08e0

File tree

11 files changed

+175
-26
lines changed

11 files changed

+175
-26
lines changed

smithy-build/src/main/java/software/amazon/smithy/build/transforms/FilterSuppressions.java

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import software.amazon.smithy.model.node.ObjectNode;
3333
import software.amazon.smithy.model.shapes.Shape;
3434
import software.amazon.smithy.model.traits.SuppressTrait;
35+
import software.amazon.smithy.model.transform.ModelTransformer;
3536
import software.amazon.smithy.model.validation.Severity;
3637
import software.amazon.smithy.model.validation.ValidationEvent;
3738
import software.amazon.smithy.model.validation.suppressions.Suppression;
@@ -217,15 +218,14 @@ protected Model transformWithConfig(TransformContext context, Config config) {
217218
}
218219

219220
Model model = context.getModel();
220-
Model.Builder builder = model.toBuilder();
221221
Set<String> removedValidators = getRemovedValidators(context, config);
222222
List<ValidationEvent> suppressedEvents = context.getOriginalModelValidationEvents().stream()
223223
.filter(event -> event.getSeverity() == Severity.SUPPRESSED)
224224
.filter(event -> !removedValidators.contains(event.getId()))
225225
.collect(Collectors.toList());
226-
filterSuppressionTraits(model, builder, config, suppressedEvents);
227-
filterMetadata(model, builder, config, suppressedEvents, removedValidators);
228-
return builder.build();
226+
model = filterSuppressionTraits(model, config, suppressedEvents, context.getTransformer());
227+
model = filterMetadata(model, config, suppressedEvents, removedValidators);
228+
return model;
229229
}
230230

231231
private Set<String> getRemovedValidators(TransformContext context, Config config) {
@@ -271,12 +271,14 @@ private Set<String> getValidatorNames(Model model) {
271271
return metadataSuppressions;
272272
}
273273

274-
private void filterSuppressionTraits(
274+
private Model filterSuppressionTraits(
275275
Model model,
276-
Model.Builder builder,
277276
Config config,
278-
List<ValidationEvent> suppressedEvents
277+
List<ValidationEvent> suppressedEvents,
278+
ModelTransformer transformer
279279
) {
280+
281+
List<Shape> replacementShapes = new ArrayList<>();
280282
// First filter and '@suppress' traits that didn't suppress anything.
281283
for (Shape shape : model.getShapesWithTrait(SuppressTrait.class)) {
282284
SuppressTrait trait = shape.expectTrait(SuppressTrait.class);
@@ -293,25 +295,24 @@ private void filterSuppressionTraits(
293295
}
294296

295297
if (allowed.isEmpty()) {
296-
builder.addShape(Shape.shapeToBuilder(shape).removeTrait(SuppressTrait.ID).build());
298+
replacementShapes.add(Shape.shapeToBuilder(shape).removeTrait(SuppressTrait.ID).build());
297299
} else if (!allowed.equals(trait.getValues())) {
298300
trait = trait.toBuilder().values(allowed).build();
299-
builder.addShape(Shape.shapeToBuilder(shape).addTrait(trait).build());
301+
replacementShapes.add(Shape.shapeToBuilder(shape).addTrait(trait).build());
300302
}
301303
}
304+
return transformer.replaceShapes(model, replacementShapes);
302305
}
303306

304-
private void filterMetadata(
307+
private Model filterMetadata(
305308
Model model,
306-
Model.Builder builder,
307309
Config config,
308310
List<ValidationEvent> suppressedEvents,
309311
Set<String> removedValidators
310312
) {
311313
// Next remove metadata suppressions that didn't suppress anything.
312314
ArrayNode suppressionsNode = model.getMetadata()
313315
.getOrDefault("suppressions", Node.arrayNode()).expectArrayNode();
314-
builder.removeMetadataProperty("suppressions");
315316
List<ObjectNode> updatedMetadataSuppressions = new ArrayList<>();
316317

317318
for (Node suppressionNode : suppressionsNode) {
@@ -339,9 +340,16 @@ && isAllowed(namespace, config.getNamespaceAllowList(), config.getNamespaceDenyL
339340
}
340341
}
341342

343+
ArrayNode updatedMetadataSuppressionsNode = Node.fromNodes(updatedMetadataSuppressions);
344+
if (suppressionsNode.equals(updatedMetadataSuppressionsNode)) {
345+
return model;
346+
}
347+
Model.Builder builder = model.toBuilder();
348+
builder.removeMetadataProperty("suppressions");
342349
if (!updatedMetadataSuppressions.isEmpty()) {
343-
builder.putMetadataProperty("suppressions", Node.fromNodes(updatedMetadataSuppressions));
350+
builder.putMetadataProperty("suppressions", updatedMetadataSuppressionsNode);
344351
}
352+
return builder.build();
345353
}
346354

347355
private boolean isAllowed(String value, Collection<String> allowList, Collection<String> denyList) {

smithy-build/src/test/java/software/amazon/smithy/build/transforms/FilterSuppressionsTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ public void cannotSetBothNamespaceAllowAndDenyList() {
6464
"namespaces,namespaceDenyList",
6565
"namespaces,filterWithTopLevelImports",
6666
"namespaces,filterWithProjectionImports",
67-
"namespaces,detectsValidatorRemoval"
67+
"namespaces,detectsValidatorRemoval",
68+
"namespaces,unchanged",
69+
"noSuppressions,removeUnused"
6870
})
6971
public void runTransformTests(String modelFile, String testName) throws Exception {
7072
Model model = Model.assembler()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"version": "1.0",
3+
"projections": {
4+
"foo": {
5+
"transforms": [
6+
{
7+
"name": "filterSuppressions",
8+
"args": {
9+
"namespaceDenyList": ["smithy.nonexistent"]
10+
}
11+
}
12+
]
13+
}
14+
}
15+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
$version: "1.0"
2+
3+
metadata validators = [
4+
{
5+
name: "EmitEachSelector",
6+
id: "Test",
7+
severity: "WARNING",
8+
configuration: {
9+
selector: ":is([id=smithy.example#Foo], [id=smithy.example#Baz])"
10+
}
11+
}
12+
]
13+
14+
metadata suppressions = [
15+
{
16+
id: "Test",
17+
reason: "reason...",
18+
namespace: "smithy.example"
19+
},
20+
{
21+
id: "Lorem",
22+
namespace: "smithy.foo"
23+
},
24+
{
25+
id: "Test",
26+
namespace: "smithy.example.nested",
27+
reason: "reason..."
28+
},
29+
{
30+
id: "Ipsum",
31+
namespace: "*"
32+
}
33+
]
34+
35+
namespace smithy.example
36+
37+
structure Foo {}
38+
39+
structure Baz {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"version": "1.0",
3+
"projections": {
4+
"foo": {
5+
"transforms": [
6+
{
7+
"name": "filterSuppressions",
8+
"args": {
9+
"removeUnused": true
10+
}
11+
}
12+
]
13+
}
14+
}
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
$version: "1.0"
2+
3+
metadata validators = [
4+
{
5+
name: "EmitEachSelector",
6+
id: "Test",
7+
severity: "WARNING",
8+
configuration: {
9+
selector: ":not([id='smithy.example#NoMatches'])"
10+
}
11+
}
12+
]
13+
14+
metadata suppressions = []
15+
16+
namespace smithy.example
17+
18+
structure Foo {
19+
foo: String
20+
}
21+
22+
structure Baz {
23+
baz: String
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
$version: "1.0"
2+
3+
metadata validators = [
4+
{
5+
name: "EmitEachSelector",
6+
id: "Test",
7+
severity: "WARNING",
8+
configuration: {
9+
selector: ":not([id='smithy.example#NoMatches'])"
10+
}
11+
}
12+
]
13+
14+
metadata suppressions = []
15+
16+
namespace smithy.example
17+
18+
structure Foo {
19+
foo: String
20+
}
21+
22+
structure Baz {
23+
baz: String
24+
}

smithy-build/src/test/resources/software/amazon/smithy/build/transforms/filtersuppressions/traits.eventIdAllowList.smithy

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ metadata validators = [
66
id: "Test",
77
severity: "WARNING",
88
configuration: {
9-
selector: ":is([id=smithy.example#Foo], [id=smithy.example#Baz])"
9+
selector: ":not([id='smithy.example#NoMatches'])"
1010
}
1111
}
1212
]
@@ -17,6 +17,11 @@ namespace smithy.example
1717
string NoMatches
1818

1919
@suppress(["Test"])
20-
structure Foo {}
20+
structure Foo {
21+
@suppress(["Test"])
22+
foo: String
23+
}
2124

22-
structure Baz {}
25+
structure Baz {
26+
baz:String
27+
}

smithy-build/src/test/resources/software/amazon/smithy/build/transforms/filtersuppressions/traits.eventIdDenyList.smithy

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ metadata validators = [
66
id: "Test",
77
severity: "WARNING",
88
configuration: {
9-
selector: ":is([id=smithy.example#Foo], [id=smithy.example#Baz])"
9+
selector: ":not([id='smithy.example#NoMatches'])"
1010
}
1111
}
1212
]
@@ -17,7 +17,13 @@ namespace smithy.example
1717
string NoMatches
1818

1919
@suppress(["NeverUsed"])
20-
structure Foo {}
20+
structure Foo {
21+
@suppress(["NeverUsed"])
22+
foo: String
23+
}
2124

2225
@suppress(["NeverUsed"])
23-
structure Baz {}
26+
structure Baz {
27+
@suppress(["NeverUsed"])
28+
baz:String
29+
}

smithy-build/src/test/resources/software/amazon/smithy/build/transforms/filtersuppressions/traits.removeUnused.smithy

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ metadata validators = [
66
id: "Test",
77
severity: "WARNING",
88
configuration: {
9-
selector: ":is([id=smithy.example#Foo], [id=smithy.example#Baz])"
9+
selector: ":not([id='smithy.example#NoMatches'])"
1010
}
1111
}
1212
]
@@ -16,6 +16,11 @@ namespace smithy.example
1616
string NoMatches
1717

1818
@suppress(["Test"])
19-
structure Foo {}
19+
structure Foo {
20+
@suppress(["Test"])
21+
foo: String
22+
}
2023

21-
structure Baz {}
24+
structure Baz {
25+
baz: String
26+
}

0 commit comments

Comments
 (0)