blob: 3b9fde7f0c22621f9e0f8c58129fd3a2add6fee2 [file] [log] [blame]
# Copyright 2015 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Tests for yapf.pytree_utils."""
import unittest
from lib2to3 import pygram
from lib2to3 import pytree
from lib2to3.pgen2 import token
from yapf.yapflib import pytree_utils
# More direct access to the symbol->number mapping living within the grammar
# module.
_GRAMMAR_SYMBOL2NUMBER = pygram.python_grammar.symbol2number
_FOO = 'foo'
_FOO1 = 'foo1'
_FOO2 = 'foo2'
_FOO3 = 'foo3'
_FOO4 = 'foo4'
_FOO5 = 'foo5'
class NodeNameTest(unittest.TestCase):
def testNodeNameForLeaf(self):
leaf = pytree.Leaf(token.LPAR, '(')
self.assertEqual('LPAR', pytree_utils.NodeName(leaf))
def testNodeNameForNode(self):
leaf = pytree.Leaf(token.LPAR, '(')
node = pytree.Node(pygram.python_grammar.symbol2number['suite'], [leaf])
self.assertEqual('suite', pytree_utils.NodeName(node))
class ParseCodeToTreeTest(unittest.TestCase):
def testParseCodeToTree(self):
# Since ParseCodeToTree is a thin wrapper around underlying lib2to3
# functionality, only a sanity test here...
tree = pytree_utils.ParseCodeToTree('foo = 2\n')
self.assertEqual('file_input', pytree_utils.NodeName(tree))
self.assertEqual(2, len(tree.children))
self.assertEqual('simple_stmt', pytree_utils.NodeName(tree.children[0]))
def testPrintFunctionToTree(self):
tree = pytree_utils.ParseCodeToTree(
'print("hello world", file=sys.stderr)\n')
self.assertEqual('file_input', pytree_utils.NodeName(tree))
self.assertEqual(2, len(tree.children))
self.assertEqual('simple_stmt', pytree_utils.NodeName(tree.children[0]))
def testPrintStatementToTree(self):
tree = pytree_utils.ParseCodeToTree('print "hello world"\n')
self.assertEqual('file_input', pytree_utils.NodeName(tree))
self.assertEqual(2, len(tree.children))
self.assertEqual('simple_stmt', pytree_utils.NodeName(tree.children[0]))
def testClassNotLocal(self):
tree = pytree_utils.ParseCodeToTree('class nonlocal: pass\n')
self.assertEqual('file_input', pytree_utils.NodeName(tree))
self.assertEqual(2, len(tree.children))
self.assertEqual('classdef', pytree_utils.NodeName(tree.children[0]))
class InsertNodesBeforeAfterTest(unittest.TestCase):
def _BuildSimpleTree(self):
# Builds a simple tree we can play with in the tests.
# The tree looks like this:
#
# suite:
# LPAR
# LPAR
# simple_stmt:
# NAME('foo')
#
lpar1 = pytree.Leaf(token.LPAR, '(')
lpar2 = pytree.Leaf(token.LPAR, '(')
simple_stmt = pytree.Node(_GRAMMAR_SYMBOL2NUMBER['simple_stmt'],
[pytree.Leaf(token.NAME, 'foo')])
return pytree.Node(_GRAMMAR_SYMBOL2NUMBER['suite'],
[lpar1, lpar2, simple_stmt])
def _MakeNewNodeRPAR(self):
return pytree.Leaf(token.RPAR, ')')
def setUp(self):
self._simple_tree = self._BuildSimpleTree()
def testInsertNodesBefore(self):
# Insert before simple_stmt and make sure it went to the right place
pytree_utils.InsertNodesBefore([self._MakeNewNodeRPAR()],
self._simple_tree.children[2])
self.assertEqual(4, len(self._simple_tree.children))
self.assertEqual('RPAR',
pytree_utils.NodeName(self._simple_tree.children[2]))
self.assertEqual('simple_stmt',
pytree_utils.NodeName(self._simple_tree.children[3]))
def testInsertNodesBeforeFirstChild(self):
# Insert before the first child of its parent
simple_stmt = self._simple_tree.children[2]
foo_child = simple_stmt.children[0]
pytree_utils.InsertNodesBefore([self._MakeNewNodeRPAR()], foo_child)
self.assertEqual(3, len(self._simple_tree.children))
self.assertEqual(2, len(simple_stmt.children))
self.assertEqual('RPAR', pytree_utils.NodeName(simple_stmt.children[0]))
self.assertEqual('NAME', pytree_utils.NodeName(simple_stmt.children[1]))
def testInsertNodesAfter(self):
# Insert after and make sure it went to the right place
pytree_utils.InsertNodesAfter([self._MakeNewNodeRPAR()],
self._simple_tree.children[2])
self.assertEqual(4, len(self._simple_tree.children))
self.assertEqual('simple_stmt',
pytree_utils.NodeName(self._simple_tree.children[2]))
self.assertEqual('RPAR',
pytree_utils.NodeName(self._simple_tree.children[3]))
def testInsertNodesAfterLastChild(self):
# Insert after the last child of its parent
simple_stmt = self._simple_tree.children[2]
foo_child = simple_stmt.children[0]
pytree_utils.InsertNodesAfter([self._MakeNewNodeRPAR()], foo_child)
self.assertEqual(3, len(self._simple_tree.children))
self.assertEqual(2, len(simple_stmt.children))
self.assertEqual('NAME', pytree_utils.NodeName(simple_stmt.children[0]))
self.assertEqual('RPAR', pytree_utils.NodeName(simple_stmt.children[1]))
def testInsertNodesWhichHasParent(self):
# Try to insert an existing tree node into another place and fail.
with self.assertRaises(RuntimeError):
pytree_utils.InsertNodesAfter([self._simple_tree.children[1]],
self._simple_tree.children[0])
class AnnotationsTest(unittest.TestCase):
def setUp(self):
self._leaf = pytree.Leaf(token.LPAR, '(')
self._node = pytree.Node(_GRAMMAR_SYMBOL2NUMBER['simple_stmt'],
[pytree.Leaf(token.NAME, 'foo')])
def testGetWhenNone(self):
self.assertIsNone(pytree_utils.GetNodeAnnotation(self._leaf, _FOO))
def testSetWhenNone(self):
pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 20)
self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 20)
def testSetAgain(self):
pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 20)
self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 20)
pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 30)
self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 30)
def testMultiple(self):
pytree_utils.SetNodeAnnotation(self._leaf, _FOO, 20)
pytree_utils.SetNodeAnnotation(self._leaf, _FOO1, 1)
pytree_utils.SetNodeAnnotation(self._leaf, _FOO2, 2)
pytree_utils.SetNodeAnnotation(self._leaf, _FOO3, 3)
pytree_utils.SetNodeAnnotation(self._leaf, _FOO4, 4)
pytree_utils.SetNodeAnnotation(self._leaf, _FOO5, 5)
self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO), 20)
self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO1), 1)
self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO2), 2)
self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO3), 3)
self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO4), 4)
self.assertEqual(pytree_utils.GetNodeAnnotation(self._leaf, _FOO5), 5)
def testSubtype(self):
pytree_utils.AppendNodeAnnotation(self._leaf,
pytree_utils.Annotation.SUBTYPE, _FOO)
self.assertSetEqual(
pytree_utils.GetNodeAnnotation(self._leaf,
pytree_utils.Annotation.SUBTYPE), {_FOO})
pytree_utils.RemoveSubtypeAnnotation(self._leaf, _FOO)
self.assertSetEqual(
pytree_utils.GetNodeAnnotation(self._leaf,
pytree_utils.Annotation.SUBTYPE), set())
def testSetOnNode(self):
pytree_utils.SetNodeAnnotation(self._node, _FOO, 20)
self.assertEqual(pytree_utils.GetNodeAnnotation(self._node, _FOO), 20)
if __name__ == '__main__':
unittest.main()