Source code for coalib.results.SourceRange

from os.path import relpath

from coala_utils.decorators import enforce_signature, get_public_members
from coalib.results.SourcePosition import SourcePosition
from coalib.results.TextRange import TextRange
from coalib.results.AbsolutePosition import AbsolutePosition


[docs]class SourceRange(TextRange): @enforce_signature def __init__(self, start: SourcePosition, end: (SourcePosition, None)=None): """ Creates a new SourceRange. :param start: A SourcePosition indicating the start of the range. :param end: A SourcePosition indicating the end of the range. If ``None`` is given, the start object will be used here. end must be in the same file and be greater than start as negative ranges are not allowed. :raises TypeError: Raised when - start is not of type SourcePosition. - end is neither of type SourcePosition, nor is it None. :raises ValueError: Raised when file of start and end mismatch. """ TextRange.__init__(self, start, end) if self.start.file != self.end.file: raise ValueError('File of start and end position do not match.') @classmethod
[docs] def from_values(cls, file, start_line=None, start_column=None, end_line=None, end_column=None): start = SourcePosition(file, start_line, start_column) if end_line or (end_column and end_column > start_column): end = SourcePosition(file, end_line if end_line else start_line, end_column) else: end = None return cls(start, end)
@classmethod
[docs] def from_clang_range(cls, range): """ Creates a SourceRange from a clang SourceRange object. :param range: A cindex.SourceRange object. """ return cls.from_values(range.start.file.name, range.start.line, range.start.column, range.end.line, range.end.column)
@classmethod @enforce_signature
[docs] def from_absolute_position(cls, file: str, position_start: AbsolutePosition, position_end: (AbsolutePosition, None)=None): """ Creates a SourceRange from a start and end positions. :param file: Name of the file. :param position_start: Start of range given by AbsolutePosition. :param position_end: End of range given by AbsolutePosition or None. """ start = SourcePosition(file, position_start.line, position_start.column) end = None if position_end: end = SourcePosition(file, position_end.line, position_end.column) return cls(start, end)
@property def file(self): return self.start.file @enforce_signature
[docs] def renamed_file(self, file_diff_dict: dict): """ Retrieves the filename this source range refers to while taking the possible file renamings in the given file_diff_dict into account: :param file_diff_dict: A dictionary with filenames as key and their associated Diff objects as values. """ diff = file_diff_dict.get(self.file) if diff is None: return self.file return diff.rename if diff.rename is not False else self.file
[docs] def expand(self, file_contents): """ Passes a new SourceRange that covers the same area of a file as this one would. All values of None get replaced with absolute values. values of None will be interpreted as follows: self.start.line is None: -> 1 self.start.column is None: -> 1 self.end.line is None: -> last line of file self.end.column is None: -> last column of self.end.line :param file_contents: File contents of the applicable file :return: TextRange with absolute values """ tr = TextRange.expand(self, file_contents) return SourceRange.from_values(self.file, tr.start.line, tr.start.column, tr.end.line, tr.end.column)
def __json__(self, use_relpath=False): _dict = get_public_members(self) if use_relpath: _dict['file'] = relpath(_dict['file']) return _dict def __str__(self): """ Creates a string representation of the SourceRange object. If the whole file is affected, then just the filename is shown. >>> str(SourceRange.from_values('test_file', None, None, None, None)) '...test_file' If the whole line is affected, then just the filename with starting line number and ending line number is shown. >>> str(SourceRange.from_values('test_file', 1, None, 2, None)) '...test_file: L1 : L2' This is the general case where particular column and line are specified. It shows the starting line and column and ending line and column, with filename in the beginning. >>> str(SourceRange.from_values('test_file', 1, 1, 2, 1)) '...test_file: L1 C1 : L2 C1' """ if self.start.line is None and self.end.line is None: format_str = '{0.start.file}' elif self.start.column is None and self.end.column is None: format_str = '{0.start.file}: L{0.start.line} : L{0.end.line}' else: format_str = ('{0.start.file}: L{0.start.line} C{0.start.column}' + ' : L{0.end.line} C{0.end.column}') return format_str.format(self) def __contains__(self, item): return (super().__contains__(item) and self.start.file == item.start.file)