$line) { $actual_line_number = $line_offset + $line_num + 1; $trimmed = trim($line); // Skip comments if (str_starts_with($trimmed, '//') || str_starts_with($trimmed, '*')) { continue; } // Check for this.property = value patterns // Match: this.something = // But not: this.data.something = if (preg_match('/\bthis\.(\w+)\s*=/', $line, $matches)) { $property_name = $matches[1]; // Allow this.data assignments if ($property_name === 'data') { continue; } // Check if it's a sub-property of data (this.data.something) if (preg_match('/\bthis\.data\.\w+/', $line)) { continue; } // Check for destructuring into this.data if (preg_match('/\bthis\.data\s*=\s*\{.*' . preg_quote($property_name, '/') . '/', $line)) { continue; } $this->add_violation( $file_path, $actual_line_number, "Setting 'this.{$property_name}' in on_load() method of class '{$class_name}'. The on_load() method should only update this.data properties.", trim($line), "Change to 'this.data.{$property_name} = ...' or move to on_create() if it's component state.", 'high' ); } // Also check for Object.assign or similar patterns that set this properties if (preg_match('/Object\.assign\s*\(\s*this\s*(?!\.data)/', $line)) { $this->add_violation( $file_path, $actual_line_number, "Using Object.assign on 'this' in on_load() method of class '{$class_name}'. The on_load() method should only update this.data.", trim($line), "Use 'Object.assign(this.data, ...)' instead, or move to on_create() for component state.", 'high' ); } } } } }