Skip to content

Commit

Permalink
Migrate UnreferencedShapeValidator (smithy-lang#319)
Browse files Browse the repository at this point in the history
* Migrate linter to validator

* Add references on test models

* Update linters test models
  • Loading branch information
Chase Coalwell authored and JordonPhillips committed Apr 22, 2020
1 parent d3b8f12 commit 3705c7e
Show file tree
Hide file tree
Showing 23 changed files with 178 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,6 @@
"smithy.api#private": true
}
},
"aws.api#StringList": {
"type": "list",
"member": {
"target": "smithy.api#String"
},
"traits": {
"smithy.api#private": true
}
},
"aws.api#clientDiscoveredEndpoint": {
"type": "structure",
"members": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
"ns.foo#Service1": {
"type": "service",
"version": "2018-03-17",
"operations": [
{
"target": "ns.foo#Operation"
}
],
"traits": {
"aws.api#service": {
"sdkId": "Some Value"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,3 @@ software.amazon.smithy.linters.ReservedWordsValidator$Provider
software.amazon.smithy.linters.ShouldHaveUsedTimestampValidator$Provider
software.amazon.smithy.linters.StandardOperationVerbValidator$Provider
software.amazon.smithy.linters.StutteredShapeNameValidator$Provider
software.amazon.smithy.linters.UnreferencedShapeValidator$Provider
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@
"members": {
"bar": {
"target": "ns.foo#String"
},
"long": {
"target": "ns.foo#Long"
},
"bool": {
"target": "ns.foo#Boolean"
},
"list": {
"target": "ns.foo#List"
},
"timestamp": {
"target": "ns.foo#UtcTimestamp"
},
"blob": {
"target": "ns.foo#Blob"
}
}
},
Expand Down Expand Up @@ -50,6 +65,9 @@
"operations": [
{
"target": "ns.foo#OperationA"
},
{
"target": "ns.foo#_OperationBaz"
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,10 @@
[ERROR] -: Error creating `EmitEachSelector` validator: Deserialization error at (/selector): unable to create software.amazon.smithy.model.selector.Selector from "service -[foo]-> *": Unable to deserialize Node using fromNode method: Syntax error at character 10 of 18, near `foo]-> *`: Expected one of the following tokens: `bound`, `collectionOperation`, `create`, `delete`, `error`, `identifier`, `input`, `instanceOperation`, `list`, `member`, `operation`, `output`, `put`, `read`, `resource`, `update`; expression `service -[foo]-> *` | Model
[ERROR] -: Error creating `EmitEachSelector` validator: Deserialization error at (/selector): unable to create software.amazon.smithy.model.selector.Selector from "[foo]": Unable to deserialize Node using fromNode method: Syntax error at character 1 of 5, near `foo]`: Expected one of the following tokens: `id`, `id|member`, `id|name`, `id|namespace`, `service|version`, `trait|`; expression `[foo]` | Model
[ERROR] -: Error creating `EmitEachSelector` validator: Deserialization error at (/selector): unable to create software.amazon.smithy.model.selector.Selector from "[foo=baz]": Unable to deserialize Node using fromNode method: Syntax error at character 1 of 9, near `foo=baz]`: Expected one of the following tokens: `id`, `id|member`, `id|name`, `id|namespace`, `service|version`, `trait|`; expression `[foo=baz]` | Model
[NOTE] ns.foo#Long: The long shape is not connected to from any service shape. | UnreferencedShape
[NOTE] ns.foo#Float: The float shape is not connected to from any service shape. | UnreferencedShape
[NOTE] ns.foo#Boolean: The boolean shape is not connected to from any service shape. | UnreferencedShape
[NOTE] ns.foo#Blob: The blob shape is not connected to from any service shape. | UnreferencedShape
[NOTE] ns.foo#List: The list shape is not connected to from any service shape. | UnreferencedShape
[NOTE] ns.foo#UtcTimestamp: The timestamp shape is not connected to from any service shape. | UnreferencedShape
[NOTE] other.ns#String: The string shape is not connected to from any service shape. | UnreferencedShape
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@
"ns.foo#CInputOutput": {
"type": "structure"
},
"ns.foo#COutputOutput": {
"type": "structure"
},
"ns.foo#D": {
"type": "operation",
"input": {
Expand All @@ -88,9 +85,6 @@
"ns.foo#DInputOutput": {
"type": "structure"
},
"ns.foo#DOutputOutput": {
"type": "structure"
},
"ns.foo#E": {
"type": "operation",
"output": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,21 @@
"shapes": {
"ns.foo#MyService": {
"type": "service",
"version": "2017-01-17"
"version": "2017-01-17",
"operations": [
{
"target": "ns.foo#Operation"
}
]
},
"ns.foo#Operation": {
"type": "operation",
"input": {
"target": "ns.foo#Structure"
},
"traits": {
"smithy.api#documentation": "operation documentation"
}
},
"ns.foo#SomeList": {
"type": "list",
Expand Down Expand Up @@ -34,6 +48,18 @@
},
"bar": {
"target": "ns.foo#DocString"
},
"someList": {
"target": "ns.foo#SomeList",
"traits": {
"smithy.api#documentation": "list documentation"
}
},
"map": {
"target": "ns.foo#Map",
"traits": {
"smithy.api#documentation": "map documentation"
}
}
}
},
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
[DANGER] ns.foo#Ignore_Me: string shape name, `Ignore_Me`, is not upper camel case | CamelCase
[ERROR] -: Each element of `suppressions` must be an object. Found array. | Model
[ERROR] -: Each element of `validators` must be an object. Found string. | Model
[SUPPRESSED] ns.baz#This_is_ignored_too: The ns.baz#This_is_ignored_too string shape is not connected to from any service shape. | UnreferencedShape
[SUPPRESSED] ns.baz#This_is_ignored_too: string shape name, `This_is_ignored_too`, is not upper camel case | CamelCase
[SUPPRESSED] ns.foo#Ignore_Me: The ns.foo#Ignore_Me string shape is not connected to from any service shape. | UnreferencedShape
[SUPPRESSED] ns.foo#OrphanShape: The ns.foo#OrphanShape string shape is not connected to from any service shape. | UnreferencedShape
[WARNING] -: Unable to locate a validator named `UnknownValidator` | UnknownValidator.UnknownValidator
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
{
"name": "UnknownValidator"
},
{
"name": "UnreferencedShape"
},
{
"name": "CamelCase"
},
Expand All @@ -30,11 +27,6 @@
"UnreferencedShape"
]
},
{
"ids": [
"UnknownValidator"
]
},
[],
{
"ids": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,34 +13,36 @@
* permissions and limitations under the License.
*/

package software.amazon.smithy.linters;
package software.amazon.smithy.model.validation.validators;

import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import software.amazon.smithy.model.Model;
import software.amazon.smithy.model.neighbor.UnreferencedShapes;
import software.amazon.smithy.model.shapes.ServiceShape;
import software.amazon.smithy.model.validation.AbstractValidator;
import software.amazon.smithy.model.validation.ValidationEvent;
import software.amazon.smithy.model.validation.ValidatorService;

/**
* Adds a validation note event for each shape in the model that is not
* connected to a service shape.
*/
public final class UnreferencedShapeValidator extends AbstractValidator {
@Override
public List<ValidationEvent> validate(Model model) {
Set<ServiceShape> serviceShapes = model.shapes(ServiceShape.class)
.collect(Collectors.toSet());

public static final class Provider extends ValidatorService.Provider {
public Provider() {
super(UnreferencedShapeValidator.class, UnreferencedShapeValidator::new);
// Do not emit validation warnings if no services are present in the model.
if (serviceShapes.isEmpty()) {
return Collections.emptyList();
}
}

@Override
public List<ValidationEvent> validate(Model model) {
return new UnreferencedShapes().compute(model).stream()
.map(shape -> note(shape, String.format(
"The %s %s shape is not connected to from any service shape.",
shape.getId(), shape.getType())))
"The %s shape is not connected to from any service shape.", shape.getType())))
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ software.amazon.smithy.model.validation.validators.TargetValidator
software.amazon.smithy.model.validation.validators.TraitConflictValidator
software.amazon.smithy.model.validation.validators.TraitTargetValidator
software.amazon.smithy.model.validation.validators.TraitValueValidator
software.amazon.smithy.model.validation.validators.UnreferencedShapeValidator
software.amazon.smithy.model.validation.validators.UnstableFeatureValidator
software.amazon.smithy.model.validation.validators.UnstableTraitValidator
software.amazon.smithy.model.validation.validators.XmlNamespaceTraitValidator
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,10 @@ public void importsSymlinksDirectoryWithAllShapes() throws Exception {
.addImport(getClass().getResource("main.json"))
.addImport(createSymbolicLink(Paths.get(getClass().getResource("nested").toURI()), "symlink-nested"))
.assemble();
assertThat(result.getValidationEvents(), empty());

result.getValidationEvents().forEach(event -> {
assertThat(event.getSuppressionReason().get(), is("This shape is being tested for model assembly."));
});
Model model = result.unwrap();
assertTrue(model.getShape(ShapeId.from("example.namespace#String")).isPresent());
assertThat(model.getShape(ShapeId.from("example.namespace#String")).get().getType(),
Expand Down Expand Up @@ -267,7 +270,9 @@ public void importsFilesWithAllShapes() throws Exception {
.addImport(Paths.get(getClass().getResource("nested").toURI()))
.assemble();

assertThat(result.getValidationEvents(), empty());
result.getValidationEvents().forEach(event -> {
assertThat(event.getSuppressionReason().get(), is("This shape is being tested for model assembly."));
});
Model model = result.unwrap();
assertTrue(model.getShape(ShapeId.from("example.namespace#String")).isPresent());
assertThat(model.getShape(ShapeId.from("example.namespace#String")).get().getType(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
},
{
"target": "ns.foo#L"
},
{
"target": "ns.foo#M"
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@
[ERROR] ns.foo#OInput$a: Members with the `httpLabel` trait must be required. | HttpLabelTrait
[ERROR] ns.foo#PInput$a: The `a` structure member corresponds to a greedy label when used as the input of the `ns.foo#P` operation. This member targets (integer: `ns.foo#Integer`), but greedy labels must target string shapes. | HttpLabelTrait
[ERROR] ns.foo#RInput$b: `httpHeader` binding of `x-foo` conflicts with the `httpPrefixHeaders` binding of `ns.foo#RInput$a` to ``. `httpHeader` bindings must not case-insensitively start with any `httpPrefixHeaders` bindings. | HttpPrefixHeadersTrait
[NOTE] ns.foo#BadError: The structure shape is not connected to from any service shape. | UnreferencedShape
[NOTE] ns.foo#BadErrorMultipleBindings: The structure shape is not connected to from any service shape. | UnreferencedShape
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@
},
{
"target": "ns.foo#R"
},
{
"target": "ns.foo#Q"
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@
},
{
"target": "ns.foo#Invalid9"
},
{
"target": "ns.foo#ValidNestedOutputOperation"
},
{
"target": "ns.foo#DeeplyNestedOutputOperation"
},
{
"target": "ns.foo#InvalidNoOutput"
},
{
"target": "ns.foo#InvalidNestedInput"
}
]
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
"operations": [
{
"target": "smithy.private#PrivateOperation"
},
{
"target": "smithy.example#InvalidOperation"
}
]
},
Expand Down Expand Up @@ -52,6 +55,15 @@
"members": {
"valid": {
"target": "smithy.private#PrivateString"
},
"list": {
"target": "smithy.example#InvalidList"
},
"struct": {
"target": "smithy.example#InvalidStructure"
},
"map": {
"target": "smithy.example#InvalidMap"
}
},
"traits": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
[ERROR] ns.foo#InvalidResourceBindingType: resource shape `resource` relationships must target a resource shape, but found (string: `smithy.api#String`) | Target
[ERROR] ns.foo#InvalidSelfResourceBinding: A resource can appear only once in an entire service closure. This resource is illegally bound into the `ns.foo#MyService` service closure from multiple shapes: [`ns.foo#InvalidSelfResourceBinding`, `ns.foo#MyService`] | SingleResourceBinding
[ERROR] ns.foo#InvalidSelfResourceBinding: Circular resource hierarchy found: ns.foo#InvalidSelfResourceBinding -> ns.foo#InvalidSelfResourceBinding | ResourceCycle
[NOTE] ns.foo#CycleA: The resource shape is not connected to from any service shape. | UnreferencedShape
[NOTE] ns.foo#CycleB: The resource shape is not connected to from any service shape. | UnreferencedShape
[NOTE] ns.foo#CycleC: The resource shape is not connected to from any service shape. | UnreferencedShape
Loading

0 comments on commit 3705c7e

Please sign in to comment.