Fix bin/publish: use correct .env path for rspade_system Fix bin/publish script: prevent grep exit code 1 from terminating script 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
161 lines
7.0 KiB
PHP
Executable File
161 lines
7.0 KiB
PHP
Executable File
<?php
|
|
|
|
namespace App\RSpade\CodeQuality\Rules\JavaScript;
|
|
|
|
use App\RSpade\CodeQuality\Rules\CodeQualityRule_Abstract;
|
|
use App\RSpade\CodeQuality\RuntimeChecks\YoureDoingItWrongException;
|
|
use App\RSpade\Core\Cache\RsxCache;
|
|
|
|
/**
|
|
* Check Jqhtml_Component implementations for common AI agent mistakes
|
|
* Validates that components follow correct patterns
|
|
*/
|
|
class JqhtmlComponentImplementation_CodeQualityRule extends CodeQualityRule_Abstract
|
|
{
|
|
public function get_id(): string
|
|
{
|
|
return 'JQHTML-IMPL-01';
|
|
}
|
|
|
|
public function get_name(): string
|
|
{
|
|
return 'Jqhtml Component Implementation Check';
|
|
}
|
|
|
|
public function get_description(): string
|
|
{
|
|
return 'Validates Jqhtml_Component subclasses follow correct patterns';
|
|
}
|
|
|
|
public function get_file_patterns(): array
|
|
{
|
|
return ['*.js'];
|
|
}
|
|
|
|
/**
|
|
* Run during manifest build for immediate feedback
|
|
*/
|
|
public function is_called_during_manifest_scan(): bool
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public function check(string $file_path, string $contents, array $metadata = []): void
|
|
{
|
|
// Skip if not a JavaScript file
|
|
if (!isset($metadata['extension']) || $metadata['extension'] !== 'js') {
|
|
return;
|
|
}
|
|
|
|
// Skip if not a Jqhtml_Component subclass
|
|
if (!isset($metadata['extends']) || $metadata['extends'] !== 'Jqhtml_Component') {
|
|
return;
|
|
}
|
|
|
|
// Check cache to avoid redundant validation
|
|
$cache_key = $metadata['hash'] ?? md5($contents);
|
|
if (RsxCache::get_persistent($cache_key, false) === true) {
|
|
// Already validated
|
|
return;
|
|
}
|
|
|
|
$lines = explode("\n", $contents);
|
|
|
|
// Check for render() method and incorrect lifecycle methods
|
|
foreach ($lines as $line_num => $line) {
|
|
$trimmed = trim($line);
|
|
|
|
// Check for render() method
|
|
if (preg_match('/^render\s*\(/', $trimmed)) {
|
|
$this->throw_render_method_error($file_path, $line_num + 1, $metadata['class'] ?? 'Unknown');
|
|
}
|
|
|
|
// Check for incorrect event method names (create, load, ready without on_ prefix)
|
|
if (preg_match('/^(create|load|ready)\s*\(/', $trimmed, $matches)) {
|
|
$method = $matches[1];
|
|
$this->throw_lifecycle_method_error($file_path, $line_num + 1, $method);
|
|
}
|
|
}
|
|
|
|
// Mark as validated in cache
|
|
RsxCache::set_persistent($cache_key, true);
|
|
}
|
|
|
|
private function throw_render_method_error(string $file_path, int $line_number, string $class_name): void
|
|
{
|
|
$error_message = "==========================================\n";
|
|
$error_message .= "FATAL: Jqhtml component should not have render() method\n";
|
|
$error_message .= "==========================================\n\n";
|
|
$error_message .= "File: {$file_path}\n";
|
|
$error_message .= "Line: {$line_number}\n";
|
|
$error_message .= "Class: {$class_name}\n\n";
|
|
$error_message .= "Jqhtml components should not define a render() method.\n\n";
|
|
$error_message .= "PROBLEM:\n";
|
|
$error_message .= "The render() method is not part of the Jqhtml_Component lifecycle.\n";
|
|
$error_message .= "Jqhtml components use template files (.jqhtml) for rendering.\n\n";
|
|
$error_message .= "INCORRECT:\n";
|
|
$error_message .= " class My_Component extends Jqhtml_Component {\n";
|
|
$error_message .= " render() {\n";
|
|
$error_message .= " return '<div>...</div>';\n";
|
|
$error_message .= " }\n";
|
|
$error_message .= " }\n\n";
|
|
$error_message .= "CORRECT:\n";
|
|
$error_message .= " // Create a template file: my_component.jqhtml\n";
|
|
$error_message .= " <div>\n";
|
|
$error_message .= " <%= content() %>\n";
|
|
$error_message .= " </div>\n\n";
|
|
$error_message .= " // JavaScript class handles logic:\n";
|
|
$error_message .= " class My_Component extends Jqhtml_Component {\n";
|
|
$error_message .= " on_ready() {\n";
|
|
$error_message .= " // Component logic here\n";
|
|
$error_message .= " }\n";
|
|
$error_message .= " }\n\n";
|
|
$error_message .= "WHY THIS MATTERS:\n";
|
|
$error_message .= "- Jqhtml separates template from logic\n";
|
|
$error_message .= "- Templates are pre-compiled for performance\n";
|
|
$error_message .= "- The render() pattern is from React, not Jqhtml\n\n";
|
|
$error_message .= "FIX:\n";
|
|
$error_message .= "1. Remove the render() method\n";
|
|
$error_message .= "2. Create a .jqhtml template file for the component\n";
|
|
$error_message .= "3. Use lifecycle methods like on_create(), on_load(), on_ready()\n";
|
|
$error_message .= "==========================================";
|
|
|
|
throw new YoureDoingItWrongException($error_message);
|
|
}
|
|
|
|
private function throw_lifecycle_method_error(string $file_path, int $line_number, string $method_name): void
|
|
{
|
|
$error_message = "==========================================\n";
|
|
$error_message .= "FATAL: Jqhtml lifecycle method missing 'on_' prefix\n";
|
|
$error_message .= "==========================================\n\n";
|
|
$error_message .= "File: {$file_path}\n";
|
|
$error_message .= "Line: {$line_number}\n";
|
|
$error_message .= "Method: {$method_name}()\n\n";
|
|
$error_message .= "Jqhtml lifecycle methods must use the 'on_' prefix.\n\n";
|
|
$error_message .= "PROBLEM:\n";
|
|
$error_message .= "The method '{$method_name}()' should be 'on_{$method_name}()'.\n";
|
|
$error_message .= "Jqhtml components use specific lifecycle method names.\n\n";
|
|
$error_message .= "INCORRECT:\n";
|
|
$error_message .= " class My_Component extends Jqhtml_Component {\n";
|
|
$error_message .= " create() { ... } // Wrong\n";
|
|
$error_message .= " load() { ... } // Wrong\n";
|
|
$error_message .= " ready() { ... } // Wrong\n";
|
|
$error_message .= " }\n\n";
|
|
$error_message .= "CORRECT:\n";
|
|
$error_message .= " class My_Component extends Jqhtml_Component {\n";
|
|
$error_message .= " on_create() { ... } // Correct\n";
|
|
$error_message .= " on_load() { ... } // Correct\n";
|
|
$error_message .= " on_ready() { ... } // Correct\n";
|
|
$error_message .= " }\n\n";
|
|
$error_message .= "LIFECYCLE METHODS:\n";
|
|
$error_message .= "- on_create(): Called when component is created\n";
|
|
$error_message .= "- on_load(): Called to load async data\n";
|
|
$error_message .= "- on_ready(): Called when component is ready in DOM\n";
|
|
$error_message .= "- on_destroy(): Called when component is destroyed\n\n";
|
|
$error_message .= "FIX:\n";
|
|
$error_message .= "Rename '{$method_name}()' to 'on_{$method_name}()'\n";
|
|
$error_message .= "==========================================";
|
|
|
|
throw new YoureDoingItWrongException($error_message);
|
|
}
|
|
} |