diff --git a/crates/emmylua_code_analysis/src/db_index/declaration/decl_tree.rs b/crates/emmylua_code_analysis/src/db_index/declaration/decl_tree.rs index 7bb214b4f..258e20fd0 100644 --- a/crates/emmylua_code_analysis/src/db_index/declaration/decl_tree.rs +++ b/crates/emmylua_code_analysis/src/db_index/declaration/decl_tree.rs @@ -151,13 +151,17 @@ impl LuaDeclarationTree { { match scope.get_kind() { LuaScopeKind::LocalOrAssignStat => { - let parent = scope.get_parent(); - if let Some(parent) = parent { - let parent_scope = match self.scopes.get(parent.id as usize) { - Some(scope) => scope, - None => return, - }; - self.walk_up(parent_scope, scope.get_position(), level, f); + if level == 0 { + let parent = scope.get_parent(); + if let Some(parent) = parent { + let parent_scope = match self.scopes.get(parent.id as usize) { + Some(scope) => scope, + None => return, + }; + self.walk_up(parent_scope, scope.get_position(), level, f); + } + } else { + self.base_walk_up(scope, start_pos, level, f); } } LuaScopeKind::Repeat => { diff --git a/crates/emmylua_code_analysis/src/diagnostic/test/incomplete_signature_doc_test.rs b/crates/emmylua_code_analysis/src/diagnostic/test/incomplete_signature_doc_test.rs index 5a1df2ab0..b640c2b8c 100644 --- a/crates/emmylua_code_analysis/src/diagnostic/test/incomplete_signature_doc_test.rs +++ b/crates/emmylua_code_analysis/src/diagnostic/test/incomplete_signature_doc_test.rs @@ -24,15 +24,14 @@ mod tests { let mut ws = VirtualWorkspace::new(); ws.enable_full_diagnostic(); - // TODO: closures are not detected as functions in the semantic model - // assert!(!ws.check_code_for( - // DiagnosticCode::MissingGlobalDoc, - // r#" - // local c = function(x, y) - // return x + y - // end - // "# - // )); + assert!(!ws.check_code_for( + DiagnosticCode::IncompleteSignatureDoc, + r#" + local c = function(x, y) + return x + y + end + "# + )); assert!(!ws.check_code_for( DiagnosticCode::IncompleteSignatureDoc, diff --git a/crates/emmylua_code_analysis/src/diagnostic/test/undefined_global_test.rs b/crates/emmylua_code_analysis/src/diagnostic/test/undefined_global_test.rs index 123b1e7a9..b63a0a95b 100644 --- a/crates/emmylua_code_analysis/src/diagnostic/test/undefined_global_test.rs +++ b/crates/emmylua_code_analysis/src/diagnostic/test/undefined_global_test.rs @@ -20,4 +20,20 @@ mod test { "# )); } + + #[test] + fn test_globals() { + let mut ws = VirtualWorkspace::new_with_init_std_lib(); + assert!(ws.check_code_for( + DiagnosticCode::UndefinedGlobal, + r#" + local fact = function(n) + if n == 0 then + return 1 + end + return n * fact(n - 1) + end + "# + )); + } } diff --git a/crates/emmylua_code_analysis/src/semantic/semantic_info/infer_expr_semantic_decl.rs b/crates/emmylua_code_analysis/src/semantic/semantic_info/infer_expr_semantic_decl.rs index 75f497155..0bfbd6ec9 100644 --- a/crates/emmylua_code_analysis/src/semantic/semantic_info/infer_expr_semantic_decl.rs +++ b/crates/emmylua_code_analysis/src/semantic/semantic_info/infer_expr_semantic_decl.rs @@ -222,6 +222,26 @@ fn infer_closure_expr_semantic_decl( level, ) } + LuaStat::LocalStat(local_stat) => { + let local_name = + local_stat.get_local_name_by_value(LuaExpr::ClosureExpr(closure_expr))?; + let name_token = local_name.get_name_token()?; + infer_token_semantic_decl(db, cache, name_token.syntax().clone(), level) + } + LuaStat::AssignStat(assign_stat) => { + let (vars, exprs) = assign_stat.get_var_and_expr_list(); + let idx = exprs.iter().position(|expr| { + matches!(expr, LuaExpr::ClosureExpr(ce) if ce.syntax() == closure_expr.syntax()) + })?; + let var = vars.get(idx)?; + infer_expr_semantic_decl( + db, + cache, + var.clone().into(), + semantic_guard.next_level()?, + level, + ) + } _ => None, } }