# flags: --preview --pyi
#
# Test cases for blank line handling around overload groups in .pyi files:
# - No blank lines between consecutive same-name decorated functions (overloads)
# - No blank lines between overloads even when a function has a docstring
# - Blank line enforced after an overload group before an unrelated statement
# - Blank line enforced before an overload group after an unrelated statement
# - Blank lines between differently-named decorated functions
# - Async overloaded functions
# - Class-level overload groups with various transitions
# - Transition from undecorated def to decorated overload group
# - Overload group immediately followed by undecorated function (no blank line)
# - Overload groups adjacent to if sys.version_info blocks
# - Overload groups inside if blocks adjacent to undecorated functions
# - Conditional overloads (if/else) with docstrings preceded/followed by undecorated defs
# - Undecorated function around @property-decorated function (with and without gaps)
# - Decorated class with undecorated methods (no spurious blank lines)
import sys
from typing import overload, type_check_only

def decorator(func): ...

@overload
def a(x: int) -> int: ...
@overload
def a(x: str) -> str: ...
def b(x): ...
@decorator
def c() -> None: ...
@overload
def d(x: int) -> int:
    """Int overload."""
@overload
def d(x: str) -> str: ...
def e(x): ...

@overload
async def async_a(x: int) -> int: ...
@overload
async def async_a(x: str) -> str: ...
var: int

class MyClass:
    @overload
    def method(self, x: int) -> int: ...
    @overload
    def method(self, x: str) -> str: ...
    def after_method(self, x): ...

    @overload
    def with_docs(self, x: int) -> int:
        """Int."""
    @overload
    def with_docs(self, x: str) -> str: ...
    def after_with_docs(self, x): ...

    @overload
    def no_gap(self, x: int) -> int: ...
    @overload
    def no_gap(self, x: str) -> str: ...
    @decorator
    def different_method(self) -> None: ...

    @decorator
    def another_dec(self) -> None: ...
    @decorator
    def yet_another_dec(self) -> None: ...

    attr: int
    @overload
    def after_attr(self, x: int) -> int: ...
    @overload
    def after_attr(self, x: str) -> str: ...
    attr2: str

    @property
    def prop1(self) -> int: ...
    @property
    def prop2(self) -> str: ...
    @property
    def prop3(self) -> bytes: ...
    @property
    def prop4_with_setter(self) -> int: ...
    @prop4_with_setter.setter
    def prop4_with_setter(self, value: int) -> None: ...
    @property
    def prop_5_with_setter(self) -> int: ...
    @prop_5_with_setter.setter
    def prop_5_with_setter(self, value: int) -> None: ...
    @property
    def prop6(self) -> int: ...
    @property
    def prop7(self) -> str: ...
    @property
    def prop8_with_setter(self) -> int: ...
    @prop8_with_setter.setter
    def prop8_with_setter(self, value: int) -> None: ...
    @property
    def prop9(self) -> int: ...
    @property
    def prop10_with_docstring(self) -> int:
        """Prop with docstring."""
    @property
    def prop11_with_docstring(self) -> int:
        """Another prop with docstring."""
    @property
    def prop12(self) -> int: ...

    @classmethod
    def make_myclass(cls) -> "MyClass": ...

    @staticmethod
    def static_method() -> None: ...


def plain() -> None: ...
@overload
def different(x: int) -> int: ...
@overload
def different(x: str) -> str: ...

def another_plain() -> None: ...
@decorator
def alpha() -> None: ...
@decorator
def beta() -> None: ...

@overload
def multi(x: int) -> int:
    """Int version."""
@overload
def multi(x: str) -> str:
    """Str version."""
@overload
def multi(x: bytes) -> bytes: ...

def next_func() -> None: ...

@overload
def three_overloads(x: int) -> int: ...
@overload
def three_overloads(x: str) -> str: ...
@overload
def three_overloads(x: bytes) -> bytes: ...

