diff --git a/kclvm/sema/src/builtin/mod.rs b/kclvm/sema/src/builtin/mod.rs index 823708ebb..0c14182ef 100644 --- a/kclvm/sema/src/builtin/mod.rs +++ b/kclvm/sema/src/builtin/mod.rs @@ -79,13 +79,12 @@ register_builtin! { ) print => Type::function( None, - Rc::new(Type::ANY), + Rc::new(Type::NONE), &[], r#"Prints the values to a stream, or to sys.stdout by default. Optional keyword arguments: sep: string inserted between values, default a space. - end: string appended after the last value, default a newline. - "#, + end: string appended after the last value, default a newline."#, true, None, ) diff --git a/kclvm/sema/src/resolver/scope.rs b/kclvm/sema/src/resolver/scope.rs index 8c25ccd20..b1f8dc267 100644 --- a/kclvm/sema/src/resolver/scope.rs +++ b/kclvm/sema/src/resolver/scope.rs @@ -333,7 +333,7 @@ impl ProgramScope { } /// Construct a builtin scope -pub(crate) fn builtin_scope() -> Scope { +pub fn builtin_scope() -> Scope { let mut elems = IndexMap::default(); for (name, builtin_func) in BUILTIN_FUNCTIONS.iter() { elems.insert( diff --git a/kclvm/tools/src/LSP/src/goto_def.rs b/kclvm/tools/src/LSP/src/goto_def.rs index 66e10e374..d2a25d87a 100644 --- a/kclvm/tools/src/LSP/src/goto_def.rs +++ b/kclvm/tools/src/LSP/src/goto_def.rs @@ -15,7 +15,9 @@ use kclvm_compiler::pkgpath_without_prefix; use kclvm_error::Position as KCLPos; use kclvm_sema::builtin::get_system_member_function_ty; -use kclvm_sema::resolver::scope::{ProgramScope, Scope, ScopeObject, ScopeObjectKind}; +use kclvm_sema::resolver::scope::{ + builtin_scope, ProgramScope, Scope, ScopeObject, ScopeObjectKind, +}; use kclvm_sema::ty::{DictType, SchemaType}; use lsp_types::{GotoDefinitionResponse, Url}; use lsp_types::{Location, Range}; @@ -204,7 +206,23 @@ pub(crate) fn resolve_var( } _ => Some(Definition::Object(obj.borrow().clone())), }, - None => None, + None => match builtin_scope().lookup(&name) { + Some(obj) => { + let mut obj = obj.borrow().clone(); + let doc = { + match &obj.ty.kind { + kclvm_sema::ty::TypeKind::Function(func) => Some(func.doc.clone()), + _ => None, + } + }; + obj.kind = ScopeObjectKind::FunctionCall; + obj.doc = doc; + obj.start = node_names[0].get_pos(); + obj.end = node_names[0].get_end_pos(); + Some(Definition::Object(obj)) + } + None => None, + }, } } _ => { diff --git a/kclvm/tools/src/LSP/src/hover.rs b/kclvm/tools/src/LSP/src/hover.rs index ac8554d5b..8fa149700 100644 --- a/kclvm/tools/src/LSP/src/hover.rs +++ b/kclvm/tools/src/LSP/src/hover.rs @@ -143,7 +143,7 @@ fn build_func_hover_content(func_ty: &FunctionType, name: String) -> Vec docs.push(sig); if !func_ty.doc.is_empty() { - docs.push(func_ty.doc.clone()); + docs.push(func_ty.doc.clone().replace("\n", "\n\n")); } docs } @@ -336,5 +336,25 @@ mod tests { } _ => unreachable!("test error"), } + + let pos = KCLPos { + filename: file.clone(), + line: 25, + column: Some(4), + }; + let got = hover(&program, &pos, &prog_scope).unwrap(); + + match got.contents { + lsp_types::HoverContents::Array(vec) => { + assert_eq!(vec.len(), 2); + if let MarkedString::String(s) = vec[0].clone() { + assert_eq!(s, "fn print() -> NoneType"); + } + if let MarkedString::String(s) = vec[1].clone() { + assert_eq!(s, "Prints the values to a stream, or to sys.stdout by default.\n\n Optional keyword arguments:\n\n sep: string inserted between values, default a space.\n\n end: string appended after the last value, default a newline."); + } + } + _ => unreachable!("test error"), + } } } diff --git a/kclvm/tools/src/LSP/src/test_data/hover_test/hover.k b/kclvm/tools/src/LSP/src/test_data/hover_test/hover.k index dbf79fd84..8eeff9c47 100644 --- a/kclvm/tools/src/LSP/src/test_data/hover_test/hover.k +++ b/kclvm/tools/src/LSP/src/test_data/hover_test/hover.k @@ -21,3 +21,5 @@ p = Person{ import base64 abdc = base64.encode("1") abcd = "a".count() + +print(1) diff --git a/kclvm/tools/src/LSP/src/tests.rs b/kclvm/tools/src/LSP/src/tests.rs index b118d864d..04afac3bb 100644 --- a/kclvm/tools/src/LSP/src/tests.rs +++ b/kclvm/tools/src/LSP/src/tests.rs @@ -1096,47 +1096,39 @@ fn konfig_completion_test_main() { label: item.to_string(), })); let expect: CompletionResponse = into_completion_items(&items).into(); - match got { - CompletionResponse::Array(arr) => { - for item in arr { - println!("{:?},", item.label); - } - } - CompletionResponse::List(_) => todo!(), - } - // assert_eq!(got, expect); - // items.clear(); - - // // import path completion - // let pos = KCLPos { - // filename: main_path_str.clone(), - // line: 1, - // column: Some(35), - // }; - // let got = completion(Some('.'), &program, &pos, &prog_scope).unwrap(); - // let pkgs = [ - // "common", - // "configmap", - // "container", - // "ingress", - // "job", - // "rbac", - // "resource", - // "secret", - // "server", - // "service", - // "serviceaccount", - // "sidecar", - // "storage", - // "strategy", - // "volume", - // ]; - // items.extend(pkgs.iter().map(|item| KCLCompletionItem { - // label: item.to_string(), - // })); - // let expect: CompletionResponse = into_completion_items(&items).into(); - - // assert_eq!(got, expect); + assert_eq!(got, expect); + items.clear(); + + // import path completion + let pos = KCLPos { + filename: main_path_str.clone(), + line: 1, + column: Some(35), + }; + let got = completion(Some('.'), &program, &pos, &prog_scope).unwrap(); + let pkgs = [ + "common", + "configmap", + "container", + "ingress", + "job", + "rbac", + "resource", + "secret", + "server", + "service", + "serviceaccount", + "sidecar", + "storage", + "strategy", + "volume", + ]; + items.extend(pkgs.iter().map(|item| KCLCompletionItem { + label: item.to_string(), + })); + let expect: CompletionResponse = into_completion_items(&items).into(); + + assert_eq!(got, expect); } #[test]