Completed
Pull Request — master (#2062)
by Lasse
02:09
created

SourceRange.from_values()   B

Complexity

Conditions 5

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
c 1
b 0
f 0
dl 0
loc 15
rs 8.5454
1
from os.path import relpath
2
3
from coalib.misc.Decorators import enforce_signature, get_public_members
4
from coalib.results.SourcePosition import SourcePosition
5
from coalib.results.TextRange import TextRange
6
from coalib.results.AbsolutePosition import AbsolutePosition
7
8
9
class SourceRange(TextRange):
10
11
    @enforce_signature
12
    def __init__(self,
13
                 start: SourcePosition,
14
                 end: (SourcePosition, None)=None):
15
        """
16
        Creates a new SourceRange.
17
18
        :param start:       A SourcePosition indicating the start of the range.
19
        :param end:         A SourcePosition indicating the end of the range.
20
                            If ``None`` is given, the start object will be used
21
                            here. end must be in the same file and be greater
22
                            than start as negative ranges are not allowed.
23
        :raises TypeError:  Raised when
24
                            - start is no SourcePosition or None.
25
                            - end is no SourcePosition.
26
        :raises ValueError: Raised when file of start and end mismatch.
27
        """
28
        TextRange.__init__(self, start, end)
29
30
        if self.start.file != self.end.file:
31
            raise ValueError("File of start and end position do not match.")
32
33
    @classmethod
34
    def from_values(cls,
35
                    file,
36
                    start_line=None,
37
                    start_column=None,
38
                    end_line=None,
39
                    end_column=None):
40
        start = SourcePosition(file, start_line, start_column)
41
        if end_line or (end_column and end_column > start_column):
42
            end = SourcePosition(file, end_line if end_line else start_line,
43
                                 end_column)
44
        else:
45
            end = None
46
47
        return cls(start, end)
48
49
    @classmethod
50
    def from_clang_range(cls, range):
51
        """
52
        Creates a SourceRange from a clang SourceRange object.
53
54
        :param range: A cindex.SourceRange object.
55
        """
56
        return cls.from_values(range.start.file.name,
57
                               range.start.line,
58
                               range.start.column,
59
                               range.end.line,
60
                               range.end.column)
61
62
    @classmethod
63
    @enforce_signature
64
    def from_absolute_position(cls,
65
                               file: str,
66
                               position_start: AbsolutePosition,
67
                               position_end: (AbsolutePosition, None)=None):
68
        """
69
        Creates a SourceRange from a start and end positions.
70
71
        :param file:           Name of the file.
72
        :param position_start: Start of range given by AbsolutePosition.
73
        :param position_end:   End of range given by AbsolutePosition or None.
74
        """
75
        start = SourcePosition(file, position_start.line, position_start.column)
76
        end = None
77
        if position_end:
78
            end = SourcePosition(file, position_end.line, position_end.column)
79
        return cls(start, end)
80
81
    @property
82
    def file(self):
83
        return self.start.file
84
85
    def expand(self, file_contents):
86
        """
87
        Passes a new SourceRange that covers the same area of a file as this
88
        one would. All values of None get replaced with absolute values.
89
90
        values of None will be interpreted as follows:
91
        self.start.line is None:   -> 1
92
        self.start.column is None: -> 1
93
        self.end.line is None:     -> last line of file
94
        self.end.column is None:   -> last column of self.end.line
95
96
        :param file_contents: File contents of the applicable file
97
        :return:              TextRange with absolute values
98
        """
99
        tr = TextRange.expand(self, file_contents)
100
101
        return SourceRange.from_values(self.file,
102
                                       tr.start.line,
103
                                       tr.start.column,
104
                                       tr.end.line,
105
                                       tr.end.column)
106
107
    def __json__(self, use_relpath=False):
108
        _dict = get_public_members(self)
109
        if use_relpath:
110
            _dict['file'] = relpath(_dict['file'])
111
        return _dict
112