Repository: wemake-services/wemake-python-styleguide

Issue:
Stray WPS513 warning.
# Bug report

`WPS513` is emitted on `if`/`else`/`if` chains that contain other statements in the last `if` block.

## What's wrong

The following snippet:

```python
if private_key is not None:
    if isinstance(private_key, PKey):
        key = private_key
    else:
        if isinstance(private_key, str):  # WPS513 Found implicit `elif` condition
            stream = io.StringIO()
            stream.write(private_key)
            stream.seek(0)
            private_key = stream
        key = RSAKey.from_private_key(private_key)
```

triggers a stray WPS513 warning.  Seems like the assignment to `key` is not taken into account.

## How is that should be

`WPS513` should only be emitted if the dangling `if` statement is the only one present in the `else` block.


Discussion:
You are right. Adding the following template to the 513 tests, it throws an incorrect violation:

```python
if some:
    ...
else:
    if other:
        ...
    ...
```

If it is no problem, I will be taking a look and fixing this violation for such cases.
@Jrryy will you please take this over?
Sure, already at it
Thanks!

Resolving patch:
diff --git a/wemake_python_styleguide/visitors/tokenize/conditions.py b/wemake_python_styleguide/visitors/tokenize/conditions.py
--- a/wemake_python_styleguide/visitors/tokenize/conditions.py
+++ b/wemake_python_styleguide/visitors/tokenize/conditions.py
@@ -1,5 +1,5 @@
 import tokenize
-from typing import ClassVar, FrozenSet
+from typing import ClassVar, FrozenSet, Sequence
 
 from typing_extensions import final
 
@@ -74,21 +74,63 @@ def _does_else_belong_to_if(self, start_index: int) -> bool:
 
         return False
 
-    def _check_implicit_elif(self, token: tokenize.TokenInfo) -> None:
-        if token.string != 'else':
-            return
+    def _if_has_code_below(
+        self,
+        remaining_tokens: Sequence[tokenize.TokenInfo],
+    ) -> bool:
+        """
+        Checks code immediately below an if statement to remove false positives.
+
+        Checks that, below an if that comes immediately after an else, there is
+        more code to be considered so as not to throw an incorrect violation.
+        """
+        index = 1
+
+        while remaining_tokens[index - 1].exact_type != tokenize.INDENT:
+            index += 1
+
+        context_count = 1
 
-        index = self.file_tokens.index(token)
+        while context_count:
+            next_token = remaining_tokens[index]
+            if next_token.exact_type == tokenize.INDENT:
+                context_count += 1
+            if next_token.exact_type == tokenize.DEDENT:
+                context_count -= 1
+            index += 1
+
+        return remaining_tokens[index].exact_type != tokenize.DEDENT
+
+    def _check_complex_else(
+        self,
+        tokens: Sequence[tokenize.TokenInfo],
+        current_token: tokenize.TokenInfo,
+        index: int,
+    ) -> None:
+        complex_else = self._if_has_code_below(tokens[index + 1:])
+        if not complex_else:
+            self.add_violation(ImplicitElifViolation(current_token))
+
+    def _is_invalid_token(self, index: int, token: tokenize.TokenInfo) -> bool:
+        is_not_else = token.string != 'else'
 
         # `else` token can belong also to `for` and `try/except` statement,
         # which can trigger false positive for that violation.
-        if not self._does_else_belong_to_if(index):
+        belongs_to_if = self._does_else_belong_to_if(index)
+
+        return is_not_else or not belongs_to_if
+
+    def _check_implicit_elif(self, token: tokenize.TokenInfo) -> None:
+        token_index = self.file_tokens.index(token)
+
+        if self._is_invalid_token(token_index, token):
             return
 
         # There's a bug in coverage, I am not sure how to make it work.
-        for next_token in self.file_tokens[index + 1:]:  # pragma: no cover
+        next_tokens = self.file_tokens[token_index + 1:]
+        for index, next_token in enumerate(next_tokens):  # pragma: no cover
             if next_token.exact_type in self._allowed_token_types:
                 continue
             elif next_token.string == 'if':
-                self.add_violation(ImplicitElifViolation(next_token))
+                self._check_complex_else(next_tokens, next_token, index)
             return


Test patch:
diff --git a/tests/test_visitors/test_tokenize/test_conditions/test_implicit_elif.py b/tests/test_visitors/test_tokenize/test_conditions/test_implicit_elif.py
--- a/tests/test_visitors/test_tokenize/test_conditions/test_implicit_elif.py
+++ b/tests/test_visitors/test_tokenize/test_conditions/test_implicit_elif.py
@@ -34,6 +34,15 @@
             ...
 """
 
+correct_else_if = """
+if some:
+    ...
+else:
+    if other:
+        ...
+    ...
+"""
+
 # Wrong:
 
 implicit_elif = """
@@ -44,6 +53,16 @@
         ...
 """
 
+implicit_elif_nested_if = """
+if some:
+    ...
+else:
+    if other:
+        ...
+        if more:
+            ...
+"""
+
 # False positives, triggered by other constructs with `else` clause
 # (see https://github.com/wemake-services/wemake-python-styleguide/issues/835)
 
@@ -80,6 +99,7 @@
     elif_cases,
     if_expression_in_else,
     not_direct_parent,
+    correct_else_if,
 ])
 def test_correct_if_statements(
     code,
@@ -98,6 +118,7 @@ def test_correct_if_statements(
 
 @pytest.mark.parametrize('code', [
     implicit_elif,
+    implicit_elif_nested_if,
 ])
 def test_implicit_elif_statements(
     code,