diff --git a/src/cache.rs b/src/cache.rs index 4ae60a3..d67a9f8 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -1,8 +1,8 @@ use dashmap::DashMap; -use pest::error::Error; +use log::info; use tower_lsp::lsp_types::CompletionItem; -use crate::{parse_global_symbols, parse_skill}; +use crate::parse_skill; #[derive(PartialEq, Debug)] struct Position { @@ -32,14 +32,9 @@ impl SymbolCache { } pub fn update(&self, path: &str) { - self.symbols.insert(path.to_owned(), vec![]); let parsed = parse_skill(path); - for rule in parsed { - match parse_global_symbols(rule) { - Ok(_) => {} - Err(_) => {} - } - } + info!("parsed: {:?}", parsed); + self.symbols.insert(path.to_owned(), parsed); } } diff --git a/src/main.rs b/src/main.rs index 8d86e7e..999c9a9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -83,6 +83,13 @@ impl LanguageServer for Backend { Ok(InitializeResult { server_info: None, capabilities: ServerCapabilities { + workspace: Some(WorkspaceServerCapabilities { + workspace_folders: Some(WorkspaceFoldersServerCapabilities { + supported: Some(true), + change_notifications: Some(OneOf::Left(true)), + }), + file_operations: None, + }), execute_command_provider: Some(ExecuteCommandOptions { commands: vec!["custom/notification".to_string()], work_done_progress_options: Default::default(), @@ -134,14 +141,24 @@ impl LanguageServer for Backend { } async fn completion(&self, cparams: CompletionParams) -> Result> { - let symbols: Vec = self - .cache - .symbols - .get_mut(&cparams.text_document_position.text_document.uri.to_string()) - .unwrap() - .to_vec(); + info!("triggered completion"); + let path = cparams + .text_document_position + .text_document + .uri + .path() + .to_string(); + info!("for: {:?}", path); + info!("with: {:?}", self.cache.symbols); + let resp = self.cache.symbols.get(&path); + info!("returned: {:?}", resp); + Ok(Some(CompletionResponse::Array(resp.unwrap().to_vec()))) + } - Ok(Some(CompletionResponse::Array(symbols))) + async fn did_save(&self, params: DidSaveTextDocumentParams) { + let path = params.text_document.uri.path().to_string(); + info!("updating cahce for {:?}", path); + self.cache.update(&path); } } diff --git a/src/skill.pest b/src/skill.pest index fffeeaa..79985f1 100644 --- a/src/skill.pest +++ b/src/skill.pest @@ -8,7 +8,7 @@ number = @{NUMBER+ ~ ("." ~ NUMBER+)? ~ ("e" ~ "-"? ~ NUMBER+)?} bool = {"t" | "nil"} literal = _{string | number | bool} -COMMENT = _{";" ~ (!NEWLINE ~ ANY)* ~ NEWLINE} +COMMENT = {";" ~ (!NEWLINE ~ ANY)* ~ NEWLINE} lisp_list = _{ "(" ~ expr* ~ ")" } lazy_list = _{ "'(" ~ expr* ~ ")" } diff --git a/src/skill.rs b/src/skill.rs index 3ed15dc..67e8765 100644 --- a/src/skill.rs +++ b/src/skill.rs @@ -1,18 +1,81 @@ +use log::info; use pest::error::Error; use pest::iterators::Pair; - use pest::Parser; +use std::fs; -use log::info; +use tower_lsp::lsp_types::{ + lsif::{EdgeDataMultiIn, Item, ItemKind}, + CompletionItem, CompletionItemKind, CompletionItemLabelDetails, Documentation, MarkupContent, + MarkupKind, +}; #[derive(Parser)] #[grammar = "skill.pest"] pub struct SkillParser; -pub fn parse_skill(path: &str) -> Vec> { - let parsed = SkillParser::parse(Rule::skill, path); - info!("{:?}", parsed); - vec![] +fn recurse_pairs<'a>( + ps: Pair, + catalog: &'a mut Vec, + last_comment: Option, +) -> Option { + let mut comment = last_comment; + match ps.as_rule() { + Rule::skill => { + comment = None; + for p in ps.into_inner() { + comment = recurse_pairs(p, catalog, comment); + } + } + Rule::list => { + comment = None; + for p in ps.into_inner() { + comment = recurse_pairs(p, catalog, comment); + } + } + Rule::COMMENT => { + info!("encountered comment: {:?}", ps.as_str()); + if ps.as_str().starts_with(";;;") { + comment = Some(ps.as_str().strip_prefix(";;;").unwrap().trim().to_owned()); + info!("encountered docstring: {:?}", comment); + } + } + Rule::assign => { + let k = ps.into_inner().next().unwrap(); + + catalog.push(CompletionItem { + label: k.as_str().to_owned(), + kind: Some(CompletionItemKind::VARIABLE), + detail: match &comment { + Some(s) => Some(s.to_owned()), + None => None, + }, + label_details: Some(CompletionItemLabelDetails { + description: None, + detail: Some("global".to_owned()), + }), + ..Default::default() + }); + comment = None; + } + _ => { + comment = None; + } + } + comment +} + +pub fn parse_skill(path: &str) -> Vec { + let content = fs::read_to_string(path).expect("could not read file"); + let parsed = SkillParser::parse(Rule::skill, &content); + let mut ret = vec![]; + let mut last_comment: Option = None; + for pairs in parsed.into_iter() { + for pair in pairs.into_iter() { + last_comment = recurse_pairs(pair, &mut ret, last_comment) + } + } + ret } pub fn parse_global_symbols(token: Pair) -> Result<&str, Error> { Ok("") diff --git a/test/data/test.il b/test/data/test.il index e79e285..dd668e5 100644 --- a/test/data/test.il +++ b/test/data/test.il @@ -13,7 +13,9 @@ token '(lazy list) cstyle(list with args) -var = arg1 + arg2 - " A" / 12 +;;; precursor magnitude as controlvector +tap_mag = arg1 + arg2 - " A" / 12 +var2 = "a" obj->op() (let (a (b 3))