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

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. 

5 

6from typing import TYPE_CHECKING, Union 

7 

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 

13 

14if TYPE_CHECKING: 

15 # Circular dependency for typing reasons only 

16 from libcst._nodes.base import CSTNode # noqa: F401 

17 

18 

19CSTVisitorT = Union["CSTTransformer", "CSTVisitor"] 

20 

21 

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. 

29 

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 """ 

34 

35 def on_visit(self, node: "CSTNode") -> bool: 

36 """ 

37 Called every time a node is visited, before we've visited its children. 

38 

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 

49 

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. 

57 

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. 

63 

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) 

72 

73 return updated_node 

74 

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) 

85 

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. 

90 

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) 

100 

101 

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. 

109 

110 When visiting nodes using a :class:`CSTVisitor`, the return value of 

111 :func:`~libcst.CSTNode.visit` will equal the passed in tree. 

112 """ 

113 

114 def on_visit(self, node: "CSTNode") -> bool: 

115 """ 

116 Called every time a node is visited, before we've visited its children. 

117 

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 

128 

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) 

138 

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) 

149 

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)