@overload
def four_overloads(x: int) -> int: ...
@overload
def four_overloads(x: str) -> str: ...

@overload
def four_overloads(x: bytes) -> bytes: ...
@overload
def four_overloads(x: float) -> float: ...

@overload
def before_if_no_gap(x: int) -> int: ...
@overload
def before_if_no_gap(x: str) -> str: ...
if sys.version_info >= (3, 10):
    def conditional_func() -> None: ...

if sys.version_info >= (3, 10):
    def other_conditional() -> None: ...
@overload
def after_if_no_gap(x: int) -> int: ...
@overload
def after_if_no_gap(x: str) -> str: ...

@overload
def before_if_with_gap(x: int) -> int: ...
@overload
def before_if_with_gap(x: str) -> str: ...

if sys.version_info >= (3, 10):
    def conditional_func2() -> None: ...

if sys.version_info >= (3, 10):
    def other_conditional2() -> None: ...

@overload
def after_if_with_gap(x: int) -> int: ...
@overload
def after_if_with_gap(x: str) -> str: ...

if sys.version_info >= (3, 10):
    @overload
    def nested_overload_before(x: int) -> int: ...
    @overload
    def nested_overload_before(x: str) -> str: ...
    def undecorated_after() -> None: ...

if sys.version_info >= (3, 10):
    def undecorated_before() -> None: ...
    @overload
    def nested_overload_after(x: int) -> int: ...
    @overload
    def nested_overload_after(x: str) -> str: ...

if sys.version_info >= (3, 10):
    @overload
    def nested_overload_before_with_gap(x: int) -> int: ...
    @overload
    def nested_overload_before_with_gap(x: str) -> str: ...

    def undecorated_after_with_gap() -> None: ...

if sys.version_info >= (3, 10):
    def undecorated_before_with_gap() -> None: ...

    @overload
    def nested_overload_after_with_gap(x: int) -> int: ...
    @overload
    def nested_overload_after_with_gap(x: str) -> str: ...

def before_conditional_overload() -> None: ...
if sys.version_info >= (3, 10):
    @overload
    def conditional_overload(x: int) -> int:
        """Int."""
else:
    @overload
    def conditional_overload(x: int) -> int:
        """Int old."""
@overload
def conditional_overload(x: str) -> str: ...
def after_conditional_overload() -> None: ...

def before_conditional_overload_with_gaps() -> None: ...

if sys.version_info >= (3, 10):
    @overload
    def conditional_overload_with_gaps(x: int) -> int:
        """Int."""
else:
    @overload
    def conditional_overload_with_gaps(x: int) -> int:
        """Int old."""

@overload
def conditional_overload_with_gaps(x: str) -> str: ...

def after_conditional_overload_with_gaps() -> None: ...

if sys.version_info >= (3, 10):
    @overload
    def if_else_different_names(x: int) -> int: ...
    @overload
    def if_else_different_names(x: str) -> str: ...
else:
    @overload
    def if_else_other_name(x: int) -> int: ...
    @overload
    def if_else_other_name(x: str) -> str: ...

@overload
def commented(x: int) -> int: ...
# comment in overload group
@overload
def commented(x: str) -> str: ...
def after_commented() -> None: ...

class MyClassWithComments:
    @overload
    def commented_method(self, x: int) -> int: ...
    # comment between class overloads
    @overload
    def commented_method(self, x: str) -> str: ...
    def after_commented_method(self) -> None: ...

    @overload
    def three_overload_methods(self, x: int) -> int: ...

    # comment after first with gap above that is retained
    @overload
    def three_overload_methods(self, x: str) -> str: ...
    # comment after second with gap below that is removed

    @overload
    def three_overload_methods(self, x: bytes) -> bytes: ...
    def after_three_overloads(self) -> None: ...

    @overload
    def four_overload_methods(self, x: int) -> int: ...

    # comment after first with gaps on both lines

    @overload
    def four_overload_methods(self, x: str) -> str: ...


    # comment after second with too many gaps above
    @overload
    def four_overload_methods(self, x: bytes) -> bytes: ...


    # comment after third with large gaps below and above


    @overload
    def four_overload_methods(self, x: list[bytes]) -> bytes: ...

