From 82b4f6f0926d85016e0b144ab9fc5ae9082a1936 Mon Sep 17 00:00:00 2001 From: light-ly Date: Wed, 13 Nov 2024 22:24:07 +0800 Subject: [PATCH 1/2] add primitives auto instantiation --- src/completion/sv.rs | 47 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/src/completion/sv.rs b/src/completion/sv.rs index 0d87213..9e5bb34 100644 --- a/src/completion/sv.rs +++ b/src/completion/sv.rs @@ -199,6 +199,23 @@ fn get_completion_token(text: &Rope, line: RopeSlice, pos: Position) -> String { } } +fn make_primitives_instantiation_code(text: &str) -> String { + let mut instantiations = text.lines() + .filter(|line| !line.trim().is_empty() && !line.trim().starts_with("//")) + .collect::>(); + // remove fake module and endmodule + instantiations.remove(0); + instantiations.pop(); + + instantiations.iter().map(|line| { + let trimmed = line.trim_start(); + if trimmed.contains('.') { + format!("\t{}", trimmed) + } else { + trimmed.to_string() + } + }).collect::>().join("\n") +} fn make_instantiation_code(module: &crate::core::hdlparam::Module) -> String { @@ -270,27 +287,41 @@ fn make_module_completions( let prefix = token.to_string().to_lowercase(); let path_to_files = server.srcs.hdl_param.path_to_hdl_file.read().unwrap(); - + // 遍历 hdlparam 中所有的 modules for (path_string, hdl_file) in path_to_files.iter() { for module in &hdl_file.fast.content { if !module.name.to_string().to_lowercase().starts_with(&prefix) { continue; } - let insert_text = make_instantiation_code(module); - let module_profile = make_module_profile_code(module); + let (insert_text, module_profile, define_info) = if hdl_file.fast.file_type == "primitives" { + let primitive_map = server.srcs.primitive_text.name_to_text.read().unwrap(); + if let Some(text) = primitive_map.get(&module.name) { + ( + make_primitives_instantiation_code(&text), + (*text).clone(), + format!("[Definition] Primitive module: {}", module.name) + ) + } else { + continue; + } + } else { + let path_uri = Url::from_file_path(path_string.to_string()).unwrap().to_string(); + let def_row = module.range.start.line; + let def_col = module.range.start.character; - let path_uri = Url::from_file_path(path_string.to_string()).unwrap().to_string(); - let def_row = module.range.start.line; - let def_col = module.range.start.character; - let define_info = format!("Go to [Definition]({path_uri}#L{def_row}:{def_col})"); + ( + make_instantiation_code(module), + make_module_profile_code(module), + format!("Go to [Definition]({path_uri}#L{def_row}:{def_col})") + ) + }; let module_profile = MarkupContent { kind: MarkupKind::Markdown, value: format!("```{}\n{}\n```\n{}", language_id, module_profile, define_info) }; - let item = CompletionItem { label: module.name.to_string(), detail: Some("module instantiation".to_string()), From ec5e1f19c4400165df2e28f197efbf375721b2ec Mon Sep 17 00:00:00 2001 From: light-ly Date: Wed, 13 Nov 2024 22:45:18 +0800 Subject: [PATCH 2/2] add primitives port/param auto completion --- src/completion/feature.rs | 154 +++++++++++++++++++++++++------------- src/completion/sv.rs | 15 +++- 2 files changed, 113 insertions(+), 56 deletions(-) diff --git a/src/completion/feature.rs b/src/completion/feature.rs index fe81758..9aaeeea 100644 --- a/src/completion/feature.rs +++ b/src/completion/feature.rs @@ -167,35 +167,58 @@ fn get_position_port_param_completion( // 补全当前 module 的所有 param if let Some((inst_module, file_type, _)) = hdl_param.find_module_context_by_name(&instance.inst_type) { let mut completion_items = Vec::::new(); - for param in inst_module.params { - let label_details = CompletionItemLabelDetails { - detail: None, - ..CompletionItemLabelDetails::default() - }; + match file_type.as_str() { + "primitives" => { + if let Some(primitives_inst) = inst_module.instances.first() { + for param_assignment in &primitives_inst.intstparam_assignments { + let label_details = CompletionItemLabelDetails { + detail: None, + ..CompletionItemLabelDetails::default() + }; - let param_desc = match file_type.as_str() { - "common" => { - param.to_vlog_description() - } - "ip" => { - param.to_vhdl_description() - } - "primitives" => { - param.to_vlog_description() - } - _ => { - param.to_vlog_description() - } - }; + let name = param_assignment.parameter.clone().unwrap(); + let param_desc = format!("parameter {}", name); - let c_item = CompletionItem { - label: param.name, - detail: Some(param_desc), - label_details: Some(label_details), - kind: Some(CompletionItemKind::TYPE_PARAMETER), - ..CompletionItem::default() - }; - completion_items.push(c_item); + let c_item = CompletionItem { + label: name, + detail: Some(param_desc), + label_details: Some(label_details), + kind: Some(CompletionItemKind::TYPE_PARAMETER), + ..CompletionItem::default() + }; + completion_items.push(c_item); + } + } + } + _ => { + for param in inst_module.params { + let label_details = CompletionItemLabelDetails { + detail: None, + ..CompletionItemLabelDetails::default() + }; + + let param_desc = match file_type.as_str() { + "common" => { + param.to_vlog_description() + } + "ip" => { + param.to_vhdl_description() + } + _ => { + param.to_vlog_description() + } + }; + + let c_item = CompletionItem { + label: param.name, + detail: Some(param_desc), + label_details: Some(label_details), + kind: Some(CompletionItemKind::TYPE_PARAMETER), + ..CompletionItem::default() + }; + completion_items.push(c_item); + } + } } return Some(CompletionList { is_incomplete: false, @@ -210,35 +233,58 @@ fn get_position_port_param_completion( if port_range.contains(pos) { if let Some((inst_module, file_type, _)) = hdl_param.find_module_context_by_name(&instance.inst_type) { let mut completion_items = Vec::::new(); - for port in inst_module.ports { - let label_details = CompletionItemLabelDetails { - detail: None, - ..CompletionItemLabelDetails::default() - }; + match file_type.as_str() { + "primitives" => { + if let Some(primitives_inst) = inst_module.instances.first() { + for port_assignment in &primitives_inst.intstport_assignments { + let label_details = CompletionItemLabelDetails { + detail: None, + ..CompletionItemLabelDetails::default() + }; - let port_desc = match file_type.as_str() { - "common" => { - port.to_vlog_description() - } - "ip" => { - port.to_vhdl_description() - } - "primitives" => { - port.to_vlog_description() - } - _ => { - port.to_vlog_description() - } - }; + let name = port_assignment.port.clone().unwrap(); + let port_desc = format!("parameter {}", name); - let c_item = CompletionItem { - label: port.name, - detail: Some(port_desc), - label_details: Some(label_details), - kind: Some(CompletionItemKind::PROPERTY), - ..CompletionItem::default() - }; - completion_items.push(c_item); + let c_item = CompletionItem { + label: name, + detail: Some(port_desc), + label_details: Some(label_details), + kind: Some(CompletionItemKind::PROPERTY), + ..CompletionItem::default() + }; + completion_items.push(c_item); + } + } + } + _ => { + for port in inst_module.ports { + let label_details = CompletionItemLabelDetails { + detail: None, + ..CompletionItemLabelDetails::default() + }; + + let port_desc = match file_type.as_str() { + "common" => { + port.to_vlog_description() + } + "ip" => { + port.to_vhdl_description() + } + _ => { + port.to_vlog_description() + } + }; + + let c_item = CompletionItem { + label: port.name, + detail: Some(port_desc), + label_details: Some(label_details), + kind: Some(CompletionItemKind::PROPERTY), + ..CompletionItem::default() + }; + completion_items.push(c_item); + } + } } return Some(CompletionList { is_incomplete: false, diff --git a/src/completion/sv.rs b/src/completion/sv.rs index 9e5bb34..ec59f10 100644 --- a/src/completion/sv.rs +++ b/src/completion/sv.rs @@ -217,6 +217,17 @@ fn make_primitives_instantiation_code(text: &str) -> String { }).collect::>().join("\n") } +fn make_primitives_module_profile_code(text: &str) -> String { + let mut lines: Vec<&str> = text.split_inclusive('\n').collect(); + + if lines.len() > 1 { + lines.remove(0); + lines.pop(); + } + + lines.join("") +} + fn make_instantiation_code(module: &crate::core::hdlparam::Module) -> String { // makeVlogParamAssignments 参数信息列表 @@ -298,8 +309,8 @@ fn make_module_completions( let primitive_map = server.srcs.primitive_text.name_to_text.read().unwrap(); if let Some(text) = primitive_map.get(&module.name) { ( - make_primitives_instantiation_code(&text), - (*text).clone(), + make_primitives_instantiation_code(text), + make_primitives_module_profile_code(text), format!("[Definition] Primitive module: {}", module.name) ) } else {