add return-or-yield-outside-of-function Python query

This commit is contained in:
alexey
2019-05-22 15:27:32 +01:00
parent dc8123db8e
commit e214174114
6 changed files with 138 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
# invalid class with return outside of a function
class InvalidClass1(object):
if [1, 2, 3]:
return "Exists"
# invalid statement with yield outside of a function
for i in [1, 2, 3]:
yield i

View File

@@ -0,0 +1,32 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>In Python, <code>return</code> and <code>yield</code> statements as well as <code>yield from</code>
expression can only be used within a function. Having them placed outside of a function or a class
method will raise a <code>SyntaxError</code> at runtime.</p>
</overview>
<recommendation>
<p>The presence of <code>return</code> and <code>yield</code> statements or <code>yield from</code>
expression outside of a function or a class method suggests a logical error, so it is not possible
to suggest a general fix.</p>
</recommendation>
<example>
<p>In this example, a <code>return</code> statement is used outside of a class method in a class and
a <code>yield</code> statement is used outside of a function in a scope of a module.</p>
<sample src="ReturnOrYieldOutsideOfFunction.py" />
</example>
<references>
<li>Python reference: <a href="https://docs.python.org/3.7/reference/simple_stmts.html#the-return-statement">
The return statement</a>.</li>
<li>Python reference: <a href="https://docs.python.org/3.7/reference/simple_stmts.html#yield">
The yield statement</a>.</li>
<li>Python PEP-380: <a href="https://docs.python.org/3/whatsnew/3.3.html#pep-380">
The yield from expression</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,25 @@
/**
* @name return or yield are used outside of a function
* @description return and yield statements should be used only within a function.
* @kind problem
* @tags reliability
* correctness
* @problem.severity error
* @sub-severity low
* @precision very-high
* @id py/return-or-yield-outside-of-function
*/
import python
from AstNode node, string kind
where
not node.getScope() instanceof Function and
(
node instanceof Return and kind = "return"
or
node instanceof Yield and kind = "yield"
or
node instanceof YieldFrom and kind = "yield from"
)
select node, "'" + kind + "' is used outside of a function."

View File

@@ -0,0 +1,9 @@
| ReturnOrYieldOutsideOfFunction_test.py:31:9:31:23 | Return | 'return' is used outside of a function. |
| ReturnOrYieldOutsideOfFunction_test.py:36:9:36:15 | Yield | 'yield' is used outside of a function. |
| ReturnOrYieldOutsideOfFunction_test.py:41:9:41:25 | YieldFrom | 'yield from' is used outside of a function. |
| ReturnOrYieldOutsideOfFunction_test.py:45:5:45:12 | Return | 'return' is used outside of a function. |
| ReturnOrYieldOutsideOfFunction_test.py:49:5:49:11 | Yield | 'yield' is used outside of a function. |
| ReturnOrYieldOutsideOfFunction_test.py:53:5:53:16 | YieldFrom | 'yield from' is used outside of a function. |
| ReturnOrYieldOutsideOfFunction_test.py:57:1:57:14 | YieldFrom | 'yield from' is used outside of a function. |
| ReturnOrYieldOutsideOfFunction_test.py:60:1:60:12 | Return | 'return' is used outside of a function. |
| ReturnOrYieldOutsideOfFunction_test.py:63:1:63:11 | Yield | 'yield' is used outside of a function. |

View File

@@ -0,0 +1 @@
Statements/ReturnOrYieldOutsideOfFunction.ql

View File

@@ -0,0 +1,63 @@
# valid class with return inside a function
class ValidClass1(object):
def class_method(self):
return False
# valid class with yield inside a function
class ValidClass2(object):
def class_method(self):
yield 1
# valid class with yield from inside a function
class ValidClass3(object):
def class_method(self):
yield from [1, 2]
# valid function with the return statement
def valid_func1():
return True
# valid function with the yield statement
def valid_func2():
yield 1
# valid function with the yield from statement
def valid_func3():
yield from [1, 2]
# invalid class with return outside of a function
class InvalidClass1(object):
if [1, 2, 3]:
return "Exists"
# invalid class with yield outside of a function
class InvalidClass2(object):
while True:
yield 1
# invalid class with yield from outside of a function
class InvalidClass2(object):
while True:
yield from [1, 2]
# invalid statement with return outside of a function
for i in [1, 2, 3]:
return i
# invalid statement with yield outside of a function
for i in [1, 2, 3]:
yield i
# invalid statement with yield from outside of a function
for i in [1, 2, 3]:
yield from i
# invalid statement with yield from outside of a function
var = [1,2,3]
yield from var
# invalid statement with return outside of a function
return False
# invalid statement with yield outside of a function
yield False