smithy
smithy copied to clipboard
Selectors: recursive mixin check?
Hi! I was wondering if there's a way to write a selector that checks if the given shape has a mixin... but checking recursively.
For example, consider this model:
$version: "2"
namespace demo
@mixin
structure MyMixin {}
@hasMyMixin
@mixin
structure Direct with [MyMixin] {}
// structure Indirect with [Direct] {}
@trait(selector: ":test(-[mixin]-> structure [id = 'demo#MyMixin'])")
structure hasMyMixin {}
In its current state, it's valid. However, if you uncomment Indirect
it no longer matches (it inherits the hasMyMixin
trait, but that fails to validate on Indirect
due to the mixin being transitive).
Would it make sense to expand the mixin
relationship, or provide a recursive variant of -[...]->
? Perhaps a "forward directed recursive neighbor" syntax, like -[...]~>
?
Is there a better, existing way to do what I'm looking for? (without resorting to Java)
Maybe we could add a synthetic “transitiveMixin” relationship available to selectors which includes direct and transitive mixins. Or maybe a :hasMixin(a, c, c) function that returns true if all mixins are present on a shape. I like the relationship but we’d need to see how disruptive it is vs a function.
I pushed up a branch that has a proof of concept for :recursive(expr)
function in it. Any result that hasn't been seen yet is recursively selected by the given expression, so you can do :recursive(-[mixin]->)
to get all mixins of a shape. It has no tests or docs, and I still need to deeply think through how good of an idea this specific approach is.
If you wanna try it out, you could pull this down and then build the Smithy CLI using ./gradlew :smithy-cli:runtime
. I want to make sure there are more use cases than just finding transitive mixins. Edit: I'll try to list some ideas on what this could do:
- Find direct and transitive mixins:
:recursive(-[mixin]->)
. - Find out if a shape has a mixin directly or transitively:
:test(:recursive(-[mixin]->) [id=test#MyMixin])
- Find the enclosing resource hierarchy of a shape:
:recursive(<-[resource, service]-)
- Find out if a shape is in the closure of a specific resource:
:test(:recursive(<-[resource]-) [id=test#A])
https://github.com/smithy-lang/smithy/commit/0dfdc54493b25f3dacbfada614e04bd8d8814620
Thank you!