@@ -129,32 +129,42 @@ services:
129
129
use ReflectionMethod;
130
130
use ShipMonk\PHPStan\DeadCode\Provider\ReflectionBasedMemberUsageProvider;
131
131
132
- class ApiOutputUsageProvider extends ReflectionBasedMemberUsageProvider
132
+ class FuzzyTwigUsageProvider extends ReflectionBasedMemberUsageProvider
133
133
{
134
134
135
135
public function shouldMarkMethodAsUsed(ReflectionMethod $method): bool
136
136
{
137
- // all methods from our ApiOutput interface are called automatically (e.g. during serialization)
138
- return $method->getDeclaringClass()->implementsInterface(ApiOutput::class);
137
+ return $method->getDeclaringClass()->implementsInterface(UsedInTwigMarkerInterface::class);
139
138
}
140
139
141
140
}
142
141
```
143
142
144
143
### AST-based customization:
145
- - For more complex usecases that are deducible only from AST (e.g. serialization calls), you just stick with raw ` MemberUsageProvider ` interface:
144
+ - For more complex usecases that are deducible only from AST, you just stick with raw ` MemberUsageProvider ` interface.
145
+ - Here is simplified example how to emit ` User::__construct ` usage in following PHP snippet:
146
146
147
147
``` php
148
+ function test(SerializerInterface $serializer): User {
149
+ return $serializer->deserialize('{"name": "John"}', User::class, 'json');
150
+ }
151
+ ```
148
152
153
+ ``` php
149
154
use ReflectionMethod;
150
155
use ShipMonk\PHPStan\DeadCode\Graph\ClassMethodRef;
151
156
use ShipMonk\PHPStan\DeadCode\Graph\ClassMethodUsage;
157
+ use ShipMonk\PHPStan\DeadCode\Graph\UsageOriginDetector;
152
158
use ShipMonk\PHPStan\DeadCode\Provider\MemberUsageProvider;
153
159
use Symfony\Component\Serializer\SerializerInterface;
154
160
155
161
class DeserializationUsageProvider implements MemberUsageProvider
156
162
{
157
163
164
+ public function __construct(
165
+ private UsageOriginDetector $originDetector,
166
+ ) {}
167
+
158
168
/**
159
169
* @return list<ClassMemberUsage >
160
170
*/
@@ -173,7 +183,7 @@ class DeserializationUsageProvider implements MemberUsageProvider
173
183
$serializedClass = $scope->getType($secondArgument)->getConstantStrings()[0];
174
184
175
185
// record the method it was called from (needed for proper transitive dead code elimination)
176
- $originRef = $this->getOriginMethodRef( $scope);
186
+ $originRef = $this->originDetector->detectOrigin($node, $scope);
177
187
178
188
// record the hidden constructor call
179
189
$constructorRef = new ClassMethodRef($serializedClass->getValue(), '__construct', false);
@@ -184,15 +194,6 @@ class DeserializationUsageProvider implements MemberUsageProvider
184
194
return [];
185
195
}
186
196
187
- private function getOriginMethodRef(Scope $scope): ?ClassMethodRef
188
- {
189
- return new ClassMethodRef(
190
- $scope->getClassReflection()->getName(),
191
- $scope->getFunction()->getName(),
192
- false,
193
- );
194
- }
195
-
196
197
}
197
198
```
198
199
0 commit comments