From aed9addb2e35d85cb6b0b8485e19c0689e312139 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 16 Jan 2025 00:43:49 +0530 Subject: [PATCH] Enhancement: Add example highlight hover content for the schema definition doc and test Signed-off-by: Siddhi Agrawal --- kclvm/tools/src/LSP/src/hover.rs | 48 +++++++++++++++++++ .../hover_test/schema_with_examples.k | 31 ++++++++++++ kclvm/tools/src/LSP/src/tests.rs | 4 ++ 3 files changed, 83 insertions(+) create mode 100644 kclvm/tools/src/LSP/src/test_data/hover_test/schema_with_examples.k diff --git a/kclvm/tools/src/LSP/src/hover.rs b/kclvm/tools/src/LSP/src/hover.rs index c69c19b40..8c77fd0ac 100644 --- a/kclvm/tools/src/LSP/src/hover.rs +++ b/kclvm/tools/src/LSP/src/hover.rs @@ -77,6 +77,17 @@ pub fn hover(kcl_pos: &KCLPos, gs: &GlobalState) -> Option { if !schema_ty.doc.is_empty() { docs.push((schema_ty.doc.clone(), MarkedStringType::String)); + + // Add examples to the hover content + if !schema_ty.examples.is_empty() { + let examples = schema_ty + .examples + .iter() + .map(|(_, example)| format!("{}\n", example.value)) + .collect::>() + .join("\n"); + docs.push((examples, MarkedStringType::LanguageString)); + } } } _ => {} @@ -777,4 +788,41 @@ mod tests { })); assert_eq!(got.contents, expected); } + + #[test] + #[bench_test] + fn schema_doc_with_examples_hover_test() { + let (file, _program, _, gs, _) = + compile_test_file("src/test_data/hover_test/schema_with_examples.k"); + + let pos = KCLPos { + filename: file.clone(), + line: 1, + column: Some(8), + }; + let got = hover(&pos, &gs).unwrap(); + + let expect_content = vec![ + lsp_types::MarkedString::String("__main__".to_string()), + lsp_types::MarkedString::LanguageString(lsp_types::LanguageString { + language: "KCL".to_string(), + value: "schema Server:\n workloadType: str = \"Deployment\"\n name: str\n labels?: {str:str}".to_string(), + }), + lsp_types::MarkedString::String("Server is an abstraction of Deployment and StatefulSet.".to_string()), + lsp_types::MarkedString::LanguageString(lsp_types::LanguageString { + language: "KCL".to_string(), + value: "import models.kube.frontend\nimport models.kube.frontend.container\nimport models.kube.templates.resource as res_tpl\n\nappConfiguration: frontend.Server {\n mainContainer = container.Main {\n name = \"php-redis\"\n env: {\n \"GET_HOSTS_FROM\": {value = \"dns\"}\n }\n }\n}\n".to_string() + }), + ]; + + match got.contents { + lsp_types::HoverContents::Array(vec) => { + assert_eq!(vec.len(), expect_content.len()); + for (i, expected) in expect_content.iter().enumerate() { + assert_eq!(&vec[i], expected); + } + } + _ => unreachable!("test error"), + } + } } diff --git a/kclvm/tools/src/LSP/src/test_data/hover_test/schema_with_examples.k b/kclvm/tools/src/LSP/src/test_data/hover_test/schema_with_examples.k new file mode 100644 index 000000000..94064b785 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/hover_test/schema_with_examples.k @@ -0,0 +1,31 @@ +schema Server: + """Server is an abstraction of Deployment and StatefulSet. + + Attributes + ---------- + workloadType : str, default is "Deployment", required + Use this attribute to specify which kind of long-running service you want. + Valid values: Deployment, StatefulSet. + name : str, required + The name of the long-running service. + labels : {str:str}, optional + The labels of the long-running service. + + Examples + -------- + import models.kube.frontend + import models.kube.frontend.container + import models.kube.templates.resource as res_tpl + + appConfiguration: frontend.Server { + mainContainer = container.Main { + name = "php-redis" + env: { + "GET_HOSTS_FROM": {value = "dns"} + } + } + } + """ + workloadType : str = "Deployment" + name: str + labels?: {str: str} diff --git a/kclvm/tools/src/LSP/src/tests.rs b/kclvm/tools/src/LSP/src/tests.rs index 6143fb414..c786436fd 100644 --- a/kclvm/tools/src/LSP/src/tests.rs +++ b/kclvm/tools/src/LSP/src/tests.rs @@ -2006,6 +2006,10 @@ fn konfig_hover_test_main() { value: "schema Server:\n name?: str\n workloadType: \"Deployment\" | \"StatefulSet\" = \"Deployment\"\n renderType?: \"Server\" | \"KubeVelaApplication\" = \"Server\"\n replicas: int = option(\"replicas\") or 1\n image: str = option(\"image\")\n schedulingStrategy: SchedulingStrategy = strategy.SchedulingStrategy {}\n mainContainer: Main\n sidecarContainers?: [Sidecar]\n initContainers?: [Sidecar]\n useBuiltInLabels?: bool = True\n labels?: {str:str}\n annotations?: {str:str}\n useBuiltInSelector?: bool = True\n selector?: {str:str}\n podMetadata?: ObjectMeta\n volumes?: [Volume]\n needNamespace?: bool = True\n enableMonitoring?: bool = False\n configMaps?: [ConfigMap]\n secrets?: [Secret]\n services?: [Service]\n ingresses?: [Ingress]\n serviceAccount?: ServiceAccount\n storage?: ObjectStorage\n database?: DataBase".to_string() }), MarkedString::String("Server is abstaction of Deployment and StatefulSet.".to_string()), + MarkedString::LanguageString(lsp_types::LanguageString { + language: "KCL".to_string(), + value: "import base.pkg.kusion_models.kube.frontend\nimport base.pkg.kusion_models.kube.frontend.container\nimport base.pkg.kusion_models.kube.templates.resource as res_tpl\n\nappConfiguration: frontend.Server {\n mainContainer = container.Main {\n name = \"php-redis\"\n env = [\n {\n name = \"GET_HOSTS_FROM\"\n value = \"dns\"\n }\n ]\n ports = [{containerPort = 80}]\n }\n selector = {\n tier = \"frontend\"\n }\n podMetadata.labels: {\n tier = \"frontend\"\n }\n schedulingStrategy.resource = res_tpl.tiny\n}\n".to_string() + }), ]; assert_eq!(expect, arr); }