def test_predicate_logic_operators(self) -> None: # Verify that we can or things together. matcher = m.BinaryOperation( left=(m.MatchMetadata(meta.PositionProvider, self._make_coderange((1, 0), (1, 1))) | m.MatchMetadata(meta.PositionProvider, self._make_coderange((1, 0), (1, 2))))) node, wrapper = self._make_fixture("a + b") self.assertTrue(matches(node, matcher, metadata_resolver=wrapper)) node, wrapper = self._make_fixture("12 + 3") self.assertTrue(matches(node, matcher, metadata_resolver=wrapper)) node, wrapper = self._make_fixture("123 + 4") self.assertFalse(matches(node, matcher, metadata_resolver=wrapper)) # Verify that we can and things together matcher = m.BinaryOperation( left=(m.MatchMetadata(meta.PositionProvider, self._make_coderange((1, 0), (1, 1))) & m.MatchMetadata(meta.ExpressionContextProvider, meta.ExpressionContext.LOAD))) node, wrapper = self._make_fixture("a + b") self.assertTrue(matches(node, matcher, metadata_resolver=wrapper)) node, wrapper = self._make_fixture("ab + cd") self.assertFalse(matches(node, matcher, metadata_resolver=wrapper)) # Verify that we can not things matcher = m.BinaryOperation(left=(~(m.MatchMetadata( meta.ExpressionContextProvider, meta.ExpressionContext.STORE)))) node, wrapper = self._make_fixture("a + b") self.assertTrue(matches(node, matcher, metadata_resolver=wrapper))
def test_simple_matcher_false(self) -> None: # Fail to match on a simple node based on the type and the position. node, wrapper = self._make_fixture("foo") self.assertFalse( matches( node, m.Name( value="foo", metadata=m.MatchMetadata( meta.SyntacticPositionProvider, self._make_coderange((2, 0), (2, 3)), ), ), metadata_resolver=wrapper, ) ) # Fail to match on any binary expression where the two children are in exact spots. node, wrapper = self._make_fixture("foo + bar") self.assertFalse( matches( node, m.BinaryOperation( left=m.MatchMetadata( meta.SyntacticPositionProvider, self._make_coderange((1, 0), (1, 1)), ), right=m.MatchMetadata( meta.SyntacticPositionProvider, self._make_coderange((1, 4), (1, 5)), ), ), metadata_resolver=wrapper, ) )
def test_findall_with_metadata_wrapper(self) -> None: # Find all assignments in a tree code = """ a = 1 b = True def foo(bar: int) -> bool: return False """ module = cst.parse_module(dedent(code)) wrapper = meta.MetadataWrapper(module) # Test that when we find over a wrapper, we implicitly use it for # metadata as well as traversal. booleans = findall( wrapper, m.MatchMetadata(meta.ExpressionContextProvider, meta.ExpressionContext.STORE), ) self.assertNodeSequenceEqual( booleans, [ cst.Name("a"), cst.Name("b"), cst.Name("foo"), cst.Name("bar"), ], ) # Test that we can provide an explicit resolver and tree booleans = findall( wrapper.module, m.MatchMetadata(meta.ExpressionContextProvider, meta.ExpressionContext.STORE), metadata_resolver=wrapper, ) self.assertNodeSequenceEqual( booleans, [ cst.Name("a"), cst.Name("b"), cst.Name("foo"), cst.Name("bar"), ], ) # Test that failing to provide metadata leads to no match booleans = findall( wrapper.module, m.MatchMetadata(meta.ExpressionContextProvider, meta.ExpressionContext.STORE), ) self.assertNodeSequenceEqual(booleans, [])
def test_extract_metadata(self) -> None: # Verify true behavior module = cst.parse_module("a + b[c], d(e, f * g)") wrapper = cst.MetadataWrapper(module) expression = cst.ensure_type( cst.ensure_type(wrapper.module.body[0], cst.SimpleStatementLine).body[0], cst.Expr, ).value nodes = m.extract( expression, m.Tuple(elements=[ m.Element( m.BinaryOperation(left=m.Name(metadata=m.SaveMatchedNode( m.MatchMetadata( meta.PositionProvider, self._make_coderange((1, 0), (1, 1)), ), "left", )))), m.Element(m.Call()), ]), metadata_resolver=wrapper, ) extracted_node = cst.ensure_type( cst.ensure_type(expression, cst.Tuple).elements[0].value, cst.BinaryOperation, ).left self.assertEqual(nodes, {"left": extracted_node}) # Verify false behavior nodes = m.extract( expression, m.Tuple(elements=[ m.Element( m.BinaryOperation(left=m.Name(metadata=m.SaveMatchedNode( m.MatchMetadata( meta.PositionProvider, self._make_coderange((1, 0), (1, 2)), ), "left", )))), m.Element(m.Call()), ]), metadata_resolver=wrapper, ) self.assertIsNone(nodes)
class RemoveBarTransformer(VisitorBasedCodemodCommand): METADATA_DEPENDENCIES = (QualifiedNameProvider, ScopeProvider) @m.leave( m.SimpleStatementLine(body=[ m.Expr( m.Call(metadata=m.MatchMetadata( QualifiedNameProvider, { QualifiedName( source=QualifiedNameSource.IMPORT, name="foo.bar", ) }, ))) ])) def _leave_foo_bar( self, original_node: cst.SimpleStatementLine, updated_node: cst.SimpleStatementLine, ) -> cst.RemovalSentinel: RemoveImportsVisitor.remove_unused_import_by_node( self.context, original_node) return cst.RemoveFromParent()
def visit_Module(self, node: cst.Module) -> None: self.results = self.findall( node, m.MatchMetadata( meta.ExpressionContextProvider, meta.ExpressionContext.STORE ), )
def visit_Name(self, node: cst.Name) -> None: # Only match name nodes that are being assigned to. if self.matches( node, m.Name(metadata=m.MatchMetadata( meta.ExpressionContextProvider, meta.ExpressionContext.STORE)), ): self.match_names.add(node.value)
class TestTransformer(m.MatcherDecoratableTransformer): METADATA_DEPENDENCIES: Sequence[meta.ProviderT] = ( meta.ExpressionContextProvider, ) def __init__(self) -> None: super().__init__() self.match_names: Set[str] = set() @m.visit( m.Name(metadata=m.MatchMetadata(meta.ExpressionContextProvider, meta.ExpressionContext.STORE))) def _visit_assignments(self, node: cst.Name) -> None: # Only match name nodes that are being assigned to. self.match_names.add(node.value)
def test_predicate_logic_on_attributes(self) -> None: # Verify that we can or things together. matcher = m.BinaryOperation(left=m.Name(metadata=m.OneOf( m.MatchMetadata( meta.PositionProvider, self._make_coderange((1, 0), (1, 1)), ), m.MatchMetadata( meta.PositionProvider, self._make_coderange((1, 0), (1, 2)), ), ))) node, wrapper = self._make_fixture("a + b") self.assertTrue(matches(node, matcher, metadata_resolver=wrapper)) matcher = m.BinaryOperation(left=m.Integer(metadata=m.OneOf( m.MatchMetadata( meta.PositionProvider, self._make_coderange((1, 0), (1, 1)), ), m.MatchMetadata( meta.PositionProvider, self._make_coderange((1, 0), (1, 2)), ), ))) node, wrapper = self._make_fixture("12 + 3") self.assertTrue(matches(node, matcher, metadata_resolver=wrapper)) node, wrapper = self._make_fixture("123 + 4") self.assertFalse(matches(node, matcher, metadata_resolver=wrapper)) # Verify that we can and things together matcher = m.BinaryOperation(left=m.Name(metadata=m.AllOf( m.MatchMetadata( meta.PositionProvider, self._make_coderange((1, 0), (1, 1)), ), m.MatchMetadata(meta.ExpressionContextProvider, meta.ExpressionContext.LOAD), ))) node, wrapper = self._make_fixture("a + b") self.assertTrue(matches(node, matcher, metadata_resolver=wrapper)) node, wrapper = self._make_fixture("ab + cd") self.assertFalse(matches(node, matcher, metadata_resolver=wrapper)) # Verify that we can not things matcher = m.BinaryOperation(left=m.Name(metadata=m.DoesNotMatch( m.MatchMetadata(meta.ExpressionContextProvider, meta.ExpressionContext.STORE)))) node, wrapper = self._make_fixture("a + b") self.assertTrue(matches(node, matcher, metadata_resolver=wrapper))