xref: /aosp_15_r20/external/yapf/yapftests/pytree_utils_test.py (revision 7249d1a64f4850ccf838e62a46276f891f72998e)
1*7249d1a6SKrzysztof Kosiński# Copyright 2015 Google Inc. All Rights Reserved.
2*7249d1a6SKrzysztof Kosiński#
3*7249d1a6SKrzysztof Kosiński# Licensed under the Apache License, Version 2.0 (the "License");
4*7249d1a6SKrzysztof Kosiński# you may not use this file except in compliance with the License.
5*7249d1a6SKrzysztof Kosiński# You may obtain a copy of the License at
6*7249d1a6SKrzysztof Kosiński#
7*7249d1a6SKrzysztof Kosiński#     http://www.apache.org/licenses/LICENSE-2.0
8*7249d1a6SKrzysztof Kosiński#
9*7249d1a6SKrzysztof Kosiński# Unless required by applicable law or agreed to in writing, software
10*7249d1a6SKrzysztof Kosiński# distributed under the License is distributed on an "AS IS" BASIS,
11*7249d1a6SKrzysztof Kosiński# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*7249d1a6SKrzysztof Kosiński# See the License for the specific language governing permissions and
13*7249d1a6SKrzysztof Kosiński# limitations under the License.
14*7249d1a6SKrzysztof Kosiński"""Tests for yapf.pytree_utils."""
15*7249d1a6SKrzysztof Kosiński
16*7249d1a6SKrzysztof Kosińskiimport unittest
17*7249d1a6SKrzysztof Kosiński
18*7249d1a6SKrzysztof Kosińskifrom lib2to3 import pygram
19*7249d1a6SKrzysztof Kosińskifrom lib2to3 import pytree
20*7249d1a6SKrzysztof Kosińskifrom lib2to3.pgen2 import token
21*7249d1a6SKrzysztof Kosiński
22*7249d1a6SKrzysztof Kosińskifrom yapf.yapflib import pytree_utils
23*7249d1a6SKrzysztof Kosiński
24*7249d1a6SKrzysztof Kosiński# More direct access to the symbol->number mapping living within the grammar
25*7249d1a6SKrzysztof Kosiński# module.
26*7249d1a6SKrzysztof Kosiński_GRAMMAR_SYMBOL2NUMBER = pygram.python_grammar.symbol2number
27*7249d1a6SKrzysztof Kosiński
28*7249d1a6SKrzysztof Kosiński_FOO = 'foo'
29*7249d1a6SKrzysztof Kosiński_FOO1 = 'foo1'
30*7249d1a6SKrzysztof Kosiński_FOO2 = 'foo2'
31*7249d1a6SKrzysztof Kosiński_FOO3 = 'foo3'
32*7249d1a6SKrzysztof Kosiński_FOO4 = 'foo4'
33*7249d1a6SKrzysztof Kosiński_FOO5 = 'foo5'
34*7249d1a6SKrzysztof Kosiński
35*7249d1a6SKrzysztof Kosiński
36*7249d1a6SKrzysztof Kosińskiclass NodeNameTest(unittest.TestCase):
37*7249d1a6SKrzysztof Kosiński
38*7249d1a6SKrzysztof Kosiński  def testNodeNameForLeaf(self):
39*7249d1a6SKrzysztof Kosiński    leaf = pytree.Leaf(token.LPAR, '(')
40*7249d1a6SKrzysztof Kosiński    self.assertEqual('LPAR', pytree_utils.NodeName(leaf))
41*7249d1a6SKrzysztof Kosiński
42*7249d1a6SKrzysztof Kosiński  def testNodeNameForNode(self):
43*7249d1a6SKrzysztof Kosiński    leaf = pytree.Leaf(token.LPAR, '(')
44*7249d1a6SKrzysztof Kosiński    node = pytree.Node(pygram.python_grammar.symbol2number['suite'], [leaf])
45*7249d1a6SKrzysztof Kosiński    self.assertEqual('suite', pytree_utils.NodeName(node))
46*7249d1a6SKrzysztof Kosiński
47*7249d1a6SKrzysztof Kosiński
48*7249d1a6SKrzysztof Kosińskiclass ParseCodeToTreeTest(unittest.TestCase):
49*7249d1a6SKrzysztof Kosiński
50*7249d1a6SKrzysztof Kosiński  def testParseCodeToTree(self):
51*7249d1a6SKrzysztof Kosiński    # Since ParseCodeToTree is a thin wrapper around underlying lib2to3
52*7249d1a6SKrzysztof Kosiński    # functionality, only a sanity test here...
53*7249d1a6SKrzysztof Kosiński    tree = pytree_utils.ParseCodeToTree('foo = 2\n')
54*7249d1a6SKrzysztof Kosiński    self.assertEqual('file_input', pytree_utils.NodeName(tree))
55*7249d1a6SKrzysztof Kosiński    self.assertEqual(2, len(tree.children))
56*7249d1a6SKrzysztof Kosiński    self.assertEqual('simple_stmt', pytree_utils.NodeName(tree.children[0]))
57*7249d1a6SKrzysztof Kosiński
58*7249d1a6SKrzysztof Kosiński  def testPrintFunctionToTree(self):
59*7249d1a6SKrzysztof Kosiński    tree = pytree_utils.ParseCodeToTree(
60*7249d1a6SKrzysztof Kosiński        'print("hello world", file=sys.stderr)\n')
61*7249d1a6SKrzysztof Kosiński    self.assertEqual('file_input', pytree_utils.NodeName(tree))
62*7249d1a6SKrzysztof Kosiński    self.assertEqual(2, len(tree.children))
63*7249d1a6SKrzysztof Kosiński    self.assertEqual('simple_stmt', pytree_utils.NodeName(tree.children[0]))
64*7249d1a6SKrzysztof Kosiński
65*7249d1a6SKrzysztof Kosiński  def testPrintStatementToTree(self):
66*7249d1a6SKrzysztof Kosiński    tree = pytree_utils.ParseCodeToTree('print "hello world"\n')
67*7249d1a6SKrzysztof Kosiński    self.assertEqual('file_input', pytree_utils.NodeName(tree))
68*7249d1a6SKrzysztof Kosiński    self.assertEqual(2, len(tree.children))
69*7249d1a6SKrzysztof Kosiński    self.assertEqual('simple_stmt', pytree_utils.NodeName(tree.children[0]))
70*7249d1a6SKrzysztof Kosiński
71*7249d1a6SKrzysztof Kosiński  def testClassNotLocal(self):
72*7249d1a6SKrzysztof Kosiński    tree = pytree_utils.ParseCodeToTree('class nonlocal: pass\n')
73*7249d1a6SKrzysztof Kosiński    self.assertEqual('file_input', pytree_utils.NodeName(tree))
74*7249d1a6SKrzysztof Kosiński    self.assertEqual(2, len(tree.children))
75*7249d1a6SKrzysztof Kosiński    self.assertEqual('classdef', pytree_utils.NodeName(tree.children[0]))
76*7249d1a6SKrzysztof Kosiński
77*7249d1a6SKrzysztof Kosiński
78*7249d1a6SKrzysztof Kosińskiclass InsertNodesBeforeAfterTest(unittest.TestCase):
79*7249d1a6SKrzysztof Kosiński
80*7249d1a6SKrzysztof Kosiński  def _BuildSimpleTree(self):
81*7249d1a6SKrzysztof Kosiński    # Builds a simple tree we can play with in the tests.
82*7249d1a6SKrzysztof Kosiński    # The tree looks like this:
83*7249d1a6SKrzysztof Kosiński    #
84*7249d1a6SKrzysztof Kosiński    #   suite:
85*7249d1a6SKrzysztof Kosiński    #     LPAR
86*7249d1a6SKrzysztof Kosiński    #     LPAR
87*7249d1a6SKrzysztof Kosiński    #     simple_stmt:
88*7249d1a6SKrzysztof Kosiński    #       NAME('foo')
89*7249d1a6SKrzysztof Kosiński    #
90*7249d1a6SKrzysztof Kosiński    lpar1 = pytree.Leaf(token.LPAR, '(')
91*7249d1a6SKrzysztof Kosiński    lpar2 = pytree.Leaf(token.LPAR, '(')
92*7249d1a6SKrzysztof Kosiński    simple_stmt = pytree.Node(_GRAMMAR_SYMBOL2NUMBER['simple_stmt'],
93*7249d1a6SKrzysztof Kosiński                              [pytree.Leaf(token.NAME, 'foo')])
94*7249d1a6SKrzysztof Kosiński    return pytree.Node(_GRAMMAR_SYMBOL2NUMBER['suite'],
95*7249d1a6SKrzysztof Kosiński                       [lpar1, lpar2, simple_stmt])
96*7249d1a6SKrzysztof Kosiński
97*7249d1a6SKrzysztof Kosiński  def _MakeNewNodeRPAR(self):
98*7249d1a6SKrzysztof Kosiński    return pytree.Leaf(token.RPAR, ')')
99*7249d1a6SKrzysztof Kosiński
100*7249d1a6SKrzysztof Kosiński  def setUp(self):
101*7249d1a6SKrzysztof Kosiński    self._simple_tree = self._BuildSimpleTree()
102*7249d1a6SKrzysztof Kosiński
103*7249d1a6SKrzysztof Kosiński  def testInsertNodesBefore(self):
104*7249d1a6SKrzysztof Kosiński    # Insert before simple_stmt and make sure it went to the right place
105*7249d1a6SKrzysztof Kosiński    pytree_utils.InsertNodesBefore([self._MakeNewNodeRPAR()],
106*7249d1a6SKrzysztof Kosiński                                   self._simple_tree.children[2])
107*7249d1a6SKrzysztof Kosiński    self.assertEqual(4, len(self._simple_tree.children))
108*7249d1a6SKrzysztof Kosiński    self.assertEqual('RPAR',
109*7249d1a6SKrzysztof Kosiński                     pytree_utils.NodeName(self._simple_tree.children[2]))
110*7249d1a6SKrzysztof Kosiński    self.assertEqual('simple_stmt',
111*7249d1a6SKrzysztof Kosiński                     pytree_utils.NodeName(self._simple_tree.children[3]))
112*7249d1a6SKrzysztof Kosiński
113*7249d1a6SKrzysztof Kosiński  def testInsertNodesBeforeFirstChild(self):
114*7249d1a6SKrzysztof Kosiński    # Insert before the first child of its parent
115*7249d1a6SKrzysztof Kosiński    simple_stmt = self._simple_tree.children[2]
116*7249d1a6SKrzysztof Kosiński    foo_child = simple_stmt.children[0]
117*7249d1a6SKrzysztof Kosiński    pytree_utils.InsertNodesBefore([self._MakeNewNodeRPAR()], foo_child)
118*7249d1a6SKrzysztof Kosiński    self.assertEqual(3, len(self._simple_tree.children))
119*7249d1a6SKrzysztof Kosiński    self.assertEqual(2, len(simple_stmt.children))
120*7249d1a6SKrzysztof Kosiński    self.assertEqual('RPAR', pytree_utils.NodeName(simple_stmt.children[0]))
121*7249d1a6SKrzysztof Kosiński    self.assertEqual('NAME', pytree_utils.NodeName(simple_stmt.children[1]))
122*7249d1a6SKrzysztof Kosiński
123*7249d1a6SKrzysztof Kosiński  def testInsertNodesAfter(self):
124*7249d1a6SKrzysztof Kosiński    # Insert after and make sure it went to the right place
125*7249d1a6SKrzysztof Kosiński    pytree_utils.InsertNodesAfter([self._MakeNewNodeRPAR()],
126*7249d1a6SKrzysztof Kosiński                                  self._simple_tree.children[2])
127*7249d1a6SKrzysztof Kosiński    self.assertEqual(4, len(self._simple_tree.children))
128*7249d1a6SKrzysztof Kosiński    self.assertEqual('simple_stmt',
129*7249d1a6SKrzysztof Kosiński                     pytree_utils.NodeName(self._simple_tree.children[2]))
130*7249d1a6SKrzysztof Kosiński    self.assertEqual('RPAR',
131*7249d1a6SKrzysztof Kosiński                     pytree_utils.NodeName(self._simple_tree.children[3]))
132*7249d1a6SKrzysztof Kosiński
133*7249d1a6SKrzysztof Kosiński  def testInsertNodesAfterLastChild(self):
134*7249d1a6SKrzysztof Kosiński    # Insert after the last child of its parent
135*7249d1a6SKrzysztof Kosiński    simple_stmt = self._simple_tree.children[2]
136*7249d1a6SKrzysztof Kosiński    foo_child = simple_stmt.children[0]
137*7249d1a6SKrzysztof Kosiński    pytree_utils.InsertNodesAfter([self._MakeNewNodeRPAR()], foo_child)
138*7249d1a6SKrzysztof Kosiński    self.assertEqual(3, len(self._simple_tree.children))
139*7249d1a6SKrzysztof Kosiński    self.assertEqual(2, len(simple_stmt.children))
140*7249d1a6SKrzysztof Kosiński    self.assertEqual('NAME', pytree_utils.NodeName(simple_stmt.children[0]))
141*7249d1a6SKrzysztof Kosiński    self.assertEqual('RPAR', pytree_utils.NodeName(simple_stmt.children[1]))
142*7249d1a6SKrzysztof Kosiński
143*7249d1a6SKrzysztof Kosiński  def testInsertNodesWhichHasParent(self):
144*7249d1a6SKrzysztof Kosiński    # Try to insert an existing tree node into another place and fail.
145*7249d1a6SKrzysztof Kosiński    with self.assertRaises(RuntimeError):
146*7249d1a6SKrzysztof Kosiński      pytree_utils.InsertNodesAfter([self._simple_tree.children[1]],
147*7249d1a6SKrzysztof Kosiński                                    self._simple_tree.children[0])
148*7249d1a6SKrzysztof Kosiński
149*7249d1a6SKrzysztof Kosiński
150*7249d1a6SKrzysztof Kosińskiclass AnnotationsTest(unittest.TestCase):
151*7249d1a6SKrzysztof Kosiński
152*7249d1a6SKrzysztof Kosiński  def setUp(self):
153*7249d1a6SKrzysztof Kosiński    self._leaf = pytree.Leaf(token.LPAR, '(')
154*7249d1a6SKrzysztof Kosiński    self._node = pytree.Node(_GRAMMAR_SYMBOL2NUMBER['simple_stmt'],
155*7249d1a6SKrzysztof Kosiński                             [pytree.Leaf(token.NAME, 'foo')])
156*7249d1a6SKrzysztof Kosiński
157*7249d1a6SKrzysztof Kosiński  def testGetWhenNone(self):
158*7249d1a6SKrzysztof Kosiński    self.assertIsNone(pytree_utils.GetNodeAnnotation(self._leaf, _FOO))
159*7249d1a6SKrzysztof Kosiński
160*7249d1a6SKrzysztof Kosiński  def testSetWhenNone(self):
161*7249d1a6SKrzysztof Kosiński    pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 20)
162*7249d1a6SKrzysztof Kosiński    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 20)
163*7249d1a6SKrzysztof Kosiński
164*7249d1a6SKrzysztof Kosiński  def testSetAgain(self):
165*7249d1a6SKrzysztof Kosiński    pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 20)
166*7249d1a6SKrzysztof Kosiński    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 20)
167*7249d1a6SKrzysztof Kosiński    pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 30)
168*7249d1a6SKrzysztof Kosiński    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 30)
169*7249d1a6SKrzysztof Kosiński
170*7249d1a6SKrzysztof Kosiński  def testMultiple(self):
171*7249d1a6SKrzysztof Kosiński    pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 20)
172*7249d1a6SKrzysztof Kosiński    pytree_utils.SetNodeAnnotation(self._leaf, _FOO1, 1)
173*7249d1a6SKrzysztof Kosiński    pytree_utils.SetNodeAnnotation(self._leaf, _FOO2, 2)
174*7249d1a6SKrzysztof Kosiński    pytree_utils.SetNodeAnnotation(self._leaf, _FOO3, 3)
175*7249d1a6SKrzysztof Kosiński    pytree_utils.SetNodeAnnotation(self._leaf, _FOO4, 4)
176*7249d1a6SKrzysztof Kosiński    pytree_utils.SetNodeAnnotation(self._leaf, _FOO5, 5)
177*7249d1a6SKrzysztof Kosiński
178*7249d1a6SKrzysztof Kosiński    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 20)
179*7249d1a6SKrzysztof Kosiński    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO1), 1)
180*7249d1a6SKrzysztof Kosiński    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO2), 2)
181*7249d1a6SKrzysztof Kosiński    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO3), 3)
182*7249d1a6SKrzysztof Kosiński    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO4), 4)
183*7249d1a6SKrzysztof Kosiński    self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO5), 5)
184*7249d1a6SKrzysztof Kosiński
185*7249d1a6SKrzysztof Kosiński  def testSubtype(self):
186*7249d1a6SKrzysztof Kosiński    pytree_utils.AppendNodeAnnotation(self._leaf,
187*7249d1a6SKrzysztof Kosiński                                      pytree_utils.Annotation.SUBTYPE, _FOO)
188*7249d1a6SKrzysztof Kosiński
189*7249d1a6SKrzysztof Kosiński    self.assertSetEqual(
190*7249d1a6SKrzysztof Kosiński        pytree_utils.GetNodeAnnotation(self._leaf,
191*7249d1a6SKrzysztof Kosiński                                       pytree_utils.Annotation.SUBTYPE), {_FOO})
192*7249d1a6SKrzysztof Kosiński
193*7249d1a6SKrzysztof Kosiński    pytree_utils.RemoveSubtypeAnnotation(self._leaf, _FOO)
194*7249d1a6SKrzysztof Kosiński
195*7249d1a6SKrzysztof Kosiński    self.assertSetEqual(
196*7249d1a6SKrzysztof Kosiński        pytree_utils.GetNodeAnnotation(self._leaf,
197*7249d1a6SKrzysztof Kosiński                                       pytree_utils.Annotation.SUBTYPE), set())
198*7249d1a6SKrzysztof Kosiński
199*7249d1a6SKrzysztof Kosiński  def testSetOnNode(self):
200*7249d1a6SKrzysztof Kosiński    pytree_utils.SetNodeAnnotation(self._node, _FOO, 20)
201*7249d1a6SKrzysztof Kosiński    self.assertEqual(pytree_utils.GetNodeAnnotation(self._node, _FOO), 20)
202*7249d1a6SKrzysztof Kosiński
203*7249d1a6SKrzysztof Kosiński
204*7249d1a6SKrzysztof Kosińskiif __name__ == '__main__':
205*7249d1a6SKrzysztof Kosiński  unittest.main()
206