@overload
def commented_gap_above(x: int) -> int: ...

# comment with gap above that is retained
@overload
def commented_gap_above(x: str) -> str: ...

@overload
def commented_gap_below(x: int) -> int: ...
# comment with gap below that is removed

@overload
def commented_gap_below(x: str) -> str: ...

@overload
def commented_gaps_both(x: int) -> int: ...

# comment with gaps on both sides

@overload
def commented_gaps_both(x: str) -> str: ...

@overload
def multi_comment(x: int) -> int: ...
# first comment
# second comment
@overload
def multi_comment(x: str) -> str: ...

@overload
def large_comment_gaps(x: int) -> int: ...


# comment with large gaps above that are collapsed
@overload
def large_comment_gaps(x: str) -> str: ...


# comment with large gaps above and below that are collapsed


@overload
def large_comment_gaps(x: int) -> int: ...

@overload
def conditional_commented(x: int) -> int: ...


# comment

if sys.version_info >= (3, 10):

    # comment
    @overload
    def conditional_commented(x: str) -> str: ...
else:

    # comment
    @overload
    def conditional_commented(x: str) -> str: ...

def before_comment_group() -> None: ...
# comment before overload group
@overload
def comment_before(x: int) -> int: ...
@overload
def comment_before(x: str) -> str: ...
def after_comment_group() -> None: ...

class ClassWithConditionalOverloads:
    def method(self) -> None: ...
    if sys.version_info >= (3, 10):
        @overload
        def conditional(self, x: int) -> int: ...
    else:
        @overload
        def conditional(self, x: str) -> str: ...
    @overload
    def conditional(self, x: bytes) -> bytes: ...

    @overload
    def conditional_commented(self, x: int) -> int: ...

    # comment

    if sys.version_info >= (3, 10):

        # comment

        @overload
        def conditional_commented(self, x: str) -> str: ...
    else:

        # comment

        @overload
        def conditional_commented(self, x: str) -> str: ...

class ClassWithOverloadThenConditional:
    @overload
    def method(self, x: int) -> int: ...
    @overload
    def method(self, x: str) -> str: ...
    if sys.version_info >= (3, 10):
        @overload
        def method(self, x: bytes) -> bytes: ...

class ClassWithNonOverloadConditional:
    def regular(self) -> None: ...
    if sys.version_info < (3, 12):
        @staticmethod
        def legacy_method() -> str:
            """Deprecated."""

@type_check_only
class DecoratedClassWithUndecoratedMethods:
    def method_a(self) -> None: ...
    def method_b(self) -> None: ...
    def method_c(self) -> None: ...

if sys.version_info >= (3, 12):
    @overload
    def elif_overload(x: int) -> int: ...
elif sys.version_info >= (3, 10):
    @overload
    def elif_overload(x: float) -> float: ...
else:
    @overload
    def elif_overload(x: bytes) -> bytes: ...
@overload
def elif_overload(x: str) -> str: ...

@overload
def before_class(x: int) -> int: ...
@overload
def before_class(x: str) -> str: ...
class AfterOverloadGroup: ...

class AfterOverloadGroup2: ...
@overload
def after_class(x: int) -> int: ...
@overload
def after_class(x: str) -> str: ...

@overload
@decorator
def multi_decorated(x: int) -> int: ...
@overload
@decorator
def multi_decorated(x: str) -> str: ...
def after_multi_decorated() -> None: ...

class Outer:
    class Inner:
        @overload
        def method(self, x: int) -> int: ...
        @overload
        def method(self, x: str) -> str: ...
    @overload
    def method(self, x: int) -> int: ...
    @overload
    def method(self, x: str) -> str: ...


