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

1from __future__ import annotations 

2 

3from typing import TYPE_CHECKING, Optional 

4 

5if TYPE_CHECKING: 

6 from .point import Point 

7 

8 

9class Position: 

10 """Position represents the location of a node in a source file. 

11 

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. 

16 

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. 

19 

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 """ 

24 

25 def __init__(self, start: Point, end: Point, indent: Optional[int] = None): 

26 self.start = start 

27 self.end = end 

28 

29 if indent is not None and indent < 0: 

30 raise IndexError(f"Position.indent value must be >= 0 or None but was {indent}") 

31 

32 self.indent = indent 

33 

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 } 

48 

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 

64 

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}>" 

68 

69 def __str__(self) -> str: 

70 return repr(self)