OLD | NEW |
(Empty) | |
| 1 # Copyright (c) 2003-2013 LOGILAB S.A. (Paris, FRANCE). |
| 2 # http://www.logilab.fr/ -- mailto:contact@logilab.fr |
| 3 # |
| 4 # This program is free software; you can redistribute it and/or modify it under |
| 5 # the terms of the GNU General Public License as published by the Free Software |
| 6 # Foundation; either version 2 of the License, or (at your option) any later |
| 7 # version. |
| 8 # |
| 9 # This program is distributed in the hope that it will be useful, but WITHOUT |
| 10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
| 11 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
| 12 # |
| 13 # You should have received a copy of the GNU General Public License along with |
| 14 # this program; if not, write to the Free Software Foundation, Inc., |
| 15 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
| 16 """ Copyright (c) 2003-2010 LOGILAB S.A. (Paris, FRANCE). |
| 17 http://www.logilab.fr/ -- mailto:contact@logilab.fr |
| 18 |
| 19 Raw metrics checker |
| 20 """ |
| 21 |
| 22 import tokenize |
| 23 |
| 24 # pylint now requires pylint >= 2.2, so this is no longer necessary |
| 25 #if not hasattr(tokenize, 'NL'): |
| 26 # raise ValueError("tokenize.NL doesn't exist -- tokenize module too old") |
| 27 |
| 28 from logilab.common.ureports import Table |
| 29 |
| 30 from pylint.interfaces import ITokenChecker |
| 31 from pylint.utils import EmptyReport |
| 32 from pylint.checkers import BaseTokenChecker |
| 33 from pylint.reporters import diff_string |
| 34 |
| 35 def report_raw_stats(sect, stats, old_stats): |
| 36 """calculate percentage of code / doc / comment / empty |
| 37 """ |
| 38 total_lines = stats['total_lines'] |
| 39 if not total_lines: |
| 40 raise EmptyReport() |
| 41 sect.description = '%s lines have been analyzed' % total_lines |
| 42 lines = ('type', 'number', '%', 'previous', 'difference') |
| 43 for node_type in ('code', 'docstring', 'comment', 'empty'): |
| 44 key = node_type + '_lines' |
| 45 total = stats[key] |
| 46 percent = float(total * 100) / total_lines |
| 47 old = old_stats.get(key, None) |
| 48 if old is not None: |
| 49 diff_str = diff_string(old, total) |
| 50 else: |
| 51 old, diff_str = 'NC', 'NC' |
| 52 lines += (node_type, str(total), '%.2f' % percent, |
| 53 str(old), diff_str) |
| 54 sect.append(Table(children=lines, cols=5, rheaders=1)) |
| 55 |
| 56 |
| 57 class RawMetricsChecker(BaseTokenChecker): |
| 58 """does not check anything but gives some raw metrics : |
| 59 * total number of lines |
| 60 * total number of code lines |
| 61 * total number of docstring lines |
| 62 * total number of comments lines |
| 63 * total number of empty lines |
| 64 """ |
| 65 |
| 66 __implements__ = (ITokenChecker,) |
| 67 |
| 68 # configuration section name |
| 69 name = 'metrics' |
| 70 # configuration options |
| 71 options = () |
| 72 # messages |
| 73 msgs = {} |
| 74 # reports |
| 75 reports = (('RP0701', 'Raw metrics', report_raw_stats),) |
| 76 |
| 77 def __init__(self, linter): |
| 78 BaseTokenChecker.__init__(self, linter) |
| 79 self.stats = None |
| 80 |
| 81 def open(self): |
| 82 """init statistics""" |
| 83 self.stats = self.linter.add_stats(total_lines=0, code_lines=0, |
| 84 empty_lines=0, docstring_lines=0, |
| 85 comment_lines=0) |
| 86 |
| 87 def process_tokens(self, tokens): |
| 88 """update stats""" |
| 89 i = 0 |
| 90 tokens = list(tokens) |
| 91 while i < len(tokens): |
| 92 i, lines_number, line_type = get_type(tokens, i) |
| 93 self.stats['total_lines'] += lines_number |
| 94 self.stats[line_type] += lines_number |
| 95 |
| 96 |
| 97 JUNK = (tokenize.NL, tokenize.INDENT, tokenize.NEWLINE, tokenize.ENDMARKER) |
| 98 |
| 99 def get_type(tokens, start_index): |
| 100 """return the line type : docstring, comment, code, empty""" |
| 101 i = start_index |
| 102 tok_type = tokens[i][0] |
| 103 start = tokens[i][2] |
| 104 pos = start |
| 105 line_type = None |
| 106 while i < len(tokens) and tokens[i][2][0] == start[0]: |
| 107 tok_type = tokens[i][0] |
| 108 pos = tokens[i][3] |
| 109 if line_type is None: |
| 110 if tok_type == tokenize.STRING: |
| 111 line_type = 'docstring_lines' |
| 112 elif tok_type == tokenize.COMMENT: |
| 113 line_type = 'comment_lines' |
| 114 elif tok_type in JUNK: |
| 115 pass |
| 116 else: |
| 117 line_type = 'code_lines' |
| 118 i += 1 |
| 119 if line_type is None: |
| 120 line_type = 'empty_lines' |
| 121 elif i < len(tokens) and tok_type == tokenize.NEWLINE: |
| 122 i += 1 |
| 123 return i, pos[0] - start[0] + 1, line_type |
| 124 |
| 125 |
| 126 def register(linter): |
| 127 """ required method to auto register this checker """ |
| 128 linter.register_checker(RawMetricsChecker(linter)) |
| 129 |
OLD | NEW |