Files
rspade_system/app/RSpade/CodeQuality/Rules/JavaScript/ThisUsage_CodeQualityRule.php
root 84ca3dfe42 Fix code quality violations and rename select input components
Move small tasks from wishlist to todo, update npm packages
Replace #[Auth] attributes with manual auth checks and code quality rule
Remove on_jqhtml_ready lifecycle method from framework
Complete ACL system with 100-based role indexing and /dev/acl tester
WIP: ACL system implementation with debug instrumentation
Convert rsx:check JS linting to RPC socket server
Clean up docs and fix $id→$sid in man pages, remove SSR/FPC feature
Reorganize wishlists: priority order, mark sublayouts complete, add email
Update model_fetch docs: mark MVP complete, fix enum docs, reorganize
Comprehensive documentation overhaul: clarity, compression, and critical rules
Convert Contacts/Projects CRUD to Model.fetch() and add fetch_or_null()
Add JS ORM relationship lazy-loading and fetch array handling
Add JS ORM relationship fetching and CRUD documentation
Fix ORM hydration and add IDE resolution for Base_* model stubs
Rename Json_Tree_Component to JS_Tree_Debug_Component and move to framework
Enhance JS ORM infrastructure and add Json_Tree class name badges

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-23 21:39:43 +00:00

136 lines
4.3 KiB
PHP
Executable File

<?php
namespace App\RSpade\CodeQuality\Rules\JavaScript;
use App\RSpade\CodeQuality\Rules\CodeQualityRule_Abstract;
use App\RSpade\CodeQuality\Support\Js_CodeQuality_Rpc;
/**
* JavaScript 'this' Usage Rule
*
* PHILOSOPHY: Enforce clear 'this' patterns in anonymous functions and static methods.
*
* RULES:
* 1. Anonymous functions: MUST use 'const $element = $(this)' or 'const that = this' as first line
* 2. Static methods: MUST NOT use naked 'this' - use Class_Name or 'const CurrentClass = this'
* 3. Instance methods: EXEMPT - can use 'this' directly (no aliasing required)
* 4. Arrow functions: EXEMPT - they inherit 'this' context
* 5. Constructors: EXEMPT - 'this' allowed directly for property assignment
*
* PATTERNS:
* - jQuery callback: const $element = $(this) // Variable must start with $
* - Anonymous function: const that = this // Instance context aliasing
* - Static (exact): Use Class_Name // When you need exact class
* - Static (polymorphic): const CurrentClass = this // When inherited classes need different behavior
*
* INSTANCE METHODS POLICY:
* Instance methods (on_ready, on_load, etc.) can use 'this' directly.
* This rule only enforces aliasing for anonymous functions and prohibits naked 'this' in static methods.
*/
class ThisUsage_CodeQualityRule extends CodeQualityRule_Abstract
{
public function get_id(): string
{
return 'JS-THIS-01';
}
public function get_name(): string
{
return "JavaScript 'this' Usage Check";
}
public function get_description(): string
{
return "Enforces clear 'this' patterns: jQuery callbacks use '\$element = \$(this)', instance methods use 'that = this'";
}
public function get_file_patterns(): array
{
return ['*.js'];
}
public function get_default_severity(): string
{
return 'high';
}
/**
* Check JavaScript file for improper 'this' usage
*/
public function check(string $file_path, string $contents, array $metadata = []): void
{
// Skip vendor and node_modules
if (str_contains($file_path, '/vendor/') || str_contains($file_path, '/node_modules/')) {
return;
}
// Skip CodeQuality directory
if (str_contains($file_path, '/CodeQuality/')) {
return;
}
// Only check JavaScript files that contain ES6 classes
if (!isset($metadata['class'])) {
return; // Not a class file
}
// Get violations from AST parser
$violations = $this->parse_with_acorn($file_path);
if (empty($violations)) {
return;
}
// Process violations
foreach ($violations as $violation) {
$this->add_violation(
$file_path,
$violation['line'],
$violation['message'],
$violation['codeSnippet'],
$violation['remediation'],
$this->get_default_severity()
);
}
}
/**
* Analyze JavaScript file for 'this' usage violations via RPC server
*/
private function parse_with_acorn(string $file_path): array
{
// Setup cache directory
$cache_dir = storage_path('rsx-tmp/cache/code-quality/js-this');
if (!is_dir($cache_dir)) {
mkdir($cache_dir, 0755, true);
}
// Cache based on file modification time
$cache_key = md5($file_path) . '-' . filemtime($file_path);
$cache_file = $cache_dir . '/' . $cache_key . '.json';
// Check cache first
if (file_exists($cache_file)) {
$cached = json_decode(file_get_contents($cache_file), true);
if ($cached !== null) {
return $cached;
}
}
// Clean old cache files for this source file
$pattern = $cache_dir . '/' . md5($file_path) . '-*.json';
foreach (glob($pattern) as $old_cache) {
if ($old_cache !== $cache_file) {
unlink($old_cache);
}
}
// Analyze via RPC server (lazy starts if not running)
$violations = Js_CodeQuality_Rpc::analyze_this($file_path);
// Cache the result
file_put_contents($cache_file, json_encode($violations));
return $violations;
}
}