# output
#
# Test cases for blank line handling around overload groups in .pyi files:
# - No blank lines between consecutive same-name decorated functions (overloads)
# - No blank lines between overloads even when a function has a docstring
# - Blank line enforced after an overload group before an unrelated statement
# - Blank line enforced before an overload group after an unrelated statement
# - Blank lines between differently-named decorated functions
# - Async overloaded functions
# - Class-level overload groups with various transitions
# - Transition from undecorated def to decorated overload group
# - Overload group immediately followed by undecorated function (no blank line)
# - Overload groups adjacent to if sys.version_info blocks
# - Overload groups inside if blocks adjacent to undecorated functions
# - Conditional overloads (if/else) with docstrings preceded/followed by undecorated defs
# - Undecorated function around @property-decorated function (with and without gaps)
# - Decorated class with undecorated methods (no spurious blank lines)
import sys
from typing import overload, type_check_only

def decorator(func): ...

@overload
def a(x: int) -> int: ...
@overload
def a(x: str) -> str: ...

def b(x): ...
@decorator
def c() -> None: ...

@overload
def d(x: int) -> int:
    """Int overload."""
@overload
def d(x: str) -> str: ...

def e(x): ...

@overload
async def async_a(x: int) -> int: ...
@overload
async def async_a(x: str) -> str: ...

var: int

class MyClass:
    @overload
    def method(self, x: int) -> int: ...
    @overload
    def method(self, x: str) -> str: ...

    def after_method(self, x): ...

    @overload
    def with_docs(self, x: int) -> int:
        """Int."""
    @overload
    def with_docs(self, x: str) -> str: ...

    def after_with_docs(self, x): ...

    @overload
    def no_gap(self, x: int) -> int: ...
    @overload
    def no_gap(self, x: str) -> str: ...

    @decorator
    def different_method(self) -> None: ...
    @decorator
    def another_dec(self) -> None: ...
    @decorator
    def yet_another_dec(self) -> None: ...

    attr: int

    @overload
    def after_attr(self, x: int) -> int: ...
    @overload
    def after_attr(self, x: str) -> str: ...

    attr2: str

    @property
    def prop1(self) -> int: ...
    @property
    def prop2(self) -> str: ...
    @property
    def prop3(self) -> bytes: ...

    @property
    def prop4_with_setter(self) -> int: ...
    @prop4_with_setter.setter
    def prop4_with_setter(self, value: int) -> None: ...

    @property
    def prop_5_with_setter(self) -> int: ...
    @prop_5_with_setter.setter
    def prop_5_with_setter(self, value: int) -> None: ...

    @property
    def prop6(self) -> int: ...
    @property
    def prop7(self) -> str: ...

    @property
    def prop8_with_setter(self) -> int: ...
    @prop8_with_setter.setter
    def prop8_with_setter(self, value: int) -> None: ...

    @property
    def prop9(self) -> int: ...
    @property
    def prop10_with_docstring(self) -> int:
        """Prop with docstring."""

    @property
    def prop11_with_docstring(self) -> int:
        """Another prop with docstring."""

    @property
    def prop12(self) -> int: ...
    @classmethod
    def make_myclass(cls) -> "MyClass": ...
    @staticmethod
    def static_method() -> None: ...

def plain() -> None: ...

@overload
def different(x: int) -> int: ...
@overload
def different(x: str) -> str: ...

def another_plain() -> None: ...
@decorator
def alpha() -> None: ...
@decorator
def beta() -> None: ...

@overload
def multi(x: int) -> int:
    """Int version."""
@overload
def multi(x: str) -> str:
    """Str version."""
@overload
def multi(x: bytes) -> bytes: ...

def next_func() -> None: ...

@overload
def three_overloads(x: int) -> int: ...
@overload
def three_overloads(x: str) -> str: ...
@overload
def three_overloads(x: bytes) -> bytes: ...

