ai_upgrade_assistant-0.2.0-alpha2/src/Service/MachineLearning/Visitor/SyntaxPatternVisitor.php
src/Service/MachineLearning/Visitor/SyntaxPatternVisitor.php
<?php
namespace Drupal\ai_upgrade_assistant\Service\MachineLearning\Visitor;
use PhpParser\Node;
use PhpParser\NodeVisitorAbstract;
/**
* Visitor for extracting syntax patterns from code.
*/
class SyntaxPatternVisitor extends NodeVisitorAbstract {
/**
* Collected patterns.
*
* @var array
*/
protected $patterns = [];
/**
* Current context stack.
*
* @var array
*/
protected $contextStack = [];
/**
* {@inheritdoc}
*/
public function beforeTraverse(array $nodes) {
$this->patterns = [
'function_calls' => [],
'method_calls' => [],
'class_definitions' => [],
'interface_implementations' => [],
'trait_usage' => [],
'namespace_patterns' => [],
'use_statements' => [],
'control_structures' => [],
];
$this->contextStack = [];
return null;
}
/**
* {@inheritdoc}
*/
public function enterNode(Node $node) {
$this->contextStack[] = get_class($node);
// Extract various syntax patterns
if ($node instanceof Node\Stmt\Function_) {
$this->extractFunctionPattern($node);
}
elseif ($node instanceof Node\Stmt\ClassMethod) {
$this->extractMethodPattern($node);
}
elseif ($node instanceof Node\Stmt\Class_) {
$this->extractClassPattern($node);
}
elseif ($node instanceof Node\Stmt\Interface_) {
$this->extractInterfacePattern($node);
}
elseif ($node instanceof Node\Stmt\TraitUse) {
$this->extractTraitPattern($node);
}
elseif ($node instanceof Node\Stmt\Namespace_) {
$this->extractNamespacePattern($node);
}
elseif ($node instanceof Node\Stmt\Use_) {
$this->extractUsePattern($node);
}
elseif ($this->isControlStructure($node)) {
$this->extractControlStructurePattern($node);
}
}
/**
* {@inheritdoc}
*/
public function leaveNode(Node $node) {
array_pop($this->contextStack);
}
/**
* Extracts function pattern.
*/
protected function extractFunctionPattern(Node\Stmt\Function_ $node) {
$this->patterns['function_calls'][] = [
'type' => 'function_definition',
'name' => $node->name->toString(),
'params' => $this->extractParameters($node->params),
'return_type' => $this->extractReturnType($node->returnType),
'context' => $this->getCurrentContext(),
];
}
/**
* Extracts method pattern.
*/
protected function extractMethodPattern(Node\Stmt\ClassMethod $node) {
$this->patterns['method_calls'][] = [
'type' => 'method_definition',
'name' => $node->name->toString(),
'visibility' => $this->getVisibility($node),
'params' => $this->extractParameters($node->params),
'return_type' => $this->extractReturnType($node->returnType),
'context' => $this->getCurrentContext(),
];
}
/**
* Extracts class pattern.
*/
protected function extractClassPattern(Node\Stmt\Class_ $node) {
$this->patterns['class_definitions'][] = [
'type' => 'class_definition',
'name' => $node->name->toString(),
'extends' => $node->extends ? $node->extends->toString() : null,
'implements' => array_map(
function ($interface) {
return $interface->toString();
},
$node->implements
),
'context' => $this->getCurrentContext(),
];
}
/**
* Extracts interface pattern.
*/
protected function extractInterfacePattern(Node\Stmt\Interface_ $node) {
$this->patterns['interface_implementations'][] = [
'type' => 'interface_definition',
'name' => $node->name->toString(),
'extends' => array_map(
function ($interface) {
return $interface->toString();
},
$node->extends
),
'context' => $this->getCurrentContext(),
];
}
/**
* Extracts trait pattern.
*/
protected function extractTraitPattern(Node\Stmt\TraitUse $node) {
$this->patterns['trait_usage'][] = [
'type' => 'trait_use',
'traits' => array_map(
function ($trait) {
return $trait->toString();
},
$node->traits
),
'context' => $this->getCurrentContext(),
];
}
/**
* Extracts namespace pattern.
*/
protected function extractNamespacePattern(Node\Stmt\Namespace_ $node) {
$this->patterns['namespace_patterns'][] = [
'type' => 'namespace_definition',
'name' => $node->name ? $node->name->toString() : null,
'context' => $this->getCurrentContext(),
];
}
/**
* Extracts use statement pattern.
*/
protected function extractUsePattern(Node\Stmt\Use_ $node) {
foreach ($node->uses as $use) {
$this->patterns['use_statements'][] = [
'type' => 'use_statement',
'name' => $use->name->toString(),
'alias' => $use->alias ? $use->alias->toString() : null,
'context' => $this->getCurrentContext(),
];
}
}
/**
* Extracts control structure pattern.
*/
protected function extractControlStructurePattern(Node $node) {
$this->patterns['control_structures'][] = [
'type' => 'control_structure',
'structure_type' => $this->getNodeType($node),
'context' => $this->getCurrentContext(),
];
}
/**
* Checks if node is a control structure.
*/
protected function isControlStructure(Node $node) {
return $node instanceof Node\Stmt\If_
|| $node instanceof Node\Stmt\Switch_
|| $node instanceof Node\Stmt\While_
|| $node instanceof Node\Stmt\Do_
|| $node instanceof Node\Stmt\For_
|| $node instanceof Node\Stmt\Foreach_
|| $node instanceof Node\Stmt\TryCatch;
}
/**
* Gets node type.
*/
protected function getNodeType(Node $node) {
$class_name = get_class($node);
$parts = explode('\\', $class_name);
return strtolower(str_replace('_', '', end($parts)));
}
/**
* Extracts method/function parameters.
*/
protected function extractParameters(array $params) {
return array_map(
function ($param) {
return [
'name' => $param->var->name,
'type' => $param->type ? $this->getTypeName($param->type) : null,
'default' => $param->default ? $this->getDefaultValue($param->default) : null,
];
},
$params
);
}
/**
* Gets type name from node.
*/
protected function getTypeName($type) {
if ($type instanceof Node\Name) {
return $type->toString();
}
elseif ($type instanceof Node\NullableType) {
return '?' . $this->getTypeName($type->type);
}
elseif ($type instanceof Node\UnionType) {
return implode('|', array_map([$this, 'getTypeName'], $type->types));
}
return (string) $type;
}
/**
* Gets default value from node.
*/
protected function getDefaultValue($default) {
if ($default instanceof Node\Scalar) {
return $default->value;
}
elseif ($default instanceof Node\Expr\Array_) {
return [];
}
elseif ($default instanceof Node\Expr\ConstFetch) {
return $default->name->toString();
}
return null;
}
/**
* Gets method visibility.
*/
protected function getVisibility(Node\Stmt\ClassMethod $node) {
if ($node->isPrivate()) {
return 'private';
}
elseif ($node->isProtected()) {
return 'protected';
}
return 'public';
}
/**
* Gets return type.
*/
protected function extractReturnType($return_type) {
if (!$return_type) {
return null;
}
return $this->getTypeName($return_type);
}
/**
* Gets current context.
*/
protected function getCurrentContext() {
return $this->contextStack;
}
/**
* Gets collected patterns.
*
* @return array
* The collected patterns.
*/
public function getPatterns() {
return $this->patterns;
}
}
