1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
|
.. _libcst-matchers:
========
Matchers
========
Matchers are provided as a way of asking whether a particular LibCST node and its
children match a particular shape. It is possible to write a visitor that
tracks attributes using ``visit_<Node>`` methods. It is also possible to implement
manual instance checking and traversal of a node's children. However, both are
cumbersome to write and hard to understand. Matchers offer a more concise way of
defining what attributes on a node matter when matching against predefined patterns.
To accomplish this, a matcher has been created which corresponds to each LibCST
node documented in :ref:`libcst-nodes`. Matchers default each of their attributes
to the special sentinel matcher :func:`~libcst.matchers.DoNotCare`. When constructing
a matcher, you can initialize the node with only the values of attributes that
you are concerned with, leaving the rest of the attributes set to
:func:`~libcst.matchers.DoNotCare` in order to skip comparing against them.
------------
Matcher APIs
------------
Functions
^^^^^^^^^
Matchers can be used either by calling :func:`~libcst.matchers.matches` or
:func:`~libcst.matchers.findall` directly, or by using various decorators to
selectively control when LibCST calls visitor functions.
.. autofunction:: libcst.matchers.matches
.. autofunction:: libcst.matchers.findall
.. autofunction:: libcst.matchers.extract
.. autofunction:: libcst.matchers.extractall
.. autofunction:: libcst.matchers.replace
.. _libcst-matcher-decorators:
Decorators
^^^^^^^^^^
The following decorators can be placed onto a method in a visitor or transformer
in order to convert it into a visitor which is called when the provided matcher is
true.
.. autofunction:: libcst.matchers.visit
.. autofunction:: libcst.matchers.leave
The following decorators can be placed onto any existing ``visit_<Node>`` or
``leave_<Node>`` visitor, as well as any visitor created using either
:func:`~libcst.matchers.visit` or :func:`~libcst.matchers.leave`. They control
whether the visitor itself gets called or skipped by LibCST when traversing a tree.
Note that when a visitor function is skipped, its children will still be visited
based on the rules set forth in :ref:`libcst-visitors`. Namely, if you have a separate
``visit_<Node>`` visitor that returns ``False`` for a particular node, we will not
traverse to its children.
.. autofunction:: libcst.matchers.call_if_inside
.. autofunction:: libcst.matchers.call_if_not_inside
When using matcher decorators, your visitors must subclass from
:class:`~libcst.matchers.MatcherDecoratableVisitor` instead of :class:`libcst.CSTVisitor`,
and from :class:`~libcst.matchers.MatcherDecoratableTransformer` instead of
:class:`libcst.CSTTransformer`. This is so that visitors and transformers not making
use of matcher decorators do not pay the extra cost of their implementation. Note that
if you do not subclass from :class:`~libcst.matchers.MatcherDecoratableVisitor` or
:class:`~libcst.matchers.MatcherDecoratableTransformer`, you can still use the
:func:`~libcst.matchers.matches` function.
Both of these classes are strict subclasses of their corresponding LibCST base class,
so they can be used anywhere that expects a LibCST base class. See :ref:`libcst-visitors`
for more information.
.. autoclass:: libcst.matchers.MatcherDecoratableVisitor
.. autoclass:: libcst.matchers.MatcherDecoratableTransformer
Traversal Order
^^^^^^^^^^^^^^^
Visit and leave functions created using :func:`~libcst.matchers.visit` or
:func:`~libcst.matchers.leave` follow the traversal order rules laid out in
LibCST's visitor :ref:`libcst-visitor-traversal` with one additional rule. Any
visit function created using the :func:`~libcst.matchers.visit` decorator will be
called **before** a ``visit_<Node>`` function if it is defined for your visitor.
The order in which various visit functions which are created with
:func:`~libcst.matchers.visit` are called is indeterminate, but all such functions
will be called before calling the ``visit_<Node>`` method. Similarly, any leave
function created using the :func:`~libcst.matchers.leave` decorator will be called
**after** a ``leave_<Node>`` function if it is defined for your visitor. The order
in which various leave functions which are created with
:func:`~libcst.matchers.leave` are called is indeterminate, but all such functions
will be called after calling the ``visit_<Node>`` function if it is defined for
your visitor.
This has a few implications. The first is that if you return ``False`` from a
``visit_<Node>`` method, we are guaranteed to call your decorated visit functions
as well. Second, when modifying a node in both ``leave_<Node>`` and a visitor
created with :func:`~libcst.matchers.leave`, the ``original_node`` will be unchanged
for both and the ``updated_node`` available to the decorated leave method will be
the node that is returned by the ``leave_<Node>`` method. Chaining modifications
across multiple leave functions is supported, but must be done with care.
-------------
Matcher Types
-------------
Concrete Matchers
^^^^^^^^^^^^^^^^^
For each node found in :ref:`libcst-nodes`, a corresponding concrete matcher
has been generated. Each matcher has attributes identical to its LibCST node
counterpart. For example, :class:`libcst.Expr` includes the ``value`` and ``semicolon``
attributes, and therefore :class:`libcst.matchers.Expr` similarly includes the same
attributes. Just as :class:`libcst.Expr`'s ``value`` is typed as taking a
:class:`libcst.BaseExpression`, :class:`libcst.matchers.Expr`'s ``value`` is typed
as taking a :class:`libcst.matchers.BaseExpression`. For every node that exists in
LibCST, both concrete and abstract, a corresponding matcher has been defined.
There are a few special cases to the rules laid out above. For starters, matchers
don't support evaluating :class:`~libcst.MaybeSentinel`. There is no way to specify
that you wish to match against a :class:`~libcst.MaybeSentinel` except with the
:func:`~libcst.matchers.DoNotCare` matcher. This tends not to be an issue in
practice because :class:`~libcst.MaybeSentinel` is only found on syntax nodes.
While there are base classes such as :class:`libcst.matchers.BaseExpression`, you
cannot match directly on them. They are provided for typing purposes only in order
to exactly match the types on LibCST node attributes. If you need to match on
all concrete subclasses of a base class, we recommend using the special matcher
:class:`~libcst.matchers.OneOf`.
.. autoclass:: libcst.matchers.BaseMatcherNode
Special Matchers
^^^^^^^^^^^^^^^^
Special matchers are matchers that don't have a corresponding LibCST node. Concrete
matchers only match against their corresponding LibCST node, limiting their use
under certain circumstances. Special matchers fill in the gap by allowing
higher-level logic constructs such as inversion. You can use any special matcher
in place of a concrete matcher when specifying matcher attributes. Additionally,
you can also use the :class:`~libcst.matchers.AllOf` and
:class:`~libcst.matchers.OneOf` special matchers in place of a concrete matcher
when calling :func:`~libcst.matchers.matches` or using decorators.
.. autoclass:: libcst.matchers.OneOf
.. autoclass:: libcst.matchers.AllOf
.. autoclass:: libcst.matchers.TypeOf
.. autofunction:: libcst.matchers.DoesNotMatch
.. autoclass:: libcst.matchers.MatchIfTrue
.. autofunction:: libcst.matchers.MatchRegex
.. autoclass:: libcst.matchers.MatchMetadata
.. autoclass:: libcst.matchers.MatchMetadataIfTrue
.. autofunction:: libcst.matchers.SaveMatchedNode
.. autofunction:: libcst.matchers.DoNotCare
Sequence Wildcard Matchers
^^^^^^^^^^^^^^^^^^^^^^^^^^
Sequence wildcard matchers are matchers that only get used when constructing a
sequence to match against. Not all LibCST nodes have attributes which are sequences,
but for those that do, sequence wildcard matchers offer a great degree of
flexibility. Unlike all other matcher types, these allow you to match against
more than one LibCST node, much like wildcards in regular expressions do.
LibCST does not implicitly match on partial sequences for you. So, when matching
against a sequence you will need to provide a complete pattern. This often means
using helpers such as :func:`~libcst.matchers.ZeroOrMore` as the first and last
element of your sequence. Think of it as the difference between Python's
`re.match <https://docs.python.org/3/library/re.html#re.match>`_ and
`re.fullmatch <https://docs.python.org/3/library/re.html#re.fullmatch>`_ functions.
LibCST matchers behave like the latter so that it is possible to specify sequences
which must start with, end with or be exactly equal to some pattern.
.. autoclass:: libcst.matchers.AtLeastN
.. autofunction:: libcst.matchers.ZeroOrMore
.. autoclass:: libcst.matchers.AtMostN
.. autofunction:: libcst.matchers.ZeroOrOne
|