From 22bc8599704f6ca9e8599e0eea849714ac37e234 Mon Sep 17 00:00:00 2001 From: He1pa <56333845+He1pa@users.noreply.github.com> Date: Wed, 17 Jan 2024 17:04:19 +0800 Subject: [PATCH] fix: fix lsp complete in comment after str type var (#992) * fix: fix lsp complete in comment after str type var Signed-off-by: he1pa <18012015693@163.com> * test: fix ut Signed-off-by: he1pa <18012015693@163.com> --------- Signed-off-by: he1pa <18012015693@163.com> --- kclvm/sema/src/advanced_resolver/node.rs | 18 ++- kclvm/sema/src/core/global_state.rs | 21 +++ kclvm/sema/src/core/symbol.rs | 140 ++++++++++++++++++ kclvm/tools/src/LSP/src/completion.rs | 21 +++ kclvm/tools/src/LSP/src/document_symbol.rs | 1 + kclvm/tools/src/LSP/src/semantic_token.rs | 2 + .../completion_test/assign/completion.k | 12 +- .../completion_test/dot/lit_str/lit_str.k | 3 +- 8 files changed, 208 insertions(+), 10 deletions(-) diff --git a/kclvm/sema/src/advanced_resolver/node.rs b/kclvm/sema/src/advanced_resolver/node.rs index 4776a96fb..9106d8be0 100644 --- a/kclvm/sema/src/advanced_resolver/node.rs +++ b/kclvm/sema/src/advanced_resolver/node.rs @@ -10,7 +10,8 @@ use crate::{ core::{ scope::LocalSymbolScopeKind, symbol::{ - ExpressionSymbol, KCLSymbolSemanticInfo, SymbolRef, UnresolvedSymbol, ValueSymbol, + CommentSymbol, ExpressionSymbol, KCLSymbolSemanticInfo, SymbolRef, UnresolvedSymbol, + ValueSymbol, }, }, ty::{Type, SCHEMA_MEMBER_FUNCTIONS}, @@ -27,6 +28,13 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { for stmt in module.body.iter() { self.stmt(&stmt); } + for comment in module.comments.iter() { + let (start, end) = comment.get_span_pos(); + self.ctx.start_pos = start; + self.ctx.end_pos = end; + self.ctx.cur_node = comment.id.clone(); + self.walk_comment(&comment.node); + } None } @@ -729,8 +737,12 @@ impl<'ctx> MutSelfTypedResultWalker<'ctx> for AdvancedResolver<'ctx> { None } - fn walk_comment(&mut self, _comment: &'ctx ast::Comment) -> Self::Result { - None + fn walk_comment(&mut self, comment: &'ctx ast::Comment) -> Self::Result { + let (start, end) = (self.ctx.start_pos.clone(), self.ctx.end_pos.clone()); + let comment_symbol = CommentSymbol::new(start, end, comment.text.clone()); + self.gs + .get_symbols_mut() + .alloc_comment_symbol(comment_symbol, self.ctx.get_node_key(&self.ctx.cur_node)) } fn walk_missing_expr(&mut self, _missing_expr: &'ctx ast::MissingExpr) -> Self::Result { diff --git a/kclvm/sema/src/core/global_state.rs b/kclvm/sema/src/core/global_state.rs index b34069fff..353e96be3 100644 --- a/kclvm/sema/src/core/global_state.rs +++ b/kclvm/sema/src/core/global_state.rs @@ -420,6 +420,27 @@ impl GlobalState { }, ); } + + for (index, symbol) in self.symbols.comments.iter() { + let symbol_ref = SymbolRef { + kind: SymbolKind::Comment, + id: index, + }; + let filename = symbol.start.filename.clone(); + if !file_sema_map.contains_key(&filename) { + file_sema_map.insert(filename.clone(), FileSemanticInfo::new(filename.clone())); + } + let file_sema_info = file_sema_map.get_mut(&filename).unwrap(); + file_sema_info.symbols.push(symbol_ref); + file_sema_info.symbol_locs.insert( + symbol_ref, + CachedLocation { + line: symbol.start.line, + column: symbol.start.column.unwrap_or(0), + }, + ); + } + // remove dummy file file_sema_map.remove(""); diff --git a/kclvm/sema/src/core/symbol.rs b/kclvm/sema/src/core/symbol.rs index 3709ac2c5..f4aecc488 100644 --- a/kclvm/sema/src/core/symbol.rs +++ b/kclvm/sema/src/core/symbol.rs @@ -65,6 +65,7 @@ pub struct SymbolData { pub(crate) unresolved: Arena, pub(crate) rules: Arena, pub(crate) exprs: Arena, + pub(crate) comments: Arena, pub(crate) symbols_info: SymbolDB, } @@ -162,6 +163,10 @@ impl SymbolData { .exprs .get(id.get_id()) .map(|symbol| symbol as &KCLSymbol), + SymbolKind::Comment => self + .comments + .get(id.get_id()) + .map(|symbol| symbol as &KCLSymbol), } } @@ -215,6 +220,12 @@ impl SymbolData { symbol }); } + SymbolKind::Comment => { + self.comments.get_mut(id.get_id()).map(|symbol| { + symbol.sema_info.ty = Some(ty); + symbol + }); + } } } @@ -624,6 +635,26 @@ impl SymbolData { pub fn get_node_symbol_map(&self) -> IndexMap { self.symbols_info.node_symbol_map.clone() } + + pub fn alloc_comment_symbol( + &mut self, + comment: CommentSymbol, + node_key: NodeKey, + ) -> Option { + let symbol_id = self.comments.insert(comment); + let symbol_ref = SymbolRef { + id: symbol_id, + kind: SymbolKind::Comment, + }; + self.symbols_info + .node_symbol_map + .insert(node_key.clone(), symbol_ref); + self.symbols_info + .symbol_ref_map + .insert(symbol_ref, node_key); + self.exprs.get_mut(symbol_id).unwrap().id = Some(symbol_ref); + Some(symbol_ref) + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize)] @@ -636,6 +667,7 @@ pub enum SymbolKind { Unresolved, Rule, Expression, + Comment, } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -1755,3 +1787,111 @@ impl ExpressionSymbol { } } } + +#[derive(Debug, Clone)] +pub struct CommentSymbol { + pub(crate) id: Option, + pub(crate) start: Position, + pub(crate) end: Position, + pub(crate) content: String, + pub(crate) sema_info: KCLSymbolSemanticInfo, +} + +impl Symbol for CommentSymbol { + type SymbolData = SymbolData; + type SemanticInfo = KCLSymbolSemanticInfo; + + fn get_sema_info(&self) -> &Self::SemanticInfo { + &self.sema_info + } + + fn is_global(&self) -> bool { + true + } + + fn get_range(&self) -> Range { + (self.start.clone(), self.end.clone()) + } + + fn get_owner(&self) -> Option { + None + } + + fn get_definition(&self) -> Option { + self.id + } + + fn get_name(&self) -> String { + self.name() + } + + fn get_id(&self) -> Option { + self.id.clone() + } + + fn get_attribute( + &self, + _name: &str, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> Option { + None + } + + fn has_attribute( + &self, + _name: &str, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> bool { + false + } + + fn get_all_attributes( + &self, + _data: &Self::SymbolData, + _module_info: Option<&ModuleInfo>, + ) -> Vec { + vec![] + } + + fn simple_dump(&self) -> String { + let mut output = "{\n".to_string(); + output.push_str("\"kind\": \"CommentSymbol\",\n"); + output.push_str(&format!( + "\"range\": \"{}:{}", + self.start.filename, self.start.line + )); + if let Some(start_col) = self.start.column { + output.push_str(&format!(":{}", start_col)); + } + + output.push_str(&format!(" to {}", self.end.line)); + if let Some(end_col) = self.end.column { + output.push_str(&format!(":{}", end_col)); + } + output.push_str(&format!("content :{}", self.name())); + output.push_str("\"\n}"); + output + } + + fn full_dump(&self, _data: &Self::SymbolData) -> Option { + Some(self.simple_dump()) + } +} + +impl CommentSymbol { + pub fn new(start: Position, end: Position, content: String) -> Self { + Self { + id: None, + start, + end, + content, + sema_info: KCLSymbolSemanticInfo::default(), + } + } + + pub fn name(&self) -> String { + format!("# {}", self.content) + } +} diff --git a/kclvm/tools/src/LSP/src/completion.rs b/kclvm/tools/src/LSP/src/completion.rs index 4d3091bd8..e98298315 100644 --- a/kclvm/tools/src/LSP/src/completion.rs +++ b/kclvm/tools/src/LSP/src/completion.rs @@ -1467,4 +1467,25 @@ mod tests { CompletionResponse::List(_) => panic!("test failed"), } } + + #[test] + fn comment_completion() { + let (file, program, _, _, gs) = + compile_test_file("src/test_data/completion_test/dot/lit_str/lit_str.k"); + + let pos = KCLPos { + filename: file.to_owned(), + line: 4, + column: Some(4), + }; + + let got = completion(Some('.'), &program, &pos, &gs).unwrap(); + + match &got { + CompletionResponse::Array(arr) => { + assert_eq!(arr.len(), 0) + } + CompletionResponse::List(_) => panic!("test failed"), + }; + } } diff --git a/kclvm/tools/src/LSP/src/document_symbol.rs b/kclvm/tools/src/LSP/src/document_symbol.rs index 872a92567..ba2dddcbe 100644 --- a/kclvm/tools/src/LSP/src/document_symbol.rs +++ b/kclvm/tools/src/LSP/src/document_symbol.rs @@ -131,6 +131,7 @@ fn symbol_kind_to_document_symbol_kind(kind: KCLSymbolKind) -> Option Some(SymbolKind::NULL), KCLSymbolKind::Rule => Some(SymbolKind::FUNCTION), KCLSymbolKind::Expression => None, + KCLSymbolKind::Comment => None, } } diff --git a/kclvm/tools/src/LSP/src/semantic_token.rs b/kclvm/tools/src/LSP/src/semantic_token.rs index 59be78472..259119654 100644 --- a/kclvm/tools/src/LSP/src/semantic_token.rs +++ b/kclvm/tools/src/LSP/src/semantic_token.rs @@ -11,6 +11,7 @@ pub const LEGEND_TYPE: &[SemanticTokenType] = &[ SemanticTokenType::NAMESPACE, SemanticTokenType::TYPE, SemanticTokenType::MACRO, + SemanticTokenType::COMMENT, ]; pub(crate) struct KCLSemanticToken { @@ -39,6 +40,7 @@ pub(crate) fn semantic_tokens_full(file: &str, gs: &GlobalState) -> Option type_index(SemanticTokenType::MACRO), + SymbolKind::Comment => type_index(SemanticTokenType::COMMENT), SymbolKind::Expression => unreachable!(), }; kcl_tokens.push(KCLSemanticToken { diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/assign/completion.k b/kclvm/tools/src/LSP/src/test_data/completion_test/assign/completion.k index 687bc8100..dbf87d567 100644 --- a/kclvm/tools/src/LSP/src/test_data/completion_test/assign/completion.k +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/assign/completion.k @@ -13,15 +13,15 @@ schema Person2: p: Person2{ a # complete `True` and `False` - b # complete `"abc"` and `"def"` + b # complete `"abc"` and `"def"` - c # complete `[]` + c # complete `[]` - d # complete `1` + d # complete `1` - e # complete `True` + e # complete `True` - f # complete `{}` + f # complete `{}` - g # complete `subpkg.Person1{}` + g # complete `subpkg.Person1{}` } diff --git a/kclvm/tools/src/LSP/src/test_data/completion_test/dot/lit_str/lit_str.k b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/lit_str/lit_str.k index 875937e32..cb6be0681 100644 --- a/kclvm/tools/src/LSP/src/test_data/completion_test/dot/lit_str/lit_str.k +++ b/kclvm/tools/src/LSP/src/test_data/completion_test/dot/lit_str/lit_str.k @@ -1,3 +1,4 @@ a = "aaa" "aaa" -a \ No newline at end of file +a +# a \ No newline at end of file