requireModule (lua.ts:28-60).
(&self, call: Node<'t>)
| 296 | |
| 297 | /// requireModule (lua.ts:28-60). |
| 298 | fn require_module(&self, call: Node<'t>) -> Option<String> { |
| 299 | let name = call.child_by_field_name("name")?; |
| 300 | if name.kind() != "identifier" || self.text(name) != "require" { |
| 301 | return None; |
| 302 | } |
| 303 | let args = call.child_by_field_name("arguments")?; |
| 304 | |
| 305 | // String win: first string_content descendant, BFS order. |
| 306 | if let Some(content) = self.find_descendant(args, "string_content") { |
| 307 | let t = self.text(content).trim(); |
| 308 | return if t.is_empty() { None } else { Some(t.to_string()) }; |
| 309 | } |
| 310 | // Fallback: a string node with no content child — strip [[ ]] / quotes. |
| 311 | if let Some(s) = self.find_descendant(args, "string") { |
| 312 | let mut t = self.text(s).trim(); |
| 313 | t = t.strip_prefix("[[").unwrap_or(t); |
| 314 | t = t.strip_suffix("]]").unwrap_or(t); |
| 315 | t = t.strip_prefix(['"', '\'']).unwrap_or(t); |
| 316 | t = t.strip_suffix(['"', '\'']).unwrap_or(t); |
| 317 | if !t.is_empty() { |
| 318 | return Some(t.to_string()); |
| 319 | } |
| 320 | } |
| 321 | // Roblox instance path: trailing field/method segment. |
| 322 | let idx = self |
| 323 | .find_descendant(args, "dot_index_expression") |
| 324 | .or_else(|| self.find_descendant(args, "method_index_expression")); |
| 325 | if let Some(idx) = idx { |
| 326 | if let Some(field) = idx |
| 327 | .child_by_field_name("field") |
| 328 | .or_else(|| idx.child_by_field_name("method")) |
| 329 | { |
| 330 | let t = self.text(field).trim(); |
| 331 | return if t.is_empty() { None } else { Some(t.to_string()) }; |
| 332 | } |
| 333 | } |
| 334 | None |
| 335 | } |
| 336 | |
| 337 | /// The hook's `emit` (lua.ts:108-126): import node at the CALL node + |
| 338 | /// imports ref from the stack top. |
no test coverage detected