Get better error message for duplicate names in MagicWordArray
authorUmherirrender <umherirrender_de.wp@web.de>
Thu, 3 Aug 2017 20:52:22 +0000 (22:52 +0200)
committerKrinkle <krinklemail@gmail.com>
Fri, 11 Aug 2017 14:26:20 +0000 (14:26 +0000)
Actually php says:
Warning: Compilation failed: two named subpatterns have the same name at
offset 679

The message is not helpful to find the duplicate name inside the
MagicWordArray, because the generated regex is unknown to count the
correct offset.
Try to detect such duplicates and throw an exception with more
information and a stacktrace.

Change-Id: I95dea67da06aa4000d52ac3338c3b865450b3e23

includes/MagicWordArray.php

index 6a9ead5..1c27833 100644 (file)
@@ -95,13 +95,22 @@ class MagicWordArray {
        public function getBaseRegex() {
                if ( is_null( $this->baseRegex ) ) {
                        $this->baseRegex = [ 0 => '', 1 => '' ];
+                       $allGroups = [];
                        foreach ( $this->names as $name ) {
                                $magic = MagicWord::get( $name );
                                $case = intval( $magic->isCaseSensitive() );
                                foreach ( $magic->getSynonyms() as $i => $syn ) {
                                        // Group name must start with a non-digit in PCRE 8.34+
                                        $it = strtr( $i, '0123456789', 'abcdefghij' );
-                                       $group = "(?P<{$it}_{$name}>" . preg_quote( $syn, '/' ) . ')';
+                                       $groupName = $it . '_' . $name;
+                                       $group = '(?P<' . $groupName . '>' . preg_quote( $syn, '/' ) . ')';
+                                       // look for same group names to avoid same named subpatterns in the regex
+                                       if ( isset( $allGroups[$groupName] ) ) {
+                                               throw new MWException(
+                                                       __METHOD__ . ': duplicate internal name in magic word array: ' . $name
+                                               );
+                                       }
+                                       $allGroups[$groupName] = true;
                                        if ( $this->baseRegex[$case] === '' ) {
                                                $this->baseRegex[$case] = $group;
                                        } else {