Coverage for phml\nodes\position.py: 62%
26 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-30 09:38 -0600
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-30 09:38 -0600
1from __future__ import annotations
3from typing import TYPE_CHECKING, Optional
5if TYPE_CHECKING:
6 from .point import Point
9class Position:
10 """Position represents the location of a node in a source file.
12 The `start` field of `Position` represents the place of the first character
13 of the parsed source region. The `end` field of Position represents the place
14 of the first character after the parsed source region, whether it exists or not.
15 The value of the `start` and `end` fields implement the `Point` interface.
17 The `indent` field of `Position` represents the start column at each index
18 (plus start line) in the source region, for elements that span multiple lines.
20 If the syntactic unit represented by a node is not present in the source file at
21 the time of parsing, the node is said to be `generated` and it must not have positional
22 information.
23 """
25 def __init__(self, start: Point, end: Point, indent: Optional[int] = None):
26 self.start = start
27 self.end = end
29 if indent is not None and indent < 0:
30 raise IndexError(f"Position.indent value must be >= 0 or None but was {indent}")
32 self.indent = indent
34 def as_dict(self) -> dict:
35 return {
36 "start": {
37 "line": self.start.line,
38 "column": self.start.column,
39 "offset": self.start.offset,
40 },
41 "end": {
42 "line": self.end.line,
43 "column": self.end.column,
44 "offset": self.end.offset,
45 },
46 "indent": self.indent,
47 }
49 def __eq__(self, obj) -> bool:
50 if isinstance(obj, Position):
51 if self.start == obj.start:
52 if self.end == obj.end:
53 return True
54 else:
55 # print(f"{self.end} != {obj.end}: end values are not equal")
56 return False
57 else:
58 # print(f"{self.start} != {obj.start}: start values are not equal")
59 return False
60 # print(
61 # f"{type(self).__name__} != {type(obj).__name__}: {type(self).__name__} can not be equated to {type(obj).__name__}"
62 # )
63 return False
65 def __repr__(self) -> str:
66 indent = f" ~ {self.indent}" if self.indent is not None else ""
67 return f"<{self.start}-{self.end}{indent}>"
69 def __str__(self) -> str:
70 return repr(self)