@overload
def four_overloads(x: int) -> int: ...
@overload
def four_overloads(x: str) -> str: ...
@overload
def four_overloads(x: bytes) -> bytes: ...
@overload
def four_overloads(x: float) -> float: ...

@overload
def before_if_no_gap(x: int) -> int: ...
@overload
def before_if_no_gap(x: str) -> str: ...

if sys.version_info >= (3, 10):
    def conditional_func() -> None: ...

if sys.version_info >= (3, 10):
    def other_conditional() -> None: ...

@overload
def after_if_no_gap(x: int) -> int: ...
@overload
def after_if_no_gap(x: str) -> str: ...

@overload
def before_if_with_gap(x: int) -> int: ...
@overload
def before_if_with_gap(x: str) -> str: ...

if sys.version_info >= (3, 10):
    def conditional_func2() -> None: ...

if sys.version_info >= (3, 10):
    def other_conditional2() -> None: ...

@overload
def after_if_with_gap(x: int) -> int: ...
@overload
def after_if_with_gap(x: str) -> str: ...

if sys.version_info >= (3, 10):
    @overload
    def nested_overload_before(x: int) -> int: ...
    @overload
    def nested_overload_before(x: str) -> str: ...

    def undecorated_after() -> None: ...

if sys.version_info >= (3, 10):
    def undecorated_before() -> None: ...

    @overload
    def nested_overload_after(x: int) -> int: ...
    @overload
    def nested_overload_after(x: str) -> str: ...

if sys.version_info >= (3, 10):
    @overload
    def nested_overload_before_with_gap(x: int) -> int: ...
    @overload
    def nested_overload_before_with_gap(x: str) -> str: ...

    def undecorated_after_with_gap() -> None: ...

if sys.version_info >= (3, 10):
    def undecorated_before_with_gap() -> None: ...

    @overload
    def nested_overload_after_with_gap(x: int) -> int: ...
    @overload
    def nested_overload_after_with_gap(x: str) -> str: ...

def before_conditional_overload() -> None: ...

if sys.version_info >= (3, 10):
    @overload
    def conditional_overload(x: int) -> int:
        """Int."""
else:
    @overload
    def conditional_overload(x: int) -> int:
        """Int old."""

@overload
def conditional_overload(x: str) -> str: ...

def after_conditional_overload() -> None: ...
def before_conditional_overload_with_gaps() -> None: ...

if sys.version_info >= (3, 10):
    @overload
    def conditional_overload_with_gaps(x: int) -> int:
        """Int."""
else:
    @overload
    def conditional_overload_with_gaps(x: int) -> int:
        """Int old."""

@overload
def conditional_overload_with_gaps(x: str) -> str: ...

def after_conditional_overload_with_gaps() -> None: ...

if sys.version_info >= (3, 10):
    @overload
    def if_else_different_names(x: int) -> int: ...
    @overload
    def if_else_different_names(x: str) -> str: ...

else:
    @overload
    def if_else_other_name(x: int) -> int: ...
    @overload
    def if_else_other_name(x: str) -> str: ...

@overload
def commented(x: int) -> int: ...
# comment in overload group
@overload
def commented(x: str) -> str: ...

def after_commented() -> None: ...

class MyClassWithComments:
    @overload
    def commented_method(self, x: int) -> int: ...
    # comment between class overloads
    @overload
    def commented_method(self, x: str) -> str: ...

    def after_commented_method(self) -> None: ...

    @overload
    def three_overload_methods(self, x: int) -> int: ...

    # comment after first with gap above that is retained
    @overload
    def three_overload_methods(self, x: str) -> str: ...
    # comment after second with gap below that is removed
    @overload
    def three_overload_methods(self, x: bytes) -> bytes: ...

    def after_three_overloads(self) -> None: ...

    @overload
    def four_overload_methods(self, x: int) -> int: ...

    # comment after first with gaps on both lines
    @overload
    def four_overload_methods(self, x: str) -> str: ...

    # comment after second with too many gaps above
    @overload
    def four_overload_methods(self, x: bytes) -> bytes: ...

    # comment after third with large gaps below and above
    @overload
    def four_overload_methods(self, x: list[bytes]) -> bytes: ...

