$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.$ (jQuery element access)
// Match this.$ followed by anything except .ajax/.get/.post/.getJSON
if (preg_match('/\bthis\.\$/', $line)) {
// Check if it's this.$.something (DOM manipulation) vs $.ajax usage
if (preg_match('/\bthis\.\$\./', $line)) {
// this.$. pattern - this is DOM manipulation
$this->add_violation(
$file_path,
$actual_line_number,
"DOM access 'this.\$' detected in on_load() method of class '{$class_name}'. The on_load() phase runs in parallel and must not access DOM.",
trim($line),
"To handle loading states, you have two options:\n" .
"1. Use conditional rendering in your .jqhtml template:\n" .
" <% if (this.data === null): %>\n" .
"
Loading...
\n" .
" <% else: %>\n" .
" ...loaded content...
\n" .
" <% endif; %>\n" .
"2. Set loading state in on_create() (before load) and clear it in on_ready() (after load).\n" .
' on_load() should only update this.data properties.',
'high'
);
}
}
// Check for this.$id() calls
if (preg_match('/\bthis\.\$id\s*\(/', $line)) {
$this->add_violation(
$file_path,
$actual_line_number,
"DOM access 'this.\$id()' detected in on_load() method of class '{$class_name}'. The on_load() phase runs in parallel and must not access DOM.",
trim($line),
"To handle loading states, you have two options:\n" .
"1. Use conditional rendering in your .jqhtml template:\n" .
" <% if (this.data === null): %>\n" .
" Loading...
\n" .
" <% else: %>\n" .
" ...loaded content...
\n" .
" <% endif; %>\n" .
"2. Set loading state in on_create() (before load) and clear it in on_ready() (after load).\n" .
' on_load() should only update this.data properties.',
'high'
);
}
// Check for jQuery selector usage (but allow $.ajax)
if (preg_match('/\$\s*\([\'"`]/', $line) && !preg_match('/\$\.(ajax|get|post|getJSON)/', $line)) {
$this->add_violation(
$file_path,
$actual_line_number,
"jQuery selector '\$()' detected in on_load() method of class '{$class_name}'. The on_load() phase runs in parallel and must not access DOM.",
trim($line),
"To handle loading states, you have two options:\n" .
"1. Use conditional rendering in your .jqhtml template:\n" .
" <% if (this.data === null): %>\n" .
" Loading...
\n" .
" <% else: %>\n" .
" ...loaded content...
\n" .
" <% endif; %>\n" .
"2. Set loading state in on_create() (before load) and clear it in on_ready() (after load).\n" .
' on_load() should only update this.data properties. Use $.ajax() for data fetching.',
'high'
);
}
// Check for this.render() calls
if (preg_match('/\bthis\.render\s*\(/', $line)) {
$this->add_violation(
$file_path,
$actual_line_number,
"Calling 'this.render()' in on_load() method of class '{$class_name}' is not allowed. Re-render happens automatically after on_load() if this.data changed.",
trim($line),
'Remove this.render() call. The framework automatically re-renders after on_load() if this.data was modified.',
'high'
);
}
}
}
}
}