Extract a function declaration. Lua function declarations come in three flavours: - `local function foo(...)` → name is `identifier`, local/private function - `function Foo.bar(...)` → name is `dot_index_expression`, public function with class context - `function Foo:bar(...)` → name is `method_index_expression`, method
(state: &mut ExtractionState, node: TsNode<'_>)
| 165 | /// - `function Foo.bar(...)` → name is `dot_index_expression`, public function with class context |
| 166 | /// - `function Foo:bar(...)` → name is `method_index_expression`, method |
| 167 | fn visit_function_declaration(state: &mut ExtractionState, node: TsNode<'_>) { |
| 168 | let Some(name_node) = node.child_by_field_name("name") else { |
| 169 | return; |
| 170 | }; |
| 171 | |
| 172 | let is_local = node.child(0).is_some_and(|c| c.kind() == "local"); |
| 173 | |
| 174 | let (name, kind, visibility, class_context) = match name_node.kind() { |
| 175 | "identifier" => { |
| 176 | let name = state.node_text(name_node); |
| 177 | ( |
| 178 | name, |
| 179 | NodeKind::Function, |
| 180 | if is_local { |
| 181 | Visibility::Private |
| 182 | } else { |
| 183 | Visibility::Pub |
| 184 | }, |
| 185 | None, |
| 186 | ) |
| 187 | } |
| 188 | "dot_index_expression" => { |
| 189 | // e.g. Connection.new |
| 190 | let table_name = name_node |
| 191 | .child_by_field_name("table") |
| 192 | .map(|n| state.node_text(n)); |
| 193 | let field_name = name_node |
| 194 | .child_by_field_name("field") |
| 195 | .map_or_else(|| "<anonymous>".to_string(), |n| state.node_text(n)); |
| 196 | (field_name, NodeKind::Function, Visibility::Pub, table_name) |
| 197 | } |
| 198 | "method_index_expression" => { |
| 199 | // e.g. Connection:connect |
| 200 | let table_name = name_node |
| 201 | .child_by_field_name("table") |
| 202 | .map(|n| state.node_text(n)); |
| 203 | let method_name = name_node |
| 204 | .child_by_field_name("method") |
| 205 | .map_or_else(|| "<anonymous>".to_string(), |n| state.node_text(n)); |
| 206 | (method_name, NodeKind::Method, Visibility::Pub, table_name) |
| 207 | } |
| 208 | _ => return, |
| 209 | }; |
| 210 | |
| 211 | let docstring = Self::extract_docstring(state, node); |
| 212 | let signature = Self::extract_function_signature(state, node, class_context.as_deref()); |
| 213 | let start_line = node.start_position().row as u32; |
| 214 | let end_line = node.end_position().row as u32; |
| 215 | let start_column = node.start_position().column as u32; |
| 216 | let end_column = node.end_position().column as u32; |
| 217 | let qualified_name = if let Some(ref ctx) = class_context { |
| 218 | format!("{}::{}::{}", state.qualified_prefix(), ctx, name) |
| 219 | } else { |
| 220 | format!("{}::{}", state.qualified_prefix(), name) |
| 221 | }; |
| 222 | let id = generate_node_id(&state.file_path, &kind, &name, start_line); |
| 223 | let metrics = count_complexity(node, &LUA_COMPLEXITY, &state.source); |
| 224 |
nothing calls this directly
no test coverage detected