@overload
def commented_gap_above(x: int) -> int: ...

# comment with gap above that is retained
@overload
def commented_gap_above(x: str) -> str: ...

@overload
def commented_gap_below(x: int) -> int: ...
# comment with gap below that is removed
@overload
def commented_gap_below(x: str) -> str: ...

@overload
def commented_gaps_both(x: int) -> int: ...

# comment with gaps on both sides
@overload
def commented_gaps_both(x: str) -> str: ...

@overload
def multi_comment(x: int) -> int: ...
# first comment
# second comment
@overload
def multi_comment(x: str) -> str: ...

@overload
def large_comment_gaps(x: int) -> int: ...

# comment with large gaps above that are collapsed
@overload
def large_comment_gaps(x: str) -> str: ...

# comment with large gaps above and below that are collapsed
@overload
def large_comment_gaps(x: int) -> int: ...

@overload
def conditional_commented(x: int) -> int: ...

# comment

if sys.version_info >= (3, 10):

    # comment
    @overload
    def conditional_commented(x: str) -> str: ...
else:

    # comment
    @overload
    def conditional_commented(x: str) -> str: ...

def before_comment_group() -> None: ...

# comment before overload group
@overload
def comment_before(x: int) -> int: ...
@overload
def comment_before(x: str) -> str: ...

def after_comment_group() -> None: ...

class ClassWithConditionalOverloads:
    def method(self) -> None: ...

    if sys.version_info >= (3, 10):
        @overload
        def conditional(self, x: int) -> int: ...
    else:
        @overload
        def conditional(self, x: str) -> str: ...

    @overload
    def conditional(self, x: bytes) -> bytes: ...

    @overload
    def conditional_commented(self, x: int) -> int: ...

    # comment

    if sys.version_info >= (3, 10):

        # comment
        @overload
        def conditional_commented(self, x: str) -> str: ...
    else:

        # comment
        @overload
        def conditional_commented(self, x: str) -> str: ...

class ClassWithOverloadThenConditional:
    @overload
    def method(self, x: int) -> int: ...
    @overload
    def method(self, x: str) -> str: ...
    if sys.version_info >= (3, 10):
        @overload
        def method(self, x: bytes) -> bytes: ...

class ClassWithNonOverloadConditional:
    def regular(self) -> None: ...
    if sys.version_info < (3, 12):
        @staticmethod
        def legacy_method() -> str:
            """Deprecated."""

@type_check_only
class DecoratedClassWithUndecoratedMethods:
    def method_a(self) -> None: ...
    def method_b(self) -> None: ...
    def method_c(self) -> None: ...

if sys.version_info >= (3, 12):
    @overload
    def elif_overload(x: int) -> int: ...
elif sys.version_info >= (3, 10):
    @overload
    def elif_overload(x: float) -> float: ...
else:
    @overload
    def elif_overload(x: bytes) -> bytes: ...

@overload
def elif_overload(x: str) -> str: ...

@overload
def before_class(x: int) -> int: ...
@overload
def before_class(x: str) -> str: ...

class AfterOverloadGroup: ...
class AfterOverloadGroup2: ...

@overload
def after_class(x: int) -> int: ...
@overload
def after_class(x: str) -> str: ...

@overload
@decorator
def multi_decorated(x: int) -> int: ...
@overload
@decorator
def multi_decorated(x: str) -> str: ...

def after_multi_decorated() -> None: ...

class Outer:
    class Inner:
        @overload
        def method(self, x: int) -> int: ...
        @overload
        def method(self, x: str) -> str: ...

    @overload
    def method(self, x: int) -> int: ...
    @overload
    def method(self, x: str) -> str: ...
