lint.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. import StringIO
  2. import locale
  3. from .interface import get_option, get_var, get_current_buffer, command
  4. from .queue import add_task
  5. locale.setlocale(locale.LC_CTYPE, "C")
  6. def check_file():
  7. checkers = get_option('lint_checker').split(',')
  8. ignore = set(filter(lambda i: i, get_option('lint_ignore').split(',') +
  9. get_var('lint_ignore').split(',')))
  10. select = set(filter(lambda s: s, get_option('lint_select').split(',') +
  11. get_var('lint_select').split(',')))
  12. buffer = get_current_buffer()
  13. add_task(run_checkers, checkers=checkers, ignore=ignore, title='Code checking', callback=parse_result, buffer=buffer, select=select)
  14. def run_checkers(task=None, checkers=None, ignore=None, buffer=None, select=None):
  15. buffer = (task and task.buffer) or buffer
  16. filename = buffer.name
  17. result = []
  18. part = 100 / len(checkers)
  19. for c in checkers:
  20. checker = globals().get(c)
  21. if not checker:
  22. continue
  23. try:
  24. for e in checker(filename):
  25. e.update(
  26. col=e.get('col') or 0,
  27. text="%s [%s]" % (e.get('text', '')
  28. .strip().replace("'", "\"").split('\n')[0], c),
  29. filename=filename,
  30. bufnr=buffer.number,
  31. )
  32. result.append(e)
  33. except SyntaxError, e:
  34. result.append(dict(
  35. lnum=e.lineno,
  36. col=e.offset or 0,
  37. text=e.args[0],
  38. bufnr=buffer.number,
  39. ))
  40. break
  41. except Exception, e:
  42. assert True
  43. if task:
  44. task.done += part
  45. result = filter(lambda e: _ignore_error(e, select, ignore), result)
  46. result = sorted(result, key=lambda x: x['lnum'])
  47. if task:
  48. task.result = result
  49. task.finished = True
  50. task.done = 100
  51. def parse_result(result):
  52. command(('let g:qf_list = %s' % repr(result)).replace('\': u', '\': '))
  53. command('call pymode#lint#Parse()')
  54. def mccabe(filename):
  55. from pylibs.mccabe import get_code_complexity
  56. complexity = int(get_option('lint_mccabe_complexity'))
  57. return mc.get_module_complexity(filename, min=complexity)
  58. def pep8(filename):
  59. PEP8 or _init_pep8()
  60. style = PEP8['style']
  61. return style.input_file(filename)
  62. def pylint(filename):
  63. from pylibs.logilab.astng.builder import MANAGER
  64. PYLINT or _init_pylint()
  65. linter = PYLINT['lint']
  66. MANAGER.astng_cache.clear()
  67. linter.reporter.out = StringIO.StringIO()
  68. linter.check(filename)
  69. errors, linter.reporter.errors = linter.reporter.errors, []
  70. return errors
  71. def pyflakes(filename):
  72. from pylibs.pyflakes import checker
  73. import _ast
  74. codeString = file(filename, 'U').read() + '\n'
  75. errors = []
  76. tree = compile(codeString, filename, "exec", _ast.PyCF_ONLY_AST)
  77. w = checker.Checker(tree, filename)
  78. w.messages.sort(lambda a, b: cmp(a.lineno, b.lineno))
  79. for w in w.messages:
  80. errors.append(dict(
  81. lnum=w.lineno,
  82. col=w.col,
  83. text=w.message % w.message_args,
  84. type='E'
  85. ))
  86. return errors
  87. PYLINT = dict()
  88. def _init_pylint():
  89. from pylibs.pylint import lint, checkers, reporters
  90. import re
  91. class VimReporter(reporters.BaseReporter):
  92. def __init__(self):
  93. reporters.BaseReporter.__init__(self)
  94. self.errors = []
  95. def add_message(self, msg_id, location, msg):
  96. _, _, line, col = location[1:]
  97. self.errors.append(dict(
  98. lnum=line,
  99. col=col,
  100. text="%s %s" % (msg_id, msg),
  101. type=msg_id[0]
  102. ))
  103. PYLINT['lint'] = lint.PyLinter()
  104. PYLINT['re'] = re.compile(
  105. '^(?:.:)?[^:]+:(\d+): \[([EWRCI]+)[^\]]*\] (.*)$')
  106. checkers.initialize(PYLINT['lint'])
  107. PYLINT['lint'].load_file_configuration(get_var('lint_config'))
  108. PYLINT['lint'].set_option("output-format", "parseable")
  109. PYLINT['lint'].set_option("include-ids", 1)
  110. PYLINT['lint'].set_option("reports", 0)
  111. PYLINT['lint'].reporter = VimReporter()
  112. PEP8 = dict()
  113. def _init_pep8():
  114. from pylibs import pep8 as p8
  115. class _PEP8Report(p8.BaseReport):
  116. def init_file(self, filename, lines, expected, line_offset):
  117. super(_PEP8Report, self).init_file(
  118. filename, lines, expected, line_offset)
  119. self.errors = []
  120. def error(self, line_number, offset, text, check):
  121. code = super(_PEP8Report, self).error(
  122. line_number, offset, text, check)
  123. self.errors.append(dict(
  124. text=text,
  125. type=code,
  126. col=offset + 1,
  127. lnum=line_number,
  128. ))
  129. def get_file_results(self):
  130. return self.errors
  131. PEP8['style'] = p8.StyleGuide(reporter=_PEP8Report)
  132. def _ignore_error(e, select, ignore):
  133. for s in select:
  134. if e['text'].startswith(s):
  135. return True
  136. for i in ignore:
  137. if e['text'].startswith(i):
  138. return False
  139. return True