Completed
Pull Request — master (#2132)
by Udayan
01:51
created

SourceRange.renamed_file()   A

Complexity

Conditions 3

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 3
dl 0
loc 14
rs 9.4285
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
    @enforce_signature
86
    def renamed_file(self, file_diff_dict: dict):
87
        """
88
        Retrieves the filename this source range refers to while taking the
89
        possible file renamings in the given file_diff_dict into account:
90
91
        :param file_diff_dict: A dictionary with filenames as key and their
92
                               associated Diff objects as values.
93
        """
94
        diff = file_diff_dict.get(self.file)
95
        if diff is None:
96
            return self.file
97
98
        return diff.rename if diff.rename is not False else self.file
99
100
    def expand(self, file_contents):
101
        """
102
        Passes a new SourceRange that covers the same area of a file as this
103
        one would. All values of None get replaced with absolute values.
104
105
        values of None will be interpreted as follows:
106
        self.start.line is None:   -> 1
107
        self.start.column is None: -> 1
108
        self.end.line is None:     -> last line of file
109
        self.end.column is None:   -> last column of self.end.line
110
111
        :param file_contents: File contents of the applicable file
112
        :return:              TextRange with absolute values
113
        """
114
        tr = TextRange.expand(self, file_contents)
115
116
        return SourceRange.from_values(self.file,
117
                                       tr.start.line,
118
                                       tr.start.column,
119
                                       tr.end.line,
120
                                       tr.end.column)
121
122
    def __json__(self, use_relpath=False):
123
        _dict = get_public_members(self)
124
        if use_relpath:
125
            _dict['file'] = relpath(_dict['file'])
126
        return _dict
127