ai_upgrade_assistant-0.2.0-alpha2/src/Service/NodeVisitor/PluginPatternVisitor.php
src/Service/NodeVisitor/PluginPatternVisitor.php
<?php
namespace Drupal\ai_upgrade_assistant\Service\NodeVisitor;
use PhpParser\Node;
use PhpParser\NodeVisitorAbstract;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
/**
* Analyzes Drupal plugin patterns and annotations.
*/
class PluginPatternVisitor extends NodeVisitorAbstract {
/**
* Collected plugin findings.
*
* @var array
*/
protected $findings = [];
/**
* Current class being analyzed.
*
* @var string|null
*/
protected $currentClass = null;
/**
* {@inheritdoc}
*/
public function enterNode(Node $node) {
if ($node instanceof Class_) {
$this->currentClass = $node->name->toString();
$this->analyzePluginAnnotations($node);
}
elseif ($node instanceof ClassMethod && $this->currentClass) {
$this->analyzePluginMethods($node);
}
}
/**
* Analyzes plugin annotations in class docblock.
*
* @param \PhpParser\Node\Stmt\Class_ $node
* The class node.
*/
protected function analyzePluginAnnotations(Class_ $node) {
$docComment = $node->getDocComment();
if ($docComment) {
$docText = $docComment->getText();
// Common plugin annotation patterns
$patterns = [
'Block' => '/@Block\s*\((.*?)\)/s',
'Field' => '/@FieldFormatter\s*\((.*?)\)/s',
'Action' => '/@Action\s*\((.*?)\)/s',
'EntityType' => '/@EntityType\s*\((.*?)\)/s',
'Views' => '/@ViewsField|@ViewsFilter|@ViewsSort|@ViewsArgument/s',
'Condition' => '/@Condition\s*\((.*?)\)/s',
'Constraint' => '/@Constraint\s*\((.*?)\)/s',
];
foreach ($patterns as $type => $pattern) {
if (preg_match($pattern, $docText, $matches)) {
$this->findings['plugins'][] = [
'type' => $type,
'class' => $this->currentClass,
'annotation' => $matches[0],
'line' => $node->getLine(),
];
}
}
}
// Check class implements and extends
if ($node->implements) {
foreach ($node->implements as $interface) {
$name = $interface->toString();
if (strpos($name, 'Drupal\\') === 0) {
$this->findings['interfaces'][] = [
'class' => $this->currentClass,
'interface' => $name,
'line' => $node->getLine(),
];
}
}
}
if ($node->extends) {
$extends = $node->extends->toString();
if (strpos($extends, 'Drupal\\') === 0) {
$this->findings['extends'][] = [
'class' => $this->currentClass,
'extends' => $extends,
'line' => $node->getLine(),
];
}
}
}
/**
* Analyzes plugin methods for common patterns.
*
* @param \PhpParser\Node\Stmt\ClassMethod $node
* The class method node.
*/
protected function analyzePluginMethods(ClassMethod $node) {
$methodName = $node->name->toString();
// Common plugin method patterns
$pluginMethods = [
'build' => 'Block',
'viewElements' => 'Field',
'execute' => 'Action',
'defaultConfiguration' => 'ConfigurableInterface',
'buildConfigurationForm' => 'ConfigurableInterface',
'submitConfigurationForm' => 'ConfigurableInterface',
'validateConfigurationForm' => 'ConfigurableInterface',
];
if (isset($pluginMethods[$methodName])) {
$this->findings['methods'][] = [
'class' => $this->currentClass,
'method' => $methodName,
'plugin_type' => $pluginMethods[$methodName],
'line' => $node->getLine(),
'visibility' => $node->isPublic() ? 'public' : ($node->isProtected() ? 'protected' : 'private'),
];
}
// Check for deprecated method usage
$docComment = $node->getDocComment();
if ($docComment && strpos($docComment->getText(), '@deprecated') !== false) {
$this->findings['deprecated_methods'][] = [
'class' => $this->currentClass,
'method' => $methodName,
'line' => $node->getLine(),
];
}
}
/**
* Gets all findings.
*
* @return array
* Array of findings.
*/
public function getFindings() {
return $this->findings;
}
/**
* Resets the visitor's state.
*/
public function reset() {
$this->findings = [];
$this->currentClass = null;
}
}
