Refactor CodePosition

Renames `CodePosition` to `CodeRange` and stores start and end position
as a `CodePosition` dataclass to avoid the ambiguity of using tuples.
This commit is contained in:
Ray Zeng 2019-07-03 16:50:46 -07:00 committed by Benjamin Woodruff
parent d0ecb018e1
commit 39e4e433d8
38 changed files with 180 additions and 160 deletions

View file

@ -6,10 +6,10 @@
# pyre-strict
import libcst.nodes as cst
from libcst.metadata.base_provider import BaseMetadataProvider
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
class BasicPositionProvider(BaseMetadataProvider[CodePosition]):
class BasicPositionProvider(BaseMetadataProvider[CodeRange]):
"""
Generates basic line and column metadata. Basic position is
defined by the start and ending bounds of a node including all whitespace

View file

@ -21,7 +21,7 @@ from typing import (
from libcst._base_visitor import CSTVisitor
from libcst._removal_sentinel import RemovalSentinel
from libcst._type_enforce import is_value_of_type
from libcst.nodes._internal import CodegenState, CodePosition
from libcst.nodes._internal import CodegenState, CodePosition, CodeRange
if TYPE_CHECKING:
@ -251,10 +251,10 @@ class CSTNode(ABC):
...
def _codegen(self, state: CodegenState, **kwargs: Any) -> None:
start = (state.line, state.column)
start = CodePosition(state.line, state.column)
self._codegen_impl(state, **kwargs)
end = (state.line, state.column)
state.record_position(self, CodePosition(start, end))
end = CodePosition(state.line, state.column)
state.record_position(self, CodeRange(start, end))
def with_changes(self: _CSTNodeSelfT, **changes: Any) -> _CSTNodeSelfT:
"""

View file

@ -39,6 +39,7 @@ if TYPE_CHECKING:
_CSTNodeT = TypeVar("_CSTNodeT", bound="CSTNode")
_ProviderT = Union[Type["BasicPositionProvider"], Type["SyntacticPositionProvider"]]
_CodePositionT = Union[Tuple[int, int], "CodePosition"]
NEWLINE_RE: Pattern[str] = re.compile(r"\r\n?|\n")
@ -47,9 +48,19 @@ NEWLINE_RE: Pattern[str] = re.compile(r"\r\n?|\n")
@add_slots
@dataclass(frozen=True)
class CodePosition:
# start and end are each a tuple of (line, column) numbers
start: Tuple[int, int]
end: Tuple[int, int]
line: int
column: int
@add_slots
@dataclass(frozen=True)
class CodeRange:
start: CodePosition
end: CodePosition
@classmethod
def create(cls, start: Tuple[int, int], end: Tuple[int, int]) -> "CodeRange":
return CodeRange(CodePosition(start[0], start[1]), CodePosition(end[0], end[1]))
@add_slots
@ -100,7 +111,7 @@ class CodegenState:
# newline resets column back to 0, but a trailing token may shift column
self.column = len(segments[-1])
def record_position(self, node: _CSTNodeT, position: CodePosition) -> None:
def record_position(self, node: _CSTNodeT, position: CodeRange) -> None:
# Don't overwrite existing position information
# (i.e. semantic position has already been recorded)
if self.provider not in node.__metadata__:
@ -123,12 +134,12 @@ class SyntacticCodegenState(CodegenState):
@contextmanager
def record_syntactic_position(self, node: _CSTNodeT) -> Iterator[None]:
start = (self.line, self.column)
start = CodePosition(self.line, self.column)
try:
yield
finally:
end = (self.line, self.column)
node.__metadata__[self.provider] = CodePosition(start, end)
end = CodePosition(self.line, self.column)
node.__metadata__[self.provider] = CodeRange(start, end)
def visit_required(fieldname: str, node: _CSTNodeT, visitor: "CSTVisitor") -> _CSTNodeT:

View file

