@@ -55,7 +55,7 @@ Shapes can be matched by type using the following tokens:
5555
5656The following selector matches all string shapes in a model:
5757
58- ::
58+ .. code-block :: none
5959
6060 string
6161
@@ -96,7 +96,7 @@ We can match shapes based on traits using an *attribute selector*. The
9696following selector finds all structure shapes with the :ref: `error-trait `
9797trait:
9898
99- ::
99+ .. code-block :: none
100100
101101 structure[trait|error]
102102
@@ -106,21 +106,21 @@ and that that specific trait is ``time``.
106106
107107We can match string shapes that have a specific trait value:
108108
109- ::
109+ .. code-block :: none
110110
111111 structure[trait|error=client]
112112
113113 Matching on trait values only works for traits that have a scalar value
114114(e.g., strings, numbers, and booleans). We can also match case-insensitvely
115115on the value by appending " i" before the closing bracket:
116116
117- ::
117+ .. code-block :: none
118118
119119 structure[trait|error=CLIENT i]
120120
121121 Fully-qualified trait names are also supported:
122122
123- ::
123+ .. code-block :: none
124124
125125 string[trait|smithy.example#customTrait=foo]
126126
@@ -132,7 +132,7 @@ Attribute selectors can be used to match the :ref:`shape ID <shape-id>`. The
132132following example matches a single resource shape with an ID of
133133``smithy.example#Foo ``:
134134
135- ::
135+ .. code-block :: none
136136
137137 resource[id='smithy.example#Foo']
138138
@@ -143,28 +143,28 @@ Smithy provides several attributes in the ``id`` namespace to make matching
143143on a shape ID easier. The following example finds all shapes that are in the
144144"smithy.example" namespace:
145145
146- ::
146+ .. code-block :: none
147147
148148 resource[id|namespace=smithy.example]
149149
150150 Though not as clear, matching shapes in a specific namespace can also be
151151achieved using the ``^= `` comparator against ``id ``:
152152
153- ::
153+ .. code-block :: none
154154
155155 resource[id^=smithy.example#]
156156
157157 The following example matches all member shapes that have a member name of
158158"key":
159159
160- ::
160+ .. code-block :: none
161161
162162 resource[id|member=key]
163163
164164 Though not as clear, matching members with a member name of "key" can also be
165165achieved using the ``$= `` comparator against ``id ``:
166166
167- ::
167+ .. code-block :: none
168168
169169 resource[id$="$key"]
170170
@@ -210,21 +210,21 @@ The *current* shape evaluated by a selector is changed using a neighbor token,
210210shape. For example, the following selector returns the key and value members of
211211every map:
212212
213- ::
213+ .. code-block :: none
214214
215215 map > member
216216
217217 We can return just the key members or just the value members by adding an
218218attribute selector on the ``id|member ``:
219219
220- ::
220+ .. code-block :: none
221221
222222 map > member[id|member=key]
223223
224224 Neighbors can be chained to traverse further into a shape. The following
225225selector returns strings that are targeted by list members:
226226
227- ::
227+ .. code-block :: none
228228
229229 list > member > string
230230
@@ -237,7 +237,7 @@ directed edge traversal is necessary to match the appropriate shapes. For
237237example, the following selector returns the "bound", "input", "output",
238238and "errors" relationships of each operation:
239239
240- ::
240+ .. code-block :: none
241241
242242 operation > *
243243
@@ -246,15 +246,15 @@ by a comma separated list of :ref:`relationships <selector-relationships>`,
246246followed by ``]-> ``. The following selector matches all structure
247247shapes referenced as operation input or output.
248248
249- ::
249+ .. code-block :: none
250250
251251 operation -[input, output]->
252252
253253 The ``:test `` function can be used to check if a shape has a named
254254relationship. The following selector matches all resource shapes that define
255255an identifier:
256256
257- ::
257+ .. code-block :: none
258258
259259 resource:test(-[identifier]->)
260260
@@ -265,11 +265,33 @@ explicitly requested using a ``trait`` directed relationship. The following
265265selector finds all service shapes that have a protocol trait applied to it
266266(that is, a trait that is marked with the :ref: `protocolDefinition-trait `):
267267
268- ::
268+ .. code-block :: none
269269
270270 service:test(-[trait]-> [trait|protocolDefinition])
271271
272272
273+ Recursive neighbors
274+ ~~~~~~~~~~~~~~~~~~~
275+
276+ The ``~> `` neighbor selector finds all shapes that are recursively connected in
277+ the closure of another shape.
278+
279+ The following selector finds all operations that are connected to a service
280+ shape:
281+
282+ .. code-block :: none
283+
284+ service ~> operation
285+
286+ The following selector finds all operations that do not have the :ref: `http-trait `
287+ that are in the closure of a service marked with the ``aws.protocols#restJson ``
288+ trait:
289+
290+ .. code-block :: none
291+
292+ service[trait|aws.protocols#restJson1] ~> operation:not([trait|http])
293+
294+
273295 .. _selector-relationships :
274296
275297Relationships
@@ -394,34 +416,34 @@ comma (",").
394416
395417The following selector matches all string and number shapes:
396418
397- ::
419+ .. code-block :: none
398420
399421 :each(string, number)
400422
401423 Each can be used inside of neighbors too. The following selector
402424matches all members that target a string or number:
403425
404- ::
426+ .. code-block :: none
405427
406428 member > :each(string, number)
407429
408430 The following ``:each `` selector matches all shapes that are either
409431targeted by a list member or targeted by a map member:
410432
411- ::
433+ .. code-block :: none
412434
413435 :each(list > member > *, map > member > *)
414436
415437 The following selector matches all list and map shapes that target strings:
416438
417- ::
439+ .. code-block :: none
418440
419441 :each(:test(list > member > string), :test(map > member > string))
420442
421443 Because none of the selectors in the ``:each `` function are intended to
422444change the current node, this can be reduced to the following selector:
423445
424- ::
446+ .. code-block :: none
425447
426448 :test(:each(list > member > string, map > member > string))
427449
@@ -435,15 +457,15 @@ shape.
435457
436458The following selector is used to match all string and number shapes:
437459
438- ::
460+ .. code-block :: none
439461
440462 :test(string, number)
441463
442464 The ``:test `` function is much more interesting when used to test if a shape
443465contains a neighbor in addition to other filtering. The following example
444466matches all shapes that are bound to a resource and have no documentation:
445467
446- ::
468+ .. code-block :: none
447469
448470 :test(-[bound, resource]->) :not([trait|documentation])
449471
@@ -457,20 +479,20 @@ filtered out from the result set.
457479
458480The following selector matches every shape except strings:
459481
460- ::
482+ .. code-block :: none
461483
462484 :not(string)
463485
464486 The following selector matches every shape except strings and floats:
465487
466- ::
488+ .. code-block :: none
467489
468490 :not(string, float)
469491
470492 The following example matches all shapes except for strings that are targeted
471493by a list member:
472494
473- ::
495+ .. code-block :: none
474496
475497 :not(list > member > string)
476498
@@ -482,15 +504,15 @@ The ``:test`` function can be used to test a shape, potentially traversing its
482504neighbors, without changing the return value of the test. The following
483505example does not match any list shape that has a string member:
484506
485- ::
507+ .. code-block :: none
486508
487509 :not(:test(list > member > string))
488510
489511 Successive ``:not `` functions can be used to filter shapes using several
490512predicates. The following example does not match strings or shapes with the
491513:ref: `sensitive-trait ` trait:
492514
493- ::
515+ .. code-block :: none
494516
495517 :not(string):not([trait|sensitive])
496518
@@ -499,15 +521,15 @@ match all of the provided predicates. The following selector finds all
499521string shapes that do not have both the ``length `` and ``pattern ``
500522traits:
501523
502- ::
524+ .. code-block :: none
503525
504526 string:not([trait|length], [trait|pattern])
505527
506528 The following example matches all structure members that target strings in
507529which the member does not have the ``length `` trait and the shape targeted by
508530the member does not have the ``length `` trait:
509531
510- ::
532+ .. code-block :: none
511533
512534 structure > member
513535 :test(> string:not([trait|length]))
@@ -516,14 +538,14 @@ the member does not have the ``length`` trait:
516538 The following selector finds all service shapes that do not have a
517539protocol trait applied to it:
518540
519- ::
541+ .. code-block :: none
520542
521543 service:not(:test(-[trait]-> [trait|protocolDefinition]))
522544
523545 The following selector finds all traits that are not attached to any shape
524546in the model:
525547
526- ::
548+ .. code-block :: none
527549
528550 :not(* -[trait]-> *)[trait|trait]
529551
@@ -539,13 +561,13 @@ the member is matched.
539561
540562The following example matches all structure members:
541563
542- ::
564+ .. code-block :: none
543565
544566 member:of(structure)
545567
546568 The following example matches all structure and list members:
547569
548- ::
570+ .. code-block :: none
549571
550572 member:of(structure, list)
551573
@@ -590,8 +612,9 @@ Selectors are defined by the following ABNF_ grammar.
590612 :/ "number"
591613 :/ "simpleType"
592614 :/ "collection"
593- neighbors :">" / `directed_neighbor `
615+ neighbors :">" / `directed_neighbor ` / ` recursive_neighbor `
594616 directed_neighbor :"-[" `relationship_type ` *("," `relationship_type`) "]->"
617+ recursive_neighbor :"~>"
595618 relationship_type :"identifier"
596619 :/ "create"
597620 :/ "read"
0 commit comments