<?php

class MyClass {
    public function validNullableTypeHinting(
        ?array $array = null,
        ?MyObject $object
    ): ?MyObject
    {
    }

    public function validWithFQN(
        ?\MyNameSpace\MyArray $array = null,
        ?\MyNameSpace\MyObject $object
    ): ?\MyNameSpace\MyObject
    {
    }

    public function validReturnTypeForThisSniff():?MyObject
    {
    }

    public function invalidTooMuchWhitespace(
        ?array $array = null,
        ?MyObject
    ):?MyObject
    {
    }

    public function invalidWithFQNTooMuchWhitespace(
        ?\MyNameSpace\MyArray $array = null,
        ?\MyNameSpace\MyObject
    ):?\MyNameSpace\MyObject
    {
    }
}

// valid in lambda
array_map(function(?int $integer = null): ?int {
    return $integer;
}, []);

// invalid in lambda
array_map(function(?int $integer = null): ?int {
    return $integer;
}, []);

interface MyInterface {
    public function invalidTypeHintsWithNewlinesAndComments( ?string $varA,
        ? /* a comment, fixing is undesirable */ array $varB,
        ? // phpcs:ignore Standard.Cat.Sniff -- fixing is undesirable
        int $varC
    ) ?bool;
}

function testSelf( ?self $self ) : ?self {}
function testParent( ?parent $parent ) : ?parent {}
function testCallable( ?callable $callable ) : ?callable {}

// Issue #2552.
class TestTokenizingOfNullableVsInlineThen {
    public function testStatic() {
        $test = Something::one(self::CONSTANT) ?: '';
        $test = Something::one(static::CONSTANT) ?: '';
    }
}

// Issue #2641.
$foo = new static(
    is_null($a) ? foo($a) : $a,
    is_null($b) ? $b : $c
);

// Issue #2791.
class testInstanceOf() {
    function testIt() {
        $foo = $value instanceof static ? '(' . $value . ')' : $value;
        $bar = $value instanceof static ? function_call($value) : $value;
        $baz = $value instanceof static ? array($value) : $value;
        $bal = $value instanceof static ? \className::$property : $value;
        $bal = $value instanceof static ? CONSTANT_NAME : $value;
    }
}

// PHP 8.0: static return type.
function testStatic() : ?static {}

// PHP 8.2: nullable true/false.
function fooG(): ?true {}
function fooH(): ?false {}

// Fatal error: null cannot be marked as nullable, but that's not the concern of this sniff.
function fooI(): ?null {}
