From ba85336f2f98f544e3139a4bf3a4c157496b8d86 Mon Sep 17 00:00:00 2001 From: Junichi Yamamoto Date: Sun, 19 Jan 2025 20:22:51 +0900 Subject: [PATCH] PHP 8.4 Support: Asymmetric Visibility v2 (Part 3) - https://github.com/apache/netbeans/issues/8035 - https://wiki.php.net/rfc#php_84 - https://wiki.php.net/rfc/asymmetric-visibility-v2 - Fix hints - `IncorrectConstructorPropertyPromotionHintError` - `UnusedVariableHint` - Add/Fix unit tests --- ...ConstructorPropertyPromotionHintError.java | 6 +- .../verification/UnusedVariableHint.java | 3 +- .../testAbstractConstructor.php | 33 +++++-- ...structor.php.testAbstractConstructor.hints | 25 ++++-- .../testOtherThanConstructor.php | 74 ++++++++++++---- ...tructor.php.testOtherThanConstructor.hints | 75 ++++++++++++---- .../testWithVariadic.php | 30 ++++++- ...estWithVariadic.php.testWithVariadic.hints | 17 +++- ...VisibilityConstructorPropertyPromotion.php | 86 +++++++++++++++++++ ...nstructorPropertyPromotion_NoError01.hints | 1 + .../verification/UnusedVariableHintTest.java | 5 ++ 11 files changed, 303 insertions(+), 52 deletions(-) create mode 100644 php/php.editor/test/unit/data/testfiles/verification/UnusedVariableHint/testAsymmetricVisibilityConstructorPropertyPromotion.php create mode 100644 php/php.editor/test/unit/data/testfiles/verification/UnusedVariableHint/testAsymmetricVisibilityConstructorPropertyPromotion.php.testAsymmetricVisibilityConstructorPropertyPromotion_NoError01.hints diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/verification/IncorrectConstructorPropertyPromotionHintError.java b/php/php.editor/src/org/netbeans/modules/php/editor/verification/IncorrectConstructorPropertyPromotionHintError.java index 37734bdf372b..9de14fed7497 100644 --- a/php/php.editor/src/org/netbeans/modules/php/editor/verification/IncorrectConstructorPropertyPromotionHintError.java +++ b/php/php.editor/src/org/netbeans/modules/php/editor/verification/IncorrectConstructorPropertyPromotionHintError.java @@ -128,7 +128,8 @@ public void visit(MethodDeclaration node) { if (CancelSupport.getDefault().isCancelled()) { return; } - if (BodyDeclaration.Modifier.isVisibilityModifier(parameter.getModifier())) { + if (BodyDeclaration.Modifier.isVisibilityModifier(parameter.getModifier()) + || BodyDeclaration.Modifier.isSetVisibilityModifier(parameter.getModifier())) { Block body = function.getBody(); if (body == null || (!body.isCurly() && body.getStatements().isEmpty())) { @@ -184,7 +185,8 @@ private void checkParameters(List parameters) { if (CancelSupport.getDefault().isCancelled()) { return; } - if (BodyDeclaration.Modifier.isVisibilityModifier(parameter.getModifier())) { + if (BodyDeclaration.Modifier.isVisibilityModifier(parameter.getModifier()) + || BodyDeclaration.Modifier.isSetVisibilityModifier(parameter.getModifier())) { // other than a constructor // e.g. // public function freeMethod(private $field) {} diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/verification/UnusedVariableHint.java b/php/php.editor/src/org/netbeans/modules/php/editor/verification/UnusedVariableHint.java index bf367b68d585..805beb2aefe3 100644 --- a/php/php.editor/src/org/netbeans/modules/php/editor/verification/UnusedVariableHint.java +++ b/php/php.editor/src/org/netbeans/modules/php/editor/verification/UnusedVariableHint.java @@ -738,7 +738,8 @@ public void visit(FormalParameter node) { if (CancelSupport.getDefault().isCancelled()) { return; } - if (BodyDeclaration.Modifier.isVisibilityModifier(node.getModifier())) { + if (BodyDeclaration.Modifier.isVisibilityModifier(node.getModifier()) + || BodyDeclaration.Modifier.isSetVisibilityModifier(node.getModifier())) { // [NETBEANS-4443] PHP 8.0 Construcotr Property Promotion forceVariableAsUsed = true; scan(node.getParameterName()); diff --git a/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testAbstractConstructor.php b/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testAbstractConstructor.php index cc6475d1b5b8..05e8de254b65 100644 --- a/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testAbstractConstructor.php +++ b/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testAbstractConstructor.php @@ -20,7 +20,7 @@ abstract class AbstractClassExample1 { - abstract public function __construct(private ?int $incorrect1 = 1); + abstract public function __construct(private ?int $incorrect1 = 1); // error1 } @@ -28,17 +28,40 @@ abstract class AbstractClassExample2 { abstract public function __construct( $test, - private $incorrect1, - private ?int $incorrect2 = 1 + private $incorrect1, // error2 + private ?int $incorrect2 = 1 // error3 ); } interface InterfaceExample1 { - public function __construct(public int|string $incorrect1); + public function __construct(public int|string $incorrect1); // error4 } interface InterfaceExample2 { - public function __construct(int $test, protected $incorrect1); + public function __construct(int $test, protected $incorrect1); // error5 } +abstract class AbstractClassSetVisibilityExample1 { + + abstract public function __construct(private(set) ?int $incorrect1 = 1); // error6 + +} + +abstract class AbstractClassSetVisibilityExample2 { + + abstract public function __construct( + $test, + private(set) $incorrect1, // error7 + private(set) ?int $incorrect2 = 1 // error8 + ); + +} + +interface InterfaceSetVisibilityExample1 { + public function __construct(public(set) int|string $incorrect1); // error9 +} + +interface InterfaceSetVisibilityExample2 { + public function __construct(int $test, protected(set) $incorrect1); // error10 +} diff --git a/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testAbstractConstructor.php.testAbstractConstructor.hints b/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testAbstractConstructor.php.testAbstractConstructor.hints index 45e514e9de30..08fee0638dc0 100644 --- a/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testAbstractConstructor.php.testAbstractConstructor.hints +++ b/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testAbstractConstructor.php.testAbstractConstructor.hints @@ -1,15 +1,30 @@ - abstract public function __construct(private ?int $incorrect1 = 1); + abstract public function __construct(private ?int $incorrect1 = 1); // error1 ---------------------------- HINT:Can't declare a promoted property in an abstract constructor. - private $incorrect1, + private $incorrect1, // error2 ------------------- HINT:Can't declare a promoted property in an abstract constructor. - private ?int $incorrect2 = 1 + private ?int $incorrect2 = 1 // error3 ---------------------------- HINT:Can't declare a promoted property in an abstract constructor. - public function __construct(public int|string $incorrect1); + public function __construct(public int|string $incorrect1); // error4 ----------------------------- HINT:Can't declare a promoted property in an abstract constructor. - public function __construct(int $test, protected $incorrect1); + public function __construct(int $test, protected $incorrect1); // error5 --------------------- +HINT:Can't declare a promoted property in an abstract constructor. + abstract public function __construct(private(set) ?int $incorrect1 = 1); // error6 + --------------------------------- +HINT:Can't declare a promoted property in an abstract constructor. + private(set) $incorrect1, // error7 + ------------------------ +HINT:Can't declare a promoted property in an abstract constructor. + private(set) ?int $incorrect2 = 1 // error8 + --------------------------------- +HINT:Can't declare a promoted property in an abstract constructor. + public function __construct(public(set) int|string $incorrect1); // error9 + ---------------------------------- +HINT:Can't declare a promoted property in an abstract constructor. + public function __construct(int $test, protected(set) $incorrect1); // error10 + -------------------------- HINT:Can't declare a promoted property in an abstract constructor. diff --git a/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testOtherThanConstructor.php b/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testOtherThanConstructor.php index 9a9da5d0cefb..abd43eed8ec5 100644 --- a/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testOtherThanConstructor.php +++ b/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testOtherThanConstructor.php @@ -19,43 +19,85 @@ */ class ClassExample1 { - public function test1(private $incorrect1): void { + public function test1(private $incorrect1): void { // error1 } - public static function test2(int $param1, public int $incorrect) { + public static function test2(int $param1, public int $incorrect) { // error2 } } abstract class AbstractClassExample1 { - abstract public function test1(private ?int $incorrect = 1); + abstract public function test1(private ?int $incorrect = 1); // error3 abstract public function test2( - public $incorrect1, - private ?int $incorrect2 = 1 + public $incorrect1, // error4 + private ?int $incorrect2 = 1 // error5 ); } interface InterfaceExample1 { - public function test(public int|string $incorrect1): void; - public function test( + public function test(public int|string $incorrect1): void; // error6 + public function test2( int $param, - public int|string $incorrect1, - protected $incorrect2 = "", + public int|string $incorrect1, // error7 + protected $incorrect2 = "", // error8 ); } -$lambda1 = function (private $incorrect1) {}; +$lambda1 = function (private $incorrect1) {}; // error9 $lambda2 = function ( string $test, - private $incorrect1, - protected int $incorrect2 = 1, + private $incorrect1, // error10 + protected int $incorrect2 = 1, // error11 ) {}; -$lambda3 = static function (public ?string $incorrect1 = "test"){}; +$lambda3 = static function (public ?string $incorrect1 = "test"){}; // error12 -$arrow1 = fn(int $test, private ?int $incorrect1,): int => 1; +$arrow1 = fn(int $test, private ?int $incorrect1,): int => 1; // error13 $arrow2 = fn( int $test, - private ?int $incorrect1, - private string|int $incorrect2 + private ?int $incorrect1, // error14 + private string|int $incorrect2 // error15 +): int => 1; + +class ClassSetVisibilityExample1 { + public function test1(private(set) $incorrect1): void { // error16 + } + + public static function test2(int $param1, public(set) int $incorrect) { // error17 + } +} + +abstract class AbstractClassSetVisibilityExample1 { + + abstract public function test1(private(set) ?int $incorrect = 1); // error18 + abstract public function test2( + public(set) $incorrect1, // error19 + private(set) ?int $incorrect2 = 1 // error20 + ); + +} + +interface InterfaceSetVisibilityExample1 { + public function test(public(set) int|string $incorrect1): void; // error21 + public function test2( + int $param, + public(set) int|string $incorrect1, // error22 + protected(set) $incorrect2 = "", // error23 + ); +} + +$lambda1 = function (private(set) $incorrect1) {}; // error24 +$lambda2 = function ( + string $test, + private(set) $incorrect1, // error25 + protected(set) int $incorrect2 = 1, // error26 +) {}; +$lambda3 = static function (public(set) ?string $incorrect1 = "test"){}; // error27 + +$arrow1 = fn(int $test, private(set) ?int $incorrect1,): int => 1; // error28 +$arrow2 = fn( + int $test, + private(set) ?int $incorrect1, // error29 + private(set) string|int $incorrect2 // error30 ): int => 1; diff --git a/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testOtherThanConstructor.php.testOtherThanConstructor.hints b/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testOtherThanConstructor.php.testOtherThanConstructor.hints index ab3b1fb11e10..5333ec3ebddb 100644 --- a/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testOtherThanConstructor.php.testOtherThanConstructor.hints +++ b/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testOtherThanConstructor.php.testOtherThanConstructor.hints @@ -1,45 +1,90 @@ - public function test1(private $incorrect1): void { + public function test1(private $incorrect1): void { // error1 ------------------- HINT:Can't declare a promoted property in a function/method other than a constructor. - public static function test2(int $param1, public int $incorrect) { + public static function test2(int $param1, public int $incorrect) { // error2 --------------------- HINT:Can't declare a promoted property in a function/method other than a constructor. - abstract public function test1(private ?int $incorrect = 1); + abstract public function test1(private ?int $incorrect = 1); // error3 --------------------------- HINT:Can't declare a promoted property in a function/method other than a constructor. - public $incorrect1, + public $incorrect1, // error4 ------------------ HINT:Can't declare a promoted property in a function/method other than a constructor. - private ?int $incorrect2 = 1 + private ?int $incorrect2 = 1 // error5 ---------------------------- HINT:Can't declare a promoted property in a function/method other than a constructor. - public function test(public int|string $incorrect1): void; + public function test(public int|string $incorrect1): void; // error6 ----------------------------- HINT:Can't declare a promoted property in a function/method other than a constructor. - public int|string $incorrect1, + public int|string $incorrect1, // error7 ----------------------------- HINT:Can't declare a promoted property in a function/method other than a constructor. - protected $incorrect2 = "", + protected $incorrect2 = "", // error8 -------------------------- HINT:Can't declare a promoted property in a function/method other than a constructor. -$lambda1 = function (private $incorrect1) {}; +$lambda1 = function (private $incorrect1) {}; // error9 ------------------- HINT:Can't declare a promoted property in a function/method other than a constructor. - private $incorrect1, + private $incorrect1, // error10 ------------------- HINT:Can't declare a promoted property in a function/method other than a constructor. - protected int $incorrect2 = 1, + protected int $incorrect2 = 1, // error11 ----------------------------- HINT:Can't declare a promoted property in a function/method other than a constructor. -$lambda3 = static function (public ?string $incorrect1 = "test"){}; +$lambda3 = static function (public ?string $incorrect1 = "test"){}; // error12 ----------------------------------- HINT:Can't declare a promoted property in a function/method other than a constructor. -$arrow1 = fn(int $test, private ?int $incorrect1,): int => 1; +$arrow1 = fn(int $test, private ?int $incorrect1,): int => 1; // error13 ------------------------ HINT:Can't declare a promoted property in a function/method other than a constructor. - private ?int $incorrect1, + private ?int $incorrect1, // error14 ------------------------ HINT:Can't declare a promoted property in a function/method other than a constructor. - private string|int $incorrect2 + private string|int $incorrect2 // error15 ------------------------------ +HINT:Can't declare a promoted property in a function/method other than a constructor. + public function test1(private(set) $incorrect1): void { // error16 + ------------------------ +HINT:Can't declare a promoted property in a function/method other than a constructor. + public static function test2(int $param1, public(set) int $incorrect) { // error17 + -------------------------- +HINT:Can't declare a promoted property in a function/method other than a constructor. + abstract public function test1(private(set) ?int $incorrect = 1); // error18 + -------------------------------- +HINT:Can't declare a promoted property in a function/method other than a constructor. + public(set) $incorrect1, // error19 + ----------------------- +HINT:Can't declare a promoted property in a function/method other than a constructor. + private(set) ?int $incorrect2 = 1 // error20 + --------------------------------- +HINT:Can't declare a promoted property in a function/method other than a constructor. + public function test(public(set) int|string $incorrect1): void; // error21 + ---------------------------------- +HINT:Can't declare a promoted property in a function/method other than a constructor. + public(set) int|string $incorrect1, // error22 + ---------------------------------- +HINT:Can't declare a promoted property in a function/method other than a constructor. + protected(set) $incorrect2 = "", // error23 + ------------------------------- +HINT:Can't declare a promoted property in a function/method other than a constructor. +$lambda1 = function (private(set) $incorrect1) {}; // error24 + ------------------------ +HINT:Can't declare a promoted property in a function/method other than a constructor. + private(set) $incorrect1, // error25 + ------------------------ +HINT:Can't declare a promoted property in a function/method other than a constructor. + protected(set) int $incorrect2 = 1, // error26 + ---------------------------------- +HINT:Can't declare a promoted property in a function/method other than a constructor. +$lambda3 = static function (public(set) ?string $incorrect1 = "test"){}; // error27 + ---------------------------------------- +HINT:Can't declare a promoted property in a function/method other than a constructor. +$arrow1 = fn(int $test, private(set) ?int $incorrect1,): int => 1; // error28 + ----------------------------- +HINT:Can't declare a promoted property in a function/method other than a constructor. + private(set) ?int $incorrect1, // error29 + ----------------------------- +HINT:Can't declare a promoted property in a function/method other than a constructor. + private(set) string|int $incorrect2 // error30 + ----------------------------------- HINT:Can't declare a promoted property in a function/method other than a constructor. diff --git a/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testWithVariadic.php b/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testWithVariadic.php index 3fe62dce703c..e85bcd8c33aa 100644 --- a/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testWithVariadic.php +++ b/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testWithVariadic.php @@ -20,7 +20,7 @@ class ClassExample1 { public function __construct( - private ...$incorrect1, + private ...$incorrect1, // error1 ) { } } @@ -28,14 +28,36 @@ public function __construct( class ClassExample2 { public function __construct( int $test1, - private string ...$incorrect1, + private string ...$incorrect1, // error2 ) { } } $anon1 = new class(1) { public function __construct( - protected string ...$incorrect1, + protected(set) string ...$incorrect1, // error3 ) { } -}; \ No newline at end of file +}; + +class ClassSetVisibilityExample1 { + public function __construct( + private(set) ...$incorrect1, // error4 + ) { + } +} + +class ClassSetVisibilityExample2 { + public function __construct( + int $test1, + private(set) string ...$incorrect1, // error5 + ) { + } +} + +$anon1 = new class(1) { + public function __construct( + protected(set) string ...$incorrect1, // error6 + ) { + } +}; diff --git a/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testWithVariadic.php.testWithVariadic.hints b/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testWithVariadic.php.testWithVariadic.hints index 691659d64679..d7f61642ba1c 100644 --- a/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testWithVariadic.php.testWithVariadic.hints +++ b/php/php.editor/test/unit/data/testfiles/verification/IncorrectConstructorPropertyPromotionHintError/testWithVariadic.php.testWithVariadic.hints @@ -1,9 +1,18 @@ - private ...$incorrect1, + private ...$incorrect1, // error1 ---------------------- HINT:Can't declare a promoted property with a variadic parameter. - private string ...$incorrect1, + private string ...$incorrect1, // error2 ----------------------------- HINT:Can't declare a promoted property with a variadic parameter. - protected string ...$incorrect1, - ------------------------------- + protected(set) string ...$incorrect1, // error3 + ------------------------------------ +HINT:Can't declare a promoted property with a variadic parameter. + private(set) ...$incorrect1, // error4 + --------------------------- +HINT:Can't declare a promoted property with a variadic parameter. + private(set) string ...$incorrect1, // error5 + ---------------------------------- +HINT:Can't declare a promoted property with a variadic parameter. + protected(set) string ...$incorrect1, // error6 + ------------------------------------ HINT:Can't declare a promoted property with a variadic parameter. diff --git a/php/php.editor/test/unit/data/testfiles/verification/UnusedVariableHint/testAsymmetricVisibilityConstructorPropertyPromotion.php b/php/php.editor/test/unit/data/testfiles/verification/UnusedVariableHint/testAsymmetricVisibilityConstructorPropertyPromotion.php new file mode 100644 index 000000000000..0699abdb10ad --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/verification/UnusedVariableHint/testAsymmetricVisibilityConstructorPropertyPromotion.php @@ -0,0 +1,86 @@ +