Completed
Push — master ( 42cdfe...147541 )
by
unknown
02:00
created

SourceRange.__contains__()   A

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 1
c 1
b 0
f 1
dl 0
loc 3
rs 10
1
from os.path import relpath
2
3
from coala_utils.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 not of type SourcePosition.
25
                            - end is neither of type SourcePosition, nor is it
26
                              None.
27
        :raises ValueError: Raised when file of start and end mismatch.
28
        """
29
        TextRange.__init__(self, start, end)
30
31
        if self.start.file != self.end.file:
32
            raise ValueError("File of start and end position do not match.")
33
34
    @classmethod
35
    def from_values(cls,
36
                    file,
37
                    start_line=None,
38
                    start_column=None,
39
                    end_line=None,
40
                    end_column=None):
41
        start = SourcePosition(file, start_line, start_column)
42
        if end_line or (end_column and end_column > start_column):
43
            end = SourcePosition(file, end_line if end_line else start_line,
44
                                 end_column)
45
        else:
46
            end = None
47
48
        return cls(start, end)
49
50
    @classmethod
51
    def from_clang_range(cls, range):
52
        """
53
        Creates a SourceRange from a clang SourceRange object.
54
55
        :param range: A cindex.SourceRange object.
56
        """
57
        return cls.from_values(range.start.file.name,
58
                               range.start.line,
59
                               range.start.column,
60
                               range.end.line,
61
                               range.end.column)
62
63
    @classmethod
64
    @enforce_signature
65
    def from_absolute_position(cls,
66
                               file: str,
67
                               position_start: AbsolutePosition,
68
                               position_end: (AbsolutePosition, None)=None):
69
        """
70
        Creates a SourceRange from a start and end positions.
71
72
        :param file:           Name of the file.
73
        :param position_start: Start of range given by AbsolutePosition.
74
        :param position_end:   End of range given by AbsolutePosition or None.
75
        """
76
        start = SourcePosition(file, position_start.line, position_start.column)
77
        end = None
78
        if position_end:
79
            end = SourcePosition(file, position_end.line, position_end.column)
80
        return cls(start, end)
81
82
    @property
83
    def file(self):
84
        return self.start.file
85
86
    @enforce_signature
87
    def renamed_file(self, file_diff_dict: dict):
88
        """
89
        Retrieves the filename this source range refers to while taking the
90
        possible file renamings in the given file_diff_dict into account:
91
92
        :param file_diff_dict: A dictionary with filenames as key and their
93
                               associated Diff objects as values.
94
        """
95
        diff = file_diff_dict.get(self.file)
96
        if diff is None:
97
            return self.file
98
99
        return diff.rename if diff.rename is not False else self.file
100
101
    def expand(self, file_contents):
102
        """
103
        Passes a new SourceRange that covers the same area of a file as this
104
        one would. All values of None get replaced with absolute values.
105
106
        values of None will be interpreted as follows:
107
        self.start.line is None:   -> 1
108
        self.start.column is None: -> 1
109
        self.end.line is None:     -> last line of file
110
        self.end.column is None:   -> last column of self.end.line
111
112
        :param file_contents: File contents of the applicable file
113
        :return:              TextRange with absolute values
114
        """
115
        tr = TextRange.expand(self, file_contents)
116
117
        return SourceRange.from_values(self.file,
118
                                       tr.start.line,
119
                                       tr.start.column,
120
                                       tr.end.line,
121
                                       tr.end.column)
122
123
    def __json__(self, use_relpath=False):
124
        _dict = get_public_members(self)
125
        if use_relpath:
126
            _dict['file'] = relpath(_dict['file'])
127
        return _dict
128
129
    def __contains__(self, item):
130
        return (super().__contains__(item) and
131
                self.start.file == item.start.file)
132