Completed
Branch sils/matlab (a0e7c4)
by Lasse
01:55
created

bears.matlab.MatlabIndentationBear.run()   A

Complexity

Conditions 3

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 3
dl 0
loc 19
rs 9.4286
1
import re
2
3
from coalib.bears.LocalBear import LocalBear
4
from coalib.results.RESULT_SEVERITY import RESULT_SEVERITY
5
from coalib.results.Result import Result
6
from coalib.results.Diff import Diff
7
8
9
class MatlabIndentationBear(LocalBear):
10
    def run(self, filename, file, indentation: int=2):
11
        """
12
        This bear features a simple algorithm to calculate the right
13
        indentation for Matlab/Octave code. However, it will not handle hanging
14
        indentation or conditions ranging over several lines yet.
15
16
        :param indentation: Number of spaces per indentation level.
17
        """
18
        new_file = list(self.reindent(file, indentation))
19
20
        if new_file != file:
21
            wholediff = Diff.from_string_arrays(file, new_file)
22
            for diff in wholediff.split_diff():
23
                yield Result(
24
                    self,
25
                    'The indentation could be changed to improve readability.',
26
                    severity=RESULT_SEVERITY.INFO,
27
                    affected_code=(diff.range(filename),),
28
                    diffs={filename: diff})
29
30
    @staticmethod
31
    def reindent(file, indentation):
32
        indent, nextindent = 0, 0
33
        for line_nr, line in enumerate(file, start=1):
34
            indent = nextindent
35
            indent, nextindent = MatlabIndentationBear.get_indent(line,
36
                                                                  indent,
37
                                                                  nextindent)
38
            stripped = line.lstrip()
39
            if stripped:
40
                yield indent*indentation*' ' + stripped
41
            else:
42
                yield line
43
44
    @staticmethod
45
    def get_indent(line, indent, nextindent):
46
        ctrlstart = r'\s*(function|if|while|for|switch)'
47
        ctrlcont = r'\s*(elseif|else|case|catch|otherwise)'
48
        ctrlend = r'\s*(end|endfunction|endif|endwhile|endfor|endswitch)'
49
        if re.match(ctrlstart, line) is not None:
50
            return indent, nextindent+1
51
        elif re.match(ctrlcont, line) is not None:
52
            return indent-1, nextindent
53
        elif re.match(ctrlend, line) is not None:
54
            return indent-1, nextindent-1
55
        else:
56
            return indent, indent
57