eclipse-pdt / pdt

PHP Development Tools project (PDT)
https://eclipse.org/pdt
Eclipse Public License 2.0
189 stars 46 forks source link

Missing error on invoking undeclared/inaccessible static method #227

Open the-liquid-metal opened 1 year ago

the-liquid-metal commented 1 year ago

Bug Description Missing error on invoking undeclared/inaccessible static method.

Eclipse environment Version: 2023-06 (4.28.0) Build id: 20230608-1333 PDT: 8.0.0.202306050832

System

To Reproduce Steps to reproduce the behavior: copy-paste this script to the IDE

<?php
declare(strict_types=1);

namespace ns1\ns2;

// just a dummy
class Test53 {}

class StrictClass1 {
    public static function fnPublic() {}
    protected static function fnProtected() {}
    private static function fnPrivate() {}

    public function fnStatic() {
        static::fnPublic();     // OK
        static::fnProtected();  // OK
        static::fnPrivate();    // OK
        static::fnUndefined();  // this statement must display error

        self::fnPublic();     // OK
        self::fnProtected();  // OK
        self::fnPrivate();    // OK
        self::fnUndefined();  // this statement must display error
    }

    public function fnInstance() {
        static::fnPublic();     // OK
        static::fnProtected();  // OK
        static::fnPrivate();    // OK
        static::fnUndefined();  // this statement must display error

        self::fnPublic();     // OK
        self::fnProtected();  // OK
        self::fnPrivate();    // OK
        self::fnUndefined();  // this statement must display error

        $this::fnPublic();     // OK
        $this::fnProtected();  // OK
        $this::fnPrivate();    // OK
        $this::fnUndefined();  // this statement must display error
    }
}

class StrictClass2 extends StrictClass1 {
    public function fnStatic() {
        static::fnPublic();     // OK
        static::fnProtected();  // OK
        static::fnPrivate();    // this statement must display error
        static::fnUndefined();  // this statement must display error

        self::fnPublic();     // OK
        self::fnProtected();  // OK
        self::fnPrivate();    // this statement must display error
        self::fnUndefined();  // this statement must display error
    }

    public function fnInstance() {
        static::fnPublic();     // OK
        static::fnProtected();  // OK
        static::fnPrivate();    // this statement must display error
        static::fnUndefined();  // this statement must display error

        self::fnPublic();     // OK
        self::fnProtected();  // OK
        self::fnPrivate();    // this statement must display error
        self::fnUndefined();  // this statement must display error

        $this::fnPublic();     // OK
        $this::fnProtected();  // OK
        $this::fnPrivate();    // this statement must display error
        $this::fnUndefined();  // this statement must display error
    }
}

class LooseClass1 {
    public function fnPublic() {}
    protected function fnProtected() {}
    private function fnPrivate() {}

    public function __callStatic($name, $args) {
        $this->$name(...$args);
    }

    public function fnStatic() {
        static::fnPublic();     // OK
        static::fnProtected();  // OK
        static::fnPrivate();    // OK
        static::fnUndefined();  // OK

        self::fnPublic();     // OK
        self::fnProtected();  // OK
        self::fnPrivate();    // OK
        self::fnUndefined();  // OK
    }

    public function fnInstance() {
        static::fnPublic();     // OK
        static::fnProtected();  // OK
        static::fnPrivate();    // OK
        static::fnUndefined();  // OK

        self::fnPublic();     // OK
        self::fnProtected();  // OK
        self::fnPrivate();    // OK
        self::fnUndefined();  // OK

        $this::fnPublic();     // OK
        $this::fnProtected();  // OK
        $this::fnPrivate();    // OK
        $this::fnUndefined();  // OK
    }
}

class LooseClass2 extends LooseClass1 {
    public function fnStatic() {
        static::fnPublic();     // OK
        static::fnProtected();  // OK
        static::fnPrivate();    // OK
        static::fnUndefined();  // OK

        self::fnPublic();     // OK
        self::fnProtected();  // OK
        self::fnPrivate();    // OK
        self::fnUndefined();  // OK
    }

    public function fnInstance() {
        static::fnPublic();     // OK
        static::fnProtected();  // OK
        static::fnPrivate();    // OK
        static::fnUndefined();  // OK

        self::fnPublic();     // OK
        self::fnProtected();  // OK
        self::fnPrivate();    // OK
        self::fnUndefined();  // OK

        $this::fnPublic();     // OK
        $this::fnProtected();  // OK
        $this::fnPrivate();    // OK
        $this::fnUndefined();  // OK
    }
}

StrictClass1::fnPublic();     // OK
StrictClass1::fnProtected();  // this statement must display error
StrictClass1::fnPrivate();    // this statement must display error
StrictClass1::fnUndefined();  // this statement must display error

$strict = new StrictClass1;
$strict::fnPublic();     // OK
$strict::fnProtected();  // this statement must display error
$strict::fnPrivate();    // this statement must display error
$strict::fnUndefined();  // this statement must display error

LooseClass1::fnPublic();     // OK
LooseClass1::fnProtected();  // OK
LooseClass1::fnPrivate();    // OK
LooseClass1::fnUndefined();  // OK

$loose = new LooseClass1;
$loose::fnPublic();     // OK
$loose::fnProtected();  // OK
$loose::fnPrivate();    // OK
$loose::fnUndefined();  // OK

function myFunc(StrictClass1 $strict, LooseClass1 $loose) {
    $strict::fnPublic();     // OK
    $strict::fnProtected();  // this statement must display error
    $strict::fnPrivate();    // this statement must display error
    $strict::fnUndefined();  // this statement must display error

    $loose::fnPublic();     // OK
    $loose::fnProtected();  // OK
    $loose::fnPrivate();    // OK
    $loose::fnUndefined();  // OK
}

$strict->fnInstance();
$loose->fnInstance();
myFunc($strict, $loose);
(new StrictClass2)->fnInstance();
(new LooseClass2)->fnInstance();