From 3ffd6159f211a9c9fd499a821069923d5953c867 Mon Sep 17 00:00:00 2001 From: Junichi Yamamoto Date: Mon, 16 Oct 2023 11:57:08 +0900 Subject: [PATCH] PHP 8.2 Support: Disjunctive Normal Form Types (Part 8) - https://github.com/apache/netbeans/issues/4725 - https://wiki.php.net/rfc/dnf_types - Fix the formatter(Prevent adding `WHITESPACE_BEFORE_METHOD_DEC_PAREN` twice) ```php // e.g. the following case has "((" function example((X&Y)|Z $param): void {} ``` - Add a unit test --- .../php/editor/indent/FormatVisitor.java | 5 +- .../formatting/php82/dnfTypes_01.php | 190 ++++++++++++ .../php82/dnfTypes_01.php.formatted | 281 ++++++++++++++++++ .../php/editor/indent/PHPFormatterTest.java | 5 + 4 files changed, 480 insertions(+), 1 deletion(-) create mode 100644 php/php.editor/test/unit/data/testfiles/formatting/php82/dnfTypes_01.php create mode 100644 php/php.editor/test/unit/data/testfiles/formatting/php82/dnfTypes_01.php.formatted diff --git a/php/php.editor/src/org/netbeans/modules/php/editor/indent/FormatVisitor.java b/php/php.editor/src/org/netbeans/modules/php/editor/indent/FormatVisitor.java index c03939e031a0..2913ec7a660a 100644 --- a/php/php.editor/src/org/netbeans/modules/php/editor/indent/FormatVisitor.java +++ b/php/php.editor/src/org/netbeans/modules/php/editor/indent/FormatVisitor.java @@ -1465,13 +1465,16 @@ public void visit(FunctionDeclaration node) { scan(node.getAttributes()); scan(node.getFunctionName()); + // e.g. function paramHasDNFType((X&Y)|Z $test): void {} + boolean addedOpenParen = false; // #270903 add indent while (ts.moveNext() && (ts.token().id() == PHPTokenId.WHITESPACE || isComment(ts.token()) - || isOpenParen(ts.token()))) { + || (isOpenParen(ts.token()) && !addedOpenParen))) { addFormatToken(formatTokens); if (isOpenParen(ts.token())) { formatTokens.add(new FormatToken.IndentToken(ts.offset() + ts.token().length(), options.continualIndentSize)); + addedOpenParen = true; } } ts.movePrevious(); diff --git a/php/php.editor/test/unit/data/testfiles/formatting/php82/dnfTypes_01.php b/php/php.editor/test/unit/data/testfiles/formatting/php82/dnfTypes_01.php new file mode 100644 index 000000000000..7fa34460fa32 --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/formatting/php82/dnfTypes_01.php @@ -0,0 +1,190 @@ +publicXField; +/** @var ClassZ|(ClassX&ClassY)|null $vardoc2 */ +$vardoc2->publicXField; +/** @var ClassZ|(ClassX&ClassY)|(ClassX&ClassZ) $vardoc3 */ +$vardoc3->publicXField; + +/* @var $vardoc4 (ClassX&ClassY)|null */ +$vardoc4->publicXField; +/* @var $vardoc5 ClassZ|(ClassX&ClassY)|null */ +$vardoc5->publicXField; +/* @var $vardoc6 ClassZ|(ClassX&ClassY)|(ClassX&ClassZ) */ +$vardoc6->publicXField; + +$closure = function((X&Y&Z)|Y $test1, X|(X&Z)|(Y&Z) $test2): void {}; +$closure = function(int $test): (X&Y&Z)|(X&Z) {}; + +$arrow = fn((X&Y)|(Y&Z) $test) => $test; +$arrow = fn((X&Y)|(Y&Z) $test): (X&Y)|(Y&Z)|(X&Z) => $test; + +$anon = new class($test) { + private (ClassX&ClassY)|ClassZ $property; + + public function __construct((ClassX&ClassY)|ClassZ $property) + { + $this->property = $property; + } + + public function test((ClassX&ClassY)|null $param): (ClassX&ClassY)|(ClassY&ClassZ) { + } +}; diff --git a/php/php.editor/test/unit/data/testfiles/formatting/php82/dnfTypes_01.php.formatted b/php/php.editor/test/unit/data/testfiles/formatting/php82/dnfTypes_01.php.formatted new file mode 100644 index 000000000000..933d833d0e4c --- /dev/null +++ b/php/php.editor/test/unit/data/testfiles/formatting/php82/dnfTypes_01.php.formatted @@ -0,0 +1,281 @@ +publicXField; +/** @var ClassZ|(ClassX&ClassY)|null $vardoc2 */ +$vardoc2->publicXField; +/** @var ClassZ|(ClassX&ClassY)|(ClassX&ClassZ) $vardoc3 */ +$vardoc3->publicXField; + +/* @var $vardoc4 (ClassX&ClassY)|null */ +$vardoc4->publicXField; +/* @var $vardoc5 ClassZ|(ClassX&ClassY)|null */ +$vardoc5->publicXField; +/* @var $vardoc6 ClassZ|(ClassX&ClassY)|(ClassX&ClassZ) */ +$vardoc6->publicXField; + +$closure = function ((X&Y&Z)|Y $test1, X|(X&Z)|(Y&Z) $test2): void { + +}; +$closure = function (int $test): (X&Y&Z)|(X&Z) { + +}; + +$arrow = fn((X&Y)|(Y&Z) $test) => $test; +$arrow = fn((X&Y)|(Y&Z) $test): (X&Y)|(Y&Z)|(X&Z) => $test; + +$anon = new class($test) { + + private (ClassX&ClassY)|ClassZ $property; + + public function __construct((ClassX&ClassY)|ClassZ $property) { + $this->property = $property; + } + + public function test((ClassX&ClassY)|null $param): (ClassX&ClassY)|(ClassY&ClassZ) { + + } +}; diff --git a/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/indent/PHPFormatterTest.java b/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/indent/PHPFormatterTest.java index 6feeccc9e879..b39411588f18 100644 --- a/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/indent/PHPFormatterTest.java +++ b/php/php.editor/test/unit/src/org/netbeans/modules/php/editor/indent/PHPFormatterTest.java @@ -1099,4 +1099,9 @@ public void testReadonlyClasses_01b() throws Exception { HashMap options = new HashMap<>(FmtOptions.getDefaults()); reformatFileContents("testfiles/formatting/php82/readonlyClasses_01b.php", options); } + + public void testDNFTypes_01() throws Exception { + HashMap options = new HashMap<>(FmtOptions.getDefaults()); + reformatFileContents("testfiles/formatting/php82/dnfTypes_01.php", options); + } }