From 322c225870e34d503fb090dbc2edba27b166c4aa Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Wed, 13 Nov 2024 17:14:28 +0800 Subject: [PATCH 1/2] feat: lsp hint for config entry key type Signed-off-by: he1pa <18012015693@163.com> --- kclvm/sema/src/advanced_resolver/node.rs | 23 +++++- kclvm/sema/src/core/symbol.rs | 5 +- kclvm/tools/src/LSP/src/inlay_hints.rs | 44 ++++++++++-- ...er__inlay_hints__tests__config_key_ty.snap | 40 +++++++++-- ...__inlay_hints__tests__config_key_ty_1.snap | 72 +++++++++++++++++++ .../inlay_hints/config_key1/config_key.k | 9 +++ 6 files changed, 176 insertions(+), 17 deletions(-) create mode 100644 kclvm/tools/src/LSP/src/snapshots/kcl_language_server__inlay_hints__tests__config_key_ty_1.snap create mode 100644 kclvm/tools/src/LSP/src/test_data/inlay_hints/config_key1/config_key.k diff --git a/kclvm/sema/src/advanced_resolver/node.rs b/kclvm/sema/src/advanced_resolver/node.rs index f9e5204d5..b74ac15c6 100644 --- a/kclvm/sema/src/advanced_resolver/node.rs +++ b/kclvm/sema/src/advanced_resolver/node.rs @@ -7,6 +7,7 @@ use kclvm_ast::pos::GetPos; use kclvm_ast::walker::MutSelfTypedResultWalker; use kclvm_error::{diagnostic::Range, Position}; +use crate::core::symbol::Symbol; use crate::{ core::{ scope::{ConfigScopeContext, LocalSymbolScopeKind}, @@ -1977,7 +1978,27 @@ impl<'ctx> AdvancedResolver<'_> { if let Some(key) = &entry.node.key { self.ctx.maybe_def = true; - self.expr(key)?; + if let Some(symbol_ref) = self.expr(key)? { + if let Some(config_key_symbol) = + self.gs.get_symbols().unresolved.get(symbol_ref.get_id()) + { + if let Some(def_ref) = config_key_symbol.get_definition() { + if let Some(def_symbol) = self.gs.get_symbols().get_symbol(def_ref) { + let ty = def_symbol.get_sema_info().ty.clone(); + let symbols = self.gs.get_symbols_mut(); + if let Some(ty) = ty { + symbols.alloc_hint( + SymbolHint { + kind: SymbolHintKind::KeyTypeHint(ty.ty_hint()), + pos: key.get_end_pos(), + }, + self.ctx.current_pkgpath.clone().unwrap(), + ); + } + } + } + } + } self.ctx.maybe_def = false; } } diff --git a/kclvm/sema/src/core/symbol.rs b/kclvm/sema/src/core/symbol.rs index efad6eacd..cd14b03c3 100644 --- a/kclvm/sema/src/core/symbol.rs +++ b/kclvm/sema/src/core/symbol.rs @@ -92,16 +92,17 @@ pub struct SymbolDB { pub(crate) pkg_symbol_map: IndexMap>, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct SymbolHint { pub kind: SymbolHintKind, pub pos: Position, } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum SymbolHintKind { TypeHint(String), VarHint(String), + KeyTypeHint(String), } impl SymbolData { diff --git a/kclvm/tools/src/LSP/src/inlay_hints.rs b/kclvm/tools/src/LSP/src/inlay_hints.rs index f3b8fe7ac..ad4f17f04 100644 --- a/kclvm/tools/src/LSP/src/inlay_hints.rs +++ b/kclvm/tools/src/LSP/src/inlay_hints.rs @@ -4,6 +4,7 @@ use kclvm_sema::core::symbol::{SymbolHint, SymbolHintKind}; use lsp_types::{ InlayHint, InlayHintKind, InlayHintLabelPart, Position as LspPosition, Range, TextEdit, }; +use std::collections::HashMap; use std::hash::Hash; use crate::to_lsp::lsp_pos; @@ -43,10 +44,27 @@ pub fn inlay_hints(file: &str, gs: &GlobalState) -> Option> { let mut inlay_hints: IndexSet = Default::default(); let sema_db = gs.get_sema_db(); if let Some(file_sema) = sema_db.get_file_sema(file) { + let mut line_hint: HashMap = HashMap::new(); for hint in file_sema.get_hints() { - inlay_hints.insert(generate_inlay_hint(hint)); + match &hint.kind { + SymbolHintKind::KeyTypeHint(_) => match line_hint.get(&hint.pos.line) { + Some(h) => { + if hint.pos.column.unwrap_or_default() > h.pos.column.unwrap_or_default() { + line_hint.insert(hint.pos.line, hint.clone()); + } + } + None => { + line_hint.insert(hint.pos.line, hint.clone()); + } + }, + _ => { + inlay_hints.insert(generate_inlay_hint(hint)); + } + } } + inlay_hints.extend(line_hint.values().map(|h| generate_inlay_hint(h))); } + Some( inlay_hints .into_iter() @@ -54,7 +72,6 @@ pub fn inlay_hints(file: &str, gs: &GlobalState) -> Option> { .collect(), ) } - #[inline] fn generate_inlay_hint(hint: &SymbolHint) -> KCLInlayHint { let (part, position, kind) = get_hint_label(hint); @@ -67,6 +84,7 @@ fn generate_inlay_hint(hint: &SymbolHint) -> KCLInlayHint { new_text: part.value.clone(), }]), SymbolHintKind::VarHint(_) => None, + SymbolHintKind::KeyTypeHint(_) => None, }; KCLInlayHint { position, @@ -108,6 +126,14 @@ fn get_hint_label(hint: &SymbolHint) -> (InlayHintLabelPart, LspPosition, InlayH lsp_pos(&hint.pos), InlayHintKind::PARAMETER, ), + SymbolHintKind::KeyTypeHint(ty) => ( + InlayHintLabelPart { + value: format!(": {ty}"), + ..Default::default() + }, + lsp_pos(&hint.pos), + InlayHintKind::TYPE, + ), } } @@ -143,9 +169,13 @@ mod tests { "src/test_data/inlay_hints/schema_args/schema_args_hint.k" ); - // Temporary revert - // inlay_hints_test_snapshot!( - // test_config_key_ty, - // "src/test_data/inlay_hints/config_key/config_key.k" - // ); + inlay_hints_test_snapshot!( + test_config_key_ty, + "src/test_data/inlay_hints/config_key/config_key.k" + ); + + inlay_hints_test_snapshot!( + test_config_key_ty_1, + "src/test_data/inlay_hints/config_key1/config_key.k" + ); } diff --git a/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__inlay_hints__tests__config_key_ty.snap b/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__inlay_hints__tests__config_key_ty.snap index 83de2a964..7ae1593a3 100644 --- a/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__inlay_hints__tests__config_key_ty.snap +++ b/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__inlay_hints__tests__config_key_ty.snap @@ -1,6 +1,6 @@ --- source: tools/src/LSP/src/inlay_hints.rs -expression: "format!(\"{:#?}\", res)" +expression: "format! (\"{:#?}\", res)" --- Some( [ @@ -19,8 +19,26 @@ Some( }, ], ), - kind: None, - text_edits: None, + kind: Some( + Type, + ), + text_edits: Some( + [ + TextEdit { + range: Range { + start: Position { + line: 6, + character: 3, + }, + end: Position { + line: 6, + character: 3, + }, + }, + new_text: ": App", + }, + ], + ), tooltip: None, padding_left: None, padding_right: None, @@ -41,7 +59,9 @@ Some( }, ], ), - kind: None, + kind: Some( + Type, + ), text_edits: None, tooltip: None, padding_left: None, @@ -63,7 +83,9 @@ Some( }, ], ), - kind: None, + kind: Some( + Type, + ), text_edits: None, tooltip: None, padding_left: None, @@ -85,7 +107,9 @@ Some( }, ], ), - kind: None, + kind: Some( + Type, + ), text_edits: None, tooltip: None, padding_left: None, @@ -107,7 +131,9 @@ Some( }, ], ), - kind: None, + kind: Some( + Type, + ), text_edits: None, tooltip: None, padding_left: None, diff --git a/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__inlay_hints__tests__config_key_ty_1.snap b/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__inlay_hints__tests__config_key_ty_1.snap new file mode 100644 index 000000000..94a2071e7 --- /dev/null +++ b/kclvm/tools/src/LSP/src/snapshots/kcl_language_server__inlay_hints__tests__config_key_ty_1.snap @@ -0,0 +1,72 @@ +--- +source: tools/src/LSP/src/inlay_hints.rs +expression: "format! (\"{:#?}\", res)" +--- +Some( + [ + InlayHint { + position: Position { + line: 6, + character: 1, + }, + label: LabelParts( + [ + InlayHintLabelPart { + value: ": Person", + tooltip: None, + location: None, + command: None, + }, + ], + ), + kind: Some( + Type, + ), + text_edits: Some( + [ + TextEdit { + range: Range { + start: Position { + line: 6, + character: 1, + }, + end: Position { + line: 6, + character: 1, + }, + }, + new_text: ": Person", + }, + ], + ), + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + }, + InlayHint { + position: Position { + line: 7, + character: 13, + }, + label: LabelParts( + [ + InlayHintLabelPart { + value: ": str", + tooltip: None, + location: None, + command: None, + }, + ], + ), + kind: Some( + Type, + ), + text_edits: None, + tooltip: None, + padding_left: None, + padding_right: None, + data: None, + }, + ], +) diff --git a/kclvm/tools/src/LSP/src/test_data/inlay_hints/config_key1/config_key.k b/kclvm/tools/src/LSP/src/test_data/inlay_hints/config_key1/config_key.k new file mode 100644 index 000000000..50b3ed7b4 --- /dev/null +++ b/kclvm/tools/src/LSP/src/test_data/inlay_hints/config_key1/config_key.k @@ -0,0 +1,9 @@ +schema Name: + name: str + +schema Person: + name: Name + +p = Person{ + name.name = "" +} \ No newline at end of file From b45e7a4192a3a13845c7d275dc84ac8783c36357 Mon Sep 17 00:00:00 2001 From: he1pa <18012015693@163.com> Date: Wed, 13 Nov 2024 17:42:19 +0800 Subject: [PATCH 2/2] update ut snapshot Signed-off-by: he1pa <18012015693@163.com> --- kclvm/tools/src/LSP/src/inlay_hints.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/kclvm/tools/src/LSP/src/inlay_hints.rs b/kclvm/tools/src/LSP/src/inlay_hints.rs index ad4f17f04..f9a4817f2 100644 --- a/kclvm/tools/src/LSP/src/inlay_hints.rs +++ b/kclvm/tools/src/LSP/src/inlay_hints.rs @@ -1,10 +1,9 @@ -use indexmap::IndexSet; +use indexmap::{IndexMap, IndexSet}; use kclvm_sema::core::global_state::GlobalState; use kclvm_sema::core::symbol::{SymbolHint, SymbolHintKind}; use lsp_types::{ InlayHint, InlayHintKind, InlayHintLabelPart, Position as LspPosition, Range, TextEdit, }; -use std::collections::HashMap; use std::hash::Hash; use crate::to_lsp::lsp_pos; @@ -44,7 +43,7 @@ pub fn inlay_hints(file: &str, gs: &GlobalState) -> Option> { let mut inlay_hints: IndexSet = Default::default(); let sema_db = gs.get_sema_db(); if let Some(file_sema) = sema_db.get_file_sema(file) { - let mut line_hint: HashMap = HashMap::new(); + let mut line_hint: IndexMap = IndexMap::new(); for hint in file_sema.get_hints() { match &hint.kind { SymbolHintKind::KeyTypeHint(_) => match line_hint.get(&hint.pos.line) {