ai_upgrade_assistant-0.2.0-alpha2/src/Service/MachineLearning/Visitor/SemanticPatternVisitor.php
src/Service/MachineLearning/Visitor/SemanticPatternVisitor.php
<?php
namespace Drupal\ai_upgrade_assistant\Service\MachineLearning\Visitor;
use PhpParser\Node;
use PhpParser\NodeVisitorAbstract;
/**
* Visitor for extracting semantic patterns from code.
*/
class SemanticPatternVisitor extends NodeVisitorAbstract {
/**
* Collected patterns.
*
* @var array
*/
protected $patterns = [];
/**
* Current class context.
*
* @var array
*/
protected $classContext = [];
/**
* Current function context.
*
* @var array
*/
protected $functionContext = [];
/**
* {@inheritdoc}
*/
public function beforeTraverse(array $nodes) {
$this->patterns = [
'drupal_patterns' => [],
'dependency_patterns' => [],
'api_usage_patterns' => [],
'data_flow_patterns' => [],
'error_handling_patterns' => [],
'security_patterns' => [],
];
return null;
}
/**
* {@inheritdoc}
*/
public function enterNode(Node $node) {
if ($node instanceof Node\Stmt\Class_) {
$this->enterClass($node);
}
elseif ($node instanceof Node\Stmt\ClassMethod) {
$this->enterFunction($node);
}
elseif ($node instanceof Node\Expr\MethodCall) {
$this->analyzeMethodCall($node);
}
elseif ($node instanceof Node\Expr\StaticCall) {
$this->analyzeStaticCall($node);
}
elseif ($node instanceof Node\Expr\FuncCall) {
$this->analyzeFunctionCall($node);
}
}
/**
* {@inheritdoc}
*/
public function leaveNode(Node $node) {
if ($node instanceof Node\Stmt\Class_) {
$this->classContext = [];
}
elseif ($node instanceof Node\Stmt\ClassMethod) {
$this->functionContext = [];
}
}
/**
* Enters a class node.
*/
protected function enterClass(Node\Stmt\Class_ $node) {
$this->classContext = [
'name' => $node->name->toString(),
'extends' => $node->extends ? $node->extends->toString() : null,
'implements' => array_map(
function ($interface) {
return $interface->toString();
},
$node->implements
),
];
// Analyze Drupal-specific patterns
$this->analyzeDrupalClassPattern($node);
}
/**
* Enters a function node.
*/
protected function enterFunction(Node\Stmt\ClassMethod $node) {
$this->functionContext = [
'name' => $node->name->toString(),
'class' => $this->classContext,
];
// Analyze Drupal hook patterns
if (strpos($node->name->toString(), 'hook_') === 0) {
$this->analyzeDrupalHookPattern($node);
}
}
/**
* Analyzes Drupal class patterns.
*/
protected function analyzeDrupalClassPattern(Node\Stmt\Class_ $node) {
$drupal_base_classes = [
'Drupal\Core\Form\FormBase' => 'form',
'Drupal\Core\Config\Entity\ConfigEntityBase' => 'config_entity',
'Drupal\Core\Entity\ContentEntityBase' => 'content_entity',
'Drupal\Core\Plugin\PluginBase' => 'plugin',
];
foreach ($drupal_base_classes as $base_class => $type) {
if ($this->classContext['extends'] === $base_class) {
$this->patterns['drupal_patterns'][] = [
'type' => $type,
'class' => $this->classContext['name'],
'semantic_type' => 'class_inheritance',
];
}
}
}
/**
* Analyzes Drupal hook patterns.
*/
protected function analyzeDrupalHookPattern(Node\Stmt\ClassMethod $node) {
$this->patterns['drupal_patterns'][] = [
'type' => 'hook',
'name' => $node->name->toString(),
'class' => $this->classContext['name'],
'semantic_type' => 'hook_implementation',
];
}
/**
* Analyzes method calls.
*/
protected function analyzeMethodCall(Node\Expr\MethodCall $node) {
// Analyze API usage patterns
$this->analyzeApiUsagePattern($node);
// Analyze data flow patterns
$this->analyzeDataFlowPattern($node);
// Analyze error handling patterns
$this->analyzeErrorHandlingPattern($node);
// Analyze security patterns
$this->analyzeSecurityPattern($node);
}
/**
* Analyzes static calls.
*/
protected function analyzeStaticCall(Node\Expr\StaticCall $node) {
if ($node->class instanceof Node\Name) {
$class = $node->class->toString();
// Analyze Drupal service container usage
if ($class === 'Drupal') {
$this->analyzeDrupalServicePattern($node);
}
}
}
/**
* Analyzes function calls.
*/
protected function analyzeFunctionCall(Node\Expr\FuncCall $node) {
if ($node->name instanceof Node\Name) {
$name = $node->name->toString();
// Analyze Drupal function patterns
if (strpos($name, 'drupal_') === 0) {
$this->patterns['drupal_patterns'][] = [
'type' => 'function',
'name' => $name,
'semantic_type' => 'drupal_function',
'context' => $this->functionContext,
];
}
}
}
/**
* Analyzes API usage patterns.
*/
protected function analyzeApiUsagePattern(Node\Expr\MethodCall $node) {
$api_patterns = [
'save' => 'entity_api',
'load' => 'entity_api',
'delete' => 'entity_api',
'query' => 'database_api',
'select' => 'database_api',
'insert' => 'database_api',
'update' => 'database_api',
'delete' => 'database_api',
'render' => 'render_api',
'buildForm' => 'form_api',
'validateForm' => 'form_api',
'submitForm' => 'form_api',
];
$method_name = $node->name->toString();
if (isset($api_patterns[$method_name])) {
$this->patterns['api_usage_patterns'][] = [
'type' => $api_patterns[$method_name],
'method' => $method_name,
'semantic_type' => 'api_call',
'context' => $this->functionContext,
];
}
}
/**
* Analyzes data flow patterns.
*/
protected function analyzeDataFlowPattern(Node\Expr\MethodCall $node) {
$data_flow_methods = [
'get' => 'data_retrieval',
'set' => 'data_storage',
'has' => 'data_check',
'delete' => 'data_deletion',
];
$method_name = $node->name->toString();
if (isset($data_flow_methods[$method_name])) {
$this->patterns['data_flow_patterns'][] = [
'type' => $data_flow_methods[$method_name],
'method' => $method_name,
'semantic_type' => 'data_flow',
'context' => $this->functionContext,
];
}
}
/**
* Analyzes error handling patterns.
*/
protected function analyzeErrorHandlingPattern(Node\Expr\MethodCall $node) {
$error_methods = [
'logException' => 'exception_logging',
'logError' => 'error_logging',
'handleException' => 'exception_handling',
];
$method_name = $node->name->toString();
if (isset($error_methods[$method_name])) {
$this->patterns['error_handling_patterns'][] = [
'type' => $error_methods[$method_name],
'method' => $method_name,
'semantic_type' => 'error_handling',
'context' => $this->functionContext,
];
}
}
/**
* Analyzes security patterns.
*/
protected function analyzeSecurityPattern(Node\Expr\MethodCall $node) {
$security_methods = [
'checkAccess' => 'access_check',
'sanitize' => 'sanitization',
'escape' => 'escaping',
'validate' => 'validation',
];
$method_name = $node->name->toString();
if (isset($security_methods[$method_name])) {
$this->patterns['security_patterns'][] = [
'type' => $security_methods[$method_name],
'method' => $method_name,
'semantic_type' => 'security',
'context' => $this->functionContext,
];
}
}
/**
* Analyzes Drupal service container usage.
*/
protected function analyzeDrupalServicePattern(Node\Expr\StaticCall $node) {
if ($node->name->toString() === 'service') {
if (isset($node->args[0]) && $node->args[0]->value instanceof Node\Scalar\String_) {
$service_name = $node->args[0]->value->value;
$this->patterns['dependency_patterns'][] = [
'type' => 'service_usage',
'service' => $service_name,
'semantic_type' => 'dependency_injection',
'context' => $this->functionContext,
];
}
}
}
/**
* Gets collected patterns.
*
* @return array
* The collected patterns.
*/
public function getPatterns() {
return $this->patterns;
}
}
