@@ -37,25 +37,27 @@ public function work(string $docContent, Tokens $tokens, int $position): string
3737
3838 $ paramNames = $ this ->getParamNames ($ docContent );
3939
40+ $ missArgumentNames = [];
4041 // remove correct params
4142 foreach ($ argumentNames as $ key => $ argumentName ) {
4243 if (in_array ($ argumentName , $ paramNames , true )) {
4344 $ paramPosition = array_search ($ argumentName , $ paramNames , true );
4445 unset($ paramNames [$ paramPosition ]);
45- unset($ argumentNames [$ key ]);
46+ } else {
47+ $ missArgumentNames [$ key ] = $ argumentName ;
4648 }
4749 }
4850
4951 // nothing to edit, all arguments are correct or there are no more @param annotations
50- if ($ argumentNames === []) {
52+ if ($ missArgumentNames === []) {
5153 return $ docContent ;
5254 }
5355
5456 if ($ paramNames === []) {
5557 return $ docContent ;
5658 }
5759
58- return $ this ->fixTypos ($ argumentNames , $ paramNames , $ docContent );
60+ return $ this ->fixTypos ($ argumentNames , $ missArgumentNames , $ paramNames , $ docContent );
5961 }
6062
6163 /**
@@ -93,20 +95,36 @@ private function getAnnotationsOfType(string $docContent, string $type): array
9395
9496 /**
9597 * @param string[] $argumentNames
98+ * @param string[] $missArgumentNames
9699 * @param string[] $paramNames
97100 */
98- private function fixTypos (array $ argumentNames , array $ paramNames , string $ docContent ): string
101+ private function fixTypos (array $ argumentNames , array $ missArgumentNames , array $ paramNames , string $ docContent ): string
99102 {
100- foreach ($ argumentNames as $ key => $ argumentName ) {
103+ // A table of permuted params. initialized by $argumentName instead of $paramNames is correct
104+ $ replacedParams = array_fill_keys ($ argumentNames , false );
105+
106+ foreach ($ missArgumentNames as $ key => $ argumentName ) {
101107 // 1. the same position
102108 if (! isset ($ paramNames [$ key ])) {
103109 continue ;
104110 }
105111
106112 $ typoName = $ paramNames [$ key ];
107- $ replacePattern = '#@param(.*?) ' . preg_quote ($ typoName , '# ' ) . '# ' ;
113+ $ replacePattern = '#@param(.*?)( ' . preg_quote ($ typoName , '# ' ) . '\b)# ' ;
114+
115+ $ docContent = Strings::replace ($ docContent , $ replacePattern , static function ($ matched ) use ($ argumentName , &$ replacedParams ) {
116+ $ paramName = $ matched [2 ];
117+
118+ // 2. If the PHPDoc $paramName is one of the existing $argumentNames and has not already been replaced, it will be deferred
119+ if (isset ($ replacedParams [$ paramName ]) && ! $ replacedParams [$ paramName ]) {
120+ $ replacedParams [$ paramName ] = true ;
121+
122+ return $ matched [0 ];
123+ }
108124
109- $ docContent = Strings::replace ($ docContent , $ replacePattern , '@param$1 ' . $ argumentName );
125+ // 3. Otherwise, replace $paramName with $argumentName in the @param line
126+ return sprintf ('@param%s%s ' , $ matched [1 ], $ argumentName );
127+ });
110128 }
111129
112130 return $ docContent ;
0 commit comments