mirror of
https://github.com/PyCQA/flake8.git
synced 2026-03-30 02:46:52 +00:00
Run checks expecting an AST
This commit is contained in:
parent
576d1f6c85
commit
0b063a1024
4 changed files with 48 additions and 2 deletions
|
|
@ -326,6 +326,37 @@ class FileChecker(object):
|
|||
self.processor.keyword_arguments_for(plugin.parameters, arguments)
|
||||
return plugin.execute(**arguments)
|
||||
|
||||
def run_ast_checks(self):
|
||||
"""Run all checks expecting an abstract syntax tree."""
|
||||
try:
|
||||
ast = self.processor.build_ast()
|
||||
except (ValueError, SyntaxError, TypeError):
|
||||
(exc_type, exception) = sys.exc_info()[:2]
|
||||
if len(exception.args) > 1:
|
||||
offset = exception.args[1]
|
||||
if len(offset) > 2:
|
||||
offset = offset[1:3]
|
||||
else:
|
||||
offset = (1, 0)
|
||||
|
||||
self.report('E999', offset[0], offset[1], '%s: %s' %
|
||||
(exc_type.__name__, exception.args[0]))
|
||||
return
|
||||
|
||||
for plugin in self.checks.ast_plugins:
|
||||
checker = self.run_check(plugin, tree=ast)
|
||||
# NOTE(sigmavirus24): If we want to allow for AST plugins that are
|
||||
# not classes exclusively, we can do the following:
|
||||
# retrieve_results = getattr(checker, 'run', lambda: checker)
|
||||
# Otherwise, we just call run on the checker
|
||||
for (line_number, offset, text, check) in checker.run():
|
||||
self.report(
|
||||
error_code=None,
|
||||
line_number=line_number,
|
||||
column=offset,
|
||||
text=text,
|
||||
)
|
||||
|
||||
def run_logical_checks(self):
|
||||
"""Run all checks expecting a logical line."""
|
||||
comments, logical_line, mapping = self.processor.build_logical_line()
|
||||
|
|
@ -404,6 +435,8 @@ class FileChecker(object):
|
|||
self.report(exc.error_code, exc.line_number, exc.column_number,
|
||||
exc.error_message)
|
||||
|
||||
self.run_ast_checks()
|
||||
|
||||
if results_queue is not None:
|
||||
results_queue.put((self.filename, self.results))
|
||||
|
||||
|
|
|
|||
|
|
@ -227,6 +227,9 @@ class Application(object):
|
|||
self.option_manager, argv
|
||||
)
|
||||
|
||||
self.check_plugins.provide_options(self.option_manager, self.options,
|
||||
self.args)
|
||||
|
||||
def make_formatter(self):
|
||||
# type: () -> NoneType
|
||||
"""Initialize a formatter based on the parsed options."""
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from flake8 import defaults
|
|||
from flake8 import exceptions
|
||||
from flake8 import utils
|
||||
|
||||
PyCF_ONLY_AST = 1024
|
||||
NEWLINE = frozenset([tokenize.NL, tokenize.NEWLINE])
|
||||
# Work around Python < 2.6 behaviour, which does not generate NL after
|
||||
# a comment which is on a line by itself.
|
||||
|
|
@ -172,6 +173,10 @@ class FileProcessor(object):
|
|||
(previous_row, previous_column) = end
|
||||
return comments, logical, mapping
|
||||
|
||||
def build_ast(self):
|
||||
"""Build an abstract syntax tree from the list of lines."""
|
||||
return compile(''.join(self.lines), '', 'exec', PyCF_ONLY_AST)
|
||||
|
||||
def build_logical_line(self):
|
||||
"""Build a logical line from the current tokens list."""
|
||||
comments, logical, mapping_list = self.build_logical_line_tokens()
|
||||
|
|
@ -223,6 +228,10 @@ class FileProcessor(object):
|
|||
except tokenize.TokenError as exc:
|
||||
raise exceptions.InvalidSyntax(exc.message, exception=exc)
|
||||
|
||||
def line_for(self, line_number):
|
||||
"""Retrieve the physical line at the specified line number."""
|
||||
return self.lines[line_number - 1]
|
||||
|
||||
def next_line(self):
|
||||
"""Get the next line from the list."""
|
||||
if self.line_number >= self.total_lines:
|
||||
|
|
|
|||
|
|
@ -187,12 +187,13 @@ class StyleGuide(object):
|
|||
error, codes_str)
|
||||
return False
|
||||
|
||||
def handle_error(self, code, filename, line_number, column_number, text):
|
||||
def handle_error(self, code, filename, line_number, column_number, text,
|
||||
physical_line=None):
|
||||
# type: (str, str, int, int, str) -> NoneType
|
||||
"""Handle an error reported by a check."""
|
||||
error = Error(code, filename, line_number, column_number, text)
|
||||
if (self.should_report_error(error.code) is Decision.Selected and
|
||||
self.is_inline_ignored(error) is False):
|
||||
self.is_inline_ignored(error, physical_line) is False):
|
||||
self.formatter.handle(error)
|
||||
self.listener.notify(error.code, error)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue