We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Incorrect line number for Z331
# Bug report

## What's wrong

```python
def foreign_jwt_authentication(token: bytes):  # noqa: Z331
    """
    Goes to the remote provider to validate the token.

    Returns the payload if everything is fine.
    Otherwise raises an exception.
    """
    unverified_payload = jwt.decode(  # type: ignore
        token, key=None, verify=False,
    )
    _make_authentication_request(settings.TOKEN_VERIFICATION_URL, token)
    return unverified_payload
```

Error:

```
./server/rest_app/logics/auth.py:41:1: Z331 Found local variable that are only used in `return` statements
```

## How is that should be

Should be reported on the ` return unverified_payload` line.
Incorrect line number for Z331
# Bug report

## What's wrong

```python
def foreign_jwt_authentication(token: bytes):  # noqa: Z331
    """
    Goes to the remote provider to validate the token.

    Returns the payload if everything is fine.
    Otherwise raises an exception.
    """
    unverified_payload = jwt.decode(  # type: ignore
        token, key=None, verify=False,
    )
    _make_authentication_request(settings.TOKEN_VERIFICATION_URL, token)
    return unverified_payload
```

Error:

```
./server/rest_app/logics/auth.py:41:1: Z331 Found local variable that are only used in `return` statements
```

## How is that should be

Should be reported on the ` return unverified_payload` line.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `wemake_python_styleguide/visitors/ast/keywords.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 
3 import ast
4 from collections import defaultdict
5 from typing import ClassVar, Dict, List, Type, Union
6 
7 from typing_extensions import final
8 
9 from wemake_python_styleguide.logics.nodes import get_parent
10 from wemake_python_styleguide.logics.variables import (
11     is_valid_block_variable_definition,
12 )
13 from wemake_python_styleguide.types import AnyFunctionDef, AnyNodes
14 from wemake_python_styleguide.violations.best_practices import (
15     ContextManagerVariableDefinitionViolation,
16     RaiseNotImplementedViolation,
17     WrongKeywordViolation,
18 )
19 from wemake_python_styleguide.violations.consistency import (
20     InconsistentReturnVariableViolation,
21     InconsistentReturnViolation,
22     InconsistentYieldViolation,
23     MultipleContextManagerAssignmentsViolation,
24 )
25 from wemake_python_styleguide.visitors.base import BaseNodeVisitor
26 from wemake_python_styleguide.visitors.decorators import alias
27 
28 AnyWith = Union[ast.With, ast.AsyncWith]
29 ReturningViolations = Union[
30     Type[InconsistentReturnViolation],
31     Type[InconsistentYieldViolation],
32 ]
33 
34 
35 @final
36 class WrongRaiseVisitor(BaseNodeVisitor):
37     """Finds wrong ``raise`` keywords."""
38 
39     def _check_exception_type(self, node: ast.Raise) -> None:
40         exception = getattr(node, 'exc', None)
41         if exception is None:
42             return
43 
44         exception_func = getattr(exception, 'func', None)
45         if exception_func:
46             exception = exception_func
47 
48         exception_name = getattr(exception, 'id', None)
49         if exception_name == 'NotImplemented':
50             self.add_violation(RaiseNotImplementedViolation(node))
51 
52     def visit_Raise(self, node: ast.Raise) -> None:
53         """
54         Checks how ``raise`` keyword is used.
55 
56         Raises:
57             RaiseNotImplementedViolation
58 
59         """
60         self._check_exception_type(node)
61         self.generic_visit(node)
62 
63 
64 @final
65 @alias('visit_any_function', (
66     'visit_FunctionDef',
67     'visit_AsyncFunctionDef',
68 ))
69 class ConsistentReturningVisitor(BaseNodeVisitor):
70     """Finds incorrect and inconsistent ``return`` and ``yield`` nodes."""
71 
72     def _check_last_return_in_function(self, node: ast.Return) -> None:
73         parent = get_parent(node)
74         if not isinstance(parent, (ast.FunctionDef, ast.AsyncFunctionDef)):
75             return
76 
77         if node is parent.body[-1] and node.value is None:
78             self.add_violation(InconsistentReturnViolation(node))
79 
80     def _iterate_returning_values(
81         self,
82         node: AnyFunctionDef,
83         returning_type,  # mypy is not ok with this type declaration
84         violation: ReturningViolations,
85     ):
86         returns: List[ast.Return] = []
87         has_values = False
88         for sub_node in ast.walk(node):
89             if isinstance(sub_node, returning_type):
90                 if sub_node.value:
91                     has_values = True
92                 returns.append(sub_node)
93 
94         for sub_node in returns:
95             if not sub_node.value and has_values:
96                 self.add_violation(violation(sub_node))
97 
98     def _check_return_values(self, node: AnyFunctionDef) -> None:
99         self._iterate_returning_values(
100             node, ast.Return, InconsistentReturnViolation,
101         )
102 
103     def _check_yield_values(self, node: AnyFunctionDef) -> None:
104         self._iterate_returning_values(
105             node, ast.Yield, InconsistentYieldViolation,
106         )
107 
108     def visit_Return(self, node: ast.Return) -> None:
109         """
110         Checks ``return`` statements for consistency.
111 
112         Raises:
113             InconsistentReturnViolation
114 
115         """
116         self._check_last_return_in_function(node)
117         self.generic_visit(node)
118 
119     def visit_any_function(self, node: AnyFunctionDef) -> None:
120         """
121         Helper to get all ``return`` and ``yield`` nodes in a function at once.
122 
123         Raises:
124             InconsistentReturnViolation
125             InconsistentYieldViolation
126 
127         """
128         self._check_return_values(node)
129         self._check_yield_values(node)
130         self.generic_visit(node)
131 
132 
133 @final
134 class WrongKeywordVisitor(BaseNodeVisitor):
135     """Finds wrong keywords."""
136 
137     _forbidden_keywords: ClassVar[AnyNodes] = (
138         ast.Pass,
139         ast.Delete,
140         ast.Global,
141         ast.Nonlocal,
142     )
143 
144     def _check_keyword(self, node: ast.AST) -> None:
145         if isinstance(node, self._forbidden_keywords):
146             if isinstance(node, ast.Delete):
147                 message = 'del'
148             else:
149                 message = node.__class__.__qualname__.lower()
150             self.add_violation(WrongKeywordViolation(node, text=message))
151 
152     def visit(self, node: ast.AST) -> None:
153         """
154         Used to find wrong keywords.
155 
156         Raises:
157             WrongKeywordViolation
158 
159         """
160         self._check_keyword(node)
161         self.generic_visit(node)
162 
163 
164 @final
165 @alias('visit_any_with', (
166     'visit_With',
167     'visit_AsyncWith',
168 ))
169 class WrongContextManagerVisitor(BaseNodeVisitor):
170     """Checks context managers."""
171 
172     def _check_target_assignment(self, node: AnyWith):
173         if len(node.items) > 1:
174             self.add_violation(
175                 MultipleContextManagerAssignmentsViolation(node),
176             )
177 
178     def _check_variable_definitions(self, node: ast.withitem) -> None:
179         if node.optional_vars is None:
180             return
181 
182         if not is_valid_block_variable_definition(node.optional_vars):
183             self.add_violation(
184                 ContextManagerVariableDefinitionViolation(get_parent(node)),
185             )
186 
187     def visit_withitem(self, node: ast.withitem) -> None:
188         """
189         Checks that all variables inside context managers defined correctly.
190 
191         Raises:
192             ContextManagerVariableDefinitionViolation
193 
194         """
195         self._check_variable_definitions(node)
196         self.generic_visit(node)
197 
198     def visit_any_with(self, node: AnyWith) -> None:
199         """
200         Checks the number of assignments for context managers.
201 
202         Raises:
203             MultipleContextManagerAssignmentsViolation
204 
205         """
206         self._check_target_assignment(node)
207         self.generic_visit(node)
208 
209 
210 @final
211 @alias('visit_return_variable', (
212     'visit_AsyncFunctionDef',
213     'visit_FunctionDef',
214 ))
215 class ConsistentReturningVariableVisitor(BaseNodeVisitor):
216     """Finds variables that are only used in `return` statements."""
217 
218     _checking_nodes: ClassVar[AnyNodes] = (
219         ast.Assign,
220         ast.AnnAssign,
221         ast.AugAssign,
222         ast.Return,
223         ast.Name,
224     )
225 
226     def _get_assign_node_variables(self, node: List[ast.AST]) -> List[str]:
227         assign = []
228         for sub_node in node:
229             if isinstance(sub_node, ast.Assign):
230                 if isinstance(sub_node.targets[0], ast.Name):
231                     assign.append(sub_node.targets[0].id)
232             if isinstance(sub_node, ast.AnnAssign):
233                 if isinstance(sub_node.target, ast.Name):
234                     assign.append(sub_node.target.id)
235         return assign
236 
237     def _get_name_nodes_variable(
238         self,
239         node: List[ast.AST],
240     ) -> Dict[str, List[ast.Name]]:
241         names: Dict[str, List[ast.Name]] = defaultdict(list)
242         for sub_node in node:
243             if isinstance(sub_node, ast.Name):
244                 if isinstance(sub_node.ctx, ast.Load):
245                     names[sub_node.id].append(sub_node)
246             if isinstance(sub_node, ast.AugAssign):
247                 if isinstance(sub_node.target, ast.Name):
248                     variable_name = sub_node.target.id
249                     names[variable_name].append(sub_node.target)
250         return names
251 
252     def _get_return_node_variables(
253         self,
254         node: List[ast.AST],
255     ) -> Dict[str, List[ast.Name]]:
256         returns: Dict[str, List[ast.Name]] = defaultdict(list)
257         for sub_node in node:
258             if isinstance(sub_node, ast.Return):
259                 if isinstance(sub_node.value, ast.Name):
260                     variable_name = sub_node.value.id
261                     returns[variable_name].append(sub_node.value)
262         return returns
263 
264     def _check_variables_for_return(self, node: AnyFunctionDef) -> None:
265         nodes = list(
266             filter(
267                 lambda sub_node: isinstance(sub_node, self._checking_nodes),
268                 ast.walk(node),
269             ),
270         )
271         assign = self._get_assign_node_variables(nodes)
272         names = self._get_name_nodes_variable(nodes)
273         returns = self._get_return_node_variables(nodes)
274 
275         returns = {name: returns[name] for name in returns if name in assign}
276 
277         for variable_name in returns:
278             if not set(names[variable_name]) - set(returns[variable_name]):
279                 self.add_violation(InconsistentReturnVariableViolation(node))
280 
281     def visit_return_variable(self, node: AnyFunctionDef) -> None:
282         """
283         Helper to get all ``return`` variables in a function at once.
284 
285         Raises:
286             InconsistentReturnVariableViolation
287 
288         """
289         self._check_variables_for_return(node)
290         self.generic_visit(node)
291
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/wemake_python_styleguide/visitors/ast/keywords.py b/wemake_python_styleguide/visitors/ast/keywords.py
--- a/wemake_python_styleguide/visitors/ast/keywords.py
+++ b/wemake_python_styleguide/visitors/ast/keywords.py
@@ -2,7 +2,7 @@
 
 import ast
 from collections import defaultdict
-from typing import ClassVar, Dict, List, Type, Union
+from typing import ClassVar, Dict, List, Tuple, Type, Union
 
 from typing_extensions import final
 
@@ -26,6 +26,10 @@
 from wemake_python_styleguide.visitors.decorators import alias
 
 AnyWith = Union[ast.With, ast.AsyncWith]
+NamesAndReturns = Tuple[
+    Dict[str, List[ast.Name]],
+    Dict[str, ast.Return],
+]
 ReturningViolations = Union[
     Type[InconsistentReturnViolation],
     Type[InconsistentYieldViolation],
@@ -252,14 +256,16 @@
     def _get_return_node_variables(
         self,
         node: List[ast.AST],
-    ) -> Dict[str, List[ast.Name]]:
+    ) -> NamesAndReturns:
         returns: Dict[str, List[ast.Name]] = defaultdict(list)
+        return_sub_nodes: Dict[str, ast.Return] = defaultdict()
         for sub_node in node:
             if isinstance(sub_node, ast.Return):
                 if isinstance(sub_node.value, ast.Name):
                     variable_name = sub_node.value.id
                     returns[variable_name].append(sub_node.value)
-        return returns
+                    return_sub_nodes[variable_name] = sub_node
+        return returns, return_sub_nodes
 
     def _check_variables_for_return(self, node: AnyFunctionDef) -> None:
         nodes = list(
@@ -270,13 +276,20 @@
         )
         assign = self._get_assign_node_variables(nodes)
         names = self._get_name_nodes_variable(nodes)
-        returns = self._get_return_node_variables(nodes)
+        returns, return_sub_nodes = self._get_return_node_variables(nodes)
 
         returns = {name: returns[name] for name in returns if name in assign}
 
+        self._check_for_violations(names, return_sub_nodes, returns)
+
+    def _check_for_violations(self, names, return_sub_nodes, returns) -> None:
         for variable_name in returns:
             if not set(names[variable_name]) - set(returns[variable_name]):
-                self.add_violation(InconsistentReturnVariableViolation(node))
+                self.add_violation(
+                    InconsistentReturnVariableViolation(
+                        return_sub_nodes[variable_name],
+                    ),
+                )
 
     def visit_return_variable(self, node: AnyFunctionDef) -> None:
         """

{"golden_diff": "diff --git a/wemake_python_styleguide/visitors/ast/keywords.py b/wemake_python_styleguide/visitors/ast/keywords.py\n--- a/wemake_python_styleguide/visitors/ast/keywords.py\n+++ b/wemake_python_styleguide/visitors/ast/keywords.py\n@@ -2,7 +2,7 @@\n \n import ast\n from collections import defaultdict\n-from typing import ClassVar, Dict, List, Type, Union\n+from typing import ClassVar, Dict, List, Tuple, Type, Union\n \n from typing_extensions import final\n \n@@ -26,6 +26,10 @@\n from wemake_python_styleguide.visitors.decorators import alias\n \n AnyWith = Union[ast.With, ast.AsyncWith]\n+NamesAndReturns = Tuple[\n+    Dict[str, List[ast.Name]],\n+    Dict[str, ast.Return],\n+]\n ReturningViolations = Union[\n     Type[InconsistentReturnViolation],\n     Type[InconsistentYieldViolation],\n@@ -252,14 +256,16 @@\n     def _get_return_node_variables(\n         self,\n         node: List[ast.AST],\n-    ) -> Dict[str, List[ast.Name]]:\n+    ) -> NamesAndReturns:\n         returns: Dict[str, List[ast.Name]] = defaultdict(list)\n+        return_sub_nodes: Dict[str, ast.Return] = defaultdict()\n         for sub_node in node:\n             if isinstance(sub_node, ast.Return):\n                 if isinstance(sub_node.value, ast.Name):\n                     variable_name = sub_node.value.id\n                     returns[variable_name].append(sub_node.value)\n-        return returns\n+                    return_sub_nodes[variable_name] = sub_node\n+        return returns, return_sub_nodes\n \n     def _check_variables_for_return(self, node: AnyFunctionDef) -> None:\n         nodes = list(\n@@ -270,13 +276,20 @@\n         )\n         assign = self._get_assign_node_variables(nodes)\n         names = self._get_name_nodes_variable(nodes)\n-        returns = self._get_return_node_variables(nodes)\n+        returns, return_sub_nodes = self._get_return_node_variables(nodes)\n \n         returns = {name: returns[name] for name in returns if name in assign}\n \n+        self._check_for_violations(names, return_sub_nodes, returns)\n+\n+    def _check_for_violations(self, names, return_sub_nodes, returns) -> None:\n         for variable_name in returns:\n             if not set(names[variable_name]) - set(returns[variable_name]):\n-                self.add_violation(InconsistentReturnVariableViolation(node))\n+                self.add_violation(\n+                    InconsistentReturnVariableViolation(\n+                        return_sub_nodes[variable_name],\n+                    ),\n+                )\n \n     def visit_return_variable(self, node: AnyFunctionDef) -> None:\n         \"\"\"\n", "issue": "Incorrect line number for Z331\n# Bug report\r\n\r\n## What's wrong\r\n\r\n```python\r\ndef foreign_jwt_authentication(token: bytes):  # noqa: Z331\r\n    \"\"\"\r\n    Goes to the remote provider to validate the token.\r\n\r\n    Returns the payload if everything is fine.\r\n    Otherwise raises an exception.\r\n    \"\"\"\r\n    unverified_payload = jwt.decode(  # type: ignore\r\n        token, key=None, verify=False,\r\n    )\r\n    _make_authentication_request(settings.TOKEN_VERIFICATION_URL, token)\r\n    return unverified_payload\r\n```\r\n\r\nError:\r\n\r\n```\r\n./server/rest_app/logics/auth.py:41:1: Z331 Found local variable that are only used in `return` statements\r\n```\r\n\r\n## How is that should be\r\n\r\nShould be reported on the ` return unverified_payload` line.\nIncorrect line number for Z331\n# Bug report\r\n\r\n## What's wrong\r\n\r\n```python\r\ndef foreign_jwt_authentication(token: bytes):  # noqa: Z331\r\n    \"\"\"\r\n    Goes to the remote provider to validate the token.\r\n\r\n    Returns the payload if everything is fine.\r\n    Otherwise raises an exception.\r\n    \"\"\"\r\n    unverified_payload = jwt.decode(  # type: ignore\r\n        token, key=None, verify=False,\r\n    )\r\n    _make_authentication_request(settings.TOKEN_VERIFICATION_URL, token)\r\n    return unverified_payload\r\n```\r\n\r\nError:\r\n\r\n```\r\n./server/rest_app/logics/auth.py:41:1: Z331 Found local variable that are only used in `return` statements\r\n```\r\n\r\n## How is that should be\r\n\r\nShould be reported on the ` return unverified_payload` line.\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\nimport ast\nfrom collections import defaultdict\nfrom typing import ClassVar, Dict, List, Type, Union\n\nfrom typing_extensions import final\n\nfrom wemake_python_styleguide.logics.nodes import get_parent\nfrom wemake_python_styleguide.logics.variables import (\n    is_valid_block_variable_definition,\n)\nfrom wemake_python_styleguide.types import AnyFunctionDef, AnyNodes\nfrom wemake_python_styleguide.violations.best_practices import (\n    ContextManagerVariableDefinitionViolation,\n    RaiseNotImplementedViolation,\n    WrongKeywordViolation,\n)\nfrom wemake_python_styleguide.violations.consistency import (\n    InconsistentReturnVariableViolation,\n    InconsistentReturnViolation,\n    InconsistentYieldViolation,\n    MultipleContextManagerAssignmentsViolation,\n)\nfrom wemake_python_styleguide.visitors.base import BaseNodeVisitor\nfrom wemake_python_styleguide.visitors.decorators import alias\n\nAnyWith = Union[ast.With, ast.AsyncWith]\nReturningViolations = Union[\n    Type[InconsistentReturnViolation],\n    Type[InconsistentYieldViolation],\n]\n\n\n@final\nclass WrongRaiseVisitor(BaseNodeVisitor):\n    \"\"\"Finds wrong ``raise`` keywords.\"\"\"\n\n    def _check_exception_type(self, node: ast.Raise) -> None:\n        exception = getattr(node, 'exc', None)\n        if exception is None:\n            return\n\n        exception_func = getattr(exception, 'func', None)\n        if exception_func:\n            exception = exception_func\n\n        exception_name = getattr(exception, 'id', None)\n        if exception_name == 'NotImplemented':\n            self.add_violation(RaiseNotImplementedViolation(node))\n\n    def visit_Raise(self, node: ast.Raise) -> None:\n        \"\"\"\n        Checks how ``raise`` keyword is used.\n\n        Raises:\n            RaiseNotImplementedViolation\n\n        \"\"\"\n        self._check_exception_type(node)\n        self.generic_visit(node)\n\n\n@final\n@alias('visit_any_function', (\n    'visit_FunctionDef',\n    'visit_AsyncFunctionDef',\n))\nclass ConsistentReturningVisitor(BaseNodeVisitor):\n    \"\"\"Finds incorrect and inconsistent ``return`` and ``yield`` nodes.\"\"\"\n\n    def _check_last_return_in_function(self, node: ast.Return) -> None:\n        parent = get_parent(node)\n        if not isinstance(parent, (ast.FunctionDef, ast.AsyncFunctionDef)):\n            return\n\n        if node is parent.body[-1] and node.value is None:\n            self.add_violation(InconsistentReturnViolation(node))\n\n    def _iterate_returning_values(\n        self,\n        node: AnyFunctionDef,\n        returning_type,  # mypy is not ok with this type declaration\n        violation: ReturningViolations,\n    ):\n        returns: List[ast.Return] = []\n        has_values = False\n        for sub_node in ast.walk(node):\n            if isinstance(sub_node, returning_type):\n                if sub_node.value:\n                    has_values = True\n                returns.append(sub_node)\n\n        for sub_node in returns:\n            if not sub_node.value and has_values:\n                self.add_violation(violation(sub_node))\n\n    def _check_return_values(self, node: AnyFunctionDef) -> None:\n        self._iterate_returning_values(\n            node, ast.Return, InconsistentReturnViolation,\n        )\n\n    def _check_yield_values(self, node: AnyFunctionDef) -> None:\n        self._iterate_returning_values(\n            node, ast.Yield, InconsistentYieldViolation,\n        )\n\n    def visit_Return(self, node: ast.Return) -> None:\n        \"\"\"\n        Checks ``return`` statements for consistency.\n\n        Raises:\n            InconsistentReturnViolation\n\n        \"\"\"\n        self._check_last_return_in_function(node)\n        self.generic_visit(node)\n\n    def visit_any_function(self, node: AnyFunctionDef) -> None:\n        \"\"\"\n        Helper to get all ``return`` and ``yield`` nodes in a function at once.\n\n        Raises:\n            InconsistentReturnViolation\n            InconsistentYieldViolation\n\n        \"\"\"\n        self._check_return_values(node)\n        self._check_yield_values(node)\n        self.generic_visit(node)\n\n\n@final\nclass WrongKeywordVisitor(BaseNodeVisitor):\n    \"\"\"Finds wrong keywords.\"\"\"\n\n    _forbidden_keywords: ClassVar[AnyNodes] = (\n        ast.Pass,\n        ast.Delete,\n        ast.Global,\n        ast.Nonlocal,\n    )\n\n    def _check_keyword(self, node: ast.AST) -> None:\n        if isinstance(node, self._forbidden_keywords):\n            if isinstance(node, ast.Delete):\n                message = 'del'\n            else:\n                message = node.__class__.__qualname__.lower()\n            self.add_violation(WrongKeywordViolation(node, text=message))\n\n    def visit(self, node: ast.AST) -> None:\n        \"\"\"\n        Used to find wrong keywords.\n\n        Raises:\n            WrongKeywordViolation\n\n        \"\"\"\n        self._check_keyword(node)\n        self.generic_visit(node)\n\n\n@final\n@alias('visit_any_with', (\n    'visit_With',\n    'visit_AsyncWith',\n))\nclass WrongContextManagerVisitor(BaseNodeVisitor):\n    \"\"\"Checks context managers.\"\"\"\n\n    def _check_target_assignment(self, node: AnyWith):\n        if len(node.items) > 1:\n            self.add_violation(\n                MultipleContextManagerAssignmentsViolation(node),\n            )\n\n    def _check_variable_definitions(self, node: ast.withitem) -> None:\n        if node.optional_vars is None:\n            return\n\n        if not is_valid_block_variable_definition(node.optional_vars):\n            self.add_violation(\n                ContextManagerVariableDefinitionViolation(get_parent(node)),\n            )\n\n    def visit_withitem(self, node: ast.withitem) -> None:\n        \"\"\"\n        Checks that all variables inside context managers defined correctly.\n\n        Raises:\n            ContextManagerVariableDefinitionViolation\n\n        \"\"\"\n        self._check_variable_definitions(node)\n        self.generic_visit(node)\n\n    def visit_any_with(self, node: AnyWith) -> None:\n        \"\"\"\n        Checks the number of assignments for context managers.\n\n        Raises:\n            MultipleContextManagerAssignmentsViolation\n\n        \"\"\"\n        self._check_target_assignment(node)\n        self.generic_visit(node)\n\n\n@final\n@alias('visit_return_variable', (\n    'visit_AsyncFunctionDef',\n    'visit_FunctionDef',\n))\nclass ConsistentReturningVariableVisitor(BaseNodeVisitor):\n    \"\"\"Finds variables that are only used in `return` statements.\"\"\"\n\n    _checking_nodes: ClassVar[AnyNodes] = (\n        ast.Assign,\n        ast.AnnAssign,\n        ast.AugAssign,\n        ast.Return,\n        ast.Name,\n    )\n\n    def _get_assign_node_variables(self, node: List[ast.AST]) -> List[str]:\n        assign = []\n        for sub_node in node:\n            if isinstance(sub_node, ast.Assign):\n                if isinstance(sub_node.targets[0], ast.Name):\n                    assign.append(sub_node.targets[0].id)\n            if isinstance(sub_node, ast.AnnAssign):\n                if isinstance(sub_node.target, ast.Name):\n                    assign.append(sub_node.target.id)\n        return assign\n\n    def _get_name_nodes_variable(\n        self,\n        node: List[ast.AST],\n    ) -> Dict[str, List[ast.Name]]:\n        names: Dict[str, List[ast.Name]] = defaultdict(list)\n        for sub_node in node:\n            if isinstance(sub_node, ast.Name):\n                if isinstance(sub_node.ctx, ast.Load):\n                    names[sub_node.id].append(sub_node)\n            if isinstance(sub_node, ast.AugAssign):\n                if isinstance(sub_node.target, ast.Name):\n                    variable_name = sub_node.target.id\n                    names[variable_name].append(sub_node.target)\n        return names\n\n    def _get_return_node_variables(\n        self,\n        node: List[ast.AST],\n    ) -> Dict[str, List[ast.Name]]:\n        returns: Dict[str, List[ast.Name]] = defaultdict(list)\n        for sub_node in node:\n            if isinstance(sub_node, ast.Return):\n                if isinstance(sub_node.value, ast.Name):\n                    variable_name = sub_node.value.id\n                    returns[variable_name].append(sub_node.value)\n        return returns\n\n    def _check_variables_for_return(self, node: AnyFunctionDef) -> None:\n        nodes = list(\n            filter(\n                lambda sub_node: isinstance(sub_node, self._checking_nodes),\n                ast.walk(node),\n            ),\n        )\n        assign = self._get_assign_node_variables(nodes)\n        names = self._get_name_nodes_variable(nodes)\n        returns = self._get_return_node_variables(nodes)\n\n        returns = {name: returns[name] for name in returns if name in assign}\n\n        for variable_name in returns:\n            if not set(names[variable_name]) - set(returns[variable_name]):\n                self.add_violation(InconsistentReturnVariableViolation(node))\n\n    def visit_return_variable(self, node: AnyFunctionDef) -> None:\n        \"\"\"\n        Helper to get all ``return`` variables in a function at once.\n\n        Raises:\n            InconsistentReturnVariableViolation\n\n        \"\"\"\n        self._check_variables_for_return(node)\n        self.generic_visit(node)\n", "path": "wemake_python_styleguide/visitors/ast/keywords.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\nimport ast\nfrom collections import defaultdict\nfrom typing import ClassVar, Dict, List, Tuple, Type, Union\n\nfrom typing_extensions import final\n\nfrom wemake_python_styleguide.logics.nodes import get_parent\nfrom wemake_python_styleguide.logics.variables import (\n    is_valid_block_variable_definition,\n)\nfrom wemake_python_styleguide.types import AnyFunctionDef, AnyNodes\nfrom wemake_python_styleguide.violations.best_practices import (\n    ContextManagerVariableDefinitionViolation,\n    RaiseNotImplementedViolation,\n    WrongKeywordViolation,\n)\nfrom wemake_python_styleguide.violations.consistency import (\n    InconsistentReturnVariableViolation,\n    InconsistentReturnViolation,\n    InconsistentYieldViolation,\n    MultipleContextManagerAssignmentsViolation,\n)\nfrom wemake_python_styleguide.visitors.base import BaseNodeVisitor\nfrom wemake_python_styleguide.visitors.decorators import alias\n\nAnyWith = Union[ast.With, ast.AsyncWith]\nNamesAndReturns = Tuple[\n    Dict[str, List[ast.Name]],\n    Dict[str, ast.Return],\n]\nReturningViolations = Union[\n    Type[InconsistentReturnViolation],\n    Type[InconsistentYieldViolation],\n]\n\n\n@final\nclass WrongRaiseVisitor(BaseNodeVisitor):\n    \"\"\"Finds wrong ``raise`` keywords.\"\"\"\n\n    def _check_exception_type(self, node: ast.Raise) -> None:\n        exception = getattr(node, 'exc', None)\n        if exception is None:\n            return\n\n        exception_func = getattr(exception, 'func', None)\n        if exception_func:\n            exception = exception_func\n\n        exception_name = getattr(exception, 'id', None)\n        if exception_name == 'NotImplemented':\n            self.add_violation(RaiseNotImplementedViolation(node))\n\n    def visit_Raise(self, node: ast.Raise) -> None:\n        \"\"\"\n        Checks how ``raise`` keyword is used.\n\n        Raises:\n            RaiseNotImplementedViolation\n\n        \"\"\"\n        self._check_exception_type(node)\n        self.generic_visit(node)\n\n\n@final\n@alias('visit_any_function', (\n    'visit_FunctionDef',\n    'visit_AsyncFunctionDef',\n))\nclass ConsistentReturningVisitor(BaseNodeVisitor):\n    \"\"\"Finds incorrect and inconsistent ``return`` and ``yield`` nodes.\"\"\"\n\n    def _check_last_return_in_function(self, node: ast.Return) -> None:\n        parent = get_parent(node)\n        if not isinstance(parent, (ast.FunctionDef, ast.AsyncFunctionDef)):\n            return\n\n        if node is parent.body[-1] and node.value is None:\n            self.add_violation(InconsistentReturnViolation(node))\n\n    def _iterate_returning_values(\n        self,\n        node: AnyFunctionDef,\n        returning_type,  # mypy is not ok with this type declaration\n        violation: ReturningViolations,\n    ):\n        returns: List[ast.Return] = []\n        has_values = False\n        for sub_node in ast.walk(node):\n            if isinstance(sub_node, returning_type):\n                if sub_node.value:\n                    has_values = True\n                returns.append(sub_node)\n\n        for sub_node in returns:\n            if not sub_node.value and has_values:\n                self.add_violation(violation(sub_node))\n\n    def _check_return_values(self, node: AnyFunctionDef) -> None:\n        self._iterate_returning_values(\n            node, ast.Return, InconsistentReturnViolation,\n        )\n\n    def _check_yield_values(self, node: AnyFunctionDef) -> None:\n        self._iterate_returning_values(\n            node, ast.Yield, InconsistentYieldViolation,\n        )\n\n    def visit_Return(self, node: ast.Return) -> None:\n        \"\"\"\n        Checks ``return`` statements for consistency.\n\n        Raises:\n            InconsistentReturnViolation\n\n        \"\"\"\n        self._check_last_return_in_function(node)\n        self.generic_visit(node)\n\n    def visit_any_function(self, node: AnyFunctionDef) -> None:\n        \"\"\"\n        Helper to get all ``return`` and ``yield`` nodes in a function at once.\n\n        Raises:\n            InconsistentReturnViolation\n            InconsistentYieldViolation\n\n        \"\"\"\n        self._check_return_values(node)\n        self._check_yield_values(node)\n        self.generic_visit(node)\n\n\n@final\nclass WrongKeywordVisitor(BaseNodeVisitor):\n    \"\"\"Finds wrong keywords.\"\"\"\n\n    _forbidden_keywords: ClassVar[AnyNodes] = (\n        ast.Pass,\n        ast.Delete,\n        ast.Global,\n        ast.Nonlocal,\n    )\n\n    def _check_keyword(self, node: ast.AST) -> None:\n        if isinstance(node, self._forbidden_keywords):\n            if isinstance(node, ast.Delete):\n                message = 'del'\n            else:\n                message = node.__class__.__qualname__.lower()\n            self.add_violation(WrongKeywordViolation(node, text=message))\n\n    def visit(self, node: ast.AST) -> None:\n        \"\"\"\n        Used to find wrong keywords.\n\n        Raises:\n            WrongKeywordViolation\n\n        \"\"\"\n        self._check_keyword(node)\n        self.generic_visit(node)\n\n\n@final\n@alias('visit_any_with', (\n    'visit_With',\n    'visit_AsyncWith',\n))\nclass WrongContextManagerVisitor(BaseNodeVisitor):\n    \"\"\"Checks context managers.\"\"\"\n\n    def _check_target_assignment(self, node: AnyWith):\n        if len(node.items) > 1:\n            self.add_violation(\n                MultipleContextManagerAssignmentsViolation(node),\n            )\n\n    def _check_variable_definitions(self, node: ast.withitem) -> None:\n        if node.optional_vars is None:\n            return\n\n        if not is_valid_block_variable_definition(node.optional_vars):\n            self.add_violation(\n                ContextManagerVariableDefinitionViolation(get_parent(node)),\n            )\n\n    def visit_withitem(self, node: ast.withitem) -> None:\n        \"\"\"\n        Checks that all variables inside context managers defined correctly.\n\n        Raises:\n            ContextManagerVariableDefinitionViolation\n\n        \"\"\"\n        self._check_variable_definitions(node)\n        self.generic_visit(node)\n\n    def visit_any_with(self, node: AnyWith) -> None:\n        \"\"\"\n        Checks the number of assignments for context managers.\n\n        Raises:\n            MultipleContextManagerAssignmentsViolation\n\n        \"\"\"\n        self._check_target_assignment(node)\n        self.generic_visit(node)\n\n\n@final\n@alias('visit_return_variable', (\n    'visit_AsyncFunctionDef',\n    'visit_FunctionDef',\n))\nclass ConsistentReturningVariableVisitor(BaseNodeVisitor):\n    \"\"\"Finds variables that are only used in `return` statements.\"\"\"\n\n    _checking_nodes: ClassVar[AnyNodes] = (\n        ast.Assign,\n        ast.AnnAssign,\n        ast.AugAssign,\n        ast.Return,\n        ast.Name,\n    )\n\n    def _get_assign_node_variables(self, node: List[ast.AST]) -> List[str]:\n        assign = []\n        for sub_node in node:\n            if isinstance(sub_node, ast.Assign):\n                if isinstance(sub_node.targets[0], ast.Name):\n                    assign.append(sub_node.targets[0].id)\n            if isinstance(sub_node, ast.AnnAssign):\n                if isinstance(sub_node.target, ast.Name):\n                    assign.append(sub_node.target.id)\n        return assign\n\n    def _get_name_nodes_variable(\n        self,\n        node: List[ast.AST],\n    ) -> Dict[str, List[ast.Name]]:\n        names: Dict[str, List[ast.Name]] = defaultdict(list)\n        for sub_node in node:\n            if isinstance(sub_node, ast.Name):\n                if isinstance(sub_node.ctx, ast.Load):\n                    names[sub_node.id].append(sub_node)\n            if isinstance(sub_node, ast.AugAssign):\n                if isinstance(sub_node.target, ast.Name):\n                    variable_name = sub_node.target.id\n                    names[variable_name].append(sub_node.target)\n        return names\n\n    def _get_return_node_variables(\n        self,\n        node: List[ast.AST],\n    ) -> NamesAndReturns:\n        returns: Dict[str, List[ast.Name]] = defaultdict(list)\n        return_sub_nodes: Dict[str, ast.Return] = defaultdict()\n        for sub_node in node:\n            if isinstance(sub_node, ast.Return):\n                if isinstance(sub_node.value, ast.Name):\n                    variable_name = sub_node.value.id\n                    returns[variable_name].append(sub_node.value)\n                    return_sub_nodes[variable_name] = sub_node\n        return returns, return_sub_nodes\n\n    def _check_variables_for_return(self, node: AnyFunctionDef) -> None:\n        nodes = list(\n            filter(\n                lambda sub_node: isinstance(sub_node, self._checking_nodes),\n                ast.walk(node),\n            ),\n        )\n        assign = self._get_assign_node_variables(nodes)\n        names = self._get_name_nodes_variable(nodes)\n        returns, return_sub_nodes = self._get_return_node_variables(nodes)\n\n        returns = {name: returns[name] for name in returns if name in assign}\n\n        self._check_for_violations(names, return_sub_nodes, returns)\n\n    def _check_for_violations(self, names, return_sub_nodes, returns) -> None:\n        for variable_name in returns:\n            if not set(names[variable_name]) - set(returns[variable_name]):\n                self.add_violation(\n                    InconsistentReturnVariableViolation(\n                        return_sub_nodes[variable_name],\n                    ),\n                )\n\n    def visit_return_variable(self, node: AnyFunctionDef) -> None:\n        \"\"\"\n        Helper to get all ``return`` variables in a function at once.\n\n        Raises:\n            InconsistentReturnVariableViolation\n\n        \"\"\"\n        self._check_variables_for_return(node)\n        self.generic_visit(node)\n", "path": "wemake_python_styleguide/visitors/ast/keywords.py"}]}