diff --git a/kclvm/sema/src/advanced_resolver/node.rs b/kclvm/sema/src/advanced_resolver/node.rs index 7dd989181..1ff49ebb9 100644 --- a/kclvm/sema/src/advanced_resolver/node.rs +++ b/kclvm/sema/src/advanced_resolver/node.rs @@ -686,7 +686,12 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { .get_scopes_mut() .set_owner_to_scope(*cur_scope, owner); } - self.do_arguments_symbol_resolve(&call_expr.args, &call_expr.keywords)?; + self.do_arguments_symbol_resolve_with_hint_schema( + &call_expr.args, + &call_expr.keywords, + true, + schema_ty, + )?; self.leave_scope(); } @@ -706,7 +711,7 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { .set_owner_to_scope(*cur_scope, owner); } - self.do_arguments_symbol_resolve_with_hint( + self.do_arguments_symbol_resolve_with_hint_func( &call_expr.args, &call_expr.keywords, true, @@ -1781,7 +1786,7 @@ impl<'ctx> AdvancedResolver<'ctx> { Ok(()) } - pub fn do_arguments_symbol_resolve_with_hint( + pub fn do_arguments_symbol_resolve_with_hint_func( &mut self, args: &'ctx [ast::NodeRef], kwargs: &'ctx [ast::NodeRef], @@ -1871,6 +1876,96 @@ impl<'ctx> AdvancedResolver<'ctx> { Ok(()) } + pub fn do_arguments_symbol_resolve_with_hint_schema( + &mut self, + args: &'ctx [ast::NodeRef], + kwargs: &'ctx [ast::NodeRef], + with_hint: bool, + schema_ty: &ty::SchemaType, + ) -> anyhow::Result<()> { + if schema_ty.func.params.is_empty() { + self.do_arguments_symbol_resolve(args, kwargs)?; + } else { + for (arg, param) in args.iter().zip(schema_ty.func.params.iter()) { + self.expr(arg)?; + + if with_hint { + let symbol_data = self.gs.get_symbols_mut(); + let id = match &arg.node { + ast::Expr::Identifier(id) => id.names.last().unwrap().id.clone(), + _ => arg.id.clone(), + }; + if let Some(arg_ref) = symbol_data + .symbols_info + .node_symbol_map + .get(&self.ctx.get_node_key(&id)) + { + match arg_ref.get_kind() { + crate::core::symbol::SymbolKind::Expression => { + if let Some(expr) = symbol_data.exprs.get_mut(arg_ref.get_id()) { + expr.hint = Some(SymbolHint { + pos: arg.get_pos(), + kind: SymbolHintKind::VarHint(param.name.clone()), + }); + } + } + crate::core::symbol::SymbolKind::Unresolved => { + let mut has_hint = false; + if let Some(unresolved) = + symbol_data.unresolved.get(arg_ref.get_id()) + { + if let Some(def) = unresolved.def { + if let Some(def) = symbol_data.get_symbol(def) { + if def.get_name() != param.name { + has_hint = true; + } + } + } + } + if has_hint { + if let Some(unresolved) = + symbol_data.unresolved.get_mut(arg_ref.get_id()) + { + unresolved.hint = Some(SymbolHint { + kind: SymbolHintKind::VarHint(param.name.clone()), + pos: arg.get_pos(), + }); + } + } + } + _ => {} + } + } + } + } + + for kw in kwargs.iter() { + if let Some(value) = &kw.node.value { + self.expr(value)?; + } + let (start_pos, end_pos): Range = kw.node.arg.get_span_pos(); + let value = self.gs.get_symbols_mut().alloc_value_symbol( + ValueSymbol::new(kw.node.arg.node.get_name(), start_pos, end_pos, None, false), + self.ctx.get_node_key(&kw.id), + self.ctx.current_pkgpath.clone().unwrap(), + ); + + if let Some(value) = self.gs.get_symbols_mut().values.get_mut(value.get_id()) { + value.sema_info = SymbolSemanticInfo { + ty: self + .ctx + .node_ty_map + .borrow() + .get(&self.ctx.get_node_key(&kw.id)) + .map(|ty| ty.clone()), + doc: None, + }; + } + } + } + Ok(()) + } + pub(crate) fn walk_config_entries( &mut self, entries: &'ctx [ast::NodeRef], diff --git a/kclvm/tools/src/LSP/src/inlay_hints.rs b/kclvm/tools/src/LSP/src/inlay_hints.rs index 54576275b..ddf803098 100644 --- a/kclvm/tools/src/LSP/src/inlay_hints.rs +++ b/kclvm/tools/src/LSP/src/inlay_hints.rs @@ -118,4 +118,9 @@ mod tests { test_function_call_arg_hint, "src/test_data/inlay_hints/function_call/function_call.k" ); + + inlay_hints_test_snapshot!( + test_schema_arg_hint, + "src/test_data/inlay_hints/schema_args/schema_args_hint.k" + ); } diff --git a/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__inlay_hints__tests__schema_arg_hint.snap b/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__inlay_hints__tests__schema_arg_hint.snap new file mode 100644 index 000000000..496236911 --- /dev/null +++ b/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__inlay_hints__tests__schema_arg_hint.snap @@ -0,0 +1,119 @@ +--- +source: tools/src/LSP/src/inlay_hints.rs +assertion_line: 122 +expression: "format!(\"{:#?}\", res)" +--- +Some( + [ + InlayHint { + position: Position { + line: 1, + character: 5, + }, + label: LabelParts( + [ + InlayHintLabelPart { + value: ": int", + tooltip: None, + location: None, + command: None, + }, + ], + ), + kind: None, + text_edits: None, + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + }, + InlayHint { + position: Position { + line: 2, + character: 5, + }, + label: LabelParts( + [ + InlayHintLabelPart { + value: ": str", + tooltip: None, + location: None, + command: None, + }, + ], + ), + kind: None, + text_edits: None, + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + }, + InlayHint { + position: Position { + line: 4, + character: 1, + }, + label: LabelParts( + [ + InlayHintLabelPart { + value: ": Person", + tooltip: None, + location: None, + command: None, + }, + ], + ), + kind: None, + text_edits: None, + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + }, + InlayHint { + position: Position { + line: 4, + character: 11, + }, + label: LabelParts( + [ + InlayHintLabelPart { + value: "age: ", + tooltip: None, + location: None, + command: None, + }, + ], + ), + kind: None, + text_edits: None, + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + }, + InlayHint { + position: Position { + line: 4, + character: 14, + }, + label: LabelParts( + [ + InlayHintLabelPart { + value: "name: ", + tooltip: None, + location: None, + command: None, + }, + ], + ), + kind: None, + text_edits: None, + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + }, + ], +) diff --git a/kclvm/tools/src/LSP/src/test_data/inlay_hints/schema_args/schema_args_hint.k b/kclvm/tools/src/LSP/src/test_data/inlay_hints/schema_args/schema_args_hint.k new file mode 100644 index 000000000..367507a2f --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/inlay_hints/schema_args/schema_args_hint.k @@ -0,0 +1,5 @@ +schema Person[age: int, name: str]: + a = age + n = name + +p = Person(1, "Alice")