From 15cfaccec1ad370951bc283cdf8cea5719479b47 Mon Sep 17 00:00:00 2001 From: LSTM-Kirigaya <1193466151@qq.com> Date: Tue, 12 Nov 2024 15:56:29 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=86=20vhdl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/lsp.code-snippets | 20 ++++++++++ src/completion/feature.rs | 77 +++++++++++++++++---------------------- src/core/hdlparam.rs | 30 +++------------ src/core/vhdl_parser.rs | 9 ++++- src/hover/feature.rs | 14 +++---- src/inlay_hint/sv.rs | 8 ++-- src/request/mod.rs | 14 ++++++- src/server.rs | 4 ++ src/sources.rs | 43 +++++++++------------- 9 files changed, 111 insertions(+), 108 deletions(-) diff --git a/.vscode/lsp.code-snippets b/.vscode/lsp.code-snippets index 334faab..865456b 100644 --- a/.vscode/lsp.code-snippets +++ b/.vscode/lsp.code-snippets @@ -15,5 +15,25 @@ "#[allow(unused)]" ], "description": "#[allow(unused)]" + }, + "match file_type": { + "scope": "rust", + "prefix": "matchfiletype", + "body": [ + "match file_type.as_str() {", + "\t\"common\" => {", + "\t\t", + "\t}", + "\t\"ip\" => {", + "\t\t", + "\t}", + "\t\"primitives\" => {", + "\t\t", + "\t}", + "\t_ => {", + "\t\t", + "\t}", + "}", + ] } } \ No newline at end of file diff --git a/src/completion/feature.rs b/src/completion/feature.rs index d7dfb53..fe81758 100644 --- a/src/completion/feature.rs +++ b/src/completion/feature.rs @@ -156,18 +156,16 @@ fn get_position_port_param_completion( let path = PathBuf::from_str(url.path()).unwrap(); let path = to_escape_path(&path); let path_string = path.to_str().unwrap(); - info!("enter get_position_port_param_completion, pos: {pos:?}"); + // info!("enter get_position_port_param_completion, pos: {pos:?}"); if let Some(hdl_file) = fast_map.get(path_string) { - info!("find hdl_file, content: {:?}", hdl_file.fast.content); + // info!("find hdl_file, content: {:?}", hdl_file.fast.content); // 在当前文件的 fast 中寻找 for module in &hdl_file.fast.content { for instance in &module.instances { if let Some(_) = &instance.instparams { if instance.gen_dot_completion_param_range().contains(pos) { // 补全当前 module 的所有 param - let inst_module = hdl_param.find_module_by_name(&instance.inst_type); - if inst_module.is_some() { - let inst_module = inst_module.unwrap(); + 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 { @@ -175,7 +173,21 @@ fn get_position_port_param_completion( ..CompletionItemLabelDetails::default() }; - let param_desc = make_param_desc(¶m); + 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 c_item = CompletionItem { label: param.name, detail: Some(param_desc), @@ -196,9 +208,7 @@ fn get_position_port_param_completion( if instance.instports.is_some() { let port_range = instance.gen_dot_completion_port_range(); if port_range.contains(pos) { - let inst_module = hdl_param.find_module_by_name(&instance.inst_type); - if inst_module.is_some() { - let inst_module = inst_module.unwrap(); + 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 { @@ -206,7 +216,21 @@ fn get_position_port_param_completion( ..CompletionItemLabelDetails::default() }; - let port_desc = make_port_desc(&port); + 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 c_item = CompletionItem { label: port.name, detail: Some(port_desc), @@ -228,36 +252,3 @@ fn get_position_port_param_completion( } None } - -fn make_port_desc(port: &crate::core::hdlparam::Port) -> String { - let mut port_desc_array = Vec::::new(); - port_desc_array.push(port.dir_type.to_string()); - if port.net_type != "unknown" { - port_desc_array.push(port.net_type.to_string()); - } - - if port.signed != "unsigned" { - port_desc_array.push("signed".to_string()); - } - - if port.width != "1" { - port_desc_array.push(port.width.to_string()); - } - - port_desc_array.push(port.name.to_string()); - let port_desc = port_desc_array.join(" "); - port_desc -} - -fn make_param_desc(param: &crate::core::hdlparam::Parameter) -> String { - let mut param_desc_array = Vec::::new(); - param_desc_array.push(format!("parameter {}", param.name)); - - if param.init != "unknown" { - param_desc_array.push("=".to_string()); - param_desc_array.push(param.init.to_string()); - } - - let param_desc = param_desc_array.join(" "); - param_desc -} diff --git a/src/core/hdlparam.rs b/src/core/hdlparam.rs index 514e2e1..b9405d6 100644 --- a/src/core/hdlparam.rs +++ b/src/core/hdlparam.rs @@ -156,26 +156,7 @@ pub struct Parameter { } impl Port { - pub fn to_description(&self) -> String { - let mut port_desc_array = Vec::::new(); - port_desc_array.push(self.dir_type.to_string()); - if self.net_type != "unknown" { - port_desc_array.push(self.net_type.to_string()); - } - - if self.signed != "unsigned" { - port_desc_array.push("signed".to_string()); - } - - if self.width != "1" { - port_desc_array.push(self.width.to_string()); - } - - port_desc_array.push(self.name.to_string()); - let port_desc = port_desc_array.join(" "); - port_desc - } - pub fn vhdl_to_vlog_description(&self) -> String { + pub fn to_vlog_description(&self) -> String { let mut port_desc_array = Vec::::new(); let dir_type = match self.dir_type.as_str() { "in" => "input", @@ -215,7 +196,7 @@ impl Port { } impl Parameter { - pub fn to_description(&self) -> String { + pub fn to_vlog_description(&self) -> String { let mut param_desc_array = Vec::::new(); param_desc_array.push(format!("parameter {}", self.name)); @@ -226,13 +207,12 @@ impl Parameter { let param_desc = param_desc_array.join(" "); param_desc } - pub fn vhdl_to_vlog_description(&self) -> String { + pub fn to_vhdl_description(&self) -> String { let mut param_desc_array = Vec::::new(); - param_desc_array.push(format!("parameter {}", self.name)); + param_desc_array.push(format!("{} : {}", self.name, self.net_type.to_lowercase())); if self.init != "unknown" { - param_desc_array.push("=".to_string()); - param_desc_array.push(self.init.to_string()); + param_desc_array.push(format!(" := {}", self.init)); } let param_desc = param_desc_array.join(" "); param_desc diff --git a/src/core/vhdl_parser.rs b/src/core/vhdl_parser.rs index e4a3f51..79849c0 100644 --- a/src/core/vhdl_parser.rs +++ b/src/core/vhdl_parser.rs @@ -35,14 +35,21 @@ pub fn vhdl_parser(path: &str) -> FastHdlparam { hdlparam } - pub fn vhdl_parse(path: &PathBuf) -> Option { let mut diagnostics = Vec::new(); let parser = VHDLParser::new(VHDLStandard::VHDL2008); if let Ok((_, design_file)) = parser.parse_design_file(path, &mut diagnostics) { return Some(design_file); } + None +} +pub fn vhdl_parse_str(path: &PathBuf, code: &str) -> Option { + let mut diagnostics = Vec::new(); + let parser = VHDLParser::new(VHDLStandard::VHDL2008); + if let Ok((_, design_file)) = parser.parse_vhdl_str(code, path, &mut diagnostics) { + return Some(design_file); + } None } diff --git a/src/hover/feature.rs b/src/hover/feature.rs index 9341ac0..47831df 100644 --- a/src/hover/feature.rs +++ b/src/hover/feature.rs @@ -301,16 +301,16 @@ fn make_port_desc_hover(file_type: &str, port: &crate::core::hdlparam::Port, ran let (language, value) = match file_type { "common" => { - (language_id.to_string(), port.to_description()) + (language_id.to_string(), port.to_vlog_description()) } "ip" => { ("vhdl".to_string(), port.to_vhdl_description()) } "primitives" => { - (language_id.to_string(), port.to_description()) + (language_id.to_string(), port.to_vlog_description()) } _ => { - (language_id.to_string(), port.to_description()) + (language_id.to_string(), port.to_vlog_description()) } }; @@ -324,16 +324,16 @@ fn make_port_desc_hover(file_type: &str, port: &crate::core::hdlparam::Port, ran fn make_param_desc_hover(file_type: &str, param: &crate::core::hdlparam::Parameter, range: &Range, language_id: &str) -> Hover { let value = match file_type { "common" => { - param.to_description() + param.to_vlog_description() } "ip" => { - param.vhdl_to_vlog_description() + param.to_vhdl_description() } "primitives" => { - param.to_description() + param.to_vlog_description() } _ => { - param.to_description() + param.to_vlog_description() } }; diff --git a/src/inlay_hint/sv.rs b/src/inlay_hint/sv.rs index 8cc14e8..04e5a7f 100644 --- a/src/inlay_hint/sv.rs +++ b/src/inlay_hint/sv.rs @@ -155,17 +155,17 @@ fn make_instport_hints( let port_desc_value = match file_type.as_str() { "common" => { - format!("```{}\n{}\n```", language_id, port_info.to_description()) + format!("```{}\n{}\n```", language_id, port_info.to_vlog_description()) } "ip" => { // TODO: 支持更多的 IP - format!("```verilog\n{}\n```", port_info.vhdl_to_vlog_description()) + format!("```verilog\n{}\n```", port_info.to_vhdl_description()) } "primitives" => { - format!("```{}\n{}\n```", language_id, port_info.to_description()) + format!("```{}\n{}\n```", language_id, port_info.to_vlog_description()) } _ => { - format!("```{}\n{}\n```", language_id, port_info.to_description()) + format!("```{}\n{}\n```", language_id, port_info.to_vlog_description()) } }; diff --git a/src/request/mod.rs b/src/request/mod.rs index 1dd793f..729dc27 100644 --- a/src/request/mod.rs +++ b/src/request/mod.rs @@ -118,11 +118,21 @@ pub fn do_fast( let parse_fast_by_language_id = |language_id: &str| { match language_id { "vhdl" => { - do_vhdl_fast(&path, &file_type, &tool_chain, backend) + do_vhdl_fast( + &path, + &file_type, + &tool_chain, + backend + ) } "verilog" | "systemverilog" => { - do_sv_fast(&path, &file_type, &tool_chain, backend) + do_sv_fast( + &path, + &file_type, + &tool_chain, + backend + ) } _ => Err(tower_lsp::jsonrpc::Error { diff --git a/src/server.rs b/src/server.rs index aa4d08e..b0141bd 100644 --- a/src/server.rs +++ b/src/server.rs @@ -285,6 +285,10 @@ impl LanguageServer for Backend { async fn did_change(&self, params: DidChangeTextDocumentParams) { info!("file did change: {:?}", params.text_document.uri); + for change in ¶ms.content_changes { + info!("change: {:?}", change); + } + // // 如果文件太大则显示错误 // if CacheManager::uri_is_big_file(¶ms.text_document.uri) { // // self.client.show_message(MessageType::WARNING, "考虑到性能问题,对于大于 1MB 的文件不会主动提供语言服务") diff --git a/src/sources.rs b/src/sources.rs index 85be09f..fb3f38d 100644 --- a/src/sources.rs +++ b/src/sources.rs @@ -1,8 +1,7 @@ -use crate::core::cache_storage::CacheManager; use crate::core::hdlparam::HdlParam; use crate::core::sv_parser::make_fast_from_syntaxtree; use crate::core::vhdl_parser::make_fast_from_design_file; -use crate::core::vhdl_parser::vhdl_parse; +use crate::core::vhdl_parser::vhdl_parse_str; use crate::definition::def_types::*; use crate::definition::get_scopes_from_syntax_tree; use crate::definition::get_scopes_from_vhdl_fast; @@ -18,7 +17,6 @@ use ropey::{Rope, RopeSlice}; use std::cmp::min; use std::collections::HashMap; use std::env::current_dir; -use std::fs; #[allow(unused)] use std::ops::Deref; use std::ops::Range as StdRange; @@ -79,7 +77,7 @@ impl LSPServer { if let Some(file) = self.srcs.get_file(file_id) { let mut file = file.write().unwrap(); - // loop through changes and apply + // 根据输入的 change 动态更新对应的代码的文本片段 for change in params.content_changes { if change.range.is_none() { file.text = Rope::from_str(&change.text); @@ -225,8 +223,6 @@ pub struct Sources { pub scope_tree: Arc>>, // include directories, passed to parser to resolve `include pub include_dirs: Arc>>, - // source directories - pub source_dirs: Arc>>, /// hdlparam 后端实现 pub hdl_param: Arc, // 同步解析线程和发送 fast 请求的 @@ -247,7 +243,6 @@ impl Sources { meta: Arc::new(RwLock::new(Vec::new())), scope_tree: Arc::new(RwLock::new(None)), include_dirs: Arc::new(RwLock::new(Vec::new())), - source_dirs: Arc::new(RwLock::new(Vec::new())), hdl_param: Arc::new(HdlParam::new()), fast_sync_controller: Arc::new(RwLock::new(HashMap::>>::new())) } @@ -273,6 +268,8 @@ impl Sources { let hdl_param_handle = self.hdl_param.clone(); let inc_dirs = self.include_dirs.clone(); + let uri = doc.uri.clone(); + let conf = server.conf.clone(); info!("launch worker to parse {:?}", doc.uri.to_string()); @@ -291,17 +288,18 @@ impl Sources { let parse_handle = thread::spawn(move || { let (lock, cvar) = &*valid_parse2; loop { - let file = source_handle.read().unwrap(); - let text = file.text.clone(); - let uri = &file.uri.clone(); - let range = &file.last_change_range.clone(); - drop(file); - info!("do parse in {:?}, language_id: {:?}", uri.to_string(), language_id); // 此时 update fast 的地方为 write 会进行阻塞 { let _unused = fast_lock.read().unwrap(); + // 从内存中直接获取增量更新系统维护的代码文本 + let file = source_handle.read().unwrap(); + let text = file.text.clone(); + let uri = &file.uri.clone(); + + let range = &file.last_change_range.clone(); + drop(file); match language_id.as_str() { "vhdl" => { vhdl_parser_pipeline( @@ -692,11 +690,16 @@ pub fn vhdl_parser_pipeline( }; let mut file = source_handle.write().unwrap(); - let mut scope_tree = if let Some(design_file) = vhdl_parse(&escape_path) { + let text = doc.to_string(); + let mut scope_tree = if let Some(design_file) = vhdl_parse_str(&escape_path, &text) { if let Some(mut fast) = make_fast_from_design_file(&design_file) { let parse_ir = ParseIR::DesignFile(design_file); file.parse_ir = Some(parse_ir); + for module in &fast.content { + info!("parse port number: {:?}", module.ports.len()); + } + let file_type = { let fast_map = hdl_param_handle.path_to_hdl_file.read().unwrap(); if let Some(hdl_file) = fast_map.get(escape_path_string) { @@ -763,7 +766,6 @@ pub trait LSPSupport { fn range_to_char_range(&self, range: &Range) -> StdRange; fn char_range_to_range(&self, range: StdRange) -> Range; fn apply_change(&mut self, change: &TextDocumentContentChangeEvent); - fn find_first_str(&self, target: &str) -> Option; } /// Extend ropey's Rope type with lsp convenience functions @@ -806,9 +808,6 @@ impl LSPSupport for Rope { } } } - fn find_first_str(&self, _: &str) -> Option { - panic!("haven't impl this method"); - } } impl<'a> LSPSupport for RopeSlice<'a> { @@ -843,12 +842,4 @@ impl<'a> LSPSupport for RopeSlice<'a> { fn apply_change(&mut self, _: &TextDocumentContentChangeEvent) { panic!("can't edit a rope slice"); } - fn find_first_str(&self, target: &str) -> Option { - for (i, c) in self.chars().enumerate() { - if c.to_string() == target { - return Some(i) - } - } - None - } }