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_visitor.""" 15*7249d1a6SKrzysztof Kosiński 16*7249d1a6SKrzysztof Kosińskiimport unittest 17*7249d1a6SKrzysztof Kosiński 18*7249d1a6SKrzysztof Kosińskifrom yapf.yapflib import py3compat 19*7249d1a6SKrzysztof Kosińskifrom yapf.yapflib import pytree_utils 20*7249d1a6SKrzysztof Kosińskifrom yapf.yapflib import pytree_visitor 21*7249d1a6SKrzysztof Kosiński 22*7249d1a6SKrzysztof Kosiński 23*7249d1a6SKrzysztof Kosińskiclass _NodeNameCollector(pytree_visitor.PyTreeVisitor): 24*7249d1a6SKrzysztof Kosiński """A tree visitor that collects the names of all tree nodes into a list. 25*7249d1a6SKrzysztof Kosiński 26*7249d1a6SKrzysztof Kosiński Attributes: 27*7249d1a6SKrzysztof Kosiński all_node_names: collected list of the names, available when the traversal 28*7249d1a6SKrzysztof Kosiński is over. 29*7249d1a6SKrzysztof Kosiński name_node_values: collects a list of NAME leaves (in addition to those going 30*7249d1a6SKrzysztof Kosiński into all_node_names). 31*7249d1a6SKrzysztof Kosiński """ 32*7249d1a6SKrzysztof Kosiński 33*7249d1a6SKrzysztof Kosiński def __init__(self): 34*7249d1a6SKrzysztof Kosiński self.all_node_names = [] 35*7249d1a6SKrzysztof Kosiński self.name_node_values = [] 36*7249d1a6SKrzysztof Kosiński 37*7249d1a6SKrzysztof Kosiński def DefaultNodeVisit(self, node): 38*7249d1a6SKrzysztof Kosiński self.all_node_names.append(pytree_utils.NodeName(node)) 39*7249d1a6SKrzysztof Kosiński super(_NodeNameCollector, self).DefaultNodeVisit(node) 40*7249d1a6SKrzysztof Kosiński 41*7249d1a6SKrzysztof Kosiński def DefaultLeafVisit(self, leaf): 42*7249d1a6SKrzysztof Kosiński self.all_node_names.append(pytree_utils.NodeName(leaf)) 43*7249d1a6SKrzysztof Kosiński 44*7249d1a6SKrzysztof Kosiński def Visit_NAME(self, leaf): 45*7249d1a6SKrzysztof Kosiński self.name_node_values.append(leaf.value) 46*7249d1a6SKrzysztof Kosiński self.DefaultLeafVisit(leaf) 47*7249d1a6SKrzysztof Kosiński 48*7249d1a6SKrzysztof Kosiński 49*7249d1a6SKrzysztof Kosiński_VISITOR_TEST_SIMPLE_CODE = r""" 50*7249d1a6SKrzysztof Kosińskifoo = bar 51*7249d1a6SKrzysztof Kosińskibaz = x 52*7249d1a6SKrzysztof Kosiński""" 53*7249d1a6SKrzysztof Kosiński 54*7249d1a6SKrzysztof Kosiński_VISITOR_TEST_NESTED_CODE = r""" 55*7249d1a6SKrzysztof Kosińskiif x: 56*7249d1a6SKrzysztof Kosiński if y: 57*7249d1a6SKrzysztof Kosiński return z 58*7249d1a6SKrzysztof Kosiński""" 59*7249d1a6SKrzysztof Kosiński 60*7249d1a6SKrzysztof Kosiński 61*7249d1a6SKrzysztof Kosińskiclass PytreeVisitorTest(unittest.TestCase): 62*7249d1a6SKrzysztof Kosiński 63*7249d1a6SKrzysztof Kosiński def testCollectAllNodeNamesSimpleCode(self): 64*7249d1a6SKrzysztof Kosiński tree = pytree_utils.ParseCodeToTree(_VISITOR_TEST_SIMPLE_CODE) 65*7249d1a6SKrzysztof Kosiński collector = _NodeNameCollector() 66*7249d1a6SKrzysztof Kosiński collector.Visit(tree) 67*7249d1a6SKrzysztof Kosiński expected_names = [ 68*7249d1a6SKrzysztof Kosiński 'file_input', 69*7249d1a6SKrzysztof Kosiński 'simple_stmt', 'expr_stmt', 'NAME', 'EQUAL', 'NAME', 'NEWLINE', 70*7249d1a6SKrzysztof Kosiński 'simple_stmt', 'expr_stmt', 'NAME', 'EQUAL', 'NAME', 'NEWLINE', 71*7249d1a6SKrzysztof Kosiński 'ENDMARKER', 72*7249d1a6SKrzysztof Kosiński ] # yapf: disable 73*7249d1a6SKrzysztof Kosiński self.assertEqual(expected_names, collector.all_node_names) 74*7249d1a6SKrzysztof Kosiński 75*7249d1a6SKrzysztof Kosiński expected_name_node_values = ['foo', 'bar', 'baz', 'x'] 76*7249d1a6SKrzysztof Kosiński self.assertEqual(expected_name_node_values, collector.name_node_values) 77*7249d1a6SKrzysztof Kosiński 78*7249d1a6SKrzysztof Kosiński def testCollectAllNodeNamesNestedCode(self): 79*7249d1a6SKrzysztof Kosiński tree = pytree_utils.ParseCodeToTree(_VISITOR_TEST_NESTED_CODE) 80*7249d1a6SKrzysztof Kosiński collector = _NodeNameCollector() 81*7249d1a6SKrzysztof Kosiński collector.Visit(tree) 82*7249d1a6SKrzysztof Kosiński expected_names = [ 83*7249d1a6SKrzysztof Kosiński 'file_input', 84*7249d1a6SKrzysztof Kosiński 'if_stmt', 'NAME', 'NAME', 'COLON', 85*7249d1a6SKrzysztof Kosiński 'suite', 'NEWLINE', 86*7249d1a6SKrzysztof Kosiński 'INDENT', 'if_stmt', 'NAME', 'NAME', 'COLON', 'suite', 'NEWLINE', 87*7249d1a6SKrzysztof Kosiński 'INDENT', 'simple_stmt', 'return_stmt', 'NAME', 'NAME', 'NEWLINE', 88*7249d1a6SKrzysztof Kosiński 'DEDENT', 'DEDENT', 'ENDMARKER', 89*7249d1a6SKrzysztof Kosiński ] # yapf: disable 90*7249d1a6SKrzysztof Kosiński self.assertEqual(expected_names, collector.all_node_names) 91*7249d1a6SKrzysztof Kosiński 92*7249d1a6SKrzysztof Kosiński expected_name_node_values = ['if', 'x', 'if', 'y', 'return', 'z'] 93*7249d1a6SKrzysztof Kosiński self.assertEqual(expected_name_node_values, collector.name_node_values) 94*7249d1a6SKrzysztof Kosiński 95*7249d1a6SKrzysztof Kosiński def testDumper(self): 96*7249d1a6SKrzysztof Kosiński # PyTreeDumper is mainly a debugging utility, so only do basic sanity 97*7249d1a6SKrzysztof Kosiński # checking. 98*7249d1a6SKrzysztof Kosiński tree = pytree_utils.ParseCodeToTree(_VISITOR_TEST_SIMPLE_CODE) 99*7249d1a6SKrzysztof Kosiński stream = py3compat.StringIO() 100*7249d1a6SKrzysztof Kosiński pytree_visitor.PyTreeDumper(target_stream=stream).Visit(tree) 101*7249d1a6SKrzysztof Kosiński 102*7249d1a6SKrzysztof Kosiński dump_output = stream.getvalue() 103*7249d1a6SKrzysztof Kosiński self.assertIn('file_input [3 children]', dump_output) 104*7249d1a6SKrzysztof Kosiński self.assertIn("NAME(Leaf(NAME, 'foo'))", dump_output) 105*7249d1a6SKrzysztof Kosiński self.assertIn("EQUAL(Leaf(EQUAL, '='))", dump_output) 106*7249d1a6SKrzysztof Kosiński 107*7249d1a6SKrzysztof Kosiński def testDumpPyTree(self): 108*7249d1a6SKrzysztof Kosiński # Similar sanity checking for the convenience wrapper DumpPyTree 109*7249d1a6SKrzysztof Kosiński tree = pytree_utils.ParseCodeToTree(_VISITOR_TEST_SIMPLE_CODE) 110*7249d1a6SKrzysztof Kosiński stream = py3compat.StringIO() 111*7249d1a6SKrzysztof Kosiński pytree_visitor.DumpPyTree(tree, target_stream=stream) 112*7249d1a6SKrzysztof Kosiński 113*7249d1a6SKrzysztof Kosiński dump_output = stream.getvalue() 114*7249d1a6SKrzysztof Kosiński self.assertIn('file_input [3 children]', dump_output) 115*7249d1a6SKrzysztof Kosiński self.assertIn("NAME(Leaf(NAME, 'foo'))", dump_output) 116*7249d1a6SKrzysztof Kosiński self.assertIn("EQUAL(Leaf(EQUAL, '='))", dump_output) 117*7249d1a6SKrzysztof Kosiński 118*7249d1a6SKrzysztof Kosiński 119*7249d1a6SKrzysztof Kosińskiif __name__ == '__main__': 120*7249d1a6SKrzysztof Kosiński unittest.main() 121