Custom Rules
Custom Rules
Learn how to create custom analysis rules for Codementor-AI to match your project's specific requirements and coding standards.
Overview
Codementor-AI's extensible rule system allows you to create custom analysis rules that can:
- Enforce project-specific coding standards
- Detect domain-specific patterns
- Validate business logic requirements
- Ensure architectural consistency
- Check for security vulnerabilities specific to your application
Rule Structure
Custom rules are PHP classes that extend the base rule class:
<?php
namespace CodementorAI\Rules\Custom;
use CodementorAI\Rules\BaseRule;
use PhpParser\Node;
class MyCustomRule extends BaseRule
{
public function getDescription(): string
{
return 'Description of what this rule checks for';
}
public function getSeverity(): string
{
return 'medium'; // critical, high, medium, low
}
public function getCategory(): string
{
return 'custom'; // security, performance, laravel, style, custom
}
public function analyze(Node $node): array
{
$issues = [];
// Your analysis logic here
if ($this->hasIssue($node)) {
$issues[] = [
'message' => 'Issue description',
'line' => $node->getLine(),
'file' => $this->getCurrentFile(),
'suggestion' => 'How to fix this issue'
];
}
return $issues;
}
private function hasIssue(Node $node): bool
{
// Your detection logic
return false;
}
}
Creating Your First Rule
Step 1: Create the Rule File
Create a new file in your custom rules directory:
mkdir -p codementor-ai/rules/custom
touch codementor-ai/rules/custom/MyCustomRule.php
Step 2: Implement the Rule
Here's a simple example that checks for hardcoded database credentials:
<?php
namespace CodementorAI\Rules\Custom;
use CodementorAI\Rules\BaseRule;
use PhpParser\Node;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\Array_;
class HardcodedCredentialsRule extends BaseRule
{
public function getDescription(): string
{
return 'Detects hardcoded database credentials in configuration files';
}
public function getSeverity(): string
{
return 'critical';
}
public function getCategory(): string
{
return 'security';
}
public function analyze(Node $node): array
{
$issues = [];
if ($node instanceof Array_) {
foreach ($node->items as $item) {
if ($item instanceof ArrayItem) {
$issues = array_merge($issues, $this->checkArrayItem($item));
}
}
}
return $issues;
}
private function checkArrayItem(ArrayItem $item): array
{
$issues = [];
if ($item->key && $this->isCredentialKey($item->key)) {
if ($item->value && $this->isHardcodedValue($item->value)) {
$issues[] = [
'message' => 'Hardcoded credential detected: ' . $item->key->value,
'line' => $item->getLine(),
'file' => $this->getCurrentFile(),
'suggestion' => 'Use environment variables instead of hardcoded values'
];
}
}
return $issues;
}
private function isCredentialKey($key): bool
{
$credentialKeys = ['password', 'secret', 'key', 'token', 'api_key'];
return in_array(strtolower($key->value), $credentialKeys);
}
private function isHardcodedValue($value): bool
{
// Check if value is a string literal (not a variable or function call)
return $value instanceof \PhpParser\Node\Scalar\String_;
}
}
Rule Categories
Organize your rules into categories for better management:
🔒 Security Rules
Rules that detect security vulnerabilities and enforce secure coding practices.
- SQL injection detection
- XSS prevention
- Authentication bypass
- Hardcoded credentials
⚡ Performance Rules
Rules that identify performance bottlenecks and optimization opportunities.
- N+1 query detection
- Memory leak detection
- Inefficient algorithms
- Resource usage optimization
🏗️ Laravel Rules
Framework-specific rules for Laravel best practices.
- Controller method validation
- Model relationship checks
- Service layer patterns
- Middleware usage
📝 Style Rules
Code style and formatting rules.
- Naming conventions
- Code formatting
- Documentation requirements
- Comment standards
Advanced Rule Features
Context-Aware Analysis
Rules can access context about the current file and project:
public function analyze(Node $node): array
{
$issues = [];
// Check if we're in a Laravel controller
if ($this->isLaravelController()) {
$issues = array_merge($issues, $this->analyzeController($node));
}
// Check if we're in a configuration file
if ($this->isConfigFile()) {
$issues = array_merge($issues, $this->analyzeConfig($node));
}
return $issues;
}
private function isLaravelController(): bool
{
$file = $this->getCurrentFile();
return strpos($file, 'app/Http/Controllers/') !== false;
}
private function isConfigFile(): bool
{
$file = $this->getCurrentFile();
return strpos($file, 'config/') !== false;
}
Configuration Options
Rules can accept configuration parameters:
class ConfigurableRule extends BaseRule
{
private array $config;
public function __construct(array $config = [])
{
$this->config = array_merge([
'max_method_length' => 50,
'allowed_exceptions' => [],
'severity_threshold' => 'medium'
], $config);
}
public function analyze(Node $node): array
{
$issues = [];
if ($node instanceof \PhpParser\Node\Stmt\ClassMethod) {
if (strlen($node->name->name) > $this->config['max_method_length']) {
$issues[] = [
'message' => "Method name too long: {$node->name->name}",
'line' => $node->getLine(),
'file' => $this->getCurrentFile(),
'suggestion' => 'Use shorter, more descriptive method names'
];
}
}
return $issues;
}
}
Registering Custom Rules
Add your custom rules to the configuration:
// config/codementor-ai.php
return [
'rules' => [
'custom' => [
'CodementorAI\Rules\Custom\HardcodedCredentialsRule',
'CodementorAI\Rules\Custom\MyCustomRule',
],
'enabled' => ['security', 'performance', 'laravel', 'custom'],
],
];
Testing Custom Rules
Create test cases for your custom rules:
<?php
namespace Tests\Rules\Custom;
use CodementorAI\Rules\Custom\HardcodedCredentialsRule;
use PHPUnit\Framework\TestCase;
class HardcodedCredentialsRuleTest extends TestCase
{
private HardcodedCredentialsRule $rule;
protected function setUp(): void
{
$this->rule = new HardcodedCredentialsRule();
}
public function testDetectsHardcodedPassword()
{
$code = '<?php return ["password" => "secret123"];';
$nodes = $this->parseCode($code);
$issues = $this->rule->analyze($nodes[0]);
$this->assertCount(1, $issues);
$this->assertEquals('Hardcoded credential detected: password', $issues[0]['message']);
}
private function parseCode(string $code): array
{
$parser = new \PhpParser\Parser\Php7(new \PhpParser\Lexer\Emulative());
return $parser->parse($code);
}
}
Best Practices
- Keep rules focused: Each rule should check for one specific issue
- Provide clear messages: Include actionable suggestions in issue descriptions
- Use appropriate severity: Match severity to the impact of the issue
- Test thoroughly: Create comprehensive test cases for your rules
- Document your rules: Explain what each rule checks and why it's important
- Consider performance: Ensure rules don't significantly slow down analysis
Sharing Rules
Share your custom rules with the community:
- Create a GitHub repository for your rules
- Document installation and usage instructions
- Provide examples and test cases
- Submit to the Codementor-AI rules registry
Next Steps
Now that you understand custom rules:
- Create your first custom rule
- Set up testing for your rules
- Integrate rules into your development workflow
- Share useful rules with your team