diff --git a/pyflakes/api.py b/pyflakes/api.py index e8647f9e..88a80045 100644 --- a/pyflakes/api.py +++ b/pyflakes/api.py @@ -53,12 +53,30 @@ def check(codeString, filename, reporter=None): except Exception: reporter.unexpectedError(filename, 'problem decoding source') return 1 + + # Some syntax errors are only detected when compiling to bytecode (like + # return outside of function), because they aren't encoded in the + # grammar. We do this separately because we can still report on other + # errors in this case. + try: + compile(tree, filename, "exec") + except SyntaxError: + value = sys.exc_info()[1] + msg = value.args[0] + + (lineno, offset, text) = value.lineno, value.offset, value.text + + reporter.syntaxError(filename, msg, lineno, offset, text) + additional_messages = 1 + else: + additional_messages = 0 + # Okay, it's syntactically valid. Now check it. w = checker.Checker(tree, filename) w.messages.sort(key=lambda m: m.lineno) for warning in w.messages: reporter.flake(warning) - return len(w.messages) + return len(w.messages) + additional_messages def checkPath(filename, reporter=None): diff --git a/pyflakes/test/test_api.py b/pyflakes/test/test_api.py index f82ac629..42f80a31 100644 --- a/pyflakes/test/test_api.py +++ b/pyflakes/test/test_api.py @@ -392,6 +392,31 @@ def test_nonKeywordAfterKeywordSyntaxError(self): foo(bar=baz, bax) %s""" % (sourcePath, column, last_line)]) + def test_nonastSyntaxError(self): + """ + SyntaxError that is not encoded in the ast, and can only be detected + by compiling to bytecode, like return outside of function. + """ + source = """\ +return +""" + sourcePath = self.makeTempFile(source) + if sys.version_info[0] == 3: + self.assertHasErrors( + sourcePath, + ["""\ +%s:1:0: 'return' outside function +return + ^ +""" % sourcePath]) + else: + self.assertHasErrors( + sourcePath, + ["""\ +%s:1: 'return' outside function +return +""" % sourcePath]) + def test_invalidEscape(self): """ The invalid escape syntax raises ValueError in Python 2