From abfe2eea126c6c126ee3a458da3f10bca7687084 Mon Sep 17 00:00:00 2001 From: Jakub Vrana Date: Fri, 23 Oct 2026 08:40:10 +0200 Subject: [PATCH] configure: remove overridden inherited methods from class synopses Class synopses include the methods of parents and interfaces by XInclude, so a method the class overrides was listed twice, e.g. ReflectionFunction::__toString() and ReflectionFunctionAbstract::__toString(). After expanding XIncludes, keep only the first method of each name. Overloads (same class and method name) are kept. This removes 181 duplicate methods from the manual. Co-Authored-By: Claude Opus 5.5 --- configure.php | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/configure.php b/configure.php index 65104fdf1a..43f7bb0340 100755 --- a/configure.php +++ b/configure.php @@ -823,6 +823,62 @@ function xml_broken_files_check() xinclude_residual_fixup( $dom ); +echo "Removing overridden inherited methods... "; +$total = classsynopsis_remove_overridden( $dom ); +echo "done: $total methods.\n"; + +function classsynopsis_remove_overridden( DOMDocument $dom ) : int +{ + // Class synopses include the methods of their parents and interfaces + // by XInclude, so a method the class overrides is listed twice: + // e.g. ReflectionFunction::__toString() and ReflectionFunctionAbstract::__toString(). + // Keep the first one (own methods are listed before inherited ones), + // and remove later ones of other classes with the same name. + // Overloads (same class and method name) are kept. + + $total = 0; + $xpath = new DOMXPath( $dom ); + $xpath->registerNamespace( "db" , "http://docbook.org/ns/docbook" ); + $members = "db:methodsynopsis|db:constructorsynopsis|db:destructorsynopsis"; + + foreach( $xpath->query( "//db:classsynopsis" ) as $classsynopsis ) + { + $seen = []; + $headers = []; + foreach( $xpath->query( $members , $classsynopsis ) as $member ) + { + $name = strtolower( trim( $xpath->evaluate( "string(db:methodname)" , $member ) ) ); + $short = preg_replace( '/^.*::/' , '' , $name ); + $first = $seen[ $short ] ??= $name; + + if ( $first === $name ) + continue; + + $header = $xpath->query( "preceding-sibling::db:classsynopsisinfo[@role='comment'][1]" , $member )->item( 0 ); + if ( $header !== null ) + $headers[] = $header; + + $member->parentNode->removeChild( $member ); + $total++; + } + + // Remove section headers like "Inherited methods" left without members. + + foreach( $headers as $header ) + { + if ( $header->parentNode === null ) + continue; + $next = $header->nextSibling; + while ( $next !== null && $next->nodeType !== XML_ELEMENT_NODE ) + $next = $next->nextSibling; + if ( $next === null || $next->localName === "classsynopsisinfo" ) + $header->parentNode->removeChild( $header ); + } + } + + return $total; +} + function xinclude_remove_fallback( DOMDocument $dom ) { // Check if there is reachable s.