diff --git a/libcst/_position.py b/libcst/_position.py index d7ba0d07..67923dc5 100644 --- a/libcst/_position.py +++ b/libcst/_position.py @@ -56,3 +56,14 @@ def __init__(self, start: _CodePositionT, end: _CodePositionT) -> None: end = cast(CodePosition, end) object.__setattr__(self, "start", start) object.__setattr__(self, "end", end) + + def __contains__(self, pos: _CodePositionT, /) -> bool: + if isinstance(pos, tuple): + line, column = pos + else: + line, column = pos.line, pos.column + + return ( + self.start.line <= line <= self.end.line + and self.start.column <= column <= self.end.column + ) diff --git a/libcst/tests/test_position.py b/libcst/tests/test_position.py new file mode 100644 index 00000000..af462159 --- /dev/null +++ b/libcst/tests/test_position.py @@ -0,0 +1,29 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from libcst._position import _CodePositionT, CodePosition, CodeRange +from libcst.testing.utils import data_provider, UnitTest + + +code_range = CodeRange((1, 2), (4, 5)) + + +class PositionTest(UnitTest): + @data_provider( + [ + (CodePosition(1, 2), True), + ((1, 2), True), + (CodePosition(3, 3), True), + ((3, 3), True), + (CodePosition(2, 1), False), + ((2, 1), True), + (CodePosition(5, 4), False), + ((5, 4), False), + ] + ) + def test_code_range_contains( + self, position: _CodePositionT, expected: bool + ) -> None: + self.assertEqual(position in code_range, expected)