diff --git a/phpstan.neon.dist b/phpstan.neon.dist index e61c7d525fe91..d6ba7f5511b3b 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -42,8 +42,6 @@ includes: - tests/phpstan/baselines/function.alreadyNarrowedType.neon - tests/phpstan/baselines/function.impossibleType.neon - tests/phpstan/baselines/function.resultUnused.neon - - tests/phpstan/baselines/greater.alwaysTrue.neon - - tests/phpstan/baselines/greaterOrEqual.alwaysFalse.neon - tests/phpstan/baselines/greaterOrEqual.alwaysTrue.neon - tests/phpstan/baselines/identical.alwaysFalse.neon - tests/phpstan/baselines/identical.alwaysTrue.neon @@ -152,3 +150,16 @@ parameters: message: '#^Parameter \#4 \$length of function substr_compare expects int, null given\.$#' path: src/wp-includes/html-api/class-wp-html-tag-processor.php reportUnmatched: false + + # HTML API: + # These errors are ignored for the sake of making it easier to keep the HTML Processor in sync with the HTML spec. + - + message: '#^Comparison operation "\>" between 999\|1000 and 0 is always true\.$#' + identifier: greater.alwaysTrue + count: 1 + path: src/wp-includes/html-api/class-wp-html-processor.php + - + message: '#^Comparison operation "\>\=" between 0 and 8 is always false\.$#' + identifier: greaterOrEqual.alwaysFalse + count: 1 + path: src/wp-includes/html-api/class-wp-html-processor.php diff --git a/src/wp-includes/html-api/class-wp-html-processor.php b/src/wp-includes/html-api/class-wp-html-processor.php index c278cca8b0e23..9eceb18729c1f 100644 --- a/src/wp-includes/html-api/class-wp-html-processor.php +++ b/src/wp-includes/html-api/class-wp-html-processor.php @@ -1585,7 +1585,6 @@ private function step_initial(): bool { return $this->step(); } goto initial_anything_else; - break; /* * > A comment token @@ -1678,7 +1677,6 @@ private function step_before_html(): bool { return $this->step(); } goto before_html_anything_else; - break; /* * > A start tag whose tag name is "html" @@ -1700,7 +1698,6 @@ private function step_before_html(): bool { * > Act as described in the "anything else" entry below. */ goto before_html_anything_else; - break; } /* @@ -1760,7 +1757,6 @@ private function step_before_head(): bool { return $this->step(); } goto before_head_anything_else; - break; /* * > A comment token @@ -1805,7 +1801,6 @@ private function step_before_head(): bool { case '-BODY': case '-HTML': goto before_head_anything_else; - break; } if ( $is_closer ) { @@ -1861,7 +1856,6 @@ private function step_in_head(): bool { } goto in_head_anything_else; - break; /* * > A comment token @@ -1993,7 +1987,6 @@ private function step_in_head(): bool { * > Act as described in the "anything else" entry below. */ goto in_head_anything_else; - break; /* * > A start tag whose tag name is "template" @@ -2086,7 +2079,6 @@ private function step_in_head_noscript(): bool { } goto in_head_noscript_anything_else; - break; /* * > A DOCTYPE token @@ -2190,7 +2182,6 @@ private function step_after_head(): bool { return true; } goto after_head_anything_else; - break; /* * > A comment token @@ -2279,7 +2270,6 @@ private function step_after_head(): bool { * > Act as described in the "anything else" entry below. */ goto after_head_anything_else; - break; } /* @@ -2783,28 +2773,27 @@ private function step_in_body(): bool { $this->state->stack_of_open_elements->remove_node( $node ); return true; - } else { - /* - * > If the stack of open elements does not have a form element in scope, - * > then this is a parse error; return and ignore the token. - * - * Note that unlike in the clause above, this is checking for any FORM in scope. - */ - if ( ! $this->state->stack_of_open_elements->has_element_in_scope( 'FORM' ) ) { - // Parse error: ignore the token. - return $this->step(); - } + } - $this->generate_implied_end_tags(); + /* + * > If the stack of open elements does not have a form element in scope, + * > then this is a parse error; return and ignore the token. + * + * Note that unlike in the clause above, this is checking for any FORM in scope. + */ + if ( ! $this->state->stack_of_open_elements->has_element_in_scope( 'FORM' ) ) { + // Parse error: ignore the token. + return $this->step(); + } - if ( ! $this->state->stack_of_open_elements->current_node_is( 'FORM' ) ) { - // @todo Indicate a parse error once it's possible. This error does not impact the logic here. - } + $this->generate_implied_end_tags(); - $this->state->stack_of_open_elements->pop_until( 'FORM' ); - return true; + if ( ! $this->state->stack_of_open_elements->current_node_is( 'FORM' ) ) { + // @todo Indicate a parse error once it's possible. This error does not impact the logic here. } - break; + + $this->state->stack_of_open_elements->pop_until( 'FORM' ); + return true; /* * > An end tag whose tag name is "p" @@ -3366,10 +3355,6 @@ private function step_in_body(): bool { */ return $this->in_body_any_other_end_tag(); } - - $this->bail( 'Should not have been able to reach end of IN BODY processing. Check HTML API code.' ); - // This unnecessary return prevents tools from inaccurately reporting type errors. - return false; } /** @@ -3418,8 +3403,6 @@ private function in_body_any_other_end_tag(): bool { } $this->bail( 'Should not have been able to reach end of "any other end tag" IN BODY processing. Check HTML API code.' ); - // This unnecessary return prevents tools from inaccurately reporting type errors. - return false; } /** @@ -3496,7 +3479,6 @@ private function step_in_table(): bool { // Non-whitespace would trigger fostering, unsupported at this time. $this->bail( 'Foster parenting is not supported.' ); - break; } break; @@ -3821,7 +3803,6 @@ private function step_in_column_group(): bool { } goto in_column_group_anything_else; - break; /* * > A comment token @@ -4382,7 +4363,6 @@ private function step_after_body(): bool { return $this->step_in_body(); } goto after_body_anything_else; - break; /* * > A comment token @@ -4705,7 +4685,6 @@ private function step_after_after_body(): bool { return $this->step_in_body(); } goto after_after_body_anything_else; - break; } /* @@ -4984,20 +4963,18 @@ private function step_in_foreign_content(): bool { $this->state->stack_of_open_elements->pop(); } return true; - } - - /* - * > An end tag whose name is "script", if the current node is an SVG script element. - */ - if ( $this->is_tag_closer() && 'SCRIPT' === $this->state->current_token->node_name && 'svg' === $this->state->current_token->namespace ) { - $this->state->stack_of_open_elements->pop(); - return true; - } + } else { + /* + * > An end tag whose name is "script", if the current node is an SVG script element. + */ + if ( 'SCRIPT' === $this->state->current_token->node_name && 'svg' === $this->state->current_token->namespace ) { + $this->state->stack_of_open_elements->pop(); + return true; + } - /* - * > Any other end tag - */ - if ( $this->is_tag_closer() ) { + /* + * > Any other end tag + */ $node = $this->state->stack_of_open_elements->current_node(); if ( $tag_name !== $node->node_name ) { // @todo Indicate a parse error once it's possible. @@ -5097,10 +5074,6 @@ private function step_in_foreign_content(): bool { $this->bail( "Unaware of the requested parsing mode: '{$this->state->insertion_mode}'." ); } } - - $this->bail( 'Should not have been able to reach end of IN FOREIGN CONTENT processing. Check HTML API code.' ); - // This unnecessary return prevents tools from inaccurately reporting type errors. - return false; } /* @@ -6388,8 +6361,6 @@ private function is_html_integration_point(): bool { } $this->bail( 'Should not have reached end of HTML Integration Point detection: check HTML API code.' ); - // This unnecessary return prevents tools from inaccurately reporting type errors. - return false; } /** diff --git a/tests/phpstan/baselines/booleanAnd.leftAlwaysTrue.neon b/tests/phpstan/baselines/booleanAnd.leftAlwaysTrue.neon index 69e4b48b16039..2ea5a45c3cfc2 100644 --- a/tests/phpstan/baselines/booleanAnd.leftAlwaysTrue.neon +++ b/tests/phpstan/baselines/booleanAnd.leftAlwaysTrue.neon @@ -33,8 +33,3 @@ parameters: identifier: booleanAnd.leftAlwaysTrue count: 1 path: ../../../src/wp-includes/canonical.php - - - message: '#^Left side of && is always true\.$#' - identifier: booleanAnd.leftAlwaysTrue - count: 1 - path: ../../../src/wp-includes/html-api/class-wp-html-processor.php diff --git a/tests/phpstan/baselines/deadCode.unreachable.neon b/tests/phpstan/baselines/deadCode.unreachable.neon index 2282799c3903d..22f5a17da9286 100644 --- a/tests/phpstan/baselines/deadCode.unreachable.neon +++ b/tests/phpstan/baselines/deadCode.unreachable.neon @@ -56,7 +56,7 @@ parameters: - message: '#^Unreachable statement \- code above always terminates\.$#' identifier: deadCode.unreachable - count: 31 + count: 12 path: ../../../src/wp-includes/html-api/class-wp-html-processor.php - message: '#^Unreachable statement \- code above always terminates\.$#' diff --git a/tests/phpstan/baselines/greater.alwaysTrue.neon b/tests/phpstan/baselines/greater.alwaysTrue.neon deleted file mode 100644 index 897d88c5ee83f..0000000000000 --- a/tests/phpstan/baselines/greater.alwaysTrue.neon +++ /dev/null @@ -1,25 +0,0 @@ -# PHPStan baseline for the `greater.alwaysTrue` errors in WordPress core. -# -# https://phpstan.org/error-identifiers/greater.alwaysTrue -# -# Each entry is scoped to a single file and carries an exact occurrence count, -# so that a new instance is reported as a new error rather than being absorbed -# silently. Fixing an occurrence therefore means decrementing or removing its -# entry here as part of the same change. -# -# The goal is to empty this file and delete it, along with the `includes` entry -# for it in phpstan.neon.dist. -# -# Generated by `composer phpstan:baselines`. Do not edit by hand; regenerate with -# -# composer phpstan:baselines -- --identifier=greater.alwaysTrue -# -# which reruns the analysis with this file suppressed so the errors surface again. - -parameters: - ignoreErrors: - - - message: '#^Comparison operation "\>" between 999\|1000 and 0 is always true\.$#' - identifier: greater.alwaysTrue - count: 1 - path: ../../../src/wp-includes/html-api/class-wp-html-processor.php diff --git a/tests/phpstan/baselines/greaterOrEqual.alwaysFalse.neon b/tests/phpstan/baselines/greaterOrEqual.alwaysFalse.neon deleted file mode 100644 index 8010e78a6979a..0000000000000 --- a/tests/phpstan/baselines/greaterOrEqual.alwaysFalse.neon +++ /dev/null @@ -1,25 +0,0 @@ -# PHPStan baseline for the `greaterOrEqual.alwaysFalse` errors in WordPress core. -# -# https://phpstan.org/error-identifiers/greaterOrEqual.alwaysFalse -# -# Each entry is scoped to a single file and carries an exact occurrence count, -# so that a new instance is reported as a new error rather than being absorbed -# silently. Fixing an occurrence therefore means decrementing or removing its -# entry here as part of the same change. -# -# The goal is to empty this file and delete it, along with the `includes` entry -# for it in phpstan.neon.dist. -# -# Generated by `composer phpstan:baselines`. Do not edit by hand; regenerate with -# -# composer phpstan:baselines -- --identifier=greaterOrEqual.alwaysFalse -# -# which reruns the analysis with this file suppressed so the errors surface again. - -parameters: - ignoreErrors: - - - message: '#^Comparison operation "\>\=" between 0 and 8 is always false\.$#' - identifier: greaterOrEqual.alwaysFalse - count: 1 - path: ../../../src/wp-includes/html-api/class-wp-html-processor.php diff --git a/tests/phpstan/baselines/if.alwaysTrue.neon b/tests/phpstan/baselines/if.alwaysTrue.neon index 6888b9780b5f9..ffd7d9081b25f 100644 --- a/tests/phpstan/baselines/if.alwaysTrue.neon +++ b/tests/phpstan/baselines/if.alwaysTrue.neon @@ -46,5 +46,5 @@ parameters: - message: '#^If condition is always true\.$#' identifier: if.alwaysTrue - count: 2 + count: 1 path: ../../../src/wp-includes/html-api/class-wp-html-processor.php