Coverage for src / renaissance / syntax_tree / text_segment.py: 100%
21 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-09-09 14:04 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-09-09 14:04 +0000
1"""Protocol defining a text segment: a consecutive piece of text within a larger text."""
3from typing import Protocol, runtime_checkable
6@runtime_checkable
7class TextSegment(Protocol):
8 """Protocol for anything that represents a text segment.
10 A text segment is a consecutive piece, a.k.a. a slice, within a text.
11 Instances include comments, whitespace (incl. empty lines), and syntax nodes.
13 Read-only access is enforced "as much as possible" by
14 exposing only @property getters in the protocol.
16 A concrete implementation of this protocol can make some of the properties lazy by using
17 functools.cached_property or manual memoized attributes,
18 such that it only triggers computation the first time it's needed.
19 For example, start_line and start_column can be computed from start_offset and full_text,
20 but only when they are first accessed.
21 Furthermore, a concrete implementation can also make a line-start-offset table once per document
22 and reuse it for every node in that document,
23 turning each node's line/column lookup into an O(log lines) binary search.
24 """
26 @property
27 def full_text(self) -> str:
28 """The full text that contains the text segment."""
29 ...
31 @property
32 def location(self) -> str:
33 """The location of the full text that contains the text segment.
35 For example, when text originates from disk the location is a file path.
36 """
37 ...
39 @property
40 def start_offset(self) -> int:
41 """Start offset of text segment.
43 start_offset is an integer in [0, len(full_text)].
44 """
45 ...
47 @property
48 def start_line(self) -> int:
49 """Start line of text segment - 0 based."""
50 ...
52 @property
53 def start_column(self) -> int:
54 """Start column of text segment - 0 based."""
55 ...
57 @property
58 def end_offset(self) -> int:
59 """Exclusive end offset of text segment.
61 end_offset is an integer in [0, len(full_text)].
62 """
63 ...
65 @property
66 def end_line(self) -> int:
67 """End line of text segment - 0 based."""
68 ...
70 @property
71 def end_column(self) -> int:
72 """End column of text segment - 0 based."""
73 ...
75 @property
76 def text_segment(self) -> str:
77 """The text segment is a slice of the full text.
79 The text segment is represented by the half-open interval [self.start_offset, self.end_offset).
81 The returned text segment is equal to self.full_text[self.start_offset:self.end_offset].
82 """
83 ...