Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/libcst/_visitors.py: 67%
48 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:43 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:43 +0000
1# Copyright (c) Meta Platforms, Inc. and affiliates.
2#
3# This source code is licensed under the MIT license found in the
4# LICENSE file in the root directory of this source tree.
6from typing import TYPE_CHECKING, Union
8from libcst._flatten_sentinel import FlattenSentinel
9from libcst._metadata_dependent import MetadataDependent
10from libcst._removal_sentinel import RemovalSentinel
11from libcst._typed_visitor import CSTTypedTransformerFunctions, CSTTypedVisitorFunctions
12from libcst._types import CSTNodeT
14if TYPE_CHECKING:
15 # Circular dependency for typing reasons only
16 from libcst._nodes.base import CSTNode # noqa: F401
19CSTVisitorT = Union["CSTTransformer", "CSTVisitor"]
22class CSTTransformer(CSTTypedTransformerFunctions, MetadataDependent):
23 """
24 The low-level base visitor class for traversing a CST and creating an
25 updated copy of the original CST. This should be used in conjunction with
26 the :func:`~libcst.CSTNode.visit` method on a :class:`~libcst.CSTNode` to
27 visit each element in a tree starting with that node, and possibly returning
28 a new node in its place.
30 When visiting nodes using a :class:`CSTTransformer`, the return value of
31 :func:`~libcst.CSTNode.visit` will be a new tree with any changes made in
32 :func:`~libcst.CSTTransformer.on_leave` calls reflected in its children.
33 """
35 def on_visit(self, node: "CSTNode") -> bool:
36 """
37 Called every time a node is visited, before we've visited its children.
39 Returns ``True`` if children should be visited, and returns ``False``
40 otherwise.
41 """
42 visit_func = getattr(self, f"visit_{type(node).__name__}", None)
43 if visit_func is not None:
44 retval = visit_func(node)
45 else:
46 retval = True
47 # Don't visit children IFF the visit function returned False.
48 return False if retval is False else True
50 def on_leave(
51 self, original_node: CSTNodeT, updated_node: CSTNodeT
52 ) -> Union[CSTNodeT, RemovalSentinel, FlattenSentinel[CSTNodeT]]:
53 """
54 Called every time we leave a node, after we've visited its children. If
55 the :func:`~libcst.CSTTransformer.on_visit` function for this node returns
56 ``False``, this function will still be called on that node.
58 ``original_node`` is guaranteed to be the same node as is passed to
59 :func:`~libcst.CSTTransformer.on_visit`, so it is safe to do state-based
60 checks using the ``is`` operator. Modifications should always be performed
61 on the ``updated_node`` so as to not overwrite changes made by child
62 visits.
64 Returning :attr:`RemovalSentinel.REMOVE` indicates that the node should be
65 removed from its parent. This is not always possible, and may raise an
66 exception if this node is required. As a convenience, you can use
67 :func:`RemoveFromParent` as an alias to :attr:`RemovalSentinel.REMOVE`.
68 """
69 leave_func = getattr(self, f"leave_{type(original_node).__name__}", None)
70 if leave_func is not None:
71 updated_node = leave_func(original_node, updated_node)
73 return updated_node
75 def on_visit_attribute(self, node: "CSTNode", attribute: str) -> None:
76 """
77 Called before a node's child attribute is visited and after we have called
78 :func:`~libcst.CSTTransformer.on_visit` on the node. A node's child
79 attributes are visited in the order that they appear in source that this
80 node originates from.
81 """
82 visit_func = getattr(self, f"visit_{type(node).__name__}_{attribute}", None)
83 if visit_func is not None:
84 visit_func(node)
86 def on_leave_attribute(self, original_node: "CSTNode", attribute: str) -> None:
87 """
88 Called after a node's child attribute is visited and before we have called
89 :func:`~libcst.CSTTransformer.on_leave` on the node.
91 Unlike :func:`~libcst.CSTTransformer.on_leave`, this function does
92 not allow modifications to the tree and is provided solely for state
93 management.
94 """
95 leave_func = getattr(
96 self, f"leave_{type(original_node).__name__}_{attribute}", None
97 )
98 if leave_func is not None:
99 leave_func(original_node)
102class CSTVisitor(CSTTypedVisitorFunctions, MetadataDependent):
103 """
104 The low-level base visitor class for traversing a CST. This should be used in
105 conjunction with the :func:`~libcst.CSTNode.visit` method on a
106 :class:`~libcst.CSTNode` to visit each element in a tree starting with that
107 node. Unlike :class:`CSTTransformer`, instances of this class cannot modify
108 the tree.
110 When visiting nodes using a :class:`CSTVisitor`, the return value of
111 :func:`~libcst.CSTNode.visit` will equal the passed in tree.
112 """
114 def on_visit(self, node: "CSTNode") -> bool:
115 """
116 Called every time a node is visited, before we've visited its children.
118 Returns ``True`` if children should be visited, and returns ``False``
119 otherwise.
120 """
121 visit_func = getattr(self, f"visit_{type(node).__name__}", None)
122 if visit_func is not None:
123 retval = visit_func(node)
124 else:
125 retval = True
126 # Don't visit children IFF the visit function returned False.
127 return False if retval is False else True
129 def on_leave(self, original_node: "CSTNode") -> None:
130 """
131 Called every time we leave a node, after we've visited its children. If
132 the :func:`~libcst.CSTVisitor.on_visit` function for this node returns
133 ``False``, this function will still be called on that node.
134 """
135 leave_func = getattr(self, f"leave_{type(original_node).__name__}", None)
136 if leave_func is not None:
137 leave_func(original_node)
139 def on_visit_attribute(self, node: "CSTNode", attribute: str) -> None:
140 """
141 Called before a node's child attribute is visited and after we have called
142 :func:`~libcst.CSTTransformer.on_visit` on the node. A node's child
143 attributes are visited in the order that they appear in source that this
144 node originates from.
145 """
146 visit_func = getattr(self, f"visit_{type(node).__name__}_{attribute}", None)
147 if visit_func is not None:
148 visit_func(node)
150 def on_leave_attribute(self, original_node: "CSTNode", attribute: str) -> None:
151 """
152 Called after a node's child attribute is visited and before we have called
153 :func:`~libcst.CSTVisitor.on_leave` on the node.
154 """
155 leave_func = getattr(
156 self, f"leave_{type(original_node).__name__}_{attribute}", None
157 )
158 if leave_func is not None:
159 leave_func(original_node)