diff --git a/src/lsp/completion.rs b/src/lsp/completion.rs index d19d039..1769cc5 100644 --- a/src/lsp/completion.rs +++ b/src/lsp/completion.rs @@ -683,6 +683,9 @@ fn top_level_keyword_completions() -> Vec { keyword_item("location", "Define a location", "location ${1:Name} {\n $0\n}"), keyword_item("species", "Define a species", "species ${1:Name} {\n $0\n}"), keyword_item("use", "Import declarations", "use ${1:path::to::item};"), + keyword_item("concept", "Define an algebraic data type", "concept ${1:Name};"), + keyword_item("sub_concept", "Define a sub-type", "sub_concept ${1:Parent}.${2:Name} {\n $0\n}"), + keyword_item("concept_comparison", "Pattern match on concepts", "concept_comparison ${1:Name} {\n $0\n}"), ] } diff --git a/src/lsp/completion_tests.rs b/src/lsp/completion_tests.rs index 301b727..739a600 100644 --- a/src/lsp/completion_tests.rs +++ b/src/lsp/completion_tests.rs @@ -248,6 +248,57 @@ character Bob {}"#; } } + #[test] + fn test_type_system_completions() { + let doc = Document::new("".to_string()); + let params = make_params(0, 0); + + let result = completion::get_completions(&doc, ¶ms); + assert!(result.is_some()); + + if let Some(response) = result { + match response { + | tower_lsp::lsp_types::CompletionResponse::Array(items) => { + // Should have type system keywords + assert!( + items.iter().any(|item| item.label == "concept"), + "Should have concept keyword" + ); + assert!( + items.iter().any(|item| item.label == "sub_concept"), + "Should have sub_concept keyword" + ); + assert!( + items.iter().any(|item| item.label == "concept_comparison"), + "Should have concept_comparison keyword" + ); + + // Check snippets have correct format + let concept_item = items.iter().find(|item| item.label == "concept"); + assert!(concept_item.is_some()); + if let Some(item) = concept_item { + let snippet = item.insert_text.as_ref().unwrap(); + assert!( + snippet.contains(";"), + "concept snippet should end with semicolon" + ); + } + + let sub_item = items.iter().find(|item| item.label == "sub_concept"); + assert!(sub_item.is_some()); + if let Some(item) = sub_item { + let snippet = item.insert_text.as_ref().unwrap(); + assert!( + snippet.contains("."), + "sub_concept snippet should contain dot notation" + ); + } + }, + | _ => panic!("Expected array response"), + } + } + } + #[test] fn test_no_duplicate_completions() { let source = "character Alice {}\ncharacter Alice {}"; // Duplicate name