|
4 | 4 | namespace Rector\TypeDeclaration\Rector\ClassMethod; |
5 | 5 |
|
6 | 6 | use PhpParser\Node; |
7 | | -use PhpParser\Node\Expr; |
8 | | -use PhpParser\Node\Expr\Assign; |
9 | | -use PhpParser\Node\Expr\AssignOp\Concat; |
10 | 7 | use PhpParser\Node\Expr\Closure; |
11 | | -use PhpParser\Node\Expr\Variable; |
12 | | -use PhpParser\Node\FunctionLike; |
13 | | -use PhpParser\Node\Identifier; |
14 | | -use PhpParser\Node\NullableType; |
15 | | -use PhpParser\Node\Param; |
16 | | -use PhpParser\Node\Stmt\Class_; |
17 | 8 | use PhpParser\Node\Stmt\ClassMethod; |
18 | 9 | use PhpParser\Node\Stmt\Function_; |
19 | | -use PhpParser\NodeVisitor; |
20 | | -use PHPStan\Type\MixedType; |
21 | | -use PHPStan\Type\Type; |
22 | | -use PHPStan\Type\TypeCombinator; |
23 | | -use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory; |
| 10 | +use Rector\Configuration\Deprecation\Contract\DeprecatedInterface; |
| 11 | +use Rector\Exception\ShouldNotHappenException; |
24 | 12 | use Rector\Rector\AbstractRector; |
25 | 13 | use Rector\ValueObject\PhpVersionFeature; |
26 | | -use Rector\VendorLocker\ParentClassMethodTypeOverrideGuard; |
27 | 14 | use Rector\VersionBonding\Contract\MinPhpVersionInterface; |
28 | 15 | use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; |
29 | 16 | use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; |
30 | 17 | /** |
31 | | - * @see \Rector\Tests\TypeDeclaration\Rector\ClassMethod\StrictStringParamConcatRector\StrictStringParamConcatRectorTest |
| 18 | + * @deprecated This rule is deprecated as it produces too many false positives. |
32 | 19 | */ |
33 | | -final class StrictStringParamConcatRector extends AbstractRector implements MinPhpVersionInterface |
| 20 | +final class StrictStringParamConcatRector extends AbstractRector implements MinPhpVersionInterface, DeprecatedInterface |
34 | 21 | { |
35 | | - /** |
36 | | - * @readonly |
37 | | - */ |
38 | | - private ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard; |
39 | | - /** |
40 | | - * @readonly |
41 | | - */ |
42 | | - private PhpDocInfoFactory $phpDocInfoFactory; |
43 | | - public function __construct(ParentClassMethodTypeOverrideGuard $parentClassMethodTypeOverrideGuard, PhpDocInfoFactory $phpDocInfoFactory) |
44 | | - { |
45 | | - $this->parentClassMethodTypeOverrideGuard = $parentClassMethodTypeOverrideGuard; |
46 | | - $this->phpDocInfoFactory = $phpDocInfoFactory; |
47 | | - } |
48 | 22 | public function getRuleDefinition(): RuleDefinition |
49 | 23 | { |
50 | 24 | return new RuleDefinition('Add string type based on concat use', [new CodeSample(<<<'CODE_SAMPLE' |
@@ -83,108 +57,6 @@ public function provideMinPhpVersion(): int |
83 | 57 | */ |
84 | 58 | public function refactor(Node $node): ?Node |
85 | 59 | { |
86 | | - if ($node instanceof ClassMethod && $this->parentClassMethodTypeOverrideGuard->hasParentClassMethod($node)) { |
87 | | - return null; |
88 | | - } |
89 | | - $hasChanged = \false; |
90 | | - $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($node); |
91 | | - foreach ($node->getParams() as $param) { |
92 | | - if ($param->type instanceof Node) { |
93 | | - continue; |
94 | | - } |
95 | | - $variableConcattedFromParam = $this->resolveVariableConcattedFromParam($param, $node); |
96 | | - if (!$variableConcattedFromParam instanceof Variable) { |
97 | | - continue; |
98 | | - } |
99 | | - $paramDocType = $phpDocInfo->getParamType($this->getName($param)); |
100 | | - if (!$paramDocType instanceof MixedType && !$paramDocType->isString()->yes()) { |
101 | | - continue; |
102 | | - } |
103 | | - $nativeType = $this->nodeTypeResolver->getNativeType($variableConcattedFromParam); |
104 | | - if (!$nativeType instanceof MixedType) { |
105 | | - continue; |
106 | | - } |
107 | | - $subtractedType = $nativeType->getSubtractedType(); |
108 | | - if (!$subtractedType instanceof Type) { |
109 | | - $param->type = new Identifier('string'); |
110 | | - $hasChanged = \true; |
111 | | - continue; |
112 | | - } |
113 | | - if (TypeCombinator::containsNull($subtractedType)) { |
114 | | - $param->type = new NullableType(new Identifier('string')); |
115 | | - $hasChanged = \true; |
116 | | - } |
117 | | - } |
118 | | - if ($hasChanged) { |
119 | | - return $node; |
120 | | - } |
121 | | - return null; |
122 | | - } |
123 | | - /** |
124 | | - * @param \PhpParser\Node\Stmt\ClassMethod|\PhpParser\Node\Stmt\Function_|\PhpParser\Node\Expr\Closure $functionLike |
125 | | - */ |
126 | | - private function resolveVariableConcattedFromParam(Param $param, $functionLike): ?Variable |
127 | | - { |
128 | | - if ($functionLike->stmts === null) { |
129 | | - return null; |
130 | | - } |
131 | | - if ($param->default instanceof Expr && !$this->getType($param->default)->isString()->yes()) { |
132 | | - return null; |
133 | | - } |
134 | | - $paramName = $this->getName($param); |
135 | | - $variableConcatted = null; |
136 | | - $this->traverseNodesWithCallable($functionLike->stmts, function (Node $node) use ($paramName, &$variableConcatted): ?int { |
137 | | - // skip nested class and function nodes |
138 | | - if ($node instanceof FunctionLike || $node instanceof Class_) { |
139 | | - return NodeVisitor::DONT_TRAVERSE_CURRENT_AND_CHILDREN; |
140 | | - } |
141 | | - if ($node instanceof Assign && $node->var instanceof Variable && $this->isName($node->var, $paramName)) { |
142 | | - $variableConcatted = null; |
143 | | - return NodeVisitor::STOP_TRAVERSAL; |
144 | | - } |
145 | | - $expr = $this->resolveAssignConcatVariable($node, $paramName); |
146 | | - if ($expr instanceof Variable) { |
147 | | - $variableConcatted = $expr; |
148 | | - } |
149 | | - $variableBinaryConcat = $this->resolveBinaryConcatVariable($node, $paramName); |
150 | | - if ($variableBinaryConcat instanceof Variable) { |
151 | | - $variableConcatted = $variableBinaryConcat; |
152 | | - } |
153 | | - return null; |
154 | | - }); |
155 | | - return $variableConcatted; |
156 | | - } |
157 | | - private function isVariableWithSameParam(Expr $expr, string $paramName): bool |
158 | | - { |
159 | | - if (!$expr instanceof Variable) { |
160 | | - return \false; |
161 | | - } |
162 | | - return $this->isName($expr, $paramName); |
163 | | - } |
164 | | - private function resolveAssignConcatVariable(Node $node, string $paramName): ?Expr |
165 | | - { |
166 | | - if (!$node instanceof Concat) { |
167 | | - return null; |
168 | | - } |
169 | | - if ($this->isVariableWithSameParam($node->var, $paramName)) { |
170 | | - return $node->var; |
171 | | - } |
172 | | - if ($this->isVariableWithSameParam($node->expr, $paramName)) { |
173 | | - return $node->expr; |
174 | | - } |
175 | | - return null; |
176 | | - } |
177 | | - private function resolveBinaryConcatVariable(Node $node, string $paramName): ?Expr |
178 | | - { |
179 | | - if (!$node instanceof Expr\BinaryOp\Concat) { |
180 | | - return null; |
181 | | - } |
182 | | - if ($this->isVariableWithSameParam($node->left, $paramName)) { |
183 | | - return $node->left; |
184 | | - } |
185 | | - if ($this->isVariableWithSameParam($node->right, $paramName)) { |
186 | | - return $node->right; |
187 | | - } |
188 | | - return null; |
| 60 | + throw new ShouldNotHappenException(sprintf('"%s" is deprecated as it produces too many false positives. Add the type manually where needed instead', self::class)); |
189 | 61 | } |
190 | 62 | } |
0 commit comments