diff --git a/src/core/primitive_parser.rs b/src/core/primitive_parser.rs index 44f1281..ec954ca 100644 --- a/src/core/primitive_parser.rs +++ b/src/core/primitive_parser.rs @@ -5,6 +5,7 @@ use std::{collections::HashMap, fs::File}; use std::io::{BufReader, Read}; use bincode::Error; +use regex::Regex; use ropey::Rope; use serde::{Serialize, Deserialize}; use sv_parser::{unwrap_node, RefNode}; @@ -28,6 +29,27 @@ impl PrimitiveText { let mut text_map = self.name_to_text.write().unwrap(); text_map.insert(name.to_owned(), text.to_owned()); } + + pub fn get_comment(&self, name: &str, text: &str) -> String { + if let Some(comment) = PrimitiveText::extract_pattern_comments(text).get(name) { + (*comment).clone() + } else { + "".to_string() + } + } + + fn extract_pattern_comments(text: &str) -> HashMap { + let re = Regex::new(r"\s*\.(?P[^\(]+)\((?P[^\)]+)\)(?:,)?\s*//\s*(?P.+)").unwrap(); + text.lines() + .filter_map(|line| { + re.captures(line).map(|caps| { + let name = caps.name("x").unwrap().as_str().to_string(); + let comment = caps.name("z").unwrap().as_str().to_string(); + (name, comment) + }) + }) + .collect() + } } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -102,7 +124,7 @@ fn xml_parser(path: &str) -> Result { } } - Ok((primitive_xml)) + Ok(primitive_xml) } fn xml_parse_template(parser: &mut EventReader>) -> Option<(String, Template)> { @@ -242,10 +264,11 @@ fn xml_parse_text(text: &str) -> Option<(String, String, FastHdlparam)> { #[cfg(test)] mod tests { use std::{fs::{self, File}, io::Write, path::Path}; + use super::{init_parse_primitive_files, xml_parser}; - const TESTFILE: &str = "D:\\work\\playground\\digital-lsp-server\\primitive_files\\verilog2.xml"; - const TESTDIR: &str = "/home/dide/project/Digital-Test/Digital-IDE-test/user/factory/xilinx"; + const TESTFILE: &str = "primitive_files/verilog2.xml"; + const TESTDIR: &str = "primitive_files"; #[test] fn gen_primitive_bin() { diff --git a/src/hover/feature.rs b/src/hover/feature.rs index f81b9e5..1e64a72 100644 --- a/src/hover/feature.rs +++ b/src/hover/feature.rs @@ -1,11 +1,11 @@ -use std::{path::PathBuf, str::FromStr}; +use std::{path::PathBuf, str::FromStr, sync::Arc}; use log::info; use regex::Regex; use ropey::RopeSlice; use tower_lsp::lsp_types::{Hover, HoverContents, LanguageString, MarkedString, Position, Range, Url}; -use crate::{core::{self, hdlparam::{Define, FastHdlparam}}, definition::{DefinitionType, GenericDec}, server::LSPServer}; +use crate::{core::{self, hdlparam::{Define, FastHdlparam}, primitive_parser::PrimitiveText}, server::LSPServer}; use super::{get_language_id_by_path_str, get_word_range_at_position, resolve_path, to_escape_path}; @@ -249,11 +249,25 @@ fn goto_instantiation<'a>( // info!("port_range: {port_range:#?}"); // info!("position port find belong module: {:?}", module); - for port in &module.ports { - if token_name == port.name { - let file_type = server.srcs.hdl_param.find_file_type_by_module_name(&instance.inst_type); - let hover = make_port_desc_hover(&file_type, port, range, language_id); - return Some(hover); + let file_type = server.srcs.hdl_param.find_file_type_by_module_name(&instance.inst_type); + if file_type == "primitives" { + let primitives_text = server.srcs.primitive_text.clone(); + let instance_assignments = &module.instances.first().unwrap().intstport_assignments; + for assignment in instance_assignments { + if assignment.port.clone().unwrap() == token_name { + let hover = make_primitives_port_desc_hover( + primitives_text, &instance.inst_type, + assignment, range, language_id + ); + return Some(hover); + } + } + } else { + for port in &module.ports { + if token_name == port.name { + let hover = make_port_desc_hover(&file_type, port, range, language_id); + return Some(hover); + } } } return None; @@ -296,6 +310,30 @@ pub fn hover_position_port_param( None } +fn make_primitives_port_desc_hover( + primitives_text: Arc, + primitives_name: &str, + inst_port: &crate::core::hdlparam::InstPort, + range: &Range, language_id: &str) -> Hover { + + let name = inst_port.port.clone().unwrap(); + let text_map = primitives_text.name_to_text.read().unwrap(); + let comment = if let Some(text) = text_map.get(primitives_name) { + primitives_text.get_comment(&name, text) + } else { + "".to_string() + }; + + let language_string = LanguageString { + language: language_id.to_string(), + value: name + " // " + &comment, + }; + Hover { + contents: HoverContents::Scalar(MarkedString::LanguageString(language_string)), + range: Some(range.clone()) + } +} + fn make_port_desc_hover(file_type: &str, port: &crate::core::hdlparam::Port, range: &Range, language_id: &str) -> Hover { info!("enter make_port_desc_hover, file_type: {}", file_type);