From ceb827b8503d795ba931c57f0aae03dd8f7b5262 Mon Sep 17 00:00:00 2001 From: LSTM-Kirigaya <1193466151@qq.com> Date: Tue, 1 Oct 2024 02:04:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=A8=A1=E5=9D=97=E8=B7=A8?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E7=9A=84=E5=AE=9A=E4=B9=89=E8=B7=B3=E8=BD=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/fast_hdlparam.rs | 26 ++++++++--- src/core/sv_parser.rs | 3 +- src/definition/feature.rs | 35 ++++++++++----- src/definition/mod.rs | 5 +++ src/hover/feature.rs | 90 ++++++++++++++++++++++++++++++++------- src/hover/mod.rs | 2 +- src/utils/file.rs | 2 + sv-parser | 2 +- 8 files changed, 131 insertions(+), 34 deletions(-) diff --git a/src/core/fast_hdlparam.rs b/src/core/fast_hdlparam.rs index 9154163..365cc46 100644 --- a/src/core/fast_hdlparam.rs +++ b/src/core/fast_hdlparam.rs @@ -1,5 +1,4 @@ use std::collections::HashMap; -use std::f64::consts::E; use std::sync::RwLock; use serde::{Deserialize, Serialize}; @@ -25,10 +24,6 @@ pub struct Range { pub end: Position } -pub trait LikePosition { - fn line(&self) -> u32; - fn character(&self) -> u32; -} impl Range { #[allow(unused)] @@ -42,6 +37,27 @@ impl Range { pub fn contains(&self, postion: &LspPosition) -> bool { compare_pos(&self.start.to_lsp_position(), postion) != 1 && compare_pos(postion, &self.end.to_lsp_position()) != 1 } + + /// 对所有的 line 或者 所有的 character 进行偏移操作 + pub fn affine(&mut self, line_offset: i32, character_offset: i32) -> &Range { + if line_offset > 0 { + self.start.line += line_offset as u32; + self.end.line += line_offset as u32; + } else { + self.start.line -= (- line_offset) as u32; + self.end.line -= (- line_offset) as u32; + } + + if character_offset > 0 { + self.start.character += character_offset as u32; + self.end.character += character_offset as u32; + } else { + self.start.character -= (- character_offset) as u32; + self.end.character -= (- character_offset) as u32; + } + + self + } } fn compare_pos(pos1: &LspPosition, pos2: &LspPosition) -> i32 { diff --git a/src/core/sv_parser.rs b/src/core/sv_parser.rs index 809c24c..baef08f 100644 --- a/src/core/sv_parser.rs +++ b/src/core/sv_parser.rs @@ -313,7 +313,7 @@ pub fn make_fast_from_syntaxtree(syntax_tree: &SyntaxTree, path: &PathBuf) -> Re } } - update_module_range(&path, &mut hdlparam); + // update_module_range(&path, &mut hdlparam); Ok(hdlparam) } @@ -576,6 +576,7 @@ fn get_includes(path: &PathBuf) -> Vec { includes } +#[allow(unused)] fn update_module_range(path: &PathBuf, hdlparam: &mut FastHdlparam) { let file = File::open(path).unwrap(); let reader = BufReader::new(file); diff --git a/src/definition/feature.rs b/src/definition/feature.rs index 6989210..af03b44 100644 --- a/src/definition/feature.rs +++ b/src/definition/feature.rs @@ -159,12 +159,9 @@ fn goto_instantiation<'a>( if token_name == port.name { let def_path = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap(); let target_uri = Url::from_file_path(def_path).unwrap(); - let mut target_range = port.range.to_lsp_range(); - target_range.start.line -= 1; - target_range.start.character -= 1; - target_range.end.line -= 1; - target_range.end.character -= 1; - + let mut target_range = port.range.clone(); + let target_range = target_range.affine(-1, -1).to_lsp_range(); + let link = vec![LocationLink { target_uri, origin_selection_range: Some(range.clone()), @@ -212,10 +209,26 @@ pub fn goto_position_port_param_definition( None } -pub fn goto_instance_definition() { +pub fn goto_module_declaration_definition( + server: &LSPServer, + token_name: &str +) -> Option { + if let Some(module) = server.srcs.hdl_param.find_module_by_name(token_name) { + let def_path = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap(); + let target_uri = Url::from_file_path(PathBuf::from_str(&def_path).unwrap()).unwrap(); + + let mut target_range = module.range.clone(); + let target_range = target_range.affine(-1, -1).to_lsp_range(); + + let link = vec![LocationLink { + target_uri, + origin_selection_range: None, + target_range: target_range, + target_selection_range: target_range + }]; + let links = GotoDefinitionResponse::Link(link); + return Some(links); + } -} - -pub fn goto_module_definition() { - + None } \ No newline at end of file diff --git a/src/definition/mod.rs b/src/definition/mod.rs index 8caccec..e177553 100644 --- a/src/definition/mod.rs +++ b/src/definition/mod.rs @@ -49,6 +49,11 @@ impl LSPServer { return Some(definition); } + // match module name + if let Some(definition) = goto_module_declaration_definition(self, &token) { + return Some(definition); + } + let byte_idx = file.text.pos_to_byte(&pos); let global_scope = scope_tree.as_ref()?; let def = global_scope.get_definition(&token, byte_idx, &doc)?; diff --git a/src/hover/feature.rs b/src/hover/feature.rs index 739aa38..e01b0ec 100644 --- a/src/hover/feature.rs +++ b/src/hover/feature.rs @@ -3,7 +3,7 @@ use std::{path::PathBuf, str::FromStr}; use log::info; use regex::Regex; use ropey::RopeSlice; -use tower_lsp::lsp_types::{Hover, HoverContents, LanguageString, MarkedString, Position, Range, Url}; +use tower_lsp::lsp_types::{Hover, HoverContents, LanguageString, MarkedString, MarkupContent, MarkupKind, Position, Range, Url}; use crate::{core::fast_hdlparam::{Define, FastHdlparam}, server::LSPServer}; @@ -339,7 +339,7 @@ pub fn hover_module_declaration( let port_num = module.ports.len(); let param_num = module.params.len(); let instance_num = module.instances.len(); - let port_desc = format!(" port {port_num} param {param_num} instantiation {instance_num}"); + let port_desc = format!("`port` {port_num}, `param` {param_num}, `instantiation` {instance_num}"); // 统计 dir let mut input_count = 0 as u32; @@ -355,26 +355,25 @@ pub fn hover_module_declaration( } } - let io_desc = format!(" input {input_count} output {output_count} inout {inout_count}"); - let desc_string = format!("{} | {}", port_desc, io_desc); + let io_desc = format!("`input` {input_count}, `output` {output_count}, `inout` {inout_count}"); - let module_path = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap(); - let module_pathbuf = PathBuf::from_str(module_path.as_str()).unwrap(); + let path_string = server.srcs.hdl_param.find_module_definition_path(&module.name).unwrap_or("unknown".to_string()); + let define_info = format!("define in {path_string}"); let mut markdowns = Vec::::new(); - markdowns.push(MarkedString::String(desc_string)); + markdowns.push(MarkedString::String(port_desc)); + markdowns.push(MarkedString::String(io_desc)); markdowns.push(MarkedString::String("".to_string())); + markdowns.push(MarkedString::String(define_info)); markdowns.push(MarkedString::String("---".to_string())); info!("module range: {:?}", module.range); - - if let Some(code) = get_range_text(&module_pathbuf, &module.range.to_lsp_range()) { - let code = LanguageString { - language: language_id.to_string(), - value: code - }; - markdowns.push(MarkedString::LanguageString(code)); - } + let module_profile = make_module_profile_code(&module); + let profile_markdown = LanguageString { + language: language_id.to_string(), + value: module_profile + }; + markdowns.push(MarkedString::LanguageString(profile_markdown)); let hover = Hover { contents: HoverContents::Array(markdowns), @@ -385,4 +384,65 @@ pub fn hover_module_declaration( } None +} + + +/// 根据 module 获取 module 的简单描述代码 +fn make_module_profile_code(module: &crate::core::fast_hdlparam::Module) -> String { + let mut codes = Vec::::new(); + let param_num = module.params.len(); + let port_num = module.ports.len(); + + if module.params.len() > 0 { + codes.push(format!("module {} #(", module.name)); + for (i, param) in module.params.iter().enumerate() { + let mut param_desc_array = Vec::::new(); + param_desc_array.push(format!("parameter {}", param.name)); + if param.init != "unknown" { + param_desc_array.push(param.init.to_string()); + } + + let param_desc = param_desc_array.join(" "); + if i == param_num - 1 { + codes.push(format!("\t{param_desc}")); + } else { + codes.push(format!("\t{param_desc},")); + } + } + codes.push(")(".to_string()); + } else { + codes.push(format!("module {} (", module.name)); + } + + if module.ports.len() > 0 { + for (i, port) in module.ports.iter().enumerate() { + 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(" "); + if i == port_num - 1 { + codes.push(format!("\t{port_desc}")); + } else { + codes.push(format!("\t{port_desc},")); + } + } + codes.push(format!(")")); + } else { + codes.push(format!(")")); + } + + let profile_string = codes.join("\n"); + profile_string } \ No newline at end of file diff --git a/src/hover/mod.rs b/src/hover/mod.rs index 227c36b..b492af6 100644 --- a/src/hover/mod.rs +++ b/src/hover/mod.rs @@ -4,6 +4,7 @@ use crate::definition::*; use crate::server::LSPServer; use crate::sources::LSPSupport; use crate::utils::*; +#[allow(unused)] use log::info; use regex::Regex; use ropey::Rope; @@ -40,7 +41,6 @@ impl LSPServer { let scope_tree: RwLockReadGuard<'_, Option> = self.srcs.scope_tree.read().ok()?; let global_scope = scope_tree.as_ref(); - // info!("get scope tree: {:?}", scope_tree); // match positional port param if let Some(hover) = hover_position_port_param(self, &line_text, &doc, pos, &language_id) { diff --git a/src/utils/file.rs b/src/utils/file.rs index 29b0c67..dc529ff 100644 --- a/src/utils/file.rs +++ b/src/utils/file.rs @@ -8,6 +8,7 @@ use crate::sources::LSPSupport; use super::to_escape_path; +#[allow(unused)] pub fn get_range_text(path: &PathBuf, range: &Range) -> Option { let path = to_escape_path(path); if let Some(rope) = open_doc_as_rope(&path) { @@ -19,6 +20,7 @@ pub fn get_range_text(path: &PathBuf, range: &Range) -> Option { None } +#[allow(unused)] pub fn open_doc_as_rope(path: &PathBuf) -> Option { if let std::result::Result::Ok(text) = fs::read_to_string(path) { let rope = Rope::from_str(text.as_str()); diff --git a/sv-parser b/sv-parser index 90e9d4c..3002b39 160000 --- a/sv-parser +++ b/sv-parser @@ -1 +1 @@ -Subproject commit 90e9d4cb3ba4e3a55a9b3fcd0fb83389a376ec35 +Subproject commit 3002b3970b64903ec98a3274d7254fefa82f0435