From 9a23747c31d4ac817cc8f0bb1aad9e68500e4490 Mon Sep 17 00:00:00 2001 From: Chase Coalwell Date: Wed, 19 Feb 2020 10:45:05 -0800 Subject: [PATCH 1/5] Emit warnings for deprecated traits --- .../linters/DeprecatedTraitsValidator.java | 50 +++++++++++++++++++ ...n.smithy.model.validation.ValidatorService | 1 + .../deprecated-traits-validator.errors | 1 + .../deprecated-traits-validator.json | 29 +++++++++++ 4 files changed, 81 insertions(+) create mode 100644 smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java create mode 100644 smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.errors create mode 100644 smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.json diff --git a/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java b/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java new file mode 100644 index 00000000000..56670fb52d6 --- /dev/null +++ b/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java @@ -0,0 +1,50 @@ +/* + * Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package software.amazon.smithy.linters; + +import static java.lang.String.format; + +import java.util.List; +import java.util.stream.Collectors; +import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.traits.DeprecatedTrait; +import software.amazon.smithy.model.traits.TraitDefinition; +import software.amazon.smithy.model.validation.AbstractValidator; +import software.amazon.smithy.model.validation.ValidationEvent; +import software.amazon.smithy.model.validation.ValidatorService; + +/** + * Emits a validation event if a model contains a trait that has been marked as deprecated. + */ +public final class DeprecatedTraitsValidator extends AbstractValidator { + + public static final class Provider extends ValidatorService.Provider { + public Provider() { + super(DeprecatedTraitsValidator.class, DeprecatedTraitsValidator::new); + } + } + + @Override + public List validate(Model model) { + + return model.shapes() + .filter(shape -> shape.hasTrait(TraitDefinition.class)) + .filter(trait -> trait.getTrait(DeprecatedTrait.class).isPresent()) + .map(deprecatedTrait -> warning(deprecatedTrait, format("The %s trait is deprecated.", + deprecatedTrait.getId().getName()))) + .collect(Collectors.toList()); + } +} diff --git a/smithy-linters/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.ValidatorService b/smithy-linters/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.ValidatorService index c15ce02fde2..09822c2035a 100644 --- a/smithy-linters/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.ValidatorService +++ b/smithy-linters/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.ValidatorService @@ -2,6 +2,7 @@ software.amazon.smithy.linters.AbbreviationNameValidator$Provider software.amazon.smithy.linters.CamelCaseValidator$Provider software.amazon.smithy.linters.DeprecatedAuthSchemesValidator$Provider software.amazon.smithy.linters.DeprecatedProtocolsValidator$Provider +software.amazon.smithy.linters.DeprecatedTraitsValidator$Provider software.amazon.smithy.linters.EmitEachSelectorValidator$Provider software.amazon.smithy.linters.EmitNoneSelectorValidator$Provider software.amazon.smithy.linters.InputOutputStructureReuseValidator$Provider diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.errors b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.errors new file mode 100644 index 00000000000..7a38b99fd58 --- /dev/null +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.errors @@ -0,0 +1 @@ +[WARNING] ns.foo#myTraitName: The myTraitName trait is deprecated. | Deprecated Traits diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.json b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.json new file mode 100644 index 00000000000..b4e89e42a06 --- /dev/null +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.json @@ -0,0 +1,29 @@ +{ + "smithy": "0.5.0", + "shapes": { + "ns.foo#MyString": { + "type": "string", + "traits": { + "ns.foo#myTraitName": { } + } + }, + "ns.foo#myTraitName": { + "type": "structure", + "members": { }, + "traits": { + "smithy.api#deprecated": { }, + "smithy.api#trait": { + "selector": "*" + } + } + } + }, + "metadata": { + "validators": [ + { + "id": "Deprecated Traits", + "name": "DeprecatedTraits" + } + ] + } +} From ea47f366e419ad8f3f9a8821923e8ac47a866ea4 Mon Sep 17 00:00:00 2001 From: Chase Coalwell Date: Wed, 19 Feb 2020 15:10:28 -0800 Subject: [PATCH 2/5] Emit on shapes with deprecated traits --- .../linters/DeprecatedTraitsValidator.java | 26 +++++++++++++++---- .../deprecated-traits-validator.errors | 3 ++- .../deprecated-traits-validator.json | 26 ++++++++++++++++--- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java b/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java index 56670fb52d6..09527926627 100644 --- a/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java +++ b/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java @@ -17,9 +17,13 @@ import static java.lang.String.format; +import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; import software.amazon.smithy.model.Model; +import software.amazon.smithy.model.shapes.Shape; +import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.model.traits.DeprecatedTrait; import software.amazon.smithy.model.traits.TraitDefinition; import software.amazon.smithy.model.validation.AbstractValidator; @@ -27,7 +31,7 @@ import software.amazon.smithy.model.validation.ValidatorService; /** - * Emits a validation event if a model contains a trait that has been marked as deprecated. + * Emits a validation event if a model contains shapes that are bound to deprecated traits. */ public final class DeprecatedTraitsValidator extends AbstractValidator { @@ -39,12 +43,24 @@ public Provider() { @Override public List validate(Model model) { - - return model.shapes() + Set deprecatedTraits = model.shapes() .filter(shape -> shape.hasTrait(TraitDefinition.class)) .filter(trait -> trait.getTrait(DeprecatedTrait.class).isPresent()) - .map(deprecatedTrait -> warning(deprecatedTrait, format("The %s trait is deprecated.", - deprecatedTrait.getId().getName()))) + .map(Shape::getId) + .collect(Collectors.toSet()); + + return model.shapes() + .filter(shape -> !shape.hasTrait(TraitDefinition.class)) + .flatMap(nonTraitShape -> validateShape(nonTraitShape, deprecatedTraits).stream()) .collect(Collectors.toList()); } + + private List validateShape(Shape shape, Set deprecatedTraits) { + List events = new ArrayList<>(); + shape.getAllTraits().keySet().stream().filter(trait -> deprecatedTraits.contains(trait.toShapeId())) + .map(boundDeprecatedTrait -> warning(shape, format("Shape `%s` uses deprecated trait: %s", + shape.getId().getName(), boundDeprecatedTrait.getName()))) + .forEach(events::add); + return events; + } } diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.errors b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.errors index 7a38b99fd58..e916323460a 100644 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.errors +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.errors @@ -1 +1,2 @@ -[WARNING] ns.foo#myTraitName: The myTraitName trait is deprecated. | Deprecated Traits +[WARNING] ns.foo#MyString: Shape `MyString` uses deprecated trait: fooTrait | DeprecatedTraits +[WARNING] ns.foo#MyString: Shape `MyString` uses deprecated trait: barTrait | DeprecatedTraits diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.json b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.json index b4e89e42a06..d05052e0cf2 100644 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.json +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.json @@ -4,10 +4,12 @@ "ns.foo#MyString": { "type": "string", "traits": { - "ns.foo#myTraitName": { } + "ns.foo#fooTrait": { }, + "ns.foo#barTrait": { }, + "ns.foo#bazTrait": { } } }, - "ns.foo#myTraitName": { + "ns.foo#fooTrait": { "type": "structure", "members": { }, "traits": { @@ -16,12 +18,30 @@ "selector": "*" } } + }, + "ns.foo#barTrait": { + "type": "structure", + "members": { }, + "traits": { + "smithy.api#deprecated": { }, + "smithy.api#trait": { + "selector": "*" + } + } + }, + "ns.foo#bazTrait": { + "type": "structure", + "members": { }, + "traits": { + "smithy.api#trait": { + "selector": "*" + } + } } }, "metadata": { "validators": [ { - "id": "Deprecated Traits", "name": "DeprecatedTraits" } ] From 204cea2f0f50bf783e1ff4a4c2ac05a3640089e7 Mon Sep 17 00:00:00 2001 From: Chase Coalwell Date: Wed, 19 Feb 2020 16:45:45 -0800 Subject: [PATCH 3/5] Include message if present --- .../linters/DeprecatedTraitsValidator.java | 22 ++++++++++++------- .../deprecated-traits-validator.errors | 4 ++-- .../deprecated-traits-validator.json | 4 +++- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java b/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java index 09527926627..d1fd88bad03 100644 --- a/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java +++ b/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java @@ -45,22 +45,28 @@ public Provider() { public List validate(Model model) { Set deprecatedTraits = model.shapes() .filter(shape -> shape.hasTrait(TraitDefinition.class)) - .filter(trait -> trait.getTrait(DeprecatedTrait.class).isPresent()) + .filter(trait -> trait.hasTrait(DeprecatedTrait.class)) .map(Shape::getId) .collect(Collectors.toSet()); return model.shapes() - .filter(shape -> !shape.hasTrait(TraitDefinition.class)) - .flatMap(nonTraitShape -> validateShape(nonTraitShape, deprecatedTraits).stream()) + .flatMap(shape -> validateShape(model, shape, deprecatedTraits).stream()) .collect(Collectors.toList()); } - private List validateShape(Shape shape, Set deprecatedTraits) { + private List validateShape(Model model, Shape shape, Set deprecatedTraits) { List events = new ArrayList<>(); - shape.getAllTraits().keySet().stream().filter(trait -> deprecatedTraits.contains(trait.toShapeId())) - .map(boundDeprecatedTrait -> warning(shape, format("Shape `%s` uses deprecated trait: %s", - shape.getId().getName(), boundDeprecatedTrait.getName()))) - .forEach(events::add); + shape.getAllTraits().forEach((shapeId, trait) -> { + if (deprecatedTraits.contains(trait.toShapeId())) { + DeprecatedTrait deprecatedTrait = model.expectShape(trait.toShapeId()).getTrait(DeprecatedTrait.class) + .get(); + String traitMessage = trait.toShapeId().toString(); + if (deprecatedTrait.getMessage().isPresent()) { + traitMessage = traitMessage.concat(", " + deprecatedTrait.getMessage().get()); + } + events.add(warning(shape, format("This shape applies a trait that is deprecated: %s", traitMessage))); + } + }); return events; } } diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.errors b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.errors index e916323460a..a206a454a04 100644 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.errors +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.errors @@ -1,2 +1,2 @@ -[WARNING] ns.foo#MyString: Shape `MyString` uses deprecated trait: fooTrait | DeprecatedTraits -[WARNING] ns.foo#MyString: Shape `MyString` uses deprecated trait: barTrait | DeprecatedTraits +[WARNING] ns.foo#MyString: This shape applies a trait that is deprecated: ns.foo#fooTrait | DeprecatedTraits +[WARNING] ns.foo#MyString: This shape applies a trait that is deprecated: ns.foo#barTrait, This trait is no longer used. | DeprecatedTraits diff --git a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.json b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.json index d05052e0cf2..3d7a1ce5079 100644 --- a/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.json +++ b/smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles/deprecated-traits-validator.json @@ -23,7 +23,9 @@ "type": "structure", "members": { }, "traits": { - "smithy.api#deprecated": { }, + "smithy.api#deprecated": { + "message": "This trait is no longer used." + }, "smithy.api#trait": { "selector": "*" } From f0cd7347f7856626787d65683da88585ffc37c0c Mon Sep 17 00:00:00 2001 From: Chase Coalwell Date: Thu, 20 Feb 2020 08:11:11 -0800 Subject: [PATCH 4/5] Refactor, return early --- .../linters/DeprecatedTraitsValidator.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java b/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java index d1fd88bad03..44fedc30056 100644 --- a/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java +++ b/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java @@ -57,15 +57,16 @@ public List validate(Model model) { private List validateShape(Model model, Shape shape, Set deprecatedTraits) { List events = new ArrayList<>(); shape.getAllTraits().forEach((shapeId, trait) -> { - if (deprecatedTraits.contains(trait.toShapeId())) { - DeprecatedTrait deprecatedTrait = model.expectShape(trait.toShapeId()).getTrait(DeprecatedTrait.class) - .get(); - String traitMessage = trait.toShapeId().toString(); - if (deprecatedTrait.getMessage().isPresent()) { - traitMessage = traitMessage.concat(", " + deprecatedTrait.getMessage().get()); - } - events.add(warning(shape, format("This shape applies a trait that is deprecated: %s", traitMessage))); + if (!deprecatedTraits.contains(trait.toShapeId())) { + return; } + DeprecatedTrait deprecatedTrait = model.expectShape(trait.toShapeId()).expectTrait(DeprecatedTrait.class); + String traitMessage = trait.toShapeId().toString(); + if (deprecatedTrait.getMessage().isPresent()) { + traitMessage = traitMessage.concat(", " + deprecatedTrait.getMessage().get()); + } + events.add(warning(shape, trait, format("This shape applies a trait that is deprecated: %s", + traitMessage))); }); return events; } From 23110bcb368b98e5fee0d2fecff9110133a611b2 Mon Sep 17 00:00:00 2001 From: Chase Coalwell Date: Thu, 20 Feb 2020 10:28:54 -0800 Subject: [PATCH 5/5] Move to model validation --- ...azon.smithy.model.validation.ValidatorService | 1 - .../validators}/DeprecatedTraitsValidator.java | 16 +++------------- ...ware.amazon.smithy.model.validation.Validator | 1 + .../deprecated-traits-validator.errors | 0 .../validators}/deprecated-traits-validator.json | 7 ------- 5 files changed, 4 insertions(+), 21 deletions(-) rename {smithy-linters/src/main/java/software/amazon/smithy/linters => smithy-model/src/main/java/software/amazon/smithy/model/validation/validators}/DeprecatedTraitsValidator.java (80%) rename {smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles => smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators}/deprecated-traits-validator.errors (100%) rename {smithy-linters/src/test/resources/software/amazon/smithy/linters/errorfiles => smithy-model/src/test/resources/software/amazon/smithy/model/errorfiles/validators}/deprecated-traits-validator.json (89%) diff --git a/smithy-linters/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.ValidatorService b/smithy-linters/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.ValidatorService index 09822c2035a..c15ce02fde2 100644 --- a/smithy-linters/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.ValidatorService +++ b/smithy-linters/src/main/resources/META-INF/services/software.amazon.smithy.model.validation.ValidatorService @@ -2,7 +2,6 @@ software.amazon.smithy.linters.AbbreviationNameValidator$Provider software.amazon.smithy.linters.CamelCaseValidator$Provider software.amazon.smithy.linters.DeprecatedAuthSchemesValidator$Provider software.amazon.smithy.linters.DeprecatedProtocolsValidator$Provider -software.amazon.smithy.linters.DeprecatedTraitsValidator$Provider software.amazon.smithy.linters.EmitEachSelectorValidator$Provider software.amazon.smithy.linters.EmitNoneSelectorValidator$Provider software.amazon.smithy.linters.InputOutputStructureReuseValidator$Provider diff --git a/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/DeprecatedTraitsValidator.java similarity index 80% rename from smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java rename to smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/DeprecatedTraitsValidator.java index 44fedc30056..3961cb60717 100644 --- a/smithy-linters/src/main/java/software/amazon/smithy/linters/DeprecatedTraitsValidator.java +++ b/smithy-model/src/main/java/software/amazon/smithy/model/validation/validators/DeprecatedTraitsValidator.java @@ -13,7 +13,7 @@ * permissions and limitations under the License. */ -package software.amazon.smithy.linters; +package software.amazon.smithy.model.validation.validators; import static java.lang.String.format; @@ -25,26 +25,16 @@ import software.amazon.smithy.model.shapes.Shape; import software.amazon.smithy.model.shapes.ShapeId; import software.amazon.smithy.model.traits.DeprecatedTrait; -import software.amazon.smithy.model.traits.TraitDefinition; import software.amazon.smithy.model.validation.AbstractValidator; import software.amazon.smithy.model.validation.ValidationEvent; -import software.amazon.smithy.model.validation.ValidatorService; /** * Emits a validation event if a model contains shapes that are bound to deprecated traits. */ public final class DeprecatedTraitsValidator extends AbstractValidator { - - public static final class Provider extends ValidatorService.Provider { - public Provider() { - super(DeprecatedTraitsValidator.class, DeprecatedTraitsValidator::new); - } - } - @Override public List validate(Model model) { - Set deprecatedTraits = model.shapes() - .filter(shape -> shape.hasTrait(TraitDefinition.class)) + Set deprecatedTraits = model.getTraitShapes().stream() .filter(trait -> trait.hasTrait(DeprecatedTrait.class)) .map(Shape::getId) .collect(Collectors.toSet()); @@ -63,7 +53,7 @@ private List validateShape(Model model, Shape shape, Set