@ -13,7 +13,7 @@ from unittest.mock import patch
import libcst.nodes as cst
from libcst._base_visitor import CSTVisitor
from libcst.metadata.position_provider import SyntacticPositionProvider
from libcst.nodes._internal import CodegenState, CodePosition, visit_required
from libcst.nodes._internal import CodegenState, CodeRange, visit_required
from libcst.testing.utils import UnitTest
@ -59,7 +59,7 @@ class CSTNodeTest(UnitTest):
node: _CSTNodeT,
code: str,
parser: Optional[Callable[[str], _CSTNodeT]] = None,
expected_position: Optional[CodePosition] = None,
expected_position: Optional[CodeRange] = None,
) -> None:
node.validate_types_deep()
self.__assert_codegen(node, code, expected_position)
@ -87,7 +87,7 @@ class CSTNodeTest(UnitTest):
self,
node: cst.CSTNode,
expected: str,
expected_position: Optional[CodePosition] = None,
expected_position: Optional[CodeRange] = None,
) -> None:
"""
Verifies that the given node's `_codegen` method is correct.

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -49,7 +49,7 @@ class AssertConstructionTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)
@ -113,7 +113,7 @@ class AssertParsingTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(
node,

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -106,7 +106,7 @@ class AssignTest(CSTNodeTest):
node: cst.CSTNode,
code: str,
parser: Optional[Callable[[str], cst.CSTNode]],
position: Optional[CodePosition] = None,
position: Optional[CodeRange] = None,
) -> None:
self.validate_node(node, code, parser, expected_position=position)
@ -264,7 +264,7 @@ class AnnAssignTest(CSTNodeTest):
node: cst.CSTNode,
code: str,
parser: Optional[Callable[[str], cst.CSTNode]],
position: Optional[CodePosition] = None,
position: Optional[CodeRange] = None,
) -> None:
self.validate_node(node, code, parser, expected_position=position)
@ -373,6 +373,6 @@ class AugAssignTest(CSTNodeTest):
node: cst.CSTNode,
code: str,
parser: Optional[Callable[[str], cst.CSTNode]],
position: Optional[CodePosition] = None,
position: Optional[CodeRange] = None,
) -> None:
self.validate_node(node, code, parser, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_expression
from libcst.testing.utils import data_provider
@ -22,7 +22,7 @@ class AtomTest(CSTNodeTest):
(
cst.Name("test", lpar=(cst.LeftParen(),), rpar=(cst.RightParen(),)),
"(test)",
CodePosition((1, 1), (1, 5)),
CodeRange.create((1, 1), (1, 5)),
),
# Decimal integers
(cst.Number(cst.Integer("12345")), "12345"),
@ -47,7 +47,7 @@ class AtomTest(CSTNodeTest):
),
"(123)",
# TODO: fix numbers
# CodePosition((1, 1), (1, 4)),
# CodeRange.create((1, 1), (1, 4)),
),
# Non-exponent floats
(cst.Number(cst.Float("12345.")), "12345."),
@ -74,7 +74,7 @@ class AtomTest(CSTNodeTest):
),
"(123.4)",
# TODO: fix numbers
# CodePosition((1, 1), (1, 5)),
# CodeRange.create((1, 1), (1, 5)),
),
# Imaginary numbers
(cst.Number(cst.Imaginary("12345j")), "12345j"),
@ -90,7 +90,7 @@ class AtomTest(CSTNodeTest):
),
"(123.4j)",
# TODO: fix numbers
# CodePosition((1, 1), (1, 6)),
# CodeRange.create((1, 1), (1, 6)),
),
# Simple elipses
(cst.Ellipses(), "..."),
@ -98,7 +98,7 @@ class AtomTest(CSTNodeTest):
(
cst.Ellipses(lpar=(cst.LeftParen(),), rpar=(cst.RightParen(),)),
"(...)",
CodePosition((1, 1), (1, 4)),
CodeRange.create((1, 1), (1, 4)),
),
# Simple strings
(cst.SimpleString('""'), '""'),
@ -119,7 +119,7 @@ class AtomTest(CSTNodeTest):
'rb"test"', lpar=(cst.LeftParen(),), rpar=(cst.RightParen(),)
),
'(rb"test")',
CodePosition((1, 1), (1, 9)),
CodeRange.create((1, 1), (1, 9)),
),
# Empty formatted strings
(cst.FormattedString(start='f"', parts=(), end='"'), 'f""'),
@ -234,7 +234,7 @@ class AtomTest(CSTNodeTest):
rpar=(cst.RightParen(),),
),
'(f"")',
CodePosition((1, 1), (1, 4)),
CodeRange.create((1, 1), (1, 4)),
),
# Concatenated strings
(
@ -263,12 +263,12 @@ class AtomTest(CSTNodeTest):
rpar=(cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),),
),
'( "ab" "c" )',
CodePosition((1, 2), (1, 10)),
CodeRange.create((1, 2), (1, 10)),
),
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
# We don't have sentinel nodes for atoms, so we know that 100% of atoms
# can be parsed identically to their creation.
@ -282,12 +282,12 @@ class AtomTest(CSTNodeTest):
format_spec=(cst.FormattedStringText("%B %d, %Y"),),
),
"{today:%B %d, %Y}",
CodePosition((1, 0), (1, 17)),
CodeRange.create((1, 0), (1, 17)),
),
)
)
def test_valid_no_parse(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
# Test some nodes that aren't valid source code by themselves
self.validate_node(node, code, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_expression
from libcst.testing.utils import data_provider
@ -20,7 +20,7 @@ class AttributeTest(CSTNodeTest):
(
cst.Attribute(cst.Name("foo"), cst.Name("bar")),
"foo.bar",
CodePosition((1, 0), (1, 7)),
CodeRange.create((1, 0), (1, 7)),
),
# Parenthesized attribute access
(
@ -31,7 +31,7 @@ class AttributeTest(CSTNodeTest):
rpar=(cst.RightParen(),),
),
"(foo.bar)",
CodePosition((1, 1), (1, 8)),
CodeRange.create((1, 1), (1, 8)),
),
# Make sure that spacing works
(
@ -46,12 +46,12 @@ class AttributeTest(CSTNodeTest):
rpar=(cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),),
),
"( foo . bar )",
CodePosition((1, 2), (1, 11)),
CodeRange.create((1, 2), (1, 11)),
),
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, parse_expression, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_expression
from libcst.testing.utils import data_provider
@ -28,12 +28,12 @@ class AwaitTest(CSTNodeTest):
rpar=(cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),),
),
"( await test )",
CodePosition((1, 2), (1, 13)),
CodeRange.create((1, 2), (1, 13)),
),
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
# We don't have sentinel nodes for atoms, so we know that 100% of atoms
# can be parsed identically to their creation.

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_expression
from libcst.testing.utils import data_provider
@ -107,12 +107,12 @@ class BinaryOperationTest(CSTNodeTest):
rpar=(cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),),
),
"( foo * bar )",
CodePosition((1, 2), (1, 13)),
CodeRange.create((1, 2), (1, 13)),
),
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, parse_expression, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_expression
from libcst.testing.utils import data_provider
@ -50,7 +50,7 @@ class BooleanOperationTest(CSTNodeTest):
),
),
"(foo)or(bar)",
CodePosition((1, 0), (1, 12)),
CodeRange.create((1, 0), (1, 12)),
),
# Make sure that spacing works
(
@ -69,7 +69,7 @@ class BooleanOperationTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, parse_expression, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_expression
from libcst.testing.utils import data_provider
@ -424,7 +424,7 @@ class CallTest(CSTNodeTest):
),
"( foo ( pos1 , * list1, kw1=1, ** dict1 ) )",
parse_expression,
CodePosition((1, 2), (1, 43)),
CodeRange.create((1, 2), (1, 43)),
),
# Test args
(
@ -437,7 +437,7 @@ class CallTest(CSTNodeTest):
),
"* list1, ",
None,
CodePosition((1, 0), (1, 8)),
CodeRange.create((1, 0), (1, 8)),
),
)
)
@ -446,7 +446,7 @@ class CallTest(CSTNodeTest):
node: cst.CSTNode,
code: str,
parser: Optional[Callable[[str], cst.CSTNode]],
position: Optional[CodePosition] = None,
position: Optional[CodeRange] = None,
) -> None:
self.validate_node(node, code, parser, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -107,7 +107,7 @@ class ClassDefCreationTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)
@ -327,6 +327,6 @@ class ClassDefParserTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, parse_statement, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_expression
from libcst.testing.utils import data_provider
@ -153,7 +153,7 @@ class ComparisonTest(CSTNodeTest):
),
),
"baz == (foo not in bar)",
CodePosition((1, 0), (1, 23)),
CodeRange.create((1, 0), (1, 23)),
),
(
cst.Comparison(
@ -168,12 +168,12 @@ class ComparisonTest(CSTNodeTest):
),
),
"a > b > c",
CodePosition((1, 0), (1, 9)),
CodeRange.create((1, 0), (1, 9)),
),
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, parse_expression, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -50,7 +50,7 @@ class DelTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, parse_statement, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.testing.utils import data_provider
@ -26,6 +26,6 @@ class ElseTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest, DummyIndentedBlock
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -133,7 +133,7 @@ class ForTest(CSTNodeTest):
node: cst.CSTNode,
code: str,
parser: Optional[Callable[[str], cst.CSTNode]],
position: Optional[CodePosition] = None,
position: Optional[CodeRange] = None,
) -> None:
self.validate_node(node, code, parser, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest, DummyIndentedBlock
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -521,7 +521,7 @@ class FunctionDefCreationTest(CSTNodeTest):
),
),
"@ bar ( )\n",
# CodePosition((1,0), (1,10))
# CodeRange.create((1,0), (1,10))
),
(
cst.Annotation(
@ -531,7 +531,7 @@ class FunctionDefCreationTest(CSTNodeTest):
annotation=cst.Name("str"),
),
" : str",
CodePosition((1, 5), (1, 8)),
CodeRange.create((1, 5), (1, 8)),
),
# Parameters
(
@ -566,14 +566,14 @@ class FunctionDefCreationTest(CSTNodeTest):
),
),
'first, second, third = 1.0, fourth = 1.5, *params: str, bar: str = "one", baz: int, biz: str = "two"',
CodePosition((1, 0), (1, 100)),
CodeRange.create((1, 0), (1, 100)),
),
(
cst.Param(
cst.Name("third"), star="", default=cst.Number(cst.Float("1.0"))
),
"third = 1.0",
CodePosition((1, 0), (1, 5)),
CodeRange.create((1, 0), (1, 5)),
),
(
cst.Param(
@ -582,12 +582,12 @@ class FunctionDefCreationTest(CSTNodeTest):
whitespace_after_star=cst.SimpleWhitespace(" "),
),
"* third",
CodePosition((1, 0), (1, 7)),
CodeRange.create((1, 0), (1, 7)),
),
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)
@ -1693,6 +1693,6 @@ class FunctionDefParserTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, parse_statement, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -43,7 +43,7 @@ class GlobalConstructionTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)
@ -126,7 +126,7 @@ class GlobalParsingTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(
node,

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest, DummyIndentedBlock
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -125,6 +125,6 @@ class IfTest(CSTNodeTest):
node: cst.CSTNode,
code: str,
parser: Optional[Callable[[str], cst.CSTNode]],
position: Optional[CodePosition] = None,
position: Optional[CodeRange] = None,
) -> None:
self.validate_node(node, code, parser, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_expression
from libcst.testing.utils import data_provider
@ -51,7 +51,7 @@ class IfExpTest(CSTNodeTest):
),
),
"(foo)if(bar)else(baz)",
CodePosition((1, 0), (1, 21)),
CodeRange.create((1, 0), (1, 21)),
),
# Make sure that spacing works
(
@ -67,12 +67,12 @@ class IfExpTest(CSTNodeTest):
rpar=(cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),),
),
"( foo if bar else baz )",
CodePosition((1, 2), (1, 25)),
CodeRange.create((1, 2), (1, 25)),
),
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, parse_expression, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -140,7 +140,7 @@ class ImportCreateTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)
@ -329,7 +329,7 @@ class ImportParseTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(
node,
@ -476,7 +476,7 @@ class ImportFromCreateTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)
@ -696,7 +696,7 @@ class ImportFromParseTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(
node,

View file

@ -11,7 +11,12 @@ from libcst.metadata.position_provider import (
BasicPositionProvider,
SyntacticPositionProvider,
)
from libcst.nodes._internal import CodegenState, CodePosition, SyntacticCodegenState
from libcst.nodes._internal import (
CodegenState,
CodePosition,
CodeRange,
SyntacticCodegenState,
)
from libcst.testing.utils import UnitTest
@ -61,17 +66,17 @@ class InternalTest(UnitTest):
# simulate codegen behavior for the dummy node
# generates the code " pass "
state = CodegenState(" " * 4, "\n")
start = (state.line, state.column)
start = CodePosition(state.line, state.column)
state.add_token(" ")
with state.record_syntactic_position(node):
state.add_token("pass")
state.add_token(" ")
end = (state.line, state.column)
state.record_position(node, CodePosition(start, end))
end = CodePosition(state.line, state.column)
state.record_position(node, CodeRange(start, end))
# check syntactic whitespace is correctly recorded
self.assertEqual(
node.__metadata__[BasicPositionProvider], CodePosition((1, 0), (1, 6))
node.__metadata__[BasicPositionProvider], CodeRange.create((1, 0), (1, 6))
)
def test_semantic_position(self) -> None:
@ -81,15 +86,16 @@ class InternalTest(UnitTest):
# simulate codegen behavior for the dummy node
# generates the code " pass "
state = SyntacticCodegenState(" " * 4, "\n")
start = (state.line, state.column)
start = CodePosition(state.line, state.column)
state.add_token(" ")
with state.record_syntactic_position(node):
state.add_token("pass")
state.add_token(" ")
end = (state.line, state.column)
state.record_position(node, CodePosition(start, end))
end = CodePosition(state.line, state.column)
state.record_position(node, CodeRange(start, end))
# check semantic whitespace is correctly recorded (ignoring whitespace)
self.assertEqual(
node.__metadata__[SyntacticPositionProvider], CodePosition((1, 1), (1, 5))
node.__metadata__[SyntacticPositionProvider],
CodeRange.create((1, 1), (1, 5)),
)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_expression
from libcst.testing.utils import data_provider
@ -152,7 +152,7 @@ class LambdaCreationTest(CSTNodeTest):
cst.Number(cst.Integer("5")),
),
'lambda first, second, third = 1.0, fourth = 1.5, *, bar = "one", baz, biz = "two": 5',
CodePosition((1, 0), (1, 84)),
CodeRange.create((1, 0), (1, 84)),
),
# Test star_arg
(
@ -242,12 +242,12 @@ class LambdaCreationTest(CSTNodeTest):
rpar=(cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),),
),
"( lambda : 5 )",
CodePosition((1, 2), (1, 13)),
CodeRange.create((1, 2), (1, 13)),
),
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)
@ -927,6 +927,6 @@ class LambdaParserTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, parse_expression, position)

View file

@ -8,7 +8,7 @@ from typing import Tuple, cast
import libcst.nodes as cst
from libcst.metadata.position_provider import SyntacticPositionProvider
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_module
from libcst.testing.utils import data_provider
@ -119,23 +119,26 @@ class ModuleTest(CSTNodeTest):
@data_provider(
{
"empty": {"code": "", "expected": CodePosition((1, 0), (1, 0))},
"empty": {"code": "", "expected": CodeRange.create((1, 0), (1, 0))},
"empty_with_newline": {
"code": "\n",
"expected": CodePosition((1, 0), (2, 0)),
"expected": CodeRange.create((1, 0), (2, 0)),
},
"empty_program_with_comments": {
"code": "# 2345",
"expected": CodePosition((1, 0), (2, 0)),
"expected": CodeRange.create((1, 0), (2, 0)),
},
"simple_pass": {
"code": "pass\n",
"expected": CodeRange.create((1, 0), (2, 0)),
},
"simple_pass": {"code": "pass\n", "expected": CodePosition((1, 0), (2, 0))},
"simple_pass_with_header_footer": {
"code": "# header\npass # trailing\n# footer\n",
"expected": CodePosition((1, 0), (4, 0)),
"expected": CodeRange.create((1, 0), (4, 0)),
},
}
)
def test_module_position(self, *, code: str, expected: CodePosition) -> None:
def test_module_position(self, *, code: str, expected: CodeRange) -> None:
module = parse_module(code)
module.code
@ -145,7 +148,7 @@ class ModuleTest(CSTNodeTest):
self, node: cst.CSTNode, start: Tuple[int, int], end: Tuple[int, int]
) -> None:
self.assertEqual(
node.__metadata__[SyntacticPositionProvider], CodePosition(start, end)
node.__metadata__[SyntacticPositionProvider], CodeRange.create(start, end)
)
def test_function_position(self) -> None:

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -45,7 +45,7 @@ class NonlocalConstructionTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)
@ -128,7 +128,7 @@ class NonlocalParsingTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(
node,

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_expression
from libcst.testing.utils import data_provider
@ -23,7 +23,7 @@ class NumberTest(CSTNodeTest):
cst.Number(operator=cst.Minus(), number=cst.Integer("5")),
"-5",
parse_expression,
CodePosition((1, 0), (1, 2)),
CodeRange.create((1, 0), (1, 2)),
),
# In parenthesis
(
@ -35,7 +35,7 @@ class NumberTest(CSTNodeTest):
),
"(-5)",
parse_expression,
CodePosition((1, 1), (1, 3)),
CodeRange.create((1, 1), (1, 3)),
),
(
cst.Number(
@ -48,7 +48,7 @@ class NumberTest(CSTNodeTest):
),
"(-(5))",
parse_expression,
CodePosition((1, 1), (1, 5)),
CodeRange.create((1, 1), (1, 5)),
),
(
cst.UnaryOperation(
@ -59,7 +59,7 @@ class NumberTest(CSTNodeTest):
),
"--5",
parse_expression,
CodePosition((1, 0), (1, 3)),
CodeRange.create((1, 0), (1, 3)),
),
# TODO: add test cases for "((5))" and "(+((5)))"
)
@ -69,7 +69,7 @@ class NumberTest(CSTNodeTest):
node: cst.CSTNode,
code: str,
parser: Optional[Callable[[str], cst.CSTNode]],
position: Optional[CodePosition] = None,
position: Optional[CodeRange] = None,
) -> None:
self.validate_node(node, code, parser, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -70,7 +70,7 @@ class RaiseConstructionTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)
@ -190,7 +190,7 @@ class RaiseParsingTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(
node,

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -21,7 +21,7 @@ class ReturnCreateTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)
@ -100,6 +100,6 @@ class ReturnParseTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, parse_statement, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest, DummyIndentedBlock
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -348,7 +348,7 @@ class SimpleStatementTest(CSTNodeTest):
node: cst.CSTNode,
code: str,
parser: Optional[Callable[[str], cst.CSTNode]],
position: Optional[CodePosition] = None,
position: Optional[CodeRange] = None,
) -> None:
self.validate_node(node, code, parser, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.testing.utils import data_provider
@ -72,6 +72,6 @@ class SmallStatementTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_expression
from libcst.testing.utils import data_provider
@ -51,7 +51,7 @@ class SubscriptTest(CSTNodeTest):
),
"foo[1:2:3, 5]",
False,
CodePosition((1, 0), (1, 13)),
CodeRange.create((1, 0), (1, 13)),
),
# Test parsing of subscript with slice/extslice.
(
@ -137,7 +137,7 @@ class SubscriptTest(CSTNodeTest):
),
"foo[::3]",
False,
CodePosition((1, 0), (1, 8)),
CodeRange.create((1, 0), (1, 8)),
),
# Some more wild slice parsings
(
@ -320,20 +320,20 @@ class SubscriptTest(CSTNodeTest):
),
"( foo [ 1 : 2 : 3 , 5 ] )",
True,
CodePosition((1, 2), (1, 24)),
CodeRange.create((1, 2), (1, 24)),
),
# Test Index, Slice, ExtSlice
(
cst.Index(cst.Number(cst.Integer("5"))),
"5",
False,
CodePosition((1, 0), (1, 1)),
CodeRange.create((1, 0), (1, 1)),
),
(
cst.Slice(lower=None, upper=None, second_colon=cst.Colon(), step=None),
"::",
False,
CodePosition((1, 0), (1, 2)),
CodeRange.create((1, 0), (1, 2)),
),
(
cst.ExtSlice(
@ -357,7 +357,7 @@ class SubscriptTest(CSTNodeTest):
),
"1 : 2 : 3 , ",
False,
CodePosition((1, 0), (1, 9)),
CodeRange.create((1, 0), (1, 9)),
),
)
)
@ -366,7 +366,7 @@ class SubscriptTest(CSTNodeTest):
node: cst.CSTNode,
code: str,
check_parsing: bool,
position: Optional[CodePosition] = None,
position: Optional[CodeRange] = None,
) -> None:
if check_parsing:
self.validate_node(node, code, parse_expression, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest, DummyIndentedBlock
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -279,7 +279,7 @@ class TryTest(CSTNodeTest):
node: cst.CSTNode,
code: str,
parser: Optional[Callable[[str], cst.CSTNode]],
position: Optional[CodePosition] = None,
position: Optional[CodeRange] = None,
) -> None:
self.validate_node(node, code, parser, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.testing.utils import data_provider
@ -68,7 +68,7 @@ class TupleTest(CSTNodeTest):
]
),
"(one, *two,)",
CodePosition((1, 1), (1, 11)),
CodeRange.create((1, 1), (1, 11)),
),
# custom parenthesis on StarredElement
(
@ -82,7 +82,7 @@ class TupleTest(CSTNodeTest):
]
),
"((*abc),)",
CodePosition((1, 1), (1, 8)),
CodeRange.create((1, 1), (1, 8)),
),
# custom whitespace on Element
(
@ -97,7 +97,7 @@ class TupleTest(CSTNodeTest):
rpar=[], # rpar can't own the trailing whitespace if it's not there
),
"one, two ",
CodePosition((1, 0), (1, 10)),
CodeRange.create((1, 0), (1, 10)),
),
# custom whitespace on StarredElement
(
@ -116,7 +116,7 @@ class TupleTest(CSTNodeTest):
rpar=[], # rpar can't own the trailing whitespace if it's not there
),
"one, (* two) ",
CodePosition((1, 0), (1, 17)),
CodeRange.create((1, 0), (1, 17)),
),
# missing spaces around tuple, okay with parenthesis
(
@ -172,7 +172,7 @@ class TupleTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_expression
from libcst.testing.utils import data_provider
@ -30,7 +30,7 @@ class UnaryOperationTest(CSTNodeTest):
rpar=(cst.RightParen(),),
),
"(not foo)",
CodePosition((1, 1), (1, 8)),
CodeRange.create((1, 1), (1, 8)),
),
(
cst.UnaryOperation(
@ -40,7 +40,7 @@ class UnaryOperationTest(CSTNodeTest):
),
),
"not(foo)",
CodePosition((1, 0), (1, 8)),
CodeRange.create((1, 0), (1, 8)),
),
# Make sure that spacing works
(
@ -51,12 +51,12 @@ class UnaryOperationTest(CSTNodeTest):
rpar=(cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),),
),
"( not foo )",
CodePosition((1, 2), (1, 10)),
CodeRange.create((1, 2), (1, 10)),
),
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, parse_expression, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest, DummyIndentedBlock
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -119,7 +119,7 @@ class WhileTest(CSTNodeTest):
node: cst.CSTNode,
code: str,
parser: Optional[Callable[[str], cst.CSTNode]],
position: Optional[CodePosition] = None,
position: Optional[CodeRange] = None,
) -> None:
self.validate_node(node, code, parser, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest, DummyIndentedBlock
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -156,7 +156,7 @@ class WithTest(CSTNodeTest):
node: cst.CSTNode,
code: str,
parser: Optional[Callable[[str], cst.CSTNode]],
position: Optional[CodePosition] = None,
position: Optional[CodeRange] = None,
) -> None:
self.validate_node(node, code, parser, expected_position=position)

View file

@ -7,7 +7,7 @@
from typing import Callable, Optional
import libcst.nodes as cst
from libcst.nodes._internal import CodePosition
from libcst.nodes._internal import CodeRange
from libcst.nodes.tests.base import CSTNodeTest
from libcst.parser import parse_statement
from libcst.testing.utils import data_provider
@ -38,7 +38,7 @@ class YieldConstructionTest(CSTNodeTest):
whitespace_after_yield=cst.SimpleWhitespace(""),
),
"yield(a)",
CodePosition((1, 0), (1, 8)),
CodeRange.create((1, 0), (1, 8)),
),
(
cst.Yield(
@ -74,7 +74,7 @@ class YieldConstructionTest(CSTNodeTest):
rpar=(cst.RightParen(whitespace_before=cst.SimpleWhitespace(" ")),),
),
"( yield from bla() )",
CodePosition((1, 2), (1, 20)),
CodeRange.create((1, 2), (1, 20)),
),
# From expression position tests
(
@ -83,12 +83,12 @@ class YieldConstructionTest(CSTNodeTest):
whitespace_after_from=cst.SimpleWhitespace(" "),
),
"from 5",
CodePosition((1, 0), (1, 6)),
CodeRange.create((1, 0), (1, 6)),
),
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
self.validate_node(node, code, expected_position=position)
@ -215,7 +215,7 @@ class YieldParsingTest(CSTNodeTest):
)
)
def test_valid(
self, node: cst.CSTNode, code: str, position: Optional[CodePosition] = None
self, node: cst.CSTNode, code: str, position: Optional[CodeRange] = None
) -> None:
# pyre-fixme[16]: `BaseSuite` has no attribute `__getitem__`.
self.validate_node(node, code, lambda code: parse_statement(code).body[0].value)